Compare commits
80 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7793c6c389 | ||
|
|
90ec468240 | ||
|
|
994293e972 | ||
|
|
b57bae4b9e | ||
|
|
e23a10f7f9 | ||
|
|
884ec4e8a5 | ||
|
|
e616916de5 | ||
|
|
8d21516623 | ||
|
|
74368c3dba | ||
|
|
18dbceb36f | ||
|
|
65d39a3702 | ||
|
|
24917e7084 | ||
|
|
e84957e3da | ||
|
|
c11a748908 | ||
|
|
90017051f2 | ||
|
|
fc816628c1 | ||
|
|
46ad273df4 | ||
|
|
b689028e87 | ||
|
|
1e831df1f6 | ||
|
|
c12486bab4 | ||
|
|
52e94a0723 | ||
|
|
16b97f9558 | ||
|
|
dbfa5d4d14 | ||
|
|
ba54d074d8 | ||
|
|
0818d396c5 | ||
|
|
770f3ba5fe | ||
|
|
553034fe52 | ||
|
|
7fe8c9150a | ||
|
|
6c419bc083 | ||
|
|
25321df959 | ||
|
|
cf1b0165af | ||
|
|
c3d358a5b8 | ||
|
|
68497d0258 | ||
|
|
71c3d04681 | ||
|
|
4c89550c43 | ||
|
|
7ebfb22d16 | ||
|
|
6eceac0966 | ||
|
|
fc5aee662d | ||
|
|
5fbbb43839 | ||
|
|
df2cfcb5fc | ||
|
|
623a0d920f | ||
|
|
e8c04f8cb6 | ||
|
|
110c1ac097 | ||
|
|
15ef272790 | ||
|
|
b3a706114c | ||
|
|
cc2d7acaf0 | ||
|
|
dfb86ccdd1 | ||
|
|
0417a69c3e | ||
|
|
2dbafbb4ee | ||
|
|
311c074622 | ||
|
|
a10c7793bb | ||
|
|
0b7d65d331 | ||
|
|
8b954b022b | ||
|
|
0013cbf91f | ||
|
|
1956edd503 | ||
|
|
560ccc1221 | ||
|
|
10a71c182b | ||
|
|
ddc0ed7072 | ||
|
|
c00efe56f4 | ||
|
|
28bcdbd7df | ||
|
|
6a8aed2049 | ||
|
|
a8785fb694 | ||
|
|
dd6d7b3d88 | ||
|
|
94f3819dc6 | ||
|
|
be1f5199f4 | ||
|
|
95aea0e33c | ||
|
|
a1b2735dd8 | ||
|
|
f345175bc2 | ||
|
|
bb45f48ab7 | ||
|
|
b2f27fd873 | ||
|
|
ced32f9bd8 | ||
|
|
dfc3ec9cef | ||
|
|
1896694532 | ||
|
|
5f269cd573 | ||
|
|
6988cd9558 | ||
|
|
2390fae5c4 | ||
|
|
56fce2131c | ||
|
|
7e575e9d7f | ||
|
|
cb4a02949e | ||
|
|
f85a206b9e |
25
.github/ISSUE_TEMPLATE.md
vendored
25
.github/ISSUE_TEMPLATE.md
vendored
@@ -1,25 +0,0 @@
|
||||
**Bug report or feature request?**
|
||||
|
||||
<!-- Note: sub-optimal but correct code is not a bug -->
|
||||
|
||||
**Uglify version (`uglifyjs -V`)**
|
||||
|
||||
**JavaScript input**
|
||||
|
||||
<!--
|
||||
A complete parsable JS program exhibiting the issue with
|
||||
UglifyJS alone - without third party tools or libraries.
|
||||
Ideally the input should be as small as possible.
|
||||
Post a link to a gist if necessary.
|
||||
|
||||
Issues without a reproducible test case will be closed.
|
||||
-->
|
||||
|
||||
**The `uglifyjs` CLI command executed or `minify()` options used.**
|
||||
|
||||
**JavaScript output or error produced.**
|
||||
|
||||
<!--
|
||||
Note: `uglify-js` only supports JavaScript.
|
||||
Those wishing to minify ES6+ should transpile first.
|
||||
-->
|
||||
51
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
51
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
<!-- Note: sub-optimal but correct code is not a bug -->
|
||||
|
||||
**Uglify version (`uglifyjs -V`)**
|
||||
|
||||
**JavaScript input**
|
||||
|
||||
<!--
|
||||
A complete parsable JS program exhibiting the issue with UglifyJS alone
|
||||
- without third party tools or libraries.
|
||||
|
||||
Ideally the input should be as small as possible, but may be large if isolating
|
||||
the problem proves to be difficult. The most important thing is that the
|
||||
standalone program reliably exhibits the bug when minified. Provide a link to a
|
||||
gist if necessary.
|
||||
|
||||
Solely providing minified output without the original uglify JS input is not
|
||||
useful in determining the cause of the problem. Issues without a reproducible
|
||||
test case will be closed.
|
||||
-->
|
||||
|
||||
**The `uglifyjs` CLI command executed or `minify()` options used.**
|
||||
|
||||
<!--
|
||||
Command-line or API call to UglifyJS without third party tools or libraries.
|
||||
|
||||
For users using bundlers or transpilers, you may be able to gather the required
|
||||
information through setting the `UGLIFY_BUG_REPORT` environment variable:
|
||||
|
||||
export UGLIFY_BUG_REPORT=1 (bash)
|
||||
set UGLIFY_BUG_REPORT=1 (Command Prompt)
|
||||
$Env:UGLIFY_BUG_REPORT=1 (PowerShell)
|
||||
|
||||
before running your usual build process. The resulting "minified" output should
|
||||
contain the necessary details for this report.
|
||||
-->
|
||||
|
||||
**JavaScript output or error produced.**
|
||||
|
||||
<!--
|
||||
Only minified code that produces different output (or error) from the original
|
||||
upon execution would be considered a bug.
|
||||
-->
|
||||
8
.github/workflows/ci.yml
vendored
8
.github/workflows/ci.yml
vendored
@@ -7,13 +7,13 @@ jobs:
|
||||
test:
|
||||
strategy:
|
||||
matrix:
|
||||
node: [ "0.8", "0.10", "0.12", "4", "6", "8", "10", "12", latest ]
|
||||
node: [ '0.8', '0.10', '0.12', '4', '6', '8', '10', '12', latest ]
|
||||
os: [ ubuntu-latest, windows-latest ]
|
||||
script: [ compress, mocha, release/benchmark, release/jetstream ]
|
||||
exclude:
|
||||
- node: "0.8"
|
||||
- node: '0.8'
|
||||
script: release/benchmark
|
||||
- node: "0.8"
|
||||
- node: '0.8'
|
||||
script: release/jetstream
|
||||
name: ${{ matrix.node }} ${{ matrix.os }} ${{ matrix.script }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
@@ -29,7 +29,7 @@ jobs:
|
||||
- name: Perform tests
|
||||
shell: bash
|
||||
run: |
|
||||
git clone --branch v1.5.4 --depth 1 https://github.com/jasongin/nvs.git ~/.nvs
|
||||
git clone --branch v1.6.0 --depth 1 https://github.com/jasongin/nvs.git ~/.nvs
|
||||
while ! timeout 60 bash -c '. ~/.nvs/nvs.sh add $NODE && nvs use $NODE'; do
|
||||
cd ~/.nvs
|
||||
while !(git clean -xdf); do echo "'git clean' failed - retrying..."; done
|
||||
|
||||
29
.github/workflows/ufuzz.yml
vendored
29
.github/workflows/ufuzz.yml
vendored
@@ -2,7 +2,7 @@ name: Fuzzing
|
||||
on:
|
||||
pull_request:
|
||||
schedule:
|
||||
- cron: "*/5 * * * *"
|
||||
- cron: '*/5 * * * *'
|
||||
env:
|
||||
BASE_URL: https://api.github.com/repos/${{ github.repository }}
|
||||
CAUSE: ${{ github.event_name }}
|
||||
@@ -13,22 +13,39 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ ubuntu-latest, windows-latest ]
|
||||
name: ${{ matrix.os }}
|
||||
include:
|
||||
- node: latest
|
||||
os: macos-latest
|
||||
- node: '8'
|
||||
os: ubuntu-latest
|
||||
- node: '8'
|
||||
os: ubuntu-latest
|
||||
- node: '8'
|
||||
os: windows-latest
|
||||
- node: '8'
|
||||
os: windows-latest
|
||||
name: ${{ matrix.node }} ${{ matrix.os }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
env:
|
||||
NODE: ${{ matrix.node }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Install GNU Core Utilities
|
||||
if: ${{ startsWith(matrix.os, 'macos') }}
|
||||
shell: bash
|
||||
run: |
|
||||
brew install coreutils
|
||||
- name: Perform fuzzing
|
||||
shell: bash
|
||||
run: |
|
||||
git clone --branch v1.5.4 --depth 1 https://github.com/jasongin/nvs.git ~/.nvs
|
||||
while ! timeout 60 bash -c '. ~/.nvs/nvs.sh add 8 && nvs use 8'; do
|
||||
git clone --branch v1.6.0 --depth 1 https://github.com/jasongin/nvs.git ~/.nvs
|
||||
while ! timeout 60 bash -c '. ~/.nvs/nvs.sh add $NODE && nvs use $NODE'; do
|
||||
cd ~/.nvs
|
||||
while !(git clean -xdf); do echo "'git clean' failed - retrying..."; done
|
||||
cd -
|
||||
done
|
||||
. ~/.nvs/nvs.sh --version
|
||||
nvs use 8
|
||||
nvs use $NODE
|
||||
node --version
|
||||
npm config set audit false
|
||||
npm config set optional false
|
||||
|
||||
75
README.md
75
README.md
@@ -135,6 +135,10 @@ a double dash to prevent input files being used as option arguments:
|
||||
`//# sourceMappingURL`.
|
||||
--timings Display operations run time on STDERR.
|
||||
--toplevel Compress and/or mangle variables in top level scope.
|
||||
--v8 Support non-standard Chrome & Node.js
|
||||
Equivalent to setting `v8: true` in `minify()`
|
||||
for `mangle` and `output` options.
|
||||
By default UglifyJS will not try to be v8-proof.
|
||||
--verbose Print diagnostic messages.
|
||||
--warn Print warning messages.
|
||||
--webkit Support non-standard Safari/Webkit.
|
||||
@@ -522,6 +526,8 @@ if (result.error) throw result.error;
|
||||
- `toplevel` (default `false`) -- set to `true` if you wish to enable top level
|
||||
variable and function name mangling and to drop unused variables and functions.
|
||||
|
||||
- `v8` (default `false`) -- enable workarounds for Chrome & Node.js bugs.
|
||||
|
||||
- `warnings` (default `false`) — pass `true` to return compressor warnings
|
||||
in `result.warnings`. Use the value `"verbose"` for more detailed warnings.
|
||||
|
||||
@@ -621,7 +627,11 @@ to be `false` and all symbol names will be omitted.
|
||||
- `arguments` (default: `true`) -- replace `arguments[index]` with function
|
||||
parameter name whenever possible.
|
||||
|
||||
- `assignments` (default: `true`) -- apply optimizations to assignment expressions.
|
||||
- `arrows` (default: `true`) -- apply optimizations to arrow functions
|
||||
|
||||
- `assignments` (default: `true`) -- apply optimizations to assignment expressions
|
||||
|
||||
- `awaits` (default: `true`) -- apply optimizations to `await` expressions
|
||||
|
||||
- `booleans` (default: `true`) -- various optimizations for boolean context,
|
||||
for example `!!a ? b : c → a ? b : c`
|
||||
@@ -638,6 +648,8 @@ to be `false` and all symbol names will be omitted.
|
||||
|
||||
- `dead_code` (default: `true`) -- remove unreachable code
|
||||
|
||||
- `default_values` (default: `true`) -- drop overshadowed default values
|
||||
|
||||
- `directives` (default: `true`) -- remove redundant or non-standard directives
|
||||
|
||||
- `drop_console` (default: `false`) -- Pass `true` to discard calls to
|
||||
@@ -683,13 +695,9 @@ to be `false` and all symbol names will be omitted.
|
||||
|
||||
- `join_vars` (default: `true`) -- join consecutive `var` statements
|
||||
|
||||
- `keep_fargs` (default: `strict`) -- Discard unused function arguments. Code
|
||||
which relies on `Function.length` will break if this is done indiscriminately,
|
||||
i.e. when passing `true`. Pass `false` to always retain function arguments.
|
||||
|
||||
- `keep_fnames` (default: `false`) -- Pass `true` to prevent the
|
||||
compressor from discarding function names. Useful for code relying on
|
||||
`Function.prototype.name`. See also: the `keep_fnames` [mangle option](#mangle-options).
|
||||
- `keep_fargs` (default: `false`) -- discard unused function arguments except
|
||||
when unsafe to do so, e.g. code which relies on `Function.prototype.length`.
|
||||
Pass `true` to always retain function arguments.
|
||||
|
||||
- `keep_infinity` (default: `false`) -- Pass `true` to prevent `Infinity` from
|
||||
being compressed into `1/0`, which may cause performance issues on Chrome.
|
||||
@@ -739,6 +747,8 @@ to be `false` and all symbol names will be omitted.
|
||||
- `reduce_vars` (default: `true`) -- Improve optimization on variables assigned with and
|
||||
used as constant values.
|
||||
|
||||
- `rests` (default: `true`) -- apply optimizations to rest parameters
|
||||
|
||||
- `sequences` (default: `true`) -- join consecutive simple statements using the
|
||||
comma operator. May be set to a positive integer to specify the maximum number
|
||||
of consecutive comma sequences that will be generated. If this option is set to
|
||||
@@ -753,20 +763,20 @@ to be `false` and all symbol names will be omitted.
|
||||
annotation `/*@__PURE__*/` or `/*#__PURE__*/` immediately precedes the call. For
|
||||
example: `/*@__PURE__*/foo();`
|
||||
|
||||
- `spread` (default: `true`) -- flatten spread expressions.
|
||||
- `spreads` (default: `true`) -- flatten spread expressions.
|
||||
|
||||
- `strings` (default: `true`) -- compact string concatenations.
|
||||
|
||||
- `switches` (default: `true`) -- de-duplicate and remove unreachable `switch` branches
|
||||
|
||||
- `toplevel` (default: `false`) -- drop unreferenced functions (`"funcs"`) and/or
|
||||
variables (`"vars"`) in the top level scope (`false` by default, `true` to drop
|
||||
both unreferenced functions and variables)
|
||||
|
||||
- `top_retain` (default: `null`) -- prevent specific toplevel functions and
|
||||
variables from `unused` removal (can be array, comma-separated, RegExp or
|
||||
function. Implies `toplevel`)
|
||||
|
||||
- `toplevel` (default: `false`) -- drop unreferenced functions (`"funcs"`) and/or
|
||||
variables (`"vars"`) in the top level scope (`false` by default, `true` to drop
|
||||
both unreferenced functions and variables)
|
||||
|
||||
- `typeofs` (default: `true`) -- Transforms `typeof foo == "undefined"` into
|
||||
`foo === void 0`. Note: recommend to set this value to `false` for IE10 and
|
||||
earlier versions due to known issues.
|
||||
@@ -803,10 +813,6 @@ to be `false` and all symbol names will be omitted.
|
||||
- `eval` (default `false`) -- Pass `true` to mangle names visible in scopes
|
||||
where `eval` or `with` are used.
|
||||
|
||||
- `keep_fnames` (default `false`) -- Pass `true` to not mangle function names.
|
||||
Useful for code relying on `Function.prototype.name`. See also: the `keep_fnames`
|
||||
[compress option](#compress-options).
|
||||
|
||||
- `reserved` (default `[]`) -- Pass an array of identifiers that should be
|
||||
excluded from mangling. Example: `["foo", "bar"]`.
|
||||
|
||||
@@ -873,7 +879,7 @@ can pass additional arguments that control the code output:
|
||||
comments, `"some"` to preserve multi-line comments that contain `@cc_on`,
|
||||
`@license`, or `@preserve` (case-insensitive), a regular expression string
|
||||
(e.g. `/^!/`), or a function which returns `boolean`, e.g.
|
||||
```js
|
||||
```javascript
|
||||
function(node, comment) {
|
||||
return comment.value.indexOf("@type " + node.TYPE) >= 0;
|
||||
}
|
||||
@@ -919,8 +925,6 @@ can pass additional arguments that control the code output:
|
||||
|
||||
- `shebang` (default `true`) -- preserve shebang `#!` in preamble (bash scripts)
|
||||
|
||||
- `v8` (default `false`) -- enable workarounds for Chrome & Node.js bugs
|
||||
|
||||
- `width` (default `80`) -- only takes effect when beautification is on, this
|
||||
specifies an (orientative) line width that the beautifier will try to
|
||||
obey. It refers to the width of the line text (excluding indentation).
|
||||
@@ -1146,7 +1150,7 @@ To enable fast minify mode from the CLI use:
|
||||
uglifyjs file.js -m
|
||||
```
|
||||
To enable fast minify mode with the API use:
|
||||
```js
|
||||
```javascript
|
||||
UglifyJS.minify(code, { compress: false, mangle: true });
|
||||
```
|
||||
|
||||
@@ -1178,10 +1182,10 @@ To allow for better optimizations, the compiler makes various assumptions:
|
||||
`Object.defineProperty()`, `Object.defineProperties()`, `Object.freeze()`,
|
||||
`Object.preventExtensions()` or `Object.seal()`).
|
||||
- Earlier versions of JavaScript will throw `SyntaxError` with the following:
|
||||
```js
|
||||
```javascript
|
||||
({
|
||||
p: 42,
|
||||
get p() {},
|
||||
p: 42,
|
||||
get p() {},
|
||||
});
|
||||
// SyntaxError: Object literal may not have data and accessor property with
|
||||
// the same name
|
||||
@@ -1191,7 +1195,7 @@ To allow for better optimizations, the compiler makes various assumptions:
|
||||
versions of Chrome and Node.js may be altered.
|
||||
- When `toplevel` is enabled, UglifyJS effectively assumes input code is wrapped
|
||||
within `function(){ ... }`, thus forbids aliasing of declared global variables:
|
||||
```js
|
||||
```javascript
|
||||
A = "FAIL";
|
||||
var B = "FAIL";
|
||||
// can be `global`, `self`, `window` etc.
|
||||
@@ -1211,7 +1215,7 @@ To allow for better optimizations, the compiler makes various assumptions:
|
||||
suppress those errors.
|
||||
- Earlier versions of Chrome and Node.js will throw `ReferenceError` with the
|
||||
following:
|
||||
```js
|
||||
```javascript
|
||||
var a;
|
||||
try {
|
||||
throw 42;
|
||||
@@ -1224,20 +1228,29 @@ To allow for better optimizations, the compiler makes various assumptions:
|
||||
```
|
||||
UglifyJS may modify the input which in turn may suppress those errors.
|
||||
- Later versions of JavaScript will throw `SyntaxError` with the following:
|
||||
```js
|
||||
```javascript
|
||||
a => {
|
||||
let a;
|
||||
let a;
|
||||
};
|
||||
// SyntaxError: Identifier 'a' has already been declared
|
||||
```
|
||||
UglifyJS may modify the input which in turn may suppress those errors.
|
||||
- Later versions of JavaScript will throw `SyntaxError` with the following:
|
||||
```js
|
||||
```javascript
|
||||
try {
|
||||
// ...
|
||||
// ...
|
||||
} catch ({ message: a }) {
|
||||
var a;
|
||||
var a;
|
||||
}
|
||||
// SyntaxError: Identifier 'a' has already been declared
|
||||
```
|
||||
UglifyJS may modify the input which in turn may suppress those errors.
|
||||
- Some versions of Chrome and Node.js will throw `ReferenceError` with the
|
||||
following:
|
||||
```javascript
|
||||
console.log(((a, b = function() {
|
||||
return a;
|
||||
// ReferenceError: a is not defined
|
||||
}()) => b)());
|
||||
```
|
||||
UglifyJS may modify the input which in turn may suppress those errors.
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
require("../tools/exit");
|
||||
require("../tools/tty");
|
||||
|
||||
var fs = require("fs");
|
||||
var info = require("../package.json");
|
||||
@@ -265,7 +265,7 @@ if (paths.length) {
|
||||
process.stdin.on("data", function(chunk) {
|
||||
chunks.push(chunk);
|
||||
}).on("end", function() {
|
||||
files = [ chunks.join("") ];
|
||||
files = { STDIN: chunks.join("") };
|
||||
run();
|
||||
});
|
||||
process.stdin.resume();
|
||||
|
||||
155
lib/ast.js
155
lib/ast.js
@@ -160,6 +160,8 @@ var restore_transforms = [];
|
||||
AST_Node.enable_validation = function() {
|
||||
AST_Node.disable_validation();
|
||||
(function validate_transform(ctor) {
|
||||
ctor.SUBCLASSES.forEach(validate_transform);
|
||||
if (!HOP(ctor.prototype, "transform")) return;
|
||||
var transform = ctor.prototype.transform;
|
||||
ctor.prototype.transform = function(tw, in_list) {
|
||||
var node = transform.call(this, tw, in_list);
|
||||
@@ -173,7 +175,6 @@ AST_Node.enable_validation = function() {
|
||||
restore_transforms.push(function() {
|
||||
ctor.prototype.transform = transform;
|
||||
});
|
||||
ctor.SUBCLASSES.forEach(validate_transform);
|
||||
})(this);
|
||||
};
|
||||
|
||||
@@ -207,13 +208,23 @@ var AST_EmptyStatement = DEFNODE("EmptyStatement", null, {
|
||||
$documentation: "The empty statement (empty block or simply a semicolon)"
|
||||
}, AST_Statement);
|
||||
|
||||
function must_be_expression(node, prop) {
|
||||
if (!(node[prop] instanceof AST_Node)) throw new Error(prop + " must be AST_Node");
|
||||
if (node[prop] instanceof AST_Hole) throw new Error(prop + " cannot be AST_Hole");
|
||||
if (node[prop] instanceof AST_Spread) throw new Error(prop + " cannot be AST_Spread");
|
||||
if (node[prop] instanceof AST_Statement && !is_function(node[prop])) {
|
||||
throw new Error(prop + " cannot be AST_Statement");
|
||||
function validate_expression(value, prop, multiple, allow_spread, allow_hole) {
|
||||
multiple = multiple ? "contain" : "be";
|
||||
if (!(value instanceof AST_Node)) throw new Error(prop + " must " + multiple + " AST_Node");
|
||||
if (value instanceof AST_DefaultValue) throw new Error(prop + " cannot " + multiple + " AST_DefaultValue");
|
||||
if (value instanceof AST_Destructured) throw new Error(prop + " cannot " + multiple + " AST_Destructured");
|
||||
if (value instanceof AST_Hole && !allow_hole) throw new Error(prop + " cannot " + multiple + " AST_Hole");
|
||||
if (value instanceof AST_Spread && !allow_spread) throw new Error(prop + " cannot " + multiple + " AST_Spread");
|
||||
if (value instanceof AST_Statement && !is_function(value)) {
|
||||
throw new Error(prop + " cannot " + multiple + " AST_Statement");
|
||||
}
|
||||
if (value instanceof AST_SymbolDeclaration) {
|
||||
throw new Error(prop + " cannot " + multiple + " AST_SymbolDeclaration");
|
||||
}
|
||||
}
|
||||
|
||||
function must_be_expression(node, prop) {
|
||||
validate_expression(node[prop], prop);
|
||||
}
|
||||
|
||||
var AST_SimpleStatement = DEFNODE("SimpleStatement", "body", {
|
||||
@@ -502,14 +513,19 @@ var AST_Toplevel = DEFNODE("Toplevel", "globals", {
|
||||
}
|
||||
}, AST_Scope);
|
||||
|
||||
var AST_Lambda = DEFNODE("Lambda", "argnames length_read uses_arguments", {
|
||||
var AST_Lambda = DEFNODE("Lambda", "argnames length_read rest uses_arguments", {
|
||||
$documentation: "Base class for functions",
|
||||
$propdoc: {
|
||||
argnames: "[(AST_Destructured|AST_SymbolFunarg)*] array of function arguments and/or destructured literals",
|
||||
argnames: "[(AST_DefaultValue|AST_Destructured|AST_SymbolFunarg)*] array of function arguments and/or destructured literals",
|
||||
rest: "[(AST_Destructured|AST_SymbolFunarg)?] rest parameter, or null if absent",
|
||||
uses_arguments: "[boolean/S] tells whether this function accesses the arguments array",
|
||||
},
|
||||
each_argname: function(visit) {
|
||||
var tw = new TreeWalker(function(node) {
|
||||
if (node instanceof AST_DefaultValue) {
|
||||
node.name.walk(tw);
|
||||
return true;
|
||||
}
|
||||
if (node instanceof AST_DestructuredKeyVal) {
|
||||
node.value.walk(tw);
|
||||
return true;
|
||||
@@ -519,6 +535,7 @@ var AST_Lambda = DEFNODE("Lambda", "argnames length_read uses_arguments", {
|
||||
this.argnames.forEach(function(argname) {
|
||||
argname.walk(tw);
|
||||
});
|
||||
if (this.rest) this.rest.walk(tw);
|
||||
},
|
||||
walk: function(visitor) {
|
||||
var node = this;
|
||||
@@ -527,6 +544,7 @@ var AST_Lambda = DEFNODE("Lambda", "argnames length_read uses_arguments", {
|
||||
node.argnames.forEach(function(argname) {
|
||||
argname.walk(visitor);
|
||||
});
|
||||
if (node.rest) node.rest.walk(visitor);
|
||||
walk_body(node, visitor);
|
||||
});
|
||||
},
|
||||
@@ -534,7 +552,10 @@ var AST_Lambda = DEFNODE("Lambda", "argnames length_read uses_arguments", {
|
||||
this.argnames.forEach(function(node) {
|
||||
validate_destructured(node, function(node) {
|
||||
if (!(node instanceof AST_SymbolFunarg)) throw new Error("argnames must be AST_SymbolFunarg[]");
|
||||
});
|
||||
}, true);
|
||||
});
|
||||
if (this.rest != null) validate_destructured(this.rest, function(node) {
|
||||
if (!(node instanceof AST_SymbolFunarg)) throw new Error("rest must be AST_SymbolFunarg");
|
||||
});
|
||||
},
|
||||
}, AST_Scope);
|
||||
@@ -546,8 +567,20 @@ var AST_Accessor = DEFNODE("Accessor", null, {
|
||||
},
|
||||
}, AST_Lambda);
|
||||
|
||||
function is_arrow(node) {
|
||||
return node instanceof AST_AsyncArrow || node instanceof AST_Arrow;
|
||||
}
|
||||
|
||||
function is_function(node) {
|
||||
return node instanceof AST_Arrow || node instanceof AST_AsyncFunction || node instanceof AST_Function;
|
||||
return is_arrow(node) || node instanceof AST_AsyncFunction || node instanceof AST_Function;
|
||||
}
|
||||
|
||||
function walk_lambda(node, tw) {
|
||||
if (is_arrow(node) && node.value) {
|
||||
node.value.walk(tw);
|
||||
} else {
|
||||
walk_body(node, tw);
|
||||
}
|
||||
}
|
||||
|
||||
var AST_Arrow = DEFNODE("Arrow", "inlined value", {
|
||||
@@ -561,6 +594,7 @@ var AST_Arrow = DEFNODE("Arrow", "inlined value", {
|
||||
node.argnames.forEach(function(argname) {
|
||||
argname.walk(visitor);
|
||||
});
|
||||
if (node.rest) node.rest.walk(visitor);
|
||||
if (node.value) {
|
||||
node.value.walk(visitor);
|
||||
} else {
|
||||
@@ -579,9 +613,38 @@ var AST_Arrow = DEFNODE("Arrow", "inlined value", {
|
||||
}, AST_Lambda);
|
||||
|
||||
function is_async(node) {
|
||||
return node instanceof AST_AsyncDefun || node instanceof AST_AsyncFunction;
|
||||
return node instanceof AST_AsyncArrow || node instanceof AST_AsyncDefun || node instanceof AST_AsyncFunction;
|
||||
}
|
||||
|
||||
var AST_AsyncArrow = DEFNODE("AsyncArrow", "inlined value", {
|
||||
$documentation: "An asynchronous arrow function expression",
|
||||
$propdoc: {
|
||||
value: "[AST_Node?] simple return expression, or null if using function body.",
|
||||
},
|
||||
walk: function(visitor) {
|
||||
var node = this;
|
||||
visitor.visit(node, function() {
|
||||
node.argnames.forEach(function(argname) {
|
||||
argname.walk(visitor);
|
||||
});
|
||||
if (node.rest) node.rest.walk(visitor);
|
||||
if (node.value) {
|
||||
node.value.walk(visitor);
|
||||
} else {
|
||||
walk_body(node, visitor);
|
||||
}
|
||||
});
|
||||
},
|
||||
_validate: function() {
|
||||
if (this.name != null) throw new Error("name must be null");
|
||||
if (this.uses_arguments) throw new Error("uses_arguments must be false");
|
||||
if (this.value != null) {
|
||||
must_be_expression(this, "value");
|
||||
if (this.body.length) throw new Error("body must be empty if value exists");
|
||||
}
|
||||
},
|
||||
}, AST_Lambda);
|
||||
|
||||
var AST_AsyncFunction = DEFNODE("AsyncFunction", "inlined name", {
|
||||
$documentation: "An asynchronous function expression",
|
||||
$propdoc: {
|
||||
@@ -838,7 +901,6 @@ var AST_Const = DEFNODE("Const", null, {
|
||||
validate_destructured(node.name, function(node) {
|
||||
if (!(node instanceof AST_SymbolConst)) throw new Error("name must be AST_SymbolConst");
|
||||
});
|
||||
if (node.value != null) must_be_expression(node, "value");
|
||||
});
|
||||
},
|
||||
}, AST_Definitions);
|
||||
@@ -851,7 +913,6 @@ var AST_Let = DEFNODE("Let", null, {
|
||||
validate_destructured(node.name, function(node) {
|
||||
if (!(node instanceof AST_SymbolLet)) throw new Error("name must be AST_SymbolLet");
|
||||
});
|
||||
if (node.value != null) must_be_expression(node, "value");
|
||||
});
|
||||
},
|
||||
}, AST_Definitions);
|
||||
@@ -864,7 +925,6 @@ var AST_Var = DEFNODE("Var", null, {
|
||||
validate_destructured(node.name, function(node) {
|
||||
if (!(node instanceof AST_SymbolVar)) throw new Error("name must be AST_SymbolVar");
|
||||
});
|
||||
if (node.value != null) must_be_expression(node, "value");
|
||||
});
|
||||
},
|
||||
}, AST_Definitions);
|
||||
@@ -873,7 +933,7 @@ var AST_VarDef = DEFNODE("VarDef", "name value", {
|
||||
$documentation: "A variable declaration; only appears in a AST_Definitions node",
|
||||
$propdoc: {
|
||||
name: "[AST_Destructured|AST_SymbolVar] name of the variable",
|
||||
value: "[AST_Node?] initializer, or null of there's no initializer"
|
||||
value: "[AST_Node?] initializer, or null of there's no initializer",
|
||||
},
|
||||
walk: function(visitor) {
|
||||
var node = this;
|
||||
@@ -882,18 +942,34 @@ var AST_VarDef = DEFNODE("VarDef", "name value", {
|
||||
if (node.value) node.value.walk(visitor);
|
||||
});
|
||||
},
|
||||
_validate: function() {
|
||||
if (this.value != null) must_be_expression(this, "value");
|
||||
},
|
||||
});
|
||||
|
||||
/* -----[ OTHER ]----- */
|
||||
|
||||
var AST_DefaultValue = DEFNODE("DefaultValue", "name value", {
|
||||
$documentation: "A default value declaration",
|
||||
$propdoc: {
|
||||
name: "[AST_Destructured|AST_SymbolDeclaration] name of the variable",
|
||||
value: "[AST_Node] value to assign if variable is `undefined`",
|
||||
},
|
||||
walk: function(visitor) {
|
||||
var node = this;
|
||||
visitor.visit(node, function() {
|
||||
node.name.walk(visitor);
|
||||
node.value.walk(visitor);
|
||||
});
|
||||
},
|
||||
_validate: function() {
|
||||
must_be_expression(this, "value");
|
||||
},
|
||||
});
|
||||
|
||||
function must_be_expressions(node, prop, allow_spread, allow_hole) {
|
||||
node[prop].forEach(function(node) {
|
||||
if (!(node instanceof AST_Node)) throw new Error(prop + " must be AST_Node[]");
|
||||
if (!allow_hole && node instanceof AST_Hole) throw new Error(prop + " cannot be AST_Hole");
|
||||
if (!allow_spread && node instanceof AST_Spread) throw new Error(prop + " cannot be AST_Spread");
|
||||
if (node instanceof AST_Statement && !is_function(node)) {
|
||||
throw new Error(prop + " cannot contain AST_Statement");
|
||||
}
|
||||
validate_expression(node, prop, true, allow_spread, allow_hole);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1048,7 +1124,7 @@ var AST_Binary = DEFNODE("Binary", "operator left right", {
|
||||
});
|
||||
},
|
||||
_validate: function() {
|
||||
must_be_expression(this, "left");
|
||||
if (!(this instanceof AST_Assign)) must_be_expression(this, "left");
|
||||
if (typeof this.operator != "string") throw new Error("operator must be string");
|
||||
must_be_expression(this, "right");
|
||||
},
|
||||
@@ -1127,24 +1203,31 @@ var AST_Array = DEFNODE("Array", "elements", {
|
||||
},
|
||||
});
|
||||
|
||||
var AST_Destructured = DEFNODE("Destructured", null, {
|
||||
var AST_Destructured = DEFNODE("Destructured", "rest", {
|
||||
$documentation: "Base class for destructured literal",
|
||||
$propdoc: {
|
||||
rest: "[(AST_Destructured|AST_SymbolDeclaration|AST_SymbolRef)?] rest parameter, or null if absent",
|
||||
},
|
||||
});
|
||||
|
||||
function validate_destructured(node, check) {
|
||||
if (node instanceof AST_DestructuredArray) return node.elements.forEach(function(node) {
|
||||
if (!(node instanceof AST_Hole)) validate_destructured(node, check);
|
||||
});
|
||||
if (node instanceof AST_DestructuredObject) return node.properties.forEach(function(prop) {
|
||||
validate_destructured(prop.value, check);
|
||||
});
|
||||
function validate_destructured(node, check, allow_default) {
|
||||
if (node instanceof AST_DefaultValue && allow_default) return validate_destructured(node.name, check);
|
||||
if (node instanceof AST_Destructured) {
|
||||
if (node.rest != null) validate_destructured(node.rest, check);
|
||||
if (node instanceof AST_DestructuredArray) return node.elements.forEach(function(node) {
|
||||
if (!(node instanceof AST_Hole)) validate_destructured(node, check, true);
|
||||
});
|
||||
if (node instanceof AST_DestructuredObject) return node.properties.forEach(function(prop) {
|
||||
validate_destructured(prop.value, check, true);
|
||||
});
|
||||
}
|
||||
check(node);
|
||||
}
|
||||
|
||||
var AST_DestructuredArray = DEFNODE("DestructuredArray", "elements", {
|
||||
$documentation: "A destructured array literal",
|
||||
$propdoc: {
|
||||
elements: "[AST_Node*] array of elements",
|
||||
elements: "[(AST_DefaultValue|AST_Destructured|AST_SymbolDeclaration|AST_SymbolRef)*] array of elements",
|
||||
},
|
||||
walk: function(visitor) {
|
||||
var node = this;
|
||||
@@ -1152,6 +1235,7 @@ var AST_DestructuredArray = DEFNODE("DestructuredArray", "elements", {
|
||||
node.elements.forEach(function(element) {
|
||||
element.walk(visitor);
|
||||
});
|
||||
if (node.rest) node.rest.walk(visitor);
|
||||
});
|
||||
},
|
||||
}, AST_Destructured);
|
||||
@@ -1160,7 +1244,7 @@ var AST_DestructuredKeyVal = DEFNODE("DestructuredKeyVal", "key value", {
|
||||
$documentation: "A key: value destructured property",
|
||||
$propdoc: {
|
||||
key: "[string|AST_Node] property name. For computed property this is an AST_Node.",
|
||||
value: "[AST_Node] property value",
|
||||
value: "[AST_DefaultValue|AST_Destructured|AST_SymbolDeclaration|AST_SymbolRef] property value",
|
||||
},
|
||||
walk: function(visitor) {
|
||||
var node = this;
|
||||
@@ -1174,7 +1258,7 @@ var AST_DestructuredKeyVal = DEFNODE("DestructuredKeyVal", "key value", {
|
||||
if (!(this.key instanceof AST_Node)) throw new Error("key must be string or AST_Node");
|
||||
must_be_expression(this, "key");
|
||||
}
|
||||
must_be_expression(this, "value");
|
||||
if (!(this.value instanceof AST_Node)) throw new Error("value must be AST_Node");
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1189,6 +1273,7 @@ var AST_DestructuredObject = DEFNODE("DestructuredObject", "properties", {
|
||||
node.properties.forEach(function(prop) {
|
||||
prop.walk(visitor);
|
||||
});
|
||||
if (node.rest) node.rest.walk(visitor);
|
||||
});
|
||||
},
|
||||
_validate: function() {
|
||||
@@ -1318,7 +1403,7 @@ var AST_Label = DEFNODE("Label", "references", {
|
||||
}
|
||||
}, AST_Symbol);
|
||||
|
||||
var AST_SymbolRef = DEFNODE("SymbolRef", "fixed in_arg", {
|
||||
var AST_SymbolRef = DEFNODE("SymbolRef", "fixed in_arg redef", {
|
||||
$documentation: "Reference to some symbol (not definition/declaration)",
|
||||
}, AST_Symbol);
|
||||
|
||||
|
||||
1493
lib/compress.js
1493
lib/compress.js
File diff suppressed because it is too large
Load Diff
@@ -87,6 +87,7 @@ function minify(files, options) {
|
||||
sourceMap: false,
|
||||
timings: false,
|
||||
toplevel: false,
|
||||
v8: false,
|
||||
validate: false,
|
||||
warnings: false,
|
||||
webkit: false,
|
||||
@@ -102,6 +103,7 @@ function minify(files, options) {
|
||||
set_shorthand("ie8", options, [ "compress", "mangle", "output" ]);
|
||||
set_shorthand("keep_fnames", options, [ "compress", "mangle" ]);
|
||||
set_shorthand("toplevel", options, [ "compress", "mangle" ]);
|
||||
set_shorthand("v8", options, [ "mangle", "output" ]);
|
||||
set_shorthand("webkit", options, [ "mangle", "output" ]);
|
||||
var quoted_props;
|
||||
if (options.mangle) {
|
||||
@@ -113,6 +115,7 @@ function minify(files, options) {
|
||||
properties: false,
|
||||
reserved: [],
|
||||
toplevel: false,
|
||||
v8: false,
|
||||
webkit: false,
|
||||
}, true);
|
||||
if (options.mangle.properties) {
|
||||
|
||||
@@ -692,7 +692,7 @@ function OutputStream(options) {
|
||||
// [ 1, (2, 3), 4 ] ==> [ 1, 3, 4 ]
|
||||
return p instanceof AST_Array
|
||||
// () => (foo, bar)
|
||||
|| p instanceof AST_Arrow && p.value === this
|
||||
|| is_arrow(p) && p.value === this
|
||||
// await (foo, bar)
|
||||
|| p instanceof AST_Await
|
||||
// 1 + (2, 3) + 4 ==> 8
|
||||
@@ -702,6 +702,8 @@ function OutputStream(options) {
|
||||
// (false, true) ? (a = 10, b = 20) : (c = 30)
|
||||
// ==> 20 (side effect, set a := 10 and b := 20)
|
||||
|| p instanceof AST_Conditional
|
||||
// [ a = (1, 2) ] = [] ==> a == 2
|
||||
|| p instanceof AST_DefaultValue
|
||||
// { [(1, 2)]: 3 }[2] ==> 3
|
||||
// { foo: (1, 2) }.foo ==> 2
|
||||
|| p instanceof AST_DestructuredKeyVal
|
||||
@@ -811,6 +813,9 @@ function OutputStream(options) {
|
||||
// ({ p: a } = o);
|
||||
if (this.left instanceof AST_DestructuredObject) return needs_parens_obj(output);
|
||||
});
|
||||
PARENS(AST_AsyncArrow, function(output) {
|
||||
return needs_parens_assign_cond(this, output);
|
||||
});
|
||||
PARENS(AST_Conditional, function(output) {
|
||||
return needs_parens_assign_cond(this, output);
|
||||
});
|
||||
@@ -990,16 +995,25 @@ function OutputStream(options) {
|
||||
});
|
||||
|
||||
/* -----[ functions ]----- */
|
||||
DEFPRINT(AST_Arrow, function(output) {
|
||||
var self = this;
|
||||
if (self.argnames.length == 1 && self.argnames[0] instanceof AST_SymbolFunarg) {
|
||||
self.argnames[0].print(output);
|
||||
} else output.with_parens(function() {
|
||||
function print_funargs(self, output) {
|
||||
output.with_parens(function() {
|
||||
self.argnames.forEach(function(arg, i) {
|
||||
if (i) output.comma();
|
||||
arg.print(output);
|
||||
});
|
||||
if (self.rest) {
|
||||
if (self.argnames.length) output.comma();
|
||||
output.print("...");
|
||||
self.rest.print(output);
|
||||
}
|
||||
});
|
||||
}
|
||||
function print_arrow(self, output) {
|
||||
if (self.argnames.length == 1 && self.argnames[0] instanceof AST_SymbolFunarg && !self.rest) {
|
||||
self.argnames[0].print(output);
|
||||
} else {
|
||||
print_funargs(self, output);
|
||||
}
|
||||
output.space();
|
||||
output.print("=>");
|
||||
output.space();
|
||||
@@ -1008,18 +1022,21 @@ function OutputStream(options) {
|
||||
} else {
|
||||
print_braced(self, output, true);
|
||||
}
|
||||
}
|
||||
DEFPRINT(AST_Arrow, function(output) {
|
||||
print_arrow(this, output);
|
||||
});
|
||||
DEFPRINT(AST_AsyncArrow, function(output) {
|
||||
output.print("async");
|
||||
output.space();
|
||||
print_arrow(this, output);
|
||||
});
|
||||
function print_lambda(self, output) {
|
||||
if (self.name) {
|
||||
output.space();
|
||||
self.name.print(output);
|
||||
}
|
||||
output.with_parens(function() {
|
||||
self.argnames.forEach(function(arg, i) {
|
||||
if (i) output.comma();
|
||||
arg.print(output);
|
||||
});
|
||||
});
|
||||
print_funargs(self, output);
|
||||
output.space();
|
||||
print_braced(self, output, true);
|
||||
}
|
||||
@@ -1200,7 +1217,7 @@ function OutputStream(options) {
|
||||
if (noin) node.walk(new TreeWalker(function(node) {
|
||||
if (parens) return true;
|
||||
if (node instanceof AST_Binary && node.operator == "in") return parens = true;
|
||||
if (node instanceof AST_Scope && !(node instanceof AST_Arrow && node.value)) return true;
|
||||
if (node instanceof AST_Scope && !(is_arrow(node) && node.value)) return true;
|
||||
}));
|
||||
node.print(output, parens);
|
||||
}
|
||||
@@ -1218,6 +1235,15 @@ function OutputStream(options) {
|
||||
}
|
||||
});
|
||||
|
||||
DEFPRINT(AST_DefaultValue, function(output) {
|
||||
var self = this;
|
||||
self.name.print(output);
|
||||
output.space();
|
||||
output.print("=");
|
||||
output.space();
|
||||
self.value.print(output);
|
||||
});
|
||||
|
||||
/* -----[ other expressions ]----- */
|
||||
function print_call_args(self, output) {
|
||||
if (self.expression instanceof AST_Call || self.expression instanceof AST_Lambda) {
|
||||
@@ -1344,25 +1370,30 @@ function OutputStream(options) {
|
||||
} : noop);
|
||||
});
|
||||
DEFPRINT(AST_DestructuredArray, function(output) {
|
||||
var a = this.elements, len = a.length;
|
||||
output.with_square(len > 0 ? function() {
|
||||
var a = this.elements, len = a.length, rest = this.rest;
|
||||
output.with_square(len || rest ? function() {
|
||||
output.space();
|
||||
a.forEach(function(exp, i) {
|
||||
if (i) output.comma();
|
||||
exp.print(output);
|
||||
});
|
||||
if (rest) {
|
||||
if (len) output.comma();
|
||||
output.print("...");
|
||||
rest.print(output);
|
||||
} else if (a[len - 1] instanceof AST_Hole) {
|
||||
// If the final element is a hole, we need to make sure it
|
||||
// doesn't look like a trailing comma, by inserting an actual
|
||||
// trailing comma.
|
||||
if (i === len - 1 && exp instanceof AST_Hole)
|
||||
output.comma();
|
||||
});
|
||||
output.comma();
|
||||
}
|
||||
output.space();
|
||||
} : noop);
|
||||
});
|
||||
DEFPRINT(AST_DestructuredKeyVal, print_key_value);
|
||||
DEFPRINT(AST_DestructuredObject, function(output) {
|
||||
var props = this.properties;
|
||||
if (props.length > 0) output.with_block(function() {
|
||||
var props = this.properties, len = props.length, rest = this.rest;
|
||||
if (len || rest) output.with_block(function() {
|
||||
props.forEach(function(prop, i) {
|
||||
if (i) {
|
||||
output.print(",");
|
||||
@@ -1371,6 +1402,15 @@ function OutputStream(options) {
|
||||
output.indent();
|
||||
prop.print(output);
|
||||
});
|
||||
if (rest) {
|
||||
if (len) {
|
||||
output.print(",");
|
||||
output.newline();
|
||||
}
|
||||
output.indent();
|
||||
output.print("...");
|
||||
rest.print(output);
|
||||
}
|
||||
output.newline();
|
||||
});
|
||||
else print_braced_empty(this, output);
|
||||
|
||||
274
lib/parse.js
274
lib/parse.js
@@ -737,7 +737,7 @@ function parse($TEXT, options) {
|
||||
|
||||
function semicolon(optional) {
|
||||
if (is("punc", ";")) next();
|
||||
else if (!optional && !can_insert_semicolon()) expect_token("punc", ";");
|
||||
else if (!optional && !can_insert_semicolon()) expect(";");
|
||||
}
|
||||
|
||||
function parenthesised() {
|
||||
@@ -796,13 +796,14 @@ function parse($TEXT, options) {
|
||||
next();
|
||||
return function_(AST_AsyncDefun);
|
||||
}
|
||||
break;
|
||||
case "await":
|
||||
if (S.in_async) return simple_statement();
|
||||
default:
|
||||
return is_token(peek(), "punc", ":")
|
||||
? labeled_statement()
|
||||
: simple_statement();
|
||||
break;
|
||||
}
|
||||
return is_token(peek(), "punc", ":")
|
||||
? labeled_statement()
|
||||
: simple_statement();
|
||||
|
||||
case "punc":
|
||||
switch (S.token.value) {
|
||||
@@ -1039,36 +1040,74 @@ function parse($TEXT, options) {
|
||||
}
|
||||
|
||||
function to_funarg(node) {
|
||||
if (node instanceof AST_Array) return new AST_DestructuredArray({
|
||||
if (node instanceof AST_Array) {
|
||||
var rest = null;
|
||||
if (node.elements[node.elements.length - 1] instanceof AST_Spread) {
|
||||
rest = to_funarg(node.elements.pop().expression);
|
||||
}
|
||||
return new AST_DestructuredArray({
|
||||
start: node.start,
|
||||
elements: node.elements.map(to_funarg),
|
||||
rest: rest,
|
||||
end: node.end,
|
||||
});
|
||||
}
|
||||
if (node instanceof AST_Assign) return new AST_DefaultValue({
|
||||
start: node.start,
|
||||
elements: node.elements.map(function(node) {
|
||||
return node instanceof AST_Hole ? node : to_funarg(node);
|
||||
}),
|
||||
end: node.end,
|
||||
});
|
||||
if (node instanceof AST_Object) return new AST_DestructuredObject({
|
||||
start: node.start,
|
||||
properties: node.properties.map(function(prop) {
|
||||
if (!(prop instanceof AST_ObjectKeyVal)) token_error(prop.start, "Invalid destructuring assignment");
|
||||
return new AST_DestructuredKeyVal({
|
||||
start: prop.start,
|
||||
key: prop.key,
|
||||
value: to_funarg(prop.value),
|
||||
end: prop.end,
|
||||
});
|
||||
}),
|
||||
name: to_funarg(node.left),
|
||||
value: node.right,
|
||||
end: node.end,
|
||||
});
|
||||
if (node instanceof AST_DefaultValue) {
|
||||
node.name = to_funarg(node.name);
|
||||
return node;
|
||||
}
|
||||
if (node instanceof AST_DestructuredArray) {
|
||||
node.elements = node.elements.map(to_funarg);
|
||||
if (node.rest) node.rest = to_funarg(node.rest);
|
||||
return node;
|
||||
}
|
||||
if (node instanceof AST_DestructuredObject) {
|
||||
node.properties.forEach(function(prop) {
|
||||
prop.value = to_funarg(prop.value);
|
||||
});
|
||||
if (node.rest) node.rest = to_funarg(node.rest);
|
||||
return node;
|
||||
}
|
||||
if (node instanceof AST_Hole) return node;
|
||||
if (node instanceof AST_Object) {
|
||||
var rest = null;
|
||||
if (node.properties[node.properties.length - 1] instanceof AST_Spread) {
|
||||
rest = to_funarg(node.properties.pop().expression);
|
||||
}
|
||||
return new AST_DestructuredObject({
|
||||
start: node.start,
|
||||
properties: node.properties.map(function(prop) {
|
||||
if (!(prop instanceof AST_ObjectKeyVal)) token_error(prop.start, "Invalid destructuring assignment");
|
||||
return new AST_DestructuredKeyVal({
|
||||
start: prop.start,
|
||||
key: prop.key,
|
||||
value: to_funarg(prop.value),
|
||||
end: prop.end,
|
||||
});
|
||||
}),
|
||||
rest: rest,
|
||||
end: node.end,
|
||||
});
|
||||
}
|
||||
if (node instanceof AST_SymbolFunarg) return node;
|
||||
if (node instanceof AST_SymbolRef) return new AST_SymbolFunarg(node);
|
||||
token_error(node.start, "Invalid arrow parameter");
|
||||
}
|
||||
|
||||
function arrow(exprs, start) {
|
||||
function arrow(exprs, start, async) {
|
||||
var was_async = S.in_async;
|
||||
S.in_async = false;
|
||||
S.in_async = async;
|
||||
var was_funarg = S.in_funarg;
|
||||
S.in_funarg = S.in_function;
|
||||
var argnames = exprs.map(to_funarg);
|
||||
var rest = exprs.rest || null;
|
||||
if (rest) rest = to_funarg(rest);
|
||||
S.in_funarg = was_funarg;
|
||||
expect("=>");
|
||||
var body, value;
|
||||
@@ -1094,9 +1133,10 @@ function parse($TEXT, options) {
|
||||
S.in_loop = loop;
|
||||
S.labels = labels;
|
||||
S.in_async = was_async;
|
||||
return new AST_Arrow({
|
||||
return new (async ? AST_AsyncArrow : AST_Arrow)({
|
||||
start: start,
|
||||
argnames: argnames,
|
||||
rest: rest,
|
||||
body: body,
|
||||
value: value,
|
||||
end: prev(),
|
||||
@@ -1122,7 +1162,7 @@ function parse($TEXT, options) {
|
||||
var was_funarg = S.in_funarg;
|
||||
S.in_funarg = S.in_function;
|
||||
var argnames = expr_list(")", !options.strict, false, function() {
|
||||
return maybe_destructured(AST_SymbolFunarg);
|
||||
return maybe_default(AST_SymbolFunarg);
|
||||
});
|
||||
S.in_funarg = was_funarg;
|
||||
var loop = S.in_loop;
|
||||
@@ -1136,6 +1176,7 @@ function parse($TEXT, options) {
|
||||
if (S.input.has_directive("use strict")) {
|
||||
if (name) strict_verify_symbol(name);
|
||||
argnames.forEach(strict_verify_symbol);
|
||||
if (argnames.rest) strict_verify_symbol(argnames.rest);
|
||||
}
|
||||
S.input.pop_directives_stack();
|
||||
--S.in_function;
|
||||
@@ -1145,6 +1186,7 @@ function parse($TEXT, options) {
|
||||
return new ctor({
|
||||
name: name,
|
||||
argnames: argnames,
|
||||
rest: argnames.rest || null,
|
||||
body: body
|
||||
});
|
||||
};
|
||||
@@ -1166,7 +1208,7 @@ function parse($TEXT, options) {
|
||||
expect("{");
|
||||
var a = [];
|
||||
while (!is("punc", "}")) {
|
||||
if (is("eof")) expect_token("punc", "}");
|
||||
if (is("eof")) expect("}");
|
||||
a.push(statement());
|
||||
}
|
||||
next();
|
||||
@@ -1177,7 +1219,7 @@ function parse($TEXT, options) {
|
||||
expect("{");
|
||||
var a = [], branch, cur, default_branch, tmp;
|
||||
while (!is("punc", "}")) {
|
||||
if (is("eof")) expect_token("punc", "}");
|
||||
if (is("eof")) expect("}");
|
||||
if (is("keyword", "case")) {
|
||||
if (branch) branch.end = prev();
|
||||
cur = [];
|
||||
@@ -1393,16 +1435,9 @@ function parse($TEXT, options) {
|
||||
}
|
||||
unexpected();
|
||||
}
|
||||
var ctor;
|
||||
if (is("name", "async") && is_token(peek(), "keyword", "function")) {
|
||||
if (is("keyword", "function")) {
|
||||
next();
|
||||
ctor = AST_AsyncFunction;
|
||||
} else if (is("keyword", "function")) {
|
||||
ctor = AST_Function;
|
||||
}
|
||||
if (ctor) {
|
||||
next();
|
||||
var func = function_(ctor);
|
||||
var func = function_(AST_Function);
|
||||
func.start = start;
|
||||
func.end = prev();
|
||||
return subscripts(func, allow_calls);
|
||||
@@ -1410,6 +1445,30 @@ function parse($TEXT, options) {
|
||||
if (is("name")) {
|
||||
var sym = _make_symbol(AST_SymbolRef, start);
|
||||
next();
|
||||
if (sym.name == "async") {
|
||||
if (is("keyword", "function")) {
|
||||
next();
|
||||
var func = function_(AST_AsyncFunction);
|
||||
func.start = start;
|
||||
func.end = prev();
|
||||
return subscripts(func, allow_calls);
|
||||
}
|
||||
if (is("name")) {
|
||||
start = S.token;
|
||||
sym = _make_symbol(AST_SymbolRef, start);
|
||||
next();
|
||||
return arrow([ sym ], start, true);
|
||||
}
|
||||
if (is("punc", "(")) {
|
||||
var call = subscripts(sym, allow_calls);
|
||||
if (!is("punc", "=>")) return call;
|
||||
var args = call.args;
|
||||
if (args[args.length - 1] instanceof AST_Spread) {
|
||||
args.rest = args.pop().expression;
|
||||
}
|
||||
return arrow(args, start, true);
|
||||
}
|
||||
}
|
||||
return is("punc", "=>") ? arrow([ sym ], start) : subscripts(sym, allow_calls);
|
||||
}
|
||||
if (ATOMIC_START_TOKEN[S.token.type]) {
|
||||
@@ -1426,17 +1485,22 @@ function parse($TEXT, options) {
|
||||
if (allow_trailing_comma && is("punc", closing)) break;
|
||||
if (allow_empty && is("punc", ",")) {
|
||||
a.push(new AST_Hole({ start: S.token, end: S.token }));
|
||||
} else if (parser === maybe_assign && is("operator", "...")) {
|
||||
} else if (!is("operator", "...")) {
|
||||
a.push(parser());
|
||||
} else if (parser === maybe_assign) {
|
||||
a.push(new AST_Spread({
|
||||
start: S.token,
|
||||
expression: (next(), parser()),
|
||||
end: prev(),
|
||||
}));
|
||||
} else {
|
||||
a.push(parser());
|
||||
next();
|
||||
a.rest = parser();
|
||||
if (a.rest instanceof AST_DefaultValue) token_error(a.rest.start, "Invalid rest parameter");
|
||||
break;
|
||||
}
|
||||
}
|
||||
next();
|
||||
expect(closing);
|
||||
return a;
|
||||
}
|
||||
|
||||
@@ -1468,6 +1532,32 @@ function parse($TEXT, options) {
|
||||
}));
|
||||
continue;
|
||||
}
|
||||
if (is_token(peek(), "operator", "=")) {
|
||||
var name = as_symbol(AST_SymbolRef);
|
||||
next();
|
||||
a.push(new AST_ObjectKeyVal({
|
||||
start: start,
|
||||
key: start.value,
|
||||
value: new AST_Assign({
|
||||
start: start,
|
||||
left: name,
|
||||
operator: "=",
|
||||
right: maybe_assign(),
|
||||
end: prev(),
|
||||
}),
|
||||
end: prev(),
|
||||
}));
|
||||
continue;
|
||||
}
|
||||
if (is_token(peek(), "punc", ",") || is_token(peek(), "punc", "}")) {
|
||||
a.push(new AST_ObjectKeyVal({
|
||||
start: start,
|
||||
key: start.value,
|
||||
value: as_symbol(AST_SymbolRef),
|
||||
end: prev(),
|
||||
}));
|
||||
continue;
|
||||
}
|
||||
var key = as_property_key();
|
||||
if (is("punc", "(")) {
|
||||
var func_start = S.token;
|
||||
@@ -1492,15 +1582,6 @@ function parse($TEXT, options) {
|
||||
}));
|
||||
continue;
|
||||
}
|
||||
if (is("punc", ",") || is("punc", "}")) {
|
||||
a.push(new AST_ObjectKeyVal({
|
||||
start: start,
|
||||
key: key,
|
||||
value: _make_symbol(AST_SymbolRef, start),
|
||||
end: prev(),
|
||||
}));
|
||||
continue;
|
||||
}
|
||||
if (start.type == "name") switch (key) {
|
||||
case "async":
|
||||
key = as_property_key();
|
||||
@@ -1561,9 +1642,8 @@ function parse($TEXT, options) {
|
||||
}
|
||||
|
||||
function as_name() {
|
||||
if (!is("name")) expect_token("name");
|
||||
var name = S.token.value;
|
||||
next();
|
||||
expect_token("name");
|
||||
return name;
|
||||
}
|
||||
|
||||
@@ -1599,17 +1679,19 @@ function parse($TEXT, options) {
|
||||
var start = S.token;
|
||||
if (is("punc", "[")) {
|
||||
next();
|
||||
var elements = expr_list("]", !options.strict, true, function() {
|
||||
return maybe_default(type);
|
||||
});
|
||||
return new AST_DestructuredArray({
|
||||
start: start,
|
||||
elements: expr_list("]", !options.strict, true, function() {
|
||||
return maybe_destructured(type);
|
||||
}),
|
||||
elements: elements,
|
||||
rest: elements.rest || null,
|
||||
end: prev(),
|
||||
});
|
||||
}
|
||||
if (is("punc", "{")) {
|
||||
next();
|
||||
var first = true, a = [];
|
||||
var first = true, a = [], rest = null;
|
||||
while (!is("punc", "}")) {
|
||||
if (first) first = false; else expect(",");
|
||||
// allow trailing comma
|
||||
@@ -1621,28 +1703,57 @@ function parse($TEXT, options) {
|
||||
a.push(new AST_DestructuredKeyVal({
|
||||
start: key_start,
|
||||
key: key,
|
||||
value: maybe_destructured(type),
|
||||
value: maybe_default(type),
|
||||
end: prev(),
|
||||
}));
|
||||
continue;
|
||||
}
|
||||
if (is("operator", "...")) {
|
||||
next();
|
||||
rest = maybe_destructured(type);
|
||||
break;
|
||||
}
|
||||
var name = as_symbol(type);
|
||||
if (is("operator", "=")) {
|
||||
next();
|
||||
name = new AST_DefaultValue({
|
||||
start: name.start,
|
||||
name: name,
|
||||
value: maybe_assign(),
|
||||
end: prev(),
|
||||
});
|
||||
}
|
||||
a.push(new AST_DestructuredKeyVal({
|
||||
start: key_start,
|
||||
key: key_start.value,
|
||||
value: as_symbol(type),
|
||||
value: name,
|
||||
end: prev(),
|
||||
}));
|
||||
}
|
||||
next();
|
||||
expect("}");
|
||||
return new AST_DestructuredObject({
|
||||
start: start,
|
||||
properties: a,
|
||||
rest: rest,
|
||||
end: prev(),
|
||||
});
|
||||
}
|
||||
return as_symbol(type);
|
||||
}
|
||||
|
||||
function maybe_default(type) {
|
||||
var start = S.token;
|
||||
var name = maybe_destructured(type);
|
||||
if (!is("operator", "=")) return name;
|
||||
next();
|
||||
return new AST_DefaultValue({
|
||||
start: start,
|
||||
name: name,
|
||||
value: maybe_assign(),
|
||||
end: prev(),
|
||||
});
|
||||
}
|
||||
|
||||
function mark_pure(call) {
|
||||
var start = call.start;
|
||||
var comments = start.comments_before;
|
||||
@@ -1787,22 +1898,47 @@ function parse($TEXT, options) {
|
||||
|
||||
function to_destructured(node) {
|
||||
if (node instanceof AST_Array) {
|
||||
var rest = null;
|
||||
if (node.elements[node.elements.length - 1] instanceof AST_Spread) {
|
||||
rest = to_destructured(node.elements.pop().expression);
|
||||
if (!(rest instanceof AST_Destructured || is_assignable(rest))) return node;
|
||||
}
|
||||
var elements = node.elements.map(to_destructured);
|
||||
return all(elements, function(node) {
|
||||
return node instanceof AST_Destructured || node instanceof AST_Hole || is_assignable(node);
|
||||
return node instanceof AST_DefaultValue
|
||||
|| node instanceof AST_Destructured
|
||||
|| node instanceof AST_Hole
|
||||
|| is_assignable(node);
|
||||
}) ? new AST_DestructuredArray({
|
||||
start: node.start,
|
||||
elements: elements,
|
||||
rest: rest,
|
||||
end: node.end,
|
||||
}) : node;
|
||||
}
|
||||
if (node instanceof AST_Assign) {
|
||||
var name = to_destructured(node.left);
|
||||
return name instanceof AST_Destructured || is_assignable(name) ? new AST_DefaultValue({
|
||||
start: node.start,
|
||||
name: name,
|
||||
value: node.right,
|
||||
end: node.end,
|
||||
}) : node;
|
||||
}
|
||||
if (!(node instanceof AST_Object)) return node;
|
||||
var rest = null;
|
||||
if (node.properties[node.properties.length - 1] instanceof AST_Spread) {
|
||||
rest = to_destructured(node.properties.pop().expression);
|
||||
if (!(rest instanceof AST_Destructured || is_assignable(rest))) return node;
|
||||
}
|
||||
var props = [];
|
||||
for (var i = 0; i < node.properties.length; i++) {
|
||||
var prop = node.properties[i];
|
||||
if (!(prop instanceof AST_ObjectKeyVal)) return node;
|
||||
var value = to_destructured(prop.value);
|
||||
if (!(value instanceof AST_Destructured || is_assignable(value))) return node;
|
||||
if (!(value instanceof AST_DefaultValue || value instanceof AST_Destructured || is_assignable(value))) {
|
||||
return node;
|
||||
}
|
||||
props.push(new AST_DestructuredKeyVal({
|
||||
start: prop.start,
|
||||
key: prop.key,
|
||||
@@ -1813,6 +1949,7 @@ function parse($TEXT, options) {
|
||||
return new AST_DestructuredObject({
|
||||
start: node.start,
|
||||
properties: props,
|
||||
rest: rest,
|
||||
end: node.end,
|
||||
});
|
||||
}
|
||||
@@ -1840,15 +1977,20 @@ function parse($TEXT, options) {
|
||||
var start = S.token;
|
||||
var exprs = [];
|
||||
while (true) {
|
||||
if (maybe_arrow && is("operator", "...")) {
|
||||
next();
|
||||
exprs.rest = maybe_destructured(AST_SymbolFunarg);
|
||||
break;
|
||||
}
|
||||
exprs.push(maybe_assign(no_in));
|
||||
if (!is("punc", ",")) break;
|
||||
next();
|
||||
if (maybe_arrow && is("punc", ")") && is_token(peek(), "punc", "=>")) break;
|
||||
}
|
||||
return exprs.length == 1 ? exprs[0] : new AST_Sequence({
|
||||
start : start,
|
||||
expressions : exprs,
|
||||
end : prev()
|
||||
return exprs.length == 1 && !exprs.rest ? exprs[0] : new AST_Sequence({
|
||||
start: start,
|
||||
expressions: exprs,
|
||||
end: prev(),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1861,7 +2003,9 @@ function parse($TEXT, options) {
|
||||
|
||||
if (options.expression) {
|
||||
handle_regexp();
|
||||
return expression();
|
||||
var exp = expression();
|
||||
expect_token("eof");
|
||||
return exp;
|
||||
}
|
||||
|
||||
return function() {
|
||||
|
||||
75
lib/scope.js
75
lib/scope.js
@@ -48,7 +48,6 @@ function SymbolDef(id, scope, orig, init) {
|
||||
this.global = false;
|
||||
this.id = id;
|
||||
this.init = init;
|
||||
this.lambda = orig instanceof AST_SymbolLambda;
|
||||
this.mangled_name = null;
|
||||
this.name = orig.name;
|
||||
this.orig = [ orig ];
|
||||
@@ -120,6 +119,7 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
|
||||
node.argnames.forEach(function(argname) {
|
||||
argname.walk(tw);
|
||||
});
|
||||
if (node.rest) node.rest.walk(tw);
|
||||
walk_body(node, tw);
|
||||
});
|
||||
return true;
|
||||
@@ -221,31 +221,33 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
|
||||
node.argnames.forEach(function(argname) {
|
||||
argname.walk(tw);
|
||||
});
|
||||
if (node.rest) node.rest.walk(tw);
|
||||
in_arg.pop();
|
||||
if (node instanceof AST_Arrow && node.value) {
|
||||
node.value.walk(tw);
|
||||
} else {
|
||||
walk_body(node, tw);
|
||||
}
|
||||
walk_lambda(node, tw);
|
||||
return true;
|
||||
}
|
||||
if (node instanceof AST_LoopControl) {
|
||||
if (node.label) node.label.thedef.references.push(node);
|
||||
return true;
|
||||
}
|
||||
// ensure mangling works if `catch` reuses a scope variable
|
||||
if (node instanceof AST_SymbolCatch) {
|
||||
var def = node.definition().redefined();
|
||||
if (def) for (var s = node.scope; s; s = s.parent_scope) {
|
||||
push_uniq(s.enclosed, def);
|
||||
if (s === def.scope) break;
|
||||
if (node instanceof AST_SymbolDeclaration) {
|
||||
if (node instanceof AST_SymbolCatch) {
|
||||
// ensure mangling works if `catch` reuses a scope variable
|
||||
var def = node.definition().redefined();
|
||||
if (def) for (var s = node.scope; s; s = s.parent_scope) {
|
||||
push_uniq(s.enclosed, def);
|
||||
if (s === def.scope) break;
|
||||
}
|
||||
} else if (node instanceof AST_SymbolConst) {
|
||||
// ensure compression works if `const` reuses a scope variable
|
||||
var redef = node.definition().redefined();
|
||||
if (redef) redef.const_redefs = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// ensure compression works if `const` reuses a scope variable
|
||||
if (node instanceof AST_SymbolConst) {
|
||||
var redef = node.definition().redefined();
|
||||
if (redef) redef.const_redefs = true;
|
||||
if (node.name != "arguments") return true;
|
||||
var parent = node instanceof AST_SymbolVar && tw.parent();
|
||||
if (parent instanceof AST_VarDef && !parent.value) return true;
|
||||
var sym = node.scope.resolve().find_variable("arguments");
|
||||
if (sym && is_arguments(sym)) sym.scope.uses_arguments = 3;
|
||||
return true;
|
||||
}
|
||||
if (node instanceof AST_SymbolRef) {
|
||||
@@ -265,10 +267,7 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
|
||||
}
|
||||
if (!sym) {
|
||||
sym = self.def_global(node);
|
||||
} else if (name == "arguments"
|
||||
&& sym.orig[0] instanceof AST_SymbolFunarg
|
||||
&& !(sym.orig[1] instanceof AST_SymbolFunarg)
|
||||
&& !(sym.scope instanceof AST_Arrow)) {
|
||||
} else if (name == "arguments" && is_arguments(sym)) {
|
||||
var parent = tw.parent();
|
||||
if (parent instanceof AST_Assign && parent.left === node
|
||||
|| parent instanceof AST_Unary && unary_side_effects[parent.operator]) {
|
||||
@@ -312,8 +311,9 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
|
||||
}
|
||||
if (node instanceof AST_SymbolLambda) {
|
||||
var def = node.thedef;
|
||||
redefine(node, node.scope.parent_scope.resolve());
|
||||
if (typeof node.thedef.init !== "undefined") {
|
||||
if (!redefine(node, node.scope.parent_scope.resolve())) {
|
||||
delete def.defun;
|
||||
} else if (typeof node.thedef.init !== "undefined") {
|
||||
node.thedef.init = false;
|
||||
} else if (def.init) {
|
||||
node.thedef.init = def.init;
|
||||
@@ -322,12 +322,18 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
|
||||
}
|
||||
}));
|
||||
|
||||
function is_arguments(sym) {
|
||||
return sym.orig[0] instanceof AST_SymbolFunarg
|
||||
&& !(sym.orig[1] instanceof AST_SymbolFunarg || sym.orig[2] instanceof AST_SymbolFunarg)
|
||||
&& !is_arrow(sym.scope);
|
||||
}
|
||||
|
||||
function redefine(node, scope) {
|
||||
var name = node.name;
|
||||
var old_def = node.thedef;
|
||||
if (!all(old_def.orig, function(sym) {
|
||||
return !(sym instanceof AST_SymbolConst || sym instanceof AST_SymbolLet);
|
||||
})) return;
|
||||
})) return false;
|
||||
var new_def = scope.find_variable(name);
|
||||
if (new_def) {
|
||||
var redef = new_def.redefined();
|
||||
@@ -342,12 +348,12 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
|
||||
}
|
||||
old_def.defun = new_def.scope;
|
||||
old_def.forEach(function(node) {
|
||||
node.redef = true;
|
||||
node.redef = old_def;
|
||||
node.thedef = new_def;
|
||||
node.reference(options);
|
||||
});
|
||||
if (old_def.lambda) new_def.lambda = true;
|
||||
if (new_def.undeclared) self.variables.set(name, new_def);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -387,6 +393,9 @@ AST_Scope.DEFMETHOD("init_vars", function(parent_scope) {
|
||||
AST_Arrow.DEFMETHOD("init_vars", function(parent_scope) {
|
||||
init_scope_vars(this, parent_scope);
|
||||
});
|
||||
AST_AsyncArrow.DEFMETHOD("init_vars", function(parent_scope) {
|
||||
init_scope_vars(this, parent_scope);
|
||||
});
|
||||
AST_Lambda.DEFMETHOD("init_vars", function(parent_scope) {
|
||||
init_scope_vars(this, parent_scope);
|
||||
this.uses_arguments = false;
|
||||
@@ -512,6 +521,7 @@ function _default_mangler_options(options) {
|
||||
keep_fnames : false,
|
||||
reserved : [],
|
||||
toplevel : false,
|
||||
v8 : false,
|
||||
webkit : false,
|
||||
});
|
||||
if (!Array.isArray(options.reserved)) options.reserved = [];
|
||||
@@ -543,7 +553,7 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options) {
|
||||
// lname is incremented when we get to the AST_Label
|
||||
var save_nesting = lname;
|
||||
descend();
|
||||
lname = save_nesting;
|
||||
if (!options.v8 || !in_label(tw)) lname = save_nesting;
|
||||
return true;
|
||||
}
|
||||
if (node instanceof AST_BlockScope) {
|
||||
@@ -602,6 +612,7 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options) {
|
||||
if (!(sym instanceof AST_SymbolConst)) return false;
|
||||
var scope = def.scope.resolve();
|
||||
if (def.scope === scope) return false;
|
||||
if (def.scope.parent_scope.find_variable(sym.name)) return false;
|
||||
redef = scope.def_variable(sym);
|
||||
scope.to_mangle.push(redef);
|
||||
}
|
||||
@@ -616,6 +627,14 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options) {
|
||||
sym.thedef = def;
|
||||
}
|
||||
}
|
||||
|
||||
function in_label(tw) {
|
||||
var level = 0, parent;
|
||||
while (parent = tw.parent(level++)) {
|
||||
if (parent instanceof AST_Block) return parent instanceof AST_Toplevel && !options.toplevel;
|
||||
if (parent instanceof AST_LabeledStatement) return true;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
AST_Toplevel.DEFMETHOD("find_colliding_names", function(options) {
|
||||
|
||||
@@ -144,7 +144,9 @@ function SourceMap(options) {
|
||||
add(source, gen_line, gen_col, orig_line, orig_col, name);
|
||||
} : add,
|
||||
setSourceContent: sources_content ? function(source, content) {
|
||||
sources_content[source] = content;
|
||||
if (!(source in sources_content)) {
|
||||
sources_content[source] = content;
|
||||
}
|
||||
} : noop,
|
||||
toString: function() {
|
||||
return JSON.stringify({
|
||||
|
||||
@@ -126,19 +126,27 @@ TreeTransformer.prototype = new TreeWalker;
|
||||
self.name = self.name.transform(tw);
|
||||
if (self.value) self.value = self.value.transform(tw);
|
||||
});
|
||||
DEF(AST_DefaultValue, function(self, tw) {
|
||||
self.name = self.name.transform(tw);
|
||||
self.value = self.value.transform(tw);
|
||||
});
|
||||
DEF(AST_Lambda, function(self, tw) {
|
||||
if (self.name) self.name = self.name.transform(tw);
|
||||
self.argnames = do_list(self.argnames, tw);
|
||||
if (self.rest) self.rest = self.rest.transform(tw);
|
||||
self.body = do_list(self.body, tw);
|
||||
});
|
||||
DEF(AST_Arrow, function(self, tw) {
|
||||
function transform_arrow(self, tw) {
|
||||
self.argnames = do_list(self.argnames, tw);
|
||||
if (self.rest) self.rest = self.rest.transform(tw);
|
||||
if (self.value) {
|
||||
self.value = self.value.transform(tw);
|
||||
} else {
|
||||
self.body = do_list(self.body, tw);
|
||||
}
|
||||
});
|
||||
}
|
||||
DEF(AST_Arrow, transform_arrow);
|
||||
DEF(AST_AsyncArrow, transform_arrow);
|
||||
DEF(AST_Call, function(self, tw) {
|
||||
self.expression = self.expression.transform(tw);
|
||||
self.args = do_list(self.args, tw);
|
||||
@@ -176,6 +184,7 @@ TreeTransformer.prototype = new TreeWalker;
|
||||
});
|
||||
DEF(AST_DestructuredArray, function(self, tw) {
|
||||
self.elements = do_list(self.elements, tw);
|
||||
if (self.rest) self.rest = self.rest.transform(tw);
|
||||
});
|
||||
DEF(AST_DestructuredKeyVal, function(self, tw) {
|
||||
if (self.key instanceof AST_Node) self.key = self.key.transform(tw);
|
||||
@@ -183,6 +192,7 @@ TreeTransformer.prototype = new TreeWalker;
|
||||
});
|
||||
DEF(AST_DestructuredObject, function(self, tw) {
|
||||
self.properties = do_list(self.properties, tw);
|
||||
if (self.rest) self.rest = self.rest.transform(tw);
|
||||
});
|
||||
DEF(AST_Object, function(self, tw) {
|
||||
self.properties = do_list(self.properties, tw);
|
||||
|
||||
@@ -241,7 +241,7 @@ function HOP(obj, prop) {
|
||||
function first_in_statement(stack, arrow) {
|
||||
var node = stack.parent(-1);
|
||||
for (var i = 0, p; p = stack.parent(i++); node = p) {
|
||||
if (p instanceof AST_Arrow) {
|
||||
if (is_arrow(p)) {
|
||||
return arrow && p.value === node;
|
||||
} else if (p instanceof AST_Binary) {
|
||||
if (p.left === node) continue;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"description": "JavaScript parser, mangler/compressor and beautifier toolkit",
|
||||
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
|
||||
"license": "BSD-2-Clause",
|
||||
"version": "3.12.3",
|
||||
"version": "3.12.5",
|
||||
"engines": {
|
||||
"node": ">=0.8.0"
|
||||
},
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"use strict";
|
||||
|
||||
require("../tools/exit");
|
||||
require("../tools/tty");
|
||||
|
||||
var assert = require("assert");
|
||||
var child_process = require("child_process");
|
||||
|
||||
@@ -78,7 +78,7 @@ replace_index_strict: {
|
||||
]
|
||||
}
|
||||
|
||||
replace_index_keep_fargs: {
|
||||
replace_index_drop_fargs_1: {
|
||||
options = {
|
||||
arguments: true,
|
||||
evaluate: true,
|
||||
@@ -101,6 +101,13 @@ replace_index_keep_fargs: {
|
||||
var arguments;
|
||||
console.log(arguments[1], arguments["1"], arguments["foo"]);
|
||||
})("bar", 42);
|
||||
(function() {
|
||||
var arguments = {
|
||||
1: "foo",
|
||||
foo: "bar",
|
||||
};
|
||||
console.log(arguments[1], arguments["1"], arguments["foo"]);
|
||||
})("bar", 42);
|
||||
}
|
||||
expect: {
|
||||
var arguments = [];
|
||||
@@ -114,8 +121,15 @@ replace_index_keep_fargs: {
|
||||
(function(arguments) {
|
||||
console.log(arguments[1], arguments[1], arguments.foo);
|
||||
})("bar", 42);
|
||||
(function() {
|
||||
(function(argument_0, argument_1) {
|
||||
var arguments;
|
||||
console.log(argument_1, argument_1, arguments.foo);
|
||||
})("bar", 42);
|
||||
(function() {
|
||||
var arguments = {
|
||||
1: "foo",
|
||||
foo: "bar",
|
||||
};
|
||||
console.log(arguments[1], arguments[1], arguments.foo);
|
||||
})("bar", 42);
|
||||
}
|
||||
@@ -125,10 +139,11 @@ replace_index_keep_fargs: {
|
||||
"42 42 undefined",
|
||||
"a a undefined",
|
||||
"42 42 undefined",
|
||||
"foo foo bar",
|
||||
]
|
||||
}
|
||||
|
||||
replace_index_keep_fargs_strict: {
|
||||
replace_index_drop_fargs_2: {
|
||||
options = {
|
||||
arguments: true,
|
||||
evaluate: true,
|
||||
@@ -412,7 +427,7 @@ issue_3273_global_strict_reduce_vars: {
|
||||
]
|
||||
}
|
||||
|
||||
issue_3273_keep_fargs_false: {
|
||||
issue_3273_drop_fargs_1: {
|
||||
options = {
|
||||
arguments: true,
|
||||
keep_fargs: false,
|
||||
@@ -435,10 +450,10 @@ issue_3273_keep_fargs_false: {
|
||||
expect_stdout: "1"
|
||||
}
|
||||
|
||||
issue_3273_keep_fargs_strict: {
|
||||
issue_3273_drop_fargs_2: {
|
||||
options = {
|
||||
arguments: true,
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
reduce_vars: true,
|
||||
}
|
||||
input: {
|
||||
@@ -633,7 +648,7 @@ issue_3282_2_passes: {
|
||||
issue_3420_1: {
|
||||
options = {
|
||||
arguments: true,
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
}
|
||||
input: {
|
||||
console.log(function() {
|
||||
@@ -655,7 +670,7 @@ issue_3420_1: {
|
||||
issue_3420_2: {
|
||||
options = {
|
||||
arguments: true,
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
}
|
||||
input: {
|
||||
var foo = function() {
|
||||
@@ -675,7 +690,7 @@ issue_3420_2: {
|
||||
issue_3420_3: {
|
||||
options = {
|
||||
arguments: true,
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
}
|
||||
input: {
|
||||
"use strict";
|
||||
@@ -697,7 +712,7 @@ issue_3420_3: {
|
||||
issue_3420_4: {
|
||||
options = {
|
||||
arguments: true,
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
}
|
||||
input: {
|
||||
!function() {
|
||||
@@ -722,7 +737,7 @@ issue_3420_4: {
|
||||
issue_3420_5: {
|
||||
options = {
|
||||
arguments: true,
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
}
|
||||
input: {
|
||||
"use strict";
|
||||
@@ -749,7 +764,7 @@ issue_3420_5: {
|
||||
issue_3420_6: {
|
||||
options = {
|
||||
arguments: true,
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
}
|
||||
input: {
|
||||
console.log(function() {
|
||||
@@ -767,7 +782,7 @@ issue_3420_6: {
|
||||
issue_3420_7: {
|
||||
options = {
|
||||
arguments: true,
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
}
|
||||
input: {
|
||||
"use strict";
|
||||
@@ -811,7 +826,7 @@ issue_4200: {
|
||||
issue_4291_1: {
|
||||
options = {
|
||||
arguments: true,
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
}
|
||||
input: {
|
||||
console.log(function() {
|
||||
@@ -831,7 +846,7 @@ issue_4291_1: {
|
||||
issue_4291_2: {
|
||||
options = {
|
||||
arguments: true,
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
}
|
||||
input: {
|
||||
var a = function() {
|
||||
@@ -855,7 +870,7 @@ issue_4291_2: {
|
||||
issue_4397: {
|
||||
options = {
|
||||
arguments: true,
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
}
|
||||
input: {
|
||||
console.log(typeof function() {
|
||||
|
||||
@@ -419,7 +419,7 @@ collapse_value: {
|
||||
options = {
|
||||
arrows: true,
|
||||
collapse_vars: true,
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
@@ -437,7 +437,7 @@ collapse_value: {
|
||||
reduce_iife_1: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
@@ -587,3 +587,54 @@ issue_4401: {
|
||||
]
|
||||
node_version: ">=4"
|
||||
}
|
||||
|
||||
issue_4448: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
var A;
|
||||
try {
|
||||
(arguments => {
|
||||
arguments[0];
|
||||
})(A);
|
||||
} catch (e) {
|
||||
console.log("PASS");
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var A;
|
||||
try {
|
||||
(arguments => {
|
||||
arguments[0];
|
||||
})(A);
|
||||
} catch (e) {
|
||||
console.log("PASS");
|
||||
}
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=4"
|
||||
}
|
||||
|
||||
issue_4476: {
|
||||
options = {
|
||||
arguments: true,
|
||||
}
|
||||
input: {
|
||||
(function(a, b) {
|
||||
(a => {
|
||||
console.log(arguments[0], a);
|
||||
})(b);
|
||||
})("foo", "bar");
|
||||
}
|
||||
expect: {
|
||||
(function(a, b) {
|
||||
(a => {
|
||||
console.log(arguments[0], a);
|
||||
})(b);
|
||||
})("foo", "bar");
|
||||
}
|
||||
expect_stdout: "foo bar"
|
||||
node_version: ">=4"
|
||||
}
|
||||
|
||||
@@ -461,3 +461,17 @@ issue_3949_2: {
|
||||
}
|
||||
expect_stdout: "100"
|
||||
}
|
||||
|
||||
issue_4521: {
|
||||
options = {
|
||||
assignments: true,
|
||||
dead_code: true,
|
||||
}
|
||||
input: {
|
||||
var a = (a = 42 | a) ? console.log(a) : 0;
|
||||
}
|
||||
expect: {
|
||||
var a = (a |= 42) ? console.log(a) : 0;
|
||||
}
|
||||
expect_stdout: "42"
|
||||
}
|
||||
|
||||
@@ -1,3 +1,27 @@
|
||||
async_arrow: {
|
||||
input: {
|
||||
(async a => console.log(a))("PASS");
|
||||
console.log(typeof (async () => 42)());
|
||||
}
|
||||
expect_exact: '(async a=>console.log(a))("PASS");console.log(typeof(async()=>42)());'
|
||||
expect_stdout: [
|
||||
"PASS",
|
||||
"object",
|
||||
]
|
||||
node_version: ">=8"
|
||||
}
|
||||
|
||||
async_label: {
|
||||
input: {
|
||||
(async function() {
|
||||
async: console.log("PASS");
|
||||
})();
|
||||
}
|
||||
expect_exact: '(async function(){async:console.log("PASS")})();'
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=8"
|
||||
}
|
||||
|
||||
await_await: {
|
||||
input: {
|
||||
(async function() {
|
||||
@@ -32,6 +56,54 @@ defun_name: {
|
||||
node_version: ">=8"
|
||||
}
|
||||
|
||||
drop_fname: {
|
||||
rename = true
|
||||
options = {
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
mangle = {
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
async function await() {
|
||||
console.log("PASS");
|
||||
}
|
||||
await();
|
||||
}
|
||||
expect: {
|
||||
(async function() {
|
||||
console.log("PASS");
|
||||
})();
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=8"
|
||||
}
|
||||
|
||||
keep_fname: {
|
||||
options = {
|
||||
keep_fnames: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
async function await() {
|
||||
console.log("PASS");
|
||||
}
|
||||
await();
|
||||
}
|
||||
expect: {
|
||||
async function await() {
|
||||
console.log("PASS");
|
||||
}
|
||||
await();
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=8"
|
||||
}
|
||||
|
||||
nested_await: {
|
||||
input: {
|
||||
(async function() {
|
||||
@@ -92,6 +164,215 @@ dont_inline: {
|
||||
node_version: ">=8"
|
||||
}
|
||||
|
||||
inline_await_1: {
|
||||
options = {
|
||||
awaits: true,
|
||||
inline: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
(async function() {
|
||||
async function f() {
|
||||
await 42;
|
||||
}
|
||||
return await f();
|
||||
})();
|
||||
console.log("PASS");
|
||||
}
|
||||
expect: {
|
||||
(async function() {
|
||||
return await void await 42;
|
||||
})();
|
||||
console.log("PASS");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=8"
|
||||
}
|
||||
|
||||
inline_await_1_trim: {
|
||||
options = {
|
||||
awaits: true,
|
||||
if_return: true,
|
||||
inline: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
(async function() {
|
||||
async function f() {
|
||||
await 42;
|
||||
}
|
||||
return await f();
|
||||
})();
|
||||
console.log("PASS");
|
||||
}
|
||||
expect: {
|
||||
(async function() {
|
||||
await 0;
|
||||
})();
|
||||
console.log("PASS");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=8"
|
||||
}
|
||||
|
||||
inline_await_2: {
|
||||
options = {
|
||||
awaits: true,
|
||||
inline: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
(async function() {
|
||||
async function f(a) {
|
||||
await a;
|
||||
}
|
||||
return await f(console);
|
||||
})();
|
||||
console.log("PASS");
|
||||
}
|
||||
expect: {
|
||||
(async function() {
|
||||
return await void await console;
|
||||
})();
|
||||
console.log("PASS");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=8"
|
||||
}
|
||||
|
||||
inline_await_2_trim: {
|
||||
options = {
|
||||
awaits: true,
|
||||
if_return: true,
|
||||
inline: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
(async function() {
|
||||
async function f(a) {
|
||||
await a.log;
|
||||
}
|
||||
return await f(console);
|
||||
})();
|
||||
console.log("PASS");
|
||||
}
|
||||
expect: {
|
||||
(async function() {
|
||||
await console.log;
|
||||
})();
|
||||
console.log("PASS");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=8"
|
||||
}
|
||||
|
||||
inline_await_3: {
|
||||
options = {
|
||||
awaits: true,
|
||||
inline: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
(async function() {
|
||||
async function f(a, b) {
|
||||
return await b(a);
|
||||
}
|
||||
return await f("PASS", console.log);
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
(async function() {
|
||||
return await (a = "PASS", b = console.log, await b(a));
|
||||
var a, b;
|
||||
})();
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=8"
|
||||
}
|
||||
|
||||
inline_await_3_trim: {
|
||||
options = {
|
||||
awaits: true,
|
||||
inline: true,
|
||||
reduce_vars: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
(async function() {
|
||||
async function f(a, b) {
|
||||
return await b(a);
|
||||
}
|
||||
return await f("PASS", console.log);
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
(async function() {
|
||||
return a = "PASS", b = console.log, await b(a);
|
||||
var a, b;
|
||||
})();
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=8"
|
||||
}
|
||||
|
||||
await_unary: {
|
||||
options = {
|
||||
awaits: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
var a;
|
||||
(async function() {
|
||||
a = "PASS";
|
||||
await delete a.p;
|
||||
a = "FAIL";
|
||||
})();
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
var a;
|
||||
(async function() {
|
||||
a = "PASS";
|
||||
await delete a.p;
|
||||
a = "FAIL";
|
||||
})();
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=8"
|
||||
}
|
||||
|
||||
await_void: {
|
||||
options = {
|
||||
awaits: true,
|
||||
if_return: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
(async function() {
|
||||
console.log("PASS");
|
||||
return await void 42;
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
(async function() {
|
||||
await console.log("PASS");
|
||||
})();
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=8"
|
||||
}
|
||||
|
||||
evaluate: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
@@ -353,7 +634,7 @@ property_access_expression: {
|
||||
reduce_iife_1: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
@@ -640,3 +921,77 @@ issue_4417: {
|
||||
expect_stdout: "undefined"
|
||||
node_version: ">=8"
|
||||
}
|
||||
|
||||
issue_4454_1: {
|
||||
rename = false
|
||||
options = {
|
||||
merge_vars: true,
|
||||
}
|
||||
input: {
|
||||
function f(a) {
|
||||
(async function(b = console.log(a)) {})();
|
||||
var await = 42..toString();
|
||||
console.log(await);
|
||||
}
|
||||
f("PASS");
|
||||
}
|
||||
expect: {
|
||||
function f(a) {
|
||||
(async function(b = console.log(a)) {})();
|
||||
var await = 42..toString();
|
||||
console.log(await);
|
||||
}
|
||||
f("PASS");
|
||||
}
|
||||
expect_stdout: [
|
||||
"PASS",
|
||||
"42",
|
||||
]
|
||||
node_version: ">=8"
|
||||
}
|
||||
|
||||
issue_4454_2: {
|
||||
rename = true
|
||||
options = {
|
||||
merge_vars: true,
|
||||
}
|
||||
input: {
|
||||
function f(a) {
|
||||
(async function(b = console.log(a)) {})();
|
||||
var await = 42..toString();
|
||||
console.log(await);
|
||||
}
|
||||
f("PASS");
|
||||
}
|
||||
expect: {
|
||||
function f(b) {
|
||||
(async function(c = console.log(b)) {})();
|
||||
var b = 42..toString();
|
||||
console.log(b);
|
||||
}
|
||||
f("PASS");
|
||||
}
|
||||
expect_stdout: [
|
||||
"PASS",
|
||||
"42",
|
||||
]
|
||||
node_version: ">=8"
|
||||
}
|
||||
|
||||
issue_4534: {
|
||||
options = {
|
||||
arguments: true,
|
||||
}
|
||||
input: {
|
||||
(function(await) {
|
||||
(async () => console.log(arguments[0]))();
|
||||
})("PASS");
|
||||
}
|
||||
expect: {
|
||||
(function(await) {
|
||||
(async () => console.log(arguments[0]))();
|
||||
})("PASS");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=8"
|
||||
}
|
||||
@@ -3145,8 +3145,8 @@ issue_2313_2: {
|
||||
var c = 0;
|
||||
!function a() {
|
||||
a && c++;
|
||||
var a = 0;
|
||||
a && c++;
|
||||
var a;
|
||||
(a = 0) && c++;
|
||||
}();
|
||||
console.log(c);
|
||||
}
|
||||
@@ -4273,8 +4273,8 @@ issue_2436_14: {
|
||||
var b = {};
|
||||
(function() {
|
||||
a && function(c, d) {
|
||||
console.log(c, d);
|
||||
}(b, a);
|
||||
console.log(b, d);
|
||||
}(0, a);
|
||||
})();
|
||||
}
|
||||
expect_stdout: true
|
||||
@@ -5502,8 +5502,7 @@ collapse_rhs_lhs_2: {
|
||||
expect: {
|
||||
var b = 1;
|
||||
(function f(f) {
|
||||
f = b;
|
||||
f[b] = 0;
|
||||
b[b] = 0;
|
||||
})();
|
||||
console.log("PASS");
|
||||
}
|
||||
@@ -5996,7 +5995,7 @@ issue_3215_1: {
|
||||
}());
|
||||
}
|
||||
expect: {
|
||||
console.log(typeof 42);
|
||||
console.log("number");
|
||||
}
|
||||
expect_stdout: "number"
|
||||
}
|
||||
@@ -8662,3 +8661,47 @@ issue_4430_2: {
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
collapse_and_assign: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
}
|
||||
input: {
|
||||
var log = console.log;
|
||||
var a = {
|
||||
p: "PASS",
|
||||
};
|
||||
console && (a = a.p);
|
||||
log(a);
|
||||
}
|
||||
expect: {
|
||||
var log = console.log;
|
||||
var a = {
|
||||
p: "PASS",
|
||||
};
|
||||
log(a = console ? a.p : a);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
collapse_or_assign: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
}
|
||||
input: {
|
||||
var log = console.log;
|
||||
var a = {
|
||||
p: "PASS",
|
||||
};
|
||||
a.q || (a = a.p);
|
||||
log(a);
|
||||
}
|
||||
expect: {
|
||||
var log = console.log;
|
||||
var a = {
|
||||
p: "PASS",
|
||||
};
|
||||
log(a = !a.q ? a.p : a);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
@@ -658,6 +658,30 @@ legacy_scope: {
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
hoist_vars: {
|
||||
options = {
|
||||
hoist_vars: true,
|
||||
}
|
||||
input: {
|
||||
{
|
||||
const a = "FAIL";
|
||||
var b = 42;
|
||||
}
|
||||
var a = "PASS";
|
||||
console.log(a, b);
|
||||
}
|
||||
expect: {
|
||||
var b;
|
||||
{
|
||||
const a = "FAIL";
|
||||
b = 42;
|
||||
}
|
||||
var a = "PASS";
|
||||
console.log(a, b);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
issue_4191: {
|
||||
options = {
|
||||
functions: true,
|
||||
@@ -1375,3 +1399,38 @@ issue_4365_2: {
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
issue_4527: {
|
||||
mangle = {}
|
||||
input: {
|
||||
(function() {
|
||||
try {
|
||||
throw 1;
|
||||
} catch (a) {
|
||||
try {
|
||||
const a = FAIL;
|
||||
} finally {
|
||||
if (!b)
|
||||
return console.log("aaaa");
|
||||
}
|
||||
}
|
||||
var b;
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
(function() {
|
||||
try {
|
||||
throw 1;
|
||||
} catch (a) {
|
||||
try {
|
||||
const a = FAIL;
|
||||
} finally {
|
||||
if (!t)
|
||||
return console.log("aaaa");
|
||||
}
|
||||
}
|
||||
var t;
|
||||
})();
|
||||
}
|
||||
expect_stdout: "aaaa"
|
||||
}
|
||||
|
||||
@@ -725,7 +725,7 @@ issue_2749: {
|
||||
expect: {
|
||||
var a = 2, c = "PASS";
|
||||
while (a--)
|
||||
b = void 0, b ? c = "FAIL" : b = 1;
|
||||
b = void 0, b ? c = "FAIL" : 1;
|
||||
var b;
|
||||
console.log(c);
|
||||
}
|
||||
@@ -1399,3 +1399,21 @@ issue_4366: {
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=4"
|
||||
}
|
||||
|
||||
issue_4570: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
inline: true,
|
||||
}
|
||||
input: {
|
||||
var a = function(b) {
|
||||
return a += b;
|
||||
}() ? 0 : a;
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
var a = (a += void 0) ? 0 : a;
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: "NaN"
|
||||
}
|
||||
|
||||
1598
test/compress/default-values.js
Normal file
1598
test/compress/default-values.js
Normal file
File diff suppressed because it is too large
Load Diff
@@ -40,7 +40,7 @@ redefine_arguments_2: {
|
||||
|
||||
redefine_arguments_3: {
|
||||
options = {
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
@@ -188,7 +188,7 @@ funarg_side_effects_1: {
|
||||
}
|
||||
expect: {
|
||||
try {
|
||||
(function({}) {})();
|
||||
[ {} ] = [];
|
||||
} catch (e) {
|
||||
console.log("PASS");
|
||||
}
|
||||
@@ -259,7 +259,7 @@ funarg_side_effects_3: {
|
||||
|
||||
funarg_unused_1: {
|
||||
options = {
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
@@ -318,7 +318,7 @@ funarg_unused_3: {
|
||||
|
||||
funarg_unused_4: {
|
||||
options = {
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
pure_getters: "strict",
|
||||
unused: true,
|
||||
}
|
||||
@@ -384,7 +384,7 @@ funarg_unused_6_inline: {
|
||||
|
||||
funarg_unused_6_keep_fargs: {
|
||||
options = {
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
@@ -426,7 +426,7 @@ funarg_collapse_vars_1: {
|
||||
funarg_collapse_vars_2: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
@@ -505,7 +505,7 @@ funarg_reduce_vars_1: {
|
||||
funarg_reduce_vars_2: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
pure_getters: "strict",
|
||||
reduce_vars: true,
|
||||
unsafe: true,
|
||||
@@ -682,7 +682,7 @@ funarg_inline: {
|
||||
}
|
||||
expect: {
|
||||
try {
|
||||
(function({}) {})();
|
||||
[ {} ] = [];
|
||||
} catch (e) {
|
||||
console.log("PASS");
|
||||
}
|
||||
@@ -691,6 +691,28 @@ funarg_inline: {
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
process_boolean_returns: {
|
||||
options = {
|
||||
booleans: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function({ length }) {
|
||||
return length ? "FAIL" : "PASS";
|
||||
}(function() {
|
||||
return 42;
|
||||
}));
|
||||
}
|
||||
expect: {
|
||||
console.log(function({ length }) {
|
||||
return length ? "FAIL" : "PASS";
|
||||
}(function() {
|
||||
return 42;
|
||||
}));
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
simple_const: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
@@ -1101,7 +1123,7 @@ join_vars: {
|
||||
|
||||
keep_fargs: {
|
||||
options = {
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
@@ -1336,6 +1358,24 @@ fn_name_unused: {
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
hoist_vars: {
|
||||
options = {
|
||||
hoist_vars: true,
|
||||
}
|
||||
input: {
|
||||
var a = "PASS";
|
||||
var [ b ] = [ 42 ];
|
||||
console.log(a, b);
|
||||
}
|
||||
expect: {
|
||||
var a = "PASS";
|
||||
var [ b ] = [ 42 ];
|
||||
console.log(a, b);
|
||||
}
|
||||
expect_stdout: "PASS 42"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_4280: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
@@ -1678,10 +1718,14 @@ issue_4312: {
|
||||
expect: {
|
||||
var a;
|
||||
b = "PASS",
|
||||
(function({
|
||||
[a = b]: d,
|
||||
}){})((c = "FAIL") && c);
|
||||
var b, c;
|
||||
c = "FAIL",
|
||||
[
|
||||
{
|
||||
[a = b]: d,
|
||||
},
|
||||
] = [ c && c ],
|
||||
void 0;
|
||||
var b, c, d;
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
@@ -1743,9 +1787,7 @@ issue_4319: {
|
||||
function f(a) {
|
||||
while (!a);
|
||||
}
|
||||
console.log(function({}) {
|
||||
return f(console);
|
||||
}(0));
|
||||
console.log(([ {} ] = [ 0 ], f(console)));
|
||||
}
|
||||
expect_stdout: "undefined"
|
||||
node_version: ">=6"
|
||||
@@ -1754,7 +1796,7 @@ issue_4319: {
|
||||
issue_4321: {
|
||||
options = {
|
||||
inline: true,
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
}
|
||||
input: {
|
||||
try {
|
||||
@@ -1769,11 +1811,9 @@ issue_4321: {
|
||||
}
|
||||
expect: {
|
||||
try {
|
||||
console.log(function({}) {
|
||||
return function() {
|
||||
while (!console);
|
||||
}();
|
||||
}());
|
||||
console.log(([ {} ] = [], function() {
|
||||
while (!console);
|
||||
}()));
|
||||
} catch (e) {
|
||||
console.log("PASS");
|
||||
}
|
||||
@@ -1804,11 +1844,15 @@ issue_4323: {
|
||||
}
|
||||
expect: {
|
||||
var a = 0;
|
||||
(function({
|
||||
[function a() {
|
||||
console.log(typeof a);
|
||||
}()]: d,
|
||||
}) {})(0);
|
||||
[
|
||||
{
|
||||
[function a() {
|
||||
console.log(typeof a);
|
||||
}()]: d,
|
||||
},
|
||||
] = [ 0 ],
|
||||
void 0;
|
||||
var d;
|
||||
e = 1,
|
||||
console.log,
|
||||
void e.p;
|
||||
@@ -2037,3 +2081,409 @@ issue_4425: {
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=8"
|
||||
}
|
||||
|
||||
issue_4436_Infinity: {
|
||||
options = {
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function({
|
||||
[delete Infinity]: a,
|
||||
}) {
|
||||
var Infinity;
|
||||
return a;
|
||||
}({
|
||||
true: "FAIL",
|
||||
false: "PASS",
|
||||
}));
|
||||
}
|
||||
expect: {
|
||||
console.log(function({
|
||||
[delete Infinity]: a,
|
||||
}) {
|
||||
return a;
|
||||
}({
|
||||
true: "FAIL",
|
||||
false: "PASS",
|
||||
}));
|
||||
}
|
||||
expect_stdout: true
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_4436_NaN: {
|
||||
options = {
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function({
|
||||
[delete NaN]: a,
|
||||
}) {
|
||||
var NaN;
|
||||
return a;
|
||||
}({
|
||||
true: "FAIL",
|
||||
false: "PASS",
|
||||
}));
|
||||
}
|
||||
expect: {
|
||||
console.log(function({
|
||||
[delete NaN]: a,
|
||||
}) {
|
||||
return a;
|
||||
}({
|
||||
true: "FAIL",
|
||||
false: "PASS",
|
||||
}));
|
||||
}
|
||||
expect_stdout: true
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_4436_undefined: {
|
||||
options = {
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function({
|
||||
[delete undefined]: a,
|
||||
}) {
|
||||
var undefined;
|
||||
return a;
|
||||
}({
|
||||
true: "FAIL",
|
||||
false: "PASS",
|
||||
}));
|
||||
}
|
||||
expect: {
|
||||
console.log(function({
|
||||
[delete undefined]: a,
|
||||
}) {
|
||||
return a;
|
||||
}({
|
||||
true: "FAIL",
|
||||
false: "PASS",
|
||||
}));
|
||||
}
|
||||
expect_stdout: true
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_4446: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
}
|
||||
input: {
|
||||
a = "PASS";
|
||||
var a = [ a[0] ] = [ a ];
|
||||
console.log(a[0]);
|
||||
}
|
||||
expect: {
|
||||
a = "PASS";
|
||||
var a = [ a[0] ] = [ a ];
|
||||
console.log(a[0]);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_4456: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var o = {
|
||||
set p(v) {
|
||||
console.log(v);
|
||||
},
|
||||
};
|
||||
[ function() {
|
||||
try {
|
||||
return o;
|
||||
} catch ({}) {}
|
||||
}().p ] = [ "PASS" ];
|
||||
}
|
||||
expect: {
|
||||
var o = {
|
||||
set p(v) {
|
||||
console.log(v);
|
||||
},
|
||||
};
|
||||
[ function() {
|
||||
try {
|
||||
return o;
|
||||
} catch ({}) {}
|
||||
}().p ] = [ "PASS" ];
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_4485_1: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
(function([]) {
|
||||
var arguments;
|
||||
try {
|
||||
arguments.length;
|
||||
} catch (e) {
|
||||
console.log("PASS");
|
||||
}
|
||||
})([]);
|
||||
}
|
||||
expect: {
|
||||
(function([]) {
|
||||
var arguments;
|
||||
try {
|
||||
arguments.length;
|
||||
} catch (e) {
|
||||
console.log("PASS");
|
||||
}
|
||||
})([]);
|
||||
}
|
||||
expect_stdout: true
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_4485_2: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
(function([]) {
|
||||
var arguments = null;
|
||||
try {
|
||||
arguments.length;
|
||||
} catch (e) {
|
||||
console.log("PASS");
|
||||
}
|
||||
})([]);
|
||||
}
|
||||
expect: {
|
||||
(function([]) {
|
||||
var arguments = null;
|
||||
try {
|
||||
arguments.length;
|
||||
} catch (e) {
|
||||
console.log("PASS");
|
||||
}
|
||||
})([]);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_4485_3: {
|
||||
options = {
|
||||
keep_fargs: false,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
(function([]) {
|
||||
var arguments;
|
||||
try {
|
||||
arguments.length;
|
||||
} catch (e) {
|
||||
console.log("PASS");
|
||||
}
|
||||
})([]);
|
||||
}
|
||||
expect: {
|
||||
(function([]) {
|
||||
var arguments;
|
||||
try {
|
||||
arguments.length;
|
||||
} catch (e) {
|
||||
console.log("PASS");
|
||||
}
|
||||
})([]);
|
||||
}
|
||||
expect_stdout: true
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_4500: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
keep_fnames: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = function f(b) {
|
||||
return [ b ] = [], b;
|
||||
}("FAIL");
|
||||
console.log(a || "PASS");
|
||||
}
|
||||
expect: {
|
||||
var a = function f(b) {
|
||||
return [ b ] = [], b;
|
||||
}("FAIL");
|
||||
console.log(a || "PASS");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_4504: {
|
||||
options = {
|
||||
inline: true,
|
||||
merge_vars: true,
|
||||
}
|
||||
input: {
|
||||
A = "FAIL";
|
||||
(function f(a) {
|
||||
({
|
||||
[console.log(a)]: 0[(b => console + b)(A)]
|
||||
} = 0);
|
||||
})("PASS");
|
||||
}
|
||||
expect: {
|
||||
A = "FAIL";
|
||||
(function f(a) {
|
||||
({
|
||||
[console.log(a)]: 0[b = A, console + b]
|
||||
} = 0);
|
||||
var b;
|
||||
})("PASS");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_4508: {
|
||||
options = {
|
||||
inline: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
for (var i = 0; i < 2; i++)
|
||||
(function f([ a ]) {
|
||||
var a = console.log(a) && b, b = null;
|
||||
})([ "PASS" ]);
|
||||
}
|
||||
expect: {
|
||||
for (var i = 0; i < 2; i++)
|
||||
[ [ a ] ] = [ [ "PASS" ] ],
|
||||
b = void 0,
|
||||
a = console.log(a) && b,
|
||||
b = null,
|
||||
void 0;
|
||||
var a, b;
|
||||
}
|
||||
expect_stdout: [
|
||||
"PASS",
|
||||
"PASS",
|
||||
]
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_4512: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function([ a, b = a ]) {}([]));
|
||||
}
|
||||
expect: {
|
||||
console.log(function([ a, b = a ]) {}([]));
|
||||
}
|
||||
expect_stdout: "undefined"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_4519_1: {
|
||||
options = {
|
||||
arguments: true,
|
||||
keep_fargs: false,
|
||||
}
|
||||
input: {
|
||||
try {
|
||||
(function() {
|
||||
var [ arguments ] = [];
|
||||
arguments[0];
|
||||
})();
|
||||
} catch (e) {
|
||||
console.log("PASS");
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
try {
|
||||
(function() {
|
||||
var [ arguments ] = [];
|
||||
arguments[0];
|
||||
})();
|
||||
} catch (e) {
|
||||
console.log("PASS");
|
||||
}
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_4519_2: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
try {
|
||||
(function() {
|
||||
var [ arguments ] = [];
|
||||
arguments[0];
|
||||
})();
|
||||
} catch (e) {
|
||||
console.log("PASS");
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
try {
|
||||
(function() {
|
||||
var [ arguments ] = [];
|
||||
arguments[0];
|
||||
})();
|
||||
} catch (e) {
|
||||
console.log("PASS");
|
||||
}
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_4554: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
A = "PASS";
|
||||
var a = "FAIL";
|
||||
try {
|
||||
(function({}, b) {
|
||||
return b;
|
||||
})(void 0, a = A);
|
||||
} catch (e) {
|
||||
console.log(a);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
A = "PASS";
|
||||
var a = "FAIL";
|
||||
try {
|
||||
(function({}, b) {
|
||||
return b;
|
||||
})(void 0, a = A);
|
||||
} catch (e) {
|
||||
console.log(a);
|
||||
}
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
@@ -4,15 +4,16 @@ unused_funarg_1: {
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f(a, b, c, d, e) {
|
||||
console.log(function f(a, b, c, d, e) {
|
||||
return a + b;
|
||||
}
|
||||
}(14, 28));
|
||||
}
|
||||
expect: {
|
||||
function f(a, b) {
|
||||
console.log(function(a, b) {
|
||||
return a + b;
|
||||
}
|
||||
}(14, 28));
|
||||
}
|
||||
expect_stdout: "42"
|
||||
}
|
||||
|
||||
unused_funarg_2: {
|
||||
@@ -21,15 +22,16 @@ unused_funarg_2: {
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f(a, b, c, d, e) {
|
||||
console.log(function f(a, b, c, d, e) {
|
||||
return a + c;
|
||||
}
|
||||
}(14, 21, 28));
|
||||
}
|
||||
expect: {
|
||||
function f(a, b, c) {
|
||||
console.log(function(a, c) {
|
||||
return a + c;
|
||||
}
|
||||
}(14, 28));
|
||||
}
|
||||
expect_stdout: "42"
|
||||
}
|
||||
|
||||
unused_nested_function: {
|
||||
@@ -357,37 +359,6 @@ drop_toplevel_vars: {
|
||||
}
|
||||
}
|
||||
|
||||
drop_toplevel_vars_fargs: {
|
||||
options = {
|
||||
keep_fargs: false,
|
||||
toplevel: "vars",
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a, b = 1, c = g;
|
||||
function f(d) {
|
||||
return function() {
|
||||
c = 2;
|
||||
};
|
||||
}
|
||||
a = 2;
|
||||
function g() {}
|
||||
function h() {}
|
||||
console.log(b = 3);
|
||||
}
|
||||
expect: {
|
||||
function f() {
|
||||
return function() {
|
||||
2;
|
||||
};
|
||||
}
|
||||
2;
|
||||
function g() {}
|
||||
function h() {}
|
||||
console.log(3);
|
||||
}
|
||||
}
|
||||
|
||||
drop_toplevel_all: {
|
||||
options = {
|
||||
toplevel: true,
|
||||
@@ -625,13 +596,14 @@ drop_fargs: {
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f(a) {
|
||||
console.log(function f(a) {
|
||||
var b = a;
|
||||
}
|
||||
}());
|
||||
}
|
||||
expect: {
|
||||
function f() {}
|
||||
console.log(function() {}());
|
||||
}
|
||||
expect_stdout: "undefined"
|
||||
}
|
||||
|
||||
drop_fnames: {
|
||||
@@ -2027,7 +1999,7 @@ issue_3192_1: {
|
||||
|
||||
issue_3192_2: {
|
||||
options = {
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
@@ -2435,7 +2407,7 @@ issue_3673: {
|
||||
|
||||
issue_3746: {
|
||||
options = {
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
@@ -2697,8 +2669,7 @@ issue_3956: {
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
var c, d;
|
||||
c += 0,
|
||||
var d;
|
||||
console.log(NaN),
|
||||
d = 1 ^ console.log(1),
|
||||
console.log(d);
|
||||
@@ -2713,7 +2684,7 @@ issue_3956: {
|
||||
issue_3962_1: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
@@ -2731,13 +2702,13 @@ issue_3962_1: {
|
||||
}
|
||||
expect: {
|
||||
var a = 0;
|
||||
a = (function(c) {
|
||||
(function(c) {
|
||||
do {
|
||||
console;
|
||||
0..toString();
|
||||
} while (0);
|
||||
if (c) console.log("PASS");
|
||||
}(1), 0);
|
||||
})(1);
|
||||
void 0;
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
@@ -2745,7 +2716,7 @@ issue_3962_1: {
|
||||
|
||||
issue_3962_2: {
|
||||
options = {
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
@@ -2764,13 +2735,13 @@ issue_3962_2: {
|
||||
}
|
||||
expect: {
|
||||
var a = 0;
|
||||
a = (function(c) {
|
||||
(function(c) {
|
||||
do {
|
||||
console;
|
||||
0..toString();
|
||||
} while (0);
|
||||
if (c) console.log("PASS");
|
||||
}(1), 0);
|
||||
})(1);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
@@ -2827,7 +2798,9 @@ issue_4017: {
|
||||
var a = 0;
|
||||
console.log(function() {
|
||||
c &= 0;
|
||||
var c = (a++, A = a, 0);
|
||||
var c;
|
||||
a++,
|
||||
A = a;
|
||||
}());
|
||||
}
|
||||
expect_stdout: "undefined"
|
||||
@@ -2948,7 +2921,7 @@ issue_4133: {
|
||||
|
||||
issue_4144: {
|
||||
options = {
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
@@ -3153,3 +3126,125 @@ issue_4413: {
|
||||
}
|
||||
expect_stdout: "0"
|
||||
}
|
||||
|
||||
issue_4464_1: {
|
||||
options = {
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f(a) {
|
||||
var a = function() {};
|
||||
return [ arguments, a ];
|
||||
}
|
||||
console.log(typeof f()[1]);
|
||||
}
|
||||
expect: {
|
||||
function f(a) {
|
||||
a = function() {};
|
||||
return [ arguments, a ];
|
||||
}
|
||||
console.log(typeof f()[1]);
|
||||
}
|
||||
expect_stdout: "function"
|
||||
}
|
||||
|
||||
issue_4464_2: {
|
||||
options = {
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f(a) {
|
||||
var a = function() {};
|
||||
return [ arguments, a ];
|
||||
}
|
||||
console.log(typeof f(42)[0][0]);
|
||||
}
|
||||
expect: {
|
||||
function f(a) {
|
||||
a = function() {};
|
||||
return [ arguments, a ];
|
||||
}
|
||||
console.log(typeof f(42)[0][0]);
|
||||
}
|
||||
expect_stdout: "function"
|
||||
}
|
||||
|
||||
issue_4464_3: {
|
||||
options = {
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
(function a(a) {
|
||||
var a = function() {};
|
||||
return [ arguments[0], a ];
|
||||
})(42).forEach(function(b) {
|
||||
console.log(typeof b);
|
||||
});
|
||||
}
|
||||
expect: {
|
||||
(function(a) {
|
||||
a = function() {};
|
||||
return [ arguments[0], a ];
|
||||
})(42).forEach(function(b) {
|
||||
console.log(typeof b);
|
||||
});
|
||||
}
|
||||
expect_stdout: [
|
||||
"function",
|
||||
"function",
|
||||
]
|
||||
}
|
||||
|
||||
issue_4558_1: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
pure_getters: true,
|
||||
reduce_vars: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = 0;
|
||||
var b = 1, b = c >>>= a;
|
||||
var c = 0;
|
||||
b && 0[a++],
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
var a = 0;
|
||||
var b = c >>>= a;
|
||||
var c;
|
||||
b && a++,
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: "0"
|
||||
}
|
||||
|
||||
issue_4558_2: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
ie8: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
(function() {
|
||||
var a = 1;
|
||||
var b = (a = NaN) || (console.log("PASS"), 2);
|
||||
return a;
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
(function() {
|
||||
var a;
|
||||
(a = NaN) || console.log("PASS");
|
||||
return a;
|
||||
})();
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
@@ -3117,3 +3117,61 @@ issue_4422: {
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_4480: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = function f(b) {
|
||||
b = "FAIL";
|
||||
arguments[0] = "PASS";
|
||||
var arguments = 0;
|
||||
console.log(b);
|
||||
}(a);
|
||||
}
|
||||
expect: {
|
||||
var a = function(b) {
|
||||
b = "FAIL";
|
||||
arguments[0] = "PASS";
|
||||
var arguments = 0;
|
||||
console.log(b);
|
||||
}(a);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_4552: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
keep_fnames: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = function f(b) {
|
||||
return function() {
|
||||
b++;
|
||||
try {
|
||||
return b;
|
||||
} catch (e) {}
|
||||
}();
|
||||
}();
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
var a = function f(b) {
|
||||
return function() {
|
||||
b++;
|
||||
try {
|
||||
return b;
|
||||
} catch (e) {}
|
||||
}();
|
||||
}();
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: "NaN"
|
||||
}
|
||||
|
||||
@@ -229,7 +229,7 @@ issue_203: {
|
||||
}
|
||||
expect: {
|
||||
var m = {};
|
||||
var fn = Function("n,o", "o.exports=42");
|
||||
var fn = Function("n,o,t", "o.exports=42");
|
||||
fn(null, m, m.exports);
|
||||
console.log(m.exports);
|
||||
}
|
||||
@@ -2175,7 +2175,7 @@ issue_3016_3: {
|
||||
expect: {
|
||||
var b = 1;
|
||||
do {
|
||||
console.log((a = void 0, a ? "FAIL" : a = "PASS"));
|
||||
console.log((a = void 0, a ? "FAIL" : "PASS"));
|
||||
} while (b--);
|
||||
var a;
|
||||
}
|
||||
@@ -2208,7 +2208,7 @@ issue_3016_3_ie8: {
|
||||
expect: {
|
||||
var b = 1;
|
||||
do {
|
||||
console.log((a = void 0, a ? "FAIL" : a = "PASS"));
|
||||
console.log((a = void 0, a ? "FAIL" : "PASS"));
|
||||
} while (b--);
|
||||
var a;
|
||||
}
|
||||
@@ -4230,7 +4230,7 @@ substitute: {
|
||||
substitute_add_farg: {
|
||||
options = {
|
||||
inline: true,
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
}
|
||||
input: {
|
||||
function f(g) {
|
||||
@@ -4411,7 +4411,9 @@ substitute_drop_farg: {
|
||||
return f;
|
||||
},
|
||||
function() {
|
||||
return f;
|
||||
return function(d, e) {
|
||||
return f(d, e);
|
||||
};
|
||||
},
|
||||
].forEach(function(g) {
|
||||
console.log(g()(o), g().call(o, o));
|
||||
@@ -4594,7 +4596,7 @@ substitute_use_strict: {
|
||||
issue_3833: {
|
||||
options = {
|
||||
inline: true,
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
@@ -4751,7 +4753,7 @@ issue_4006: {
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
reduce_vars: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
@@ -5132,8 +5134,8 @@ issue_4259: {
|
||||
console.log(typeof a);
|
||||
}
|
||||
expect: {
|
||||
function a() {
|
||||
for (a in a);
|
||||
var a = function b() {
|
||||
for (b in b);
|
||||
}
|
||||
a();
|
||||
console.log(typeof a);
|
||||
@@ -5223,3 +5225,61 @@ trailing_comma: {
|
||||
expect_exact: 'new function(a,b){console.log(b,a)}(42,"PASS");'
|
||||
expect_stdout: "PASS 42"
|
||||
}
|
||||
|
||||
issue_4451: {
|
||||
options = {
|
||||
functions: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = function f() {
|
||||
for (f in "foo")
|
||||
return f;
|
||||
};
|
||||
while (console.log(typeof a()));
|
||||
}
|
||||
expect: {
|
||||
var a = function f() {
|
||||
for (f in "foo")
|
||||
return f;
|
||||
};
|
||||
while (console.log(typeof a()));
|
||||
}
|
||||
expect_stdout: "function"
|
||||
}
|
||||
|
||||
issue_4471: {
|
||||
options = {
|
||||
inline: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
f(f());
|
||||
function f() {
|
||||
return g();
|
||||
}
|
||||
function g() {
|
||||
{
|
||||
console.log("PASS");
|
||||
}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
f(g());
|
||||
function f() {
|
||||
return g();
|
||||
}
|
||||
function g() {
|
||||
console.log("PASS");
|
||||
}
|
||||
}
|
||||
expect_stdout: [
|
||||
"PASS",
|
||||
"PASS",
|
||||
]
|
||||
}
|
||||
|
||||
@@ -89,6 +89,31 @@ sequences_funs: {
|
||||
}
|
||||
}
|
||||
|
||||
catch_var: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
hoist_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = "PASS";
|
||||
try {
|
||||
a;
|
||||
} catch (a) {
|
||||
var a = 0;
|
||||
a;
|
||||
}
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
var a = "PASS";
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_2295: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
@@ -109,3 +134,76 @@ issue_2295: {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
issue_4487: {
|
||||
options = {
|
||||
functions: true,
|
||||
hoist_vars: true,
|
||||
keep_fnames: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = function f() {
|
||||
var f = console.log(typeof f);
|
||||
};
|
||||
var b = a();
|
||||
}
|
||||
expect: {
|
||||
function a() {
|
||||
var a = console.log(typeof a);
|
||||
}
|
||||
a();
|
||||
}
|
||||
expect_stdout: "undefined"
|
||||
}
|
||||
|
||||
issue_4489: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
evaluate: true,
|
||||
hoist_vars: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
A = 0;
|
||||
var o = !0 || null;
|
||||
for (var k in o);
|
||||
console.log(k);
|
||||
}
|
||||
expect: {
|
||||
!(A = 0);
|
||||
for (var k in true);
|
||||
console.log(k);
|
||||
}
|
||||
expect_stdout: "undefined"
|
||||
}
|
||||
|
||||
issue_4517: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
hoist_vars: true,
|
||||
join_vars: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function() {
|
||||
var a = 2;
|
||||
A = a;
|
||||
var b = typeof !1;
|
||||
return A + b;
|
||||
}());
|
||||
}
|
||||
expect: {
|
||||
console.log(function() {
|
||||
var a = 2;
|
||||
A = a;
|
||||
return A + typeof !1;
|
||||
}());
|
||||
}
|
||||
expect_stdout: "2boolean"
|
||||
}
|
||||
|
||||
@@ -2900,3 +2900,22 @@ issue_4250: {
|
||||
}
|
||||
expect_stdout: "0"
|
||||
}
|
||||
|
||||
issue_4568: {
|
||||
options = {
|
||||
ie8: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
console.log(typeof f, function(a) {
|
||||
return a.length;
|
||||
}([ function f() {} ]));
|
||||
}
|
||||
expect: {
|
||||
console.log(typeof f, function(a) {
|
||||
return a.length;
|
||||
}([ function f() {} ]));
|
||||
}
|
||||
expect_stdout: "undefined 1"
|
||||
}
|
||||
|
||||
@@ -63,42 +63,81 @@ eval_unused: {
|
||||
unused: true,
|
||||
}
|
||||
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');
|
||||
function o(k) {
|
||||
return { c: 14 }[k];
|
||||
}
|
||||
console.log(function f1(a, eval, c, d, e) {
|
||||
return a("c") + eval;
|
||||
}(o, 28, true));
|
||||
console.log(function f2(a, b, c, d, e) {
|
||||
return a + eval("c");
|
||||
}(14, true, 28));
|
||||
console.log(function f3(a, eval, c, d, e) {
|
||||
return a + eval("c");
|
||||
}(28, o, true));
|
||||
}
|
||||
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');
|
||||
function o(k) {
|
||||
return { c: 14 }[k];
|
||||
}
|
||||
console.log(function(a, eval) {
|
||||
return a("c") + eval;
|
||||
}(o, 28));
|
||||
console.log(function f2(a, b, c, d, e) {
|
||||
return a + eval("c");
|
||||
}(14, true, 28));
|
||||
console.log(function f3(a, eval, c, d, e) {
|
||||
return a + eval("c");
|
||||
}(28, o, true));
|
||||
}
|
||||
expect_stdout: [
|
||||
"42",
|
||||
"42",
|
||||
"42",
|
||||
]
|
||||
}
|
||||
|
||||
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');
|
||||
}
|
||||
mangle = {}
|
||||
beautify = {
|
||||
beautify: true,
|
||||
}
|
||||
expect_exact: 'function f1(n,c,e,a,f){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")}'
|
||||
input: {
|
||||
function o(k) {
|
||||
return { cc: 14 }[k + "c"];
|
||||
}
|
||||
console.log(function f1(a, eval, c, d, e) {
|
||||
return a("c") + eval;
|
||||
}(o, 28, true));
|
||||
console.log(function f2(a, b, c, d, e) {
|
||||
return a + eval("c");
|
||||
}(14, true, 28));
|
||||
console.log(function f3(a, eval, c, d, e) {
|
||||
return a + eval("c");
|
||||
}(28, o, true));
|
||||
}
|
||||
expect_exact: [
|
||||
"function o(o) {",
|
||||
" return {",
|
||||
" cc: 14",
|
||||
' }[o + "c"];',
|
||||
"}",
|
||||
"",
|
||||
"console.log(function o(c, e, n, r, t) {",
|
||||
' return c("c") + e;',
|
||||
"}(o, 28, true));",
|
||||
"",
|
||||
"console.log(function f2(a, b, c, d, e) {",
|
||||
' return a + eval("c");',
|
||||
"}(14, true, 28));",
|
||||
"",
|
||||
"console.log(function f3(a, eval, c, d, e) {",
|
||||
' return a + eval("c");',
|
||||
"}(28, o, true));",
|
||||
]
|
||||
expect_stdout: [
|
||||
"42",
|
||||
"42",
|
||||
"42",
|
||||
]
|
||||
}
|
||||
|
||||
@@ -790,7 +790,7 @@ issue_3795: {
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
join_vars: true,
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
loops: true,
|
||||
passes: 2,
|
||||
reduce_vars: true,
|
||||
|
||||
@@ -18,43 +18,6 @@ keep_fargs_false: {
|
||||
function j(e) {}
|
||||
console.log(h(), i().length, j.length);
|
||||
}
|
||||
expect: {
|
||||
console.log(function f() {
|
||||
return f.length;
|
||||
}(), function g() {
|
||||
return g;
|
||||
}().length);
|
||||
function h() {
|
||||
return h.length;
|
||||
}
|
||||
function i() {
|
||||
return i;
|
||||
}
|
||||
function j() {}
|
||||
console.log(h(), i().length, j.length);
|
||||
}
|
||||
}
|
||||
|
||||
keep_fargs_strict: {
|
||||
options = {
|
||||
keep_fargs: "strict",
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function f(a) {
|
||||
return f.length;
|
||||
}(), function g(b) {
|
||||
return g;
|
||||
}().length);
|
||||
function h(c) {
|
||||
return h.length;
|
||||
}
|
||||
function i(d) {
|
||||
return i;
|
||||
}
|
||||
function j(e) {}
|
||||
console.log(h(), i().length, j.length);
|
||||
}
|
||||
expect: {
|
||||
console.log(function f(a) {
|
||||
return f.length;
|
||||
@@ -117,61 +80,11 @@ keep_fargs_true: {
|
||||
]
|
||||
}
|
||||
|
||||
replace_index: {
|
||||
options = {
|
||||
arguments: true,
|
||||
evaluate: true,
|
||||
keep_fargs: "strict",
|
||||
properties: true,
|
||||
}
|
||||
input: {
|
||||
var arguments = [];
|
||||
console.log(arguments[0]);
|
||||
(function() {
|
||||
console.log(arguments[1], arguments["1"], arguments["foo"]);
|
||||
})("bar", 42);
|
||||
(function(a, b) {
|
||||
console.log(arguments[1], arguments["1"], arguments["foo"]);
|
||||
})("bar", 42);
|
||||
(function(arguments) {
|
||||
console.log(arguments[1], arguments["1"], arguments["foo"]);
|
||||
})("bar", 42);
|
||||
(function() {
|
||||
var arguments;
|
||||
console.log(arguments[1], arguments["1"], arguments["foo"]);
|
||||
})("bar", 42);
|
||||
}
|
||||
expect: {
|
||||
var arguments = [];
|
||||
console.log(arguments[0]);
|
||||
(function(argument_0, argument_1) {
|
||||
console.log(argument_1, argument_1, arguments.foo);
|
||||
})("bar", 42);
|
||||
(function(a, b) {
|
||||
console.log(b, b, arguments.foo);
|
||||
})("bar", 42);
|
||||
(function(arguments) {
|
||||
console.log(arguments[1], arguments[1], arguments.foo);
|
||||
})("bar", 42);
|
||||
(function() {
|
||||
var arguments;
|
||||
console.log(arguments[1], arguments[1], arguments.foo);
|
||||
})("bar", 42);
|
||||
}
|
||||
expect_stdout: [
|
||||
"undefined",
|
||||
"42 42 undefined",
|
||||
"42 42 undefined",
|
||||
"a a undefined",
|
||||
"42 42 undefined",
|
||||
]
|
||||
}
|
||||
|
||||
replace_index_strict: {
|
||||
options = {
|
||||
arguments: true,
|
||||
evaluate: true,
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
properties: true,
|
||||
reduce_vars: true,
|
||||
}
|
||||
@@ -202,7 +115,7 @@ replace_index_strict: {
|
||||
issue_1858: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
pure_getters: true,
|
||||
unused: true,
|
||||
}
|
||||
@@ -224,7 +137,7 @@ issue_1858: {
|
||||
issue_2187_2: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
@@ -245,7 +158,7 @@ issue_2187_2: {
|
||||
issue_2203_2: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
@@ -280,7 +193,7 @@ issue_2203_2: {
|
||||
issue_2298: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
passes: 2,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
@@ -323,7 +236,7 @@ issue_2298: {
|
||||
issue_2319_1: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
@@ -346,7 +259,7 @@ issue_2319_1: {
|
||||
issue_2319_2: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
@@ -371,7 +284,7 @@ issue_2319_2: {
|
||||
issue_2319_3: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
@@ -396,7 +309,7 @@ issue_2319_3: {
|
||||
issue_2425_1: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
@@ -419,7 +332,7 @@ issue_2425_1: {
|
||||
issue_2425_2: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
@@ -442,7 +355,7 @@ issue_2425_2: {
|
||||
issue_2425_3: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
@@ -465,7 +378,7 @@ issue_2425_3: {
|
||||
issue_2436_13: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
passes: 2,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
@@ -499,7 +412,7 @@ issue_2436_13: {
|
||||
issue_2506: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
passes: 2,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
@@ -538,7 +451,7 @@ issue_2506: {
|
||||
|
||||
issue_2226_1: {
|
||||
options = {
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
@@ -585,7 +498,7 @@ issue_2226_1: {
|
||||
issue_2226_2: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
@@ -607,7 +520,7 @@ issue_2226_2: {
|
||||
issue_2226_3: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
@@ -627,7 +540,7 @@ issue_2226_3: {
|
||||
|
||||
issue_3192: {
|
||||
options = {
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
@@ -657,7 +570,7 @@ issue_3192: {
|
||||
if_increment: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
@@ -679,7 +592,7 @@ if_increment: {
|
||||
try_increment: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
@@ -703,7 +616,7 @@ try_increment: {
|
||||
issue_2630_3: {
|
||||
options = {
|
||||
inline: true,
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
@@ -740,7 +653,7 @@ issue_2630_3: {
|
||||
issue_3364: {
|
||||
options = {
|
||||
functions: true,
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
@@ -805,7 +718,7 @@ issue_3364: {
|
||||
|
||||
defun_label: {
|
||||
options = {
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
passes: 2,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
@@ -837,7 +750,7 @@ defun_label: {
|
||||
|
||||
iife_func_side_effects: {
|
||||
options = {
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
@@ -889,7 +802,7 @@ iife_func_side_effects: {
|
||||
issue_1595_1: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
@@ -909,7 +822,7 @@ issue_1595_1: {
|
||||
issue_1595_2: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
@@ -929,7 +842,7 @@ issue_1595_2: {
|
||||
issue_1595_3: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
passes: 2,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
@@ -950,7 +863,7 @@ issue_1595_3: {
|
||||
issue_1595_4: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
@@ -972,7 +885,7 @@ issue_1595_4: {
|
||||
|
||||
duplicate_lambda_defun_name_1: {
|
||||
options = {
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
reduce_vars: true,
|
||||
}
|
||||
input: {
|
||||
@@ -992,7 +905,7 @@ duplicate_lambda_defun_name_1: {
|
||||
|
||||
duplicate_lambda_defun_name_2: {
|
||||
options = {
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
passes: 2,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
@@ -1013,7 +926,7 @@ duplicate_lambda_defun_name_2: {
|
||||
|
||||
function_name_mangle: {
|
||||
options = {
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
keep_fnames: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
@@ -1031,7 +944,7 @@ function_name_mangle: {
|
||||
|
||||
function_name_mangle_ie8: {
|
||||
options = {
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
keep_fnames: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
@@ -1052,7 +965,7 @@ function_name_mangle_ie8: {
|
||||
|
||||
issue_3420_1: {
|
||||
options = {
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
@@ -1075,7 +988,7 @@ issue_3420_1: {
|
||||
issue_3420_2: {
|
||||
options = {
|
||||
inline: true,
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
@@ -1096,7 +1009,7 @@ issue_3420_2: {
|
||||
issue_3420_3: {
|
||||
options = {
|
||||
inline: true,
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
@@ -1118,7 +1031,7 @@ issue_3420_3: {
|
||||
|
||||
issue_3423_1: {
|
||||
options = {
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
@@ -1138,7 +1051,7 @@ issue_3423_1: {
|
||||
|
||||
issue_3423_2: {
|
||||
options = {
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
@@ -1165,7 +1078,7 @@ collapse_vars_repeated: {
|
||||
hoist_funs: true,
|
||||
if_return: true,
|
||||
join_vars: true,
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
loops: true,
|
||||
properties: true,
|
||||
reduce_funcs: true,
|
||||
@@ -1212,7 +1125,7 @@ collapse_vars_repeated: {
|
||||
chained_3: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
@@ -1236,7 +1149,7 @@ replace_all_var_scope: {
|
||||
rename = true
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
unused: true,
|
||||
}
|
||||
mangle = {}
|
||||
@@ -1265,7 +1178,7 @@ replace_all_var_scope: {
|
||||
|
||||
issue_1583: {
|
||||
options = {
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
passes: 2,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
@@ -1302,7 +1215,7 @@ issues_3267_1: {
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
reduce_vars: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
@@ -1331,7 +1244,7 @@ issues_3267_1: {
|
||||
|
||||
trailing_argument_side_effects: {
|
||||
options = {
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
@@ -1355,7 +1268,7 @@ trailing_argument_side_effects: {
|
||||
|
||||
recursive_iife_1: {
|
||||
options = {
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
@@ -1374,7 +1287,7 @@ recursive_iife_1: {
|
||||
|
||||
recursive_iife_2: {
|
||||
options = {
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
@@ -1455,7 +1368,7 @@ issue_3619: {
|
||||
|
||||
issue_4353_1: {
|
||||
options = {
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
@@ -1470,7 +1383,7 @@ issue_4353_1: {
|
||||
|
||||
issue_4353_2: {
|
||||
options = {
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
|
||||
@@ -207,3 +207,123 @@ labels_10: {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
issue_4466_1: {
|
||||
mangle = {
|
||||
v8: false,
|
||||
}
|
||||
input: {
|
||||
A: if (console.log("PASS"))
|
||||
B:;
|
||||
else
|
||||
C:;
|
||||
}
|
||||
expect: {
|
||||
e: if (console.log("PASS"))
|
||||
l:;
|
||||
else
|
||||
l:;
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=12"
|
||||
}
|
||||
|
||||
issue_4466_1_v8: {
|
||||
mangle = {
|
||||
v8: true,
|
||||
}
|
||||
input: {
|
||||
A: if (console.log("PASS"))
|
||||
B:;
|
||||
else
|
||||
C:;
|
||||
}
|
||||
expect: {
|
||||
e: if (console.log("PASS"))
|
||||
l:;
|
||||
else
|
||||
o:;
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=12"
|
||||
}
|
||||
|
||||
issue_4466_2: {
|
||||
mangle = {
|
||||
toplevel: false,
|
||||
v8: false,
|
||||
}
|
||||
input: {
|
||||
if (console.log("PASS"))
|
||||
A:;
|
||||
else
|
||||
B:;
|
||||
}
|
||||
expect: {
|
||||
if (console.log("PASS"))
|
||||
e:;
|
||||
else
|
||||
e:;
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_4466_2_v8: {
|
||||
mangle = {
|
||||
toplevel: false,
|
||||
v8: true,
|
||||
}
|
||||
input: {
|
||||
if (console.log("PASS"))
|
||||
A:;
|
||||
else
|
||||
B:;
|
||||
}
|
||||
expect: {
|
||||
if (console.log("PASS"))
|
||||
e:;
|
||||
else
|
||||
l:;
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_4466_2_toplevel: {
|
||||
mangle = {
|
||||
toplevel: true,
|
||||
v8: false,
|
||||
}
|
||||
input: {
|
||||
if (console.log("PASS"))
|
||||
A:;
|
||||
else
|
||||
B:;
|
||||
}
|
||||
expect: {
|
||||
if (console.log("PASS"))
|
||||
e:;
|
||||
else
|
||||
e:;
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_4466_2_toplevel_v8: {
|
||||
mangle = {
|
||||
toplevel: true,
|
||||
v8: true,
|
||||
}
|
||||
input: {
|
||||
if (console.log("PASS"))
|
||||
A:;
|
||||
else
|
||||
B:;
|
||||
}
|
||||
expect: {
|
||||
if (console.log("PASS"))
|
||||
e:;
|
||||
else
|
||||
e:;
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
@@ -359,6 +359,28 @@ reduce_block_2_toplevel: {
|
||||
node_version: ">=4"
|
||||
}
|
||||
|
||||
reduce_vars: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
"use strict";
|
||||
let a = "PASS";
|
||||
console.log(a);
|
||||
a = "FAIL";
|
||||
}
|
||||
expect: {
|
||||
"use strict";
|
||||
console.log("PASS");
|
||||
"FAIL";
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=4"
|
||||
}
|
||||
|
||||
hoist_props: {
|
||||
options = {
|
||||
hoist_props: true,
|
||||
@@ -1228,3 +1250,92 @@ issue_1753_toplevel: {
|
||||
expect_stdout: "0"
|
||||
node_version: ">=4"
|
||||
}
|
||||
|
||||
issue_4438: {
|
||||
options = {
|
||||
if_return: true,
|
||||
}
|
||||
input: {
|
||||
"use strict";
|
||||
function f() {
|
||||
if (console) {
|
||||
{
|
||||
let a = console.log;
|
||||
return void a("PASS");
|
||||
}
|
||||
}
|
||||
}
|
||||
f();
|
||||
}
|
||||
expect: {
|
||||
"use strict";
|
||||
function f() {
|
||||
if (!console)
|
||||
;
|
||||
else {
|
||||
let a = console.log;
|
||||
a("PASS");
|
||||
}
|
||||
}
|
||||
f();
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=4"
|
||||
}
|
||||
|
||||
issue_4531_1: {
|
||||
mangle = {
|
||||
ie8: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
"use strict";
|
||||
var a;
|
||||
console.log(function a() {
|
||||
let a;
|
||||
var b;
|
||||
}());
|
||||
}
|
||||
expect: {
|
||||
"use strict";
|
||||
var o;
|
||||
console.log(function o() {
|
||||
let o;
|
||||
var t;
|
||||
}());
|
||||
}
|
||||
expect_stdout: "undefined"
|
||||
node_version: ">=4"
|
||||
}
|
||||
|
||||
issue_4531_2: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
ie8: true,
|
||||
toplevel: true,
|
||||
}
|
||||
mangle = {
|
||||
ie8: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
"use strict";
|
||||
var a = console;
|
||||
console.log(typeof a, function a() {
|
||||
let { [console]: a } = 0 && a;
|
||||
var b = console;
|
||||
while (!b);
|
||||
}());
|
||||
}
|
||||
expect: {
|
||||
"use strict";
|
||||
var o = console;
|
||||
console.log(typeof o, function o() {
|
||||
let { [console]: o } = 0;
|
||||
var e = console;
|
||||
while (!e);
|
||||
}());
|
||||
}
|
||||
expect_stdout: "object undefined"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
@@ -1026,7 +1026,7 @@ issue_4075: {
|
||||
|
||||
issue_4082: {
|
||||
options = {
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
loops: true,
|
||||
unused: true,
|
||||
}
|
||||
@@ -1050,7 +1050,7 @@ issue_4082: {
|
||||
|
||||
issue_4084: {
|
||||
options = {
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
loops: true,
|
||||
passes: 2,
|
||||
reduce_vars: true,
|
||||
@@ -1280,3 +1280,33 @@ issue_4355: {
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_4564: {
|
||||
options = {
|
||||
loops: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
try {
|
||||
throw null;
|
||||
} catch (a) {
|
||||
var a;
|
||||
(function() {
|
||||
for (a in "foo");
|
||||
})();
|
||||
console.log(a);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
try {
|
||||
throw null;
|
||||
} catch (a) {
|
||||
var a;
|
||||
(function() {
|
||||
for (a in "foo");
|
||||
})();
|
||||
console.log(a);
|
||||
}
|
||||
}
|
||||
expect_stdout: "2"
|
||||
}
|
||||
|
||||
@@ -327,7 +327,7 @@ issue_4103: {
|
||||
|
||||
issue_4107: {
|
||||
options = {
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
merge_vars: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
|
||||
@@ -1386,3 +1386,75 @@ issue_4142: {
|
||||
}
|
||||
expect_stdout: "0"
|
||||
}
|
||||
|
||||
issue_4542_1: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe_math: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function(a) {
|
||||
return a / (1 / (a[0] = 2));
|
||||
}([ 3 ]));
|
||||
}
|
||||
expect: {
|
||||
console.log(function(a) {
|
||||
return a / (1 / (a[0] = 2));
|
||||
}([ 3 ]));
|
||||
}
|
||||
expect_stdout: "4"
|
||||
}
|
||||
|
||||
issue_4542_2: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe_math: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function(a) {
|
||||
return a / (1 / --a[0]);
|
||||
}([ 3 ]));
|
||||
}
|
||||
expect: {
|
||||
console.log(function(a) {
|
||||
return a / (1 / --a[0]);
|
||||
}([ 3 ]));
|
||||
}
|
||||
expect_stdout: "4"
|
||||
}
|
||||
|
||||
issue_4542_3: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe_math: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function(a) {
|
||||
return a / (0 / (a[0] = 0, 1));
|
||||
}([ 1 ]));
|
||||
}
|
||||
expect: {
|
||||
console.log(function(a) {
|
||||
return a / (0 / (a[0] = 0, 1));
|
||||
}([ 1 ]));
|
||||
}
|
||||
expect_stdout: "NaN"
|
||||
}
|
||||
|
||||
issue_4542_4: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe_math: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function(a) {
|
||||
return a / (1 / (a.length = 1));
|
||||
}([ 2, 3 ]));
|
||||
}
|
||||
expect: {
|
||||
console.log(function(a) {
|
||||
return a / (1 / (a.length = 1));
|
||||
}([ 2, 3 ]));
|
||||
}
|
||||
expect_stdout: "2"
|
||||
}
|
||||
|
||||
@@ -685,7 +685,7 @@ issue_3858: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
inline: true,
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
@@ -711,7 +711,7 @@ inline_pure_call_1: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
inline: true,
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
reduce_vars: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
@@ -733,7 +733,7 @@ inline_pure_call_2: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
inline: true,
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
reduce_vars: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
@@ -756,7 +756,7 @@ inline_pure_call_3: {
|
||||
collapse_vars: true,
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
passes: 2,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
|
||||
@@ -1208,3 +1208,32 @@ issue_3427: {
|
||||
expect: {}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
issue_4440: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
try {
|
||||
(function() {
|
||||
arguments = null;
|
||||
console.log(arguments.p = "FAIL");
|
||||
})();
|
||||
} catch (e) {
|
||||
console.log("PASS");
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
try {
|
||||
(function() {
|
||||
arguments = null;
|
||||
console.log(arguments.p = "FAIL");
|
||||
})();
|
||||
} catch (e) {
|
||||
console.log("PASS");
|
||||
}
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
@@ -2373,7 +2373,7 @@ redefine_farg_1: {
|
||||
function f(a) {
|
||||
return typeof a;
|
||||
}
|
||||
function g() {
|
||||
function g(a) {
|
||||
return "number";
|
||||
}
|
||||
function h(a, b) {
|
||||
@@ -6928,7 +6928,7 @@ issue_3622: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
reduce_vars: true,
|
||||
sequences: true,
|
||||
toplevel: true,
|
||||
@@ -7196,7 +7196,7 @@ issue_3894: {
|
||||
issue_3922: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
pure_getters: "strict",
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
@@ -7601,3 +7601,32 @@ issue_4188_2: {
|
||||
}
|
||||
expect_stdout: "number undefined"
|
||||
}
|
||||
|
||||
issue_4568: {
|
||||
options = {
|
||||
booleans: true,
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
loops: true,
|
||||
passes: 2,
|
||||
reduce_vars: true,
|
||||
sequences: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
(function(a) {
|
||||
a && console.log("FAIL");
|
||||
if (1)
|
||||
do {
|
||||
if (!console.log("PASS")) break;
|
||||
} while (1);
|
||||
})(!(0 !== delete NaN));
|
||||
}
|
||||
expect: {
|
||||
(function(a) {
|
||||
for (a && console.log("FAIL"), 1; console.log("PASS"); ) 1;
|
||||
})(!(0 !== delete NaN));
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
665
test/compress/rests.js
Normal file
665
test/compress/rests.js
Normal file
@@ -0,0 +1,665 @@
|
||||
arrow_1: {
|
||||
input: {
|
||||
console.log.apply(console, ((...a) => a)("PASS", 42));
|
||||
}
|
||||
expect_exact: 'console.log.apply(console,((...a)=>a)("PASS",42));'
|
||||
expect_stdout: "PASS 42"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
arrow_2: {
|
||||
input: {
|
||||
console.log.apply(console, ((a, ...b) => b)("FAIL", "PASS", 42));
|
||||
}
|
||||
expect_exact: 'console.log.apply(console,((a,...b)=>b)("FAIL","PASS",42));'
|
||||
expect_stdout: "PASS 42"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
arrow_destructured_array_1: {
|
||||
input: {
|
||||
console.log.apply(console, (([ ...a ]) => a)("PASS"));
|
||||
}
|
||||
expect_exact: 'console.log.apply(console,(([...a])=>a)("PASS"));'
|
||||
expect_stdout: "P A S S"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
arrow_destructured_array_2: {
|
||||
input: {
|
||||
console.log.apply(console, (([ a, ...b ]) => b)([ "FAIL", "PASS", 42 ]));
|
||||
}
|
||||
expect_exact: 'console.log.apply(console,(([a,...b])=>b)(["FAIL","PASS",42]));'
|
||||
expect_stdout: "PASS 42"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
arrow_destructured_array_3: {
|
||||
input: {
|
||||
console.log((([ [ ...a ] = "FAIL" ]) => a)([ "PASS" ]).join("|"));
|
||||
}
|
||||
expect_exact: 'console.log((([[...a]="FAIL"])=>a)(["PASS"]).join("|"));'
|
||||
expect_stdout: "P|A|S|S"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
arrow_destructured_object_1: {
|
||||
input: {
|
||||
var f = ({ ...a }) => a, o = f({ PASS: 42 });
|
||||
for (var k in o)
|
||||
console.log(k, o[k]);
|
||||
}
|
||||
expect_exact: "var f=({...a})=>a,o=f({PASS:42});for(var k in o)console.log(k,o[k]);"
|
||||
expect_stdout: "PASS 42"
|
||||
node_version: ">=8"
|
||||
}
|
||||
|
||||
arrow_destructured_object_2: {
|
||||
input: {
|
||||
var f = ({ FAIL: a, ...b }) => b, o = f({ PASS: 42, FAIL: null });
|
||||
for (var k in o)
|
||||
console.log(k, o[k]);
|
||||
}
|
||||
expect_exact: "var f=({FAIL:a,...b})=>b,o=f({PASS:42,FAIL:null});for(var k in o)console.log(k,o[k]);"
|
||||
expect_stdout: "PASS 42"
|
||||
node_version: ">=8"
|
||||
}
|
||||
|
||||
arrow_destructured_object_3: {
|
||||
input: {
|
||||
var f = ([ { ...a } = [ "FAIL" ] ]) => a;
|
||||
var o = f([ "PASS" ]);
|
||||
for (var k in o)
|
||||
console.log(k, o[k]);
|
||||
}
|
||||
expect_exact: 'var f=([{...a}=["FAIL"]])=>a;var o=f(["PASS"]);for(var k in o)console.log(k,o[k]);'
|
||||
expect_stdout: [
|
||||
"0 P",
|
||||
"1 A",
|
||||
"2 S",
|
||||
"3 S",
|
||||
]
|
||||
node_version: ">=8"
|
||||
}
|
||||
|
||||
funarg_1: {
|
||||
input: {
|
||||
console.log.apply(console, function(...a) {
|
||||
return a;
|
||||
}("PASS", 42));
|
||||
}
|
||||
expect_exact: 'console.log.apply(console,function(...a){return a}("PASS",42));'
|
||||
expect_stdout: "PASS 42"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
funarg_2: {
|
||||
input: {
|
||||
console.log.apply(console, function(a, ...b) {
|
||||
return b;
|
||||
}("FAIL", "PASS", 42));
|
||||
}
|
||||
expect_exact: 'console.log.apply(console,function(a,...b){return b}("FAIL","PASS",42));'
|
||||
expect_stdout: "PASS 42"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
destructured_array_1: {
|
||||
input: {
|
||||
var [ ...a ] = [ "PASS", 42 ];
|
||||
console.log.apply(console, a);
|
||||
}
|
||||
expect_exact: 'var[...a]=["PASS",42];console.log.apply(console,a);'
|
||||
expect_stdout: "PASS 42"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
destructured_array_2: {
|
||||
input: {
|
||||
var [ a, ...b ] = [ "FAIL", "PASS", 42 ];
|
||||
console.log.apply(console, b);
|
||||
}
|
||||
expect_exact: 'var[a,...b]=["FAIL","PASS",42];console.log.apply(console,b);'
|
||||
expect_stdout: "PASS 42"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
destructured_object_1: {
|
||||
input: {
|
||||
var { ...a } = [ "FAIL", "PASS", 42 ];
|
||||
console.log(a[1], a[2]);
|
||||
}
|
||||
expect_exact: 'var{...a}=["FAIL","PASS",42];console.log(a[1],a[2]);'
|
||||
expect_stdout: "PASS 42"
|
||||
node_version: ">=8"
|
||||
}
|
||||
|
||||
destructured_object_2: {
|
||||
input: {
|
||||
var { 0: a, ...b } = [ "FAIL", "PASS", 42 ];
|
||||
console.log(b[1], b[2]);
|
||||
}
|
||||
expect_exact: 'var{0:a,...b}=["FAIL","PASS",42];console.log(b[1],b[2]);'
|
||||
expect_stdout: "PASS 42"
|
||||
node_version: ">=8"
|
||||
}
|
||||
|
||||
drop_fargs: {
|
||||
options = {
|
||||
keep_fargs: false,
|
||||
rests: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function(a, ...b) {
|
||||
return b[0];
|
||||
}("FAIL", "PASS"));
|
||||
}
|
||||
expect: {
|
||||
console.log(function(b) {
|
||||
return b[0];
|
||||
}([ "PASS" ]));
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
inline: {
|
||||
options = {
|
||||
inline: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function(a, ...[ b, c ]) {
|
||||
return c + b + a;
|
||||
}("SS", "A", "P"));
|
||||
}
|
||||
expect: {
|
||||
console.log(([ a, ...[ b, c ] ] = [ "SS", "A", "P" ], c + b + a));
|
||||
var a, b, c;
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
retain_var: {
|
||||
options = {
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var [ ...a ] = [ "PASS" ];
|
||||
console.log(a[0]);
|
||||
}
|
||||
expect: {
|
||||
var [ ...a ] = [ "PASS" ];
|
||||
console.log(a[0]);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
reduce_destructured_array: {
|
||||
options = {
|
||||
reduce_vars: true,
|
||||
rests: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var [ ...a ] = [ "PASS" ];
|
||||
console.log(a[0]);
|
||||
}
|
||||
expect: {
|
||||
console.log([ "PASS" ][0]);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
reduce_destructured_object: {
|
||||
options = {
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var { ...a } = [ "PASS" ];
|
||||
console.log(a[0]);
|
||||
}
|
||||
expect: {
|
||||
var { ...a } = [ "PASS" ];
|
||||
console.log(a[0]);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=8"
|
||||
}
|
||||
|
||||
retain_destructured_array: {
|
||||
options = {
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var [ a, ...b ] = [ "FAIL", "PASS", 42 ];
|
||||
console.log.apply(console, b);
|
||||
}
|
||||
expect: {
|
||||
var [ , ...b ] = [ "FAIL", "PASS", 42 ];
|
||||
console.log.apply(console, b);
|
||||
}
|
||||
expect_stdout: "PASS 42"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
retain_destructured_object_1: {
|
||||
options = {
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var { 0: a, ...b } = [ "FAIL", "PASS", 42 ];
|
||||
for (var k in b)
|
||||
console.log(k, b[k]);
|
||||
}
|
||||
expect: {
|
||||
var { 0: a, ...b } = [ "FAIL", "PASS", 42 ];
|
||||
for (var k in b)
|
||||
console.log(k, b[k]);
|
||||
}
|
||||
expect_stdout: [
|
||||
"1 PASS",
|
||||
"2 42",
|
||||
]
|
||||
node_version: ">=8"
|
||||
}
|
||||
|
||||
retain_destructured_object_2: {
|
||||
options = {
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var { foo: [ a ], ...b } = { foo: [ "FAIL" ], bar: "PASS", baz: 42 };
|
||||
for (var k in b)
|
||||
console.log(k, b[k]);
|
||||
}
|
||||
expect: {
|
||||
var { foo: [], ...b } = { foo: [ "FAIL" ], bar: "PASS", baz: 42 };
|
||||
for (var k in b)
|
||||
console.log(k, b[k]);
|
||||
}
|
||||
expect_stdout: [
|
||||
"bar PASS",
|
||||
"baz 42",
|
||||
]
|
||||
node_version: ">=8"
|
||||
}
|
||||
|
||||
retain_funarg_destructured_array_1: {
|
||||
options = {
|
||||
inline: true,
|
||||
keep_fargs: false,
|
||||
pure_getters: "strict",
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
console.log((([ ...a ]) => a)([ "PASS" ])[0]);
|
||||
}
|
||||
expect: {
|
||||
console.log((([ ...a ]) => a)([ "PASS" ])[0]);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
retain_funarg_destructured_array_2: {
|
||||
options = {
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function([ a, ...b ]) {
|
||||
return b;
|
||||
}("bar")[1]);
|
||||
}
|
||||
expect: {
|
||||
console.log(function([ , ...b ]) {
|
||||
return b;
|
||||
}("bar")[1]);
|
||||
}
|
||||
expect_stdout: "r"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
retain_funarg_destructured_object_1: {
|
||||
options = {
|
||||
inline: true,
|
||||
keep_fargs: false,
|
||||
pure_getters: "strict",
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
console.log((({ ...a }) => a)([ "PASS" ])[0]);
|
||||
}
|
||||
expect: {
|
||||
console.log((({ ...a }) => a)([ "PASS" ])[0]);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=8"
|
||||
}
|
||||
|
||||
retain_funarg_destructured_object_2: {
|
||||
options = {
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function({ p: a, ... b }) {
|
||||
return b;
|
||||
}({ p: "FAIL" }).p || "PASS");
|
||||
}
|
||||
expect: {
|
||||
console.log(function({ p: a, ... b }) {
|
||||
return b;
|
||||
}({ p: "FAIL" }).p || "PASS");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=8"
|
||||
}
|
||||
|
||||
drop_unused_call_args_1: {
|
||||
options = {
|
||||
rests: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
(function(...a) {
|
||||
console.log(a[0]);
|
||||
})(42, console.log("PASS"));
|
||||
}
|
||||
expect: {
|
||||
(function(a) {
|
||||
console.log(a[0]);
|
||||
})([ 42, console.log("PASS") ]);
|
||||
}
|
||||
expect_stdout: [
|
||||
"PASS",
|
||||
"42",
|
||||
]
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
drop_unused_call_args_2: {
|
||||
options = {
|
||||
keep_fargs: false,
|
||||
rests: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function(a, ...b) {
|
||||
return b;
|
||||
}(console).length);
|
||||
}
|
||||
expect: {
|
||||
console.log(function(b) {
|
||||
return b;
|
||||
}((console, [])).length);
|
||||
}
|
||||
expect_stdout: "0"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
merge_funarg: {
|
||||
options = {
|
||||
merge_vars: true,
|
||||
}
|
||||
input: {
|
||||
(function(...a) {
|
||||
var b = a.length;
|
||||
console.log(b);
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
(function(...b) {
|
||||
var b = b.length;
|
||||
console.log(b);
|
||||
})();
|
||||
}
|
||||
expect_stdout: "0"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
merge_funarg_destructured_array: {
|
||||
options = {
|
||||
merge_vars: true,
|
||||
}
|
||||
input: {
|
||||
(function([ ...a ]) {
|
||||
var b = a.length;
|
||||
console.log(b);
|
||||
})([]);
|
||||
}
|
||||
expect: {
|
||||
(function([ ...b ]) {
|
||||
var b = b.length;
|
||||
console.log(b);
|
||||
})([]);
|
||||
}
|
||||
expect_stdout: "0"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
merge_funarg_destructured_object: {
|
||||
options = {
|
||||
merge_vars: true,
|
||||
}
|
||||
input: {
|
||||
(function({ ...a }) {
|
||||
var b = a[0];
|
||||
console.log(b);
|
||||
})([ "PASS" ]);
|
||||
}
|
||||
expect: {
|
||||
(function({ ...b }) {
|
||||
var b = b[0];
|
||||
console.log(b);
|
||||
})([ "PASS" ]);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=8"
|
||||
}
|
||||
|
||||
keep_arguments: {
|
||||
options = {
|
||||
arguments: true,
|
||||
keep_fargs: false,
|
||||
}
|
||||
input: {
|
||||
(function(...[ {} ]) {
|
||||
console.log(arguments[0]);
|
||||
})("PASS");
|
||||
}
|
||||
expect: {
|
||||
(function(...[ {} ]) {
|
||||
console.log(arguments[0]);
|
||||
})("PASS");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
drop_rest_array: {
|
||||
options = {
|
||||
rests: true,
|
||||
}
|
||||
input: {
|
||||
var [ ...[ a ]] = [ "PASS" ];
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
var [ a ] = [ "PASS" ];
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
drop_rest_arrow: {
|
||||
options = {
|
||||
arrows: true,
|
||||
keep_fargs: false,
|
||||
reduce_vars: true,
|
||||
rests: true,
|
||||
}
|
||||
input: {
|
||||
console.log(((...[ a ]) => a)("PASS"));
|
||||
}
|
||||
expect: {
|
||||
console.log((a => a)("PASS"));
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
drop_rest_lambda: {
|
||||
options = {
|
||||
keep_fargs: false,
|
||||
reduce_vars: true,
|
||||
rests: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
function f(...[ a ]) {
|
||||
return a;
|
||||
}
|
||||
console.log(f("PASS"), f(42));
|
||||
}
|
||||
expect: {
|
||||
function f(a) {
|
||||
return a;
|
||||
}
|
||||
console.log(f("PASS"), f(42));
|
||||
}
|
||||
expect_stdout: "PASS 42"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_4525_1: {
|
||||
options = {
|
||||
arguments: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function(a, ...[]) {
|
||||
a = "FAIL";
|
||||
return arguments[0];
|
||||
}("PASS"));
|
||||
}
|
||||
expect: {
|
||||
console.log(function(a, ...[]) {
|
||||
a = "FAIL";
|
||||
return arguments[0];
|
||||
}("PASS"));
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_4525_2: {
|
||||
options = {
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function(a, ...[]) {
|
||||
a = "FAIL";
|
||||
return arguments[0];
|
||||
}("PASS"));
|
||||
}
|
||||
expect: {
|
||||
console.log(function(a, ...[]) {
|
||||
a = "FAIL";
|
||||
return arguments[0];
|
||||
}("PASS"));
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_4538: {
|
||||
options = {
|
||||
rests: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
console.log(typeof function f(...a) {
|
||||
return a.p, f;
|
||||
}()());
|
||||
}
|
||||
expect: {
|
||||
console.log(typeof function f(...a) {
|
||||
return a.p, f;
|
||||
}()());
|
||||
}
|
||||
expect_stdout: "function"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_4544_1: {
|
||||
options = {
|
||||
keep_fnames: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
try {
|
||||
(function f(...[ {} ]) {})();
|
||||
} catch (e) {
|
||||
console.log("PASS");
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
try {
|
||||
[ ...[ {} ] ] = [];
|
||||
} catch (e) {
|
||||
console.log("PASS");
|
||||
}
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_4544_2: {
|
||||
options = {
|
||||
keep_fnames: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
try {
|
||||
(function f(a, ...[ {} ]) {})([]);
|
||||
} catch (e) {
|
||||
console.log("PASS");
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
try {
|
||||
[ , ...[ {} ] ] = [ [] ];
|
||||
} catch (e) {
|
||||
console.log("PASS");
|
||||
}
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_4562: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
rests: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
console.log((([ ...[ a ] ]) => a)("foo"));
|
||||
}
|
||||
expect: {
|
||||
console.log((([ a ]) => a)("foo"));
|
||||
}
|
||||
expect_stdout: "f"
|
||||
node_version: ">=6"
|
||||
}
|
||||
@@ -436,7 +436,7 @@ trim_new: {
|
||||
|
||||
issue_4325: {
|
||||
options = {
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
passes: 2,
|
||||
pure_getters: "strict",
|
||||
reduce_vars: true,
|
||||
|
||||
@@ -85,6 +85,28 @@ collapse_vars_4: {
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
conditionals_farg: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
}
|
||||
input: {
|
||||
function log(msg) {
|
||||
console.log(msg);
|
||||
}
|
||||
var a = 42, b = [ "PASS" ], c = [ "FAIL" ];
|
||||
a ? log(...b) : log(...c);
|
||||
}
|
||||
expect: {
|
||||
function log(msg) {
|
||||
console.log(msg);
|
||||
}
|
||||
var a = 42, b = [ "PASS" ], c = [ "FAIL" ];
|
||||
log(...a ? b : c);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
dont_inline: {
|
||||
options = {
|
||||
inline: true,
|
||||
@@ -106,7 +128,7 @@ dont_inline: {
|
||||
do_inline: {
|
||||
options = {
|
||||
inline: true,
|
||||
spread: true,
|
||||
spreads: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function(a) {
|
||||
@@ -145,7 +167,7 @@ drop_empty_call_1: {
|
||||
drop_empty_call_2: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
spread: true,
|
||||
spreads: true,
|
||||
}
|
||||
input: {
|
||||
(function() {})(...[ console.log("PASS") ]);
|
||||
@@ -159,7 +181,7 @@ drop_empty_call_2: {
|
||||
|
||||
convert_hole: {
|
||||
options = {
|
||||
spread: true,
|
||||
spreads: true,
|
||||
}
|
||||
input: {
|
||||
console.log(...[ "PASS", , 42 ]);
|
||||
@@ -192,7 +214,7 @@ keep_property_access: {
|
||||
|
||||
keep_fargs: {
|
||||
options = {
|
||||
keep_fargs: "strict",
|
||||
keep_fargs: false,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
@@ -253,7 +275,7 @@ reduce_vars_2: {
|
||||
convert_setter: {
|
||||
options = {
|
||||
objects: true,
|
||||
spread: true,
|
||||
spreads: true,
|
||||
}
|
||||
input: {
|
||||
var o = {
|
||||
@@ -397,7 +419,7 @@ keep_getter_4: {
|
||||
keep_accessor: {
|
||||
options = {
|
||||
objects: true,
|
||||
spread: true,
|
||||
spreads: true,
|
||||
}
|
||||
input: {
|
||||
var o = {
|
||||
@@ -445,7 +467,7 @@ keep_accessor: {
|
||||
object_key_order_1: {
|
||||
options = {
|
||||
objects: true,
|
||||
spread: true,
|
||||
spreads: true,
|
||||
}
|
||||
input: {
|
||||
var o = {
|
||||
@@ -475,7 +497,7 @@ object_key_order_1: {
|
||||
object_key_order_2: {
|
||||
options = {
|
||||
objects: true,
|
||||
spread: true,
|
||||
spreads: true,
|
||||
}
|
||||
input: {
|
||||
var o = {
|
||||
@@ -505,7 +527,7 @@ object_key_order_2: {
|
||||
object_key_order_3: {
|
||||
options = {
|
||||
objects: true,
|
||||
spread: true,
|
||||
spreads: true,
|
||||
}
|
||||
input: {
|
||||
var o = {
|
||||
@@ -535,7 +557,7 @@ object_key_order_3: {
|
||||
object_key_order_4: {
|
||||
options = {
|
||||
objects: true,
|
||||
spread: true,
|
||||
spreads: true,
|
||||
}
|
||||
input: {
|
||||
var o = {
|
||||
@@ -565,7 +587,7 @@ object_key_order_4: {
|
||||
object_spread_array: {
|
||||
options = {
|
||||
objects: true,
|
||||
spread: true,
|
||||
spreads: true,
|
||||
}
|
||||
input: {
|
||||
var o = {
|
||||
@@ -591,7 +613,7 @@ object_spread_array: {
|
||||
object_spread_string: {
|
||||
options = {
|
||||
objects: true,
|
||||
spread: true,
|
||||
spreads: true,
|
||||
}
|
||||
input: {
|
||||
var o = {
|
||||
@@ -648,7 +670,7 @@ unused_var_side_effects: {
|
||||
issue_4329: {
|
||||
options = {
|
||||
objects: true,
|
||||
spread: true,
|
||||
spreads: true,
|
||||
}
|
||||
input: {
|
||||
console.log({
|
||||
@@ -727,7 +749,7 @@ issue_4342: {
|
||||
issue_4345: {
|
||||
options = {
|
||||
objects: true,
|
||||
spread: true,
|
||||
spreads: true,
|
||||
}
|
||||
input: {
|
||||
console.log({
|
||||
@@ -787,7 +809,7 @@ issue_4361: {
|
||||
issue_4363: {
|
||||
options = {
|
||||
objects: true,
|
||||
spread: true,
|
||||
spreads: true,
|
||||
}
|
||||
input: {
|
||||
({
|
||||
@@ -804,3 +826,95 @@ issue_4363: {
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=8"
|
||||
}
|
||||
|
||||
issue_4556: {
|
||||
options = {
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function() {
|
||||
var a = "" + [ a++ ];
|
||||
var b = [ ...a ];
|
||||
}());
|
||||
}
|
||||
expect: {
|
||||
console.log(function() {
|
||||
var a;
|
||||
}());
|
||||
}
|
||||
expect_stdout: "undefined"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_4560_1: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var a = 0;
|
||||
(function(...{
|
||||
[a++]: {},
|
||||
}) {})(2);
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
var a = 0;
|
||||
(function(...{
|
||||
[a++]: {},
|
||||
}) {})(2);
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: "1"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_4560_2: {
|
||||
options = {
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = 0;
|
||||
(function(...{
|
||||
[a++]: {},
|
||||
}) {})(2);
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
var a = 0;
|
||||
(function(...{
|
||||
[a++]: {},
|
||||
}) {})(2);
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: "1"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_4560_3: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var a = 0, b;
|
||||
[ ...{
|
||||
[a++]: b,
|
||||
} ] = [ "PASS" ];
|
||||
console.log(b);
|
||||
}
|
||||
expect: {
|
||||
var a = 0, b;
|
||||
[ ...{
|
||||
[a++]: b,
|
||||
} ] = [ "PASS" ];
|
||||
console.log(b);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=6"
|
||||
}
|
||||
3
test/input/reduce/destructured_assign.js
Normal file
3
test/input/reduce/destructured_assign.js
Normal file
@@ -0,0 +1,3 @@
|
||||
var o = {};
|
||||
[ o[1 + .1 + .1] ] = [ 42 ];
|
||||
console.log(o[1.2]);
|
||||
17
test/input/reduce/destructured_assign.reduced.js
Normal file
17
test/input/reduce/destructured_assign.reduced.js
Normal file
@@ -0,0 +1,17 @@
|
||||
// (beautified)
|
||||
var o = {};
|
||||
|
||||
[ o[1 + .1 + .1] ] = [];
|
||||
|
||||
console.log(o);
|
||||
// output: { '1.2000000000000002': undefined }
|
||||
//
|
||||
// minify: { '1.2': undefined }
|
||||
//
|
||||
// options: {
|
||||
// "compress": {
|
||||
// "unsafe_math": true
|
||||
// },
|
||||
// "mangle": false,
|
||||
// "validate": true
|
||||
// }
|
||||
@@ -1,14 +1,12 @@
|
||||
// (beautified)
|
||||
try {
|
||||
1 in 0;
|
||||
} catch ({
|
||||
message: message
|
||||
}) {
|
||||
} catch (message) {
|
||||
console.log(message);
|
||||
}
|
||||
// output: Cannot use 'in' operator to search for '1' in 0
|
||||
// output: TypeError: Cannot use 'in' operator to search for '1' in 0
|
||||
//
|
||||
// minify: Cannot use 'in' operator to search for '0' in 0
|
||||
// minify: TypeError: Cannot use 'in' operator to search for '0' in 0
|
||||
//
|
||||
// options: {
|
||||
// "mangle": false
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
(function f(a) {
|
||||
do {
|
||||
console.log(f.length);
|
||||
} while (console.log(f += 0));
|
||||
})();
|
||||
console.log(function(undefined) {
|
||||
return undefined[function() {
|
||||
{}
|
||||
}] || 1 + .1 + .1;
|
||||
}(42));
|
||||
|
||||
@@ -1,19 +1,14 @@
|
||||
// (beautified)
|
||||
(function f(a) {
|
||||
do {
|
||||
console.log(f.length);
|
||||
} while (console.log(f += 0));
|
||||
})();
|
||||
// output: 1
|
||||
// function(){}0
|
||||
console.log(function() {
|
||||
return 1 + .1 + .1;
|
||||
}());
|
||||
// output: 1.2000000000000002
|
||||
//
|
||||
// minify: 0
|
||||
// function(){}0
|
||||
// minify: 1.2
|
||||
//
|
||||
// options: {
|
||||
// "compress": {
|
||||
// "keep_fargs": false,
|
||||
// "unsafe": true
|
||||
// "unsafe_math": true
|
||||
// },
|
||||
// "mangle": false
|
||||
// }
|
||||
@@ -1,8 +1,5 @@
|
||||
console.log(function f(a) {
|
||||
({
|
||||
set p(v) {
|
||||
f++;
|
||||
}
|
||||
});
|
||||
return f.length;
|
||||
}());
|
||||
({
|
||||
set p(v) {
|
||||
console.log(+v + .1 + .1);
|
||||
}
|
||||
}).p = 1;
|
||||
|
||||
@@ -1,20 +1,16 @@
|
||||
// (beautified)
|
||||
console.log(function f(a) {
|
||||
({
|
||||
set p(v) {
|
||||
f++;
|
||||
}
|
||||
});
|
||||
return f.length;
|
||||
}());
|
||||
// output: 1
|
||||
({
|
||||
set p(v) {
|
||||
console.log(1 + .1 + .1);
|
||||
}
|
||||
}).p = 0;
|
||||
// output: 1.2000000000000002
|
||||
//
|
||||
// minify: 0
|
||||
// minify: 1.2
|
||||
//
|
||||
// options: {
|
||||
// "compress": {
|
||||
// "keep_fargs": false,
|
||||
// "unsafe": true
|
||||
// "unsafe_math": true
|
||||
// },
|
||||
// "mangle": false
|
||||
// }
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
var site = "https://browserbench.org/JetStream1.1";
|
||||
if (typeof phantom == "undefined") {
|
||||
require("../tools/exit");
|
||||
require("../tools/tty");
|
||||
var args = process.argv.slice(2);
|
||||
var debug = args.indexOf("--debug");
|
||||
if (debug < 0) {
|
||||
|
||||
40
test/mocha/bug-report.js
Normal file
40
test/mocha/bug-report.js
Normal file
@@ -0,0 +1,40 @@
|
||||
var assert = require("assert");
|
||||
var exec = require("child_process").exec;
|
||||
|
||||
describe("UGLIFY_BUG_REPORT", function() {
|
||||
var env = Object.create(process.env);
|
||||
env.UGLIFY_BUG_REPORT = 1;
|
||||
it("Should generate bug report via API", function(done) {
|
||||
exec('"' + process.argv[0] + '"', { env: env }, function(err, stdout) {
|
||||
if (err) throw err;
|
||||
assert.strictEqual(stdout, [
|
||||
"// UGLIFY_BUG_REPORT",
|
||||
"// <<undefined>>",
|
||||
"",
|
||||
"//-------------------------------------------------------------",
|
||||
"// INPUT CODE",
|
||||
"...---...",
|
||||
"",
|
||||
].join("\n"));
|
||||
done();
|
||||
}).stdin.end('console.log(require("./").minify("...---...").code);');
|
||||
});
|
||||
it("Should generate bug report via CLI", function(done) {
|
||||
exec('"' + process.argv[0] + '" bin/uglifyjs -mc', { env: env }, function(err, stdout) {
|
||||
if (err) throw err;
|
||||
assert.strictEqual(stdout, [
|
||||
"// UGLIFY_BUG_REPORT",
|
||||
"// {",
|
||||
'// "mangle": {},',
|
||||
'// "compress": {}',
|
||||
"// }",
|
||||
"",
|
||||
"//-------------------------------------------------------------",
|
||||
"// STDIN",
|
||||
"...---...",
|
||||
"",
|
||||
].join("\n"));
|
||||
done();
|
||||
}).stdin.end("...---...");
|
||||
});
|
||||
});
|
||||
@@ -3,7 +3,7 @@ var UglifyJS = require("../node");
|
||||
|
||||
describe("Getters and setters", function() {
|
||||
it("Should not accept operator symbols as getter/setter name", function() {
|
||||
var illegalOperators = [
|
||||
[
|
||||
"++",
|
||||
"--",
|
||||
"+",
|
||||
@@ -42,43 +42,26 @@ describe("Getters and setters", function() {
|
||||
"&=",
|
||||
"&&",
|
||||
"||"
|
||||
];
|
||||
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) {
|
||||
].reduce(function(tests, illegalOperator) {
|
||||
tests.push({
|
||||
code: "var obj = { get " + illegalOperator + "() { return test; }};",
|
||||
operator: illegalOperator,
|
||||
});
|
||||
tests.push({
|
||||
code: "var obj = { set " + illegalOperator + "(value) { test = value; }};",
|
||||
operator: illegalOperator,
|
||||
});
|
||||
return tests;
|
||||
}, []).forEach(function(test) {
|
||||
assert.throws(function() {
|
||||
UglifyJS.parse(test.code);
|
||||
}, test.operator == "=" ? function(e) {
|
||||
return e instanceof UglifyJS.JS_Parse_Error
|
||||
&& e.message === "Unexpected token: operator «" + 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));
|
||||
}
|
||||
&& /^Unexpected token: punc «{», expected: punc «.*?»$/.test(e.message);
|
||||
} : function(e) {
|
||||
return e instanceof UglifyJS.JS_Parse_Error
|
||||
&& e.message === "Unexpected token: operator «" + test.operator + "»";
|
||||
}, "Expected but didn't get a syntax error while parsing following line:\n" + test.code);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -89,4 +89,13 @@ describe("Number literals", function() {
|
||||
}, code);
|
||||
});
|
||||
});
|
||||
it("Should reject invalid syntax under expression=true", function() {
|
||||
assert.throws(function() {
|
||||
UglifyJS.parse("42.g", {
|
||||
expression: true,
|
||||
});
|
||||
}, function(e) {
|
||||
return e instanceof UglifyJS.JS_Parse_Error;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -37,8 +37,7 @@ describe("test/reduce.js", function() {
|
||||
it("Should retain setter arguments", function() {
|
||||
var result = reduce_test(read("test/input/reduce/setter.js"), {
|
||||
compress: {
|
||||
keep_fargs: false,
|
||||
unsafe: true,
|
||||
unsafe_math: true,
|
||||
},
|
||||
mangle: false,
|
||||
}, {
|
||||
@@ -110,28 +109,24 @@ describe("test/reduce.js", function() {
|
||||
});
|
||||
it("Should print correct output for irreducible test case", function() {
|
||||
var result = reduce_test([
|
||||
"console.log(function f(a) {",
|
||||
" return f.length;",
|
||||
"}());",
|
||||
"console.log(1 + .1 + .1);",
|
||||
].join("\n"), {
|
||||
compress: {
|
||||
keep_fargs: false,
|
||||
unsafe_math: true,
|
||||
},
|
||||
mangle: false,
|
||||
});
|
||||
if (result.error) throw result.error;
|
||||
assert.strictEqual(result.code, [
|
||||
"// (beautified)",
|
||||
"console.log(function f(a) {",
|
||||
" return f.length;",
|
||||
"}());",
|
||||
"// output: 1",
|
||||
"console.log(1 + .1 + .1);",
|
||||
"// output: 1.2000000000000002",
|
||||
"// ",
|
||||
"// minify: 0",
|
||||
"// minify: 1.2",
|
||||
"// ",
|
||||
"// options: {",
|
||||
'// "compress": {',
|
||||
'// "keep_fargs": false',
|
||||
'// "unsafe_math": true',
|
||||
"// },",
|
||||
'// "mangle": false',
|
||||
"// }",
|
||||
@@ -303,8 +298,7 @@ describe("test/reduce.js", function() {
|
||||
if (semver.satisfies(process.version, "<=0.10")) return;
|
||||
var result = reduce_test(read("test/input/reduce/diff_error.js"), {
|
||||
compress: {
|
||||
keep_fargs: false,
|
||||
unsafe: true,
|
||||
unsafe_math: true,
|
||||
},
|
||||
mangle: false,
|
||||
}, {
|
||||
@@ -313,6 +307,18 @@ describe("test/reduce.js", function() {
|
||||
if (result.error) throw result.error;
|
||||
assert.strictEqual(result.code, read("test/input/reduce/diff_error.reduced.js"));
|
||||
});
|
||||
it("Should maintain valid LHS in destructuring assignments", function() {
|
||||
if (semver.satisfies(process.version, "<6")) return;
|
||||
var result = reduce_test(read("test/input/reduce/destructured_assign.js"), {
|
||||
compress: {
|
||||
unsafe_math: true,
|
||||
},
|
||||
mangle: false,
|
||||
validate: true,
|
||||
});
|
||||
if (result.error) throw result.error;
|
||||
assert.strictEqual(result.code, read("test/input/reduce/destructured_assign.reduced.js"));
|
||||
});
|
||||
it("Should handle destructured catch expressions", function() {
|
||||
if (semver.satisfies(process.version, "<6")) return;
|
||||
var result = reduce_test(read("test/input/reduce/destructured_catch.js"), {
|
||||
|
||||
@@ -244,6 +244,39 @@ describe("sourcemaps", function() {
|
||||
assert.strictEqual(result.code, '(function(){console.log("hello")}).call(this);');
|
||||
assert.strictEqual(result.map, '{"version":3,"sources":["main.coffee"],"names":["console","log"],"mappings":"CAAA,WAAAA,QAAQC,IAAI"}');
|
||||
});
|
||||
it("Should not overwrite existing sourcesContent", function() {
|
||||
var result = UglifyJS.minify({
|
||||
"in.js": [
|
||||
'"use strict";',
|
||||
"",
|
||||
"var _window$foo = window.foo,",
|
||||
" a = _window$foo[0],",
|
||||
" b = _window$foo[1];",
|
||||
].join("\n"),
|
||||
}, {
|
||||
compress: false,
|
||||
mangle: false,
|
||||
sourceMap: {
|
||||
content: {
|
||||
version: 3,
|
||||
sources: [ "in.js" ],
|
||||
names: [
|
||||
"window",
|
||||
"foo",
|
||||
"a",
|
||||
"b",
|
||||
],
|
||||
mappings: ";;kBAAaA,MAAM,CAACC,G;IAAfC,C;IAAGC,C",
|
||||
file: "in.js",
|
||||
sourcesContent: [ "let [a, b] = window.foo;\n" ],
|
||||
},
|
||||
includeSources: true,
|
||||
},
|
||||
});
|
||||
if (result.error) throw result.error;
|
||||
assert.strictEqual(result.code, '"use strict";var _window$foo=window.foo,a=_window$foo[0],b=_window$foo[1];');
|
||||
assert.strictEqual(result.map, '{"version":3,"sources":["in.js"],"sourcesContent":["let [a, b] = window.foo;\\n"],"names":["window","foo","a","b"],"mappings":"6BAAaA,OAAOC,IAAfC,E,eAAGC,E"}');
|
||||
});
|
||||
});
|
||||
|
||||
describe("sourceMapInline", function() {
|
||||
|
||||
@@ -104,15 +104,14 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
|
||||
|
||||
// quick ignores
|
||||
if (node instanceof U.AST_Accessor) return;
|
||||
if (node instanceof U.AST_Destructured) return;
|
||||
if (node instanceof U.AST_Directive) return;
|
||||
if (!in_list && node instanceof U.AST_EmptyStatement) return;
|
||||
if (node instanceof U.AST_Label) return;
|
||||
if (node instanceof U.AST_LabelRef) return;
|
||||
if (!in_list && node instanceof U.AST_SymbolDeclaration) return;
|
||||
if (node instanceof U.AST_Toplevel) return;
|
||||
var parent = tt.parent();
|
||||
if (node instanceof U.AST_SymbolFunarg && parent instanceof U.AST_Accessor) return;
|
||||
if (!in_list && parent.rest !== node && node instanceof U.AST_SymbolDeclaration) return;
|
||||
|
||||
// ensure that the _permute prop is a number.
|
||||
// can not use `node.start._permute |= 0;` as it will erase fractional part.
|
||||
@@ -124,7 +123,7 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
|
||||
|
||||
// ignore lvalues
|
||||
if (parent instanceof U.AST_Assign && parent.left === node) return;
|
||||
if (parent instanceof U.AST_DestructuredArray) return;
|
||||
if (parent instanceof U.AST_DefaultValue && parent.name === node) return;
|
||||
if (parent instanceof U.AST_DestructuredKeyVal && parent.value === node) return;
|
||||
if (parent instanceof U.AST_Unary && parent.expression === node) switch (parent.operator) {
|
||||
case "++":
|
||||
@@ -153,6 +152,20 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
|
||||
node.left,
|
||||
node.right,
|
||||
][ permute & 1 ];
|
||||
if (expr instanceof U.AST_Destructured) expr = expr.transform(new U.TreeTransformer(function(node, descend) {
|
||||
if (node instanceof U.AST_DefaultValue) return new U.AST_Assign({
|
||||
operator: "=",
|
||||
left: node.name.transform(this),
|
||||
right: node.value,
|
||||
start: {},
|
||||
});
|
||||
if (node instanceof U.AST_DestructuredKeyVal) return new U.AST_ObjectKeyVal(node);
|
||||
if (node instanceof U.AST_Destructured) {
|
||||
node = new (node instanceof U.AST_DestructuredArray ? U.AST_Array : U.AST_Object)(node);
|
||||
descend(node, this);
|
||||
}
|
||||
return node;
|
||||
}));
|
||||
CHANGED = true;
|
||||
return permute < 2 ? expr : wrap_with_console_log(expr);
|
||||
}
|
||||
@@ -211,6 +224,28 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
|
||||
node.alternative,
|
||||
][ ((node.start._permute += step) * steps | 0) % 3 ];
|
||||
}
|
||||
else if (node instanceof U.AST_DefaultValue) {
|
||||
node.start._permute++;
|
||||
CHANGED = true;
|
||||
return node.name;
|
||||
}
|
||||
else if (node instanceof U.AST_DestructuredArray) {
|
||||
var expr = node.elements[0];
|
||||
if (expr && !(expr instanceof U.AST_Hole)) {
|
||||
node.start._permute++;
|
||||
CHANGED = true;
|
||||
return expr;
|
||||
}
|
||||
}
|
||||
else if (node instanceof U.AST_DestructuredObject) {
|
||||
// first property's value
|
||||
var expr = node.properties[0];
|
||||
if (expr) {
|
||||
node.start._permute++;
|
||||
CHANGED = true;
|
||||
return expr.value;
|
||||
}
|
||||
}
|
||||
else if (node instanceof U.AST_Defun) {
|
||||
switch (((node.start._permute += step) * steps | 0) % 2) {
|
||||
case 0:
|
||||
@@ -304,7 +339,16 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
|
||||
}
|
||||
else if (node instanceof U.AST_Object) {
|
||||
// first property's value
|
||||
var expr = node.properties[0] instanceof U.AST_ObjectKeyVal && node.properties[0].value;
|
||||
var expr = node.properties[0];
|
||||
if (expr instanceof U.AST_ObjectKeyVal) {
|
||||
expr = expr.value;
|
||||
} else if (expr instanceof U.AST_Spread) {
|
||||
expr = expr.expression;
|
||||
} else if (expr && expr.key instanceof U.AST_Node) {
|
||||
expr = expr.key;
|
||||
} else {
|
||||
expr = null;
|
||||
}
|
||||
if (expr) {
|
||||
node.start._permute++;
|
||||
CHANGED = true;
|
||||
@@ -314,7 +358,7 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
|
||||
else if (node instanceof U.AST_PropAccess) {
|
||||
var expr = [
|
||||
node.expression,
|
||||
node.property instanceof U.AST_Node && node.property,
|
||||
node.property instanceof U.AST_Node && !(parent instanceof U.AST_Destructured) && node.property,
|
||||
][ node.start._permute++ % 2 ];
|
||||
if (expr) {
|
||||
CHANGED = true;
|
||||
@@ -416,15 +460,10 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
|
||||
CHANGED = true;
|
||||
return List.skip;
|
||||
}
|
||||
|
||||
// skip element/property from (destructured) array/object
|
||||
if (parent instanceof U.AST_Array
|
||||
|| parent instanceof U.AST_Destructured
|
||||
|| parent instanceof U.AST_Object) {
|
||||
node.start._permute++;
|
||||
CHANGED = true;
|
||||
return List.skip;
|
||||
}
|
||||
} else if (parent.rest === node) {
|
||||
node.start._permute++;
|
||||
CHANGED = true;
|
||||
return null;
|
||||
}
|
||||
|
||||
// replace this node
|
||||
@@ -627,7 +666,7 @@ function has_loopcontrol(body, loop, label) {
|
||||
}
|
||||
|
||||
function is_error(result) {
|
||||
return typeof result == "object" && typeof result.name == "string" && typeof result.message == "string";
|
||||
return result && typeof result.name == "string" && typeof result.message == "string";
|
||||
}
|
||||
|
||||
function is_timed_out(result) {
|
||||
@@ -636,7 +675,10 @@ function is_timed_out(result) {
|
||||
|
||||
function is_statement(node) {
|
||||
return node instanceof U.AST_Statement
|
||||
&& !(node instanceof U.AST_Arrow || node instanceof U.AST_AsyncFunction || node instanceof U.AST_Function);
|
||||
&& !(node instanceof U.AST_Arrow
|
||||
|| node instanceof U.AST_AsyncArrow
|
||||
|| node instanceof U.AST_AsyncFunction
|
||||
|| node instanceof U.AST_Function);
|
||||
}
|
||||
|
||||
function merge_sequence(array, node) {
|
||||
|
||||
@@ -64,7 +64,7 @@ function createContext() {
|
||||
}
|
||||
}
|
||||
|
||||
exports.run_code = function(code, toplevel, timeout) {
|
||||
function run_code(code, toplevel, timeout) {
|
||||
timeout = timeout || 5000;
|
||||
var stdout = "";
|
||||
var original_write = process.stdout.write;
|
||||
@@ -79,7 +79,17 @@ exports.run_code = function(code, toplevel, timeout) {
|
||||
} finally {
|
||||
process.stdout.write = original_write;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
exports.run_code = semver.satisfies(process.version, "0.8") ? function(code, toplevel, timeout) {
|
||||
var stdout = run_code(code, toplevel, timeout);
|
||||
if (typeof stdout != "string" || !/arguments/.test(code)) return stdout;
|
||||
do {
|
||||
var prev = stdout;
|
||||
stdout = run_code(code, toplevel, timeout);
|
||||
} while (prev !== stdout);
|
||||
return stdout;
|
||||
} : run_code;
|
||||
|
||||
function strip_func_ids(text) {
|
||||
return ("" + text).replace(/F[0-9]{6}N/g, "<F<>N>");
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
// bin/uglifyjs s.js -c && bin/uglifyjs s.js -c passes=3 && bin/uglifyjs s.js -c passes=3 -m
|
||||
// cat s.js | node && node s.js && bin/uglifyjs s.js -c | node && bin/uglifyjs s.js -c passes=3 | node && bin/uglifyjs s.js -c passes=3 -m | node
|
||||
|
||||
require("../../tools/exit");
|
||||
require("../../tools/tty");
|
||||
|
||||
var UglifyJS = require("../..");
|
||||
var randomBytes = require("crypto").randomBytes;
|
||||
@@ -137,8 +137,11 @@ var SUPPORT = function(matrix) {
|
||||
catch_omit_var: "try {} catch {}",
|
||||
computed_key: "({[0]: 0});",
|
||||
const_block: "var a; { const a = 0; }",
|
||||
default_value: "[ a = 0 ] = [];",
|
||||
destructuring: "[] = [];",
|
||||
let: "let a;",
|
||||
rest: "var [...a] = [];",
|
||||
rest_object: "var {...a} = {};",
|
||||
spread: "[...[]];",
|
||||
spread_object: "({...0});",
|
||||
trailing_comma: "function f(a,) {}",
|
||||
@@ -425,18 +428,48 @@ function createArgs(recurmax, stmtDepth, canThrow) {
|
||||
function createAssignmentPairs(recurmax, stmtDepth, canThrow, nameLenBefore, was_async) {
|
||||
var avoid = [];
|
||||
var len = unique_vars.length;
|
||||
var pairs = createPairs(recurmax);
|
||||
var pairs = createPairs(recurmax, !nameLenBefore);
|
||||
pairs.has_rest = nameLenBefore && convertToRest(pairs.names);
|
||||
unique_vars.length = len;
|
||||
return pairs;
|
||||
|
||||
function createAssignmentValue(recurmax) {
|
||||
function convertToRest(names) {
|
||||
var last = names.length - 1;
|
||||
if (last >= 0 && SUPPORT.rest && rng(20) == 0) {
|
||||
var name = names[last];
|
||||
if (name && name.indexOf("=") < 0) {
|
||||
if (/^[[{]/.test(name)) name = "[ " + name + " ]";
|
||||
names[last] = "..." + name;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function fill(nameFn, valueFn) {
|
||||
var save_async = async;
|
||||
if (was_async != null) async = was_async;
|
||||
if (was_async != null) {
|
||||
async = false;
|
||||
if (save_async || was_async) addAvoidVar("await");
|
||||
}
|
||||
avoid.forEach(addAvoidVar);
|
||||
var save_vars = nameLenBefore && VAR_NAMES.splice(nameLenBefore);
|
||||
var value = nameLenBefore && rng(2) ? createValue() : createExpression(recurmax, NO_COMMA, stmtDepth, canThrow);
|
||||
if (nameFn) nameFn();
|
||||
if (was_async != null) {
|
||||
async = was_async;
|
||||
if (save_async || was_async) removeAvoidVar("await");
|
||||
}
|
||||
if (valueFn) valueFn();
|
||||
if (save_vars) [].push.apply(VAR_NAMES, save_vars);
|
||||
avoid.forEach(removeAvoidVar);
|
||||
async = save_async;
|
||||
return value;
|
||||
}
|
||||
|
||||
function createAssignmentValue(recurmax) {
|
||||
return nameLenBefore && rng(2) ? createValue() : createExpression(recurmax, NO_COMMA, stmtDepth, canThrow);
|
||||
}
|
||||
|
||||
function createDefaultValue(recurmax, noDefault) {
|
||||
return !noDefault && SUPPORT.default_value && rng(20) == 0 ? " = " + createAssignmentValue(recurmax) : "";
|
||||
}
|
||||
|
||||
function createKey(recurmax, keys) {
|
||||
@@ -459,20 +492,22 @@ function createAssignmentPairs(recurmax, stmtDepth, canThrow, nameLenBefore, was
|
||||
return name;
|
||||
}
|
||||
|
||||
function createPairs(recurmax) {
|
||||
function createPairs(recurmax, noDefault) {
|
||||
var names = [], values = [];
|
||||
var m = rng(4), n = rng(4);
|
||||
if (!nameLenBefore) m = Math.max(m, n, 1);
|
||||
for (var i = Math.max(m, n); --i >= 0;) {
|
||||
if (i < m && i < n) {
|
||||
createDestructured(recurmax, names, values);
|
||||
continue;
|
||||
}
|
||||
if (i < m) {
|
||||
names.unshift(createName());
|
||||
}
|
||||
if (i < n) {
|
||||
values.unshift(createAssignmentValue(recurmax));
|
||||
createDestructured(recurmax, noDefault, names, values);
|
||||
} else if (i < m) {
|
||||
var name = createName();
|
||||
fill(function() {
|
||||
names.unshift(name + createDefaultValue(recurmax, noDefault));
|
||||
});
|
||||
} else {
|
||||
fill(null, function() {
|
||||
values.unshift(createAssignmentValue(recurmax));
|
||||
});
|
||||
}
|
||||
}
|
||||
return {
|
||||
@@ -481,7 +516,7 @@ function createAssignmentPairs(recurmax, stmtDepth, canThrow, nameLenBefore, was
|
||||
};
|
||||
}
|
||||
|
||||
function createDestructured(recurmax, names, values) {
|
||||
function createDestructured(recurmax, noDefault, names, values) {
|
||||
switch (rng(20)) {
|
||||
case 0:
|
||||
if (--recurmax < 0) {
|
||||
@@ -489,20 +524,26 @@ function createAssignmentPairs(recurmax, stmtDepth, canThrow, nameLenBefore, was
|
||||
values.unshift('""');
|
||||
} else {
|
||||
var pairs = createPairs(recurmax);
|
||||
while (!rng(10)) {
|
||||
var index = rng(pairs.names.length + 1);
|
||||
pairs.names.splice(index, 0, "");
|
||||
if (index < pairs.values.length) {
|
||||
pairs.values.splice(index, 0, rng(2) ? createAssignmentValue(recurmax) : "");
|
||||
} else switch (rng(5)) {
|
||||
case 0:
|
||||
pairs.values[index] = createAssignmentValue(recurmax);
|
||||
case 1:
|
||||
pairs.values.length = index + 1;
|
||||
var default_value;
|
||||
fill(function() {
|
||||
default_value = createDefaultValue(recurmax, noDefault);
|
||||
}, function() {
|
||||
while (!rng(10)) {
|
||||
var index = rng(pairs.names.length + 1);
|
||||
pairs.names.splice(index, 0, "");
|
||||
if (index < pairs.values.length) {
|
||||
pairs.values.splice(index, 0, rng(2) ? createAssignmentValue(recurmax) : "");
|
||||
} else switch (rng(5)) {
|
||||
case 0:
|
||||
pairs.values[index] = createAssignmentValue(recurmax);
|
||||
case 1:
|
||||
pairs.values.length = index + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
names.unshift("[ " + pairs.names.join(", ") + " ]");
|
||||
values.unshift("[ " + pairs.values.join(", ") + " ]");
|
||||
convertToRest(pairs.names);
|
||||
names.unshift("[ " + pairs.names.join(", ") + " ]" + default_value);
|
||||
values.unshift("[ " + pairs.values.join(", ") + " ]");
|
||||
});
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
@@ -521,33 +562,33 @@ function createAssignmentPairs(recurmax, stmtDepth, canThrow, nameLenBefore, was
|
||||
keys[index] = key;
|
||||
}
|
||||
});
|
||||
var save_async = async;
|
||||
if (was_async != null) {
|
||||
async = false;
|
||||
if (save_async || was_async) avoid.push("await");
|
||||
}
|
||||
addAvoidVars(avoid);
|
||||
var save_vars = nameLenBefore && VAR_NAMES.splice(nameLenBefore);
|
||||
names.unshift("{ " + addTrailingComma(pairs.names.map(function(name, index) {
|
||||
var key = index in keys ? keys[index] : rng(10) && createKey(recurmax, keys);
|
||||
return key ? key + ": " + name : name;
|
||||
}).join(", ")) + " }");
|
||||
if (was_async != null) {
|
||||
async = was_async;
|
||||
if (save_async || was_async) removeAvoidVars([ avoid.pop() ]);
|
||||
}
|
||||
values.unshift("{ " + addTrailingComma(pairs.values.map(function(value, index) {
|
||||
var key = index in keys ? keys[index] : createKey(recurmax, keys);
|
||||
return key + ": " + value;
|
||||
}).join(", ")) + " }");
|
||||
if (save_vars) [].push.apply(VAR_NAMES, save_vars);
|
||||
removeAvoidVars(avoid);
|
||||
async = save_async;
|
||||
fill(function() {
|
||||
var last = pairs.names.length - 1, has_rest = false;
|
||||
var s = pairs.names.map(function(name, index) {
|
||||
if (index in keys) return keys[index] + ": " + name;
|
||||
if (index == last && SUPPORT.rest_object && rng(20) == 0 && name.indexOf("=") < 0) {
|
||||
has_rest = true;
|
||||
return "..." + name;
|
||||
}
|
||||
return rng(10) == 0 ? name : createKey(recurmax, keys) + ": " + name;
|
||||
}).join(", ");
|
||||
if (!has_rest) s = addTrailingComma(s);
|
||||
names.unshift("{ " + s + " }" + createDefaultValue(recurmax, noDefault));
|
||||
}, function() {
|
||||
values.unshift("{ " + addTrailingComma(pairs.values.map(function(value, index) {
|
||||
var key = index in keys ? keys[index] : createKey(recurmax, keys);
|
||||
return key + ": " + value;
|
||||
}).join(", ")) + " }");
|
||||
});
|
||||
}
|
||||
break;
|
||||
default:
|
||||
names.unshift(createName());
|
||||
values.unshift(createAssignmentValue(recurmax));
|
||||
var name = createName();
|
||||
fill(function() {
|
||||
names.unshift(name + createDefaultValue(recurmax, noDefault));
|
||||
}, function() {
|
||||
values.unshift(createAssignmentValue(recurmax));
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -575,8 +616,8 @@ function createBlockVariables(recurmax, stmtDepth, canThrow, fn) {
|
||||
}
|
||||
unique_vars.length -= 6;
|
||||
fn(function() {
|
||||
addAvoidVars(consts);
|
||||
addAvoidVars(lets);
|
||||
consts.forEach(addAvoidVar);
|
||||
lets.forEach(addAvoidVar);
|
||||
if (rng(2)) {
|
||||
return createDefinitions("const", consts) + "\n" + createDefinitions("let", lets) + "\n";
|
||||
} else {
|
||||
@@ -610,17 +651,17 @@ function createBlockVariables(recurmax, stmtDepth, canThrow, fn) {
|
||||
default:
|
||||
s += names.map(function(name) {
|
||||
if (type == "let" && !rng(10)) {
|
||||
removeAvoidVars([ name ]);
|
||||
removeAvoidVar(name);
|
||||
return name;
|
||||
}
|
||||
var value = createExpression(recurmax, NO_COMMA, stmtDepth, canThrow);
|
||||
removeAvoidVars([ name ]);
|
||||
removeAvoidVar(name);
|
||||
return name + " = " + value;
|
||||
}).join(", ") + ";";
|
||||
names.length = 0;
|
||||
break;
|
||||
}
|
||||
removeAvoidVars(names);
|
||||
names.forEach(removeAvoidVar);
|
||||
return s;
|
||||
}
|
||||
}
|
||||
@@ -659,7 +700,8 @@ function createFunction(recurmax, allowDefun, canThrow, stmtDepth) {
|
||||
if (SUPPORT.destructuring && (!allowDefun || !(name in called)) && rng(2)) {
|
||||
called[name] = false;
|
||||
var pairs = createAssignmentPairs(recurmax, stmtDepth, canThrow, nameLenBefore, save_async);
|
||||
params = addTrailingComma(pairs.names.join(", "));
|
||||
params = pairs.names.join(", ");
|
||||
if (!pairs.has_rest) params = addTrailingComma(params);
|
||||
args = addTrailingComma(pairs.values.join(", "));
|
||||
} else {
|
||||
params = createParams(save_async);
|
||||
@@ -877,9 +919,9 @@ function createStatement(recurmax, canThrow, canBreak, canContinue, cannotReturn
|
||||
unique_vars.length -= 6;
|
||||
if (SUPPORT.computed_key && rng(10) == 0) {
|
||||
s += " catch ({ message: " + message + ", ";
|
||||
addAvoidVars([ name ]);
|
||||
addAvoidVar(name);
|
||||
s += "[" + createExpression(recurmax, NO_COMMA, stmtDepth, canThrow) + "]: " + name;
|
||||
removeAvoidVars([ name ]);
|
||||
removeAvoidVar(name);
|
||||
s += " }) { ";
|
||||
} else {
|
||||
s += " catch ({ name: " + name + ", message: " + message + " }) { ";
|
||||
@@ -1011,7 +1053,7 @@ function _createExpression(recurmax, noComma, stmtDepth, canThrow) {
|
||||
var s = [];
|
||||
switch (rng(5)) {
|
||||
case 0:
|
||||
if (SUPPORT.arrow && !async && !name && rng(2)) {
|
||||
if (SUPPORT.arrow && !name && rng(2)) {
|
||||
var args, suffix;
|
||||
(rng(2) ? createBlockVariables : function() {
|
||||
arguments[3]();
|
||||
@@ -1019,21 +1061,23 @@ function _createExpression(recurmax, noComma, stmtDepth, canThrow) {
|
||||
var params;
|
||||
if (SUPPORT.destructuring && rng(2)) {
|
||||
var pairs = createAssignmentPairs(recurmax, stmtDepth, canThrow, nameLenBefore, save_async);
|
||||
params = addTrailingComma(pairs.names.join(", "));
|
||||
params = pairs.names.join(", ");
|
||||
if (!pairs.has_rest) params = addTrailingComma(params);
|
||||
args = addTrailingComma(pairs.values.join(", "));
|
||||
} else {
|
||||
params = createParams(save_async, NO_DUPLICATE);
|
||||
}
|
||||
params = (async ? "async (" : "(") + params + ") => ";
|
||||
if (defns) {
|
||||
s.push(
|
||||
"((" + params + ") => {",
|
||||
"(" + params + "{",
|
||||
strictMode(),
|
||||
defns(),
|
||||
_createStatements(rng(5) + 1, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CAN_RETURN, stmtDepth)
|
||||
);
|
||||
suffix = "})";
|
||||
} else {
|
||||
s.push("((" + params + ") => ");
|
||||
s.push("(" + params);
|
||||
switch (rng(10)) {
|
||||
case 0:
|
||||
s.push('(typeof arguments != "undefined" && arguments && arguments[' + rng(3) + "])");
|
||||
@@ -1441,18 +1485,26 @@ function _createSimpleBinaryExpr(recurmax, noComma, stmtDepth, canThrow) {
|
||||
function createTypeofExpr(recurmax, stmtDepth, canThrow) {
|
||||
switch (rng(8)) {
|
||||
case 0:
|
||||
return "(typeof " + createVarName(MANDATORY, DONT_STORE) + ' === "' + TYPEOF_OUTCOMES[rng(TYPEOF_OUTCOMES.length)] + '")';
|
||||
return "(typeof " + createVar() + ' === "' + TYPEOF_OUTCOMES[rng(TYPEOF_OUTCOMES.length)] + '")';
|
||||
case 1:
|
||||
return "(typeof " + createVarName(MANDATORY, DONT_STORE) + ' !== "' + TYPEOF_OUTCOMES[rng(TYPEOF_OUTCOMES.length)] + '")';
|
||||
return "(typeof " + createVar() + ' !== "' + TYPEOF_OUTCOMES[rng(TYPEOF_OUTCOMES.length)] + '")';
|
||||
case 2:
|
||||
return "(typeof " + createVarName(MANDATORY, DONT_STORE) + ' == "' + TYPEOF_OUTCOMES[rng(TYPEOF_OUTCOMES.length)] + '")';
|
||||
return "(typeof " + createVar() + ' == "' + TYPEOF_OUTCOMES[rng(TYPEOF_OUTCOMES.length)] + '")';
|
||||
case 3:
|
||||
return "(typeof " + createVarName(MANDATORY, DONT_STORE) + ' != "' + TYPEOF_OUTCOMES[rng(TYPEOF_OUTCOMES.length)] + '")';
|
||||
return "(typeof " + createVar() + ' != "' + TYPEOF_OUTCOMES[rng(TYPEOF_OUTCOMES.length)] + '")';
|
||||
case 4:
|
||||
return "(typeof " + createVarName(MANDATORY, DONT_STORE) + ")";
|
||||
return "(typeof " + createVar() + ")";
|
||||
default:
|
||||
return "(typeof " + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + ")";
|
||||
}
|
||||
|
||||
function createVar() {
|
||||
var save_async = async;
|
||||
if (!async && avoid_vars.indexOf("await") >= 0) async = true;
|
||||
var name = createVarName(MANDATORY, DONT_STORE);
|
||||
async = save_async;
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
function createValue() {
|
||||
@@ -1483,15 +1535,13 @@ function createUnaryPostfix() {
|
||||
return UNARY_POSTFIX[rng(UNARY_POSTFIX.length)];
|
||||
}
|
||||
|
||||
function addAvoidVars(names) {
|
||||
avoid_vars = avoid_vars.concat(names);
|
||||
function addAvoidVar(name) {
|
||||
avoid_vars.push(name);
|
||||
}
|
||||
|
||||
function removeAvoidVars(names) {
|
||||
names.forEach(function(name) {
|
||||
var index = avoid_vars.lastIndexOf(name);
|
||||
if (index >= 0) avoid_vars.splice(index, 1);
|
||||
});
|
||||
function removeAvoidVar(name) {
|
||||
var index = avoid_vars.lastIndexOf(name);
|
||||
if (index >= 0) avoid_vars.splice(index, 1);
|
||||
}
|
||||
|
||||
function getVarName(noConst) {
|
||||
@@ -1664,18 +1714,20 @@ function log(options) {
|
||||
}
|
||||
}
|
||||
errorln("//-------------------------------------------------------------");
|
||||
var reduce_options = JSON.parse(options);
|
||||
reduce_options.validate = true;
|
||||
var reduced = reduce_test(original_code, reduce_options, {
|
||||
verbose: false,
|
||||
}).code;
|
||||
if (reduced) {
|
||||
errorln();
|
||||
errorln("// reduced test case (output will differ)");
|
||||
errorln();
|
||||
errorln(reduced);
|
||||
errorln();
|
||||
errorln("//-------------------------------------------------------------");
|
||||
if (!ok) {
|
||||
var reduce_options = JSON.parse(options);
|
||||
reduce_options.validate = true;
|
||||
var reduced = reduce_test(original_code, reduce_options, {
|
||||
verbose: false,
|
||||
}).code;
|
||||
if (reduced) {
|
||||
errorln();
|
||||
errorln("// reduced test case (output will differ)");
|
||||
errorln();
|
||||
errorln(reduced);
|
||||
errorln();
|
||||
errorln("//-------------------------------------------------------------");
|
||||
}
|
||||
}
|
||||
errorln("minify(options):");
|
||||
errorln(JSON.stringify(JSON.parse(options), null, 2));
|
||||
@@ -1692,7 +1744,9 @@ function log(options) {
|
||||
|
||||
function sort_globals(code) {
|
||||
var globals = sandbox.run_code("throw Object.keys(this).sort();" + code);
|
||||
return globals.length ? "var " + globals.join(",") + ";" + code : code;
|
||||
return globals.length ? "var " + globals.map(function(name) {
|
||||
return name + "=" + name;
|
||||
}).join(",") + ";" + code : code;
|
||||
}
|
||||
|
||||
function fuzzy_match(original, uglified) {
|
||||
@@ -1709,6 +1763,18 @@ function fuzzy_match(original, uglified) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function is_error_in(ex) {
|
||||
return ex.name == "TypeError" && /'in'/.test(ex.message);
|
||||
}
|
||||
|
||||
function is_error_spread(ex) {
|
||||
return ex.name == "TypeError" && /Found non-callable @@iterator|is not iterable|undefined is not a function/.test(ex.message);
|
||||
}
|
||||
|
||||
function is_error_recursion(ex) {
|
||||
return ex.name == "RangeError" && /Invalid string length|Maximum call stack size exceeded/.test(ex.message);
|
||||
}
|
||||
|
||||
function patch_try_catch(orig, toplevel) {
|
||||
var stack = [ {
|
||||
code: orig,
|
||||
@@ -1757,13 +1823,13 @@ function patch_try_catch(orig, toplevel) {
|
||||
});
|
||||
offset += insert.length;
|
||||
code = new_code;
|
||||
} else if (result.name == "TypeError" && /'in'/.test(result.message)) {
|
||||
} else if (is_error_in(result)) {
|
||||
index = result.ufuzz_catch;
|
||||
return orig.slice(0, index) + result.ufuzz_var + ' = new Error("invalid `in`");' + orig.slice(index);
|
||||
} else if (result.name == "TypeError" && /not iterable/.test(result.message)) {
|
||||
} else if (is_error_spread(result)) {
|
||||
index = result.ufuzz_catch;
|
||||
return orig.slice(0, index) + result.ufuzz_var + ' = new Error("spread not iterable");' + orig.slice(index);
|
||||
} else if (result.name == "RangeError" && result.message == "Maximum call stack size exceeded") {
|
||||
} else if (is_error_recursion(result)) {
|
||||
index = result.ufuzz_try;
|
||||
return orig.slice(0, index) + 'throw new Error("skipping infinite recursion");' + orig.slice(index);
|
||||
}
|
||||
@@ -1781,6 +1847,18 @@ var beautify_options = {
|
||||
},
|
||||
};
|
||||
var minify_options = require("./options.json");
|
||||
if (typeof sandbox.run_code("A:if (0) B:; else B:;") != "string") {
|
||||
minify_options.forEach(function(o) {
|
||||
if (!("mangle" in o)) o.mangle = {};
|
||||
if (o.mangle) o.mangle.v8 = true;
|
||||
});
|
||||
}
|
||||
var is_bug_async_arrow_rest = function() {};
|
||||
if (SUPPORT.arrow && SUPPORT.async && SUPPORT.rest && typeof sandbox.run_code("async (a = f(...[], b)) => 0;") != "string") {
|
||||
is_bug_async_arrow_rest = function(ex) {
|
||||
return ex.name == "SyntaxError" && ex.message == "Rest parameter must be last formal parameter";
|
||||
};
|
||||
}
|
||||
if (SUPPORT.destructuring && typeof sandbox.run_code("console.log([ 1 ], {} = 2);") != "string") {
|
||||
beautify_options.output.v8 = true;
|
||||
minify_options.forEach(function(o) {
|
||||
@@ -1799,6 +1877,8 @@ for (var round = 1; round <= num_iterations; round++) {
|
||||
var orig_result = [ sandbox.run_code(original_code), sandbox.run_code(original_code, true) ];
|
||||
errored = typeof orig_result[0] != "string";
|
||||
if (errored) {
|
||||
println();
|
||||
println();
|
||||
println("//=============================================================");
|
||||
println("// original code");
|
||||
try_beautify(original_code, false, orig_result[0], println);
|
||||
@@ -1807,6 +1887,7 @@ for (var round = 1; round <= num_iterations; round++) {
|
||||
println("original result:");
|
||||
println(orig_result[0]);
|
||||
println();
|
||||
if (is_bug_async_arrow_rest(orig_result[0])) continue;
|
||||
}
|
||||
minify_options.forEach(function(options) {
|
||||
var o = JSON.parse(options);
|
||||
@@ -1838,8 +1919,14 @@ for (var round = 1; round <= num_iterations; round++) {
|
||||
ok = sandbox.same_stdout(orig_result[toplevel ? 3 : 2], uglify_result);
|
||||
}
|
||||
// ignore difference in error message caused by `in`
|
||||
if (!ok && errored && is_error_in(uglify_result) && is_error_in(original_result)) ok = true;
|
||||
// ignore difference in error message caused by spread syntax
|
||||
if (!ok && errored && is_error_spread(uglify_result) && is_error_spread(original_result)) ok = true;
|
||||
// ignore difference in depth of termination caused by infinite recursion
|
||||
if (!ok && errored && is_error_recursion(original_result)) {
|
||||
if (is_error_recursion(uglify_result) || typeof uglify_result == "string") ok = true;
|
||||
}
|
||||
// ignore errors above when caught by try-catch
|
||||
if (!ok) {
|
||||
var orig_skipped = patch_try_catch(original_code, toplevel);
|
||||
var uglify_skipped = patch_try_catch(uglify_code, toplevel);
|
||||
|
||||
@@ -70,7 +70,7 @@ function run() {
|
||||
|
||||
function trap(data) {
|
||||
stderr += data;
|
||||
if (~stderr.indexOf("\nminify(options):\n")) {
|
||||
if (~stderr.indexOf("!!!!!! Failed... round ")) {
|
||||
process.exitCode = 1;
|
||||
child.stderr.removeListener("data", trap);
|
||||
}
|
||||
|
||||
@@ -21,14 +21,16 @@
|
||||
},
|
||||
{
|
||||
"compress": {
|
||||
"hoist_vars": true,
|
||||
"keep_infinity": true,
|
||||
"passes": 1e6,
|
||||
"unsafe": true
|
||||
},
|
||||
"keep_fnames": true,
|
||||
"toplevel": true
|
||||
},
|
||||
{
|
||||
"compress": {
|
||||
"keep_fargs": false,
|
||||
"passes": 1e6,
|
||||
"sequences": 1e6,
|
||||
"unsafe": true,
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
// workaround for tty output truncation upon process.exit()
|
||||
var exit = process.exit;
|
||||
process.exit = function() {
|
||||
var args = [].slice.call(arguments);
|
||||
process.once("uncaughtException", function() {
|
||||
(function callback() {
|
||||
if (process.stdout.bufferSize || process.stderr.bufferSize) {
|
||||
setTimeout(callback, 1);
|
||||
} else {
|
||||
exit.apply(process, args);
|
||||
}
|
||||
})();
|
||||
});
|
||||
throw exit;
|
||||
};
|
||||
@@ -3,11 +3,11 @@ var fs = require("fs");
|
||||
exports.FILES = [
|
||||
require.resolve("../lib/utils.js"),
|
||||
require.resolve("../lib/ast.js"),
|
||||
require.resolve("../lib/parse.js"),
|
||||
require.resolve("../lib/transform.js"),
|
||||
require.resolve("../lib/parse.js"),
|
||||
require.resolve("../lib/scope.js"),
|
||||
require.resolve("../lib/output.js"),
|
||||
require.resolve("../lib/compress.js"),
|
||||
require.resolve("../lib/output.js"),
|
||||
require.resolve("../lib/sourcemap.js"),
|
||||
require.resolve("../lib/mozilla-ast.js"),
|
||||
require.resolve("../lib/propmangle.js"),
|
||||
@@ -23,6 +23,37 @@ new Function("exports", function() {
|
||||
return code.join("\n\n");
|
||||
}())(exports);
|
||||
|
||||
function to_comment(value) {
|
||||
if (typeof value != "string") value = JSON.stringify(value, function(key, value) {
|
||||
return typeof value == "function" ? "<[ " + value + " ]>" : value;
|
||||
}, 2);
|
||||
return "// " + value.replace(/\n/g, "\n// ");
|
||||
}
|
||||
|
||||
if (+process.env["UGLIFY_BUG_REPORT"]) exports.minify = function(files, options) {
|
||||
if (typeof options == "undefined") options = "<<undefined>>";
|
||||
var code = [
|
||||
"// UGLIFY_BUG_REPORT",
|
||||
to_comment(options),
|
||||
];
|
||||
if (typeof files == "string") {
|
||||
code.push("");
|
||||
code.push("//-------------------------------------------------------------")
|
||||
code.push("// INPUT CODE", files);
|
||||
} else for (var name in files) {
|
||||
code.push("");
|
||||
code.push("//-------------------------------------------------------------")
|
||||
code.push(to_comment(name), files[name]);
|
||||
}
|
||||
if (options.sourceMap && options.sourceMap.url) {
|
||||
code.push("");
|
||||
code.push("//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiJ9");
|
||||
}
|
||||
var result = { code: code.join("\n") };
|
||||
if (options.sourceMap) result.map = '{"version":3,"sources":[],"names":[],"mappings":""}';
|
||||
return result;
|
||||
};
|
||||
|
||||
function describe_ast() {
|
||||
var out = OutputStream({ beautify: true });
|
||||
function doitem(ctor) {
|
||||
|
||||
22
tools/tty.js
Normal file
22
tools/tty.js
Normal file
@@ -0,0 +1,22 @@
|
||||
// workaround for tty output truncation on Node.js
|
||||
try {
|
||||
// prevent buffer overflow and other asynchronous bugs
|
||||
process.stdout._handle.setBlocking(true);
|
||||
process.stderr._handle.setBlocking(true);
|
||||
} catch (e) {
|
||||
// ensure output buffers are flushed before process termination
|
||||
var exit = process.exit;
|
||||
process.exit = function() {
|
||||
var args = [].slice.call(arguments);
|
||||
process.once("uncaughtException", function() {
|
||||
(function callback() {
|
||||
if (process.stdout.bufferSize || process.stderr.bufferSize) {
|
||||
setTimeout(callback, 1);
|
||||
} else {
|
||||
exit.apply(process, args);
|
||||
}
|
||||
})();
|
||||
});
|
||||
throw exit;
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user