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: test:
strategy: strategy:
matrix: 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 ] os: [ ubuntu-latest, windows-latest ]
script: [ compress, mocha, release/benchmark, release/jetstream ] script: [ compress, mocha, release/benchmark, release/jetstream ]
exclude:
- node: "0.8"
script: release/jetstream
name: ${{ matrix.node }} ${{ matrix.os }} ${{ matrix.script }} name: ${{ matrix.node }} ${{ matrix.os }} ${{ matrix.script }}
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
env: env:
NODE: ${{ matrix.node }} NODE: ${{ matrix.node }}
TYPE: ${{ matrix.script }} TYPE: ${{ matrix.script }}
steps: steps:
- uses: actions/checkout@v1 - uses: actions/checkout@v2
- uses: actions/cache@v1 - uses: actions/cache@v1
with: with:
path: tmp path: tmp
@@ -21,11 +24,20 @@ jobs:
- name: Perform tests - name: Perform tests
shell: bash shell: bash
run: | 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/nvs.sh --version
nvs add $NODE
nvs use $NODE nvs use $NODE
node --version node --version
npm --version --no-update-notifier npm config set audit false
npm install --no-audit --no-optional --no-save --no-update-notifier 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 node test/$TYPE

View File

@@ -1,7 +1,7 @@
name: Fuzzing name: Fuzzing
on: on:
schedule: schedule:
- cron: "*/15 * * * *" - cron: "*/8 * * * *"
jobs: jobs:
ufuzz: ufuzz:
strategy: strategy:
@@ -11,15 +11,24 @@ jobs:
name: ${{ matrix.os }} name: ${{ matrix.os }}
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
steps: steps:
- uses: actions/checkout@v1 - uses: actions/checkout@v2
- name: Perform fuzzing - name: Perform fuzzing
shell: bash shell: bash
run: | 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/nvs.sh --version
nvs add 10
nvs use 10 nvs use 10
node --version node --version
npm --version --no-update-notifier npm config set audit false
npm install --no-audit --no-optional --no-save --no-update-notifier 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 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 `includeSources` Pass this flag if you want to include
the content of source files in the the content of source files in the
source map as sourcesContent property. source map as sourcesContent property.
`names` Include symbol names in the source map.
`root` Path to the original source to be included in `root` Path to the original source to be included in
the source map. the source map.
`url` If specified, path to the source map to append in `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 "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. - `--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 Otherwise UglifyJS assumes HTTP `X-SourceMap` is being used and will omit the
`//# sourceMappingURL=` directive. `//# 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'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 ## Parse options
- `bare_returns` (default `false`) -- support top level `return` statements - `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; if (process.argv.indexOf("ast") >= 0) program.helpInformation = UglifyJS.describe_ast;
else if (process.argv.indexOf("options") >= 0) program.helpInformation = function() { else if (process.argv.indexOf("options") >= 0) program.helpInformation = function() {
var text = []; var text = [];
var toplevels = [];
var padding = "";
var options = UglifyJS.default_options(); var options = UglifyJS.default_options();
for (var option in options) { for (var name in options) {
text.push("--" + (option == "output" ? "beautify" : option == "sourceMap" ? "source-map" : option) + " options:"); var option = options[name];
text.push(format_object(options[option])); if (option && typeof option == "object") {
text.push(""); 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"); return text.join("\n");
}; };
program.option("-p, --parse <options>", "Specify parser options.", parse_js()); program.option("-p, --parse <options>", "Specify parser options.", parse_js());
@@ -220,7 +237,10 @@ function run() {
// load on demand - assumes dev tree checked out // load on demand - assumes dev tree checked out
var reduce_test = require("../test/reduce"); var reduce_test = require("../test/reduce");
var testcase = files[0] || files[Object.keys(files)[0]]; 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 { else {
var result = UglifyJS.minify(files, options); var result = UglifyJS.minify(files, options);
@@ -337,7 +357,7 @@ function simple_glob(glob) {
.replace(/\?/g, "[^/\\\\]") + "$"; .replace(/\?/g, "[^/\\\\]") + "$";
var mod = process.platform === "win32" ? "i" : ""; var mod = process.platform === "win32" ? "i" : "";
var rx = new RegExp(pattern, mod); var rx = new RegExp(pattern, mod);
var results = entries.filter(function(name) { var results = entries.sort().filter(function(name) {
return rx.test(name); return rx.test(name);
}).map(function(name) { }).map(function(name) {
return path.join(dir, 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, content: null,
filename: null, filename: null,
includeSources: false, includeSources: false,
names: true,
root: null, root: null,
url: null, url: null,
}, true); }, true);
@@ -138,7 +139,7 @@ function minify(files, options) {
warnings.push(warning); warnings.push(warning);
}, options.warnings == "verbose"); }, options.warnings == "verbose");
if (timings) timings.parse = Date.now(); if (timings) timings.parse = Date.now();
var source_maps, toplevel; var toplevel;
if (files instanceof AST_Toplevel) { if (files instanceof AST_Toplevel) {
toplevel = files; toplevel = files;
} else { } else {
@@ -151,19 +152,17 @@ function minify(files, options) {
if (typeof source_map_content == "string" && source_map_content != "inline") { if (typeof source_map_content == "string" && source_map_content != "inline") {
source_map_content = parse_source_map(source_map_content); 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)) { for (var name in files) if (HOP(files, name)) {
options.parse.filename = name; options.parse.filename = name;
options.parse.toplevel = toplevel = parse(files[name], options.parse); options.parse.toplevel = toplevel = parse(files[name], options.parse);
if (source_maps) { if (source_map_content == "inline") {
if (source_map_content == "inline") { var inlined_content = read_source_map(name, toplevel);
var inlined_content = read_source_map(name, toplevel); if (inlined_content) {
if (inlined_content) { options.sourceMap.orig[name] = parse_source_map(inlined_content);
source_maps[name] = parse_source_map(inlined_content);
}
} else {
source_maps[name] = source_map_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 (!HOP(options.output, "code") || options.output.code) {
if (options.sourceMap) { if (options.sourceMap) {
options.output.source_map = SourceMap({ options.output.source_map = SourceMap(options.sourceMap);
file: options.sourceMap.filename,
orig: source_maps,
root: options.sourceMap.root
});
if (options.sourceMap.includeSources) { if (options.sourceMap.includeSources) {
if (files instanceof AST_Toplevel) { if (files instanceof AST_Toplevel) {
throw new Error("original source content unavailable"); throw new Error("original source content unavailable");
} else for (var name in files) if (HOP(files, name)) { } 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; delete options.output.ast;

View File

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

View File

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

View File

@@ -43,62 +43,149 @@
"use strict"; "use strict";
// a small wrapper around fitzgen's source-map library var vlq_char = characters("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/");
function SourceMap(options) { var vlq_bits = vlq_char.reduce(function(map, ch, bits) {
options = defaults(options, { map[ch] = bits;
file: null, return map;
root: null, }, Object.create(null));
orig: null,
orig_line_diff: 0, function vlq_decode(indices, str) {
dest_line_diff: 0, var value = 0;
}, true); var shift = 0;
var generator = new MOZ_SourceMap.SourceMapGenerator({ for (var i = 0, j = 0; i < str.length; i++) {
file: options.file, var bits = vlq_bits[str[i]];
sourceRoot: options.root value += (bits & 31) << shift;
}); if (bits & 32) {
var maps = options.orig && Object.create(null); shift += 5;
if (maps) for (var source in options.orig) { } else {
var map = new MOZ_SourceMap.SourceMapConsumer(options.orig[source]); indices[j++] += value & 1 ? 0x80000000 | -(value >> 1) : value >> 1;
if (Array.isArray(options.orig[source].sources)) { value = shift = 0;
map._sources.toArray().forEach(function(source) {
var sourceContent = map.sourceContentFor(source, true);
if (sourceContent) generator.setSourceContent(source, sourceContent);
});
} }
maps[source] = map;
} }
return { return j;
add: function(source, gen_line, gen_col, orig_line, orig_col, name) { }
var map = maps && maps[source];
if (map) { function vlq_encode(num) {
var info = map.originalPositionFor({ var result = "";
line: orig_line, num = Math.abs(num) << 1 | num >>> 31;
column: orig_col 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; sources: map.sources,
orig_line = info.line; };
orig_col = info.column; if (!sources_content || !map.sourcesContent) return;
name = info.name || name; for (var i = 0; i < map.sources.length; i++) {
} var content = map.sourcesContent[i];
generator.addMapping({ if (content) sources_content[map.sources[i]] = content;
name: name, }
source: source, });
generated: { var prev_source;
line: gen_line + options.dest_line_diff, var generated_line = 1;
column: gen_col var generated_column = 0;
}, var source_index = 0;
original: { var original_line = 1;
line: orig_line + options.orig_line_diff, var original_column = 0;
column: orig_col 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;
} }
}); if (!indices || indices.length < 4) {
}, source = null;
get: function() { } else {
return generator; 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() { 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); configure_error_stack(DefaultsError);
function defaults(args, defs, croak) { function defaults(args, defs, croak) {
if (args === true) args = {}; if (croak) for (var i in args) {
var ret = args || {}; if (HOP(args, i) && !HOP(defs, i)) throw new DefaultsError("`" + i + "` is not a supported option", defs);
if (croak) for (var i in ret) if (HOP(ret, i) && !HOP(defs, i)) {
throw new DefaultsError("`" + i + "` is not a supported option", defs);
} }
for (var i in defs) if (HOP(defs, i)) { for (var i in args) {
ret[i] = (args && HOP(args, i)) ? args[i] : defs[i]; if (HOP(args, i)) defs[i] = args[i];
} }
return ret; return defs;
} }
function merge(obj, ext) { function merge(obj, ext) {
@@ -217,6 +215,12 @@ Dictionary.prototype = {
return this; return this;
}, },
has: function(key) { return ("$" + key) in this._values }, 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) { each: function(f) {
for (var i in this._values) for (var i in this._values)
f(this._values[i], i.substr(1)); f(this._values[i], i.substr(1));

View File

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

View File

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

View File

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

View File

@@ -803,8 +803,7 @@ collapse_vars_assignment: {
expect: { expect: {
function log(x) { return console.log(x), x; } function log(x) { return console.log(x), x; }
function f0(c) { function f0(c) {
var a = 3 / c; return 3 / c;
return a = a;
} }
function f1(c) { function f1(c) {
return 1 - 3 / c; return 1 - 3 / c;
@@ -2012,6 +2011,7 @@ issue_1631_3: {
join_vars: true, join_vars: true,
sequences: true, sequences: true,
side_effects: true, side_effects: true,
unused: true,
} }
input: { input: {
function g() { function g() {
@@ -2031,8 +2031,8 @@ issue_1631_3: {
function f() { function f() {
return a = 2, 4; return a = 2, 4;
} }
var a = 0, b = 1, t = f(); var a = 0, t = f();
return b = a + t; return a + t;
} }
console.log(g()); console.log(g());
} }
@@ -2204,8 +2204,8 @@ var_defs: {
} }
expect: { expect: {
var f1 = function(x, y) { var f1 = function(x, y) {
var r = x + y, a = r * r - r, b = 7; var r = x + y, z = r * r - r, b = 7;
console.log(a + b); console.log(z + b);
}; };
f1("1", 0); f1("1", 0);
} }
@@ -2569,8 +2569,7 @@ chained_3: {
} }
expect: { expect: {
console.log(function(a, b) { console.log(function(a, b) {
var c = 1; var c = 1, c = b;
c = b;
b++; b++;
return c; return c;
}(0, 2)); }(0, 2));
@@ -2665,8 +2664,8 @@ double_def_1: {
a(); a();
} }
expect: { expect: {
var a; var a = x;
(a = (a = x) && y)(); (a = a && y)();
} }
} }
@@ -2699,8 +2698,8 @@ toplevel_single_reference: {
} }
expect: { expect: {
for (var b in x) { for (var b in x) {
var a; var a = b;
b(a = b); b(b);
} }
} }
} }
@@ -4243,8 +4242,7 @@ issue_2497: {
if (true) if (true)
for (var i = 0; i < 1; ++i) for (var i = 0; i < 1; ++i)
for (var k = 0; k < 1; ++k) { for (var k = 0; k < 1; ++k) {
value = 1; value = (value = 1) ? value + 1 : 0;
value = value ? value + 1 : 0;
} }
else else
for (i = 0; i < 1; ++i) for (i = 0; i < 1; ++i)
@@ -7806,3 +7804,153 @@ issue_3744: {
} }
expect_stdout: "PASS" 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: { expect: {
var a, b; var a, b;
x() ? y() : z(); (x() ? y : z)();
} }
} }
@@ -1666,3 +1666,130 @@ issue_3668: {
} }
expect_stdout: "undefined" 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" 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: { try_catch_finally: {
options = { options = {
conditionals: true, conditionals: true,
@@ -130,10 +190,7 @@ try_catch_finally: {
a = 3; a = 3;
console.log("PASS"); console.log("PASS");
}(); }();
try { console.log(a);
console.log(a);
} finally {
}
} }
expect_stdout: [ expect_stdout: [
"PASS", "PASS",
@@ -892,3 +949,205 @@ issue_3578: {
} }
expect_stdout: "PASS" 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: { drop_lone_use_strict: {
options = { options = {
directives: true, directives: true,
side_effects: true, unused: true,
} }
input: { input: {
function f1() { function f1() {
@@ -66,10 +66,8 @@ drop_lone_use_strict: {
function f1() { function f1() {
} }
function f2() { function f2() {
"use strict";
function f3() {
}
} }
(function() {})();
} }
} }

View File

@@ -2444,3 +2444,69 @@ issue_3746: {
} }
expect_stdout: "PASS" 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" 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 = {}; var obj = {};
obj.one = 1; obj.one = 1;
obj.two = 2; obj.two = 2;
console.log(obj.one); console.log(obj.one, obj.two);
})(); })();
} }
expect: { expect: {
console.log(1); console.log(1, 2);
} }
expect_stdout: "1" expect_stdout: "1 2"
} }
issue_3071_2: { issue_3071_2: {
options = { options = {
evaluate: true,
hoist_props: true, hoist_props: true,
inline: true, inline: true,
join_vars: true, join_vars: true,
@@ -793,19 +792,18 @@ issue_3071_2: {
obj = {}; obj = {};
obj.one = 1; obj.one = 1;
obj.two = 2; obj.two = 2;
console.log(obj.one); console.log(obj.one, obj.two);
var obj; var obj;
})(); })();
} }
expect: { expect: {
console.log(1); console.log(1, 2);
} }
expect_stdout: "1" expect_stdout: "1 2"
} }
issue_3071_2_toplevel: { issue_3071_2_toplevel: {
options = { options = {
evaluate: true,
hoist_props: true, hoist_props: true,
inline: true, inline: true,
join_vars: true, join_vars: true,
@@ -821,14 +819,14 @@ issue_3071_2_toplevel: {
obj = {}; obj = {};
obj.one = 1; obj.one = 1;
obj.two = 2; obj.two = 2;
console.log(obj.one); console.log(obj.one, obj.two);
var obj; var obj;
})(); })();
} }
expect: { expect: {
console.log(1); console.log(1, 2);
} }
expect_stdout: "1" expect_stdout: "1 2"
} }
issue_3071_3: { issue_3071_3: {

View File

@@ -2420,3 +2420,43 @@ issue_3750: {
} }
expect_stdout: "PASS" 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: 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 variable a [test/compress/issue-1034.js:4,20]",
"WARN: Dropping unused function nope [test/compress/issue-1034.js:11,21]", "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: Dropping unreachable code [test/compress/issue-1034.js:9,12]",
"WARN: Declarations in 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]", "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 b [test/compress/issue-1034.js:7,20]",
"INFO: Dropping unused variable c [test/compress/issue-1034.js:9,16]", "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: 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 variable a [test/compress/issue-1034.js:5,20]",
"WARN: Dropping unused function nope [test/compress/issue-1034.js:12,21]", "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: Dropping unreachable code [test/compress/issue-1034.js:10,12]",
"WARN: Declarations in 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]", "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 b [test/compress/issue-1034.js:8,20]",
"INFO: Dropping unused variable c [test/compress/issue-1034.js:10,16]", "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); console.log(a, b);
} }
expect: { expect: {
for (var a = 100, b = 10, L1 = 5; --L1 > 0;) for (var a = 100, b = 10, L1 = 5, ignore; --L1 > 0;) {
if (--b, 0) var ignore = 0; --b;
}
console.log(a, b); console.log(a, b);
} }
expect_stdout: "100 6" expect_stdout: "100 6"

View File

@@ -26,7 +26,7 @@ warn: {
}().length); }().length);
} }
expect_warnings: [ 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.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)(); (0, 1, _decorators.logThis)();
} }
expect: { expect: {
eval(); (0, eval)();
logThis(); logThis();
(0, _decorators.logThis)(); (0, _decorators.logThis)();
} }

View File

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

View File

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

View File

@@ -549,6 +549,7 @@ issue_2740_2: {
dead_code: true, dead_code: true,
loops: true, loops: true,
passes: 2, passes: 2,
unused: true,
} }
input: { input: {
L1: while (x()) { L1: while (x()) {
@@ -564,6 +565,7 @@ issue_2740_3: {
options = { options = {
dead_code: true, dead_code: true,
loops: true, loops: true,
unused: true,
} }
input: { input: {
L1: for (var x = 0; x < 3; x++) { L1: for (var x = 0; x < 3; x++) {
@@ -589,6 +591,7 @@ issue_2740_4: {
dead_code: true, dead_code: true,
loops: true, loops: true,
passes: 2, passes: 2,
unused: true,
} }
input: { input: {
L1: for (var x = 0; x < 3; x++) { L1: for (var x = 0; x < 3; x++) {
@@ -613,6 +616,7 @@ issue_2740_5: {
dead_code: true, dead_code: true,
loops: true, loops: true,
passes: 2, passes: 2,
unused: true,
} }
input: { input: {
L1: for (var x = 0; x < 3; x++) { L1: for (var x = 0; x < 3; x++) {
@@ -763,6 +767,7 @@ issue_3631_1: {
loops: true, loops: true,
reduce_vars: true, reduce_vars: true,
toplevel: true, toplevel: true,
unused: true,
} }
input: { input: {
var c = 0; var c = 0;
@@ -789,6 +794,7 @@ issue_3631_2: {
loops: true, loops: true,
reduce_vars: true, reduce_vars: true,
toplevel: true, toplevel: true,
unused: true,
} }
input: { input: {
L: for (var a = 1; a--; console.log(b)) { 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: { issue_869_1: {
mangle = { mangle = {
properties: { properties: {
@@ -1856,36 +1304,6 @@ issue_3188_3: {
expect_stdout: "PASS" expect_stdout: "PASS"
} }
join_expr: {
options = {
evaluate: true,
join_vars: true,
}
input: {
var c = "FAIL";
(function() {
var a = 0;
switch ((a = {}) && (a.b = 0)) {
case 0:
c = "PASS";
}
})();
console.log(c);
}
expect: {
var c = "FAIL";
(function() {
var a = 0;
switch (a = { b: 0 }, a.b) {
case 0:
c = "PASS";
}
})();
console.log(c);
}
expect_stdout: "PASS"
}
issue_3389: { issue_3389: {
options = { options = {
evaluate: true, evaluate: true,

View File

@@ -223,6 +223,25 @@ unsafe_evaluate: {
expect_stdout: true 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: { unsafe_evaluate_side_effect_free_1: {
options = { options = {
evaluate: true, evaluate: true,
@@ -2289,11 +2308,10 @@ redefine_farg_2: {
console.log(f([]), g([]), h([])); console.log(f([]), g([]), h([]));
} }
expect: { expect: {
console.log((a = [], typeof a), "number",function(a, b) { console.log(typeof [], "number",function(a, b) {
a = b; a = b;
return typeof a; return typeof a;
}([])); }([]));
var a;
} }
expect_stdout: "object number undefined" expect_stdout: "object number undefined"
} }
@@ -4571,7 +4589,7 @@ perf_8: {
expect_stdout: "348150" expect_stdout: "348150"
} }
issue_2485: { issue_2485_1: {
options = { options = {
reduce_funcs: true, reduce_funcs: true,
reduce_vars: true, reduce_vars: true,
@@ -4619,6 +4637,53 @@ issue_2485: {
expect_stdout: "6" 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: { issue_2455: {
options = { options = {
reduce_vars: true, reduce_vars: true,
@@ -5435,8 +5500,7 @@ lvalues_def_1: {
} }
expect: { expect: {
var b = 1; var b = 1;
var a = b++; var a = b++, b = NaN;
b = NaN;
console.log(a, b); console.log(a, b);
} }
expect_stdout: "1 NaN" expect_stdout: "1 NaN"
@@ -5455,8 +5519,7 @@ lvalues_def_2: {
} }
expect: { expect: {
var b = 1; var b = 1;
var a = b += 1; var a = b += 1, b = NaN;
b = NaN;
console.log(a, b); console.log(a, b);
} }
expect_stdout: "2 NaN" expect_stdout: "2 NaN"
@@ -6511,17 +6574,17 @@ issue_3240_3: {
} }
expect: { expect: {
(function() { (function() {
(function f(b) { f();
function f(b) {
if (!f.a) f.a = 0; if (!f.a) f.a = 0;
console.log(f.a.toString()); console.log(f.a.toString());
var g = function() { (function() {
(b ? function() {} : function() { (b ? function() {} : function() {
f.a++; f.a++;
f(1); f(1);
})(); })();
}; })();
g(); }
})();
})(); })();
} }
expect_stdout: [ expect_stdout: [
@@ -6555,7 +6618,8 @@ issue_3240_4: {
} }
expect: { expect: {
(function() { (function() {
(function f(b) { f();
function f(b) {
if (!f.a) f.a = 0; if (!f.a) f.a = 0;
console.log(f.a.toString()); console.log(f.a.toString());
(function() { (function() {
@@ -6564,7 +6628,7 @@ issue_3240_4: {
f(1); f(1);
})(); })();
})(); })();
})(); }
})(); })();
} }
expect_stdout: [ expect_stdout: [
@@ -6867,9 +6931,48 @@ issue_3666: {
} finally { } finally {
for (;!a;) for (;!a;)
a++; a++;
var b = a = "PASS"; a = "PASS";
} }
console.log(a, b); console.log(a, "PASS");
} }
expect_stdout: "PASS 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, dead_code: true,
evaluate: true, evaluate: true,
side_effects: true, side_effects: true,
unused: true,
} }
input: { input: {
L: if (true) { L: if (true) {

View File

@@ -435,3 +435,25 @@ emberjs_global: {
} }
expect_stdout: Error("PASS") 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["tokenizer"] = tokenizer;
exports["TreeTransformer"] = TreeTransformer; exports["TreeTransformer"] = TreeTransformer;
exports["TreeWalker"] = TreeWalker; 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))); "use strict";
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImlucHV0Mi5qcyJdLCJuYW1lcyI6WyJyZXF1aXJlIiwiYXJyIl0sIm1hcHBpbmdzIjoiMEpBQWNBLEtBQVFDIiwic291cmNlc0NvbnRlbnQiOlsiY29uc3Qge2Zvb30gPSByZXF1aXJlKFwiYmFyXCIpO1xuY29uc3Qge2hlbGxvfSA9IHJlcXVpcmUoXCJ3b3JsZFwiKTtcblxuZm9vLngoLi4uZm9vLnkoaGVsbG8ueikpO1xuIl19
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"), var _require = require("bar"),
foo = _require.foo; 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)}; 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" "aaaaaaaaaaaaaaaa"
;a(err,data),a(err, ;a(err,data),a(err,
data)} 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)}; 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) { function f(x) {
return g(x); return g(x);
function g(x) { function g(x) {
return x; return x + x;
} }
} }

View File

@@ -8,15 +8,14 @@ if (typeof phantom == "undefined") {
require("../tools/exit"); require("../tools/exit");
var args = process.argv.slice(2); var args = process.argv.slice(2);
var debug = args.indexOf("--debug"); var debug = args.indexOf("--debug");
if (debug >= 0) { if (debug < 0) {
debug = false;
} else {
args.splice(debug, 1); args.splice(debug, 1);
debug = true; 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"); args.push("--timings");
var child_process = require("child_process"); var child_process = require("child_process");
var fetch = require("./fetch"); var fetch = require("./fetch");
@@ -39,10 +38,10 @@ if (typeof phantom == "undefined") {
}); });
if (/\.js$/.test(url)) { if (/\.js$/.test(url)) {
var stderr = ""; var stderr = "";
var uglifyjs = child_process.fork("bin/uglifyjs", args, { var uglifyjs = child_process.spawn(process.argv[0], args, {
silent: true silent: true
}).on("exit", function(code) { }).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); console.log(stderr);
if (code) throw new Error("uglifyjs failed with code " + code); 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 exec = require("child_process").exec;
var fs = require("fs"); var fs = require("fs");
var run_code = require("../sandbox").run_code; var run_code = require("../sandbox").run_code;
var to_ascii = require("../node").to_ascii;
function read(path) { function read(path) {
return fs.readFileSync(path, "utf8"); return fs.readFileSync(path, "utf8");
@@ -48,6 +49,62 @@ describe("bin/uglifyjs", function() {
done(); 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) { 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"; var command = uglifyjscmd + " test/mocha.js --source-map content=blah,url=inline --verbose";
exec(command, function(err, stdout, stderr) { exec(command, function(err, stdout, stderr) {
@@ -109,9 +166,12 @@ describe("bin/uglifyjs", function() {
} }
var command = [ var command = [
uglifyjscmd, uglifyjscmd,
"--source-map", "content=" + mapFile, "--beautify",
"--source-map", "includeSources=true", "--source-map", [
"--source-map", "url=inline", "content=" + mapFile,
"includeSources",
"url=inline",
].join(","),
].join(" "); ].join(" ");
var child = exec(command, function(err, stdout) { var child = exec(command, function(err, stdout) {
@@ -245,7 +305,7 @@ describe("bin/uglifyjs", function() {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, [ assert.strictEqual(stdout, [
"var Foo=function Foo(){console.log(1+2)};new Foo;var bar=function(){function foo(bar){return bar}return foo}();", "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")); ].join("\n"));
var stderrLines = stderr.split("\n"); var stderrLines = stderr.split("\n");
@@ -587,7 +647,7 @@ describe("bin/uglifyjs", function() {
}); });
function read_map() { 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; delete map.sourcesContent;
return JSON.stringify(map).replace(/"/g, '\\"'); return JSON.stringify(map).replace(/"/g, '\\"');
} }
@@ -674,7 +734,7 @@ describe("bin/uglifyjs", function() {
var command = uglifyjscmd + " test/input/rename/input.js --rename"; var command = uglifyjscmd + " test/input/rename/input.js --rename";
exec(command, function(err, stdout, stderr) { exec(command, function(err, stdout, stderr) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, "function f(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(); done();
}); });
}); });
@@ -682,7 +742,7 @@ describe("bin/uglifyjs", function() {
var command = uglifyjscmd + " test/input/rename/input.js -mc passes=2 --no-rename"; var command = uglifyjscmd + " test/input/rename/input.js -mc passes=2 --no-rename";
exec(command, function(err, stdout, stderr) { exec(command, function(err, stdout, stderr) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, "function f(n){return function(n){return n}(n)}\n"); assert.strictEqual(stdout, "function f(n){return function(n){return n+n}(n)}\n");
done(); done();
}); });
}); });
@@ -690,7 +750,7 @@ describe("bin/uglifyjs", function() {
var command = uglifyjscmd + " test/input/rename/input.js -mc passes=2"; var command = uglifyjscmd + " test/input/rename/input.js -mc passes=2";
exec(command, function(err, stdout, stderr) { exec(command, function(err, stdout, stderr) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, "function f(n){return n}\n"); assert.strictEqual(stdout, "function f(n){return n+n}\n");
done(); done();
}); });
}); });
@@ -698,7 +758,7 @@ describe("bin/uglifyjs", function() {
var command = uglifyjscmd + " test/input/rename/input.js -c passes=2"; var command = uglifyjscmd + " test/input/rename/input.js -c passes=2";
exec(command, function(err, stdout, stderr) { exec(command, function(err, stdout, stderr) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, "function f(x){return function(x){return x}(x)}\n"); assert.strictEqual(stdout, "function f(x){return function(x){return x+x}(x)}\n");
done(); done();
}); });
}); });

View File

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

View File

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

View File

@@ -1,6 +1,6 @@
var fs = require("fs"); 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"); if (/exports\.js$/.test(file)) file = require.resolve("./exports");
return fs.readFileSync(file, "utf8"); 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 crypto = require("crypto");
var U = require("./node"); var U = require("..");
var List = U.List; var List = U.List;
var os = require("os"); var os = require("os");
var sandbox = require("./sandbox"); var sandbox = require("./sandbox");
@@ -24,6 +24,10 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
reduce_options = reduce_options || {}; reduce_options = reduce_options || {};
var max_iterations = reduce_options.max_iterations || 1000; var max_iterations = reduce_options.max_iterations || 1000;
var max_timeout = reduce_options.max_timeout || 10000; 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 verbose = reduce_options.verbose;
var minify_options_json = JSON.stringify(minify_options, null, 2); var minify_options_json = JSON.stringify(minify_options, null, 2);
var result_cache = Object.create(null); 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); var differs = producesDifferentResultWhenMinified(result_cache, testcase, minify_options, max_timeout);
if (verbose) { 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) { if (!differs) {
// same stdout result produced when minified // same stdout result produced when minified
@@ -39,16 +43,19 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
code: [ code: [
"// Can't reproduce test failure", "// Can't reproduce test failure",
"// minify options: " + to_comment(minify_options_json) "// minify options: " + to_comment(minify_options_json)
].join("\n") ].join("\n"),
warnings: warnings,
}; };
} else if (differs.timed_out) { } else if (differs.timed_out) {
return { return {
code: [ code: [
"// Can't reproduce test failure within " + max_timeout + "ms", "// Can't reproduce test failure within " + max_timeout + "ms",
"// minify options: " + to_comment(minify_options_json) "// minify options: " + to_comment(minify_options_json)
].join("\n") ].join("\n"),
warnings: warnings,
}; };
} else if (differs.error) { } else if (differs.error) {
differs.warnings = warnings;
return differs; return differs;
} else if (is_error(differs.unminified_result) } else if (is_error(differs.unminified_result)
&& is_error(differs.minified_result) && is_error(differs.minified_result)
@@ -57,7 +64,8 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
code: [ code: [
"// No differences except in error message", "// No differences except in error message",
"// minify options: " + to_comment(minify_options_json) "// minify options: " + to_comment(minify_options_json)
].join("\n") ].join("\n"),
warnings: warnings,
}; };
} else { } else {
max_timeout = Math.min(100 * differs.elapsed, max_timeout); 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) { else if (node instanceof U.AST_Binary) {
CHANGED = true;
var permute = ((node.start._permute += step) * steps | 0) % 4; var permute = ((node.start._permute += step) * steps | 0) % 4;
var expr = [ var expr = [
node.left, node.left,
node.right, node.right,
][ permute & 1 ]; ][ 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; CHANGED = true;
return null; return permute < 2 ? expr : wrap_with_console_log(expr);
}
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_BlockStatement) { else if (node instanceof U.AST_BlockStatement) {
if (in_list) { if (in_list) {
@@ -193,12 +174,26 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
return to_sequence(seq); 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) { else if (node instanceof U.AST_Defun) {
switch (((node.start._permute += step) * steps | 0) % 2) { switch (((node.start._permute += step) * steps | 0) % 2) {
case 0: case 0:
CHANGED = true; CHANGED = true;
return List.skip; return List.skip;
case 1: default:
if (!has_exit(node)) { if (!has_exit(node)) {
// hoist function declaration body // hoist function declaration body
var body = node.body; var body = node.body;
@@ -230,15 +225,11 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
return to_statement(expr); return to_statement(expr);
} }
} }
else if (node instanceof U.AST_PropAccess) { else if (node instanceof U.AST_Finally) {
var expr = [ // drop finally block
node.expression, node.start._permute++;
node.property instanceof U.AST_Node && node.property, CHANGED = true;
][ node.start._permute++ % 2 ]; return null;
if (expr) {
CHANGED = true;
return expr;
}
} }
else if (node instanceof U.AST_For) { else if (node instanceof U.AST_For) {
var expr = [ var expr = [
@@ -287,6 +278,16 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
return expr; 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) { else if (node instanceof U.AST_SimpleStatement) {
if (node.body instanceof U.AST_Call && node.body.expression instanceof U.AST_Function) { if (node.body instanceof U.AST_Call && node.body.expression instanceof U.AST_Function) {
// hoist simple statement IIFE function expression body // 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) { for (var pass = 1; pass <= 3; ++pass) {
var testcase_ast = U.parse(testcase); 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) { testcase_ast.walk(new U.TreeWalker(function(node) {
// unshare start props to retain visit data between iterations // unshare start props to retain visit data between iterations
node.start = JSON.parse(JSON.stringify(node.start)); node.start = JSON.parse(JSON.stringify(node.start));
node.start._permute = 0; node.start._permute = 0;
})); }));
for (var c = 0; c < max_iterations; ++c) { for (var c = 0; c < max_iterations; ++c) {
if (verbose) { if (verbose && pass == 1 && c % 25 == 0) {
if (pass == 1 && c % 25 == 0) { log("// reduce test pass " + pass + ", iteration " + c + ": " + testcase.length + " bytes");
console.error("// reduce test pass "
+ pass + ", iteration " + c + ": " + testcase.length + " bytes");
}
} }
var CHANGED = false; var CHANGED = false;
var code_ast = testcase_ast.clone(true).transform(tt); 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) { } catch (ex) {
// AST is not well formed. // AST is not well formed.
// no harm done - just log the error, ignore latest change and continue iterating. // no harm done - just log the error, ignore latest change and continue iterating.
console.error("*** Error generating code from AST."); log("*** Error generating code from AST.");
console.error(ex); log(ex.stack);
console.error("*** Discarding permutation and continuing."); log("*** Discarding permutation and continuing.");
continue; continue;
} }
var diff = producesDifferentResultWhenMinified(result_cache, code, minify_options, max_timeout); 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) { } else if (diff.error) {
// something went wrong during minify() - could be malformed AST or genuine bug. // 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. // no harm done - just log code & error, ignore latest change and continue iterating.
console.error("*** Error during minification."); log("*** Error during minification.");
console.error(code); log(code);
console.error(diff.error); log(diff.error.stack);
console.error("*** Discarding permutation and continuing."); log("*** Discarding permutation and continuing.");
} else if (is_error(diff.unminified_result) } else if (is_error(diff.unminified_result)
&& is_error(diff.minified_result) && is_error(diff.minified_result)
&& diff.unminified_result.name == diff.minified_result.name) { && diff.unminified_result.name == diff.minified_result.name) {
// ignore difference in error messages caused by minification // ignore difference in error messages caused by minification
diff_error_message = testcase;
} else { } else {
// latest permutation is valid, so use it as the basis of new changes // latest permutation is valid, so use it as the basis of new changes
testcase_ast = code_ast; testcase_ast = code_ast;
@@ -467,7 +491,7 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
} }
if (c == 0) break; if (c == 0) break;
if (verbose) { 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); 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)); lines.push("// options: " + to_comment(minify_options_json));
testcase.code += lines.join("\n"); testcase.code += lines.join("\n");
testcase.warnings = warnings;
return testcase; 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) { function run_code(result_cache, code, toplevel, timeout) {
var key = crypto.createHash("sha1").update(code).digest("base64"); var key = crypto.createHash("sha1").update(code).digest("base64");
return result_cache[key] || (result_cache[key] = sandbox.run_code(code, toplevel, timeout)); 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")([ require("./run")([
"-b", "-b",
"-b braces", "-b braces",

View File

@@ -764,10 +764,18 @@ function _createExpression(recurmax, noComma, stmtDepth, canThrow) {
return createObjectLiteral(recurmax, stmtDepth, canThrow) + "." + getDotKey(); return createObjectLiteral(recurmax, stmtDepth, canThrow) + "." + getDotKey();
case p++: case p++:
var name = getVarName(); 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++: case p++:
var name = getVarName(); 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++: case p++:
case p++: case p++:
@@ -1023,7 +1031,7 @@ function log_suspects(minify_options, component) {
errorln(result.error); errorln(result.error);
} else { } else {
var r = sandbox.run_code(result.code, sandbox.has_toplevel(m)); 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) { function log_suspects_global(options) {
var o = {}; var suspects = Object.keys(default_options).filter(function(component) {
UglifyJS.minify("", o); return typeof default_options[component] != "object";
var suspects = Object.keys(o).filter(function(component) {
return typeof o[component] != "object";
}).filter(function(component) { }).filter(function(component) {
var m = JSON.parse(options); var m = JSON.parse(options);
m[component] = false; m[component] = false;
@@ -1050,7 +1056,7 @@ function log_suspects_global(options) {
errorln(result.error); errorln(result.error);
} else { } else {
var r = sandbox.run_code(result.code, sandbox.has_toplevel(m)); 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) { if (suspects.length > 0) {
@@ -1107,7 +1113,10 @@ function log(options) {
errorln(JSON.stringify(JSON.parse(options), null, 2)); errorln(JSON.stringify(JSON.parse(options), null, 2));
errorln(); errorln();
if (!ok && typeof uglify_code == "string") { 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); log_suspects_global(options);
errorln("!!!!!! Failed... round " + round); errorln("!!!!!! Failed... round " + round);
} }
@@ -1150,7 +1159,7 @@ for (var round = 1; round <= num_iterations; round++) {
uglify_code = uglify_code.code; uglify_code = uglify_code.code;
uglify_result = sandbox.run_code(uglify_code, toplevel); uglify_result = sandbox.run_code(uglify_code, toplevel);
ok = sandbox.same_stdout(original_result, uglify_result); 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); ok = fuzzy_match(original_result, uglify_result);
if (!ok) { if (!ok) {
var fuzzy_result = sandbox.run_code(original_code.replace(/( - 0\.1){3}/g, " - 0.3"), toplevel); 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() { process.once("uncaughtException", function() {
(function callback() { (function callback() {
if (process.stdout.bufferSize || process.stderr.bufferSize) { if (process.stdout.bufferSize || process.stderr.bufferSize) {
setImmediate(callback); setTimeout(callback, 1);
} else { } else {
exit.apply(process, args); exit.apply(process, args);
} }

View File

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