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,9 +1,6 @@
|
|||||||
language: node_js
|
language: node_js
|
||||||
before_install: "npm install -g npm"
|
before_install: "npm install -g npm"
|
||||||
node_js:
|
node_js:
|
||||||
- "0.12"
|
- "0.8"
|
||||||
- "0.10"
|
- "0.10"
|
||||||
- "4"
|
- "0.11"
|
||||||
matrix:
|
|
||||||
fast_finish: true
|
|
||||||
sudo: false
|
|
||||||
|
|||||||
263
README.md
263
README.md
@@ -52,92 +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 and Userscripts that
|
|
||||||
may be anonymous function wrapped (IIFE) by the
|
|
||||||
.user.js engine `caller`.
|
|
||||||
--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]
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Specify `--output` (`-o`) to declare the output file. Otherwise the output
|
Specify `--output` (`-o`) to declare the output file. Otherwise the output
|
||||||
@@ -211,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
|
||||||
@@ -325,9 +236,6 @@ to set `true`; it's effectively a shortcut for `foo=true`).
|
|||||||
- `cascade` -- small optimization for sequences, transform `x, x` into `x`
|
- `cascade` -- small optimization for sequences, transform `x, x` into `x`
|
||||||
and `x = something(), x` into `x = something()`
|
and `x = something(), x` into `x = something()`
|
||||||
|
|
||||||
- `collapse_vars` -- default `false`. Collapse single-use `var` and `const`
|
|
||||||
definitions when possible.
|
|
||||||
|
|
||||||
- `warnings` -- display warnings when dropping unreachable code or unused
|
- `warnings` -- display warnings when dropping unreachable code or unused
|
||||||
declarations etc.
|
declarations etc.
|
||||||
|
|
||||||
@@ -353,15 +261,10 @@ to set `true`; it's effectively a shortcut for `foo=true`).
|
|||||||
- `drop_console` -- default `false`. Pass `true` to discard calls to
|
- `drop_console` -- default `false`. Pass `true` to discard calls to
|
||||||
`console.*` functions.
|
`console.*` functions.
|
||||||
|
|
||||||
- `keep_fargs` -- default `true`. Prevents the
|
- `keep_fargs` -- default `false`. Pass `true` to prevent the
|
||||||
compressor from discarding unused function arguments. You need this
|
compressor from discarding unused function arguments. You need this
|
||||||
for code which relies on `Function.length`.
|
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
|
### The `unsafe` option
|
||||||
|
|
||||||
It enables some transformations that *might* break code logic in certain
|
It enables some transformations that *might* break code logic in certain
|
||||||
@@ -369,14 +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).
|
||||||
|
|
||||||
### Conditional compilation
|
### Conditional compilation
|
||||||
|
|
||||||
@@ -400,8 +303,6 @@ separate file and include it into the build. For example you can have a
|
|||||||
```javascript
|
```javascript
|
||||||
const DEBUG = false;
|
const DEBUG = false;
|
||||||
const PRODUCTION = true;
|
const PRODUCTION = true;
|
||||||
// Alternative for environments that don't support `const`
|
|
||||||
/** @const */ var STAGING = false;
|
|
||||||
// etc.
|
// etc.
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -411,8 +312,8 @@ and build your code like this:
|
|||||||
|
|
||||||
UglifyJS will notice the constants and, since they cannot be altered, it
|
UglifyJS will notice the constants and, since they cannot be altered, it
|
||||||
will evaluate references to them to the value itself and drop unreachable
|
will evaluate references to them to the value itself and drop unreachable
|
||||||
code as usual. The build will contain the `const` declarations if you use
|
code as usual. The possible downside of this approach is that the build
|
||||||
them. If you are targeting < ES6 environments, use `/** @const */ var`.
|
will contain the `const` declarations.
|
||||||
|
|
||||||
<a name="codegen-options"></a>
|
<a name="codegen-options"></a>
|
||||||
## Beautifier options
|
## Beautifier options
|
||||||
@@ -609,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).
|
||||||
|
|
||||||
@@ -631,9 +522,6 @@ Other options:
|
|||||||
|
|
||||||
- `mangle` — pass `false` to skip mangling names.
|
- `mangle` — pass `false` to skip mangling names.
|
||||||
|
|
||||||
- `mangleProperties` (default `false`) — pass an object to specify custom
|
|
||||||
mangle property options.
|
|
||||||
|
|
||||||
- `output` (default `null`) — pass an object if you wish to specify
|
- `output` (default `null`) — pass an object if you wish to specify
|
||||||
additional [output options][codegen]. The defaults are optimized
|
additional [output options][codegen]. The defaults are optimized
|
||||||
for best compression.
|
for best compression.
|
||||||
@@ -641,13 +529,6 @@ Other options:
|
|||||||
- `compress` (default `{}`) — pass `false` to skip compressing entirely.
|
- `compress` (default `{}`) — pass `false` to skip compressing entirely.
|
||||||
Pass an object to specify custom [compressor options][compressor].
|
Pass an object to specify custom [compressor options][compressor].
|
||||||
|
|
||||||
- `parse` (default {}) — pass an object if you wish to specify some
|
|
||||||
additional [parser options][parser]. (not all options available... see below)
|
|
||||||
|
|
||||||
##### mangleProperties options
|
|
||||||
|
|
||||||
- `regex` — Pass a RegExp to only mangle certain names (maps to the `--mange-regex` CLI arguments option)
|
|
||||||
|
|
||||||
We could add more options to `UglifyJS.minify` — if you need additional
|
We could add more options to `UglifyJS.minify` — if you need additional
|
||||||
functionality please suggest!
|
functionality please suggest!
|
||||||
|
|
||||||
@@ -666,9 +547,6 @@ properties are available:
|
|||||||
|
|
||||||
- `strict` — disable automatic semicolon insertion and support for trailing
|
- `strict` — disable automatic semicolon insertion and support for trailing
|
||||||
comma in arrays and objects
|
comma in arrays and objects
|
||||||
- `bare_returns` — Allow return outside of functions. (maps to the
|
|
||||||
`--bare-returns` CLI arguments option and available to `minify` `parse`
|
|
||||||
other options object)
|
|
||||||
- `filename` — the name of the file where this code is coming from
|
- `filename` — the name of the file where this code is coming from
|
||||||
- `toplevel` — a `toplevel` node (as returned by a previous invocation of
|
- `toplevel` — a `toplevel` node (as returned by a previous invocation of
|
||||||
`parse`)
|
`parse`)
|
||||||
@@ -803,9 +681,8 @@ The `source_map_options` (optional) can contain the following properties:
|
|||||||
came from. It can be simply a string in JSON, or a JSON object containing
|
came from. It can be simply a string in JSON, or a JSON object containing
|
||||||
the original source map.
|
the original source map.
|
||||||
|
|
||||||
[acorn]: https://github.com/ternjs/acorn
|
[acorn]: https://github.com/marijnh/acorn
|
||||||
[source-map]: https://github.com/mozilla/source-map
|
[source-map]: https://github.com/mozilla/source-map
|
||||||
[sm-spec]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit
|
[sm-spec]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit
|
||||||
[codegen]: http://lisperator.net/uglifyjs/codegen
|
[codegen]: http://lisperator.net/uglifyjs/codegen
|
||||||
[compressor]: http://lisperator.net/uglifyjs/compress
|
[compressor]: http://lisperator.net/uglifyjs/compress
|
||||||
[parser]: http://lisperator.net/uglifyjs/parser
|
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
201
bin/uglifyjs
201
bin/uglifyjs
@@ -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("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")
|
|
||||||
.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("p", "prefix")
|
||||||
.alias("o", "output")
|
.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-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")
|
|
||||||
.array("pure-funcs")
|
|
||||||
|
|
||||||
.boolean("expr")
|
.boolean("expr")
|
||||||
.boolean("source-map-include-sources")
|
.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("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("dump-spidermonkey-ast")
|
|
||||||
.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)
|
||||||
|
|
||||||
@@ -137,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,50 +144,15 @@ 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");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ARGS.pure_funcs) {
|
|
||||||
if (COMPRESS) COMPRESS.pure_funcs = ARGS.pure_funcs;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ARGS.r) {
|
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;
|
||||||
}
|
}
|
||||||
@@ -233,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;
|
||||||
@@ -258,10 +203,11 @@ 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";
|
||||||
|
ARGS.export_all = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
var ORIG_MAP = ARGS.in_source_map;
|
var ORIG_MAP = ARGS.in_source_map;
|
||||||
@@ -269,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) {
|
||||||
@@ -282,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -310,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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -320,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) {
|
||||||
@@ -357,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;
|
||||||
@@ -373,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 = [];
|
||||||
@@ -388,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 SCOPE_IS_NEEDED = COMPRESS || MANGLE || ARGS.lint;
|
||||||
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");
|
|
||||||
|
|
||||||
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();
|
||||||
}
|
}
|
||||||
@@ -429,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)) {
|
||||||
@@ -451,38 +372,34 @@ async.eachLimit(files, 1, function (file, cb) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ARGS.dump_spidermonkey_ast) {
|
time_it("generate", function(){
|
||||||
print(JSON.stringify(TOPLEVEL.to_mozilla_ast(), null, 2));
|
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 {
|
} else {
|
||||||
time_it("generate", function(){
|
sys.print(output);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
}));
|
}));
|
||||||
@@ -499,19 +416,17 @@ function normalize(o) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getOptions(flag, constants) {
|
function getOptions(x, constants) {
|
||||||
var x = ARGS[flag];
|
x = ARGS[x];
|
||||||
if (x == null || x === false) return null;
|
if (!x) return null;
|
||||||
var ret = {};
|
var ret = {};
|
||||||
if (x !== "") {
|
if (x !== true) {
|
||||||
if (Array.isArray(x)) x = x.map(function (v) { return "(" + v + ")"; }).join(", ");
|
|
||||||
|
|
||||||
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 for flag `" + flag + "': " + x);
|
sys.error("Error parsing arguments in: " + x);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -530,8 +445,8 @@ function getOptions(flag, 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 for flag `" + flag + "': " + x);
|
sys.error("Error parsing arguments in: " + x);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@@ -563,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);
|
|
||||||
}
|
|
||||||
|
|||||||
43
lib/ast.js
43
lib/ast.js
@@ -81,11 +81,10 @@ function DEFNODE(type, props, methods, base) {
|
|||||||
ctor.DEFMETHOD = function(name, method) {
|
ctor.DEFMETHOD = function(name, method) {
|
||||||
this.prototype[name] = method;
|
this.prototype[name] = method;
|
||||||
};
|
};
|
||||||
exports["AST_" + type] = ctor;
|
|
||||||
return 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);
|
}, null);
|
||||||
|
|
||||||
var AST_Node = DEFNODE("Node", "start end", {
|
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 = parse(wrapped_tl);
|
||||||
wrapped_tl = wrapped_tl.transform(new TreeTransformer(function before(node){
|
wrapped_tl = wrapped_tl.transform(new TreeTransformer(function before(node){
|
||||||
if (node instanceof AST_Directive) {
|
if (node instanceof AST_SimpleStatement) {
|
||||||
switch (node.value) {
|
node = node.body;
|
||||||
|
if (node instanceof AST_String) switch (node.getValue()) {
|
||||||
case "$ORIG":
|
case "$ORIG":
|
||||||
return MAP.splice(self.body);
|
return MAP.splice(self.body);
|
||||||
case "$EXPORTS":
|
case "$EXPORTS":
|
||||||
@@ -864,11 +864,10 @@ var AST_String = DEFNODE("String", "value quote", {
|
|||||||
}
|
}
|
||||||
}, AST_Constant);
|
}, AST_Constant);
|
||||||
|
|
||||||
var AST_Number = DEFNODE("Number", "value literal", {
|
var AST_Number = DEFNODE("Number", "value", {
|
||||||
$documentation: "A number literal",
|
$documentation: "A number literal",
|
||||||
$propdoc: {
|
$propdoc: {
|
||||||
value: "[number] the numeric value",
|
value: "[number] the numeric value"
|
||||||
literal: "[string] numeric value as string (optional)"
|
|
||||||
}
|
}
|
||||||
}, AST_Constant);
|
}, AST_Constant);
|
||||||
|
|
||||||
@@ -927,36 +926,27 @@ var AST_True = DEFNODE("True", null, {
|
|||||||
function TreeWalker(callback) {
|
function TreeWalker(callback) {
|
||||||
this.visit = callback;
|
this.visit = callback;
|
||||||
this.stack = [];
|
this.stack = [];
|
||||||
this.directives = Object.create(null);
|
|
||||||
};
|
};
|
||||||
TreeWalker.prototype = {
|
TreeWalker.prototype = {
|
||||||
_visit: function(node, descend) {
|
_visit: function(node, descend) {
|
||||||
this.push(node);
|
this.stack.push(node);
|
||||||
var ret = this.visit(node, descend ? function(){
|
var ret = this.visit(node, descend ? function(){
|
||||||
descend.call(node);
|
descend.call(node);
|
||||||
} : noop);
|
} : noop);
|
||||||
if (!ret && descend) {
|
if (!ret && descend) {
|
||||||
descend.call(node);
|
descend.call(node);
|
||||||
}
|
}
|
||||||
this.pop(node);
|
this.stack.pop();
|
||||||
return ret;
|
return ret;
|
||||||
},
|
},
|
||||||
parent: function(n) {
|
parent: function(n) {
|
||||||
return this.stack[this.stack.length - 2 - (n || 0)];
|
return this.stack[this.stack.length - 2 - (n || 0)];
|
||||||
},
|
},
|
||||||
push: function (node) {
|
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);
|
this.stack.push(node);
|
||||||
},
|
},
|
||||||
pop: function(node) {
|
pop: function() {
|
||||||
this.stack.pop();
|
return this.stack.pop();
|
||||||
if (node instanceof AST_Lambda) {
|
|
||||||
this.directives = Object.getPrototypeOf(this.directives);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
self: function() {
|
self: function() {
|
||||||
return this.stack[this.stack.length - 1];
|
return this.stack[this.stack.length - 1];
|
||||||
@@ -969,16 +959,7 @@ TreeWalker.prototype = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
has_directive: function(type) {
|
has_directive: function(type) {
|
||||||
var dir = this.directives[type];
|
return this.find_parent(AST_Scope).has_directive(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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
in_boolean_context: function() {
|
in_boolean_context: function() {
|
||||||
var stack = this.stack;
|
var stack = this.stack;
|
||||||
|
|||||||
392
lib/compress.js
392
lib/compress.js
@@ -61,12 +61,11 @@ function Compressor(options, false_by_default) {
|
|||||||
loops : !false_by_default,
|
loops : !false_by_default,
|
||||||
unused : !false_by_default,
|
unused : !false_by_default,
|
||||||
hoist_funs : !false_by_default,
|
hoist_funs : !false_by_default,
|
||||||
keep_fargs : true,
|
keep_fargs : false,
|
||||||
keep_fnames : false,
|
keep_fnames : false,
|
||||||
hoist_vars : false,
|
hoist_vars : false,
|
||||||
if_return : !false_by_default,
|
if_return : !false_by_default,
|
||||||
join_vars : !false_by_default,
|
join_vars : !false_by_default,
|
||||||
collapse_vars : false,
|
|
||||||
cascade : !false_by_default,
|
cascade : !false_by_default,
|
||||||
side_effects : !false_by_default,
|
side_effects : !false_by_default,
|
||||||
pure_getters : false,
|
pure_getters : false,
|
||||||
@@ -112,7 +111,6 @@ merge(Compressor.prototype, {
|
|||||||
node.DEFMETHOD("optimize", function(compressor){
|
node.DEFMETHOD("optimize", function(compressor){
|
||||||
var self = this;
|
var self = this;
|
||||||
if (self._optimized) return self;
|
if (self._optimized) return self;
|
||||||
if (compressor.has_directive("use asm")) return self;
|
|
||||||
var opt = optimizer(self, compressor);
|
var opt = optimizer(self, compressor);
|
||||||
opt._optimized = true;
|
opt._optimized = true;
|
||||||
if (opt === self) return opt;
|
if (opt === self) return opt;
|
||||||
@@ -176,23 +174,6 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// we shouldn't compress (1,func)(something) to
|
|
||||||
// func(something) because that changes the meaning of
|
|
||||||
// the func (becomes lexical instead of global).
|
|
||||||
function maintain_this_binding(parent, orig, val) {
|
|
||||||
if (parent instanceof AST_Call && parent.expression === orig) {
|
|
||||||
if (val instanceof AST_PropAccess || val instanceof AST_SymbolRef && val.name === "eval") {
|
|
||||||
return make_node(AST_Seq, orig, {
|
|
||||||
car: make_node(AST_Number, orig, {
|
|
||||||
value: 0
|
|
||||||
}),
|
|
||||||
cdr: val
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
function as_statement_array(thing) {
|
function as_statement_array(thing) {
|
||||||
if (thing === null) return [];
|
if (thing === null) return [];
|
||||||
if (thing instanceof AST_BlockStatement) return thing.body;
|
if (thing instanceof AST_BlockStatement) return thing.body;
|
||||||
@@ -217,7 +198,7 @@ merge(Compressor.prototype, {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function tighten_body(statements, compressor) {
|
function tighten_body(statements, compressor) {
|
||||||
var CHANGED, max_iter = 10;
|
var CHANGED;
|
||||||
do {
|
do {
|
||||||
CHANGED = false;
|
CHANGED = false;
|
||||||
if (compressor.option("angular")) {
|
if (compressor.option("angular")) {
|
||||||
@@ -236,10 +217,7 @@ merge(Compressor.prototype, {
|
|||||||
if (compressor.option("join_vars")) {
|
if (compressor.option("join_vars")) {
|
||||||
statements = join_consecutive_vars(statements, compressor);
|
statements = join_consecutive_vars(statements, compressor);
|
||||||
}
|
}
|
||||||
if (compressor.option("collapse_vars")) {
|
} while (CHANGED);
|
||||||
statements = collapse_single_use_vars(statements, compressor);
|
|
||||||
}
|
|
||||||
} while (CHANGED && max_iter-- > 0);
|
|
||||||
|
|
||||||
if (compressor.option("negate_iife")) {
|
if (compressor.option("negate_iife")) {
|
||||||
negate_iifes(statements, compressor);
|
negate_iifes(statements, compressor);
|
||||||
@@ -247,163 +225,6 @@ merge(Compressor.prototype, {
|
|||||||
|
|
||||||
return statements;
|
return statements;
|
||||||
|
|
||||||
function collapse_single_use_vars(statements, compressor) {
|
|
||||||
// Iterate statements backwards looking for a statement with a var/const
|
|
||||||
// declaration immediately preceding it. Grab the rightmost var definition
|
|
||||||
// and if it has exactly one reference then attempt to replace its reference
|
|
||||||
// in the statement with the var value and then erase the var definition.
|
|
||||||
|
|
||||||
var self = compressor.self();
|
|
||||||
var var_defs_removed = false;
|
|
||||||
for (var stat_index = statements.length; --stat_index >= 0;) {
|
|
||||||
var stat = statements[stat_index];
|
|
||||||
if (stat instanceof AST_Definitions) continue;
|
|
||||||
|
|
||||||
// Process child blocks of statement if present.
|
|
||||||
[stat, stat.body, stat.alternative, stat.bcatch, stat.bfinally].forEach(function(node) {
|
|
||||||
node && node.body && collapse_single_use_vars(node.body, compressor);
|
|
||||||
});
|
|
||||||
|
|
||||||
// The variable definition must precede a statement.
|
|
||||||
if (stat_index <= 0) break;
|
|
||||||
var prev_stat_index = stat_index - 1;
|
|
||||||
var prev_stat = statements[prev_stat_index];
|
|
||||||
if (!(prev_stat instanceof AST_Definitions)) continue;
|
|
||||||
var var_defs = prev_stat.definitions;
|
|
||||||
if (var_defs == null) continue;
|
|
||||||
|
|
||||||
var var_names_seen = {};
|
|
||||||
var side_effects_encountered = false;
|
|
||||||
var lvalues_encountered = false;
|
|
||||||
var lvalues = {};
|
|
||||||
|
|
||||||
// Scan variable definitions from right to left.
|
|
||||||
for (var var_defs_index = var_defs.length; --var_defs_index >= 0;) {
|
|
||||||
|
|
||||||
// Obtain var declaration and var name with basic sanity check.
|
|
||||||
var var_decl = var_defs[var_defs_index];
|
|
||||||
if (var_decl.value == null) break;
|
|
||||||
var var_name = var_decl.name.name;
|
|
||||||
if (!var_name || !var_name.length) break;
|
|
||||||
|
|
||||||
// Bail if we've seen a var definition of same name before.
|
|
||||||
if (var_name in var_names_seen) break;
|
|
||||||
var_names_seen[var_name] = true;
|
|
||||||
|
|
||||||
// Only interested in cases with just one reference to the variable.
|
|
||||||
var def = self.find_variable && self.find_variable(var_name);
|
|
||||||
if (!def || !def.references || def.references.length !== 1 || var_name == "arguments") {
|
|
||||||
side_effects_encountered = true;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
var ref = def.references[0];
|
|
||||||
|
|
||||||
// Don't replace ref if eval() or with statement in scope.
|
|
||||||
if (ref.scope.uses_eval || ref.scope.uses_with) break;
|
|
||||||
|
|
||||||
// Constant single use vars can be replaced in any scope.
|
|
||||||
if (var_decl.value.is_constant(compressor)) {
|
|
||||||
var ctt = new TreeTransformer(function(node) {
|
|
||||||
if (node === ref)
|
|
||||||
return replace_var(node, ctt.parent(), true);
|
|
||||||
});
|
|
||||||
stat.transform(ctt);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Restrict var replacement to constants if side effects encountered.
|
|
||||||
if (side_effects_encountered |= lvalues_encountered) continue;
|
|
||||||
|
|
||||||
// Non-constant single use vars can only be replaced in same scope.
|
|
||||||
if (ref.scope !== self) {
|
|
||||||
side_effects_encountered |= var_decl.value.has_side_effects(compressor);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Detect lvalues in var value.
|
|
||||||
var tw = new TreeWalker(function(node){
|
|
||||||
if (node instanceof AST_SymbolRef && is_lvalue(node, tw.parent())) {
|
|
||||||
lvalues[node.name] = lvalues_encountered = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
var_decl.value.walk(tw);
|
|
||||||
|
|
||||||
// Replace the non-constant single use var in statement if side effect free.
|
|
||||||
var unwind = false;
|
|
||||||
var tt = new TreeTransformer(
|
|
||||||
function preorder(node) {
|
|
||||||
if (unwind) return node;
|
|
||||||
var parent = tt.parent();
|
|
||||||
if (node instanceof AST_Lambda
|
|
||||||
|| node instanceof AST_Try
|
|
||||||
|| node instanceof AST_With
|
|
||||||
|| node instanceof AST_Case
|
|
||||||
|| node instanceof AST_IterationStatement
|
|
||||||
|| (parent instanceof AST_If && node !== parent.condition)
|
|
||||||
|| (parent instanceof AST_Conditional && node !== parent.condition)
|
|
||||||
|| (parent instanceof AST_Binary
|
|
||||||
&& (parent.operator == "&&" || parent.operator == "||")
|
|
||||||
&& node === parent.right)
|
|
||||||
|| (parent instanceof AST_Switch && node !== parent.expression)) {
|
|
||||||
return side_effects_encountered = unwind = true, node;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
function postorder(node) {
|
|
||||||
if (unwind) return node;
|
|
||||||
if (node === ref)
|
|
||||||
return unwind = true, replace_var(node, tt.parent(), false);
|
|
||||||
if (side_effects_encountered |= node.has_side_effects(compressor))
|
|
||||||
return unwind = true, node;
|
|
||||||
if (lvalues_encountered && node instanceof AST_SymbolRef && node.name in lvalues) {
|
|
||||||
side_effects_encountered = true;
|
|
||||||
return unwind = true, node;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
stat.transform(tt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove extraneous empty statments in block after removing var definitions.
|
|
||||||
// Leave at least one statement in `statements`.
|
|
||||||
if (var_defs_removed) for (var i = statements.length; --i >= 0;) {
|
|
||||||
if (statements.length > 1 && statements[i] instanceof AST_EmptyStatement)
|
|
||||||
statements.splice(i, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return statements;
|
|
||||||
|
|
||||||
function is_lvalue(node, parent) {
|
|
||||||
return node instanceof AST_SymbolRef && (
|
|
||||||
(parent instanceof AST_Assign && node === parent.left)
|
|
||||||
|| (parent instanceof AST_Unary && parent.expression === node
|
|
||||||
&& (parent.operator == "++" || parent.operator == "--")));
|
|
||||||
}
|
|
||||||
function replace_var(node, parent, is_constant) {
|
|
||||||
if (is_lvalue(node, parent)) return node;
|
|
||||||
|
|
||||||
// Remove var definition and return its value to the TreeTransformer to replace.
|
|
||||||
var value = maintain_this_binding(parent, node, var_decl.value);
|
|
||||||
var_decl.value = null;
|
|
||||||
|
|
||||||
var_defs.splice(var_defs_index, 1);
|
|
||||||
if (var_defs.length === 0) {
|
|
||||||
statements[prev_stat_index] = make_node(AST_EmptyStatement, self);
|
|
||||||
var_defs_removed = true;
|
|
||||||
}
|
|
||||||
// Further optimize statement after substitution.
|
|
||||||
stat.walk(new TreeWalker(function(node){
|
|
||||||
delete node._squeezed;
|
|
||||||
delete node._optimized;
|
|
||||||
}));
|
|
||||||
|
|
||||||
compressor.warn("Replacing " + (is_constant ? "constant" : "variable") +
|
|
||||||
" " + var_name + " [{file}:{line},{col}]", node.start);
|
|
||||||
CHANGED = true;
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function process_for_angular(statements) {
|
function process_for_angular(statements) {
|
||||||
function has_inject(comment) {
|
function has_inject(comment) {
|
||||||
return /@ngInject/.test(comment.value);
|
return /@ngInject/.test(comment.value);
|
||||||
@@ -562,12 +383,7 @@ merge(Compressor.prototype, {
|
|||||||
continue loop;
|
continue loop;
|
||||||
}
|
}
|
||||||
//---
|
//---
|
||||||
// XXX: what was the intention of this case?
|
if (ret.length == 1 && in_lambda && ret[0] instanceof AST_SimpleStatement
|
||||||
// if sequences is not enabled, this can lead to an endless loop (issue #866).
|
|
||||||
// however, with sequences on this helps producing slightly better output for
|
|
||||||
// the example code.
|
|
||||||
if (compressor.option("sequences")
|
|
||||||
&& ret.length == 1 && in_lambda && ret[0] instanceof AST_SimpleStatement
|
|
||||||
&& (!stat.alternative || stat.alternative instanceof AST_SimpleStatement)) {
|
&& (!stat.alternative || stat.alternative instanceof AST_SimpleStatement)) {
|
||||||
CHANGED = true;
|
CHANGED = true;
|
||||||
ret.push(make_node(AST_Return, ret[0], {
|
ret.push(make_node(AST_Return, ret[0], {
|
||||||
@@ -673,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();
|
||||||
@@ -904,32 +720,6 @@ merge(Compressor.prototype, {
|
|||||||
return [ this ];
|
return [ this ];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
AST_Node.DEFMETHOD("is_constant", function(compressor){
|
|
||||||
// Accomodate when compress option evaluate=false
|
|
||||||
// as well as the common constant expressions !0 and !1
|
|
||||||
return this instanceof AST_Constant
|
|
||||||
|| (this instanceof AST_UnaryPrefix && this.operator == "!"
|
|
||||||
&& this.expression instanceof AST_Constant)
|
|
||||||
|| this.evaluate(compressor).length > 1;
|
|
||||||
});
|
|
||||||
// Obtain the constant value of an expression already known to be constant.
|
|
||||||
// Result only valid iff this.is_constant(compressor) is true.
|
|
||||||
AST_Node.DEFMETHOD("constant_value", function(compressor){
|
|
||||||
// Accomodate when option evaluate=false.
|
|
||||||
if (this instanceof AST_Constant) return this.value;
|
|
||||||
// Accomodate the common constant expressions !0 and !1 when option evaluate=false.
|
|
||||||
if (this instanceof AST_UnaryPrefix
|
|
||||||
&& this.operator == "!"
|
|
||||||
&& this.expression instanceof AST_Constant) {
|
|
||||||
return !this.expression.value;
|
|
||||||
}
|
|
||||||
var result = this.evaluate(compressor)
|
|
||||||
if (result.length > 1) {
|
|
||||||
return result[1];
|
|
||||||
}
|
|
||||||
// should never be reached
|
|
||||||
return undefined;
|
|
||||||
});
|
|
||||||
def(AST_Statement, function(){
|
def(AST_Statement, function(){
|
||||||
throw new Error(string_template("Cannot evaluate a statement [{file}:{line},{col}]", this.start));
|
throw new Error(string_template("Cannot evaluate a statement [{file}:{line},{col}]", this.start));
|
||||||
});
|
});
|
||||||
@@ -1106,7 +896,6 @@ merge(Compressor.prototype, {
|
|||||||
def(AST_Call, function(compressor){
|
def(AST_Call, function(compressor){
|
||||||
var pure = compressor.option("pure_funcs");
|
var pure = compressor.option("pure_funcs");
|
||||||
if (!pure) return true;
|
if (!pure) return true;
|
||||||
if (typeof pure == "function") return pure(this);
|
|
||||||
return pure.indexOf(this.expression.print_to_string()) < 0;
|
return pure.indexOf(this.expression.print_to_string()) < 0;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1200,7 +989,7 @@ merge(Compressor.prototype, {
|
|||||||
/* -----[ optimizers ]----- */
|
/* -----[ optimizers ]----- */
|
||||||
|
|
||||||
OPT(AST_Directive, function(self, compressor){
|
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 make_node(AST_EmptyStatement, self);
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
@@ -1236,7 +1025,6 @@ merge(Compressor.prototype, {
|
|||||||
|
|
||||||
AST_Scope.DEFMETHOD("drop_unused", function(compressor){
|
AST_Scope.DEFMETHOD("drop_unused", function(compressor){
|
||||||
var self = this;
|
var self = this;
|
||||||
if (compressor.has_directive("use asm")) return self;
|
|
||||||
if (compressor.option("unused")
|
if (compressor.option("unused")
|
||||||
&& !(self instanceof AST_Toplevel)
|
&& !(self instanceof AST_Toplevel)
|
||||||
&& !self.uses_eval
|
&& !self.uses_eval
|
||||||
@@ -1380,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;
|
||||||
}
|
}
|
||||||
@@ -1416,10 +1204,9 @@ merge(Compressor.prototype, {
|
|||||||
});
|
});
|
||||||
|
|
||||||
AST_Scope.DEFMETHOD("hoist_declarations", function(compressor){
|
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_funs = compressor.option("hoist_funs");
|
||||||
var hoist_vars = compressor.option("hoist_vars");
|
var hoist_vars = compressor.option("hoist_vars");
|
||||||
|
var self = this;
|
||||||
if (hoist_funs || hoist_vars) {
|
if (hoist_funs || hoist_vars) {
|
||||||
var dirs = [];
|
var dirs = [];
|
||||||
var hoisted = [];
|
var hoisted = [];
|
||||||
@@ -1454,10 +1241,7 @@ merge(Compressor.prototype, {
|
|||||||
var seq = node.to_assignments();
|
var seq = node.to_assignments();
|
||||||
var p = tt.parent();
|
var p = tt.parent();
|
||||||
if (p instanceof AST_ForIn && p.init === node) {
|
if (p instanceof AST_ForIn && p.init === node) {
|
||||||
if (seq == null) {
|
if (seq == null) return node.definitions[0].name;
|
||||||
var def = node.definitions[0].name;
|
|
||||||
return make_node(AST_SymbolRef, def, def);
|
|
||||||
}
|
|
||||||
return seq;
|
return seq;
|
||||||
}
|
}
|
||||||
if (p instanceof AST_For && p.init === node) {
|
if (p instanceof AST_For && p.init === node) {
|
||||||
@@ -1688,13 +1472,9 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
if (is_empty(self.alternative)) self.alternative = null;
|
if (is_empty(self.alternative)) self.alternative = null;
|
||||||
var negated = self.condition.negate(compressor);
|
var negated = self.condition.negate(compressor);
|
||||||
var self_condition_length = self.condition.print_to_string().length;
|
var negated_is_best = best_of(self.condition, negated) === negated;
|
||||||
var negated_length = negated.print_to_string().length;
|
|
||||||
var negated_is_best = negated_length < self_condition_length;
|
|
||||||
if (self.alternative && negated_is_best) {
|
if (self.alternative && negated_is_best) {
|
||||||
negated_is_best = false; // because we already do the switch here.
|
negated_is_best = false; // because we already do the switch here.
|
||||||
// no need to swap values of self_condition_length and negated_length
|
|
||||||
// here because they are only used in an equality comparison later on.
|
|
||||||
self.condition = negated;
|
self.condition = negated;
|
||||||
var tmp = self.body;
|
var tmp = self.body;
|
||||||
self.body = self.alternative || make_node(AST_EmptyStatement);
|
self.body = self.alternative || make_node(AST_EmptyStatement);
|
||||||
@@ -1716,13 +1496,6 @@ merge(Compressor.prototype, {
|
|||||||
}).transform(compressor);
|
}).transform(compressor);
|
||||||
}
|
}
|
||||||
if (is_empty(self.alternative) && self.body instanceof AST_SimpleStatement) {
|
if (is_empty(self.alternative) && self.body instanceof AST_SimpleStatement) {
|
||||||
if (self_condition_length === negated_length && !negated_is_best
|
|
||||||
&& self.condition instanceof AST_Binary && self.condition.operator == "||") {
|
|
||||||
// although the code length of self.condition and negated are the same,
|
|
||||||
// negated does not require additional surrounding parentheses.
|
|
||||||
// see https://github.com/mishoo/UglifyJS2/issues/979
|
|
||||||
negated_is_best = true;
|
|
||||||
}
|
|
||||||
if (negated_is_best) return make_node(AST_SimpleStatement, self, {
|
if (negated_is_best) return make_node(AST_SimpleStatement, self, {
|
||||||
body: make_node(AST_Binary, self, {
|
body: make_node(AST_Binary, self, {
|
||||||
operator : "||",
|
operator : "||",
|
||||||
@@ -2136,7 +1909,17 @@ merge(Compressor.prototype, {
|
|||||||
if (!compressor.option("side_effects"))
|
if (!compressor.option("side_effects"))
|
||||||
return self;
|
return self;
|
||||||
if (!self.car.has_side_effects(compressor)) {
|
if (!self.car.has_side_effects(compressor)) {
|
||||||
return maintain_this_binding(compressor.parent(), self, self.cdr);
|
// 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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (compressor.option("cascade")) {
|
if (compressor.option("cascade")) {
|
||||||
if (self.car instanceof AST_Assign
|
if (self.car instanceof AST_Assign
|
||||||
@@ -2248,14 +2031,15 @@ merge(Compressor.prototype, {
|
|||||||
var commutativeOperators = makePredicate("== === != !== * & | ^");
|
var commutativeOperators = makePredicate("== === != !== * & | ^");
|
||||||
|
|
||||||
OPT(AST_Binary, function(self, compressor){
|
OPT(AST_Binary, function(self, compressor){
|
||||||
function reverse(op, force) {
|
var reverse = compressor.has_directive("use asm") ? noop
|
||||||
if (force || !(self.left.has_side_effects(compressor) || self.right.has_side_effects(compressor))) {
|
: function(op, force) {
|
||||||
if (op) self.operator = op;
|
if (force || !(self.left.has_side_effects(compressor) || self.right.has_side_effects(compressor))) {
|
||||||
var tmp = self.left;
|
if (op) self.operator = op;
|
||||||
self.left = self.right;
|
var tmp = self.left;
|
||||||
self.right = tmp;
|
self.left = self.right;
|
||||||
}
|
self.right = tmp;
|
||||||
}
|
}
|
||||||
|
};
|
||||||
if (commutativeOperators(self.operator)) {
|
if (commutativeOperators(self.operator)) {
|
||||||
if (self.right instanceof AST_Constant
|
if (self.right instanceof AST_Constant
|
||||||
&& !(self.left instanceof AST_Constant)) {
|
&& !(self.left instanceof AST_Constant)) {
|
||||||
@@ -2320,32 +2104,6 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
break;
|
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);
|
|
||||||
return maintain_this_binding(compressor.parent(), self, self.right.evaluate(compressor)[0]);
|
|
||||||
} else {
|
|
||||||
compressor.warn("Condition left of && always false [{file}:{line},{col}]", self.start);
|
|
||||||
return maintain_this_binding(compressor.parent(), self, 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 maintain_this_binding(compressor.parent(), self, ll[0]);
|
|
||||||
} else {
|
|
||||||
compressor.warn("Condition left of || always false [{file}:{line},{col}]", self.start);
|
|
||||||
return maintain_this_binding(compressor.parent(), self, self.right.evaluate(compressor)[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);
|
||||||
@@ -2397,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, {
|
||||||
@@ -2472,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,
|
||||||
@@ -2490,15 +2247,7 @@ merge(Compressor.prototype, {
|
|||||||
});
|
});
|
||||||
|
|
||||||
OPT(AST_SymbolRef, function(self, compressor){
|
OPT(AST_SymbolRef, function(self, compressor){
|
||||||
function isLHS(symbol, parent) {
|
if (self.undeclared()) {
|
||||||
return (
|
|
||||||
parent instanceof AST_Binary &&
|
|
||||||
parent.operator === '=' &&
|
|
||||||
parent.left === symbol
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (self.undeclared() && !isLHS(self, compressor.parent())) {
|
|
||||||
var defines = compressor.option("global_defs");
|
var defines = compressor.option("global_defs");
|
||||||
if (defines && defines.hasOwnProperty(self.name)) {
|
if (defines && defines.hasOwnProperty(self.name)) {
|
||||||
return make_node_from_constant(compressor, defines[self.name], self);
|
return make_node_from_constant(compressor, defines[self.name], self);
|
||||||
@@ -2518,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})
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -2566,10 +2323,10 @@ merge(Compressor.prototype, {
|
|||||||
if (cond.length > 1) {
|
if (cond.length > 1) {
|
||||||
if (cond[1]) {
|
if (cond[1]) {
|
||||||
compressor.warn("Condition always true [{file}:{line},{col}]", self.start);
|
compressor.warn("Condition always true [{file}:{line},{col}]", self.start);
|
||||||
return maintain_this_binding(compressor.parent(), self, self.consequent);
|
return self.consequent;
|
||||||
} else {
|
} else {
|
||||||
compressor.warn("Condition always false [{file}:{line},{col}]", self.start);
|
compressor.warn("Condition always false [{file}:{line},{col}]", self.start);
|
||||||
return maintain_this_binding(compressor.parent(), self, self.alternative);
|
return self.alternative;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var negated = cond[0].negate(compressor);
|
var negated = cond[0].negate(compressor);
|
||||||
@@ -2586,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:
|
||||||
@@ -2607,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, {
|
||||||
@@ -2637,52 +2392,32 @@ merge(Compressor.prototype, {
|
|||||||
alternative: alternative
|
alternative: alternative
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// y?1:1 --> 1
|
// x=y?1:1 --> x=1
|
||||||
if (consequent.is_constant(compressor)
|
if (consequent instanceof AST_Constant
|
||||||
&& alternative.is_constant(compressor)
|
&& alternative instanceof AST_Constant
|
||||||
&& consequent.equivalent_to(alternative)) {
|
&& consequent.equivalent_to(alternative)) {
|
||||||
var consequent_value = consequent.constant_value();
|
|
||||||
if (self.condition.has_side_effects(compressor)) {
|
if (self.condition.has_side_effects(compressor)) {
|
||||||
return AST_Seq.from_array([self.condition, make_node_from_constant(compressor, consequent_value, self)]);
|
return AST_Seq.from_array([self.condition, make_node_from_constant(compressor, consequent.value, self)]);
|
||||||
} else {
|
} else {
|
||||||
return make_node_from_constant(compressor, consequent_value, self);
|
return make_node_from_constant(compressor, consequent.value, self);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// x=y?true:false --> x=!!y
|
||||||
// y?true:false --> !!y
|
if (consequent instanceof AST_True
|
||||||
if (is_true(consequent) && is_false(alternative)) {
|
&& alternative instanceof AST_False) {
|
||||||
if (self.condition.is_boolean()) {
|
|
||||||
// boolean_expression ? true : false --> boolean_expression
|
|
||||||
return self.condition;
|
|
||||||
}
|
|
||||||
self.condition = self.condition.negate(compressor);
|
self.condition = self.condition.negate(compressor);
|
||||||
return make_node(AST_UnaryPrefix, self.condition, {
|
return make_node(AST_UnaryPrefix, self.condition, {
|
||||||
operator: "!",
|
operator: "!",
|
||||||
expression: self.condition
|
expression: self.condition
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// y?false:true --> !y
|
// x=y?false:true --> x=!y
|
||||||
if (is_false(consequent) && is_true(alternative)) {
|
if (consequent instanceof AST_False
|
||||||
|
&& alternative instanceof AST_True) {
|
||||||
return self.condition.negate(compressor)
|
return self.condition.negate(compressor)
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
|
|
||||||
// AST_True or !0
|
|
||||||
function is_true(node) {
|
|
||||||
return node instanceof AST_True
|
|
||||||
|| (node instanceof AST_UnaryPrefix
|
|
||||||
&& node.operator == "!"
|
|
||||||
&& node.expression instanceof AST_Constant
|
|
||||||
&& !node.expression.value);
|
|
||||||
}
|
|
||||||
// AST_False or !1
|
|
||||||
function is_false(node) {
|
|
||||||
return node instanceof AST_False
|
|
||||||
|| (node instanceof AST_UnaryPrefix
|
|
||||||
&& node.operator == "!"
|
|
||||||
&& node.expression instanceof AST_Constant
|
|
||||||
&& !!node.expression.value);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
OPT(AST_Boolean, function(self, compressor){
|
OPT(AST_Boolean, function(self, compressor){
|
||||||
@@ -2745,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;
|
||||||
@@ -2754,11 +2489,4 @@ merge(Compressor.prototype, {
|
|||||||
OPT(AST_Object, literals_in_boolean_context);
|
OPT(AST_Object, literals_in_boolean_context);
|
||||||
OPT(AST_RegExp, 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;
|
|
||||||
});
|
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
|||||||
@@ -146,14 +146,7 @@
|
|||||||
case "boolean":
|
case "boolean":
|
||||||
return new (val ? AST_True : AST_False)(args);
|
return new (val ? AST_True : AST_False)(args);
|
||||||
default:
|
default:
|
||||||
var rx = M.regex;
|
args.value = val;
|
||||||
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;
|
|
||||||
}
|
|
||||||
return new AST_RegExp(args);
|
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) {
|
def_to_moz(AST_Constant, function To_Moz_Literal(M) {
|
||||||
var value = M.value;
|
var value = M.value;
|
||||||
if (typeof value === 'number' && (value < 0 || (value === 0 && 1 / value < 0))) {
|
if (typeof value === 'number' && (value < 0 || (value === 0 && 1 / value < 0))) {
|
||||||
@@ -363,15 +343,13 @@
|
|||||||
prefix: true,
|
prefix: true,
|
||||||
argument: {
|
argument: {
|
||||||
type: "Literal",
|
type: "Literal",
|
||||||
value: -value,
|
value: -value
|
||||||
raw: M.start.raw
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
type: "Literal",
|
type: "Literal",
|
||||||
value: value,
|
value: value
|
||||||
raw: M.start.raw
|
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -391,12 +369,6 @@
|
|||||||
|
|
||||||
/* -----[ tools ]----- */
|
/* -----[ tools ]----- */
|
||||||
|
|
||||||
function raw_token(moznode) {
|
|
||||||
if (moznode.type == "Literal") {
|
|
||||||
return moznode.raw != null ? moznode.raw : moznode.value + "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function my_start_token(moznode) {
|
function my_start_token(moznode) {
|
||||||
var loc = moznode.loc, start = loc && loc.start;
|
var loc = moznode.loc, start = loc && loc.start;
|
||||||
var range = moznode.range;
|
var range = moznode.range;
|
||||||
@@ -407,8 +379,7 @@
|
|||||||
pos : range ? range[0] : moznode.start,
|
pos : range ? range[0] : moznode.start,
|
||||||
endline : start && start.line,
|
endline : start && start.line,
|
||||||
endcol : start && start.column,
|
endcol : start && start.column,
|
||||||
endpos : range ? range[0] : moznode.start,
|
endpos : range ? range[0] : moznode.start
|
||||||
raw : raw_token(moznode),
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -422,14 +393,13 @@
|
|||||||
pos : range ? range[1] : moznode.end,
|
pos : range ? range[1] : moznode.end,
|
||||||
endline : end && end.line,
|
endline : end && end.line,
|
||||||
endcol : end && end.column,
|
endcol : end && end.column,
|
||||||
endpos : range ? range[1] : moznode.end,
|
endpos : range ? range[1] : moznode.end
|
||||||
raw : raw_token(moznode),
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
function map(moztype, mytype, propmap) {
|
function map(moztype, mytype, propmap) {
|
||||||
var moz_to_me = "function From_Moz_" + moztype + "(M){\n";
|
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" +
|
"start: my_start_token(M),\n" +
|
||||||
"end: my_end_token(M)";
|
"end: my_end_token(M)";
|
||||||
|
|
||||||
@@ -472,8 +442,8 @@
|
|||||||
//me_to_moz = parse(me_to_moz).print_to_string({ beautify: true });
|
//me_to_moz = parse(me_to_moz).print_to_string({ beautify: true });
|
||||||
//console.log(moz_to_me);
|
//console.log(moz_to_me);
|
||||||
|
|
||||||
moz_to_me = new Function("U2", "my_start_token", "my_end_token", "from_moz", "return(" + moz_to_me + ")")(
|
moz_to_me = new Function("my_start_token", "my_end_token", "from_moz", "return(" + moz_to_me + ")")(
|
||||||
exports, my_start_token, my_end_token, from_moz
|
my_start_token, my_end_token, from_moz
|
||||||
);
|
);
|
||||||
me_to_moz = new Function("to_moz", "to_moz_block", "return(" + me_to_moz + ")")(
|
me_to_moz = new Function("to_moz", "to_moz_block", "return(" + me_to_moz + ")")(
|
||||||
to_moz, to_moz_block
|
to_moz, to_moz_block
|
||||||
|
|||||||
170
lib/output.js
170
lib/output.js
@@ -60,7 +60,6 @@ function OutputStream(options) {
|
|||||||
bracketize : false,
|
bracketize : false,
|
||||||
semicolons : true,
|
semicolons : true,
|
||||||
comments : false,
|
comments : false,
|
||||||
shebang : true,
|
|
||||||
preserve_line : false,
|
preserve_line : false,
|
||||||
screw_ie8 : false,
|
screw_ie8 : false,
|
||||||
preamble : null,
|
preamble : null,
|
||||||
@@ -88,14 +87,13 @@ function OutputStream(options) {
|
|||||||
|
|
||||||
function make_string(str, quote) {
|
function make_string(str, quote) {
|
||||||
var dq = 0, sq = 0;
|
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) {
|
switch (s) {
|
||||||
case "\\": return "\\\\";
|
case "\\": return "\\\\";
|
||||||
case "\b": return "\\b";
|
case "\b": return "\\b";
|
||||||
case "\f": return "\\f";
|
case "\f": return "\\f";
|
||||||
case "\n": return "\\n";
|
case "\n": return "\\n";
|
||||||
case "\r": return "\\r";
|
case "\r": return "\\r";
|
||||||
case "\x0B": return options.screw_ie8 ? "\\v" : "\\x0B";
|
|
||||||
case "\u2028": return "\\u2028";
|
case "\u2028": return "\\u2028";
|
||||||
case "\u2029": return "\\u2029";
|
case "\u2029": return "\\u2029";
|
||||||
case '"': ++dq; return '"';
|
case '"': ++dq; return '"';
|
||||||
@@ -126,11 +124,8 @@ function OutputStream(options) {
|
|||||||
|
|
||||||
function encode_string(str, quote) {
|
function encode_string(str, quote) {
|
||||||
var ret = make_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(/<\x2fscript([>\/\t\n\f\r ])/gi, "<\\/script$1");
|
||||||
ret = ret.replace(/\x3c!--/g, "\\x3c!--");
|
|
||||||
ret = ret.replace(/--\x3e/g, "--\\x3e");
|
|
||||||
}
|
|
||||||
return ret;
|
return ret;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -166,8 +161,6 @@ function OutputStream(options) {
|
|||||||
str = String(str);
|
str = String(str);
|
||||||
var ch = str.charAt(0);
|
var ch = str.charAt(0);
|
||||||
if (might_need_semicolon) {
|
if (might_need_semicolon) {
|
||||||
might_need_semicolon = false;
|
|
||||||
|
|
||||||
if ((!ch || ";}".indexOf(ch) < 0) && !/[;]$/.test(last)) {
|
if ((!ch || ";}".indexOf(ch) < 0) && !/[;]$/.test(last)) {
|
||||||
if (options.semicolons || requireSemicolonChars(ch)) {
|
if (options.semicolons || requireSemicolonChars(ch)) {
|
||||||
OUTPUT += ";";
|
OUTPUT += ";";
|
||||||
@@ -178,17 +171,12 @@ function OutputStream(options) {
|
|||||||
current_pos++;
|
current_pos++;
|
||||||
current_line++;
|
current_line++;
|
||||||
current_col = 0;
|
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)
|
if (!options.beautify)
|
||||||
might_need_space = false;
|
might_need_space = 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]) {
|
||||||
@@ -382,13 +370,8 @@ function OutputStream(options) {
|
|||||||
nodetype.DEFMETHOD("_codegen", generator);
|
nodetype.DEFMETHOD("_codegen", generator);
|
||||||
};
|
};
|
||||||
|
|
||||||
var use_asm = false;
|
|
||||||
|
|
||||||
AST_Node.DEFMETHOD("print", function(stream, force_parens){
|
AST_Node.DEFMETHOD("print", function(stream, force_parens){
|
||||||
var self = this, generator = self._codegen, prev_use_asm = use_asm;
|
var self = this, generator = self._codegen;
|
||||||
if (self instanceof AST_Directive && self.value == "use asm") {
|
|
||||||
use_asm = true;
|
|
||||||
}
|
|
||||||
function doit() {
|
function doit() {
|
||||||
self.add_comments(stream);
|
self.add_comments(stream);
|
||||||
self.add_source_map(stream);
|
self.add_source_map(stream);
|
||||||
@@ -401,9 +384,6 @@ function OutputStream(options) {
|
|||||||
doit();
|
doit();
|
||||||
}
|
}
|
||||||
stream.pop_node();
|
stream.pop_node();
|
||||||
if (self instanceof AST_Lambda) {
|
|
||||||
use_asm = prev_use_asm;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
AST_Node.DEFMETHOD("print_to_string", function(options){
|
AST_Node.DEFMETHOD("print_to_string", function(options){
|
||||||
@@ -416,69 +396,63 @@ function OutputStream(options) {
|
|||||||
|
|
||||||
AST_Node.DEFMETHOD("add_comments", function(output){
|
AST_Node.DEFMETHOD("add_comments", function(output){
|
||||||
var c = output.option("comments"), self = this;
|
var c = output.option("comments"), self = this;
|
||||||
var start = self.start;
|
if (c) {
|
||||||
if (start && !start._comments_dumped) {
|
var start = self.start;
|
||||||
start._comments_dumped = true;
|
if (start && !start._comments_dumped) {
|
||||||
var comments = start.comments_before || [];
|
start._comments_dumped = true;
|
||||||
|
var comments = start.comments_before || [];
|
||||||
|
|
||||||
// XXX: ugly fix for https://github.com/mishoo/UglifyJS2/issues/112
|
// XXX: ugly fix for https://github.com/mishoo/UglifyJS2/issues/112
|
||||||
// and https://github.com/mishoo/UglifyJS2/issues/372
|
// and https://github.com/mishoo/UglifyJS2/issues/372
|
||||||
if (self instanceof AST_Exit && self.value) {
|
if (self instanceof AST_Exit && self.value) {
|
||||||
self.value.walk(new TreeWalker(function(node){
|
self.value.walk(new TreeWalker(function(node){
|
||||||
if (node.start && node.start.comments_before) {
|
if (node.start && node.start.comments_before) {
|
||||||
comments = comments.concat(node.start.comments_before);
|
comments = comments.concat(node.start.comments_before);
|
||||||
node.start.comments_before = [];
|
node.start.comments_before = [];
|
||||||
}
|
}
|
||||||
if (node instanceof AST_Function ||
|
if (node instanceof AST_Function ||
|
||||||
node instanceof AST_Array ||
|
node instanceof AST_Array ||
|
||||||
node instanceof AST_Object)
|
node instanceof AST_Object)
|
||||||
{
|
{
|
||||||
return true; // don't go inside.
|
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 comment.type == "comment5" || c.test(comment.value);
|
|
||||||
});
|
|
||||||
} else if (typeof c == "function") {
|
|
||||||
comments = comments.filter(function(comment){
|
|
||||||
return comment.type == "comment5" || 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 if (c.type == "comment2") {
|
|
||||||
output.print("/*" + c.value + "*/");
|
if (c.test) {
|
||||||
if (start.nlb) {
|
comments = comments.filter(function(comment){
|
||||||
output.print("\n");
|
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();
|
output.indent();
|
||||||
} else {
|
|
||||||
output.space();
|
|
||||||
}
|
}
|
||||||
}
|
else if (c.type == "comment2") {
|
||||||
else if (output.pos() === 0 && c.type == "comment5" && output.option("shebang")) {
|
output.print("/*" + c.value + "*/");
|
||||||
output.print("#!" + c.value + "\n");
|
if (start.nlb) {
|
||||||
output.indent();
|
output.print("\n");
|
||||||
}
|
output.indent();
|
||||||
});
|
} else {
|
||||||
|
output.space();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1057,24 +1031,16 @@ function OutputStream(options) {
|
|||||||
output.print(self.operator);
|
output.print(self.operator);
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_Binary, function(self, output){
|
DEFPRINT(AST_Binary, function(self, output){
|
||||||
var op = self.operator;
|
|
||||||
self.left.print(output);
|
self.left.print(output);
|
||||||
if (op[0] == ">" /* ">>" ">>>" ">" ">=" */
|
output.space();
|
||||||
&& self.left instanceof AST_UnaryPostfix
|
output.print(self.operator);
|
||||||
&& self.left.operator == "--") {
|
if (self.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 == "<<")
|
|
||||||
&& self.right instanceof AST_UnaryPrefix
|
&& self.right instanceof AST_UnaryPrefix
|
||||||
&& self.right.operator == "!"
|
&& self.right.operator == "!"
|
||||||
&& self.right.expression instanceof AST_UnaryPrefix
|
&& self.right.expression instanceof AST_UnaryPrefix
|
||||||
&& self.right.expression.operator == "--") {
|
&& self.right.expression.operator == "--") {
|
||||||
// space is mandatory to avoid outputting <!--
|
// space is mandatory to avoid outputting <!--
|
||||||
|
// http://javascript.spec.whatwg.org/#comment-syntax
|
||||||
output.print(" ");
|
output.print(" ");
|
||||||
} else {
|
} else {
|
||||||
// the space is optional depending on "beautify"
|
// the space is optional depending on "beautify"
|
||||||
@@ -1178,11 +1144,7 @@ function OutputStream(options) {
|
|||||||
output.print_string(self.getValue(), self.quote);
|
output.print_string(self.getValue(), self.quote);
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_Number, function(self, output){
|
DEFPRINT(AST_Number, function(self, output){
|
||||||
if (use_asm && self.start.raw != null) {
|
output.print(make_num(self.getValue()));
|
||||||
output.print(self.start.raw);
|
|
||||||
} else {
|
|
||||||
output.print(make_num(self.getValue()));
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
function regexp_safe_literal(code) {
|
function regexp_safe_literal(code) {
|
||||||
@@ -1358,12 +1320,6 @@ function OutputStream(options) {
|
|||||||
DEFMAP(AST_Finally, basic_sourcemap_gen);
|
DEFMAP(AST_Finally, basic_sourcemap_gen);
|
||||||
DEFMAP(AST_Definitions, basic_sourcemap_gen);
|
DEFMAP(AST_Definitions, basic_sourcemap_gen);
|
||||||
DEFMAP(AST_Constant, 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){
|
DEFMAP(AST_ObjectProperty, function(self, output){
|
||||||
output.add_mapping(self.start, self.key);
|
output.add_mapping(self.start, self.key);
|
||||||
});
|
});
|
||||||
|
|||||||
68
lib/parse.js
68
lib/parse.js
@@ -59,6 +59,7 @@ var OPERATOR_CHARS = makePredicate(characters("+-*&%=<>!?|~^"));
|
|||||||
|
|
||||||
var RE_HEX_NUMBER = /^0x[0-9a-f]+$/i;
|
var RE_HEX_NUMBER = /^0x[0-9a-f]+$/i;
|
||||||
var RE_OCT_NUMBER = /^0[0-7]+$/;
|
var RE_OCT_NUMBER = /^0[0-7]+$/;
|
||||||
|
var RE_DEC_NUMBER = /^\d*\.?\d*(?:e[+-]?\d*(?:\d\.?|\.?\d)\d*)?$/i;
|
||||||
|
|
||||||
var OPERATORS = makePredicate([
|
var OPERATORS = makePredicate([
|
||||||
"in",
|
"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("[{(,.;:"));
|
var PUNC_BEFORE_EXPRESSION = makePredicate(characters("[{(,.;:"));
|
||||||
|
|
||||||
@@ -181,15 +182,13 @@ function parse_js_number(num) {
|
|||||||
return parseInt(num.substr(2), 16);
|
return parseInt(num.substr(2), 16);
|
||||||
} else if (RE_OCT_NUMBER.test(num)) {
|
} else if (RE_OCT_NUMBER.test(num)) {
|
||||||
return parseInt(num.substr(1), 8);
|
return parseInt(num.substr(1), 8);
|
||||||
} else {
|
} else if (RE_DEC_NUMBER.test(num)) {
|
||||||
var val = parseFloat(num);
|
return parseFloat(num);
|
||||||
if (val == num) return val;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
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) {
|
||||||
@@ -210,10 +209,10 @@ function is_token(token, type, val) {
|
|||||||
|
|
||||||
var EX_EOF = {};
|
var EX_EOF = {};
|
||||||
|
|
||||||
function tokenizer($TEXT, filename, html5_comments, shebang) {
|
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,
|
||||||
@@ -285,9 +284,6 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|||||||
nlb : S.newline_before,
|
nlb : S.newline_before,
|
||||||
file : filename
|
file : filename
|
||||||
};
|
};
|
||||||
if (/^(?:num|string|regexp)$/i.test(type)) {
|
|
||||||
ret.raw = $TEXT.substring(ret.pos, ret.endpos);
|
|
||||||
}
|
|
||||||
if (!is_comment) {
|
if (!is_comment) {
|
||||||
ret.comments_before = S.comments_before;
|
ret.comments_before = S.comments_before;
|
||||||
S.comments_before = [];
|
S.comments_before = [];
|
||||||
@@ -301,8 +297,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function skip_whitespace() {
|
function skip_whitespace() {
|
||||||
var ch;
|
while (WHITESPACE_CHARS(peek()))
|
||||||
while (WHITESPACE_CHARS(ch = peek()) || ch == "\u2028" || ch == "\u2029")
|
|
||||||
next();
|
next();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -357,13 +352,8 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|||||||
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) {
|
||||||
@@ -380,7 +370,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|||||||
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
|
||||||
@@ -399,7 +389,6 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|||||||
if (octal_len > 0) ch = String.fromCharCode(parseInt(ch, 8));
|
if (octal_len > 0) ch = String.fromCharCode(parseInt(ch, 8));
|
||||||
else ch = read_escaped_char(true);
|
else ch = read_escaped_char(true);
|
||||||
}
|
}
|
||||||
else if ("\r\n\u2028\u2029".indexOf(ch) >= 0) parse_error("Unterminated string constant");
|
|
||||||
else if (ch == quote) break;
|
else if (ch == quote) break;
|
||||||
ret += ch;
|
ret += ch;
|
||||||
}
|
}
|
||||||
@@ -484,11 +473,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|||||||
regexp += ch;
|
regexp += ch;
|
||||||
}
|
}
|
||||||
var mods = read_name();
|
var mods = read_name();
|
||||||
try {
|
return token("regexp", new RegExp(regexp, mods));
|
||||||
return token("regexp", new RegExp(regexp, mods));
|
|
||||||
} catch(e) {
|
|
||||||
parse_error(e.message);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
function read_operator(prefix) {
|
function read_operator(prefix) {
|
||||||
@@ -572,13 +557,6 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|||||||
if (PUNC_CHARS(ch)) return token("punc", next());
|
if (PUNC_CHARS(ch)) return token("punc", next());
|
||||||
if (OPERATOR_CHARS(ch)) return read_operator();
|
if (OPERATOR_CHARS(ch)) return read_operator();
|
||||||
if (code == 92 || is_identifier_start(code)) return read_word();
|
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 + "'");
|
parse_error("Unexpected character '" + ch + "'");
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -648,13 +626,12 @@ function parse($TEXT, options) {
|
|||||||
expression : false,
|
expression : false,
|
||||||
html5_comments : true,
|
html5_comments : true,
|
||||||
bare_returns : false,
|
bare_returns : false,
|
||||||
shebang : true,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
var S = {
|
var S = {
|
||||||
input : (typeof $TEXT == "string"
|
input : (typeof $TEXT == "string"
|
||||||
? tokenizer($TEXT, options.filename,
|
? tokenizer($TEXT, options.filename,
|
||||||
options.html5_comments, options.shebang)
|
options.html5_comments)
|
||||||
: $TEXT),
|
: $TEXT),
|
||||||
token : null,
|
token : null,
|
||||||
prev : null,
|
prev : null,
|
||||||
@@ -725,9 +702,9 @@ function parse($TEXT, options) {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
function semicolon(optional) {
|
function semicolon() {
|
||||||
if (is("punc", ";")) next();
|
if (is("punc", ";")) next();
|
||||||
else if (!optional && !can_insert_semicolon()) unexpected();
|
else if (!can_insert_semicolon()) unexpected();
|
||||||
};
|
};
|
||||||
|
|
||||||
function parenthesised() {
|
function parenthesised() {
|
||||||
@@ -815,7 +792,7 @@ function parse($TEXT, options) {
|
|||||||
case "do":
|
case "do":
|
||||||
return new AST_Do({
|
return new AST_Do({
|
||||||
body : in_loop(statement),
|
body : in_loop(statement),
|
||||||
condition : (expect_token("keyword", "while"), tmp = parenthesised(), semicolon(true), tmp)
|
condition : (expect_token("keyword", "while"), tmp = parenthesised(), semicolon(), tmp)
|
||||||
});
|
});
|
||||||
|
|
||||||
case "while":
|
case "while":
|
||||||
@@ -1126,7 +1103,7 @@ function parse($TEXT, options) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
var new_ = function(allow_calls) {
|
var new_ = function() {
|
||||||
var start = S.token;
|
var start = S.token;
|
||||||
expect_token("operator", "new");
|
expect_token("operator", "new");
|
||||||
var newexp = expr_atom(false), args;
|
var newexp = expr_atom(false), args;
|
||||||
@@ -1141,7 +1118,7 @@ function parse($TEXT, options) {
|
|||||||
expression : newexp,
|
expression : newexp,
|
||||||
args : args,
|
args : args,
|
||||||
end : prev()
|
end : prev()
|
||||||
}), allow_calls);
|
}), true);
|
||||||
};
|
};
|
||||||
|
|
||||||
function as_atom_node() {
|
function as_atom_node() {
|
||||||
@@ -1178,13 +1155,6 @@ function parse($TEXT, options) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "operator":
|
|
||||||
if (!is_identifier_string(tok.value)) {
|
|
||||||
throw new JS_Parse_Error("Invalid getter/setter name: " + tok.value,
|
|
||||||
tok.file, tok.line, tok.col, tok.pos);
|
|
||||||
}
|
|
||||||
ret = _make_symbol(AST_SymbolRef);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
next();
|
next();
|
||||||
return ret;
|
return ret;
|
||||||
@@ -1192,7 +1162,7 @@ function parse($TEXT, options) {
|
|||||||
|
|
||||||
var expr_atom = function(allow_calls) {
|
var expr_atom = function(allow_calls) {
|
||||||
if (is("operator", "new")) {
|
if (is("operator", "new")) {
|
||||||
return new_(allow_calls);
|
return new_();
|
||||||
}
|
}
|
||||||
var start = S.token;
|
var start = S.token;
|
||||||
if (is("punc")) {
|
if (is("punc")) {
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
102
lib/scope.js
102
lib/scope.js
@@ -67,34 +67,24 @@ 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
|
||||||
var self = this;
|
var self = this;
|
||||||
var scope = self.parent_scope = null;
|
var scope = self.parent_scope = null;
|
||||||
var labels = new Dictionary();
|
|
||||||
var defun = null;
|
var defun = null;
|
||||||
var last_var_had_const_pragma = false;
|
|
||||||
var nesting = 0;
|
var nesting = 0;
|
||||||
var tw = new TreeWalker(function(node, descend){
|
var tw = new TreeWalker(function(node, descend){
|
||||||
if (options.screw_ie8 && node instanceof AST_Catch) {
|
if (options.screw_ie8 && node instanceof AST_Catch) {
|
||||||
@@ -110,24 +100,16 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
|
|||||||
node.init_scope_vars(nesting);
|
node.init_scope_vars(nesting);
|
||||||
var save_scope = node.parent_scope = scope;
|
var save_scope = node.parent_scope = scope;
|
||||||
var save_defun = defun;
|
var save_defun = defun;
|
||||||
var save_labels = labels;
|
|
||||||
defun = scope = node;
|
defun = scope = node;
|
||||||
labels = new Dictionary();
|
|
||||||
++nesting; descend(); --nesting;
|
++nesting; descend(); --nesting;
|
||||||
scope = save_scope;
|
scope = save_scope;
|
||||||
defun = save_defun;
|
defun = save_defun;
|
||||||
labels = save_labels;
|
|
||||||
return true; // don't descend again in TreeWalker
|
return true; // don't descend again in TreeWalker
|
||||||
}
|
}
|
||||||
if (node instanceof AST_LabeledStatement) {
|
if (node instanceof AST_Directive) {
|
||||||
var l = node.label;
|
node.scope = scope;
|
||||||
if (labels.has(l.name)) {
|
push_uniq(scope.directives, node.value);
|
||||||
throw new Error(string_template("Label {name} defined twice", l));
|
return true;
|
||||||
}
|
|
||||||
labels.set(l.name, l);
|
|
||||||
descend();
|
|
||||||
labels.del(l.name);
|
|
||||||
return true; // no descend again
|
|
||||||
}
|
}
|
||||||
if (node instanceof AST_With) {
|
if (node instanceof AST_With) {
|
||||||
for (var s = scope; s; s = s.parent_scope)
|
for (var s = scope; s; s = s.parent_scope)
|
||||||
@@ -137,10 +119,6 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
|
|||||||
if (node instanceof AST_Symbol) {
|
if (node instanceof AST_Symbol) {
|
||||||
node.scope = scope;
|
node.scope = scope;
|
||||||
}
|
}
|
||||||
if (node instanceof AST_Label) {
|
|
||||||
node.thedef = node;
|
|
||||||
node.references = [];
|
|
||||||
}
|
|
||||||
if (node instanceof AST_SymbolLambda) {
|
if (node instanceof AST_SymbolLambda) {
|
||||||
defun.def_function(node);
|
defun.def_function(node);
|
||||||
}
|
}
|
||||||
@@ -152,28 +130,16 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
|
|||||||
// later.
|
// later.
|
||||||
(node.scope = defun.parent_scope).def_function(node);
|
(node.scope = defun.parent_scope).def_function(node);
|
||||||
}
|
}
|
||||||
else if (node instanceof AST_Var) {
|
|
||||||
last_var_had_const_pragma = node.has_const_pragma();
|
|
||||||
}
|
|
||||||
else if (node instanceof AST_SymbolVar
|
else if (node instanceof AST_SymbolVar
|
||||||
|| node instanceof AST_SymbolConst) {
|
|| node instanceof AST_SymbolConst) {
|
||||||
var def = defun.def_variable(node);
|
var def = defun.def_variable(node);
|
||||||
def.constant = node instanceof AST_SymbolConst || last_var_had_const_pragma;
|
def.constant = node instanceof AST_SymbolConst;
|
||||||
def.init = tw.parent().value;
|
def.init = tw.parent().value;
|
||||||
}
|
}
|
||||||
else if (node instanceof AST_SymbolCatch) {
|
else if (node instanceof AST_SymbolCatch) {
|
||||||
(options.screw_ie8 ? scope : defun)
|
(options.screw_ie8 ? scope : defun)
|
||||||
.def_variable(node);
|
.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);
|
self.walk(tw);
|
||||||
|
|
||||||
@@ -188,17 +154,8 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
|
|||||||
func = prev_func;
|
func = prev_func;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (node instanceof AST_LoopControl && node.label) {
|
|
||||||
node.label.thedef.references.push(node);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (node instanceof AST_SymbolRef) {
|
if (node instanceof AST_SymbolRef) {
|
||||||
var name = node.name;
|
var name = node.name;
|
||||||
if (name == "eval" && tw.parent() instanceof AST_Call) {
|
|
||||||
for (var s = node.scope; s && !s.uses_eval; s = s.parent_scope) {
|
|
||||||
s.uses_eval = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var sym = node.scope.find_variable(name);
|
var sym = node.scope.find_variable(name);
|
||||||
if (!sym) {
|
if (!sym) {
|
||||||
var g;
|
var g;
|
||||||
@@ -211,6 +168,10 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
|
|||||||
globals.set(name, g);
|
globals.set(name, g);
|
||||||
}
|
}
|
||||||
node.thedef = g;
|
node.thedef = g;
|
||||||
|
if (name == "eval" && tw.parent() instanceof AST_Call) {
|
||||||
|
for (var s = node.scope; s && !s.uses_eval; s = s.parent_scope)
|
||||||
|
s.uses_eval = true;
|
||||||
|
}
|
||||||
if (func && name == "arguments") {
|
if (func && name == "arguments") {
|
||||||
func.uses_arguments = true;
|
func.uses_arguments = true;
|
||||||
}
|
}
|
||||||
@@ -222,13 +183,10 @@ 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){
|
||||||
|
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.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.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
|
this.uses_with = false; // will be set to true if this or some nested scope uses the `with` statement
|
||||||
@@ -239,13 +197,13 @@ AST_Scope.DEFMETHOD("init_scope_vars", function(nesting){
|
|||||||
this.nesting = nesting; // the nesting level of this scope (0 means toplevel)
|
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_Lambda.DEFMETHOD("init_scope_vars", function(){
|
||||||
AST_Scope.prototype.init_scope_vars.apply(this, arguments);
|
AST_Scope.prototype.init_scope_vars.apply(this, arguments);
|
||||||
this.uses_arguments = false;
|
this.uses_arguments = false;
|
||||||
|
|
||||||
var symbol = new AST_VarDef({ name: "arguments", start: this.start, end: this.end });
|
|
||||||
var def = new SymbolDef(this, this.variables.size(), symbol);
|
|
||||||
this.variables.set(symbol.name, def);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
AST_SymbolRef.DEFMETHOD("reference", function() {
|
AST_SymbolRef.DEFMETHOD("reference", function() {
|
||||||
@@ -266,6 +224,11 @@ AST_Scope.DEFMETHOD("find_variable", function(name){
|
|||||||
|| (this.parent_scope && this.parent_scope.find_variable(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){
|
AST_Scope.DEFMETHOD("def_function", function(symbol){
|
||||||
this.functions.set(symbol.name, this.def_variable(symbol));
|
this.functions.set(symbol.name, this.def_variable(symbol));
|
||||||
});
|
});
|
||||||
@@ -362,12 +325,6 @@ AST_Symbol.DEFMETHOD("global", function(){
|
|||||||
return this.definition().global;
|
return this.definition().global;
|
||||||
});
|
});
|
||||||
|
|
||||||
AST_Var.DEFMETHOD("has_const_pragma", function() {
|
|
||||||
var comments_before = this.start && this.start.comments_before;
|
|
||||||
var lastComment = comments_before && comments_before[comments_before.length - 1];
|
|
||||||
return lastComment && /@const\b/.test(lastComment.value);
|
|
||||||
});
|
|
||||||
|
|
||||||
AST_Toplevel.DEFMETHOD("_default_mangler_options", function(options){
|
AST_Toplevel.DEFMETHOD("_default_mangler_options", function(options){
|
||||||
return defaults(options, {
|
return defaults(options, {
|
||||||
except : [],
|
except : [],
|
||||||
@@ -381,25 +338,12 @@ AST_Toplevel.DEFMETHOD("_default_mangler_options", function(options){
|
|||||||
|
|
||||||
AST_Toplevel.DEFMETHOD("mangle_names", function(options){
|
AST_Toplevel.DEFMETHOD("mangle_names", function(options){
|
||||||
options = this._default_mangler_options(options);
|
options = this._default_mangler_options(options);
|
||||||
|
|
||||||
// Never mangle arguments
|
|
||||||
options.except.push('arguments');
|
|
||||||
|
|
||||||
// We only need to mangle declaration nodes. Special logic wired
|
// We only need to mangle declaration nodes. Special logic wired
|
||||||
// into the code generator will display the mangled name if it's
|
// into the code generator will display the mangled name if it's
|
||||||
// present (and for AST_SymbolRef-s it'll use the mangled name of
|
// present (and for AST_SymbolRef-s it'll use the mangled name of
|
||||||
// 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
|
||||||
@@ -434,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){
|
||||||
|
|||||||
@@ -53,11 +53,16 @@ function SourceMap(options) {
|
|||||||
orig_line_diff : 0,
|
orig_line_diff : 0,
|
||||||
dest_line_diff : 0,
|
dest_line_diff : 0,
|
||||||
});
|
});
|
||||||
var generator = new MOZ_SourceMap.SourceMapGenerator({
|
|
||||||
file : options.file,
|
|
||||||
sourceRoot : options.root
|
|
||||||
});
|
|
||||||
var orig_map = options.orig && new MOZ_SourceMap.SourceMapConsumer(options.orig);
|
var orig_map = options.orig && new MOZ_SourceMap.SourceMapConsumer(options.orig);
|
||||||
|
var generator;
|
||||||
|
if (orig_map) {
|
||||||
|
generator = MOZ_SourceMap.SourceMapGenerator.fromSourceMap(orig_map);
|
||||||
|
} else {
|
||||||
|
generator = new MOZ_SourceMap.SourceMapGenerator({
|
||||||
|
file : options.file,
|
||||||
|
sourceRoot : options.root
|
||||||
|
});
|
||||||
|
}
|
||||||
function add(source, gen_line, gen_col, orig_line, orig_col, name) {
|
function add(source, gen_line, gen_col, orig_line, orig_col, name) {
|
||||||
if (orig_map) {
|
if (orig_map) {
|
||||||
var info = orig_map.originalPositionFor({
|
var info = orig_map.originalPositionFor({
|
||||||
@@ -78,7 +83,7 @@ function SourceMap(options) {
|
|||||||
source : source,
|
source : source,
|
||||||
name : name
|
name : name
|
||||||
});
|
});
|
||||||
};
|
}
|
||||||
return {
|
return {
|
||||||
add : add,
|
add : add,
|
||||||
get : function() { return generator },
|
get : function() { return generator },
|
||||||
|
|||||||
@@ -64,13 +64,13 @@ TreeTransformer.prototype = new TreeWalker;
|
|||||||
x = this;
|
x = this;
|
||||||
descend(x, tw);
|
descend(x, tw);
|
||||||
} else {
|
} else {
|
||||||
tw.stack[tw.stack.length - 1] = x = this;
|
tw.stack[tw.stack.length - 1] = x = this.clone();
|
||||||
descend(x, tw);
|
descend(x, tw);
|
||||||
y = tw.after(x, in_list);
|
y = tw.after(x, in_list);
|
||||||
if (y !== undefined) x = y;
|
if (y !== undefined) x = y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tw.pop(this);
|
tw.pop();
|
||||||
return x;
|
return x;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
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;
|
|
||||||
};
|
};
|
||||||
|
|||||||
128
npm-shrinkwrap.json
generated
128
npm-shrinkwrap.json
generated
@@ -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"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
83
package.json
83
package.json
@@ -1,54 +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-2-Clause",
|
"version": "2.4.17",
|
||||||
"version": "2.6.2",
|
"engines": { "node" : ">=0.4.0" },
|
||||||
"engines": {
|
"maintainers": [{
|
||||||
"node": ">=0.8.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.5.1",
|
"uglifyjs" : "bin/uglifyjs"
|
||||||
"uglify-to-browserify": "~1.0.0",
|
},
|
||||||
"yargs": "~3.10.0"
|
"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",
|
|
||||||
"mocha": "~2.3.4"
|
|
||||||
},
|
|
||||||
"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"
|
|
||||||
},
|
|
||||||
"keywords": ["uglify", "uglify-js", "minify", "minifier"]
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -332,19 +318,15 @@ cond_7_1: {
|
|||||||
cond_8: {
|
cond_8: {
|
||||||
options = {
|
options = {
|
||||||
conditionals: true,
|
conditionals: true,
|
||||||
evaluate : true,
|
evaluate : true
|
||||||
booleans : false
|
|
||||||
};
|
};
|
||||||
input: {
|
input: {
|
||||||
var a;
|
|
||||||
// compress these
|
// compress these
|
||||||
a = condition ? true : false;
|
a = condition ? true : false;
|
||||||
a = !condition ? true : false;
|
|
||||||
a = condition() ? true : false;
|
|
||||||
|
|
||||||
a = condition ? !0 : !1;
|
a = !condition ? true : false;
|
||||||
a = !condition ? !null : !2;
|
|
||||||
a = condition() ? !0 : !-3.5;
|
a = condition() ? true : false;
|
||||||
|
|
||||||
if (condition) {
|
if (condition) {
|
||||||
a = true;
|
a = true;
|
||||||
@@ -352,19 +334,11 @@ cond_8: {
|
|||||||
a = false;
|
a = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (condition) {
|
|
||||||
a = !0;
|
|
||||||
} else {
|
|
||||||
a = !1;
|
|
||||||
}
|
|
||||||
|
|
||||||
a = condition ? false : true;
|
a = condition ? false : true;
|
||||||
a = !condition ? false : true;
|
|
||||||
a = condition() ? false : true;
|
|
||||||
|
|
||||||
a = condition ? !3 : !0;
|
a = !condition ? false : true;
|
||||||
a = !condition ? !2 : !0;
|
|
||||||
a = condition() ? !1 : !0;
|
a = condition() ? false : true;
|
||||||
|
|
||||||
if (condition) {
|
if (condition) {
|
||||||
a = false;
|
a = false;
|
||||||
@@ -372,443 +346,25 @@ cond_8: {
|
|||||||
a = true;
|
a = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (condition) {
|
|
||||||
a = !1;
|
|
||||||
} else {
|
|
||||||
a = !0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// don't compress these
|
// don't compress these
|
||||||
a = condition ? 1 : false;
|
a = condition ? 1 : false;
|
||||||
|
|
||||||
a = !condition ? true : 0;
|
a = !condition ? true : 0;
|
||||||
|
|
||||||
a = condition ? 1 : 0;
|
a = condition ? 1 : 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var a;
|
|
||||||
a = !!condition;
|
a = !!condition;
|
||||||
a = !condition;
|
a = !condition;
|
||||||
a = !!condition();
|
a = !!condition();
|
||||||
|
|
||||||
a = !!condition;
|
a = !!condition;
|
||||||
a = !condition;
|
|
||||||
a = !!condition();
|
|
||||||
|
|
||||||
a = !!condition;
|
|
||||||
a = !!condition;
|
|
||||||
|
|
||||||
a = !condition;
|
a = !condition;
|
||||||
a = !!condition;
|
a = !!condition;
|
||||||
a = !condition();
|
a = !condition();
|
||||||
|
|
||||||
a = !condition;
|
a = !condition;
|
||||||
a = !!condition;
|
|
||||||
a = !condition();
|
|
||||||
|
|
||||||
a = !condition;
|
|
||||||
a = !condition;
|
|
||||||
|
|
||||||
a = condition ? 1 : false;
|
a = condition ? 1 : false;
|
||||||
a = condition ? 0 : true;
|
a = condition ? 0 : true;
|
||||||
a = condition ? 1 : 0;
|
a = condition ? 1 : 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cond_8b: {
|
|
||||||
options = {
|
|
||||||
conditionals: true,
|
|
||||||
evaluate : true,
|
|
||||||
booleans : true
|
|
||||||
};
|
|
||||||
input: {
|
|
||||||
var a;
|
|
||||||
// compress these
|
|
||||||
a = condition ? true : false;
|
|
||||||
a = !condition ? true : false;
|
|
||||||
a = condition() ? true : false;
|
|
||||||
|
|
||||||
a = condition ? !0 : !1;
|
|
||||||
a = !condition ? !null : !2;
|
|
||||||
a = condition() ? !0 : !-3.5;
|
|
||||||
|
|
||||||
if (condition) {
|
|
||||||
a = true;
|
|
||||||
} else {
|
|
||||||
a = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (condition) {
|
|
||||||
a = !0;
|
|
||||||
} else {
|
|
||||||
a = !1;
|
|
||||||
}
|
|
||||||
|
|
||||||
a = condition ? false : true;
|
|
||||||
a = !condition ? false : true;
|
|
||||||
a = condition() ? false : true;
|
|
||||||
|
|
||||||
a = condition ? !3 : !0;
|
|
||||||
a = !condition ? !2 : !0;
|
|
||||||
a = condition() ? !1 : !0;
|
|
||||||
|
|
||||||
if (condition) {
|
|
||||||
a = false;
|
|
||||||
} else {
|
|
||||||
a = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (condition) {
|
|
||||||
a = !1;
|
|
||||||
} else {
|
|
||||||
a = !0;
|
|
||||||
}
|
|
||||||
|
|
||||||
a = condition ? 1 : false;
|
|
||||||
a = !condition ? true : 0;
|
|
||||||
a = condition ? 1 : 0;
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
var a;
|
|
||||||
a = !!condition;
|
|
||||||
a = !condition;
|
|
||||||
a = !!condition();
|
|
||||||
|
|
||||||
a = !!condition;
|
|
||||||
a = !condition;
|
|
||||||
a = !!condition();
|
|
||||||
|
|
||||||
a = !!condition;
|
|
||||||
a = !!condition;
|
|
||||||
|
|
||||||
a = !condition;
|
|
||||||
a = !!condition;
|
|
||||||
a = !condition();
|
|
||||||
|
|
||||||
a = !condition;
|
|
||||||
a = !!condition;
|
|
||||||
a = !condition();
|
|
||||||
|
|
||||||
a = !condition;
|
|
||||||
a = !condition;
|
|
||||||
|
|
||||||
a = condition ? 1 : !1;
|
|
||||||
a = condition ? 0 : !0;
|
|
||||||
a = condition ? 1 : 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cond_8c: {
|
|
||||||
options = {
|
|
||||||
conditionals: true,
|
|
||||||
evaluate : false,
|
|
||||||
booleans : false
|
|
||||||
};
|
|
||||||
input: {
|
|
||||||
var a;
|
|
||||||
// compress these
|
|
||||||
a = condition ? true : false;
|
|
||||||
a = !condition ? true : false;
|
|
||||||
a = condition() ? true : false;
|
|
||||||
|
|
||||||
a = condition ? !0 : !1;
|
|
||||||
a = !condition ? !null : !2;
|
|
||||||
a = condition() ? !0 : !-3.5;
|
|
||||||
|
|
||||||
if (condition) {
|
|
||||||
a = true;
|
|
||||||
} else {
|
|
||||||
a = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (condition) {
|
|
||||||
a = !0;
|
|
||||||
} else {
|
|
||||||
a = !1;
|
|
||||||
}
|
|
||||||
|
|
||||||
a = condition ? false : true;
|
|
||||||
a = !condition ? false : true;
|
|
||||||
a = condition() ? false : true;
|
|
||||||
|
|
||||||
a = condition ? !3 : !0;
|
|
||||||
a = !condition ? !2 : !0;
|
|
||||||
a = condition() ? !1 : !0;
|
|
||||||
|
|
||||||
if (condition) {
|
|
||||||
a = false;
|
|
||||||
} else {
|
|
||||||
a = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (condition) {
|
|
||||||
a = !1;
|
|
||||||
} else {
|
|
||||||
a = !0;
|
|
||||||
}
|
|
||||||
|
|
||||||
a = condition ? 1 : false;
|
|
||||||
a = !condition ? true : 0;
|
|
||||||
a = condition ? 1 : 0;
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
var a;
|
|
||||||
a = !!condition;
|
|
||||||
a = !condition;
|
|
||||||
a = !!condition();
|
|
||||||
|
|
||||||
a = !!condition;
|
|
||||||
a = !condition;
|
|
||||||
a = condition() ? !0 : !-3.5;
|
|
||||||
|
|
||||||
a = !!condition;
|
|
||||||
a = !!condition;
|
|
||||||
|
|
||||||
a = !condition;
|
|
||||||
a = !!condition;
|
|
||||||
a = !condition();
|
|
||||||
|
|
||||||
a = !condition;
|
|
||||||
a = !!condition;
|
|
||||||
a = !condition();
|
|
||||||
|
|
||||||
a = !condition;
|
|
||||||
a = !condition;
|
|
||||||
|
|
||||||
a = condition ? 1 : false;
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
trivial_boolean_ternary_expressions : {
|
|
||||||
options = {
|
|
||||||
conditionals: true,
|
|
||||||
evaluate : true,
|
|
||||||
booleans : true
|
|
||||||
};
|
|
||||||
input: {
|
|
||||||
f('foo' in m ? true : false);
|
|
||||||
f('foo' in m ? false : true);
|
|
||||||
|
|
||||||
f(g ? true : false);
|
|
||||||
f(foo() ? true : false);
|
|
||||||
f("bar" ? true : false);
|
|
||||||
f(5 ? true : false);
|
|
||||||
f(5.7 ? true : false);
|
|
||||||
f(x - y ? true : false);
|
|
||||||
|
|
||||||
f(x == y ? true : false);
|
|
||||||
f(x === y ? !0 : !1);
|
|
||||||
f(x < y ? !0 : false);
|
|
||||||
f(x <= y ? true : false);
|
|
||||||
f(x > y ? true : !1);
|
|
||||||
f(x >= y ? !0 : !1);
|
|
||||||
|
|
||||||
f(g ? false : true);
|
|
||||||
f(foo() ? false : true);
|
|
||||||
f("bar" ? false : true);
|
|
||||||
f(5 ? false : true);
|
|
||||||
f(5.7 ? false : true);
|
|
||||||
f(x - y ? false : true);
|
|
||||||
|
|
||||||
f(x == y ? !1 : !0);
|
|
||||||
f(x === y ? false : true);
|
|
||||||
|
|
||||||
f(x < y ? false : true);
|
|
||||||
f(x <= y ? false : !0);
|
|
||||||
f(x > y ? !1 : true);
|
|
||||||
f(x >= y ? !1 : !0);
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
f('foo' in m);
|
|
||||||
f(!('foo' in m));
|
|
||||||
|
|
||||||
f(!!g);
|
|
||||||
f(!!foo());
|
|
||||||
f(!0);
|
|
||||||
f(!0);
|
|
||||||
f(!0);
|
|
||||||
f(!!(x - y));
|
|
||||||
|
|
||||||
f(x == y);
|
|
||||||
f(x === y);
|
|
||||||
f(x < y);
|
|
||||||
f(x <= y);
|
|
||||||
f(x > y);
|
|
||||||
f(x >= y);
|
|
||||||
|
|
||||||
f(!g);
|
|
||||||
f(!foo());
|
|
||||||
f(!1);
|
|
||||||
f(!1);
|
|
||||||
f(!1);
|
|
||||||
f(!(x - y));
|
|
||||||
|
|
||||||
f(x != y);
|
|
||||||
f(x !== y);
|
|
||||||
|
|
||||||
f(!(x < y));
|
|
||||||
f(!(x <= y));
|
|
||||||
f(!(x > y));
|
|
||||||
f(!(x >= y));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -87,120 +87,3 @@ dead_code_constant_boolean_should_warn_more: {
|
|||||||
var moo;
|
var moo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dead_code_const_declaration: {
|
|
||||||
options = {
|
|
||||||
dead_code : true,
|
|
||||||
loops : true,
|
|
||||||
booleans : true,
|
|
||||||
conditionals : true,
|
|
||||||
evaluate : true
|
|
||||||
};
|
|
||||||
input: {
|
|
||||||
var unused;
|
|
||||||
const CONST_FOO = false;
|
|
||||||
if (CONST_FOO) {
|
|
||||||
console.log("unreachable");
|
|
||||||
var moo;
|
|
||||||
function bar() {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
var unused;
|
|
||||||
const CONST_FOO = !1;
|
|
||||||
var moo;
|
|
||||||
function bar() {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dead_code_const_annotation: {
|
|
||||||
options = {
|
|
||||||
dead_code : true,
|
|
||||||
loops : true,
|
|
||||||
booleans : true,
|
|
||||||
conditionals : true,
|
|
||||||
evaluate : true
|
|
||||||
};
|
|
||||||
input: {
|
|
||||||
var unused;
|
|
||||||
/** @const */ var CONST_FOO_ANN = false;
|
|
||||||
if (CONST_FOO_ANN) {
|
|
||||||
console.log("unreachable");
|
|
||||||
var moo;
|
|
||||||
function bar() {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
var unused;
|
|
||||||
var CONST_FOO_ANN = !1;
|
|
||||||
var moo;
|
|
||||||
function bar() {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dead_code_const_annotation_regex: {
|
|
||||||
options = {
|
|
||||||
dead_code : true,
|
|
||||||
loops : true,
|
|
||||||
booleans : true,
|
|
||||||
conditionals : true,
|
|
||||||
evaluate : true
|
|
||||||
};
|
|
||||||
input: {
|
|
||||||
var unused;
|
|
||||||
// @constraint this shouldn't be a constant
|
|
||||||
var CONST_FOO_ANN = false;
|
|
||||||
if (CONST_FOO_ANN) {
|
|
||||||
console.log("reachable");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
var unused;
|
|
||||||
var CONST_FOO_ANN = !1;
|
|
||||||
CONST_FOO_ANN && console.log('reachable');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dead_code_const_annotation_complex_scope: {
|
|
||||||
options = {
|
|
||||||
dead_code : true,
|
|
||||||
loops : true,
|
|
||||||
booleans : true,
|
|
||||||
conditionals : true,
|
|
||||||
evaluate : true
|
|
||||||
};
|
|
||||||
input: {
|
|
||||||
var unused_var;
|
|
||||||
/** @const */ var test = 'test';
|
|
||||||
// @const
|
|
||||||
var CONST_FOO_ANN = false;
|
|
||||||
var unused_var_2;
|
|
||||||
if (CONST_FOO_ANN) {
|
|
||||||
console.log("unreachable");
|
|
||||||
var moo;
|
|
||||||
function bar() {}
|
|
||||||
}
|
|
||||||
if (test === 'test') {
|
|
||||||
var beef = 'good';
|
|
||||||
/** @const */ var meat = 'beef';
|
|
||||||
var pork = 'bad';
|
|
||||||
if (meat === 'pork') {
|
|
||||||
console.log('also unreachable');
|
|
||||||
} else if (pork === 'good') {
|
|
||||||
console.log('reached, not const');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
var unused_var;
|
|
||||||
var test = 'test';
|
|
||||||
var CONST_FOO_ANN = !1;
|
|
||||||
var unused_var_2;
|
|
||||||
var moo;
|
|
||||||
function bar() {}
|
|
||||||
var beef = 'good';
|
|
||||||
var meat = 'beef';
|
|
||||||
var pork = 'bad';
|
|
||||||
'good' === pork && console.log('reached, not const');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
unused_funarg_1: {
|
unused_funarg_1: {
|
||||||
options = { unused: true, keep_fargs: false };
|
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, keep_fargs: false };
|
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) {};
|
||||||
@@ -173,7 +173,7 @@ keep_fnames: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
function foo() {
|
function foo() {
|
||||||
return function bar(baz) {};
|
return function bar() {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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"}';
|
|
||||||
}
|
|
||||||
@@ -9,50 +9,3 @@ keep_name_of_setter: {
|
|||||||
input: { a = { set foo () {} } }
|
input: { a = { set foo () {} } }
|
||||||
expect: { a = { set foo () {} } }
|
expect: { a = { set foo () {} } }
|
||||||
}
|
}
|
||||||
|
|
||||||
setter_with_operator_keys: {
|
|
||||||
input: {
|
|
||||||
var tokenCodes = {
|
|
||||||
get instanceof(){
|
|
||||||
return test0;
|
|
||||||
},
|
|
||||||
set instanceof(value){
|
|
||||||
test0 = value;
|
|
||||||
},
|
|
||||||
set typeof(value){
|
|
||||||
test1 = value;
|
|
||||||
},
|
|
||||||
get typeof(){
|
|
||||||
return test1;
|
|
||||||
},
|
|
||||||
set else(value){
|
|
||||||
test2 = value;
|
|
||||||
},
|
|
||||||
get else(){
|
|
||||||
return test2;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
var tokenCodes = {
|
|
||||||
get instanceof(){
|
|
||||||
return test0;
|
|
||||||
},
|
|
||||||
set instanceof(value){
|
|
||||||
test0 = value;
|
|
||||||
},
|
|
||||||
set typeof(value){
|
|
||||||
test1 = value;
|
|
||||||
},
|
|
||||||
get typeof(){
|
|
||||||
return test1;
|
|
||||||
},
|
|
||||||
set else(value){
|
|
||||||
test2 = value;
|
|
||||||
},
|
|
||||||
get else(){
|
|
||||||
return test2;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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; }
|
|
||||||
}
|
|
||||||
@@ -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,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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
remove_redundant_sequence_items: {
|
|
||||||
options = { side_effects: true };
|
|
||||||
input: {
|
|
||||||
(0, 1, eval)();
|
|
||||||
(0, 1, logThis)();
|
|
||||||
(0, 1, _decorators.logThis)();
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
(0, eval)();
|
|
||||||
logThis();
|
|
||||||
(0, _decorators.logThis)();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dont_remove_this_binding_sequence: {
|
|
||||||
options = { side_effects: true };
|
|
||||||
input: {
|
|
||||||
(0, eval)();
|
|
||||||
(0, logThis)();
|
|
||||||
(0, _decorators.logThis)();
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
(0, eval)();
|
|
||||||
logThis();
|
|
||||||
(0, _decorators.logThis)();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
dont_mangle_arguments: {
|
|
||||||
mangle = {
|
|
||||||
};
|
|
||||||
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 : false
|
|
||||||
};
|
|
||||||
input: {
|
|
||||||
(function(){
|
|
||||||
var arguments = arguments, not_arguments = 9;
|
|
||||||
console.log(not_arguments, arguments);
|
|
||||||
})(5,6,7);
|
|
||||||
}
|
|
||||||
expect_exact: "(function(){var arguments=arguments,o=9;console.log(o,arguments)})(5,6,7);"
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
keep_var_for_in: {
|
|
||||||
options = {
|
|
||||||
hoist_vars: true,
|
|
||||||
unused: true
|
|
||||||
};
|
|
||||||
input: {
|
|
||||||
(function(obj){
|
|
||||||
var foo = 5;
|
|
||||||
for (var i in obj)
|
|
||||||
return foo;
|
|
||||||
})();
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
(function(obj){
|
|
||||||
var i, foo = 5;
|
|
||||||
for (i in obj)
|
|
||||||
return foo;
|
|
||||||
})();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,96 +0,0 @@
|
|||||||
this_binding_conditionals: {
|
|
||||||
options = {
|
|
||||||
conditionals: true,
|
|
||||||
evaluate : true
|
|
||||||
};
|
|
||||||
input: {
|
|
||||||
(1 && a)();
|
|
||||||
(0 || a)();
|
|
||||||
(0 || 1 && a)();
|
|
||||||
(1 ? a : 0)();
|
|
||||||
|
|
||||||
(1 && a.b)();
|
|
||||||
(0 || a.b)();
|
|
||||||
(0 || 1 && a.b)();
|
|
||||||
(1 ? a.b : 0)();
|
|
||||||
|
|
||||||
(1 && a[b])();
|
|
||||||
(0 || a[b])();
|
|
||||||
(0 || 1 && a[b])();
|
|
||||||
(1 ? a[b] : 0)();
|
|
||||||
|
|
||||||
(1 && eval)();
|
|
||||||
(0 || eval)();
|
|
||||||
(0 || 1 && eval)();
|
|
||||||
(1 ? eval : 0)();
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
a();
|
|
||||||
a();
|
|
||||||
a();
|
|
||||||
a();
|
|
||||||
|
|
||||||
(0, a.b)();
|
|
||||||
(0, a.b)();
|
|
||||||
(0, a.b)();
|
|
||||||
(0, a.b)();
|
|
||||||
|
|
||||||
(0, a[b])();
|
|
||||||
(0, a[b])();
|
|
||||||
(0, a[b])();
|
|
||||||
(0, a[b])();
|
|
||||||
|
|
||||||
(0, eval)();
|
|
||||||
(0, eval)();
|
|
||||||
(0, eval)();
|
|
||||||
(0, eval)();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this_binding_collapse_vars: {
|
|
||||||
options = {
|
|
||||||
collapse_vars: true,
|
|
||||||
};
|
|
||||||
input: {
|
|
||||||
var c = a; c();
|
|
||||||
var d = a.b; d();
|
|
||||||
var e = eval; e();
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
a();
|
|
||||||
(0, a.b)();
|
|
||||||
(0, eval)();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this_binding_side_effects: {
|
|
||||||
options = {
|
|
||||||
side_effects : true
|
|
||||||
};
|
|
||||||
input: {
|
|
||||||
(function (foo) {
|
|
||||||
(0, foo)();
|
|
||||||
(0, foo.bar)();
|
|
||||||
(0, eval)('console.log(foo);');
|
|
||||||
}());
|
|
||||||
(function (foo) {
|
|
||||||
var eval = console;
|
|
||||||
(0, foo)();
|
|
||||||
(0, foo.bar)();
|
|
||||||
(0, eval)('console.log(foo);');
|
|
||||||
}());
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
(function (foo) {
|
|
||||||
foo();
|
|
||||||
(0, foo.bar)();
|
|
||||||
(0, eval)('console.log(foo);');
|
|
||||||
}());
|
|
||||||
(function (foo) {
|
|
||||||
var eval = console;
|
|
||||||
foo();
|
|
||||||
(0, foo.bar)();
|
|
||||||
(0, eval)('console.log(foo);');
|
|
||||||
}());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,88 +0,0 @@
|
|||||||
eval_collapse_vars: {
|
|
||||||
options = {
|
|
||||||
collapse_vars:true, sequences:false, properties:true, dead_code:true, conditionals:true,
|
|
||||||
comparisons:true, evaluate:true, booleans:true, loops:true, unused:true, hoist_funs:true,
|
|
||||||
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true
|
|
||||||
};
|
|
||||||
input: {
|
|
||||||
function f1() {
|
|
||||||
var e = 7;
|
|
||||||
var s = "abcdef";
|
|
||||||
var i = 2;
|
|
||||||
var eval = console.log.bind(console);
|
|
||||||
var x = s.charAt(i++);
|
|
||||||
var y = s.charAt(i++);
|
|
||||||
var z = s.charAt(i++);
|
|
||||||
eval(x, y, z, e);
|
|
||||||
}
|
|
||||||
function p1() { var a = foo(), b = bar(), eval = baz(); return a + b + eval; }
|
|
||||||
function p2() { var a = foo(), b = bar(), eval = baz; return a + b + eval(); }
|
|
||||||
(function f2(eval) {
|
|
||||||
var a = 2;
|
|
||||||
console.log(a - 5);
|
|
||||||
eval("console.log(a);");
|
|
||||||
})(eval);
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
function f1() {
|
|
||||||
var e = 7,
|
|
||||||
s = "abcdef",
|
|
||||||
i = 2,
|
|
||||||
eval = console.log.bind(console),
|
|
||||||
x = s.charAt(i++),
|
|
||||||
y = s.charAt(i++),
|
|
||||||
z = s.charAt(i++);
|
|
||||||
eval(x, y, z, e);
|
|
||||||
}
|
|
||||||
function p1() { return foo() + bar() + baz(); }
|
|
||||||
function p2() { var a = foo(), b = bar(), eval = baz; return a + b + eval(); }
|
|
||||||
(function f2(eval) {
|
|
||||||
var a = 2;
|
|
||||||
console.log(a - 5);
|
|
||||||
eval("console.log(a);");
|
|
||||||
})(eval);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
eval_unused: {
|
|
||||||
options = { unused: true, keep_fargs: false };
|
|
||||||
input: {
|
|
||||||
function f1(a, eval, c, d, e) {
|
|
||||||
return a('c') + eval;
|
|
||||||
}
|
|
||||||
function f2(a, b, c, d, e) {
|
|
||||||
return a + eval('c');
|
|
||||||
}
|
|
||||||
function f3(a, eval, c, d, e) {
|
|
||||||
return a + eval('c');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
function f1(a, eval) {
|
|
||||||
return a('c') + eval;
|
|
||||||
}
|
|
||||||
function f2(a, b, c, d, e) {
|
|
||||||
return a + eval('c');
|
|
||||||
}
|
|
||||||
function f3(a, eval, c, d, e) {
|
|
||||||
return a + eval('c');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
eval_mangle: {
|
|
||||||
mangle = {
|
|
||||||
};
|
|
||||||
input: {
|
|
||||||
function f1(a, eval, c, d, e) {
|
|
||||||
return a('c') + eval;
|
|
||||||
}
|
|
||||||
function f2(a, b, c, d, e) {
|
|
||||||
return a + eval('c');
|
|
||||||
}
|
|
||||||
function f3(a, eval, c, d, e) {
|
|
||||||
return a + eval('c');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
expect_exact: 'function f1(n,c,e,a,o){return n("c")+c}function f2(a,b,c,d,e){return a+eval("c")}function f3(a,eval,c,d,e){return a+eval("c")}'
|
|
||||||
}
|
|
||||||
@@ -1,89 +0,0 @@
|
|||||||
issue979_reported: {
|
|
||||||
options = {
|
|
||||||
sequences:true, properties:true, dead_code:true, conditionals:true,
|
|
||||||
comparisons:true, evaluate:true, booleans:true, loops:true, unused:true, hoist_funs:true,
|
|
||||||
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true
|
|
||||||
}
|
|
||||||
input: {
|
|
||||||
function f1() {
|
|
||||||
if (a == 1 || b == 2) {
|
|
||||||
foo();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function f2() {
|
|
||||||
if (!(a == 1 || b == 2)) {
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
foo();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
function f1() {
|
|
||||||
1!=a&&2!=b||foo();
|
|
||||||
}
|
|
||||||
function f2() {
|
|
||||||
1!=a&&2!=b||foo();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
issue979_test_negated_is_best: {
|
|
||||||
options = {
|
|
||||||
sequences:true, properties:true, dead_code:true, conditionals:true,
|
|
||||||
comparisons:true, evaluate:true, booleans:true, loops:true, unused:true, hoist_funs:true,
|
|
||||||
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true
|
|
||||||
}
|
|
||||||
input: {
|
|
||||||
function f3() {
|
|
||||||
if (a == 1 | b == 2) {
|
|
||||||
foo();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function f4() {
|
|
||||||
if (!(a == 1 | b == 2)) {
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
foo();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function f5() {
|
|
||||||
if (a == 1 && b == 2) {
|
|
||||||
foo();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function f6() {
|
|
||||||
if (!(a == 1 && b == 2)) {
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
foo();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function f7() {
|
|
||||||
if (a == 1 || b == 2) {
|
|
||||||
foo();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return bar();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
function f3() {
|
|
||||||
1==a|2==b&&foo();
|
|
||||||
}
|
|
||||||
function f4() {
|
|
||||||
1==a|2==b&&foo();
|
|
||||||
}
|
|
||||||
function f5() {
|
|
||||||
1==a&&2==b&&foo();
|
|
||||||
}
|
|
||||||
function f6() {
|
|
||||||
1!=a||2!=b||foo();
|
|
||||||
}
|
|
||||||
function f7() {
|
|
||||||
return 1!=a&&2!=b?bar():void foo();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -121,27 +121,3 @@ drop_if_else_break_4: {
|
|||||||
for (; bar() && (x(), y(), foo());) baz(), z(), k();
|
for (; bar() && (x(), y(), foo());) baz(), z(), k();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
parse_do_while_with_semicolon: {
|
|
||||||
options = { loops: false };
|
|
||||||
input: {
|
|
||||||
do {
|
|
||||||
x();
|
|
||||||
} while (false);y()
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
do x(); while (false);y();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
parse_do_while_without_semicolon: {
|
|
||||||
options = { loops: false };
|
|
||||||
input: {
|
|
||||||
do {
|
|
||||||
x();
|
|
||||||
} while (false)y()
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
do x(); while (false);y();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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);"
|
|
||||||
}
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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");';
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
var Mocha = require('mocha'),
|
|
||||||
fs = require('fs'),
|
|
||||||
path = require('path');
|
|
||||||
|
|
||||||
// Instantiate a Mocha instance.
|
|
||||||
var mocha = new Mocha({});
|
|
||||||
|
|
||||||
var testDir = __dirname + '/mocha/';
|
|
||||||
|
|
||||||
// Add each .js file to the mocha instance
|
|
||||||
fs.readdirSync(testDir).filter(function(file){
|
|
||||||
// Only keep the .js files
|
|
||||||
return file.substr(-3) === '.js';
|
|
||||||
|
|
||||||
}).forEach(function(file){
|
|
||||||
mocha.addFile(
|
|
||||||
path.join(testDir, file)
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
module.exports = function() {
|
|
||||||
mocha.run(function(failures) {
|
|
||||||
if (failures !== 0) {
|
|
||||||
process.on('exit', function () {
|
|
||||||
process.exit(failures);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
var UglifyJS = require('../../');
|
|
||||||
var assert = require("assert");
|
|
||||||
|
|
||||||
describe("arguments", function() {
|
|
||||||
it("Should known that arguments in functions are local scoped", function() {
|
|
||||||
var ast = UglifyJS.parse("var arguments; var f = function() {arguments.length}");
|
|
||||||
ast.figure_out_scope();
|
|
||||||
|
|
||||||
// Test scope of `var arguments`
|
|
||||||
assert.strictEqual(ast.find_variable("arguments").global, true);
|
|
||||||
|
|
||||||
// Select arguments symbol in function
|
|
||||||
var symbol = ast.body[1].definitions[0].value.find_variable("arguments");
|
|
||||||
|
|
||||||
assert.strictEqual(symbol.global, false);
|
|
||||||
assert.strictEqual(symbol.scope, ast. // From ast
|
|
||||||
body[1]. // Select 2nd statement (equals to `var f ...`)
|
|
||||||
definitions[0]. // First definition of selected statement
|
|
||||||
value // Select function as scope
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
var UglifyJS = require('../../');
|
|
||||||
var assert = require("assert");
|
|
||||||
|
|
||||||
describe("comment filters", function() {
|
|
||||||
it("Should be able to filter comments by passing regex", function() {
|
|
||||||
var ast = UglifyJS.parse("/*!test1*/\n/*test2*/\n//!test3\n//test4\n<!--test5\n<!--!test6\n-->test7\n-->!test8");
|
|
||||||
assert.strictEqual(ast.print_to_string({comments: /^!/}), "/*!test1*/\n//!test3\n//!test6\n//!test8\n");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Should be able to filter comments by passing a function", function() {
|
|
||||||
var ast = UglifyJS.parse("/*TEST 123*/\n//An other comment\n//8 chars.");
|
|
||||||
var f = function(node, comment) {
|
|
||||||
return comment.value.length === 8;
|
|
||||||
};
|
|
||||||
|
|
||||||
assert.strictEqual(ast.print_to_string({comments: f}), "/*TEST 123*/\n//8 chars.\n");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Should be able to get the comment and comment type when using a function", function() {
|
|
||||||
var ast = UglifyJS.parse("/*!test1*/\n/*test2*/\n//!test3\n//test4\n<!--test5\n<!--!test6\n-->test7\n-->!test8");
|
|
||||||
var f = function(node, comment) {
|
|
||||||
return comment.type == "comment1" || comment.type == "comment3";
|
|
||||||
};
|
|
||||||
|
|
||||||
assert.strictEqual(ast.print_to_string({comments: f}), "//!test3\n//test4\n//test5\n//!test6\n");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Should be able to filter comments by passing a boolean", function() {
|
|
||||||
var ast = UglifyJS.parse("/*!test1*/\n/*test2*/\n//!test3\n//test4\n<!--test5\n<!--!test6\n-->test7\n-->!test8");
|
|
||||||
|
|
||||||
assert.strictEqual(ast.print_to_string({comments: true}), "/*!test1*/\n/*test2*/\n//!test3\n//test4\n//test5\n//!test6\n//test7\n//!test8\n");
|
|
||||||
assert.strictEqual(ast.print_to_string({comments: false}), "");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Should never be able to filter comment5 (shebangs)", function() {
|
|
||||||
var ast = UglifyJS.parse("#!Random comment\n//test1\n/*test2*/");
|
|
||||||
var f = function(node, comment) {
|
|
||||||
assert.strictEqual(comment.type === "comment5", false);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
assert.strictEqual(ast.print_to_string({comments: f}), "#!Random comment\n//test1\n/*test2*/\n");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,89 +0,0 @@
|
|||||||
var UglifyJS = require('../../');
|
|
||||||
var assert = require("assert");
|
|
||||||
|
|
||||||
describe("Getters and setters", function() {
|
|
||||||
it("Should not accept operator symbols as getter/setter name", function() {
|
|
||||||
var illegalOperators = [
|
|
||||||
"++",
|
|
||||||
"--",
|
|
||||||
"+",
|
|
||||||
"-",
|
|
||||||
"!",
|
|
||||||
"~",
|
|
||||||
"&",
|
|
||||||
"|",
|
|
||||||
"^",
|
|
||||||
"*",
|
|
||||||
"/",
|
|
||||||
"%",
|
|
||||||
">>",
|
|
||||||
"<<",
|
|
||||||
">>>",
|
|
||||||
"<",
|
|
||||||
">",
|
|
||||||
"<=",
|
|
||||||
">=",
|
|
||||||
"==",
|
|
||||||
"===",
|
|
||||||
"!=",
|
|
||||||
"!==",
|
|
||||||
"?",
|
|
||||||
"=",
|
|
||||||
"+=",
|
|
||||||
"-=",
|
|
||||||
"/=",
|
|
||||||
"*=",
|
|
||||||
"%=",
|
|
||||||
">>=",
|
|
||||||
"<<=",
|
|
||||||
">>>=",
|
|
||||||
"|=",
|
|
||||||
"^=",
|
|
||||||
"&=",
|
|
||||||
"&&",
|
|
||||||
"||"
|
|
||||||
];
|
|
||||||
var generator = function() {
|
|
||||||
var results = [];
|
|
||||||
|
|
||||||
for (var i in illegalOperators) {
|
|
||||||
results.push({
|
|
||||||
code: "var obj = { get " + illegalOperators[i] + "() { return test; }};",
|
|
||||||
operator: illegalOperators[i],
|
|
||||||
method: "get"
|
|
||||||
});
|
|
||||||
results.push({
|
|
||||||
code: "var obj = { set " + illegalOperators[i] + "(value) { test = value}};",
|
|
||||||
operator: illegalOperators[i],
|
|
||||||
method: "set"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return results;
|
|
||||||
};
|
|
||||||
|
|
||||||
var testCase = function(data) {
|
|
||||||
return function() {
|
|
||||||
UglifyJS.parse(data.code);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
var fail = function(data) {
|
|
||||||
return function (e) {
|
|
||||||
return e instanceof UglifyJS.JS_Parse_Error &&
|
|
||||||
e.message === "Invalid getter/setter name: " + data.operator;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
var errorMessage = function(data) {
|
|
||||||
return "Expected but didn't get a syntax error while parsing following line:\n" + data.code;
|
|
||||||
};
|
|
||||||
|
|
||||||
var tests = generator();
|
|
||||||
for (var i = 0; i < tests.length; i++) {
|
|
||||||
var test = tests[i];
|
|
||||||
assert.throws(testCase(test), fail(test), errorMessage(test));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
var UglifyJS = require('../../');
|
|
||||||
var assert = require("assert");
|
|
||||||
|
|
||||||
describe("String literals", function() {
|
|
||||||
it("Should throw syntax error if a string literal contains a newline", function() {
|
|
||||||
var inputs = [
|
|
||||||
"'\n'",
|
|
||||||
"'\r'",
|
|
||||||
'"\r\n"',
|
|
||||||
"'\u2028'",
|
|
||||||
'"\u2029"'
|
|
||||||
];
|
|
||||||
|
|
||||||
var test = function(input) {
|
|
||||||
return function() {
|
|
||||||
var ast = UglifyJS.parse(input);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
var error = function(e) {
|
|
||||||
return e instanceof UglifyJS.JS_Parse_Error &&
|
|
||||||
e.message === "Unterminated string constant";
|
|
||||||
};
|
|
||||||
|
|
||||||
for (var input in inputs) {
|
|
||||||
assert.throws(test(inputs[input]), error);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Should not throw syntax error if a string has a line continuation", function() {
|
|
||||||
var output = UglifyJS.parse('var a = "a\\\nb";').print_to_string();
|
|
||||||
assert.equal(output, 'var a="ab";');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -4,6 +4,7 @@ var U = require("../tools/node");
|
|||||||
var path = require("path");
|
var path = require("path");
|
||||||
var fs = require("fs");
|
var fs = require("fs");
|
||||||
var assert = require("assert");
|
var assert = require("assert");
|
||||||
|
var sys = require("util");
|
||||||
|
|
||||||
var tests_dir = path.dirname(module.filename);
|
var tests_dir = path.dirname(module.filename);
|
||||||
var failures = 0;
|
var failures = 0;
|
||||||
@@ -11,17 +12,11 @@ var failed_files = {};
|
|||||||
|
|
||||||
run_compress_tests();
|
run_compress_tests();
|
||||||
if (failures) {
|
if (failures) {
|
||||||
console.error("\n!!! Failed " + failures + " test cases.");
|
sys.error("\n!!! Failed " + failures + " test cases.");
|
||||||
console.error("!!! " + Object.keys(failed_files).join(", "));
|
sys.error("!!! " + Object.keys(failed_files).join(", "));
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
var mocha_tests = require("./mocha.js");
|
|
||||||
mocha_tests();
|
|
||||||
|
|
||||||
var run_sourcemaps_tests = require('./sourcemaps');
|
|
||||||
run_sourcemaps_tests();
|
|
||||||
|
|
||||||
var run_ast_conversion_tests = require("./mozilla-ast");
|
var run_ast_conversion_tests = require("./mozilla-ast");
|
||||||
|
|
||||||
run_ast_conversion_tests({
|
run_ast_conversion_tests({
|
||||||
@@ -36,7 +31,7 @@ function tmpl() {
|
|||||||
|
|
||||||
function log() {
|
function log() {
|
||||||
var txt = tmpl.apply(this, arguments);
|
var txt = tmpl.apply(this, arguments);
|
||||||
console.log("%s", txt);
|
sys.puts(txt);
|
||||||
}
|
}
|
||||||
|
|
||||||
function log_directory(dir) {
|
function log_directory(dir) {
|
||||||
@@ -89,25 +84,12 @@ function run_compress_tests() {
|
|||||||
warnings: false
|
warnings: false
|
||||||
});
|
});
|
||||||
var cmp = new U.Compressor(options, true);
|
var cmp = new U.Compressor(options, true);
|
||||||
var output_options = test.beautify || {};
|
var expect = make_code(as_toplevel(test.expect), false);
|
||||||
var expect;
|
|
||||||
if (test.expect) {
|
|
||||||
expect = make_code(as_toplevel(test.expect), output_options);
|
|
||||||
} else {
|
|
||||||
expect = test.expect_exact;
|
|
||||||
}
|
|
||||||
var input = as_toplevel(test.input);
|
var input = as_toplevel(test.input);
|
||||||
var input_code = make_code(test.input, { beautify: true });
|
var input_code = make_code(test.input);
|
||||||
if (test.mangle_props) {
|
|
||||||
input = U.mangle_properties(input, test.mangle_props);
|
|
||||||
}
|
|
||||||
var output = input.transform(cmp);
|
var output = input.transform(cmp);
|
||||||
output.figure_out_scope();
|
output.figure_out_scope();
|
||||||
if (test.mangle) {
|
output = make_code(output, false);
|
||||||
output.compute_char_frequency(test.mangle);
|
|
||||||
output.mangle_names(test.mangle);
|
|
||||||
}
|
|
||||||
output = make_code(output, output_options);
|
|
||||||
if (expect != output) {
|
if (expect != output) {
|
||||||
log("!!! failed\n---INPUT---\n{input}\n---OUTPUT---\n{output}\n---EXPECTED---\n{expected}\n\n", {
|
log("!!! failed\n---INPUT---\n{input}\n---OUTPUT---\n{output}\n---EXPECTED---\n{expected}\n\n", {
|
||||||
input: input_code,
|
input: input_code,
|
||||||
@@ -151,7 +133,7 @@ function parse_test(file) {
|
|||||||
file: file,
|
file: file,
|
||||||
line: node.start.line,
|
line: node.start.line,
|
||||||
col: node.start.col,
|
col: node.start.col,
|
||||||
code: make_code(node, { beautify: false })
|
code: make_code(node, false)
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -168,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,
|
||||||
@@ -180,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;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -198,15 +171,15 @@ function parse_test(file) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function make_code(ast, options) {
|
function make_code(ast, beautify) {
|
||||||
options.inline_script = true;
|
if (arguments.length == 1) beautify = true;
|
||||||
var stream = U.OutputStream(options);
|
var stream = U.OutputStream({ beautify: beautify });
|
||||||
ast.print(stream);
|
ast.print(stream);
|
||||||
return stream.get();
|
return stream.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
function evaluate(code) {
|
function evaluate(code) {
|
||||||
if (code instanceof U.AST_Node)
|
if (code instanceof U.AST_Node)
|
||||||
code = make_code(code, { beautify: true });
|
code = make_code(code);
|
||||||
return new Function("return(" + code + ")")();
|
return new Function("return(" + code + ")")();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
|
||||||
}
|
|
||||||
|
|
||||||
5603
tools/domprops.json
5603
tools/domprops.json
File diff suppressed because it is too large
Load Diff
@@ -1,18 +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;
|
|
||||||
exports["SymbolDef"] = SymbolDef;
|
|
||||||
149
tools/node.js
149
tools/node.js
@@ -1,5 +1,28 @@
|
|||||||
var path = require("path");
|
var path = require("path");
|
||||||
var fs = require("fs");
|
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 = [
|
var FILES = exports.FILES = [
|
||||||
"../lib/utils.js",
|
"../lib/utils.js",
|
||||||
@@ -10,40 +33,35 @@ 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",
|
|
||||||
"./exports.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));
|
||||||
});
|
});
|
||||||
|
|
||||||
var UglifyJS = exports;
|
FILES.forEach(load_global);
|
||||||
|
|
||||||
new Function("MOZ_SourceMap", "exports", FILES.map(function(file){
|
|
||||||
return fs.readFileSync(file, "utf8");
|
|
||||||
}).join("\n\n"))(
|
|
||||||
require("source-map"),
|
|
||||||
UglifyJS
|
|
||||||
);
|
|
||||||
|
|
||||||
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.
|
||||||
|
for (var i in UglifyJS) {
|
||||||
|
if (UglifyJS.hasOwnProperty(i)) {
|
||||||
|
exports[i] = UglifyJS[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
exports.minify = function(files, options) {
|
exports.minify = function(files, options) {
|
||||||
options = UglifyJS.defaults(options, {
|
options = UglifyJS.defaults(options, {
|
||||||
spidermonkey : false,
|
spidermonkey : false,
|
||||||
outSourceMap : null,
|
outSourceMap : null,
|
||||||
sourceRoot : null,
|
sourceRoot : null,
|
||||||
inSourceMap : null,
|
inSourceMap : null,
|
||||||
fromString : false,
|
fromString : false,
|
||||||
warnings : false,
|
warnings : false,
|
||||||
mangle : {},
|
mangle : {},
|
||||||
mangleProperties : false,
|
output : null,
|
||||||
nameCache : null,
|
compress : {}
|
||||||
output : null,
|
|
||||||
compress : {},
|
|
||||||
parse : {}
|
|
||||||
});
|
});
|
||||||
UglifyJS.base54.reset();
|
UglifyJS.base54.reset();
|
||||||
|
|
||||||
@@ -56,21 +74,17 @@ exports.minify = function(files, options) {
|
|||||||
} else {
|
} else {
|
||||||
if (typeof files == "string")
|
if (typeof files == "string")
|
||||||
files = [ files ];
|
files = [ files ];
|
||||||
files.forEach(function(file, i){
|
files.forEach(function(file){
|
||||||
var code = options.fromString
|
var code = options.fromString
|
||||||
? file
|
? file
|
||||||
: fs.readFileSync(file, "utf8");
|
: fs.readFileSync(file, "utf8");
|
||||||
sourcesContent[file] = code;
|
sourcesContent[file] = code;
|
||||||
toplevel = UglifyJS.parse(code, {
|
toplevel = UglifyJS.parse(code, {
|
||||||
filename: options.fromString ? i : file,
|
filename: options.fromString ? "?" : file,
|
||||||
toplevel: toplevel,
|
toplevel: toplevel
|
||||||
bare_returns: options.parse ? options.parse.bare_returns : undefined
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (options.wrap) {
|
|
||||||
toplevel = toplevel.wrap_commonjs(options.wrap, options.exportAll);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. compress
|
// 2. compress
|
||||||
if (options.compress) {
|
if (options.compress) {
|
||||||
@@ -81,21 +95,14 @@ exports.minify = function(files, options) {
|
|||||||
toplevel = toplevel.transform(sq);
|
toplevel = toplevel.transform(sq);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. mangle properties
|
// 3. mangle
|
||||||
if (options.mangleProperties || options.nameCache) {
|
|
||||||
options.mangleProperties.cache = UglifyJS.readNameCache(options.nameCache, "props");
|
|
||||||
toplevel = UglifyJS.mangle_properties(toplevel, options.mangleProperties);
|
|
||||||
UglifyJS.writeNameCache(options.nameCache, "props", options.mangleProperties.cache);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 4. mangle
|
|
||||||
if (options.mangle) {
|
if (options.mangle) {
|
||||||
toplevel.figure_out_scope(options.mangle);
|
toplevel.figure_out_scope(options.mangle);
|
||||||
toplevel.compute_char_frequency(options.mangle);
|
toplevel.compute_char_frequency(options.mangle);
|
||||||
toplevel.mangle_names(options.mangle);
|
toplevel.mangle_names(options.mangle);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 5. output
|
// 4. output
|
||||||
var inMap = options.inSourceMap;
|
var inMap = options.inSourceMap;
|
||||||
var output = {};
|
var output = {};
|
||||||
if (typeof options.inSourceMap == "string") {
|
if (typeof options.inSourceMap == "string") {
|
||||||
@@ -122,7 +129,7 @@ exports.minify = function(files, options) {
|
|||||||
var stream = UglifyJS.OutputStream(output);
|
var stream = UglifyJS.OutputStream(output);
|
||||||
toplevel.print(stream);
|
toplevel.print(stream);
|
||||||
|
|
||||||
if (options.outSourceMap && "string" === typeof options.outSourceMap) {
|
if(options.outSourceMap){
|
||||||
stream += "\n//# sourceMappingURL=" + options.outSourceMap;
|
stream += "\n//# sourceMappingURL=" + options.outSourceMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -185,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