Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c7d3c07f5a |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,3 +1,2 @@
|
|||||||
/node_modules/
|
|
||||||
/npm-debug.log
|
|
||||||
tmp/
|
tmp/
|
||||||
|
node_modules/
|
||||||
|
|||||||
@@ -1,10 +1,6 @@
|
|||||||
language: node_js
|
language: node_js
|
||||||
before_install: "npm install -g npm"
|
before_install: "npm install -g npm"
|
||||||
node_js:
|
node_js:
|
||||||
- "iojs"
|
- "0.8"
|
||||||
- "0.12"
|
|
||||||
- "0.11"
|
|
||||||
- "0.10"
|
- "0.10"
|
||||||
matrix:
|
- "0.11"
|
||||||
fast_finish: true
|
|
||||||
sudo: false
|
|
||||||
|
|||||||
228
README.md
228
README.md
@@ -52,88 +52,70 @@ a double dash to prevent input files being used as option arguments:
|
|||||||
The available options are:
|
The available options are:
|
||||||
|
|
||||||
```
|
```
|
||||||
--source-map Specify an output file where to generate source
|
--source-map Specify an output file where to generate source map.
|
||||||
map.
|
[string]
|
||||||
--source-map-root The path to the original source to be included
|
--source-map-root The path to the original source to be included in the
|
||||||
in the source map.
|
source map. [string]
|
||||||
--source-map-url The path to the source map to be added in //#
|
--source-map-url The path to the source map to be added in //#
|
||||||
sourceMappingURL. Defaults to the value passed
|
sourceMappingURL. Defaults to the value passed with
|
||||||
with --source-map.
|
--source-map. [string]
|
||||||
--source-map-include-sources Pass this flag if you want to include the
|
--source-map-include-sources
|
||||||
content of source files in the source map as
|
Pass this flag if you want to include the content of
|
||||||
sourcesContent property.
|
source files in the source map as sourcesContent
|
||||||
--in-source-map Input source map, useful if you're compressing
|
property. [boolean]
|
||||||
JS that was generated from some other original
|
--in-source-map Input source map, useful if you're compressing JS that was
|
||||||
code.
|
generated from some other original code.
|
||||||
--screw-ie8 Pass this flag if you don't care about full
|
--screw-ie8 Pass this flag if you don't care about full compliance
|
||||||
compliance with Internet Explorer 6-8 quirks
|
with Internet Explorer 6-8 quirks (by default UglifyJS
|
||||||
(by default UglifyJS will try to be IE-proof).
|
will try to be IE-proof). [boolean]
|
||||||
--expr Parse a single expression, rather than a
|
--expr Parse a single expression, rather than a program (for
|
||||||
program (for parsing JSON)
|
parsing JSON) [boolean]
|
||||||
-p, --prefix Skip prefix for original filenames that appear
|
-p, --prefix Skip prefix for original filenames that appear in source
|
||||||
in source maps. For example -p 3 will drop 3
|
maps. For example -p 3 will drop 3 directories from file
|
||||||
directories from file names and ensure they are
|
names and ensure they are relative paths. You can also
|
||||||
relative paths. You can also specify -p
|
specify -p relative, which will make UglifyJS figure out
|
||||||
relative, which will make UglifyJS figure out
|
itself the relative paths between original sources, the
|
||||||
itself the relative paths between original
|
source map and the output file. [string]
|
||||||
sources, the source map and the output file.
|
-o, --output Output file (default STDOUT).
|
||||||
-o, --output Output file (default STDOUT).
|
-b, --beautify Beautify output/specify output options. [string]
|
||||||
-b, --beautify Beautify output/specify output options.
|
-m, --mangle Mangle names/pass mangler options. [string]
|
||||||
-m, --mangle Mangle names/pass mangler options.
|
-r, --reserved Reserved names to exclude from mangling.
|
||||||
-r, --reserved Reserved names to exclude from mangling.
|
-c, --compress Enable compressor/pass compressor options. Pass options
|
||||||
-c, --compress Enable compressor/pass compressor options. Pass
|
like -c hoist_vars=false,if_return=false. Use -c with no
|
||||||
options like -c
|
argument to use the default compression options. [string]
|
||||||
hoist_vars=false,if_return=false. Use -c with
|
-d, --define Global definitions [string]
|
||||||
no argument to use the default compression
|
-e, --enclose Embed everything in a big function, with a configurable
|
||||||
options.
|
parameter/argument list. [string]
|
||||||
-d, --define Global definitions
|
--comments Preserve copyright comments in the output. By default this
|
||||||
-e, --enclose Embed everything in a big function, with a
|
works like Google Closure, keeping JSDoc-style comments
|
||||||
configurable parameter/argument list.
|
that contain "@license" or "@preserve". You can optionally
|
||||||
--comments Preserve copyright comments in the output. By
|
pass one of the following arguments to this flag:
|
||||||
default this works like Google Closure, keeping
|
- "all" to keep all comments
|
||||||
JSDoc-style comments that contain "@license" or
|
- a valid JS regexp (needs to start with a slash) to keep
|
||||||
"@preserve". You can optionally pass one of the
|
only comments that match.
|
||||||
following arguments to this flag:
|
Note that currently not *all* comments can be kept when
|
||||||
- "all" to keep all comments
|
compression is on, because of dead code removal or
|
||||||
- a valid JS regexp (needs to start with a
|
cascading statements into sequences. [string]
|
||||||
slash) to keep only comments that match.
|
--preamble Preamble to prepend to the output. You can use this to
|
||||||
Note that currently not *all* comments can be
|
insert a comment, for example for licensing information.
|
||||||
kept when compression is on, because of dead
|
This will not be parsed, but the source map will adjust
|
||||||
code removal or cascading statements into
|
for its presence.
|
||||||
sequences.
|
--stats Display operations run time on STDERR. [boolean]
|
||||||
--preamble Preamble to prepend to the output. You can use
|
--acorn Use Acorn for parsing. [boolean]
|
||||||
this to insert a comment, for example for
|
--spidermonkey Assume input files are SpiderMonkey AST format (as JSON).
|
||||||
licensing information. This will not be
|
[boolean]
|
||||||
parsed, but the source map will adjust for its
|
--self Build itself (UglifyJS2) as a library (implies
|
||||||
presence.
|
--wrap=UglifyJS --export-all) [boolean]
|
||||||
--stats Display operations run time on STDERR.
|
--wrap Embed everything in a big function, making the “exports”
|
||||||
--acorn Use Acorn for parsing.
|
and “global” variables available. You need to pass an
|
||||||
--spidermonkey Assume input files are SpiderMonkey AST format
|
argument to this option to specify the name that your
|
||||||
(as JSON).
|
module will take when included in, say, a browser.
|
||||||
--self Build itself (UglifyJS2) as a library (implies
|
[string]
|
||||||
--wrap=UglifyJS --export-all)
|
--export-all Only used when --wrap, this tells UglifyJS to add code to
|
||||||
--wrap Embed everything in a big function, making the
|
automatically export all globals. [boolean]
|
||||||
“exports” and “global” variables available. You
|
--lint Display some scope warnings [boolean]
|
||||||
need to pass an argument to this option to
|
-v, --verbose Verbose [boolean]
|
||||||
specify the name that your module will take
|
-V, --version Print version number and exit. [boolean]
|
||||||
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
|
|
||||||
--mangle-regex Only mangle property names matching the regex
|
|
||||||
--name-cache File to hold mangled names mappings
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Specify `--output` (`-o`) to declare the output file. Otherwise the output
|
Specify `--output` (`-o`) to declare the output file. Otherwise the output
|
||||||
@@ -207,73 +189,6 @@ comma-separated list of names. For example:
|
|||||||
|
|
||||||
to prevent the `require`, `exports` and `$` names from being changed.
|
to prevent the `require`, `exports` and `$` names from being changed.
|
||||||
|
|
||||||
### 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.
|
|
||||||
|
|
||||||
You can also use a regular expression to define which property names should be
|
|
||||||
mangled. For example, `--mangle-regex="/^_/"` will only mangle property names
|
|
||||||
that start with an underscore.
|
|
||||||
|
|
||||||
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
|
## Compressor options
|
||||||
|
|
||||||
You need to pass `--compress` (`-c`) to enable the compressor. Optionally
|
You need to pass `--compress` (`-c`) to enable the compressor. Optionally
|
||||||
@@ -357,15 +272,14 @@ contrived cases, but should be fine for most code. You might want to try it
|
|||||||
on your own code, it should reduce the minified size. Here's what happens
|
on your own code, it should reduce the minified size. Here's what happens
|
||||||
when this flag is on:
|
when this flag is on:
|
||||||
|
|
||||||
- `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()` → `{}`
|
- `new Object()` → `{}`
|
||||||
- `String(exp)` or `exp.toString()` → `"" + exp`
|
- `String(exp)` or `exp.toString()` → `"" + exp`
|
||||||
- `new Object/RegExp/Function/Error/Array (...)` → we discard the `new`
|
- `new Object/RegExp/Function/Error/Array (...)` → we discard the `new`
|
||||||
- `typeof foo == "undefined"` → `foo === void 0`
|
- `typeof foo == "undefined"` → `foo === void 0`
|
||||||
- `void 0` → `undefined` (if there is a variable named "undefined" in
|
- `void 0` → `undefined` (if there is a variable named "undefined" in
|
||||||
scope; we do it because the variable name will be mangled, typically
|
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`)
|
|
||||||
|
|
||||||
### Conditional compilation
|
### Conditional compilation
|
||||||
|
|
||||||
@@ -596,16 +510,6 @@ var result = UglifyJS.minify("compiled.js", {
|
|||||||
// same as before, it returns `code` and `map`
|
// same as before, it returns `code` and `map`
|
||||||
```
|
```
|
||||||
|
|
||||||
If your input source map is not in a file, you can pass it in as an object
|
|
||||||
using the `inSourceMap` argument:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
var result = UglifyJS.minify("compiled.js", {
|
|
||||||
inSourceMap: JSON.parse(my_source_map_string),
|
|
||||||
outSourceMap: "minified.js.map"
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
The `inSourceMap` is only used if you also request `outSourceMap` (it makes
|
The `inSourceMap` is only used if you also request `outSourceMap` (it makes
|
||||||
no sense otherwise).
|
no sense otherwise).
|
||||||
|
|
||||||
|
|||||||
@@ -1,77 +0,0 @@
|
|||||||
#! /usr/bin/env node
|
|
||||||
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
var U2 = require("../tools/node");
|
|
||||||
var fs = require("fs");
|
|
||||||
var yargs = require("yargs");
|
|
||||||
var ARGS = yargs
|
|
||||||
.describe("o", "Output file")
|
|
||||||
.argv;
|
|
||||||
var files = ARGS._.slice();
|
|
||||||
var output = {
|
|
||||||
vars: {},
|
|
||||||
props: {}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (ARGS.o) try {
|
|
||||||
output = JSON.parse(fs.readFileSync(ARGS.o, "utf8"));
|
|
||||||
} catch(ex) {}
|
|
||||||
|
|
||||||
files.forEach(getProps);
|
|
||||||
|
|
||||||
if (ARGS.o) {
|
|
||||||
fs.writeFileSync(ARGS.o, JSON.stringify(output, null, 2), "utf8");
|
|
||||||
} else {
|
|
||||||
console.log("%s", JSON.stringify(output, null, 2));
|
|
||||||
}
|
|
||||||
|
|
||||||
function getProps(filename) {
|
|
||||||
var code = fs.readFileSync(filename, "utf8");
|
|
||||||
var ast = U2.parse(code);
|
|
||||||
|
|
||||||
ast.walk(new U2.TreeWalker(function(node){
|
|
||||||
if (node instanceof U2.AST_ObjectKeyVal) {
|
|
||||||
add(node.key);
|
|
||||||
}
|
|
||||||
else if (node instanceof U2.AST_ObjectProperty) {
|
|
||||||
add(node.key.name);
|
|
||||||
}
|
|
||||||
else if (node instanceof U2.AST_Dot) {
|
|
||||||
add(node.property);
|
|
||||||
}
|
|
||||||
else if (node instanceof U2.AST_Sub) {
|
|
||||||
addStrings(node.property);
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
|
|
||||||
function addStrings(node) {
|
|
||||||
var out = {};
|
|
||||||
try {
|
|
||||||
(function walk(node){
|
|
||||||
node.walk(new U2.TreeWalker(function(node){
|
|
||||||
if (node instanceof U2.AST_Seq) {
|
|
||||||
walk(node.cdr);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (node instanceof U2.AST_String) {
|
|
||||||
add(node.value);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (node instanceof U2.AST_Conditional) {
|
|
||||||
walk(node.consequent);
|
|
||||||
walk(node.alternative);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
throw out;
|
|
||||||
}));
|
|
||||||
})(node);
|
|
||||||
} catch(ex) {
|
|
||||||
if (ex !== out) throw ex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function add(name) {
|
|
||||||
output.props[name] = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
144
bin/uglifyjs
144
bin/uglifyjs
@@ -67,11 +67,6 @@ You need to pass an argument to this option to specify the name that your module
|
|||||||
.describe("bare-returns", "Allow return outside of functions. Useful when minifying CommonJS modules.")
|
.describe("bare-returns", "Allow return outside of functions. Useful when minifying CommonJS modules.")
|
||||||
.describe("keep-fnames", "Do not mangle/drop function names. Useful for code relying on Function.prototype.name.")
|
.describe("keep-fnames", "Do not mangle/drop function names. Useful for code relying on Function.prototype.name.")
|
||||||
.describe("quotes", "Quote style (0 - auto, 1 - single, 2 - double, 3 - original)")
|
.describe("quotes", "Quote style (0 - auto, 1 - single, 2 - double, 3 - original)")
|
||||||
.describe("reserved-file", "File containing reserved names")
|
|
||||||
.describe("reserve-domprops", "Make (most?) DOM properties reserved for --mangle-props")
|
|
||||||
.describe("mangle-props", "Mangle property names")
|
|
||||||
.describe("mangle-regex", "Only mangle property names matching the regex")
|
|
||||||
.describe("name-cache", "File to hold mangled names mappings")
|
|
||||||
|
|
||||||
.alias("p", "prefix")
|
.alias("p", "prefix")
|
||||||
.alias("o", "output")
|
.alias("o", "output")
|
||||||
@@ -89,21 +84,13 @@ You need to pass an argument to this option to specify the name that your module
|
|||||||
.string("source-map-root")
|
.string("source-map-root")
|
||||||
.string("source-map-url")
|
.string("source-map-url")
|
||||||
.string("b")
|
.string("b")
|
||||||
.string("beautify")
|
|
||||||
.string("m")
|
.string("m")
|
||||||
.string("mangle")
|
|
||||||
.string("c")
|
.string("c")
|
||||||
.string("compress")
|
|
||||||
.string("d")
|
.string("d")
|
||||||
.string("define")
|
|
||||||
.string("e")
|
.string("e")
|
||||||
.string("enclose")
|
|
||||||
.string("comments")
|
.string("comments")
|
||||||
.string("wrap")
|
.string("wrap")
|
||||||
.string("p")
|
.string("p")
|
||||||
.string("prefix")
|
|
||||||
.string("name-cache")
|
|
||||||
.array("reserved-file")
|
|
||||||
|
|
||||||
.boolean("expr")
|
.boolean("expr")
|
||||||
.boolean("source-map-include-sources")
|
.boolean("source-map-include-sources")
|
||||||
@@ -111,18 +98,14 @@ You need to pass an argument to this option to specify the name that your module
|
|||||||
.boolean("export-all")
|
.boolean("export-all")
|
||||||
.boolean("self")
|
.boolean("self")
|
||||||
.boolean("v")
|
.boolean("v")
|
||||||
.boolean("verbose")
|
|
||||||
.boolean("stats")
|
.boolean("stats")
|
||||||
.boolean("acorn")
|
.boolean("acorn")
|
||||||
.boolean("spidermonkey")
|
.boolean("spidermonkey")
|
||||||
.boolean("lint")
|
.boolean("lint")
|
||||||
.boolean("V")
|
.boolean("V")
|
||||||
.boolean("version")
|
|
||||||
.boolean("noerr")
|
.boolean("noerr")
|
||||||
.boolean("bare-returns")
|
.boolean("bare-returns")
|
||||||
.boolean("keep-fnames")
|
.boolean("keep-fnames")
|
||||||
.boolean("mangle-props")
|
|
||||||
.boolean("reserve-domprops")
|
|
||||||
|
|
||||||
.wrap(80)
|
.wrap(80)
|
||||||
|
|
||||||
@@ -133,24 +116,24 @@ normalize(ARGS);
|
|||||||
|
|
||||||
if (ARGS.noerr) {
|
if (ARGS.noerr) {
|
||||||
UglifyJS.DefaultsError.croak = function(msg, defs) {
|
UglifyJS.DefaultsError.croak = function(msg, defs) {
|
||||||
print_error("WARN: " + msg);
|
sys.error("WARN: " + msg);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ARGS.version || ARGS.V) {
|
if (ARGS.version || ARGS.V) {
|
||||||
var json = require("../package.json");
|
var json = require("../package.json");
|
||||||
print(json.name + ' ' + json.version);
|
sys.puts(json.name + ' ' + json.version);
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ARGS.ast_help) {
|
if (ARGS.ast_help) {
|
||||||
var desc = UglifyJS.describe_ast();
|
var desc = UglifyJS.describe_ast();
|
||||||
print(typeof desc == "string" ? desc : JSON.stringify(desc, null, 2));
|
sys.puts(typeof desc == "string" ? desc : JSON.stringify(desc, null, 2));
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ARGS.h || ARGS.help) {
|
if (ARGS.h || ARGS.help) {
|
||||||
print(yargs.help());
|
sys.puts(yargs.help());
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,15 +144,6 @@ if (ARGS.acorn) {
|
|||||||
var COMPRESS = getOptions("c", true);
|
var COMPRESS = getOptions("c", true);
|
||||||
var MANGLE = getOptions("m", true);
|
var MANGLE = getOptions("m", true);
|
||||||
var BEAUTIFY = getOptions("b", true);
|
var BEAUTIFY = getOptions("b", true);
|
||||||
var RESERVED = null;
|
|
||||||
|
|
||||||
if (ARGS.reserved_file) ARGS.reserved_file.forEach(function(filename){
|
|
||||||
RESERVED = UglifyJS.readReservedFile(filename, RESERVED);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (ARGS.reserve_domprops) {
|
|
||||||
RESERVED = UglifyJS.readDefaultReservedFile(RESERVED);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ARGS.d) {
|
if (ARGS.d) {
|
||||||
if (COMPRESS) COMPRESS.global_defs = getOptions("d");
|
if (COMPRESS) COMPRESS.global_defs = getOptions("d");
|
||||||
@@ -179,28 +153,6 @@ if (ARGS.r) {
|
|||||||
if (MANGLE) MANGLE.except = ARGS.r.replace(/^\s+|\s+$/g).split(/\s*,+\s*/);
|
if (MANGLE) MANGLE.except = ARGS.r.replace(/^\s+|\s+$/g).split(/\s*,+\s*/);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (RESERVED && MANGLE) {
|
|
||||||
if (!MANGLE.except) MANGLE.except = RESERVED.vars;
|
|
||||||
else MANGLE.except = MANGLE.except.concat(RESERVED.vars);
|
|
||||||
}
|
|
||||||
|
|
||||||
function readNameCache(key) {
|
|
||||||
return UglifyJS.readNameCache(ARGS.name_cache, key);
|
|
||||||
}
|
|
||||||
|
|
||||||
function writeNameCache(key, cache) {
|
|
||||||
return UglifyJS.writeNameCache(ARGS.name_cache, key, cache);
|
|
||||||
}
|
|
||||||
|
|
||||||
function extractRegex(str) {
|
|
||||||
if (/^\/.*\/[a-zA-Z]*$/.test(str)) {
|
|
||||||
var regex_pos = str.lastIndexOf("/");
|
|
||||||
return new RegExp(str.substr(1, regex_pos - 1), str.substr(regex_pos + 1));
|
|
||||||
} else {
|
|
||||||
throw new Error("Invalid regular expression: " + str);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ARGS.quotes === true) {
|
if (ARGS.quotes === true) {
|
||||||
ARGS.quotes = 3;
|
ARGS.quotes = 3;
|
||||||
}
|
}
|
||||||
@@ -225,12 +177,13 @@ if (ARGS.keep_fnames) {
|
|||||||
if (BEAUTIFY)
|
if (BEAUTIFY)
|
||||||
UglifyJS.merge(OUTPUT_OPTIONS, BEAUTIFY);
|
UglifyJS.merge(OUTPUT_OPTIONS, BEAUTIFY);
|
||||||
|
|
||||||
if (ARGS.comments != null) {
|
if (ARGS.comments) {
|
||||||
if (/^\/.*\/[a-zA-Z]*$/.test(ARGS.comments)) {
|
if (/^\/.*\/[a-zA-Z]*$/.test(ARGS.comments)) {
|
||||||
|
var regex_pos = ARGS.comments.lastIndexOf("/");
|
||||||
try {
|
try {
|
||||||
OUTPUT_OPTIONS.comments = extractRegex(ARGS.comments);
|
OUTPUT_OPTIONS.comments = new RegExp(ARGS.comments.substr(1, regex_pos - 1), ARGS.comments.substr(regex_pos + 1));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print_error("ERROR: Invalid --comments: " + e.message);
|
sys.error("ERROR: Invalid --comments: " + e.message);
|
||||||
}
|
}
|
||||||
} else if (ARGS.comments == "all") {
|
} else if (ARGS.comments == "all") {
|
||||||
OUTPUT_OPTIONS.comments = true;
|
OUTPUT_OPTIONS.comments = true;
|
||||||
@@ -250,7 +203,7 @@ var files = ARGS._.slice();
|
|||||||
|
|
||||||
if (ARGS.self) {
|
if (ARGS.self) {
|
||||||
if (files.length > 0) {
|
if (files.length > 0) {
|
||||||
print_error("WARN: Ignoring input files since --self was passed");
|
sys.error("WARN: Ignoring input files since --self was passed");
|
||||||
}
|
}
|
||||||
files = UglifyJS.FILES;
|
files = UglifyJS.FILES;
|
||||||
if (!ARGS.wrap) ARGS.wrap = "UglifyJS";
|
if (!ARGS.wrap) ARGS.wrap = "UglifyJS";
|
||||||
@@ -262,7 +215,7 @@ var ORIG_MAP = ARGS.in_source_map;
|
|||||||
if (ORIG_MAP) {
|
if (ORIG_MAP) {
|
||||||
ORIG_MAP = JSON.parse(fs.readFileSync(ORIG_MAP));
|
ORIG_MAP = JSON.parse(fs.readFileSync(ORIG_MAP));
|
||||||
if (files.length == 0) {
|
if (files.length == 0) {
|
||||||
print_error("INFO: Using file from the input source map: " + ORIG_MAP.file);
|
sys.error("INFO: Using file from the input source map: " + ORIG_MAP.file);
|
||||||
files = [ ORIG_MAP.file ];
|
files = [ ORIG_MAP.file ];
|
||||||
}
|
}
|
||||||
if (ARGS.source_map_root == null) {
|
if (ARGS.source_map_root == null) {
|
||||||
@@ -275,12 +228,12 @@ if (files.length == 0) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (files.indexOf("-") >= 0 && ARGS.source_map) {
|
if (files.indexOf("-") >= 0 && ARGS.source_map) {
|
||||||
print_error("ERROR: Source map doesn't work with input from STDIN");
|
sys.error("ERROR: Source map doesn't work with input from STDIN");
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (files.filter(function(el){ return el == "-" }).length > 1) {
|
if (files.filter(function(el){ return el == "-" }).length > 1) {
|
||||||
print_error("ERROR: Can read a single file from STDIN (two or more dashes specified)");
|
sys.error("ERROR: Can read a single file from STDIN (two or more dashes specified)");
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -303,9 +256,9 @@ try {
|
|||||||
var compressor = COMPRESS && UglifyJS.Compressor(COMPRESS);
|
var compressor = COMPRESS && UglifyJS.Compressor(COMPRESS);
|
||||||
} catch(ex) {
|
} catch(ex) {
|
||||||
if (ex instanceof UglifyJS.DefaultsError) {
|
if (ex instanceof UglifyJS.DefaultsError) {
|
||||||
print_error(ex.msg);
|
sys.error(ex.msg);
|
||||||
print_error("Supported options:");
|
sys.error("Supported options:");
|
||||||
print_error(sys.inspect(ex.defs));
|
sys.error(sys.inspect(ex.defs));
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -313,7 +266,7 @@ try {
|
|||||||
async.eachLimit(files, 1, function (file, cb) {
|
async.eachLimit(files, 1, function (file, cb) {
|
||||||
read_whole_file(file, function (err, code) {
|
read_whole_file(file, function (err, code) {
|
||||||
if (err) {
|
if (err) {
|
||||||
print_error("ERROR: can't read file: " + file);
|
sys.error("ERROR: can't read file: " + file);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
if (ARGS.p != null) {
|
if (ARGS.p != null) {
|
||||||
@@ -350,9 +303,9 @@ async.eachLimit(files, 1, function (file, cb) {
|
|||||||
});
|
});
|
||||||
} catch(ex) {
|
} catch(ex) {
|
||||||
if (ex instanceof UglifyJS.JS_Parse_Error) {
|
if (ex instanceof UglifyJS.JS_Parse_Error) {
|
||||||
print_error("Parse error at " + file + ":" + ex.line + "," + ex.col);
|
sys.error("Parse error at " + file + ":" + ex.line + "," + ex.col);
|
||||||
print_error(ex.message);
|
sys.error(ex.message);
|
||||||
print_error(ex.stack);
|
sys.error(ex.stack);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
throw ex;
|
throw ex;
|
||||||
@@ -366,11 +319,11 @@ async.eachLimit(files, 1, function (file, cb) {
|
|||||||
TOPLEVEL = UglifyJS.AST_Node.from_mozilla_ast(TOPLEVEL);
|
TOPLEVEL = UglifyJS.AST_Node.from_mozilla_ast(TOPLEVEL);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (ARGS.wrap != null) {
|
if (ARGS.wrap) {
|
||||||
TOPLEVEL = TOPLEVEL.wrap_commonjs(ARGS.wrap, ARGS.export_all);
|
TOPLEVEL = TOPLEVEL.wrap_commonjs(ARGS.wrap, ARGS.export_all);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ARGS.enclose != null) {
|
if (ARGS.enclose) {
|
||||||
var arg_parameter_list = ARGS.enclose;
|
var arg_parameter_list = ARGS.enclose;
|
||||||
if (arg_parameter_list === true) {
|
if (arg_parameter_list === true) {
|
||||||
arg_parameter_list = [];
|
arg_parameter_list = [];
|
||||||
@@ -381,33 +334,11 @@ async.eachLimit(files, 1, function (file, cb) {
|
|||||||
TOPLEVEL = TOPLEVEL.wrap_enclose(arg_parameter_list);
|
TOPLEVEL = TOPLEVEL.wrap_enclose(arg_parameter_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ARGS.mangle_props || ARGS.name_cache) (function(){
|
|
||||||
var reserved = RESERVED ? RESERVED.props : null;
|
|
||||||
var cache = readNameCache("props");
|
|
||||||
var regex;
|
|
||||||
|
|
||||||
try {
|
|
||||||
regex = ARGS.mangle_regex ? extractRegex(ARGS.mangle_regex) : null;
|
|
||||||
} catch (e) {
|
|
||||||
print_error("ERROR: Invalid --mangle-regex: " + e.message);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
TOPLEVEL = UglifyJS.mangle_properties(TOPLEVEL, {
|
|
||||||
reserved : reserved,
|
|
||||||
cache : cache,
|
|
||||||
only_cache : !ARGS.mangle_props,
|
|
||||||
regex : regex
|
|
||||||
});
|
|
||||||
writeNameCache("props", cache);
|
|
||||||
})();
|
|
||||||
|
|
||||||
var SCOPE_IS_NEEDED = COMPRESS || MANGLE || ARGS.lint;
|
var SCOPE_IS_NEEDED = COMPRESS || MANGLE || ARGS.lint;
|
||||||
var TL_CACHE = readNameCache("vars");
|
|
||||||
|
|
||||||
if (SCOPE_IS_NEEDED) {
|
if (SCOPE_IS_NEEDED) {
|
||||||
time_it("scope", function(){
|
time_it("scope", function(){
|
||||||
TOPLEVEL.figure_out_scope({ screw_ie8: ARGS.screw_ie8, cache: TL_CACHE });
|
TOPLEVEL.figure_out_scope({ screw_ie8: ARGS.screw_ie8 });
|
||||||
if (ARGS.lint) {
|
if (ARGS.lint) {
|
||||||
TOPLEVEL.scope_warnings();
|
TOPLEVEL.scope_warnings();
|
||||||
}
|
}
|
||||||
@@ -422,20 +353,17 @@ async.eachLimit(files, 1, function (file, cb) {
|
|||||||
|
|
||||||
if (SCOPE_IS_NEEDED) {
|
if (SCOPE_IS_NEEDED) {
|
||||||
time_it("scope", function(){
|
time_it("scope", function(){
|
||||||
TOPLEVEL.figure_out_scope({ screw_ie8: ARGS.screw_ie8, cache: TL_CACHE });
|
TOPLEVEL.figure_out_scope({ screw_ie8: ARGS.screw_ie8 });
|
||||||
if (MANGLE && !TL_CACHE) {
|
if (MANGLE) {
|
||||||
TOPLEVEL.compute_char_frequency(MANGLE);
|
TOPLEVEL.compute_char_frequency(MANGLE);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MANGLE) time_it("mangle", function(){
|
if (MANGLE) time_it("mangle", function(){
|
||||||
MANGLE.cache = TL_CACHE;
|
|
||||||
TOPLEVEL.mangle_names(MANGLE);
|
TOPLEVEL.mangle_names(MANGLE);
|
||||||
});
|
});
|
||||||
|
|
||||||
writeNameCache("vars", TL_CACHE);
|
|
||||||
|
|
||||||
if (ARGS.source_map_include_sources) {
|
if (ARGS.source_map_include_sources) {
|
||||||
for (var file in SOURCES_CONTENT) {
|
for (var file in SOURCES_CONTENT) {
|
||||||
if (SOURCES_CONTENT.hasOwnProperty(file)) {
|
if (SOURCES_CONTENT.hasOwnProperty(file)) {
|
||||||
@@ -463,15 +391,15 @@ async.eachLimit(files, 1, function (file, cb) {
|
|||||||
if (OUTPUT_FILE) {
|
if (OUTPUT_FILE) {
|
||||||
fs.writeFileSync(OUTPUT_FILE, output, "utf8");
|
fs.writeFileSync(OUTPUT_FILE, output, "utf8");
|
||||||
} else {
|
} else {
|
||||||
print(output);
|
sys.print(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ARGS.stats) {
|
if (ARGS.stats) {
|
||||||
print_error(UglifyJS.string_template("Timing information (compressed {count} files):", {
|
sys.error(UglifyJS.string_template("Timing information (compressed {count} files):", {
|
||||||
count: files.length
|
count: files.length
|
||||||
}));
|
}));
|
||||||
for (var i in STATS) if (STATS.hasOwnProperty(i)) {
|
for (var i in STATS) if (STATS.hasOwnProperty(i)) {
|
||||||
print_error(UglifyJS.string_template("- {name}: {time}s", {
|
sys.error(UglifyJS.string_template("- {name}: {time}s", {
|
||||||
name: i,
|
name: i,
|
||||||
time: (STATS[i] / 1000).toFixed(3)
|
time: (STATS[i] / 1000).toFixed(3)
|
||||||
}));
|
}));
|
||||||
@@ -490,15 +418,15 @@ function normalize(o) {
|
|||||||
|
|
||||||
function getOptions(x, constants) {
|
function getOptions(x, constants) {
|
||||||
x = ARGS[x];
|
x = ARGS[x];
|
||||||
if (x == null) return null;
|
if (!x) return null;
|
||||||
var ret = {};
|
var ret = {};
|
||||||
if (x !== "") {
|
if (x !== true) {
|
||||||
var ast;
|
var ast;
|
||||||
try {
|
try {
|
||||||
ast = UglifyJS.parse(x, { expression: true });
|
ast = UglifyJS.parse(x, { expression: true });
|
||||||
} catch(ex) {
|
} catch(ex) {
|
||||||
if (ex instanceof UglifyJS.JS_Parse_Error) {
|
if (ex instanceof UglifyJS.JS_Parse_Error) {
|
||||||
print_error("Error parsing arguments in: " + x);
|
sys.error("Error parsing arguments in: " + x);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -517,8 +445,8 @@ function getOptions(x, constants) {
|
|||||||
ret[name] = true;
|
ret[name] = true;
|
||||||
return true; // no descend
|
return true; // no descend
|
||||||
}
|
}
|
||||||
print_error(node.TYPE)
|
sys.error(node.TYPE)
|
||||||
print_error("Error parsing arguments in: " + x);
|
sys.error("Error parsing arguments in: " + x);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@@ -550,11 +478,3 @@ function time_it(name, cont) {
|
|||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
function print_error(msg) {
|
|
||||||
console.error("%s", msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
function print(txt) {
|
|
||||||
console.log("%s", txt);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -489,7 +489,7 @@ merge(Compressor.prototype, {
|
|||||||
seq = [];
|
seq = [];
|
||||||
};
|
};
|
||||||
statements.forEach(function(stat){
|
statements.forEach(function(stat){
|
||||||
if (stat instanceof AST_SimpleStatement && seq.length < 2000) seq.push(stat.body);
|
if (stat instanceof AST_SimpleStatement) seq.push(stat.body);
|
||||||
else push_seq(), ret.push(stat);
|
else push_seq(), ret.push(stat);
|
||||||
});
|
});
|
||||||
push_seq();
|
push_seq();
|
||||||
@@ -1086,7 +1086,7 @@ merge(Compressor.prototype, {
|
|||||||
var tt = new TreeTransformer(
|
var tt = new TreeTransformer(
|
||||||
function before(node, descend, in_list) {
|
function before(node, descend, in_list) {
|
||||||
if (node instanceof AST_Lambda && !(node instanceof AST_Accessor)) {
|
if (node instanceof AST_Lambda && !(node instanceof AST_Accessor)) {
|
||||||
if (compressor.option("unsafe") && !compressor.option("keep_fargs")) {
|
if (!compressor.option("keep_fargs")) {
|
||||||
for (var a = node.argnames, i = a.length; --i >= 0;) {
|
for (var a = node.argnames, i = a.length; --i >= 0;) {
|
||||||
var sym = a[i];
|
var sym = a[i];
|
||||||
if (sym.unreferenced()) {
|
if (sym.unreferenced()) {
|
||||||
@@ -1168,12 +1168,12 @@ merge(Compressor.prototype, {
|
|||||||
return make_node(AST_EmptyStatement, node);
|
return make_node(AST_EmptyStatement, node);
|
||||||
}
|
}
|
||||||
if (def.length == 0) {
|
if (def.length == 0) {
|
||||||
return in_list ? MAP.splice(side_effects.body) : side_effects;
|
return side_effects;
|
||||||
}
|
}
|
||||||
node.definitions = def;
|
node.definitions = def;
|
||||||
if (side_effects) {
|
if (side_effects) {
|
||||||
side_effects.body.unshift(node);
|
side_effects.body.unshift(node);
|
||||||
return in_list ? MAP.splice(side_effects.body) : side_effects;
|
node = side_effects;
|
||||||
}
|
}
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
@@ -2104,34 +2104,6 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (compressor.option("conditionals")) {
|
|
||||||
if (self.operator == "&&") {
|
|
||||||
var ll = self.left.evaluate(compressor);
|
|
||||||
var rr = self.right.evaluate(compressor);
|
|
||||||
if (ll.length > 1) {
|
|
||||||
if (ll[1]) {
|
|
||||||
compressor.warn("Condition left of && always true [{file}:{line},{col}]", self.start);
|
|
||||||
return rr[0];
|
|
||||||
} else {
|
|
||||||
compressor.warn("Condition left of && always false [{file}:{line},{col}]", self.start);
|
|
||||||
return ll[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (self.operator == "||") {
|
|
||||||
var ll = self.left.evaluate(compressor);
|
|
||||||
var rr = self.right.evaluate(compressor);
|
|
||||||
if (ll.length > 1) {
|
|
||||||
if (ll[1]) {
|
|
||||||
compressor.warn("Condition left of || always true [{file}:{line},{col}]", self.start);
|
|
||||||
return ll[0];
|
|
||||||
} else {
|
|
||||||
compressor.warn("Condition left of || always false [{file}:{line},{col}]", self.start);
|
|
||||||
return rr[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (compressor.option("booleans") && compressor.in_boolean_context()) switch (self.operator) {
|
if (compressor.option("booleans") && compressor.in_boolean_context()) switch (self.operator) {
|
||||||
case "&&":
|
case "&&":
|
||||||
var ll = self.left.evaluate(compressor);
|
var ll = self.left.evaluate(compressor);
|
||||||
@@ -2183,7 +2155,7 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (compressor.option("comparisons") && self.is_boolean()) {
|
if (compressor.option("comparisons")) {
|
||||||
if (!(compressor.parent() instanceof AST_Binary)
|
if (!(compressor.parent() instanceof AST_Binary)
|
||||||
|| compressor.parent() instanceof AST_Assign) {
|
|| compressor.parent() instanceof AST_Assign) {
|
||||||
var negated = make_node(AST_UnaryPrefix, self, {
|
var negated = make_node(AST_UnaryPrefix, self, {
|
||||||
@@ -2258,11 +2230,10 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// x && (y && z) ==> x && y && z
|
// x * (y * z) ==> x * y * z
|
||||||
// x || (y || z) ==> x || y || z
|
|
||||||
if (self.right instanceof AST_Binary
|
if (self.right instanceof AST_Binary
|
||||||
&& self.right.operator == self.operator
|
&& self.right.operator == self.operator
|
||||||
&& (self.operator == "&&" || self.operator == "||"))
|
&& (self.operator == "*" || self.operator == "&&" || self.operator == "||"))
|
||||||
{
|
{
|
||||||
self.left = make_node(AST_Binary, self.left, {
|
self.left = make_node(AST_Binary, self.left, {
|
||||||
operator : self.operator,
|
operator : self.operator,
|
||||||
@@ -2296,8 +2267,16 @@ merge(Compressor.prototype, {
|
|||||||
OPT(AST_Infinity, function (self, compressor) {
|
OPT(AST_Infinity, function (self, compressor) {
|
||||||
return make_node(AST_Binary, self, {
|
return make_node(AST_Binary, self, {
|
||||||
operator : '/',
|
operator : '/',
|
||||||
left : make_node(AST_Number, self, {value: 1}),
|
left : make_node(AST_Number, null, {value: 1}),
|
||||||
right : make_node(AST_Number, self, {value: 0})
|
right : make_node(AST_Number, null, {value: 0})
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
OPT(AST_NaN, function (self, compressor) {
|
||||||
|
return make_node(AST_Binary, self, {
|
||||||
|
operator : '/',
|
||||||
|
left : make_node(AST_Number, null, {value: 0}),
|
||||||
|
right : make_node(AST_Number, null, {value: 0})
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -2364,7 +2343,6 @@ merge(Compressor.prototype, {
|
|||||||
&& alternative instanceof AST_Assign
|
&& alternative instanceof AST_Assign
|
||||||
&& consequent.operator == alternative.operator
|
&& consequent.operator == alternative.operator
|
||||||
&& consequent.left.equivalent_to(alternative.left)
|
&& consequent.left.equivalent_to(alternative.left)
|
||||||
&& !consequent.left.has_side_effects(compressor)
|
|
||||||
) {
|
) {
|
||||||
/*
|
/*
|
||||||
* Stuff like this:
|
* Stuff like this:
|
||||||
@@ -2385,7 +2363,6 @@ merge(Compressor.prototype, {
|
|||||||
if (consequent instanceof AST_Call
|
if (consequent instanceof AST_Call
|
||||||
&& alternative.TYPE === consequent.TYPE
|
&& alternative.TYPE === consequent.TYPE
|
||||||
&& consequent.args.length == alternative.args.length
|
&& consequent.args.length == alternative.args.length
|
||||||
&& !consequent.expression.has_side_effects(compressor)
|
|
||||||
&& consequent.expression.equivalent_to(alternative.expression)) {
|
&& consequent.expression.equivalent_to(alternative.expression)) {
|
||||||
if (consequent.args.length == 0) {
|
if (consequent.args.length == 0) {
|
||||||
return make_node(AST_Seq, self, {
|
return make_node(AST_Seq, self, {
|
||||||
@@ -2503,7 +2480,7 @@ merge(Compressor.prototype, {
|
|||||||
});
|
});
|
||||||
|
|
||||||
function literals_in_boolean_context(self, compressor) {
|
function literals_in_boolean_context(self, compressor) {
|
||||||
if (compressor.option("booleans") && compressor.in_boolean_context() && !self.has_side_effects(compressor)) {
|
if (compressor.option("booleans") && compressor.in_boolean_context()) {
|
||||||
return make_node(AST_True, self);
|
return make_node(AST_True, self);
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
|
|||||||
@@ -176,6 +176,7 @@ function OutputStream(options) {
|
|||||||
might_need_space = false;
|
might_need_space = false;
|
||||||
}
|
}
|
||||||
might_need_semicolon = false;
|
might_need_semicolon = false;
|
||||||
|
maybe_newline();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!options.beautify && options.preserve_line && stack[stack.length - 1]) {
|
if (!options.beautify && options.preserve_line && stack[stack.length - 1]) {
|
||||||
|
|||||||
21
lib/parse.js
21
lib/parse.js
@@ -108,7 +108,7 @@ var OPERATORS = makePredicate([
|
|||||||
"||"
|
"||"
|
||||||
]);
|
]);
|
||||||
|
|
||||||
var WHITESPACE_CHARS = makePredicate(characters(" \u00a0\n\r\t\f\u000b\u200b\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\uFEFF"));
|
var WHITESPACE_CHARS = makePredicate(characters(" \u00a0\n\r\t\f\u000b\u200b\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000"));
|
||||||
|
|
||||||
var PUNC_BEFORE_EXPRESSION = makePredicate(characters("[{(,.;:"));
|
var PUNC_BEFORE_EXPRESSION = makePredicate(characters("[{(,.;:"));
|
||||||
|
|
||||||
@@ -187,9 +187,8 @@ function parse_js_number(num) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
function JS_Parse_Error(message, filename, line, col, pos) {
|
function JS_Parse_Error(message, line, col, pos) {
|
||||||
this.message = message;
|
this.message = message;
|
||||||
this.filename = filename;
|
|
||||||
this.line = line;
|
this.line = line;
|
||||||
this.col = col;
|
this.col = col;
|
||||||
this.pos = pos;
|
this.pos = pos;
|
||||||
@@ -201,7 +200,7 @@ JS_Parse_Error.prototype.toString = function() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function js_error(message, filename, line, col, pos) {
|
function js_error(message, filename, line, col, pos) {
|
||||||
throw new JS_Parse_Error(message, filename, line, col, pos);
|
throw new JS_Parse_Error(message, line, col, pos);
|
||||||
};
|
};
|
||||||
|
|
||||||
function is_token(token, type, val) {
|
function is_token(token, type, val) {
|
||||||
@@ -213,7 +212,7 @@ var EX_EOF = {};
|
|||||||
function tokenizer($TEXT, filename, html5_comments) {
|
function tokenizer($TEXT, filename, html5_comments) {
|
||||||
|
|
||||||
var S = {
|
var S = {
|
||||||
text : $TEXT,
|
text : $TEXT.replace(/\uFEFF/g, ''),
|
||||||
filename : filename,
|
filename : filename,
|
||||||
pos : 0,
|
pos : 0,
|
||||||
tokpos : 0,
|
tokpos : 0,
|
||||||
@@ -298,8 +297,7 @@ function tokenizer($TEXT, filename, html5_comments) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function skip_whitespace() {
|
function skip_whitespace() {
|
||||||
var ch;
|
while (WHITESPACE_CHARS(peek()))
|
||||||
while (WHITESPACE_CHARS(ch = peek()) || ch == "\u2028" || ch == "\u2029")
|
|
||||||
next();
|
next();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -354,13 +352,8 @@ function tokenizer($TEXT, filename, html5_comments) {
|
|||||||
case 120 : return String.fromCharCode(hex_bytes(2)); // \x
|
case 120 : return String.fromCharCode(hex_bytes(2)); // \x
|
||||||
case 117 : return String.fromCharCode(hex_bytes(4)); // \u
|
case 117 : return String.fromCharCode(hex_bytes(4)); // \u
|
||||||
case 10 : return ""; // newline
|
case 10 : return ""; // newline
|
||||||
case 13 : // \r
|
default : return ch;
|
||||||
if (peek() == "\n") { // DOS newline
|
|
||||||
next(true, in_string);
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return ch;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function hex_bytes(n) {
|
function hex_bytes(n) {
|
||||||
@@ -377,7 +370,7 @@ function tokenizer($TEXT, filename, html5_comments) {
|
|||||||
var read_string = with_eof_error("Unterminated string constant", function(quote_char){
|
var read_string = with_eof_error("Unterminated string constant", function(quote_char){
|
||||||
var quote = next(), ret = "";
|
var quote = next(), ret = "";
|
||||||
for (;;) {
|
for (;;) {
|
||||||
var ch = next(true, true);
|
var ch = next(true);
|
||||||
if (ch == "\\") {
|
if (ch == "\\") {
|
||||||
// read OctalEscapeSequence (XXX: deprecated if "strict mode")
|
// read OctalEscapeSequence (XXX: deprecated if "strict mode")
|
||||||
// https://github.com/mishoo/UglifyJS/issues/178
|
// https://github.com/mishoo/UglifyJS/issues/178
|
||||||
|
|||||||
@@ -1,221 +0,0 @@
|
|||||||
/***********************************************************************
|
|
||||||
|
|
||||||
A JavaScript tokenizer / parser / beautifier / compressor.
|
|
||||||
https://github.com/mishoo/UglifyJS2
|
|
||||||
|
|
||||||
-------------------------------- (C) ---------------------------------
|
|
||||||
|
|
||||||
Author: Mihai Bazon
|
|
||||||
<mihai.bazon@gmail.com>
|
|
||||||
http://mihai.bazon.net/blog
|
|
||||||
|
|
||||||
Distributed under the BSD license:
|
|
||||||
|
|
||||||
Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions
|
|
||||||
are met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above
|
|
||||||
copyright notice, this list of conditions and the following
|
|
||||||
disclaimer.
|
|
||||||
|
|
||||||
* Redistributions in binary form must reproduce the above
|
|
||||||
copyright notice, this list of conditions and the following
|
|
||||||
disclaimer in the documentation and/or other materials
|
|
||||||
provided with the distribution.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
|
|
||||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
||||||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
|
|
||||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
|
||||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
||||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
||||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
|
|
||||||
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
|
||||||
THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
SUCH DAMAGE.
|
|
||||||
|
|
||||||
***********************************************************************/
|
|
||||||
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
function find_builtins() {
|
|
||||||
var a = [];
|
|
||||||
[ Object, Array, Function, Number,
|
|
||||||
String, Boolean, Error, Math,
|
|
||||||
Date, RegExp
|
|
||||||
].forEach(function(ctor){
|
|
||||||
Object.getOwnPropertyNames(ctor).map(add);
|
|
||||||
if (ctor.prototype) {
|
|
||||||
Object.getOwnPropertyNames(ctor.prototype).map(add);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
function add(name) {
|
|
||||||
push_uniq(a, name);
|
|
||||||
}
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
|
|
||||||
function mangle_properties(ast, options) {
|
|
||||||
options = defaults(options, {
|
|
||||||
reserved : null,
|
|
||||||
cache : null,
|
|
||||||
only_cache : false,
|
|
||||||
regex : null
|
|
||||||
});
|
|
||||||
|
|
||||||
var reserved = options.reserved;
|
|
||||||
if (reserved == null)
|
|
||||||
reserved = find_builtins();
|
|
||||||
|
|
||||||
var cache = options.cache;
|
|
||||||
if (cache == null) {
|
|
||||||
cache = {
|
|
||||||
cname: -1,
|
|
||||||
props: new Dictionary()
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
var regex = options.regex;
|
|
||||||
|
|
||||||
var names_to_mangle = [];
|
|
||||||
|
|
||||||
// step 1: find candidates to mangle
|
|
||||||
ast.walk(new TreeWalker(function(node){
|
|
||||||
if (node instanceof AST_ObjectKeyVal) {
|
|
||||||
add(node.key);
|
|
||||||
}
|
|
||||||
else if (node instanceof AST_ObjectProperty) {
|
|
||||||
// setter or getter, since KeyVal is handled above
|
|
||||||
add(node.key.name);
|
|
||||||
}
|
|
||||||
else if (node instanceof AST_Dot) {
|
|
||||||
if (this.parent() instanceof AST_Assign) {
|
|
||||||
add(node.property);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (node instanceof AST_Sub) {
|
|
||||||
if (this.parent() instanceof AST_Assign) {
|
|
||||||
addStrings(node.property);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
|
|
||||||
// step 2: transform the tree, renaming properties
|
|
||||||
return ast.transform(new TreeTransformer(function(node){
|
|
||||||
if (node instanceof AST_ObjectKeyVal) {
|
|
||||||
if (should_mangle(node.key)) {
|
|
||||||
node.key = mangle(node.key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (node instanceof AST_ObjectProperty) {
|
|
||||||
// setter or getter
|
|
||||||
if (should_mangle(node.key.name)) {
|
|
||||||
node.key.name = mangle(node.key.name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (node instanceof AST_Dot) {
|
|
||||||
if (should_mangle(node.property)) {
|
|
||||||
node.property = mangle(node.property);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (node instanceof AST_Sub) {
|
|
||||||
node.property = mangleStrings(node.property);
|
|
||||||
}
|
|
||||||
// else if (node instanceof AST_String) {
|
|
||||||
// if (should_mangle(node.value)) {
|
|
||||||
// AST_Node.warn(
|
|
||||||
// "Found \"{prop}\" property candidate for mangling in an arbitrary string [{file}:{line},{col}]", {
|
|
||||||
// file : node.start.file,
|
|
||||||
// line : node.start.line,
|
|
||||||
// col : node.start.col,
|
|
||||||
// prop : node.value
|
|
||||||
// }
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}));
|
|
||||||
|
|
||||||
// only function declarations after this line
|
|
||||||
|
|
||||||
function can_mangle(name) {
|
|
||||||
if (reserved.indexOf(name) >= 0) return false;
|
|
||||||
if (options.only_cache) {
|
|
||||||
return cache.props.has(name);
|
|
||||||
}
|
|
||||||
if (/^[0-9.]+$/.test(name)) return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function should_mangle(name) {
|
|
||||||
if (regex && !regex.test(name)) return false;
|
|
||||||
if (reserved.indexOf(name) >= 0) return false;
|
|
||||||
return cache.props.has(name)
|
|
||||||
|| names_to_mangle.indexOf(name) >= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
function add(name) {
|
|
||||||
if (can_mangle(name))
|
|
||||||
push_uniq(names_to_mangle, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
function mangle(name) {
|
|
||||||
var mangled = cache.props.get(name);
|
|
||||||
if (!mangled) {
|
|
||||||
do {
|
|
||||||
mangled = base54(++cache.cname);
|
|
||||||
} while (!can_mangle(mangled));
|
|
||||||
cache.props.set(name, mangled);
|
|
||||||
}
|
|
||||||
return mangled;
|
|
||||||
}
|
|
||||||
|
|
||||||
function addStrings(node) {
|
|
||||||
var out = {};
|
|
||||||
try {
|
|
||||||
(function walk(node){
|
|
||||||
node.walk(new TreeWalker(function(node){
|
|
||||||
if (node instanceof AST_Seq) {
|
|
||||||
walk(node.cdr);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (node instanceof AST_String) {
|
|
||||||
add(node.value);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (node instanceof AST_Conditional) {
|
|
||||||
walk(node.consequent);
|
|
||||||
walk(node.alternative);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
throw out;
|
|
||||||
}));
|
|
||||||
})(node);
|
|
||||||
} catch(ex) {
|
|
||||||
if (ex !== out) throw ex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function mangleStrings(node) {
|
|
||||||
return node.transform(new TreeTransformer(function(node){
|
|
||||||
if (node instanceof AST_Seq) {
|
|
||||||
node.cdr = mangleStrings(node.cdr);
|
|
||||||
}
|
|
||||||
else if (node instanceof AST_String) {
|
|
||||||
if (should_mangle(node.value)) {
|
|
||||||
node.value = mangle(node.value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (node instanceof AST_Conditional) {
|
|
||||||
node.consequent = mangleStrings(node.consequent);
|
|
||||||
node.alternative = mangleStrings(node.alternative);
|
|
||||||
}
|
|
||||||
return node;
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
29
lib/scope.js
29
lib/scope.js
@@ -67,26 +67,18 @@ SymbolDef.prototype = {
|
|||||||
|| this.orig[0] instanceof AST_SymbolDefun));
|
|| this.orig[0] instanceof AST_SymbolDefun));
|
||||||
},
|
},
|
||||||
mangle: function(options) {
|
mangle: function(options) {
|
||||||
var cache = options.cache && options.cache.props;
|
if (!this.mangled_name && !this.unmangleable(options)) {
|
||||||
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;
|
var s = this.scope;
|
||||||
if (!options.screw_ie8 && this.orig[0] instanceof AST_SymbolLambda)
|
if (!options.screw_ie8 && this.orig[0] instanceof AST_SymbolLambda)
|
||||||
s = s.parent_scope;
|
s = s.parent_scope;
|
||||||
this.mangled_name = s.next_mangled(options, this);
|
this.mangled_name = s.next_mangled(options, this);
|
||||||
if (this.global && cache) {
|
|
||||||
cache.set(this.name, this.mangled_name);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
|
AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
|
||||||
options = defaults(options, {
|
options = defaults(options, {
|
||||||
screw_ie8: false,
|
screw_ie8: false
|
||||||
cache: null
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// pass 1: setup scope chaining and handle definitions
|
// pass 1: setup scope chaining and handle definitions
|
||||||
@@ -191,10 +183,6 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
self.walk(tw);
|
self.walk(tw);
|
||||||
|
|
||||||
if (options.cache) {
|
|
||||||
this.cname = options.cache.cname;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
AST_Scope.DEFMETHOD("init_scope_vars", function(nesting){
|
AST_Scope.DEFMETHOD("init_scope_vars", function(nesting){
|
||||||
@@ -356,15 +344,6 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options){
|
|||||||
// the AST_SymbolDeclaration that it points to).
|
// the AST_SymbolDeclaration that it points to).
|
||||||
var lname = -1;
|
var lname = -1;
|
||||||
var to_mangle = [];
|
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){
|
var tw = new TreeWalker(function(node, descend){
|
||||||
if (node instanceof AST_LabeledStatement) {
|
if (node instanceof AST_LabeledStatement) {
|
||||||
// lname is incremented when we get to the AST_Label
|
// lname is incremented when we get to the AST_Label
|
||||||
@@ -399,10 +378,6 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options){
|
|||||||
});
|
});
|
||||||
this.walk(tw);
|
this.walk(tw);
|
||||||
to_mangle.forEach(function(def){ def.mangle(options) });
|
to_mangle.forEach(function(def){ def.mangle(options) });
|
||||||
|
|
||||||
if (options.cache) {
|
|
||||||
options.cache.cname = this.cname;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
AST_Toplevel.DEFMETHOD("compute_char_frequency", function(options){
|
AST_Toplevel.DEFMETHOD("compute_char_frequency", function(options){
|
||||||
|
|||||||
12
lib/utils.js
12
lib/utils.js
@@ -106,12 +106,10 @@ function defaults(args, defs, croak) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function merge(obj, ext) {
|
function merge(obj, ext) {
|
||||||
var count = 0;
|
|
||||||
for (var i in ext) if (ext.hasOwnProperty(i)) {
|
for (var i in ext) if (ext.hasOwnProperty(i)) {
|
||||||
obj[i] = ext[i];
|
obj[i] = ext[i];
|
||||||
count++;
|
|
||||||
}
|
}
|
||||||
return count;
|
return obj;
|
||||||
};
|
};
|
||||||
|
|
||||||
function noop() {};
|
function noop() {};
|
||||||
@@ -300,11 +298,5 @@ Dictionary.prototype = {
|
|||||||
for (var i in this._values)
|
for (var i in this._values)
|
||||||
ret.push(f(this._values[i], i.substr(1)));
|
ret.push(f(this._values[i], i.substr(1)));
|
||||||
return ret;
|
return ret;
|
||||||
},
|
}
|
||||||
toObject: function() { return this._values }
|
|
||||||
};
|
|
||||||
Dictionary.fromObject = function(obj) {
|
|
||||||
var dict = new Dictionary();
|
|
||||||
dict._size = merge(dict._values, obj);
|
|
||||||
return dict;
|
|
||||||
};
|
};
|
||||||
|
|||||||
80
package.json
80
package.json
@@ -1,51 +1,37 @@
|
|||||||
{
|
{
|
||||||
"name": "uglify-js",
|
"name": "uglify-js",
|
||||||
"description": "JavaScript parser, mangler/compressor and beautifier toolkit",
|
"description": "JavaScript parser, mangler/compressor and beautifier toolkit",
|
||||||
"homepage": "http://lisperator.net/uglifyjs",
|
"homepage": "http://lisperator.net/uglifyjs",
|
||||||
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
|
"main": "tools/node.js",
|
||||||
"license": "BSD",
|
"version": "2.4.17",
|
||||||
"version": "2.4.24",
|
"engines": { "node" : ">=0.4.0" },
|
||||||
"engines": {
|
"maintainers": [{
|
||||||
"node": ">=0.4.0"
|
"name": "Mihai Bazon",
|
||||||
},
|
"email": "mihai.bazon@gmail.com",
|
||||||
"maintainers": [
|
"web": "http://lisperator.net/"
|
||||||
"Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)"
|
}],
|
||||||
],
|
"repository": {
|
||||||
"repository": {
|
"type": "git",
|
||||||
"type": "git",
|
"url": "https://github.com/mishoo/UglifyJS2.git"
|
||||||
"url": "https://github.com/mishoo/UglifyJS2.git"
|
},
|
||||||
},
|
"dependencies": {
|
||||||
"bugs": {
|
"async" : "~0.2.6",
|
||||||
"url": "https://github.com/mishoo/UglifyJS2/issues"
|
"source-map" : "0.1.34",
|
||||||
},
|
"yargs": "~1.3.3",
|
||||||
"main": "tools/node.js",
|
"uglify-to-browserify": "~1.0.0"
|
||||||
"bin": {
|
},
|
||||||
"uglifyjs": "bin/uglifyjs"
|
"devDependencies": {
|
||||||
},
|
"acorn": "~0.6.0",
|
||||||
"files": [
|
"escodegen": "~1.3.3",
|
||||||
"bin",
|
"esfuzz": "~0.3.1",
|
||||||
"lib",
|
"estraverse": "~1.5.1"
|
||||||
"tools",
|
},
|
||||||
"LICENSE"
|
"browserify": {
|
||||||
],
|
"transform": [ "uglify-to-browserify" ]
|
||||||
"dependencies": {
|
},
|
||||||
"async": "~0.2.6",
|
"bin": {
|
||||||
"source-map": "0.1.34",
|
"uglifyjs" : "bin/uglifyjs"
|
||||||
"uglify-to-browserify": "~1.0.0",
|
},
|
||||||
"yargs": "~3.5.4"
|
"license": "BSD",
|
||||||
},
|
"scripts": {"test": "node test/run-tests.js"}
|
||||||
"devDependencies": {
|
|
||||||
"acorn": "~0.6.0",
|
|
||||||
"escodegen": "~1.3.3",
|
|
||||||
"esfuzz": "~0.3.1",
|
|
||||||
"estraverse": "~1.5.1"
|
|
||||||
},
|
|
||||||
"browserify": {
|
|
||||||
"transform": [
|
|
||||||
"uglify-to-browserify"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"scripts": {
|
|
||||||
"test": "node test/run-tests.js"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -86,9 +86,7 @@ ifs_4: {
|
|||||||
x(foo)[10].bar.baz = something_else();
|
x(foo)[10].bar.baz = something_else();
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
foo && bar
|
x(foo)[10].bar.baz = (foo && bar) ? something() : something_else();
|
||||||
? x(foo)[10].bar.baz = something()
|
|
||||||
: x(foo)[10].bar.baz = something_else();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -135,7 +133,6 @@ ifs_6: {
|
|||||||
comparisons: true
|
comparisons: true
|
||||||
};
|
};
|
||||||
input: {
|
input: {
|
||||||
var x;
|
|
||||||
if (!foo && !bar && !baz && !boo) {
|
if (!foo && !bar && !baz && !boo) {
|
||||||
x = 10;
|
x = 10;
|
||||||
} else {
|
} else {
|
||||||
@@ -143,7 +140,6 @@ ifs_6: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var x;
|
|
||||||
x = foo || bar || baz || boo ? 20 : 10;
|
x = foo || bar || baz || boo ? 20 : 10;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -153,7 +149,6 @@ cond_1: {
|
|||||||
conditionals: true
|
conditionals: true
|
||||||
};
|
};
|
||||||
input: {
|
input: {
|
||||||
var do_something; // if undeclared it's assumed to have side-effects
|
|
||||||
if (some_condition()) {
|
if (some_condition()) {
|
||||||
do_something(x);
|
do_something(x);
|
||||||
} else {
|
} else {
|
||||||
@@ -161,7 +156,6 @@ cond_1: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var do_something;
|
|
||||||
do_something(some_condition() ? x : y);
|
do_something(some_condition() ? x : y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -171,7 +165,6 @@ cond_2: {
|
|||||||
conditionals: true
|
conditionals: true
|
||||||
};
|
};
|
||||||
input: {
|
input: {
|
||||||
var x, FooBar;
|
|
||||||
if (some_condition()) {
|
if (some_condition()) {
|
||||||
x = new FooBar(1);
|
x = new FooBar(1);
|
||||||
} else {
|
} else {
|
||||||
@@ -179,7 +172,6 @@ cond_2: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var x, FooBar;
|
|
||||||
x = new FooBar(some_condition() ? 1 : 2);
|
x = new FooBar(some_condition() ? 1 : 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -189,7 +181,6 @@ cond_3: {
|
|||||||
conditionals: true
|
conditionals: true
|
||||||
};
|
};
|
||||||
input: {
|
input: {
|
||||||
var FooBar;
|
|
||||||
if (some_condition()) {
|
if (some_condition()) {
|
||||||
new FooBar(1);
|
new FooBar(1);
|
||||||
} else {
|
} else {
|
||||||
@@ -197,7 +188,6 @@ cond_3: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var FooBar;
|
|
||||||
some_condition() ? new FooBar(1) : FooBar(2);
|
some_condition() ? new FooBar(1) : FooBar(2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -207,7 +197,6 @@ cond_4: {
|
|||||||
conditionals: true
|
conditionals: true
|
||||||
};
|
};
|
||||||
input: {
|
input: {
|
||||||
var do_something;
|
|
||||||
if (some_condition()) {
|
if (some_condition()) {
|
||||||
do_something();
|
do_something();
|
||||||
} else {
|
} else {
|
||||||
@@ -215,7 +204,6 @@ cond_4: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var do_something;
|
|
||||||
some_condition(), do_something();
|
some_condition(), do_something();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -315,7 +303,6 @@ cond_7_1: {
|
|||||||
evaluate : true
|
evaluate : true
|
||||||
};
|
};
|
||||||
input: {
|
input: {
|
||||||
var x;
|
|
||||||
// access to global should be assumed to have side effects
|
// access to global should be assumed to have side effects
|
||||||
if (y) {
|
if (y) {
|
||||||
x = 1+1;
|
x = 1+1;
|
||||||
@@ -324,7 +311,6 @@ cond_7_1: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var x;
|
|
||||||
x = (y, 2);
|
x = (y, 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -335,7 +321,6 @@ cond_8: {
|
|||||||
evaluate : true
|
evaluate : true
|
||||||
};
|
};
|
||||||
input: {
|
input: {
|
||||||
var a;
|
|
||||||
// compress these
|
// compress these
|
||||||
a = condition ? true : false;
|
a = condition ? true : false;
|
||||||
|
|
||||||
@@ -370,7 +355,6 @@ cond_8: {
|
|||||||
|
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var a;
|
|
||||||
a = !!condition;
|
a = !!condition;
|
||||||
a = !condition;
|
a = !condition;
|
||||||
a = !!condition();
|
a = !!condition();
|
||||||
@@ -383,164 +367,4 @@ cond_8: {
|
|||||||
a = condition ? 0 : true;
|
a = condition ? 0 : true;
|
||||||
a = condition ? 1 : 0;
|
a = condition ? 1 : 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
conditional_and: {
|
|
||||||
options = {
|
|
||||||
conditionals: true,
|
|
||||||
evaluate : true
|
|
||||||
};
|
|
||||||
input: {
|
|
||||||
var a;
|
|
||||||
// compress these
|
|
||||||
|
|
||||||
a = true && condition;
|
|
||||||
a = 1 && console.log("a");
|
|
||||||
a = 2 * 3 && 2 * condition;
|
|
||||||
a = 5 == 5 && condition + 3;
|
|
||||||
a = "string" && 4 - condition;
|
|
||||||
a = 5 + "" && condition / 5;
|
|
||||||
a = -4.5 && 6 << condition;
|
|
||||||
a = 6 && 7;
|
|
||||||
|
|
||||||
a = false && condition;
|
|
||||||
a = NaN && console.log("b");
|
|
||||||
a = 0 && console.log("c");
|
|
||||||
a = undefined && 2 * condition;
|
|
||||||
a = null && condition + 3;
|
|
||||||
a = 2 * 3 - 6 && 4 - condition;
|
|
||||||
a = 10 == 7 && condition / 5;
|
|
||||||
a = !"string" && 6 % condition;
|
|
||||||
a = 0 && 7;
|
|
||||||
|
|
||||||
// don't compress these
|
|
||||||
|
|
||||||
a = condition && true;
|
|
||||||
a = console.log("a") && 2;
|
|
||||||
a = 4 - condition && "string";
|
|
||||||
a = 6 << condition && -4.5;
|
|
||||||
|
|
||||||
a = condition && false;
|
|
||||||
a = console.log("b") && NaN;
|
|
||||||
a = console.log("c") && 0;
|
|
||||||
a = 2 * condition && undefined;
|
|
||||||
a = condition + 3 && null;
|
|
||||||
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
var a;
|
|
||||||
|
|
||||||
a = condition;
|
|
||||||
a = console.log("a");
|
|
||||||
a = 2 * condition;
|
|
||||||
a = condition + 3;
|
|
||||||
a = 4 - condition;
|
|
||||||
a = condition / 5;
|
|
||||||
a = 6 << condition;
|
|
||||||
a = 7;
|
|
||||||
|
|
||||||
a = false;
|
|
||||||
a = NaN;
|
|
||||||
a = 0;
|
|
||||||
a = void 0;
|
|
||||||
a = null;
|
|
||||||
a = 0;
|
|
||||||
a = false;
|
|
||||||
a = false;
|
|
||||||
a = 0;
|
|
||||||
|
|
||||||
a = condition && true;
|
|
||||||
a = console.log("a") && 2;
|
|
||||||
a = 4 - condition && "string";
|
|
||||||
a = 6 << condition && -4.5;
|
|
||||||
|
|
||||||
a = condition && false;
|
|
||||||
a = console.log("b") && NaN;
|
|
||||||
a = console.log("c") && 0;
|
|
||||||
a = 2 * condition && void 0;
|
|
||||||
a = condition + 3 && null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
conditional_or: {
|
|
||||||
options = {
|
|
||||||
conditionals: true,
|
|
||||||
evaluate : true
|
|
||||||
};
|
|
||||||
input: {
|
|
||||||
var a;
|
|
||||||
// compress these
|
|
||||||
|
|
||||||
a = true || condition;
|
|
||||||
a = 1 || console.log("a");
|
|
||||||
a = 2 * 3 || 2 * condition;
|
|
||||||
a = 5 == 5 || condition + 3;
|
|
||||||
a = "string" || 4 - condition;
|
|
||||||
a = 5 + "" || condition / 5;
|
|
||||||
a = -4.5 || 6 << condition;
|
|
||||||
a = 6 || 7;
|
|
||||||
|
|
||||||
a = false || condition;
|
|
||||||
a = 0 || console.log("b");
|
|
||||||
a = NaN || console.log("c");
|
|
||||||
a = undefined || 2 * condition;
|
|
||||||
a = null || condition + 3;
|
|
||||||
a = 2 * 3 - 6 || 4 - condition;
|
|
||||||
a = 10 == 7 || condition / 5;
|
|
||||||
a = !"string" || 6 % condition;
|
|
||||||
a = null || 7;
|
|
||||||
|
|
||||||
a = console.log(undefined && condition || null);
|
|
||||||
a = console.log(undefined || condition && null);
|
|
||||||
|
|
||||||
// don't compress these
|
|
||||||
|
|
||||||
a = condition || true;
|
|
||||||
a = console.log("a") || 2;
|
|
||||||
a = 4 - condition || "string";
|
|
||||||
a = 6 << condition || -4.5;
|
|
||||||
|
|
||||||
a = condition || false;
|
|
||||||
a = console.log("b") || NaN;
|
|
||||||
a = console.log("c") || 0;
|
|
||||||
a = 2 * condition || undefined;
|
|
||||||
a = condition + 3 || null;
|
|
||||||
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
var a;
|
|
||||||
|
|
||||||
a = true;
|
|
||||||
a = 1;
|
|
||||||
a = 6;
|
|
||||||
a = true;
|
|
||||||
a = "string";
|
|
||||||
a = "5";
|
|
||||||
a = -4.5;
|
|
||||||
a = 6;
|
|
||||||
|
|
||||||
a = condition;
|
|
||||||
a = console.log("b");
|
|
||||||
a = console.log("c");
|
|
||||||
a = 2 * condition;
|
|
||||||
a = condition + 3;
|
|
||||||
a = 4 - condition;
|
|
||||||
a = condition / 5;
|
|
||||||
a = 6 % condition;
|
|
||||||
a = 7;
|
|
||||||
|
|
||||||
a = console.log(null);
|
|
||||||
a = console.log(condition && null);
|
|
||||||
|
|
||||||
a = condition || true;
|
|
||||||
a = console.log("a") || 2;
|
|
||||||
a = 4 - condition || "string";
|
|
||||||
a = 6 << condition || -4.5;
|
|
||||||
|
|
||||||
a = condition || false;
|
|
||||||
a = console.log("b") || NaN;
|
|
||||||
a = console.log("c") || 0;
|
|
||||||
a = 2 * condition || void 0;
|
|
||||||
a = condition + 3 || null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
unused_funarg_1: {
|
unused_funarg_1: {
|
||||||
options = { unused: true, unsafe: true };
|
options = { unused: true };
|
||||||
input: {
|
input: {
|
||||||
function f(a, b, c, d, e) {
|
function f(a, b, c, d, e) {
|
||||||
return a + b;
|
return a + b;
|
||||||
@@ -13,7 +13,7 @@ unused_funarg_1: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
unused_funarg_2: {
|
unused_funarg_2: {
|
||||||
options = { unused: true, unsafe: true };
|
options = { unused: true };
|
||||||
input: {
|
input: {
|
||||||
function f(a, b, c, d, e) {
|
function f(a, b, c, d, e) {
|
||||||
return a + c;
|
return a + c;
|
||||||
@@ -165,7 +165,7 @@ used_var_in_catch: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
keep_fnames: {
|
keep_fnames: {
|
||||||
options = { unused: true, keep_fnames: true, unsafe: true };
|
options = { unused: true, keep_fnames: true };
|
||||||
input: {
|
input: {
|
||||||
function foo() {
|
function foo() {
|
||||||
return function bar(baz) {};
|
return function bar(baz) {};
|
||||||
@@ -176,4 +176,4 @@ keep_fnames: {
|
|||||||
return function bar() {};
|
return function bar() {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6,7 +6,7 @@ NaN_and_Infinity_must_have_parens: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
(1/0).toString();
|
(1/0).toString();
|
||||||
NaN.toString(); // transformation to 0/0 dropped
|
(0/0).toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,29 +0,0 @@
|
|||||||
negate_booleans_1: {
|
|
||||||
options = {
|
|
||||||
comparisons: true
|
|
||||||
};
|
|
||||||
input: {
|
|
||||||
var a = !a || !b || !c || !d || !e || !f;
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
var a = !(a && b && c && d && e && f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
negate_booleans_2: {
|
|
||||||
options = {
|
|
||||||
comparisons: true
|
|
||||||
};
|
|
||||||
input: {
|
|
||||||
var match = !x && // should not touch this one
|
|
||||||
(!z || c) &&
|
|
||||||
(!k || d) &&
|
|
||||||
the_stuff();
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
var match = !x &&
|
|
||||||
(!z || c) &&
|
|
||||||
(!k || d) &&
|
|
||||||
the_stuff();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -84,12 +84,7 @@ function run_compress_tests() {
|
|||||||
warnings: false
|
warnings: false
|
||||||
});
|
});
|
||||||
var cmp = new U.Compressor(options, true);
|
var cmp = new U.Compressor(options, true);
|
||||||
var expect;
|
var expect = make_code(as_toplevel(test.expect), false);
|
||||||
if (test.expect) {
|
|
||||||
expect = make_code(as_toplevel(test.expect), false);
|
|
||||||
} else {
|
|
||||||
expect = test.expect_exact;
|
|
||||||
}
|
|
||||||
var input = as_toplevel(test.input);
|
var input = as_toplevel(test.input);
|
||||||
var input_code = make_code(test.input);
|
var input_code = make_code(test.input);
|
||||||
var output = input.transform(cmp);
|
var output = input.transform(cmp);
|
||||||
@@ -155,7 +150,7 @@ function parse_test(file) {
|
|||||||
}
|
}
|
||||||
if (node instanceof U.AST_LabeledStatement) {
|
if (node instanceof U.AST_LabeledStatement) {
|
||||||
assert.ok(
|
assert.ok(
|
||||||
node.label.name == "input" || node.label.name == "expect" || node.label.name == "expect_exact",
|
node.label.name == "input" || node.label.name == "expect",
|
||||||
tmpl("Unsupported label {name} [{line},{col}]", {
|
tmpl("Unsupported label {name} [{line},{col}]", {
|
||||||
name: node.label.name,
|
name: node.label.name,
|
||||||
line: node.label.start.line,
|
line: node.label.start.line,
|
||||||
@@ -167,16 +162,7 @@ function parse_test(file) {
|
|||||||
if (stat.body.length == 1) stat = stat.body[0];
|
if (stat.body.length == 1) stat = stat.body[0];
|
||||||
else if (stat.body.length == 0) stat = new U.AST_EmptyStatement();
|
else if (stat.body.length == 0) stat = new U.AST_EmptyStatement();
|
||||||
}
|
}
|
||||||
if (node.label.name === "expect_exact") {
|
test[node.label.name] = stat;
|
||||||
if (!(stat.TYPE === "SimpleStatement" && stat.body.TYPE === "String")) {
|
|
||||||
throw new Error(
|
|
||||||
"The value of the expect_exact clause should be a string, " +
|
|
||||||
"like `expect_exact: \"some.exact.javascript;\"`");
|
|
||||||
}
|
|
||||||
test[node.label.name] = stat.body.start.value
|
|
||||||
} else {
|
|
||||||
test[node.label.name] = stat;
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
5603
tools/domprops.json
5603
tools/domprops.json
File diff suppressed because it is too large
Load Diff
@@ -1,8 +1,10 @@
|
|||||||
var path = require("path");
|
var path = require("path");
|
||||||
var fs = require("fs");
|
var fs = require("fs");
|
||||||
var vm = require("vm");
|
var vm = require("vm");
|
||||||
|
var sys = require("util");
|
||||||
|
|
||||||
var UglifyJS = vm.createContext({
|
var UglifyJS = vm.createContext({
|
||||||
|
sys : sys,
|
||||||
console : console,
|
console : console,
|
||||||
process : process,
|
process : process,
|
||||||
Buffer : Buffer,
|
Buffer : Buffer,
|
||||||
@@ -17,7 +19,7 @@ function load_global(file) {
|
|||||||
} catch(ex) {
|
} catch(ex) {
|
||||||
// XXX: in case of a syntax error, the message is kinda
|
// XXX: in case of a syntax error, the message is kinda
|
||||||
// useless. (no location information).
|
// useless. (no location information).
|
||||||
console.log("ERROR in file: " + file + " / " + ex);
|
sys.debug("ERROR in file: " + file + " / " + ex);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -31,8 +33,7 @@ var FILES = exports.FILES = [
|
|||||||
"../lib/output.js",
|
"../lib/output.js",
|
||||||
"../lib/compress.js",
|
"../lib/compress.js",
|
||||||
"../lib/sourcemap.js",
|
"../lib/sourcemap.js",
|
||||||
"../lib/mozilla-ast.js",
|
"../lib/mozilla-ast.js"
|
||||||
"../lib/propmangle.js"
|
|
||||||
].map(function(file){
|
].map(function(file){
|
||||||
return fs.realpathSync(path.join(path.dirname(__filename), file));
|
return fs.realpathSync(path.join(path.dirname(__filename), file));
|
||||||
});
|
});
|
||||||
@@ -40,7 +41,7 @@ var FILES = exports.FILES = [
|
|||||||
FILES.forEach(load_global);
|
FILES.forEach(load_global);
|
||||||
|
|
||||||
UglifyJS.AST_Node.warn_function = function(txt) {
|
UglifyJS.AST_Node.warn_function = function(txt) {
|
||||||
console.error("WARN: %s", txt);
|
sys.error("WARN: " + txt);
|
||||||
};
|
};
|
||||||
|
|
||||||
// XXX: perhaps we shouldn't export everything but heck, I'm lazy.
|
// XXX: perhaps we shouldn't export everything but heck, I'm lazy.
|
||||||
@@ -191,63 +192,3 @@ exports.describe_ast = function() {
|
|||||||
doitem(UglifyJS.AST_Node);
|
doitem(UglifyJS.AST_Node);
|
||||||
return out + "";
|
return out + "";
|
||||||
};
|
};
|
||||||
|
|
||||||
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");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -1,61 +0,0 @@
|
|||||||
<html>
|
|
||||||
<head>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<script>(function(){
|
|
||||||
var props = {};
|
|
||||||
|
|
||||||
function addObject(obj) {
|
|
||||||
if (obj == null) return;
|
|
||||||
try {
|
|
||||||
Object.getOwnPropertyNames(obj).forEach(add);
|
|
||||||
} catch(ex) {}
|
|
||||||
if (obj.prototype) {
|
|
||||||
Object.getOwnPropertyNames(obj.prototype).forEach(add);
|
|
||||||
}
|
|
||||||
if (typeof obj == "function") {
|
|
||||||
try {
|
|
||||||
Object.getOwnPropertyNames(new obj).forEach(add);
|
|
||||||
} catch(ex) {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function add(name) {
|
|
||||||
props[name] = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
Object.getOwnPropertyNames(window).forEach(function(thing){
|
|
||||||
addObject(window[thing]);
|
|
||||||
});
|
|
||||||
|
|
||||||
try {
|
|
||||||
addObject(new Event("click"));
|
|
||||||
addObject(new Event("contextmenu"));
|
|
||||||
addObject(new Event("mouseup"));
|
|
||||||
addObject(new Event("mousedown"));
|
|
||||||
addObject(new Event("keydown"));
|
|
||||||
addObject(new Event("keypress"));
|
|
||||||
addObject(new Event("keyup"));
|
|
||||||
} catch(ex) {}
|
|
||||||
|
|
||||||
var ta = document.createElement("textarea");
|
|
||||||
ta.style.width = "100%";
|
|
||||||
ta.style.height = "20em";
|
|
||||||
ta.style.boxSizing = "border-box";
|
|
||||||
<!-- ta.value = Object.keys(props).sort(cmp).map(function(name){ -->
|
|
||||||
<!-- return JSON.stringify(name); -->
|
|
||||||
<!-- }).join(",\n"); -->
|
|
||||||
ta.value = JSON.stringify({
|
|
||||||
vars: [],
|
|
||||||
props: Object.keys(props).sort(cmp)
|
|
||||||
}, null, 2);
|
|
||||||
document.body.appendChild(ta);
|
|
||||||
|
|
||||||
function cmp(a, b) {
|
|
||||||
a = a.toLowerCase();
|
|
||||||
b = b.toLowerCase();
|
|
||||||
return a < b ? -1 : a > b ? 1 : 0;
|
|
||||||
}
|
|
||||||
})();</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
Reference in New Issue
Block a user