Compare commits

..

1 Commits

Author SHA1 Message Date
Mihai Bazon
c7d3c07f5a v2.4.17 2015-03-11 00:03:12 +02:00
35 changed files with 370 additions and 7602 deletions

3
.gitignore vendored
View File

@@ -1,3 +1,2 @@
/node_modules/
/npm-debug.log
tmp/
node_modules/

View File

@@ -1,9 +1,6 @@
language: node_js
before_install: "npm install -g npm"
node_js:
- "0.12"
- "0.8"
- "0.10"
- "4"
matrix:
fast_finish: true
sudo: false
- "0.11"

235
README.md
View File

@@ -52,90 +52,70 @@ a double dash to prevent input files being used as option arguments:
The available options are:
```
--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
--mangle-regex Only mangle property names matching the regex
--name-cache File to hold mangled names mappings
--pure-funcs List of functions that can be safely removed if
their return value is not used [array]
--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]
```
Specify `--output` (`-o`) to declare the output file. Otherwise the output
@@ -209,73 +189,6 @@ comma-separated list of names. For example:
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
You need to pass `--compress` (`-c`) to enable the compressor. Optionally
@@ -352,11 +265,6 @@ to set `true`; it's effectively a shortcut for `foo=true`).
compressor from discarding unused function arguments. You need this
for code which relies on `Function.length`.
- `keep_fnames` -- default `false`. Pass `true` to prevent the
compressor from mangling/discarding function names. Useful for code relying on
`Function.prototype.name`.
### The `unsafe` option
It enables some transformations that *might* break code logic in certain
@@ -364,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
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()` → `{}`
- `String(exp)` or `exp.toString()` → `"" + exp`
- `new Object/RegExp/Function/Error/Array (...)` → we discard the `new`
- `typeof foo == "undefined"` → `foo === void 0`
- `void 0` → `undefined` (if there is a variable named "undefined" in
scope; we do it because the variable name will be mangled, typically
reduced to a single character)
- discards unused function arguments (affects `function.length`)
reduced to a single character).
### Conditional compilation
@@ -603,16 +510,6 @@ var result = UglifyJS.minify("compiled.js", {
// 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
no sense otherwise).

View File

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

View File

@@ -67,13 +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("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("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")
.describe("pure-funcs", "List of functions that can be safely removed if their return value is not used")
.describe("dump-spidermonkey-ast", "Dump SpiderMonkey AST to stdout.")
.alias("p", "prefix")
.alias("o", "output")
@@ -91,22 +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-url")
.string("b")
.string("beautify")
.string("m")
.string("mangle")
.string("c")
.string("compress")
.string("d")
.string("define")
.string("e")
.string("enclose")
.string("comments")
.string("wrap")
.string("p")
.string("prefix")
.string("name-cache")
.array("reserved-file")
.array("pure-funcs")
.boolean("expr")
.boolean("source-map-include-sources")
@@ -114,19 +98,14 @@ You need to pass an argument to this option to specify the name that your module
.boolean("export-all")
.boolean("self")
.boolean("v")
.boolean("verbose")
.boolean("stats")
.boolean("acorn")
.boolean("spidermonkey")
.boolean("dump-spidermonkey-ast")
.boolean("lint")
.boolean("V")
.boolean("version")
.boolean("noerr")
.boolean("bare-returns")
.boolean("keep-fnames")
.boolean("mangle-props")
.boolean("reserve-domprops")
.wrap(80)
@@ -137,24 +116,24 @@ normalize(ARGS);
if (ARGS.noerr) {
UglifyJS.DefaultsError.croak = function(msg, defs) {
print_error("WARN: " + msg);
sys.error("WARN: " + msg);
};
}
if (ARGS.version || ARGS.V) {
var json = require("../package.json");
print(json.name + ' ' + json.version);
sys.puts(json.name + ' ' + json.version);
process.exit(0);
}
if (ARGS.ast_help) {
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);
}
if (ARGS.h || ARGS.help) {
print(yargs.help());
sys.puts(yargs.help());
process.exit(0);
}
@@ -165,50 +144,15 @@ if (ARGS.acorn) {
var COMPRESS = getOptions("c", true);
var MANGLE = getOptions("m", 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 (COMPRESS) COMPRESS.global_defs = getOptions("d");
}
if (ARGS.pure_funcs) {
if (COMPRESS) COMPRESS.pure_funcs = ARGS.pure_funcs;
}
if (ARGS.r) {
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) {
ARGS.quotes = 3;
}
@@ -233,12 +177,13 @@ if (ARGS.keep_fnames) {
if (BEAUTIFY)
UglifyJS.merge(OUTPUT_OPTIONS, BEAUTIFY);
if (ARGS.comments != null) {
if (ARGS.comments) {
if (/^\/.*\/[a-zA-Z]*$/.test(ARGS.comments)) {
var regex_pos = ARGS.comments.lastIndexOf("/");
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) {
print_error("ERROR: Invalid --comments: " + e.message);
sys.error("ERROR: Invalid --comments: " + e.message);
}
} else if (ARGS.comments == "all") {
OUTPUT_OPTIONS.comments = true;
@@ -258,10 +203,11 @@ var files = ARGS._.slice();
if (ARGS.self) {
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;
if (!ARGS.wrap) ARGS.wrap = "UglifyJS";
ARGS.export_all = true;
}
var ORIG_MAP = ARGS.in_source_map;
@@ -269,7 +215,7 @@ var ORIG_MAP = ARGS.in_source_map;
if (ORIG_MAP) {
ORIG_MAP = JSON.parse(fs.readFileSync(ORIG_MAP));
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 ];
}
if (ARGS.source_map_root == null) {
@@ -282,12 +228,12 @@ if (files.length == 0) {
}
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);
}
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);
}
@@ -310,9 +256,9 @@ try {
var compressor = COMPRESS && UglifyJS.Compressor(COMPRESS);
} catch(ex) {
if (ex instanceof UglifyJS.DefaultsError) {
print_error(ex.msg);
print_error("Supported options:");
print_error(sys.inspect(ex.defs));
sys.error(ex.msg);
sys.error("Supported options:");
sys.error(sys.inspect(ex.defs));
process.exit(1);
}
}
@@ -320,7 +266,7 @@ try {
async.eachLimit(files, 1, function (file, cb) {
read_whole_file(file, function (err, code) {
if (err) {
print_error("ERROR: can't read file: " + file);
sys.error("ERROR: can't read file: " + file);
process.exit(1);
}
if (ARGS.p != null) {
@@ -357,9 +303,9 @@ async.eachLimit(files, 1, function (file, cb) {
});
} catch(ex) {
if (ex instanceof UglifyJS.JS_Parse_Error) {
print_error("Parse error at " + file + ":" + ex.line + "," + ex.col);
print_error(ex.message);
print_error(ex.stack);
sys.error("Parse error at " + file + ":" + ex.line + "," + ex.col);
sys.error(ex.message);
sys.error(ex.stack);
process.exit(1);
}
throw ex;
@@ -373,11 +319,11 @@ async.eachLimit(files, 1, function (file, cb) {
TOPLEVEL = UglifyJS.AST_Node.from_mozilla_ast(TOPLEVEL);
});
if (ARGS.wrap != null) {
if (ARGS.wrap) {
TOPLEVEL = TOPLEVEL.wrap_commonjs(ARGS.wrap, ARGS.export_all);
}
if (ARGS.enclose != null) {
if (ARGS.enclose) {
var arg_parameter_list = ARGS.enclose;
if (arg_parameter_list === true) {
arg_parameter_list = [];
@@ -388,33 +334,11 @@ async.eachLimit(files, 1, function (file, cb) {
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 TL_CACHE = readNameCache("vars");
var SCOPE_IS_NEEDED = COMPRESS || MANGLE || ARGS.lint;
if (SCOPE_IS_NEEDED) {
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) {
TOPLEVEL.scope_warnings();
}
@@ -429,20 +353,17 @@ async.eachLimit(files, 1, function (file, cb) {
if (SCOPE_IS_NEEDED) {
time_it("scope", function(){
TOPLEVEL.figure_out_scope({ screw_ie8: ARGS.screw_ie8, cache: TL_CACHE });
if (MANGLE && !TL_CACHE) {
TOPLEVEL.figure_out_scope({ screw_ie8: ARGS.screw_ie8 });
if (MANGLE) {
TOPLEVEL.compute_char_frequency(MANGLE);
}
});
}
if (MANGLE) time_it("mangle", function(){
MANGLE.cache = TL_CACHE;
TOPLEVEL.mangle_names(MANGLE);
});
writeNameCache("vars", TL_CACHE);
if (ARGS.source_map_include_sources) {
for (var file in SOURCES_CONTENT) {
if (SOURCES_CONTENT.hasOwnProperty(file)) {
@@ -451,38 +372,34 @@ async.eachLimit(files, 1, function (file, cb) {
}
}
if (ARGS.dump_spidermonkey_ast) {
print(JSON.stringify(TOPLEVEL.to_mozilla_ast(), null, 2));
time_it("generate", function(){
TOPLEVEL.print(output);
});
output = output.get();
if (SOURCE_MAP) {
fs.writeFileSync(ARGS.source_map, SOURCE_MAP, "utf8");
var source_map_url = ARGS.source_map_url || (
P_RELATIVE
? path.relative(path.dirname(OUTPUT_FILE), ARGS.source_map)
: ARGS.source_map
);
output += "\n//# sourceMappingURL=" + source_map_url;
}
if (OUTPUT_FILE) {
fs.writeFileSync(OUTPUT_FILE, output, "utf8");
} else {
time_it("generate", function(){
TOPLEVEL.print(output);
});
output = output.get();
if (SOURCE_MAP) {
fs.writeFileSync(ARGS.source_map, SOURCE_MAP, "utf8");
var source_map_url = ARGS.source_map_url || (
P_RELATIVE
? path.relative(path.dirname(OUTPUT_FILE), ARGS.source_map)
: ARGS.source_map
);
output += "\n//# sourceMappingURL=" + source_map_url;
}
if (OUTPUT_FILE) {
fs.writeFileSync(OUTPUT_FILE, output, "utf8");
} else {
print(output);
}
sys.print(output);
}
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
}));
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,
time: (STATS[i] / 1000).toFixed(3)
}));
@@ -501,15 +418,15 @@ function normalize(o) {
function getOptions(x, constants) {
x = ARGS[x];
if (x == null) return null;
if (!x) return null;
var ret = {};
if (x !== "") {
if (x !== true) {
var ast;
try {
ast = UglifyJS.parse(x, { expression: true });
} catch(ex) {
if (ex instanceof UglifyJS.JS_Parse_Error) {
print_error("Error parsing arguments in: " + x);
sys.error("Error parsing arguments in: " + x);
process.exit(1);
}
}
@@ -528,8 +445,8 @@ function getOptions(x, constants) {
ret[name] = true;
return true; // no descend
}
print_error(node.TYPE)
print_error("Error parsing arguments in: " + x);
sys.error(node.TYPE)
sys.error("Error parsing arguments in: " + x);
process.exit(1);
}));
}
@@ -561,11 +478,3 @@ function time_it(name, cont) {
}
return ret;
}
function print_error(msg) {
console.error("%s", msg);
}
function print(txt) {
console.log("%s", txt);
}

View File

@@ -81,11 +81,10 @@ function DEFNODE(type, props, methods, base) {
ctor.DEFMETHOD = function(name, method) {
this.prototype[name] = method;
};
exports["AST_" + type] = ctor;
return ctor;
};
var AST_Token = DEFNODE("Token", "type value line col pos endline endcol endpos nlb comments_before file raw", {
var AST_Token = DEFNODE("Token", "type value line col pos endline endcol endpos nlb comments_before file", {
}, null);
var AST_Node = DEFNODE("Node", "start end", {
@@ -330,11 +329,12 @@ var AST_Toplevel = DEFNODE("Toplevel", "globals", {
}
}));
}
var wrapped_tl = "(function(exports, global){ '$ORIG'; '$EXPORTS'; global['" + name + "'] = exports; }({}, (function(){return this}())))";
var wrapped_tl = "(function(exports, global){ global['" + name + "'] = exports; '$ORIG'; '$EXPORTS'; }({}, (function(){return this}())))";
wrapped_tl = parse(wrapped_tl);
wrapped_tl = wrapped_tl.transform(new TreeTransformer(function before(node){
if (node instanceof AST_Directive) {
switch (node.value) {
if (node instanceof AST_SimpleStatement) {
node = node.body;
if (node instanceof AST_String) switch (node.getValue()) {
case "$ORIG":
return MAP.splice(self.body);
case "$EXPORTS":
@@ -864,11 +864,10 @@ var AST_String = DEFNODE("String", "value quote", {
}
}, AST_Constant);
var AST_Number = DEFNODE("Number", "value literal", {
var AST_Number = DEFNODE("Number", "value", {
$documentation: "A number literal",
$propdoc: {
value: "[number] the numeric value",
literal: "[string] numeric value as string (optional)"
value: "[number] the numeric value"
}
}, AST_Constant);
@@ -927,36 +926,27 @@ var AST_True = DEFNODE("True", null, {
function TreeWalker(callback) {
this.visit = callback;
this.stack = [];
this.directives = Object.create(null);
};
TreeWalker.prototype = {
_visit: function(node, descend) {
this.push(node);
this.stack.push(node);
var ret = this.visit(node, descend ? function(){
descend.call(node);
} : noop);
if (!ret && descend) {
descend.call(node);
}
this.pop(node);
this.stack.pop();
return ret;
},
parent: function(n) {
return this.stack[this.stack.length - 2 - (n || 0)];
},
push: function (node) {
if (node instanceof AST_Lambda) {
this.directives = Object.create(this.directives);
} else if (node instanceof AST_Directive) {
this.directives[node.value] = this.directives[node.value] ? "up" : true;
}
this.stack.push(node);
},
pop: function(node) {
this.stack.pop();
if (node instanceof AST_Lambda) {
this.directives = Object.getPrototypeOf(this.directives);
}
pop: function() {
return this.stack.pop();
},
self: function() {
return this.stack[this.stack.length - 1];
@@ -969,16 +959,7 @@ TreeWalker.prototype = {
}
},
has_directive: function(type) {
var dir = this.directives[type];
if (dir) return dir;
var node = this.stack[this.stack.length - 1];
if (node instanceof AST_Scope) {
for (var i = 0; i < node.body.length; ++i) {
var st = node.body[i];
if (!(st instanceof AST_Directive)) break;
if (st.value == type) return true;
}
}
return this.find_parent(AST_Scope).has_directive(type);
},
in_boolean_context: function() {
var stack = this.stack;

View File

@@ -61,7 +61,7 @@ function Compressor(options, false_by_default) {
loops : !false_by_default,
unused : !false_by_default,
hoist_funs : !false_by_default,
keep_fargs : true,
keep_fargs : false,
keep_fnames : false,
hoist_vars : false,
if_return : !false_by_default,
@@ -111,7 +111,6 @@ merge(Compressor.prototype, {
node.DEFMETHOD("optimize", function(compressor){
var self = this;
if (self._optimized) return self;
if (compressor.has_directive("use asm")) return self;
var opt = optimizer(self, compressor);
opt._optimized = true;
if (opt === self) return opt;
@@ -490,7 +489,7 @@ merge(Compressor.prototype, {
seq = [];
};
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);
});
push_seq();
@@ -897,7 +896,6 @@ merge(Compressor.prototype, {
def(AST_Call, function(compressor){
var pure = compressor.option("pure_funcs");
if (!pure) return true;
if (typeof pure == "function") return pure(this);
return pure.indexOf(this.expression.print_to_string()) < 0;
});
@@ -991,7 +989,7 @@ merge(Compressor.prototype, {
/* -----[ optimizers ]----- */
OPT(AST_Directive, function(self, compressor){
if (compressor.has_directive(self.value) === "up") {
if (self.scope.has_directive(self.value) !== self.scope) {
return make_node(AST_EmptyStatement, self);
}
return self;
@@ -1027,7 +1025,6 @@ merge(Compressor.prototype, {
AST_Scope.DEFMETHOD("drop_unused", function(compressor){
var self = this;
if (compressor.has_directive("use asm")) return self;
if (compressor.option("unused")
&& !(self instanceof AST_Toplevel)
&& !self.uses_eval
@@ -1171,12 +1168,12 @@ merge(Compressor.prototype, {
return make_node(AST_EmptyStatement, node);
}
if (def.length == 0) {
return in_list ? MAP.splice(side_effects.body) : side_effects;
return side_effects;
}
node.definitions = def;
if (side_effects) {
side_effects.body.unshift(node);
return in_list ? MAP.splice(side_effects.body) : side_effects;
node = side_effects;
}
return node;
}
@@ -1207,10 +1204,9 @@ merge(Compressor.prototype, {
});
AST_Scope.DEFMETHOD("hoist_declarations", function(compressor){
var self = this;
if (compressor.has_directive("use asm")) return self;
var hoist_funs = compressor.option("hoist_funs");
var hoist_vars = compressor.option("hoist_vars");
var self = this;
if (hoist_funs || hoist_vars) {
var dirs = [];
var hoisted = [];
@@ -1913,11 +1909,15 @@ merge(Compressor.prototype, {
if (!compressor.option("side_effects"))
return self;
if (!self.car.has_side_effects(compressor)) {
// we shouldn't compress (1,func)(something) to
// func(something) because that changes the meaning of
// the func (becomes lexical instead of global).
var p = compressor.parent();
if (!(p instanceof AST_Call && p.expression === self)) {
// we shouldn't compress (1,eval)(something) to
// eval(something) because that changes the meaning of
// eval (becomes lexical instead of global).
var p;
if (!(self.cdr instanceof AST_SymbolRef
&& self.cdr.name == "eval"
&& self.cdr.undeclared()
&& (p = compressor.parent()) instanceof AST_Call
&& p.expression === self)) {
return self.cdr;
}
}
@@ -2031,14 +2031,15 @@ merge(Compressor.prototype, {
var commutativeOperators = makePredicate("== === != !== * & | ^");
OPT(AST_Binary, function(self, compressor){
function reverse(op, force) {
if (force || !(self.left.has_side_effects(compressor) || self.right.has_side_effects(compressor))) {
if (op) self.operator = op;
var tmp = self.left;
self.left = self.right;
self.right = tmp;
}
}
var reverse = compressor.has_directive("use asm") ? noop
: function(op, force) {
if (force || !(self.left.has_side_effects(compressor) || self.right.has_side_effects(compressor))) {
if (op) self.operator = op;
var tmp = self.left;
self.left = self.right;
self.right = tmp;
}
};
if (commutativeOperators(self.operator)) {
if (self.right instanceof AST_Constant
&& !(self.left instanceof AST_Constant)) {
@@ -2103,34 +2104,6 @@ merge(Compressor.prototype, {
}
break;
}
if (compressor.option("conditionals")) {
if (self.operator == "&&") {
var ll = self.left.evaluate(compressor);
if (ll.length > 1) {
if (ll[1]) {
compressor.warn("Condition left of && always true [{file}:{line},{col}]", self.start);
var rr = self.right.evaluate(compressor);
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);
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);
var rr = self.right.evaluate(compressor);
return rr[0];
}
}
}
}
if (compressor.option("booleans") && compressor.in_boolean_context()) switch (self.operator) {
case "&&":
var ll = self.left.evaluate(compressor);
@@ -2182,7 +2155,7 @@ merge(Compressor.prototype, {
}
break;
}
if (compressor.option("comparisons") && self.is_boolean()) {
if (compressor.option("comparisons")) {
if (!(compressor.parent() instanceof AST_Binary)
|| compressor.parent() instanceof AST_Assign) {
var negated = make_node(AST_UnaryPrefix, self, {
@@ -2257,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
&& self.right.operator == self.operator
&& (self.operator == "&&" || self.operator == "||"))
&& (self.operator == "*" || self.operator == "&&" || self.operator == "||"))
{
self.left = make_node(AST_Binary, self.left, {
operator : self.operator,
@@ -2275,15 +2247,7 @@ merge(Compressor.prototype, {
});
OPT(AST_SymbolRef, function(self, compressor){
function isLHS(symbol, parent) {
return (
parent instanceof AST_Binary &&
parent.operator === '=' &&
parent.left === symbol
);
}
if (self.undeclared() && !isLHS(self, compressor.parent())) {
if (self.undeclared()) {
var defines = compressor.option("global_defs");
if (defines && defines.hasOwnProperty(self.name)) {
return make_node_from_constant(compressor, defines[self.name], self);
@@ -2303,8 +2267,16 @@ merge(Compressor.prototype, {
OPT(AST_Infinity, function (self, compressor) {
return make_node(AST_Binary, self, {
operator : '/',
left : make_node(AST_Number, self, {value: 1}),
right : make_node(AST_Number, self, {value: 0})
left : make_node(AST_Number, null, {value: 1}),
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})
});
});
@@ -2371,7 +2343,6 @@ merge(Compressor.prototype, {
&& alternative instanceof AST_Assign
&& consequent.operator == alternative.operator
&& consequent.left.equivalent_to(alternative.left)
&& !consequent.left.has_side_effects(compressor)
) {
/*
* Stuff like this:
@@ -2392,7 +2363,6 @@ merge(Compressor.prototype, {
if (consequent instanceof AST_Call
&& alternative.TYPE === consequent.TYPE
&& consequent.args.length == alternative.args.length
&& !consequent.expression.has_side_effects(compressor)
&& consequent.expression.equivalent_to(alternative.expression)) {
if (consequent.args.length == 0) {
return make_node(AST_Seq, self, {
@@ -2510,7 +2480,7 @@ merge(Compressor.prototype, {
});
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 self;
@@ -2519,11 +2489,4 @@ merge(Compressor.prototype, {
OPT(AST_Object, literals_in_boolean_context);
OPT(AST_RegExp, literals_in_boolean_context);
OPT(AST_Return, function(self, compressor){
if (self.value instanceof AST_Undefined) {
self.value = null;
}
return self;
});
})();

View File

@@ -146,14 +146,7 @@
case "boolean":
return new (val ? AST_True : AST_False)(args);
default:
var rx = M.regex;
if (rx && rx.pattern) {
// RegExpLiteral as per ESTree AST spec
args.value = new RegExp(rx.pattern, rx.flags).toString();
} else {
// support legacy RegExp
args.value = M.regex && M.raw ? M.raw : val;
}
args.value = val;
return new AST_RegExp(args);
}
},
@@ -341,19 +334,6 @@
};
});
def_to_moz(AST_RegExp, function To_Moz_RegExpLiteral(M) {
var value = M.value;
return {
type: "Literal",
value: value,
raw: value.toString(),
regex: {
pattern: value.source,
flags: value.toString().match(/[gimuy]*$/)[0]
}
};
});
def_to_moz(AST_Constant, function To_Moz_Literal(M) {
var value = M.value;
if (typeof value === 'number' && (value < 0 || (value === 0 && 1 / value < 0))) {
@@ -363,15 +343,13 @@
prefix: true,
argument: {
type: "Literal",
value: -value,
raw: M.start.raw
value: -value
}
};
}
return {
type: "Literal",
value: value,
raw: M.start.raw
value: value
};
});
@@ -391,12 +369,6 @@
/* -----[ tools ]----- */
function raw_token(moznode) {
if (moznode.type == "Literal") {
return moznode.raw != null ? moznode.raw : moznode.value + "";
}
}
function my_start_token(moznode) {
var loc = moznode.loc, start = loc && loc.start;
var range = moznode.range;
@@ -407,8 +379,7 @@
pos : range ? range[0] : moznode.start,
endline : start && start.line,
endcol : start && start.column,
endpos : range ? range[0] : moznode.start,
raw : raw_token(moznode),
endpos : range ? range[0] : moznode.start
});
};
@@ -422,14 +393,13 @@
pos : range ? range[1] : moznode.end,
endline : end && end.line,
endcol : end && end.column,
endpos : range ? range[1] : moznode.end,
raw : raw_token(moznode),
endpos : range ? range[1] : moznode.end
});
};
function map(moztype, mytype, propmap) {
var moz_to_me = "function From_Moz_" + moztype + "(M){\n";
moz_to_me += "return new U2." + mytype.name + "({\n" +
moz_to_me += "return new " + mytype.name + "({\n" +
"start: my_start_token(M),\n" +
"end: my_end_token(M)";
@@ -472,8 +442,8 @@
//me_to_moz = parse(me_to_moz).print_to_string({ beautify: true });
//console.log(moz_to_me);
moz_to_me = new Function("U2", "my_start_token", "my_end_token", "from_moz", "return(" + moz_to_me + ")")(
exports, my_start_token, my_end_token, from_moz
moz_to_me = new Function("my_start_token", "my_end_token", "from_moz", "return(" + moz_to_me + ")")(
my_start_token, my_end_token, from_moz
);
me_to_moz = new Function("to_moz", "to_moz_block", "return(" + me_to_moz + ")")(
to_moz, to_moz_block

View File

@@ -60,7 +60,6 @@ function OutputStream(options) {
bracketize : false,
semicolons : true,
comments : false,
shebang : true,
preserve_line : false,
screw_ie8 : false,
preamble : null,
@@ -88,14 +87,13 @@ function OutputStream(options) {
function make_string(str, quote) {
var dq = 0, sq = 0;
str = str.replace(/[\\\b\f\n\r\v\t\x22\x27\u2028\u2029\0\ufeff]/g, function(s){
str = str.replace(/[\\\b\f\n\r\t\x22\x27\u2028\u2029\0\ufeff]/g, function(s){
switch (s) {
case "\\": return "\\\\";
case "\b": return "\\b";
case "\f": return "\\f";
case "\n": return "\\n";
case "\r": return "\\r";
case "\x0B": return options.screw_ie8 ? "\\v" : "\\x0B";
case "\u2028": return "\\u2028";
case "\u2029": return "\\u2029";
case '"': ++dq; return '"';
@@ -126,11 +124,8 @@ function OutputStream(options) {
function encode_string(str, quote) {
var ret = make_string(str, quote);
if (options.inline_script) {
if (options.inline_script)
ret = ret.replace(/<\x2fscript([>\/\t\n\f\r ])/gi, "<\\/script$1");
ret = ret.replace(/\x3c!--/g, "\\x3c!--");
ret = ret.replace(/--\x3e/g, "--\\x3e");
}
return ret;
};
@@ -166,8 +161,6 @@ function OutputStream(options) {
str = String(str);
var ch = str.charAt(0);
if (might_need_semicolon) {
might_need_semicolon = false;
if ((!ch || ";}".indexOf(ch) < 0) && !/[;]$/.test(last)) {
if (options.semicolons || requireSemicolonChars(ch)) {
OUTPUT += ";";
@@ -178,17 +171,12 @@ function OutputStream(options) {
current_pos++;
current_line++;
current_col = 0;
if (/^\s+$/.test(str)) {
// reset the semicolon flag, since we didn't print one
// now and might still have to later
might_need_semicolon = true;
}
}
if (!options.beautify)
might_need_space = false;
}
might_need_semicolon = false;
maybe_newline();
}
if (!options.beautify && options.preserve_line && stack[stack.length - 1]) {
@@ -382,13 +370,8 @@ function OutputStream(options) {
nodetype.DEFMETHOD("_codegen", generator);
};
var use_asm = false;
AST_Node.DEFMETHOD("print", function(stream, force_parens){
var self = this, generator = self._codegen, prev_use_asm = use_asm;
if (self instanceof AST_Directive && self.value == "use asm") {
use_asm = true;
}
var self = this, generator = self._codegen;
function doit() {
self.add_comments(stream);
self.add_source_map(stream);
@@ -401,9 +384,6 @@ function OutputStream(options) {
doit();
}
stream.pop_node();
if (self instanceof AST_Lambda) {
use_asm = prev_use_asm;
}
});
AST_Node.DEFMETHOD("print_to_string", function(options){
@@ -416,69 +396,63 @@ function OutputStream(options) {
AST_Node.DEFMETHOD("add_comments", function(output){
var c = output.option("comments"), self = this;
var start = self.start;
if (start && !start._comments_dumped) {
start._comments_dumped = true;
var comments = start.comments_before || [];
if (c) {
var start = self.start;
if (start && !start._comments_dumped) {
start._comments_dumped = true;
var comments = start.comments_before || [];
// XXX: ugly fix for https://github.com/mishoo/UglifyJS2/issues/112
// and https://github.com/mishoo/UglifyJS2/issues/372
if (self instanceof AST_Exit && self.value) {
self.value.walk(new TreeWalker(function(node){
if (node.start && node.start.comments_before) {
comments = comments.concat(node.start.comments_before);
node.start.comments_before = [];
}
if (node instanceof AST_Function ||
node instanceof AST_Array ||
node instanceof AST_Object)
{
return true; // don't go inside.
}
}));
}
if (!c) {
comments = comments.filter(function(comment) {
return comment.type == "comment5";
});
} else if (c.test) {
comments = comments.filter(function(comment){
return c.test(comment.value) || comment.type == "comment5";
});
} else if (typeof c == "function") {
comments = comments.filter(function(comment){
return c(self, comment) || comment.type == "comment5";
});
}
// Keep single line comments after nlb, after nlb
if (!output.option("beautify") && comments.length > 0 &&
/comment[134]/.test(comments[0].type) &&
output.col() !== 0 && comments[0].nlb)
{
output.print("\n");
}
comments.forEach(function(c){
if (/comment[134]/.test(c.type)) {
output.print("//" + c.value + "\n");
output.indent();
// XXX: ugly fix for https://github.com/mishoo/UglifyJS2/issues/112
// and https://github.com/mishoo/UglifyJS2/issues/372
if (self instanceof AST_Exit && self.value) {
self.value.walk(new TreeWalker(function(node){
if (node.start && node.start.comments_before) {
comments = comments.concat(node.start.comments_before);
node.start.comments_before = [];
}
if (node instanceof AST_Function ||
node instanceof AST_Array ||
node instanceof AST_Object)
{
return true; // don't go inside.
}
}));
}
else if (c.type == "comment2") {
output.print("/*" + c.value + "*/");
if (start.nlb) {
output.print("\n");
if (c.test) {
comments = comments.filter(function(comment){
return c.test(comment.value);
});
} else if (typeof c == "function") {
comments = comments.filter(function(comment){
return c(self, comment);
});
}
// Keep single line comments after nlb, after nlb
if (!output.option("beautify") && comments.length > 0 &&
/comment[134]/.test(comments[0].type) &&
output.col() !== 0 && comments[0].nlb)
{
output.print("\n");
}
comments.forEach(function(c){
if (/comment[134]/.test(c.type)) {
output.print("//" + c.value + "\n");
output.indent();
} else {
output.space();
}
}
else if (output.pos() === 0 && c.type == "comment5" && output.option("shebang")) {
output.print("#!" + c.value + "\n");
output.indent();
}
});
else if (c.type == "comment2") {
output.print("/*" + c.value + "*/");
if (start.nlb) {
output.print("\n");
output.indent();
} else {
output.space();
}
}
});
}
}
});
@@ -1057,24 +1031,16 @@ function OutputStream(options) {
output.print(self.operator);
});
DEFPRINT(AST_Binary, function(self, output){
var op = self.operator;
self.left.print(output);
if (op[0] == ">" /* ">>" ">>>" ">" ">=" */
&& self.left instanceof AST_UnaryPostfix
&& self.left.operator == "--") {
// space is mandatory to avoid outputting -->
output.print(" ");
} else {
// the space is optional depending on "beautify"
output.space();
}
output.print(op);
if ((op == "<" || op == "<<")
output.space();
output.print(self.operator);
if (self.operator == "<"
&& self.right instanceof AST_UnaryPrefix
&& self.right.operator == "!"
&& self.right.expression instanceof AST_UnaryPrefix
&& self.right.expression.operator == "--") {
// space is mandatory to avoid outputting <!--
// http://javascript.spec.whatwg.org/#comment-syntax
output.print(" ");
} else {
// the space is optional depending on "beautify"
@@ -1178,11 +1144,7 @@ function OutputStream(options) {
output.print_string(self.getValue(), self.quote);
});
DEFPRINT(AST_Number, function(self, output){
if (use_asm && self.start.raw != null) {
output.print(self.start.raw);
} else {
output.print(make_num(self.getValue()));
}
output.print(make_num(self.getValue()));
});
function regexp_safe_literal(code) {
@@ -1358,12 +1320,6 @@ function OutputStream(options) {
DEFMAP(AST_Finally, basic_sourcemap_gen);
DEFMAP(AST_Definitions, basic_sourcemap_gen);
DEFMAP(AST_Constant, basic_sourcemap_gen);
DEFMAP(AST_ObjectSetter, function(self, output){
output.add_mapping(self.start, self.key.name);
});
DEFMAP(AST_ObjectGetter, function(self, output){
output.add_mapping(self.start, self.key.name);
});
DEFMAP(AST_ObjectProperty, function(self, output){
output.add_mapping(self.start, self.key);
});

View File

@@ -59,6 +59,7 @@ var OPERATOR_CHARS = makePredicate(characters("+-*&%=<>!?|~^"));
var RE_HEX_NUMBER = /^0x[0-9a-f]+$/i;
var RE_OCT_NUMBER = /^0[0-7]+$/;
var RE_DEC_NUMBER = /^\d*\.?\d*(?:e[+-]?\d*(?:\d\.?|\.?\d)\d*)?$/i;
var OPERATORS = makePredicate([
"in",
@@ -107,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("[{(,.;:"));
@@ -181,15 +182,13 @@ function parse_js_number(num) {
return parseInt(num.substr(2), 16);
} else if (RE_OCT_NUMBER.test(num)) {
return parseInt(num.substr(1), 8);
} else {
var val = parseFloat(num);
if (val == num) return val;
} else if (RE_DEC_NUMBER.test(num)) {
return parseFloat(num);
}
};
function JS_Parse_Error(message, filename, line, col, pos) {
function JS_Parse_Error(message, line, col, pos) {
this.message = message;
this.filename = filename;
this.line = line;
this.col = col;
this.pos = pos;
@@ -201,7 +200,7 @@ JS_Parse_Error.prototype.toString = function() {
};
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) {
@@ -210,10 +209,10 @@ function is_token(token, type, val) {
var EX_EOF = {};
function tokenizer($TEXT, filename, html5_comments, shebang) {
function tokenizer($TEXT, filename, html5_comments) {
var S = {
text : $TEXT,
text : $TEXT.replace(/\uFEFF/g, ''),
filename : filename,
pos : 0,
tokpos : 0,
@@ -285,9 +284,6 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
nlb : S.newline_before,
file : filename
};
if (/^(?:num|string|regexp)$/i.test(type)) {
ret.raw = $TEXT.substring(ret.pos, ret.endpos);
}
if (!is_comment) {
ret.comments_before = S.comments_before;
S.comments_before = [];
@@ -301,8 +297,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
};
function skip_whitespace() {
var ch;
while (WHITESPACE_CHARS(ch = peek()) || ch == "\u2028" || ch == "\u2029")
while (WHITESPACE_CHARS(peek()))
next();
};
@@ -357,13 +352,8 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
case 120 : return String.fromCharCode(hex_bytes(2)); // \x
case 117 : return String.fromCharCode(hex_bytes(4)); // \u
case 10 : return ""; // newline
case 13 : // \r
if (peek() == "\n") { // DOS newline
next(true, in_string);
return "";
}
default : return ch;
}
return ch;
};
function hex_bytes(n) {
@@ -380,7 +370,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
var read_string = with_eof_error("Unterminated string constant", function(quote_char){
var quote = next(), ret = "";
for (;;) {
var ch = next(true, true);
var ch = next(true);
if (ch == "\\") {
// read OctalEscapeSequence (XXX: deprecated if "strict mode")
// https://github.com/mishoo/UglifyJS/issues/178
@@ -483,11 +473,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
regexp += ch;
}
var mods = read_name();
try {
return token("regexp", new RegExp(regexp, mods));
} catch(e) {
parse_error(e.message);
}
return token("regexp", new RegExp(regexp, mods));
});
function read_operator(prefix) {
@@ -571,13 +557,6 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
if (PUNC_CHARS(ch)) return token("punc", next());
if (OPERATOR_CHARS(ch)) return read_operator();
if (code == 92 || is_identifier_start(code)) return read_word();
if (shebang) {
if (S.pos == 0 && looking_at("#!")) {
forward(2);
return skip_line_comment("comment5");
}
}
parse_error("Unexpected character '" + ch + "'");
};
@@ -647,13 +626,12 @@ function parse($TEXT, options) {
expression : false,
html5_comments : true,
bare_returns : false,
shebang : true,
});
var S = {
input : (typeof $TEXT == "string"
? tokenizer($TEXT, options.filename,
options.html5_comments, options.shebang)
options.html5_comments)
: $TEXT),
token : null,
prev : null,
@@ -1125,7 +1103,7 @@ function parse($TEXT, options) {
});
};
var new_ = function(allow_calls) {
var new_ = function() {
var start = S.token;
expect_token("operator", "new");
var newexp = expr_atom(false), args;
@@ -1140,7 +1118,7 @@ function parse($TEXT, options) {
expression : newexp,
args : args,
end : prev()
}), allow_calls);
}), true);
};
function as_atom_node() {
@@ -1184,7 +1162,7 @@ function parse($TEXT, options) {
var expr_atom = function(allow_calls) {
if (is("operator", "new")) {
return new_(allow_calls);
return new_();
}
var start = S.token;
if (is("punc")) {

View File

@@ -1,223 +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 = [];
var unmangleable = [];
// 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) {
node.key = mangle(node.key);
}
else if (node instanceof AST_ObjectProperty) {
// setter or getter
node.key.name = mangle(node.key.name);
}
else if (node instanceof AST_Dot) {
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 (unmangleable.indexOf(name) >= 0) return false;
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);
if (!should_mangle(name)) {
push_uniq(unmangleable, name);
}
}
function mangle(name) {
if (!should_mangle(name)) {
return 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) {
node.value = mangle(node.value);
}
else if (node instanceof AST_Conditional) {
node.consequent = mangleStrings(node.consequent);
node.alternative = mangleStrings(node.alternative);
}
return node;
}));
}
}

View File

@@ -67,32 +67,23 @@ SymbolDef.prototype = {
|| this.orig[0] instanceof AST_SymbolDefun));
},
mangle: function(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)) {
if (!this.mangled_name && !this.unmangleable(options)) {
var s = this.scope;
if (!options.screw_ie8 && this.orig[0] instanceof AST_SymbolLambda)
s = s.parent_scope;
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){
options = defaults(options, {
screw_ie8: false,
cache: null
screw_ie8: false
});
// pass 1: setup scope chaining and handle definitions
var self = this;
var scope = self.parent_scope = null;
var labels = new Dictionary();
var defun = null;
var nesting = 0;
var tw = new TreeWalker(function(node, descend){
@@ -109,24 +100,16 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
node.init_scope_vars(nesting);
var save_scope = node.parent_scope = scope;
var save_defun = defun;
var save_labels = labels;
defun = scope = node;
labels = new Dictionary();
++nesting; descend(); --nesting;
scope = save_scope;
defun = save_defun;
labels = save_labels;
return true; // don't descend again in TreeWalker
}
if (node instanceof AST_LabeledStatement) {
var l = node.label;
if (labels.has(l.name)) {
throw new Error(string_template("Label {name} defined twice", l));
}
labels.set(l.name, l);
descend();
labels.del(l.name);
return true; // no descend again
if (node instanceof AST_Directive) {
node.scope = scope;
push_uniq(scope.directives, node.value);
return true;
}
if (node instanceof AST_With) {
for (var s = scope; s; s = s.parent_scope)
@@ -136,10 +119,6 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
if (node instanceof AST_Symbol) {
node.scope = scope;
}
if (node instanceof AST_Label) {
node.thedef = node;
node.references = [];
}
if (node instanceof AST_SymbolLambda) {
defun.def_function(node);
}
@@ -161,15 +140,6 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
(options.screw_ie8 ? scope : defun)
.def_variable(node);
}
else if (node instanceof AST_LabelRef) {
var sym = labels.get(node.name);
if (!sym) throw new Error(string_template("Undefined label {name} [{line},{col}]", {
name: node.name,
line: node.start.line,
col: node.start.col
}));
node.thedef = sym;
}
});
self.walk(tw);
@@ -184,10 +154,6 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
func = prev_func;
return true;
}
if (node instanceof AST_LoopControl && node.label) {
node.label.thedef.references.push(node);
return true;
}
if (node instanceof AST_SymbolRef) {
var name = node.name;
var sym = node.scope.find_variable(name);
@@ -217,13 +183,10 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
}
});
self.walk(tw);
if (options.cache) {
this.cname = options.cache.cname;
}
});
AST_Scope.DEFMETHOD("init_scope_vars", function(nesting){
this.directives = []; // contains the directives defined in this scope, i.e. "use strict"
this.variables = new Dictionary(); // map name to AST_SymbolVar (variables defined in this scope; includes functions)
this.functions = new Dictionary(); // map name to AST_SymbolDefun (functions defined in this scope)
this.uses_with = false; // will be set to true if this or some nested scope uses the `with` statement
@@ -234,6 +197,10 @@ AST_Scope.DEFMETHOD("init_scope_vars", function(nesting){
this.nesting = nesting; // the nesting level of this scope (0 means toplevel)
});
AST_Scope.DEFMETHOD("strict", function(){
return this.has_directive("use strict");
});
AST_Lambda.DEFMETHOD("init_scope_vars", function(){
AST_Scope.prototype.init_scope_vars.apply(this, arguments);
this.uses_arguments = false;
@@ -257,6 +224,11 @@ AST_Scope.DEFMETHOD("find_variable", function(name){
|| (this.parent_scope && this.parent_scope.find_variable(name));
});
AST_Scope.DEFMETHOD("has_directive", function(value){
return this.parent_scope && this.parent_scope.has_directive(value)
|| (this.directives.indexOf(value) >= 0 ? this : null);
});
AST_Scope.DEFMETHOD("def_function", function(symbol){
this.functions.set(symbol.name, this.def_variable(symbol));
});
@@ -372,15 +344,6 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options){
// the AST_SymbolDeclaration that it points to).
var lname = -1;
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){
if (node instanceof AST_LabeledStatement) {
// lname is incremented when we get to the AST_Label
@@ -415,10 +378,6 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options){
});
this.walk(tw);
to_mangle.forEach(function(def){ def.mangle(options) });
if (options.cache) {
options.cache.cname = this.cname;
}
});
AST_Toplevel.DEFMETHOD("compute_char_frequency", function(options){

View File

@@ -70,7 +70,7 @@ TreeTransformer.prototype = new TreeWalker;
if (y !== undefined) x = y;
}
}
tw.pop(this);
tw.pop();
return x;
});
};

View File

@@ -106,12 +106,10 @@ function defaults(args, defs, croak) {
};
function merge(obj, ext) {
var count = 0;
for (var i in ext) if (ext.hasOwnProperty(i)) {
obj[i] = ext[i];
count++;
}
return count;
return obj;
};
function noop() {};
@@ -300,11 +298,5 @@ Dictionary.prototype = {
for (var i in this._values)
ret.push(f(this._values[i], i.substr(1)));
return ret;
},
toObject: function() { return this._values }
};
Dictionary.fromObject = function(obj) {
var dict = new Dictionary();
dict._size = merge(dict._values, obj);
return dict;
}
};

128
npm-shrinkwrap.json generated
View File

@@ -1,128 +0,0 @@
{
"name": "uglify-js",
"version": "2.4.24",
"dependencies": {
"abbrev": {
"version": "1.0.7",
"from": "abbrev@>=1.0.0 <2.0.0",
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.7.tgz"
},
"amdefine": {
"version": "1.0.0",
"from": "amdefine@>=0.0.4",
"resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.0.tgz"
},
"async": {
"version": "0.2.10",
"from": "async@>=0.2.6 <0.3.0",
"resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz"
},
"camelcase": {
"version": "1.2.1",
"from": "camelcase@>=1.0.2 <2.0.0",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz"
},
"decamelize": {
"version": "1.0.0",
"from": "decamelize@>=1.0.0 <2.0.0",
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.0.0.tgz"
},
"deep-is": {
"version": "0.1.3",
"from": "deep-is@>=0.1.2 <0.2.0",
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz"
},
"esprima": {
"version": "1.1.1",
"from": "esprima@>=1.1.1 <1.2.0",
"resolved": "https://registry.npmjs.org/esprima/-/esprima-1.1.1.tgz"
},
"estraverse": {
"version": "1.5.1",
"from": "estraverse@>=1.5.1 <1.6.0",
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.5.1.tgz"
},
"esutils": {
"version": "1.0.0",
"from": "esutils@>=1.0.0 <1.1.0",
"resolved": "https://registry.npmjs.org/esutils/-/esutils-1.0.0.tgz"
},
"fast-levenshtein": {
"version": "1.0.7",
"from": "fast-levenshtein@>=1.0.0 <1.1.0",
"resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-1.0.7.tgz"
},
"levn": {
"version": "0.2.5",
"from": "levn@>=0.2.5 <0.3.0",
"resolved": "https://registry.npmjs.org/levn/-/levn-0.2.5.tgz"
},
"nopt": {
"version": "2.1.2",
"from": "nopt@>=2.1.2 <2.2.0",
"resolved": "https://registry.npmjs.org/nopt/-/nopt-2.1.2.tgz"
},
"optionator": {
"version": "0.5.0",
"from": "optionator@>=0.5.0 <0.6.0",
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.5.0.tgz"
},
"prelude-ls": {
"version": "1.1.2",
"from": "prelude-ls@>=1.1.1 <1.2.0",
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz"
},
"reflect": {
"version": "0.1.3",
"from": "git://github.com/zaach/reflect.js.git",
"resolved": "git://github.com/zaach/reflect.js.git#286bcd79661c96ecc404357d3c0e35fdb54a6967"
},
"source-map": {
"version": "0.5.1",
"from": "source-map@>=0.5.1 <0.6.0",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.1.tgz"
},
"type-check": {
"version": "0.3.1",
"from": "type-check@>=0.3.1 <0.4.0",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.1.tgz"
},
"uglify-js": {
"version": "2.4.24",
"from": "git://github.com/mishoo/UglifyJS2.git",
"resolved": "git://github.com/mishoo/UglifyJS2.git#2a06c7758e24a64740473c8031eafbb7fefa213f",
"dependencies": {
"source-map": {
"version": "0.1.34",
"from": "source-map@0.1.34",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.34.tgz"
}
}
},
"uglify-to-browserify": {
"version": "1.0.2",
"from": "uglify-to-browserify@>=1.0.0 <1.1.0",
"resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz"
},
"window-size": {
"version": "0.1.0",
"from": "window-size@0.1.0",
"resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz"
},
"wordwrap": {
"version": "0.0.2",
"from": "wordwrap@0.0.2",
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz"
},
"yargs": {
"version": "3.10.0",
"from": "yargs@>=3.10.0 <3.11.0",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz"
},
"zeparser": {
"version": "0.0.7",
"from": "git://github.com/qfox/ZeParser.git",
"resolved": "git://github.com/qfox/ZeParser.git#c99240c5ba7054c467733800ff38265958a2dda9"
}
}
}

View File

@@ -1,52 +1,37 @@
{
"name": "uglify-js",
"description": "JavaScript parser, mangler/compressor and beautifier toolkit",
"homepage": "http://lisperator.net/uglifyjs",
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
"license": "BSD-2-Clause",
"version": "2.6.0",
"engines": {
"node": ">=0.8.0"
},
"maintainers": [
"Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)"
],
"repository": {
"type": "git",
"url": "https://github.com/mishoo/UglifyJS2.git"
},
"bugs": {
"url": "https://github.com/mishoo/UglifyJS2/issues"
},
"main": "tools/node.js",
"bin": {
"uglifyjs": "bin/uglifyjs"
},
"files": [
"bin",
"lib",
"tools",
"LICENSE"
],
"dependencies": {
"async": "~0.2.6",
"source-map": "~0.5.1",
"uglify-to-browserify": "~1.0.0",
"yargs": "~3.10.0"
},
"devDependencies": {
"acorn": "~0.6.0",
"escodegen": "~1.3.3",
"esfuzz": "~0.3.1",
"estraverse": "~1.5.1"
},
"browserify": {
"transform": [
"uglify-to-browserify"
]
},
"scripts": {
"shrinkwrap": "rm ./npm-shrinkwrap.json; rm -rf ./node_modules; npm i && npm shrinkwrap && npm outdated",
"test": "node test/run-tests.js"
}
"homepage": "http://lisperator.net/uglifyjs",
"main": "tools/node.js",
"version": "2.4.17",
"engines": { "node" : ">=0.4.0" },
"maintainers": [{
"name": "Mihai Bazon",
"email": "mihai.bazon@gmail.com",
"web": "http://lisperator.net/"
}],
"repository": {
"type": "git",
"url": "https://github.com/mishoo/UglifyJS2.git"
},
"dependencies": {
"async" : "~0.2.6",
"source-map" : "0.1.34",
"yargs": "~1.3.3",
"uglify-to-browserify": "~1.0.0"
},
"devDependencies": {
"acorn": "~0.6.0",
"escodegen": "~1.3.3",
"esfuzz": "~0.3.1",
"estraverse": "~1.5.1"
},
"browserify": {
"transform": [ "uglify-to-browserify" ]
},
"bin": {
"uglifyjs" : "bin/uglifyjs"
},
"license": "BSD",
"scripts": {"test": "node test/run-tests.js"}
}

View File

@@ -1,106 +0,0 @@
asm_mixed: {
options = {
sequences : true,
properties : true,
dead_code : true,
drop_debugger : true,
conditionals : true,
comparisons : true,
evaluate : true,
booleans : true,
loops : true,
unused : true,
hoist_funs : true,
keep_fargs : true,
keep_fnames : false,
hoist_vars : true,
if_return : true,
join_vars : true,
cascade : true,
side_effects : true,
negate_iife : true
};
input: {
// adapted from http://asmjs.org/spec/latest/
function asm_GeometricMean(stdlib, foreign, buffer) {
"use asm";
var exp = stdlib.Math.exp;
var log = stdlib.Math.log;
var values = new stdlib.Float64Array(buffer);
function logSum(start, end) {
start = start|0;
end = end|0;
var sum = 0.0, p = 0, q = 0;
// asm.js forces byte addressing of the heap by requiring shifting by 3
for (p = start << 3, q = end << 3; (p|0) < (q|0); p = (p + 8)|0) {
sum = sum + +log(values[p>>3]);
}
return +sum;
}
function geometricMean(start, end) {
start = start|0;
end = end|0;
return +exp(+logSum(start, end) / +((end - start)|0));
}
return { geometricMean: geometricMean };
}
function no_asm_GeometricMean(stdlib, foreign, buffer) {
var exp = stdlib.Math.exp;
var log = stdlib.Math.log;
var values = new stdlib.Float64Array(buffer);
function logSum(start, end) {
start = start|0;
end = end|0;
var sum = 0.0, p = 0, q = 0;
// asm.js forces byte addressing of the heap by requiring shifting by 3
for (p = start << 3, q = end << 3; (p|0) < (q|0); p = (p + 8)|0) {
sum = sum + +log(values[p>>3]);
}
return +sum;
}
function geometricMean(start, end) {
start = start|0;
end = end|0;
return +exp(+logSum(start, end) / +((end - start)|0));
}
return { geometricMean: geometricMean };
}
}
expect: {
function asm_GeometricMean(stdlib, foreign, buffer) {
"use asm";
var exp = stdlib.Math.exp;
var log = stdlib.Math.log;
var values = new stdlib.Float64Array(buffer);
function logSum(start, end) {
start = start | 0;
end = end | 0;
var sum = 0.0, p = 0, q = 0;
for (p = start << 3, q = end << 3; (p | 0) < (q | 0); p = p + 8 | 0) {
sum = sum + +log(values[p >> 3]);
}
return +sum;
}
function geometricMean(start, end) {
start = start | 0;
end = end | 0;
return +exp(+logSum(start, end) / +(end - start | 0));
}
return { geometricMean: geometricMean };
}
function no_asm_GeometricMean(stdlib, foreign, buffer) {
function logSum(start, end) {
start = 0 | start, end = 0 | end;
var sum = 0, p = 0, q = 0;
for (p = start << 3, q = end << 3; (0 | q) > (0 | p); p = p + 8 | 0) sum += +log(values[p >> 3]);
return +sum;
}
function geometricMean(start, end) {
return start = 0 | start, end = 0 | end, +exp(+logSum(start, end) / +(end - start | 0));
}
var exp = stdlib.Math.exp, log = stdlib.Math.log, values = new stdlib.Float64Array(buffer);
return { geometricMean: geometricMean };
}
}
}

View File

@@ -86,9 +86,7 @@ ifs_4: {
x(foo)[10].bar.baz = something_else();
}
expect: {
foo && bar
? x(foo)[10].bar.baz = something()
: x(foo)[10].bar.baz = something_else();
x(foo)[10].bar.baz = (foo && bar) ? something() : something_else();
}
}
@@ -135,7 +133,6 @@ ifs_6: {
comparisons: true
};
input: {
var x;
if (!foo && !bar && !baz && !boo) {
x = 10;
} else {
@@ -143,7 +140,6 @@ ifs_6: {
}
}
expect: {
var x;
x = foo || bar || baz || boo ? 20 : 10;
}
}
@@ -153,7 +149,6 @@ cond_1: {
conditionals: true
};
input: {
var do_something; // if undeclared it's assumed to have side-effects
if (some_condition()) {
do_something(x);
} else {
@@ -161,7 +156,6 @@ cond_1: {
}
}
expect: {
var do_something;
do_something(some_condition() ? x : y);
}
}
@@ -171,7 +165,6 @@ cond_2: {
conditionals: true
};
input: {
var x, FooBar;
if (some_condition()) {
x = new FooBar(1);
} else {
@@ -179,7 +172,6 @@ cond_2: {
}
}
expect: {
var x, FooBar;
x = new FooBar(some_condition() ? 1 : 2);
}
}
@@ -189,7 +181,6 @@ cond_3: {
conditionals: true
};
input: {
var FooBar;
if (some_condition()) {
new FooBar(1);
} else {
@@ -197,7 +188,6 @@ cond_3: {
}
}
expect: {
var FooBar;
some_condition() ? new FooBar(1) : FooBar(2);
}
}
@@ -207,7 +197,6 @@ cond_4: {
conditionals: true
};
input: {
var do_something;
if (some_condition()) {
do_something();
} else {
@@ -215,7 +204,6 @@ cond_4: {
}
}
expect: {
var do_something;
some_condition(), do_something();
}
}
@@ -315,7 +303,6 @@ cond_7_1: {
evaluate : true
};
input: {
var x;
// access to global should be assumed to have side effects
if (y) {
x = 1+1;
@@ -324,7 +311,6 @@ cond_7_1: {
}
}
expect: {
var x;
x = (y, 2);
}
}
@@ -335,7 +321,6 @@ cond_8: {
evaluate : true
};
input: {
var a;
// compress these
a = condition ? true : false;
@@ -370,7 +355,6 @@ cond_8: {
}
expect: {
var a;
a = !!condition;
a = !condition;
a = !!condition();
@@ -383,164 +367,4 @@ cond_8: {
a = condition ? 0 : true;
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;
}
}
}

View File

@@ -1,5 +1,5 @@
unused_funarg_1: {
options = { unused: true, keep_fargs: false };
options = { unused: true };
input: {
function f(a, b, c, d, e) {
return a + b;
@@ -13,7 +13,7 @@ unused_funarg_1: {
}
unused_funarg_2: {
options = { unused: true, keep_fargs: false };
options = { unused: true };
input: {
function f(a, b, c, d, e) {
return a + c;
@@ -165,7 +165,7 @@ used_var_in_catch: {
}
keep_fnames: {
options = { unused: true, keep_fnames: true, unsafe: true };
options = { unused: true, keep_fnames: true };
input: {
function foo() {
return function bar(baz) {};
@@ -173,7 +173,7 @@ keep_fnames: {
}
expect: {
function foo() {
return function bar(baz) {};
return function bar() {};
}
}
}
}

View File

@@ -1,71 +0,0 @@
html_comment_in_expression: {
input: {
function f(a, b, x, y) { return a < !--b && x-- > y; }
}
expect_exact: "function f(a,b,x,y){return a< !--b&&x-- >y}";
}
html_comment_in_less_than: {
input: {
function f(a, b) { return a < !--b; }
}
expect_exact: "function f(a,b){return a< !--b}";
}
html_comment_in_left_shift: {
input: {
function f(a, b) { return a << !--b; }
}
expect_exact: "function f(a,b){return a<< !--b}";
}
html_comment_in_right_shift: {
input: {
function f(a, b) { return a-- >> b; }
}
expect_exact: "function f(a,b){return a-- >>b}";
}
html_comment_in_zero_fill_right_shift: {
input: {
function f(a, b) { return a-- >>> b; }
}
expect_exact: "function f(a,b){return a-- >>>b}";
}
html_comment_in_greater_than: {
input: {
function f(a, b) { return a-- > b; }
}
expect_exact: "function f(a,b){return a-- >b}";
}
html_comment_in_greater_than_or_equal: {
input: {
function f(a, b) { return a-- >= b; }
}
expect_exact: "function f(a,b){return a-- >=b}";
}
html_comment_in_right_shift_assign: {
input: {
// Note: illegal javascript
function f(a, b) { return a-- >>= b; }
}
expect_exact: "function f(a,b){return a-- >>=b}";
}
html_comment_in_zero_fill_right_shift_assign: {
input: {
// Note: illegal javascript
function f(a, b) { return a-- >>>= b; }
}
expect_exact: "function f(a,b){return a-- >>>=b}";
}
html_comment_in_string_literal: {
input: {
function f() { return "<!--HTML-->comment in<!--string literal-->"; }
}
expect_exact: 'function f(){return"\\x3c!--HTML--\\x3ecomment in\\x3c!--string literal--\\x3e"}';
}

View File

@@ -1,11 +0,0 @@
do_not_update_lhs: {
options = { global_defs: { DEBUG: false } };
input: { DEBUG = false; }
expect: { DEBUG = false; }
}
do_update_rhs: {
options = { global_defs: { DEBUG: false } };
input: { MY_DEBUG = DEBUG; }
expect: { MY_DEBUG = false; }
}

View File

@@ -6,7 +6,7 @@ NaN_and_Infinity_must_have_parens: {
}
expect: {
(1/0).toString();
NaN.toString(); // transformation to 0/0 dropped
(0/0).toString();
}
}

View File

@@ -1,37 +0,0 @@
dont_reuse_prop: {
mangle_props = {
regex: /asd/
};
input: {
var obj = {};
obj.a = 123;
obj.asd = 256;
console.log(obj.a);
}
expect: {
var obj = {};
obj.a = 123;
obj.b = 256;
console.log(obj.a);
}
}
unmangleable_props_should_always_be_reserved: {
mangle_props = {
regex: /asd/
};
input: {
var obj = {};
obj.asd = 256;
obj.a = 123;
console.log(obj.a);
}
expect: {
var obj = {};
obj.b = 256;
obj.a = 123;
console.log(obj.a);
}
}

View File

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

View File

@@ -1,23 +0,0 @@
remove_redundant_sequence_items: {
options = { side_effects: true };
input: {
(0, 1, logThis)();
(0, 1, _decorators.logThis)();
}
expect: {
(0, logThis)();
(0, _decorators.logThis)();
}
}
dont_remove_lexical_binding_sequence: {
options = { side_effects: true };
input: {
(0, logThis)();
(0, _decorators.logThis)();
}
expect: {
(0, logThis)();
(0, _decorators.logThis)();
}
}

View File

@@ -1,12 +0,0 @@
new_statement: {
input: {
new x(1);
new x(1)(2);
new x(1)(2)(3);
new new x(1);
new new x(1)(2);
new (new x(1))(2);
(new new x(1))(2);
}
expect_exact: "new x(1);new x(1)(2);new x(1)(2)(3);new new x(1);new new x(1)(2);new new x(1)(2);(new new x(1))(2);"
}

View File

@@ -1,124 +0,0 @@
return_undefined: {
options = {
sequences : false,
if_return : true,
evaluate : true,
dead_code : true,
conditionals : true,
comparisons : true,
booleans : true,
unused : true,
side_effects : true,
properties : true,
drop_debugger : true,
loops : true,
hoist_funs : true,
keep_fargs : true,
keep_fnames : false,
hoist_vars : true,
join_vars : true,
cascade : true,
negate_iife : true
};
input: {
function f0() {
}
function f1() {
return undefined;
}
function f2() {
return void 0;
}
function f3() {
return void 123;
}
function f4() {
return;
}
function f5(a, b) {
console.log(a, b);
baz(a);
return;
}
function f6(a, b) {
console.log(a, b);
if (a) {
foo(b);
baz(a);
return a + b;
}
return undefined;
}
function f7(a, b) {
console.log(a, b);
if (a) {
foo(b);
baz(a);
return void 0;
}
return a + b;
}
function f8(a, b) {
foo(a);
bar(b);
return void 0;
}
function f9(a, b) {
foo(a);
bar(b);
return undefined;
}
function f10() {
return false;
}
function f11() {
return null;
}
function f12() {
return 0;
}
}
expect: {
function f0() {}
function f1() {}
function f2() {}
function f3() {}
function f4() {}
function f5(a, b) {
console.log(a, b);
baz(a);
}
function f6(a, b) {
console.log(a, b);
if (a) {
foo(b);
baz(a);
return a + b;
}
}
function f7(a, b) {
console.log(a, b);
if (!a)
return a + b;
foo(b);
baz(a);
}
function f8(a, b) {
foo(a);
bar(b);
}
function f9(a, b) {
foo(a);
bar(b);
}
function f10() {
return !1;
}
function f11() {
return null;
}
function f12() {
return 0;
}
}
}

View File

@@ -1,18 +0,0 @@
do_screw: {
options = { screw_ie8: true };
beautify = {
screw_ie8: true,
ascii_only: true
};
input: f("\v");
expect_exact: 'f("\\v");';
}
dont_screw: {
options = { screw_ie8: false };
beautify = { screw_ie8: false, ascii_only: true };
input: f("\v");
expect_exact: 'f("\\x0B");';
}

View File

@@ -100,4 +100,4 @@ module.exports = function(options) {
}
process.stdout.write(prefix + "Probability of error is less than " + (100 / options.iterations) + "%, stopping.\n");
};
};

View File

@@ -4,6 +4,7 @@ var U = require("../tools/node");
var path = require("path");
var fs = require("fs");
var assert = require("assert");
var sys = require("util");
var tests_dir = path.dirname(module.filename);
var failures = 0;
@@ -11,14 +12,11 @@ var failed_files = {};
run_compress_tests();
if (failures) {
console.error("\n!!! Failed " + failures + " test cases.");
console.error("!!! " + Object.keys(failed_files).join(", "));
sys.error("\n!!! Failed " + failures + " test cases.");
sys.error("!!! " + Object.keys(failed_files).join(", "));
process.exit(1);
}
var run_sourcemaps_tests = require('./sourcemaps');
run_sourcemaps_tests();
var run_ast_conversion_tests = require("./mozilla-ast");
run_ast_conversion_tests({
@@ -33,7 +31,7 @@ function tmpl() {
function log() {
var txt = tmpl.apply(this, arguments);
console.log("%s", txt);
sys.puts(txt);
}
function log_directory(dir) {
@@ -86,21 +84,12 @@ function run_compress_tests() {
warnings: false
});
var cmp = new U.Compressor(options, true);
var output_options = test.beautify || {};
var expect;
if (test.expect) {
expect = make_code(as_toplevel(test.expect), output_options);
} else {
expect = test.expect_exact;
}
var expect = make_code(as_toplevel(test.expect), false);
var input = as_toplevel(test.input);
var input_code = make_code(test.input, { beautify: true });
if (test.mangle_props) {
input = U.mangle_properties(input, test.mangle_props);
}
var input_code = make_code(test.input);
var output = input.transform(cmp);
output.figure_out_scope();
output = make_code(output, output_options);
output = make_code(output, false);
if (expect != output) {
log("!!! failed\n---INPUT---\n{input}\n---OUTPUT---\n{output}\n---EXPECTED---\n{expected}\n\n", {
input: input_code,
@@ -144,7 +133,7 @@ function parse_test(file) {
file: file,
line: node.start.line,
col: node.start.col,
code: make_code(node, { beautify: false })
code: make_code(node, false)
}));
}
@@ -161,7 +150,7 @@ function parse_test(file) {
}
if (node instanceof U.AST_LabeledStatement) {
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}]", {
name: node.label.name,
line: node.label.start.line,
@@ -173,16 +162,7 @@ function parse_test(file) {
if (stat.body.length == 1) stat = stat.body[0];
else if (stat.body.length == 0) stat = new U.AST_EmptyStatement();
}
if (node.label.name === "expect_exact") {
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;
}
test[node.label.name] = stat;
return true;
}
});
@@ -191,15 +171,15 @@ function parse_test(file) {
};
}
function make_code(ast, options) {
options.inline_script = true;
var stream = U.OutputStream(options);
function make_code(ast, beautify) {
if (arguments.length == 1) beautify = true;
var stream = U.OutputStream({ beautify: beautify });
ast.print(stream);
return stream.get();
}
function evaluate(code) {
if (code instanceof U.AST_Node)
code = make_code(code, { beautify: true });
code = make_code(code);
return new Function("return(" + code + ")")();
}

View File

@@ -1,40 +0,0 @@
var UglifyJS = require("..");
var ok = require("assert");
module.exports = function () {
console.log("--- Sourcemaps tests");
var basic = source_map([
'var x = 1 + 1;'
].join('\n'));
ok.equal(basic.version, 3);
ok.deepEqual(basic.names, ['x']);
var issue836 = source_map([
"({",
" get enabled() {",
" return 3;",
" },",
" set enabled(x) {",
" ;",
" }",
"});",
].join("\n"));
ok.deepEqual(issue836.names, ['enabled', 'x']);
}
function source_map(js) {
var source_map = UglifyJS.SourceMap();
var stream = UglifyJS.OutputStream({ source_map: source_map });
var parsed = UglifyJS.parse(js);
parsed.print(stream);
return JSON.parse(source_map.toString());
}
// Run standalone
if (module.parent === null) {
module.exports();
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,17 +0,0 @@
exports["Compressor"] = Compressor;
exports["DefaultsError"] = DefaultsError;
exports["Dictionary"] = Dictionary;
exports["JS_Parse_Error"] = JS_Parse_Error;
exports["MAP"] = MAP;
exports["OutputStream"] = OutputStream;
exports["SourceMap"] = SourceMap;
exports["TreeTransformer"] = TreeTransformer;
exports["TreeWalker"] = TreeWalker;
exports["base54"] = base54;
exports["defaults"] = defaults;
exports["mangle_properties"] = mangle_properties;
exports["merge"] = merge;
exports["parse"] = parse;
exports["push_uniq"] = push_uniq;
exports["string_template"] = string_template;
exports["is_identifier"] = is_identifier;

View File

@@ -1,5 +1,28 @@
var path = require("path");
var fs = require("fs");
var vm = require("vm");
var sys = require("util");
var UglifyJS = vm.createContext({
sys : sys,
console : console,
process : process,
Buffer : Buffer,
MOZ_SourceMap : require("source-map")
});
function load_global(file) {
file = path.resolve(path.dirname(module.filename), file);
try {
var code = fs.readFileSync(file, "utf8");
return vm.runInContext(code, UglifyJS, file);
} catch(ex) {
// XXX: in case of a syntax error, the message is kinda
// useless. (no location information).
sys.debug("ERROR in file: " + file + " / " + ex);
process.exit(1);
}
};
var FILES = exports.FILES = [
"../lib/utils.js",
@@ -10,26 +33,24 @@ var FILES = exports.FILES = [
"../lib/output.js",
"../lib/compress.js",
"../lib/sourcemap.js",
"../lib/mozilla-ast.js",
"../lib/propmangle.js",
"./exports.js",
"../lib/mozilla-ast.js"
].map(function(file){
return fs.realpathSync(path.join(path.dirname(__filename), file));
});
var UglifyJS = exports;
new Function("MOZ_SourceMap", "exports", FILES.map(function(file){
return fs.readFileSync(file, "utf8");
}).join("\n\n"))(
require("source-map"),
UglifyJS
);
FILES.forEach(load_global);
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.
for (var i in UglifyJS) {
if (UglifyJS.hasOwnProperty(i)) {
exports[i] = UglifyJS[i];
}
}
exports.minify = function(files, options) {
options = UglifyJS.defaults(options, {
spidermonkey : false,
@@ -53,20 +74,17 @@ exports.minify = function(files, options) {
} else {
if (typeof files == "string")
files = [ files ];
files.forEach(function(file, i){
files.forEach(function(file){
var code = options.fromString
? file
: fs.readFileSync(file, "utf8");
sourcesContent[file] = code;
toplevel = UglifyJS.parse(code, {
filename: options.fromString ? i : file,
filename: options.fromString ? "?" : file,
toplevel: toplevel
});
});
}
if (options.wrap) {
toplevel = toplevel.wrap_commonjs(options.wrap, options.exportAll);
}
// 2. compress
if (options.compress) {
@@ -111,7 +129,7 @@ exports.minify = function(files, options) {
var stream = UglifyJS.OutputStream(output);
toplevel.print(stream);
if (options.outSourceMap && "string" === typeof options.outSourceMap) {
if(options.outSourceMap){
stream += "\n//# sourceMappingURL=" + options.outSourceMap;
}
@@ -174,63 +192,3 @@ exports.describe_ast = function() {
doitem(UglifyJS.AST_Node);
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");
}
};

View File

@@ -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>