Compare commits

...

10 Commits

Author SHA1 Message Date
Alex Lam S.L
5b22334f3b Merge pull request #1982 from alexlamsl/harmony-v3.0.10
Merging from master for 3.0.10
2017-05-21 03:23:59 +08:00
alexlamsl
a3053c537a Merge branch 'master' into harmony-v3.0.10 2017-05-21 01:36:38 +08:00
Alex Lam S.L
d3c4a8e9e7 v3.0.10 2017-05-21 01:30:17 +08:00
kzc
d6f77a6352 update keywords in package.json (#1981) 2017-05-20 22:10:51 +08:00
kzc
7e164aba8f add "es5" to package.json keywords (#1980) 2017-05-20 22:09:50 +08:00
kzc
22aedef849 document minify() option toplevel (#1979) 2017-05-20 22:09:21 +08:00
Alex Lam S.L
58fae7dc07 enhance if_return to handle return void... (#1977)
fixes #512
2017-05-20 15:58:46 +08:00
Alex Lam S.L
a2172e1a99 fix parsing of yield as object key (#1976)
fixes #1974
2017-05-20 13:11:37 +08:00
kzc
5bf8d7e949 document 3.x minify() does not throw errors (#1975) 2017-05-20 10:49:35 +08:00
kzc
1df9d06f4a document minify warnings and add an error example (#1973) 2017-05-19 17:20:21 +08:00
9 changed files with 108 additions and 35 deletions

View File

@@ -298,27 +298,64 @@ like this:
var UglifyJS = require("uglify-es"); var UglifyJS = require("uglify-es");
``` ```
There is a single high level minification function, `minify(files, options)`, which will There is a single high level minification function, `minify(code, options)`, which will
performs all the steps in a configurable manner. performs all the steps in a configurable manner.
Example: 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 also compress multiple files:
```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));"
}); };
console.log(result.code); var result = UglifyJS.minify(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));
```
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).
@@ -344,7 +381,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
{ {
@@ -499,8 +536,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.
@@ -725,8 +762,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.
``` ```

View File

@@ -940,12 +940,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
@@ -955,7 +955,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];
@@ -965,7 +965,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, {
@@ -975,8 +975,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);
@@ -985,11 +985,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;
// //

View File

@@ -2411,7 +2411,8 @@ function parse($TEXT, options) {
unexpected(tmp); unexpected(tmp);
} }
case "name": case "name":
if (tmp.value === "yield" && S.input.has_directive("use strict") && !is_in_generator()) { if (tmp.value == "yield" && !is_token(peek(), "punc", ":")
&& S.input.has_directive("use strict") && !is_in_generator()) {
token_error(tmp, "Unexpected yield identifier inside strict mode"); token_error(tmp, "Unexpected yield identifier inside strict mode");
} }
case "string": case "string":

View File

@@ -4,7 +4,7 @@
"homepage": "https://github.com/mishoo/UglifyJS2/tree/harmony", "homepage": "https://github.com/mishoo/UglifyJS2/tree/harmony",
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)", "author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
"license": "BSD-2-Clause", "license": "BSD-2-Clause",
"version": "3.0.9", "version": "3.0.10",
"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", "uglify-es", "minify", "minifier", "es5", "es6", "es2015"]
} }

View File

@@ -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();
}
}
}

View File

@@ -190,3 +190,12 @@ yield_sub: {
} }
expect_exact: 'function*foo(){yield x["foo"];(yield x)["foo"];yield(yield obj.foo())["bar"]()}' expect_exact: 'function*foo(){yield x["foo"];(yield x)["foo"];yield(yield obj.foo())["bar"]()}'
} }
yield_as_ES5_property: {
input: {
"use strict";
console.log({yield: 42}.yield);
}
expect_exact: '"use strict";console.log({yield:42}.yield);'
expect_stdout: "42"
}

View File

@@ -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();
}); });

View File

@@ -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();
}); });

View File

@@ -65,9 +65,9 @@ describe("Yield", function() {
); );
}); });
it("Should not allow yield to be used as symbol, identifier or property outside generators in strict mode", function() { it("Should not allow yield to be used as symbol, identifier or shorthand property outside generators in strict mode", function() {
var tests = [ var tests = [
// Fail as as_symbol // Fail in as_symbol
'"use strict"; import yield from "bar";', '"use strict"; import yield from "bar";',
'"use strict"; yield = 123;', '"use strict"; yield = 123;',
'"use strict"; yield: "123";', '"use strict"; yield: "123";',
@@ -79,13 +79,12 @@ describe("Yield", function() {
'"use strict"; var yield = "foo";', '"use strict"; var yield = "foo";',
'"use strict"; class yield {}', '"use strict"; class yield {}',
// Fail as maybe_assign // Fail in maybe_assign
'"use strict"; var foo = yield;', '"use strict"; var foo = yield;',
'"use strict"; var foo = bar = yield', '"use strict"; var foo = bar = yield',
// Fail as as_property_name // Fail in as_property_name
'"use strict"; var foo = {yield};', '"use strict"; var foo = {yield};',
'"use strict"; var bar = {yield: "foo"};'
]; ];
var fail = function(e) { var fail = function(e) {