Compare commits

...

5 Commits

Author SHA1 Message Date
Alex Lam S.L
daaefc17b9 v3.0.4 2017-05-12 04:52:39 +08:00
Alex Lam S.L
1d407e761e fix invalid transform on const (#1919)
- preserve (re)assignment to `const` for runtime error
- suppress `cascade` on `const`, as runtime behaviour is ill-defined
2017-05-12 04:51:44 +08:00
kzc
2b44f4ae30 update README (#1918) 2017-05-12 03:36:33 +08:00
Alexis Tyler
e51c3541da fix typo (#1913) 2017-05-11 20:24:33 +08:00
Alex Lam S.L
3bf194684b update documentation (#1909)
- clarify options on `--source-map`
- fix `minify()` examples

fixes #1905
2017-05-11 17:50:50 +08:00
6 changed files with 155 additions and 44 deletions

View File

@@ -7,7 +7,7 @@ UglifyJS is a JavaScript parser, minifier, compressor and beautifier toolkit.
#### Note: #### Note:
- **`uglify-js@3.x` has a new API and CLI and is not backwards compatible with [`uglify-js@2.x`](https://github.com/mishoo/UglifyJS2/tree/v2.x)**. - **`uglify-js@3.x` has a new API and CLI and is not backwards compatible with [`uglify-js@2.x`](https://github.com/mishoo/UglifyJS2/tree/v2.x)**.
- **Documentation for UglifyJS `2.x` releases can be found [here](https://github.com/mishoo/UglifyJS2/tree/v2.x)**. - **Documentation for UglifyJS `2.x` releases can be found [here](https://github.com/mishoo/UglifyJS2/tree/v2.x)**.
- Release versions of `uglify-js` only support ECMAScript 5 (ES5). - `uglify-js` only supports ECMAScript 5 (ES5).
- Those wishing to minify - Those wishing to minify
ES2015+ (ES6+) should use the `npm` package [**uglify-es**](https://github.com/mishoo/UglifyJS2/tree/harmony). ES2015+ (ES6+) should use the `npm` package [**uglify-es**](https://github.com/mishoo/UglifyJS2/tree/harmony).
@@ -149,16 +149,21 @@ debugging your compressed JavaScript. To get a source map, pass
`--source-map --output output.js` (source map will be written out to `--source-map --output output.js` (source map will be written out to
`output.js.map`). `output.js.map`).
Additionally you might need `--source-map root=<URL>` to pass the URL where Additional options:
the original files can be found. Use `--source-map url=<URL>` to specify
the URL where the source map can be found. - `--source-map filename=<NAME>` to specify the name of the source map.
- `--source-map root=<URL>` to pass the URL where the original files can be found.
Otherwise UglifyJS assumes HTTP `X-SourceMap` is being used and will omit the
`//# sourceMappingURL=` directive.
- `--source-map url=<URL>` to specify the URL where the source map can be found.
For example: For example:
uglifyjs /home/doe/work/foo/src/js/file1.js \ uglifyjs js/file1.js js/file2.js \
/home/doe/work/foo/src/js/file2.js \
-o foo.min.js -c -m \ -o foo.min.js -c -m \
--source-map base="/home/doe/work/foo/src",root="http://foo.com/src" --source-map root="http://foo.com/src",url=foo.min.js.map
The above will compress and mangle `file1.js` and `file2.js`, will drop the The above will compress and mangle `file1.js` and `file2.js`, will drop the
output in `foo.min.js` and the source map in `foo.min.js.map`. The source output in `foo.min.js` and the source map in `foo.min.js.map`. The source
@@ -177,11 +182,9 @@ CoffeeScript → compiled JS, UglifyJS can generate a map from CoffeeScript →
compressed JS by mapping every token in the compiled JS to its original compressed JS by mapping every token in the compiled JS to its original
location. location.
To use this feature you need to pass `--in-source-map To use this feature pass `--source-map content="/path/to/input/source.map"`
/path/to/input/source.map` or `--in-source-map inline` if the source map is or `--source-map content=inline` if the source map is included inline with
included inline with the sources. Normally the input source map should also the sources.
point to the file containing the generated JS, so if that's correct you can
omit input files from the command line.
## Mangler options ## Mangler options
@@ -464,7 +467,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:
```js ```js
uglifyJS.minify([ "input.js"], { uglifyJS.minify(fs.readFileSync("input.js", "utf8"), {
compress: { compress: {
dead_code: true, dead_code: true,
global_defs: { global_defs: {
@@ -670,44 +673,47 @@ Other options:
##### mangle ##### mangle
- `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 toplevel 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
(disabled by default). (disabled by default).
- `keep_fnames` -- default `false`. Pass `true` to not mangle - `keep_fnames` -- default `false`. Pass `true` to not mangle
function names. Useful for code relying on `Function.prototype.name`. function names. Useful for code relying on `Function.prototype.name`.
See also: the `keep_fnames` [compress option](#compressor-options). See also: the `keep_fnames` [compress option](#compressor-options).
Examples: Examples:
```javascript ```javascript
//tst.js // test.js
var globalVar; var globalVar;
function funcName(firstLongName, anotherLongName) function funcName(firstLongName, anotherLongName)
{ {
var myVariable = firstLongName + anotherLongName; var myVariable = firstLongName + anotherLongName;
} }
```
```javascript
var code = fs.readFileSync("test.js", "utf8");
UglifyJS.minify("tst.js").code; UglifyJS.minify(code).code;
// 'function funcName(a,n){}var globalVar;' // 'function funcName(a,n){}var globalVar;'
UglifyJS.minify("tst.js", { mangle: { reserved: ['firstLongName'] } }).code; UglifyJS.minify(code, { mangle: { reserved: ['firstLongName'] } }).code;
// 'function funcName(firstLongName,a){}var globalVar;' // 'function funcName(firstLongName,a){}var globalVar;'
UglifyJS.minify("tst.js", { mangle: { toplevel: true } }).code; UglifyJS.minify(code, { mangle: { toplevel: true } }).code;
// 'function n(n,a){}var a;' // 'function n(n,a){}var a;'
``` ```
##### mangle.properties options ##### mangle.properties options
- `regex` — Pass a RegExp to only mangle certain names - `regex` — Pass a RegExp to only mangle certain names
- `keep_quoted` — Only mangle unquoted property names - `keep_quoted` — Only mangle unquoted property names
- `debug` — Mangle names with the original name still present. Defaults to `false`. - `debug` — Mangle names with the original name still present. Defaults to `false`.
Pass an empty string to enable, or a non-empty string to set the suffix. Pass an empty string to enable, or a non-empty string to set the suffix.
[acorn]: https://github.com/ternjs/acorn [acorn]: https://github.com/ternjs/acorn
[sm-spec]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k [sm-spec]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k

View File

@@ -525,6 +525,14 @@ merge(Compressor.prototype, {
return lhs instanceof AST_SymbolRef && lhs.definition().orig[0] instanceof AST_SymbolLambda; return lhs instanceof AST_SymbolRef && lhs.definition().orig[0] instanceof AST_SymbolLambda;
} }
function is_reference_const(ref) {
if (!(ref instanceof AST_SymbolRef)) return false;
var orig = ref.definition().orig;
for (var i = orig.length; --i >= 0;) {
if (orig[i] instanceof AST_SymbolConst) return true;
}
}
function find_variable(compressor, name) { function find_variable(compressor, name) {
var scope, i = 0; var scope, i = 0;
while (scope = compressor.parent(i++)) { while (scope = compressor.parent(i++)) {
@@ -790,7 +798,8 @@ merge(Compressor.prototype, {
return make_node(AST_SymbolRef, expr.name, expr.name); return make_node(AST_SymbolRef, expr.name, expr.name);
} }
} else { } else {
return expr[expr instanceof AST_Assign ? "left" : "expression"]; var lhs = expr[expr instanceof AST_Assign ? "left" : "expression"];
return !is_reference_const(lhs) && lhs;
} }
} }
@@ -1973,6 +1982,7 @@ merge(Compressor.prototype, {
&& node instanceof AST_Assign && node instanceof AST_Assign
&& node.operator == "=" && node.operator == "="
&& node.left instanceof AST_SymbolRef && node.left instanceof AST_SymbolRef
&& !is_reference_const(node.left)
&& scope === self) { && scope === self) {
node.right.walk(tw); node.right.walk(tw);
return true; return true;
@@ -3178,7 +3188,7 @@ merge(Compressor.prototype, {
&& (left.operator == "++" || left.operator == "--")) { && (left.operator == "++" || left.operator == "--")) {
left = left.expression; left = left.expression;
} else left = null; } else left = null;
if (!left || is_lhs_read_only(left)) { if (!left || is_lhs_read_only(left) || is_reference_const(left)) {
expressions[++i] = cdr; expressions[++i] = cdr;
continue; continue;
} }

View File

@@ -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.3", "version": "3.0.4",
"engines": { "engines": {
"node": ">=0.8.0" "node": ">=0.8.0"
}, },

View File

@@ -2186,3 +2186,49 @@ compound_assignment: {
} }
expect_stdout: "4" expect_stdout: "4"
} }
reassign_const_1: {
options = {
collapse_vars: true,
}
input: {
function f() {
const a = 1;
a = 2;
return a;
}
console.log(f());
}
expect: {
function f() {
const a = 1;
a = 2;
return a;
}
console.log(f());
}
expect_stdout: true
}
reassign_const_2: {
options = {
collapse_vars: true,
}
input: {
function f() {
const a = 1;
++a;
return a;
}
console.log(f());
}
expect: {
function f() {
const a = 1;
++a;
return a;
}
console.log(f());
}
expect_stdout: true
}

View File

@@ -1147,3 +1147,28 @@ var_catch_toplevel: {
}(); }();
} }
} }
reassign_const: {
options = {
cascade: true,
sequences: true,
side_effects: true,
unused: true,
}
input: {
function f() {
const a = 1;
a = 2;
return a;
}
console.log(f());
}
expect: {
function f() {
const a = 1;
return a = 2, a;
}
console.log(f());
}
expect_stdout: true
}

View File

@@ -710,3 +710,27 @@ issue_27: {
})(jQuery); })(jQuery);
} }
} }
reassign_const: {
options = {
cascade: true,
sequences: true,
side_effects: true,
}
input: {
function f() {
const a = 1;
a++;
return a;
}
console.log(f());
}
expect: {
function f() {
const a = 1;
return a++, a;
}
console.log(f());
}
expect_stdout: true
}