Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e95052a423 | ||
|
|
e667f0acb8 | ||
|
|
69ac794bc8 | ||
|
|
efdb65913b | ||
|
|
a1dedeb3ce | ||
|
|
d3c4a8e9e7 | ||
|
|
7e164aba8f | ||
|
|
22aedef849 | ||
|
|
58fae7dc07 | ||
|
|
5bf8d7e949 | ||
|
|
1df9d06f4a | ||
|
|
3408fc9d32 | ||
|
|
eae26756f1 |
148
README.md
148
README.md
@@ -127,7 +127,7 @@ a double dash to prevent input files being used as option arguments:
|
|||||||
`url` If specified, path to the source map to append in
|
`url` If specified, path to the source map to append in
|
||||||
`//# sourceMappingURL`.
|
`//# sourceMappingURL`.
|
||||||
--stats Display operations run time on STDERR.
|
--stats Display operations run time on STDERR.
|
||||||
--toplevel Compress and/or mangle variables in toplevel scope.
|
--toplevel Compress and/or mangle variables in top level scope.
|
||||||
--verbose Print diagnostic messages.
|
--verbose Print diagnostic messages.
|
||||||
--warn Print warning messages.
|
--warn Print warning messages.
|
||||||
--wrap <name> Embed everything in a big function, making the
|
--wrap <name> Embed everything in a big function, making the
|
||||||
@@ -202,7 +202,7 @@ Example:
|
|||||||
To enable the mangler you need to pass `--mangle` (`-m`). The following
|
To enable the mangler you need to pass `--mangle` (`-m`). The following
|
||||||
(comma-separated) options are supported:
|
(comma-separated) options are supported:
|
||||||
|
|
||||||
- `toplevel` — mangle names declared in the toplevel scope (disabled by
|
- `toplevel` — mangle names declared in the top level scope (disabled by
|
||||||
default).
|
default).
|
||||||
|
|
||||||
- `eval` — mangle names visible in scopes where `eval` or `with` are used
|
- `eval` — mangle names visible in scopes where `eval` or `with` are used
|
||||||
@@ -301,27 +301,94 @@ like this:
|
|||||||
var UglifyJS = require("uglify-js");
|
var UglifyJS = require("uglify-js");
|
||||||
```
|
```
|
||||||
|
|
||||||
There is a single high level minification function, `minify(files, options)`, which will
|
There is a single high level function, **`minify(code, options)`**,
|
||||||
performs all the steps in a configurable manner.
|
which will perform all minification [phases](#minify-options) in a configurable
|
||||||
Example:
|
manner. By default `minify()` will enable the options [`compress`](#compress-options)
|
||||||
|
and [`mangle`](#mangle-options). Example:
|
||||||
```javascript
|
```javascript
|
||||||
var result = UglifyJS.minify("var b = function() {};");
|
var code = "function add(first, second) { return first + second; }";
|
||||||
console.log(result.code); // minified output
|
var result = UglifyJS.minify(code);
|
||||||
console.log(result.error); // runtime error
|
console.log(result.error); // runtime error, or `undefined` if no error
|
||||||
|
console.log(result.code); // minified output: function add(n,d){return n+d}
|
||||||
```
|
```
|
||||||
|
|
||||||
You can also compress multiple files:
|
You can `minify` more than one JavaScript file at a time by using an object
|
||||||
|
for the first argument where the keys are file names and the values are source
|
||||||
|
code:
|
||||||
```javascript
|
```javascript
|
||||||
var result = UglifyJS.minify({
|
var code = {
|
||||||
"file1.js": "var a = function() {};",
|
"file1.js": "function add(first, second) { return first + second; }",
|
||||||
"file2.js": "var b = function() {};"
|
"file2.js": "console.log(add(1 + 2, 3 + 4));"
|
||||||
});
|
};
|
||||||
|
var result = UglifyJS.minify(code);
|
||||||
console.log(result.code);
|
console.log(result.code);
|
||||||
|
// function add(d,n){return d+n}console.log(add(3,7));
|
||||||
|
```
|
||||||
|
|
||||||
|
The `toplevel` option:
|
||||||
|
```javascript
|
||||||
|
var code = {
|
||||||
|
"file1.js": "function add(first, second) { return first + second; }",
|
||||||
|
"file2.js": "console.log(add(1 + 2, 3 + 4));"
|
||||||
|
};
|
||||||
|
var options = { toplevel: true };
|
||||||
|
var result = UglifyJS.minify(code, options);
|
||||||
|
console.log(result.code);
|
||||||
|
// console.log(function(n,o){return n+o}(3,7));
|
||||||
|
```
|
||||||
|
|
||||||
|
An example of a combination of `minify()` options:
|
||||||
|
```javascript
|
||||||
|
var code = {
|
||||||
|
"file1.js": "function add(first, second) { return first + second; }",
|
||||||
|
"file2.js": "console.log(add(1 + 2, 3 + 4));"
|
||||||
|
};
|
||||||
|
var options = {
|
||||||
|
toplevel: true,
|
||||||
|
compress: {
|
||||||
|
global_defs: {
|
||||||
|
"@console.log": "alert"
|
||||||
|
},
|
||||||
|
passes: 2
|
||||||
|
},
|
||||||
|
output: {
|
||||||
|
beautify: false,
|
||||||
|
preamble: "/* uglified */"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var result = UglifyJS.minify(code, options);
|
||||||
|
console.log(result.code);
|
||||||
|
// /* uglified */
|
||||||
|
// alert(10);"
|
||||||
|
```
|
||||||
|
|
||||||
|
To produce warnings:
|
||||||
|
```javascript
|
||||||
|
var code = "function f(){ var u; return 2 + 3; }";
|
||||||
|
var options = { warnings: true };
|
||||||
|
var result = UglifyJS.minify(code, options);
|
||||||
|
console.log(result.error); // runtime error, `undefined` in this case
|
||||||
|
console.log(result.warnings); // [ 'Dropping unused variable u [0:1,18]' ]
|
||||||
|
console.log(result.code); // function f(){return 5}
|
||||||
|
```
|
||||||
|
|
||||||
|
An error example:
|
||||||
|
```javascript
|
||||||
|
var result = UglifyJS.minify({"foo.js" : "if (0) else console.log(1);"});
|
||||||
|
console.log(JSON.stringify(result.error));
|
||||||
|
// {"message":"Unexpected token: keyword (else)","filename":"foo.js","line":1,"col":7,"pos":7}
|
||||||
|
```
|
||||||
|
Note: unlike `uglify-js@2.x`, the `3.x` API does not throw errors. To
|
||||||
|
achieve a similar effect one could do the following:
|
||||||
|
```javascript
|
||||||
|
var result = UglifyJS.minify(code, options);
|
||||||
|
if (result.error) throw result.error;
|
||||||
```
|
```
|
||||||
|
|
||||||
## Minify options
|
## Minify options
|
||||||
|
|
||||||
- `warnings` (default `false`) — pass `true` to display compressor warnings.
|
- `warnings` (default `false`) — pass `true` to return compressor warnings
|
||||||
|
in `result.warnings`. Use the value `"verbose"` for more detailed warnings.
|
||||||
|
|
||||||
- `parse` (default `{}`) — pass an object if you wish to specify some
|
- `parse` (default `{}`) — pass an object if you wish to specify some
|
||||||
additional [parse options](#parse-options).
|
additional [parse options](#parse-options).
|
||||||
@@ -347,7 +414,7 @@ console.log(result.code);
|
|||||||
|
|
||||||
- `ie8` (default `false`) - set to `true` to support IE8.
|
- `ie8` (default `false`) - set to `true` to support IE8.
|
||||||
|
|
||||||
## Minify option structure
|
## Minify options structure
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
{
|
{
|
||||||
@@ -462,6 +529,9 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
|
|||||||
- `unsafe_proto` (default: false) -- optimize expressions like
|
- `unsafe_proto` (default: false) -- optimize expressions like
|
||||||
`Array.prototype.slice.call(a)` into `[].slice.call(a)`
|
`Array.prototype.slice.call(a)` into `[].slice.call(a)`
|
||||||
|
|
||||||
|
- `unsafe_regexp` (default: false) -- enable substitutions of variables with
|
||||||
|
`RegExp` values the same way as if they are constants.
|
||||||
|
|
||||||
- `conditionals` -- apply optimizations for `if`-s and conditional
|
- `conditionals` -- apply optimizations for `if`-s and conditional
|
||||||
expressions
|
expressions
|
||||||
|
|
||||||
@@ -481,7 +551,7 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
|
|||||||
assignments do not count as references unless set to `"keep_assign"`)
|
assignments do not count as references unless set to `"keep_assign"`)
|
||||||
|
|
||||||
- `toplevel` -- drop unreferenced functions (`"funcs"`) and/or variables (`"vars"`)
|
- `toplevel` -- drop unreferenced functions (`"funcs"`) and/or variables (`"vars"`)
|
||||||
in the toplevel scope (`false` by default, `true` to drop both unreferenced
|
in the top level scope (`false` by default, `true` to drop both unreferenced
|
||||||
functions and variables)
|
functions and variables)
|
||||||
|
|
||||||
- `top_retain` -- prevent specific toplevel functions and variables from `unused`
|
- `top_retain` -- prevent specific toplevel functions and variables from `unused`
|
||||||
@@ -499,8 +569,8 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
|
|||||||
- `cascade` -- small optimization for sequences, transform `x, x` into `x`
|
- `cascade` -- small optimization for sequences, transform `x, x` into `x`
|
||||||
and `x = something(), x` into `x = something()`
|
and `x = something(), x` into `x = something()`
|
||||||
|
|
||||||
- `collapse_vars` -- Collapse single-use `var` and `const` definitions
|
- `collapse_vars` -- Collapse single-use non-constant variables - side
|
||||||
when possible.
|
effects permitting.
|
||||||
|
|
||||||
- `reduce_vars` -- Improve optimization on variables assigned with and
|
- `reduce_vars` -- Improve optimization on variables assigned with and
|
||||||
used as constant values.
|
used as constant values.
|
||||||
@@ -552,16 +622,16 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
|
|||||||
- `keep_infinity` -- default `false`. Pass `true` to prevent `Infinity` from
|
- `keep_infinity` -- default `false`. Pass `true` to prevent `Infinity` from
|
||||||
being compressed into `1/0`, which may cause performance issues on Chrome.
|
being compressed into `1/0`, which may cause performance issues on Chrome.
|
||||||
|
|
||||||
- `side_effects` -- default `true`. Pass `false` to disable potentially dropping
|
- `side_effects` -- default `true`. Pass `false` to disable potentially dropping
|
||||||
functions marked as "pure". A function call is marked as "pure" if a comment
|
functions marked as "pure". A function call is marked as "pure" if a comment
|
||||||
annotation `/*@__PURE__*/` or `/*#__PURE__*/` immediately precedes the call. For
|
annotation `/*@__PURE__*/` or `/*#__PURE__*/` immediately precedes the call. For
|
||||||
example: `/*@__PURE__*/foo()`;
|
example: `/*@__PURE__*/foo();`
|
||||||
|
|
||||||
## Mangle options
|
## Mangle options
|
||||||
|
|
||||||
- `reserved` - pass an array of identifiers that should be excluded from mangling
|
- `reserved` - pass an array of identifiers that should be excluded from mangling
|
||||||
|
|
||||||
- `toplevel` — mangle names declared in the toplevel scope (disabled by
|
- `toplevel` — mangle names declared in the top level scope (disabled by
|
||||||
default).
|
default).
|
||||||
|
|
||||||
- `eval` — mangle names visible in scopes where eval or with are used
|
- `eval` — mangle names visible in scopes where eval or with are used
|
||||||
@@ -722,8 +792,8 @@ Another way of doing that is to declare your globals as constants in a
|
|||||||
separate file and include it into the build. For example you can have a
|
separate file and include it into the build. For example you can have a
|
||||||
`build/defines.js` file with the following:
|
`build/defines.js` file with the following:
|
||||||
```javascript
|
```javascript
|
||||||
const DEBUG = false;
|
var DEBUG = false;
|
||||||
const PRODUCTION = true;
|
var PRODUCTION = true;
|
||||||
// etc.
|
// etc.
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -743,7 +813,7 @@ You can also use conditional compilation via the programmatic API. With the diff
|
|||||||
property name is `global_defs` and is a compressor property:
|
property name is `global_defs` and is a compressor property:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var result = uglifyJS.minify(fs.readFileSync("input.js", "utf8"), {
|
var result = UglifyJS.minify(fs.readFileSync("input.js", "utf8"), {
|
||||||
compress: {
|
compress: {
|
||||||
dead_code: true,
|
dead_code: true,
|
||||||
global_defs: {
|
global_defs: {
|
||||||
@@ -753,6 +823,32 @@ var result = uglifyJS.minify(fs.readFileSync("input.js", "utf8"), {
|
|||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
|
To replace an identifier with an arbitrary non-constant expression it is
|
||||||
|
necessary to prefix the `global_defs` key with `"@"` to instruct UglifyJS
|
||||||
|
to parse the value as an expression:
|
||||||
|
```javascript
|
||||||
|
UglifyJS.minify("alert('hello');", {
|
||||||
|
compress: {
|
||||||
|
global_defs: {
|
||||||
|
"@alert": "console.log"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).code;
|
||||||
|
// returns: 'console.log("hello");'
|
||||||
|
```
|
||||||
|
|
||||||
|
Otherwise it would be replaced as string literal:
|
||||||
|
```javascript
|
||||||
|
UglifyJS.minify("alert('hello');", {
|
||||||
|
compress: {
|
||||||
|
global_defs: {
|
||||||
|
"alert": "console.log"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).code;
|
||||||
|
// returns: '"console.log"("hello");'
|
||||||
|
```
|
||||||
|
|
||||||
### Using native Uglify AST with `minify()`
|
### Using native Uglify AST with `minify()`
|
||||||
```javascript
|
```javascript
|
||||||
// example: parse only, produce native Uglify AST
|
// example: parse only, produce native Uglify AST
|
||||||
|
|||||||
@@ -83,9 +83,21 @@ function Compressor(options, false_by_default) {
|
|||||||
unsafe_comps : false,
|
unsafe_comps : false,
|
||||||
unsafe_math : false,
|
unsafe_math : false,
|
||||||
unsafe_proto : false,
|
unsafe_proto : false,
|
||||||
|
unsafe_regexp : false,
|
||||||
unused : !false_by_default,
|
unused : !false_by_default,
|
||||||
warnings : false,
|
warnings : false,
|
||||||
}, true);
|
}, true);
|
||||||
|
var global_defs = this.options["global_defs"];
|
||||||
|
if (typeof global_defs == "object") for (var key in global_defs) {
|
||||||
|
if (/^@/.test(key) && HOP(global_defs, key)) {
|
||||||
|
var ast = parse(global_defs[key]);
|
||||||
|
if (ast.body.length == 1 && ast.body[0] instanceof AST_SimpleStatement) {
|
||||||
|
global_defs[key.slice(1)] = ast.body[0].body;
|
||||||
|
} else throw new Error(string_template("Can't handle expression: {value}", {
|
||||||
|
value: global_defs[key]
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
var pure_funcs = this.options["pure_funcs"];
|
var pure_funcs = this.options["pure_funcs"];
|
||||||
if (typeof pure_funcs == "function") {
|
if (typeof pure_funcs == "function") {
|
||||||
this.pure_funcs = pure_funcs;
|
this.pure_funcs = pure_funcs;
|
||||||
@@ -913,12 +925,12 @@ merge(Compressor.prototype, {
|
|||||||
continue loop;
|
continue loop;
|
||||||
case stat instanceof AST_If:
|
case stat instanceof AST_If:
|
||||||
if (stat.body instanceof AST_Return) {
|
if (stat.body instanceof AST_Return) {
|
||||||
|
var value = stat.body.value;
|
||||||
//---
|
//---
|
||||||
// pretty silly case, but:
|
// pretty silly case, but:
|
||||||
// if (foo()) return; return; ==> foo(); return;
|
// if (foo()) return; return; ==> foo(); return;
|
||||||
if (((in_lambda && ret.length == 0)
|
if ((in_lambda && ret.length == 0 || ret[0] instanceof AST_Return && !ret[0].value)
|
||||||
|| (ret[0] instanceof AST_Return && !ret[0].value))
|
&& !value && !stat.alternative) {
|
||||||
&& !stat.body.value && !stat.alternative) {
|
|
||||||
CHANGED = true;
|
CHANGED = true;
|
||||||
var cond = make_node(AST_SimpleStatement, stat.condition, {
|
var cond = make_node(AST_SimpleStatement, stat.condition, {
|
||||||
body: stat.condition
|
body: stat.condition
|
||||||
@@ -928,7 +940,7 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
//---
|
//---
|
||||||
// if (foo()) return x; return y; ==> return foo() ? x : y;
|
// if (foo()) return x; return y; ==> return foo() ? x : y;
|
||||||
if (ret[0] instanceof AST_Return && stat.body.value && ret[0].value && !stat.alternative) {
|
if (ret[0] instanceof AST_Return && value && ret[0].value && !stat.alternative) {
|
||||||
CHANGED = true;
|
CHANGED = true;
|
||||||
stat = stat.clone();
|
stat = stat.clone();
|
||||||
stat.alternative = ret[0];
|
stat.alternative = ret[0];
|
||||||
@@ -938,7 +950,7 @@ merge(Compressor.prototype, {
|
|||||||
//---
|
//---
|
||||||
// if (foo()) return x; [ return ; ] ==> return foo() ? x : undefined;
|
// if (foo()) return x; [ return ; ] ==> return foo() ? x : undefined;
|
||||||
if (multiple_if_returns && (ret.length == 0 || ret[0] instanceof AST_Return)
|
if (multiple_if_returns && (ret.length == 0 || ret[0] instanceof AST_Return)
|
||||||
&& stat.body.value && !stat.alternative && in_lambda) {
|
&& value && !stat.alternative && in_lambda) {
|
||||||
CHANGED = true;
|
CHANGED = true;
|
||||||
stat = stat.clone();
|
stat = stat.clone();
|
||||||
stat.alternative = ret[0] || make_node(AST_Return, stat, {
|
stat.alternative = ret[0] || make_node(AST_Return, stat, {
|
||||||
@@ -948,8 +960,8 @@ merge(Compressor.prototype, {
|
|||||||
continue loop;
|
continue loop;
|
||||||
}
|
}
|
||||||
//---
|
//---
|
||||||
// if (foo()) return; [ else x... ]; y... ==> if (!foo()) { x...; y... }
|
// if (foo()) return [ void bar() ]; [ else x...; ] y... ==> if (!foo()) { x...; y... } else bar();
|
||||||
if (!stat.body.value && in_lambda) {
|
if (in_lambda && (!value || value instanceof AST_UnaryPrefix && value.operator == "void")) {
|
||||||
CHANGED = true;
|
CHANGED = true;
|
||||||
stat = stat.clone();
|
stat = stat.clone();
|
||||||
stat.condition = stat.condition.negate(compressor);
|
stat.condition = stat.condition.negate(compressor);
|
||||||
@@ -958,11 +970,12 @@ merge(Compressor.prototype, {
|
|||||||
stat.body = make_node(AST_BlockStatement, stat, {
|
stat.body = make_node(AST_BlockStatement, stat, {
|
||||||
body: body
|
body: body
|
||||||
});
|
});
|
||||||
stat.alternative = null;
|
stat.alternative = value ? make_node(AST_SimpleStatement, value, {
|
||||||
|
body: value.expression
|
||||||
|
}) : null;
|
||||||
ret = funs.concat([ stat.transform(compressor) ]);
|
ret = funs.concat([ stat.transform(compressor) ]);
|
||||||
continue loop;
|
continue loop;
|
||||||
}
|
}
|
||||||
|
|
||||||
//---
|
//---
|
||||||
// if (a) return b; if (c) return d; e; ==> return a ? b : c ? d : void e;
|
// if (a) return b; if (c) return d; e; ==> return a ? b : c ? d : void e;
|
||||||
//
|
//
|
||||||
@@ -3765,7 +3778,7 @@ merge(Compressor.prototype, {
|
|||||||
if (fixed) {
|
if (fixed) {
|
||||||
if (d.should_replace === undefined) {
|
if (d.should_replace === undefined) {
|
||||||
var init = fixed.evaluate(compressor);
|
var init = fixed.evaluate(compressor);
|
||||||
if (init !== fixed) {
|
if (init !== fixed && (compressor.option("unsafe_regexp") || !(init instanceof RegExp))) {
|
||||||
init = make_node_from_constant(init, fixed);
|
init = make_node_from_constant(init, fixed);
|
||||||
var value_length = init.optimize(compressor).print_to_string().length;
|
var value_length = init.optimize(compressor).print_to_string().length;
|
||||||
var fn;
|
var fn;
|
||||||
|
|||||||
@@ -189,12 +189,43 @@ function OutputStream(options) {
|
|||||||
var might_need_semicolon = false;
|
var might_need_semicolon = false;
|
||||||
var might_add_newline = 0;
|
var might_add_newline = 0;
|
||||||
var last = "";
|
var last = "";
|
||||||
|
var mapping_token, mapping_name, mappings = options.source_map && [];
|
||||||
|
|
||||||
|
var do_add_mapping = mappings ? function() {
|
||||||
|
mappings.forEach(function(mapping) {
|
||||||
|
try {
|
||||||
|
options.source_map.add(
|
||||||
|
mapping.token.file,
|
||||||
|
mapping.line, mapping.col,
|
||||||
|
mapping.token.line, mapping.token.col,
|
||||||
|
!mapping.name && mapping.token.type == "name" ? mapping.token.value : mapping.name
|
||||||
|
);
|
||||||
|
} catch(ex) {
|
||||||
|
AST_Node.warn("Couldn't figure out mapping for {file}:{line},{col} → {cline},{ccol} [{name}]", {
|
||||||
|
file: mapping.token.file,
|
||||||
|
line: mapping.token.line,
|
||||||
|
col: mapping.token.col,
|
||||||
|
cline: mapping.line,
|
||||||
|
ccol: mapping.col,
|
||||||
|
name: mapping.name || ""
|
||||||
|
})
|
||||||
|
}
|
||||||
|
});
|
||||||
|
mappings = [];
|
||||||
|
} : noop;
|
||||||
|
|
||||||
var ensure_line_len = options.max_line_len ? function() {
|
var ensure_line_len = options.max_line_len ? function() {
|
||||||
if (current_col > options.max_line_len) {
|
if (current_col > options.max_line_len) {
|
||||||
if (might_add_newline) {
|
if (might_add_newline) {
|
||||||
var left = OUTPUT.slice(0, might_add_newline);
|
var left = OUTPUT.slice(0, might_add_newline);
|
||||||
var right = OUTPUT.slice(might_add_newline);
|
var right = OUTPUT.slice(might_add_newline);
|
||||||
|
if (mappings) {
|
||||||
|
var delta = right.length - current_col;
|
||||||
|
mappings.forEach(function(mapping) {
|
||||||
|
mapping.line++;
|
||||||
|
mapping.col += delta;
|
||||||
|
});
|
||||||
|
}
|
||||||
OUTPUT = left + "\n" + right;
|
OUTPUT = left + "\n" + right;
|
||||||
current_line++;
|
current_line++;
|
||||||
current_pos++;
|
current_pos++;
|
||||||
@@ -204,7 +235,10 @@ function OutputStream(options) {
|
|||||||
AST_Node.warn("Output exceeds {max_line_len} characters", options);
|
AST_Node.warn("Output exceeds {max_line_len} characters", options);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
might_add_newline = 0;
|
if (might_add_newline) {
|
||||||
|
might_add_newline = 0;
|
||||||
|
do_add_mapping();
|
||||||
|
}
|
||||||
} : noop;
|
} : noop;
|
||||||
|
|
||||||
var requireSemicolonChars = makePredicate("( [ + * / - , .");
|
var requireSemicolonChars = makePredicate("( [ + * / - , .");
|
||||||
@@ -264,6 +298,18 @@ function OutputStream(options) {
|
|||||||
}
|
}
|
||||||
might_need_space = false;
|
might_need_space = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mapping_token) {
|
||||||
|
mappings.push({
|
||||||
|
token: mapping_token,
|
||||||
|
name: mapping_name,
|
||||||
|
line: current_line,
|
||||||
|
col: current_col
|
||||||
|
});
|
||||||
|
mapping_token = false;
|
||||||
|
if (!might_add_newline) do_add_mapping();
|
||||||
|
}
|
||||||
|
|
||||||
OUTPUT += str;
|
OUTPUT += str;
|
||||||
current_pos += str.length;
|
current_pos += str.length;
|
||||||
var a = str.split(/\r?\n/), n = a.length - 1;
|
var a = str.split(/\r?\n/), n = a.length - 1;
|
||||||
@@ -358,24 +404,9 @@ function OutputStream(options) {
|
|||||||
space();
|
space();
|
||||||
};
|
};
|
||||||
|
|
||||||
var add_mapping = options.source_map ? function(token, name) {
|
var add_mapping = mappings ? function(token, name) {
|
||||||
try {
|
mapping_token = token;
|
||||||
if (token) options.source_map.add(
|
mapping_name = name;
|
||||||
token.file || "?",
|
|
||||||
current_line, current_col,
|
|
||||||
token.line, token.col,
|
|
||||||
(!name && token.type == "name") ? token.value : name
|
|
||||||
);
|
|
||||||
} catch(ex) {
|
|
||||||
AST_Node.warn("Couldn't figure out mapping for {file}:{line},{col} → {cline},{ccol} [{name}]", {
|
|
||||||
file: token.file,
|
|
||||||
line: token.line,
|
|
||||||
col: token.col,
|
|
||||||
cline: current_line,
|
|
||||||
ccol: current_col,
|
|
||||||
name: name || ""
|
|
||||||
})
|
|
||||||
}
|
|
||||||
} : noop;
|
} : noop;
|
||||||
|
|
||||||
function get() {
|
function get() {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"homepage": "http://lisperator.net/uglifyjs",
|
"homepage": "http://lisperator.net/uglifyjs",
|
||||||
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
|
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
|
||||||
"license": "BSD-2-Clause",
|
"license": "BSD-2-Clause",
|
||||||
"version": "3.0.8",
|
"version": "3.0.11",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.8.0"
|
"node": ">=0.8.0"
|
||||||
},
|
},
|
||||||
@@ -40,5 +40,5 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "node test/run-tests.js"
|
"test": "node test/run-tests.js"
|
||||||
},
|
},
|
||||||
"keywords": ["uglify", "uglify-js", "minify", "minifier"]
|
"keywords": ["uglify", "uglify-js", "minify", "minifier", "es5"]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -990,3 +990,50 @@ Infinity_NaN_undefined_LHS: {
|
|||||||
"}",
|
"}",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_1964_1: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unsafe_regexp: false,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
var long_variable_name = /\s/;
|
||||||
|
return "a b c".split(long_variable_name)[1];
|
||||||
|
}
|
||||||
|
console.log(f());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f() {
|
||||||
|
var long_variable_name = /\s/;
|
||||||
|
return "a b c".split(long_variable_name)[1];
|
||||||
|
}
|
||||||
|
console.log(f());
|
||||||
|
}
|
||||||
|
expect_stdout: "b"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1964_2: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unsafe_regexp: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
var long_variable_name = /\s/;
|
||||||
|
return "a b c".split(long_variable_name)[1];
|
||||||
|
}
|
||||||
|
console.log(f());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f() {
|
||||||
|
return "a b c".split(/\s/)[1];
|
||||||
|
}
|
||||||
|
console.log(f());
|
||||||
|
}
|
||||||
|
expect_stdout: "b"
|
||||||
|
}
|
||||||
|
|||||||
@@ -160,3 +160,17 @@ issue_1801: {
|
|||||||
console.log(!0);
|
console.log(!0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_1986: {
|
||||||
|
options = {
|
||||||
|
global_defs: {
|
||||||
|
"@alert": "console.log",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
alert(42);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(42);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -302,3 +302,25 @@ issue_1437_conditionals: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_512: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
if_return: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function a() {
|
||||||
|
if (b()) {
|
||||||
|
c();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function a() {
|
||||||
|
if (!b()) throw e;
|
||||||
|
c();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
5
test/input/issue-505/input.js
Normal file
5
test/input/issue-505/input.js
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
function test(callback) {
|
||||||
|
'aaaaaaaaaaaaaaaa';
|
||||||
|
callback(err, data);
|
||||||
|
callback(err, data);
|
||||||
|
}
|
||||||
5
test/input/issue-505/output.js
Normal file
5
test/input/issue-505/output.js
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
function test(a){
|
||||||
|
"aaaaaaaaaaaaaaaa"
|
||||||
|
;a(err,data),a(err,data)
|
||||||
|
}
|
||||||
|
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjAiXSwibmFtZXMiOlsidGVzdCIsImNhbGxiYWNrIiwiZXJyIiwiZGF0YSJdLCJtYXBwaW5ncyI6IkFBQUEsU0FBU0EsS0FBS0M7QUFDVjtDQUNBQSxFQUFTQyxJQUFLQyxNQUNkRixFQUFTQyxJQUFLQyJ9
|
||||||
@@ -1,2 +1,2 @@
|
|||||||
new function(){console.log(3)};
|
new function(){console.log(3)};
|
||||||
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIl0sIm5hbWVzIjpbImNvbnNvbGUiLCJsb2ciXSwibWFwcGluZ3MiOiJBQUErQyxHQUFyQyxZQUFnQkEsUUFBUUMsSUFBSSIsInNvdXJjZXNDb250ZW50IjpbImNsYXNzIEZvbyB7IGNvbnN0cnVjdG9yKCl7Y29uc29sZS5sb2coMSsyKTt9IH0gbmV3IEZvbygpO1xuIl19
|
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIl0sIm5hbWVzIjpbImNvbnNvbGUiLCJsb2ciXSwibWFwcGluZ3MiOiJBQUErQyxJQUFyQyxXQUFnQkEsUUFBUUMsSUFBSSIsInNvdXJjZXNDb250ZW50IjpbImNsYXNzIEZvbyB7IGNvbnN0cnVjdG9yKCl7Y29uc29sZS5sb2coMSsyKTt9IH0gbmV3IEZvbygpO1xuIl19
|
||||||
|
|||||||
@@ -19,7 +19,9 @@ describe("bin/uglifyjs", function () {
|
|||||||
eval(stdout);
|
eval(stdout);
|
||||||
|
|
||||||
assert.strictEqual(typeof WrappedUglifyJS, 'object');
|
assert.strictEqual(typeof WrappedUglifyJS, 'object');
|
||||||
assert.strictEqual(WrappedUglifyJS.minify("foo([true,,2+3]);").code, "foo([!0,,5]);");
|
var result = WrappedUglifyJS.minify("foo([true,,2+3]);");
|
||||||
|
assert.strictEqual(result.error, undefined);
|
||||||
|
assert.strictEqual(result.code, "foo([!0,,5]);");
|
||||||
|
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
@@ -61,7 +63,7 @@ describe("bin/uglifyjs", function () {
|
|||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
|
|
||||||
assert.strictEqual(stdout, "var bar=function(){function foo(bar){return bar}return foo}();\n" +
|
assert.strictEqual(stdout, "var bar=function(){function foo(bar){return bar}return foo}();\n" +
|
||||||
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvaW5wdXQvaXNzdWUtMTMyMy9zYW1wbGUuanMiXSwibmFtZXMiOlsiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxHQUFJQSxLQUFNLFdBQ04sUUFBU0MsS0FBS0QsS0FDVixNQUFPQSxLQUdYLE1BQU9DIn0=\n");
|
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvaW5wdXQvaXNzdWUtMTMyMy9zYW1wbGUuanMiXSwibmFtZXMiOlsiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFJQSxJQUFNLFdBQ04sU0FBU0MsSUFBS0QsS0FDVixPQUFPQSxJQUdYLE9BQU9DIn0=\n");
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -173,7 +175,7 @@ describe("bin/uglifyjs", function () {
|
|||||||
|
|
||||||
assert.strictEqual(stdout, [
|
assert.strictEqual(stdout, [
|
||||||
"var bar=function(){function foo(bar){return bar}return foo}();",
|
"var bar=function(){function foo(bar){return bar}return foo}();",
|
||||||
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvaW5wdXQvaXNzdWUtMTMyMy9zYW1wbGUuanMiXSwibmFtZXMiOlsiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxHQUFJQSxLQUFNLFdBQ04sUUFBU0MsS0FBS0QsS0FDVixNQUFPQSxLQUdYLE1BQU9DIn0=",
|
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvaW5wdXQvaXNzdWUtMTMyMy9zYW1wbGUuanMiXSwibmFtZXMiOlsiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFJQSxJQUFNLFdBQ04sU0FBU0MsSUFBS0QsS0FDVixPQUFPQSxJQUdYLE9BQU9DIn0=",
|
||||||
"",
|
"",
|
||||||
].join("\n"));
|
].join("\n"));
|
||||||
assert.strictEqual(stderr, "WARN: inline source map not found\n");
|
assert.strictEqual(stderr, "WARN: inline source map not found\n");
|
||||||
@@ -512,7 +514,7 @@ describe("bin/uglifyjs", function () {
|
|||||||
|
|
||||||
assert.strictEqual(stdout, [
|
assert.strictEqual(stdout, [
|
||||||
'"use strict";var foo=function foo(x){return"foo "+x};console.log(foo("bar"));',
|
'"use strict";var foo=function foo(x){return"foo "+x};console.log(foo("bar"));',
|
||||||
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImluZGV4LmpzIl0sIm5hbWVzIjpbImZvbyIsIngiLCJjb25zb2xlIiwibG9nIl0sIm1hcHBpbmdzIjoiWUFBQSxJQUFJQSxLQUFNLFFBQU5BLEtBQU1DLEdBQUEsTUFBSyxPQUFTQSxFQUN4QkMsU0FBUUMsSUFBSUgsSUFBSSJ9",
|
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImluZGV4LmpzIl0sIm5hbWVzIjpbImZvbyIsIngiLCJjb25zb2xlIiwibG9nIl0sIm1hcHBpbmdzIjoiYUFBQSxJQUFJQSxJQUFNLFNBQU5BLElBQU1DLEdBQUEsTUFBSyxPQUFTQSxHQUN4QkMsUUFBUUMsSUFBSUgsSUFBSSJ9",
|
||||||
""
|
""
|
||||||
].join("\n"));
|
].join("\n"));
|
||||||
done();
|
done();
|
||||||
|
|||||||
@@ -138,13 +138,25 @@ describe("minify", function() {
|
|||||||
});
|
});
|
||||||
var code = result.code;
|
var code = result.code;
|
||||||
assert.strictEqual(code, "var a=function(n){return n};\n" +
|
assert.strictEqual(code, "var a=function(n){return n};\n" +
|
||||||
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjAiXSwibmFtZXMiOlsiYSIsImZvbyJdLCJtYXBwaW5ncyI6IkFBQUEsR0FBSUEsR0FBSSxTQUFTQyxHQUFPLE1BQU9BIn0=");
|
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjAiXSwibmFtZXMiOlsiYSIsImZvbyJdLCJtYXBwaW5ncyI6IkFBQUEsSUFBSUEsRUFBSSxTQUFTQyxHQUFPLE9BQU9BIn0=");
|
||||||
});
|
});
|
||||||
it("should not append source map to output js when sourceMapInline is not enabled", function() {
|
it("should not append source map to output js when sourceMapInline is not enabled", function() {
|
||||||
var result = Uglify.minify('var a = function(foo) { return foo; };');
|
var result = Uglify.minify('var a = function(foo) { return foo; };');
|
||||||
var code = result.code;
|
var code = result.code;
|
||||||
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() {
|
||||||
|
var result = Uglify.minify(read("./test/input/issue-505/input.js"), {
|
||||||
|
output: {
|
||||||
|
max_line_len: 20
|
||||||
|
},
|
||||||
|
sourceMap: {
|
||||||
|
url: "inline"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
assert.strictEqual(result.error, undefined);
|
||||||
|
assert.strictEqual(result.code, read("./test/input/issue-505/output.js"));
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("#__PURE__", function() {
|
describe("#__PURE__", function() {
|
||||||
@@ -181,4 +193,19 @@ describe("minify", function() {
|
|||||||
assert.strictEqual(err.col, 12);
|
assert.strictEqual(err.col, 12);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("global_defs", function() {
|
||||||
|
it("should throw for non-trivial expressions", function() {
|
||||||
|
var result = Uglify.minify("alert(42);", {
|
||||||
|
compress: {
|
||||||
|
global_defs: {
|
||||||
|
"@alert": "debugger"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
var err = result.error;
|
||||||
|
assert.ok(err instanceof Error);
|
||||||
|
assert.strictEqual(err.stack.split(/\n/)[0], "Error: Can't handle expression: debugger");
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -15,7 +15,9 @@ describe("spidermonkey export/import sanity test", function() {
|
|||||||
|
|
||||||
eval(stdout);
|
eval(stdout);
|
||||||
assert.strictEqual(typeof SpiderUglify, "object");
|
assert.strictEqual(typeof SpiderUglify, "object");
|
||||||
assert.strictEqual(SpiderUglify.minify("foo([true,,2+3]);").code, "foo([!0,,5]);");
|
var result = SpiderUglify.minify("foo([true,,2+3]);");
|
||||||
|
assert.strictEqual(result.error, undefined);
|
||||||
|
assert.strictEqual(result.code, "foo([!0,,5]);");
|
||||||
|
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
var UglifyJS = require("./node");
|
var UglifyJS = require("..");
|
||||||
var ok = require("assert");
|
var ok = require("assert");
|
||||||
|
|
||||||
module.exports = function () {
|
module.exports = function () {
|
||||||
@@ -26,11 +26,11 @@ module.exports = function () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function source_map(js) {
|
function source_map(js) {
|
||||||
var source_map = UglifyJS.SourceMap();
|
return JSON.parse(UglifyJS.minify(js, {
|
||||||
var stream = UglifyJS.OutputStream({ source_map: source_map });
|
compress: false,
|
||||||
var parsed = UglifyJS.parse(js);
|
mangle: false,
|
||||||
parsed.print(stream);
|
sourceMap: true
|
||||||
return JSON.parse(source_map.toString());
|
}).map);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run standalone
|
// Run standalone
|
||||||
|
|||||||
Reference in New Issue
Block a user