uglify-js
Advanced tools
Comparing version
@@ -301,3 +301,4 @@ /*********************************************************************** | ||
function skip_whitespace() { | ||
while (WHITESPACE_CHARS(peek())) | ||
var ch; | ||
while (WHITESPACE_CHARS(ch = peek()) || ch == "\u2028" || ch == "\u2029") | ||
next(); | ||
@@ -304,0 +305,0 @@ }; |
@@ -70,3 +70,7 @@ /*********************************************************************** | ||
mangle: function(options) { | ||
if (!this.mangled_name && !this.unmangleable(options)) { | ||
var cache = options.cache && options.cache.props; | ||
if (this.global && cache && cache.has(this.name)) { | ||
this.mangled_name = cache.get(this.name); | ||
} | ||
else if (!this.mangled_name && !this.unmangleable(options)) { | ||
var s = this.scope; | ||
@@ -76,2 +80,5 @@ if (!options.screw_ie8 && this.orig[0] instanceof AST_SymbolLambda) | ||
this.mangled_name = s.next_mangled(options, this); | ||
if (this.global && cache) { | ||
cache.set(this.name, this.mangled_name); | ||
} | ||
} | ||
@@ -83,3 +90,4 @@ } | ||
options = defaults(options, { | ||
screw_ie8: false | ||
screw_ie8: false, | ||
cache: null | ||
}); | ||
@@ -189,2 +197,6 @@ | ||
self.walk(tw); | ||
if (options.cache) { | ||
this.cname = options.cache.cname; | ||
} | ||
}); | ||
@@ -351,2 +363,11 @@ | ||
var to_mangle = []; | ||
if (options.cache) { | ||
this.globals.each(function(symbol){ | ||
if (options.except.indexOf(symbol.name) < 0) { | ||
to_mangle.push(symbol); | ||
} | ||
}); | ||
} | ||
var tw = new TreeWalker(function(node, descend){ | ||
@@ -386,2 +407,6 @@ if (node instanceof AST_LabeledStatement) { | ||
to_mangle.forEach(function(def){ def.mangle(options) }); | ||
if (options.cache) { | ||
options.cache.cname = this.cname; | ||
} | ||
}); | ||
@@ -388,0 +413,0 @@ |
@@ -109,6 +109,8 @@ /*********************************************************************** | ||
function merge(obj, ext) { | ||
var count = 0; | ||
for (var i in ext) if (ext.hasOwnProperty(i)) { | ||
obj[i] = ext[i]; | ||
count++; | ||
} | ||
return obj; | ||
return count; | ||
}; | ||
@@ -302,3 +304,9 @@ | ||
return ret; | ||
} | ||
}, | ||
toObject: function() { return this._values } | ||
}; | ||
Dictionary.fromObject = function(obj) { | ||
var dict = new Dictionary(); | ||
dict._size = merge(dict._values, obj); | ||
return dict; | ||
}; |
@@ -6,3 +6,3 @@ { | ||
"main": "tools/node.js", | ||
"version": "2.4.17", | ||
"version": "2.4.18", | ||
"engines": { "node" : ">=0.4.0" }, | ||
@@ -21,3 +21,3 @@ "maintainers": [{ | ||
"source-map" : "0.1.34", | ||
"yargs": "~1.3.3", | ||
"yargs": "~3.5.4", | ||
"uglify-to-browserify": "~1.0.0" | ||
@@ -24,0 +24,0 @@ }, |
213
README.md
@@ -55,66 +55,83 @@ UglifyJS 2 | ||
``` | ||
--source-map Specify an output file where to generate source map. | ||
[string] | ||
--source-map-root The path to the original source to be included in the | ||
source map. [string] | ||
--source-map-url The path to the source map to be added in //# | ||
sourceMappingURL. Defaults to the value passed with | ||
--source-map. [string] | ||
--source-map-include-sources | ||
Pass this flag if you want to include the content of | ||
source files in the source map as sourcesContent | ||
property. [boolean] | ||
--in-source-map Input source map, useful if you're compressing JS that was | ||
generated from some other original code. | ||
--screw-ie8 Pass this flag if you don't care about full compliance | ||
with Internet Explorer 6-8 quirks (by default UglifyJS | ||
will try to be IE-proof). [boolean] | ||
--expr Parse a single expression, rather than a program (for | ||
parsing JSON) [boolean] | ||
-p, --prefix Skip prefix for original filenames that appear in source | ||
maps. For example -p 3 will drop 3 directories from file | ||
names and ensure they are relative paths. You can also | ||
specify -p relative, which will make UglifyJS figure out | ||
itself the relative paths between original sources, the | ||
source map and the output file. [string] | ||
-o, --output Output file (default STDOUT). | ||
-b, --beautify Beautify output/specify output options. [string] | ||
-m, --mangle Mangle names/pass mangler options. [string] | ||
-r, --reserved Reserved names to exclude from mangling. | ||
-c, --compress Enable compressor/pass compressor options. Pass options | ||
like -c hoist_vars=false,if_return=false. Use -c with no | ||
argument to use the default compression options. [string] | ||
-d, --define Global definitions [string] | ||
-e, --enclose Embed everything in a big function, with a configurable | ||
parameter/argument list. [string] | ||
--comments Preserve copyright comments in the output. By default this | ||
works like Google Closure, keeping JSDoc-style comments | ||
that contain "@license" or "@preserve". You can optionally | ||
pass one of the following arguments to this flag: | ||
- "all" to keep all comments | ||
- a valid JS regexp (needs to start with a slash) to keep | ||
only comments that match. | ||
Note that currently not *all* comments can be kept when | ||
compression is on, because of dead code removal or | ||
cascading statements into sequences. [string] | ||
--preamble Preamble to prepend to the output. You can use this to | ||
insert a comment, for example for licensing information. | ||
This will not be parsed, but the source map will adjust | ||
for its presence. | ||
--stats Display operations run time on STDERR. [boolean] | ||
--acorn Use Acorn for parsing. [boolean] | ||
--spidermonkey Assume input files are SpiderMonkey AST format (as JSON). | ||
[boolean] | ||
--self Build itself (UglifyJS2) as a library (implies | ||
--wrap=UglifyJS --export-all) [boolean] | ||
--wrap Embed everything in a big function, making the “exports” | ||
and “global” variables available. You need to pass an | ||
argument to this option to specify the name that your | ||
module will take when included in, say, a browser. | ||
[string] | ||
--export-all Only used when --wrap, this tells UglifyJS to add code to | ||
automatically export all globals. [boolean] | ||
--lint Display some scope warnings [boolean] | ||
-v, --verbose Verbose [boolean] | ||
-V, --version Print version number and exit. [boolean] | ||
--source-map Specify an output file where to generate source | ||
map. | ||
--source-map-root The path to the original source to be included | ||
in the source map. | ||
--source-map-url The path to the source map to be added in //# | ||
sourceMappingURL. Defaults to the value passed | ||
with --source-map. | ||
--source-map-include-sources Pass this flag if you want to include the | ||
content of source files in the source map as | ||
sourcesContent property. | ||
--in-source-map Input source map, useful if you're compressing | ||
JS that was generated from some other original | ||
code. | ||
--screw-ie8 Pass this flag if you don't care about full | ||
compliance with Internet Explorer 6-8 quirks | ||
(by default UglifyJS will try to be IE-proof). | ||
--expr Parse a single expression, rather than a | ||
program (for parsing JSON) | ||
-p, --prefix Skip prefix for original filenames that appear | ||
in source maps. For example -p 3 will drop 3 | ||
directories from file names and ensure they are | ||
relative paths. You can also specify -p | ||
relative, which will make UglifyJS figure out | ||
itself the relative paths between original | ||
sources, the source map and the output file. | ||
-o, --output Output file (default STDOUT). | ||
-b, --beautify Beautify output/specify output options. | ||
-m, --mangle Mangle names/pass mangler options. | ||
-r, --reserved Reserved names to exclude from mangling. | ||
-c, --compress Enable compressor/pass compressor options. Pass | ||
options like -c | ||
hoist_vars=false,if_return=false. Use -c with | ||
no argument to use the default compression | ||
options. | ||
-d, --define Global definitions | ||
-e, --enclose Embed everything in a big function, with a | ||
configurable parameter/argument list. | ||
--comments Preserve copyright comments in the output. By | ||
default this works like Google Closure, keeping | ||
JSDoc-style comments that contain "@license" or | ||
"@preserve". You can optionally pass one of the | ||
following arguments to this flag: | ||
- "all" to keep all comments | ||
- a valid JS regexp (needs to start with a | ||
slash) to keep only comments that match. | ||
Note that currently not *all* comments can be | ||
kept when compression is on, because of dead | ||
code removal or cascading statements into | ||
sequences. | ||
--preamble Preamble to prepend to the output. You can use | ||
this to insert a comment, for example for | ||
licensing information. This will not be | ||
parsed, but the source map will adjust for its | ||
presence. | ||
--stats Display operations run time on STDERR. | ||
--acorn Use Acorn for parsing. | ||
--spidermonkey Assume input files are SpiderMonkey AST format | ||
(as JSON). | ||
--self Build itself (UglifyJS2) as a library (implies | ||
--wrap=UglifyJS --export-all) | ||
--wrap Embed everything in a big function, making the | ||
“exports” and “global” variables available. You | ||
need to pass an argument to this option to | ||
specify the name that your module will take | ||
when included in, say, a browser. | ||
--export-all Only used when --wrap, this tells UglifyJS to | ||
add code to automatically export all globals. | ||
--lint Display some scope warnings | ||
-v, --verbose Verbose | ||
-V, --version Print version number and exit. | ||
--noerr Don't throw an error for unknown options in -c, | ||
-b or -m. | ||
--bare-returns Allow return outside of functions. Useful when | ||
minifying CommonJS modules. | ||
--keep-fnames Do not mangle/drop function names. Useful for | ||
code relying on Function.prototype.name. | ||
--reserved-file File containing reserved names | ||
--reserve-domprops Make (most?) DOM properties reserved for | ||
--mangle-props | ||
--mangle-props Mangle property names | ||
--name-cache File to hold mangled names mappings | ||
``` | ||
@@ -193,2 +210,65 @@ | ||
### Mangling property names (`--mangle-props`) | ||
**Note:** this will probably break your code. Mangling property names is a | ||
separate step, different from variable name mangling. Pass | ||
`--mangle-props`. It will mangle all properties that are seen in some | ||
object literal, or that are assigned to. For example: | ||
```js | ||
var x = { | ||
foo: 1 | ||
}; | ||
x.bar = 2; | ||
x["baz"] = 3; | ||
x[condition ? "moo" : "boo"] = 4; | ||
console.log(x.something()); | ||
``` | ||
In the above code, `foo`, `bar`, `baz`, `moo` and `boo` will be replaced | ||
with single characters, while `something()` will be left as is. | ||
In order for this to be of any use, we should avoid mangling standard JS | ||
names. For instance, if your code would contain `x.length = 10`, then | ||
`length` becomes a candidate for mangling and it will be mangled throughout | ||
the code, regardless if it's being used as part of your own objects or | ||
accessing an array's length. To avoid that, you can use `--reserved-file` | ||
to pass a filename that should contain the names to be excluded from | ||
mangling. This file can be used both for excluding variable names and | ||
property names. It could look like this, for example: | ||
```js | ||
{ | ||
"vars": [ "define", "require", ... ], | ||
"props": [ "length", "prototype", ... ] | ||
} | ||
``` | ||
`--reserved-file` can be an array of file names (either a single | ||
comma-separated argument, or you can pass multiple `--reserved-file` | ||
arguments) — in this case it will exclude names from all those files. | ||
A default exclusion file is provided in `tools/domprops.json` which should | ||
cover most standard JS and DOM properties defined in various browsers. Pass | ||
`--reserve-domprops` to read that in. | ||
When you compress multiple files using this option, in order for them to | ||
work together in the end we need to ensure somehow that one property gets | ||
mangled to the same name in all of them. For this, pass `--name-cache | ||
filename.json` and UglifyJS will maintain these mappings in a file which can | ||
then be reused. It should be initially empty. Example: | ||
``` | ||
rm -f /tmp/cache.json # start fresh | ||
uglifyjs file1.js file2.js --mangle-props --name-cache /tmp/cache.json -o part1.js | ||
uglifyjs file3.js file4.js --mangle-props --name-cache /tmp/cache.json -o part2.js | ||
``` | ||
Now, `part1.js` and `part2.js` will be consistent with each other in terms | ||
of mangled property names. | ||
Using the name cache is not necessary if you compress all your files in a | ||
single call to UglifyJS. | ||
## Compressor options | ||
@@ -277,3 +357,3 @@ | ||
- `new Array(1, 2, 3)` or `Array(1, 2, 3)` → `[1, 2, 3 ]` | ||
- `new Array(1, 2, 3)` or `Array(1, 2, 3)` → `[ 1, 2, 3 ]` | ||
- `new Object()` → `{}` | ||
@@ -285,3 +365,4 @@ - `String(exp)` or `exp.toString()` → `"" + exp` | ||
scope; we do it because the variable name will be mangled, typically | ||
reduced to a single character). | ||
reduced to a single character) | ||
- discards unused function arguments (affects `function.length`) | ||
@@ -288,0 +369,0 @@ ### Conditional compilation |
@@ -36,3 +36,4 @@ var path = require("path"); | ||
"../lib/sourcemap.js", | ||
"../lib/mozilla-ast.js" | ||
"../lib/mozilla-ast.js", | ||
"../lib/propmangle.js" | ||
].map(function(file){ | ||
@@ -196,1 +197,61 @@ return fs.realpathSync(path.join(path.dirname(__filename), file)); | ||
}; | ||
function readReservedFile(filename, reserved) { | ||
if (!reserved) { | ||
reserved = { vars: [], props: [] }; | ||
} | ||
var data = fs.readFileSync(filename, "utf8"); | ||
data = JSON.parse(data); | ||
if (data.vars) { | ||
data.vars.forEach(function(name){ | ||
UglifyJS.push_uniq(reserved.vars, name); | ||
}); | ||
} | ||
if (data.props) { | ||
data.props.forEach(function(name){ | ||
UglifyJS.push_uniq(reserved.props, name); | ||
}); | ||
} | ||
return reserved; | ||
} | ||
exports.readReservedFile = readReservedFile; | ||
exports.readDefaultReservedFile = function(reserved) { | ||
return readReservedFile(path.join(__dirname, "domprops.json"), reserved); | ||
}; | ||
exports.readNameCache = function(filename, key) { | ||
var cache = null; | ||
if (filename) { | ||
try { | ||
var cache = fs.readFileSync(filename, "utf8"); | ||
cache = JSON.parse(cache)[key]; | ||
if (!cache) throw "init"; | ||
cache.props = UglifyJS.Dictionary.fromObject(cache.props); | ||
} catch(ex) { | ||
cache = { | ||
cname: -1, | ||
props: new UglifyJS.Dictionary() | ||
}; | ||
} | ||
} | ||
return cache; | ||
}; | ||
exports.writeNameCache = function(filename, key, cache) { | ||
if (filename) { | ||
var data; | ||
try { | ||
data = fs.readFileSync(filename, "utf8"); | ||
data = JSON.parse(data); | ||
} catch(ex) { | ||
data = {}; | ||
} | ||
data[key] = { | ||
cname: cache.cname, | ||
props: cache.props.toObject() | ||
}; | ||
fs.writeFileSync(filename, JSON.stringify(data, null, 2), "utf8"); | ||
} | ||
}; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
514913
45.54%24
26.32%13596
77.84%770
11.76%7
40%+ Added
+ Added
+ Added
+ Added
+ Added
- Removed
Updated