Compare commits
37 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6ad8e1081f | ||
|
|
815eff1f7c | ||
|
|
1e9b576ee9 | ||
|
|
3797458365 | ||
|
|
1858c2018c | ||
|
|
ec7f071272 | ||
|
|
f1eb03f2c0 | ||
|
|
0f4cfa877a | ||
|
|
1d5c2becbd | ||
|
|
22a09ea7c5 | ||
|
|
bad664c632 | ||
|
|
8a191c0a84 | ||
|
|
83fb8b4ca1 | ||
|
|
f38e31bd1e | ||
|
|
24e8b47977 | ||
|
|
95618793a4 | ||
|
|
2f3b460212 | ||
|
|
06e135e35f | ||
|
|
ebbf3d4a51 | ||
|
|
a270ba6b59 | ||
|
|
37f35e4ac2 | ||
|
|
50a578c1f6 | ||
|
|
85237b08d4 | ||
|
|
27b159e711 | ||
|
|
82b3eed5ef | ||
|
|
0f7aa41e33 | ||
|
|
370c8e0385 | ||
|
|
4240fba9b8 | ||
|
|
267bc70d33 | ||
|
|
a53ab99378 | ||
|
|
02308a7b56 | ||
|
|
0b3705e82f | ||
|
|
da5a21b240 | ||
|
|
5bd0cf8633 | ||
|
|
9199ab5846 | ||
|
|
ca6dce43fe | ||
|
|
543dd7d3d7 |
27
.github/workflows/ci.yml
vendored
Normal file
27
.github/workflows/ci.yml
vendored
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
name: CI
|
||||||
|
on: [ push, pull_request ]
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
os: [ ubuntu-latest, windows-latest ]
|
||||||
|
node: [ "0.10", 0.12, 4, 6, 8, 10, latest ]
|
||||||
|
script: [ compress, mocha, release/benchmark, release/jetstream ]
|
||||||
|
name: ${{ matrix.os }} ${{ matrix.node }} ${{ matrix.script }}
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
env:
|
||||||
|
NODE: ${{ matrix.node }}
|
||||||
|
TYPE: ${{ matrix.script }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v1
|
||||||
|
- shell: bash
|
||||||
|
run: |
|
||||||
|
git clone --branch v1.5.2 --depth 1 https://github.com/jasongin/nvs.git ~/.nvs
|
||||||
|
. ~/.nvs/nvs.sh
|
||||||
|
nvs --version
|
||||||
|
nvs add node/$NODE
|
||||||
|
nvs use node/$NODE
|
||||||
|
node --version
|
||||||
|
npm --version --no-update-notifier
|
||||||
|
npm install --no-audit --no-optional --no-save --no-update-notifier
|
||||||
|
node test/$TYPE
|
||||||
25
.github/workflows/ufuzz.yml
vendored
Normal file
25
.github/workflows/ufuzz.yml
vendored
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
name: Fuzzing
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: "*/15 * * * *"
|
||||||
|
jobs:
|
||||||
|
ufuzz:
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
os: [ ubuntu-latest, windows-latest ]
|
||||||
|
name: ${{ matrix.os }}
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v1
|
||||||
|
- shell: bash
|
||||||
|
run: |
|
||||||
|
git clone --branch v1.5.2 --depth 1 https://github.com/jasongin/nvs.git ~/.nvs
|
||||||
|
. ~/.nvs/nvs.sh
|
||||||
|
nvs --version
|
||||||
|
nvs add node
|
||||||
|
nvs use node
|
||||||
|
node --version
|
||||||
|
npm --version --no-update-notifier
|
||||||
|
npm install --no-audit --no-optional --no-save --no-update-notifier
|
||||||
|
node test/ufuzz/job 3600000
|
||||||
42
README.md
42
README.md
@@ -478,42 +478,42 @@ if (result.error) throw result.error;
|
|||||||
|
|
||||||
## Minify options
|
## Minify options
|
||||||
|
|
||||||
- `warnings` (default `false`) — pass `true` to return compressor warnings
|
|
||||||
in `result.warnings`. Use the value `"verbose"` for more detailed warnings.
|
|
||||||
|
|
||||||
- `parse` (default `{}`) — pass an object if you wish to specify some
|
|
||||||
additional [parse options](#parse-options).
|
|
||||||
|
|
||||||
- `compress` (default `{}`) — pass `false` to skip compressing entirely.
|
- `compress` (default `{}`) — pass `false` to skip compressing entirely.
|
||||||
Pass an object to specify custom [compress options](#compress-options).
|
Pass an object to specify custom [compress options](#compress-options).
|
||||||
|
|
||||||
|
- `ie8` (default `false`) -- set to `true` to support IE8.
|
||||||
|
|
||||||
|
- `keep_fnames` (default: `false`) -- pass `true` to prevent discarding or mangling
|
||||||
|
of function names. Useful for code relying on `Function.prototype.name`.
|
||||||
|
|
||||||
- `mangle` (default `true`) — pass `false` to skip mangling names, or pass
|
- `mangle` (default `true`) — pass `false` to skip mangling names, or pass
|
||||||
an object to specify [mangle options](#mangle-options) (see below).
|
an object to specify [mangle options](#mangle-options) (see below).
|
||||||
|
|
||||||
- `mangle.properties` (default `false`) — a subcategory of the mangle option.
|
- `mangle.properties` (default `false`) — a subcategory of the mangle option.
|
||||||
Pass an object to specify custom [mangle property options](#mangle-properties-options).
|
Pass an object to specify custom [mangle property options](#mangle-properties-options).
|
||||||
|
|
||||||
- `output` (default `null`) — pass an object if you wish to specify
|
- `nameCache` (default `null`) -- pass an empty object `{}` or a previously
|
||||||
additional [output options](#output-options). The defaults are optimized
|
|
||||||
for best compression.
|
|
||||||
|
|
||||||
- `sourceMap` (default `false`) - pass an object if you wish to specify
|
|
||||||
[source map options](#source-map-options).
|
|
||||||
|
|
||||||
- `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.
|
|
||||||
|
|
||||||
- `nameCache` (default `null`) - pass an empty object `{}` or a previously
|
|
||||||
used `nameCache` object if you wish to cache mangled variable and
|
used `nameCache` object if you wish to cache mangled variable and
|
||||||
property names across multiple invocations of `minify()`. Note: this is
|
property names across multiple invocations of `minify()`. Note: this is
|
||||||
a read/write property. `minify()` will read the name cache state of this
|
a read/write property. `minify()` will read the name cache state of this
|
||||||
object and update it during minification so that it may be
|
object and update it during minification so that it may be
|
||||||
reused or externally persisted by the user.
|
reused or externally persisted by the user.
|
||||||
|
|
||||||
- `ie8` (default `false`) - set to `true` to support IE8.
|
- `output` (default `null`) — pass an object if you wish to specify
|
||||||
|
additional [output options](#output-options). The defaults are optimized
|
||||||
|
for best compression.
|
||||||
|
|
||||||
- `keep_fnames` (default: `false`) - pass `true` to prevent discarding or mangling
|
- `parse` (default `{}`) — pass an object if you wish to specify some
|
||||||
of function names. Useful for code relying on `Function.prototype.name`.
|
additional [parse options](#parse-options).
|
||||||
|
|
||||||
|
- `sourceMap` (default `false`) -- pass an object if you wish to specify
|
||||||
|
[source map options](#source-map-options).
|
||||||
|
|
||||||
|
- `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.
|
||||||
|
|
||||||
|
- `warnings` (default `false`) — pass `true` to return compressor warnings
|
||||||
|
in `result.warnings`. Use the value `"verbose"` for more detailed warnings.
|
||||||
|
|
||||||
## Minify options structure
|
## Minify options structure
|
||||||
|
|
||||||
@@ -682,6 +682,8 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
|
|||||||
where the return value is discarded, to avoid the parens that the
|
where the return value is discarded, to avoid the parens that the
|
||||||
code generator would insert.
|
code generator would insert.
|
||||||
|
|
||||||
|
- `objects` (default: `true`) -- compact duplicate keys in object literals.
|
||||||
|
|
||||||
- `passes` (default: `1`) -- The maximum number of times to run compress.
|
- `passes` (default: `1`) -- The maximum number of times to run compress.
|
||||||
In some cases more than one pass leads to further compressed code. Keep in
|
In some cases more than one pass leads to further compressed code. Keep in
|
||||||
mind more passes will take more time.
|
mind more passes will take more time.
|
||||||
|
|||||||
468
lib/compress.js
468
lib/compress.js
@@ -74,6 +74,7 @@ function Compressor(options, false_by_default) {
|
|||||||
keep_infinity : false,
|
keep_infinity : false,
|
||||||
loops : !false_by_default,
|
loops : !false_by_default,
|
||||||
negate_iife : !false_by_default,
|
negate_iife : !false_by_default,
|
||||||
|
objects : !false_by_default,
|
||||||
passes : 1,
|
passes : 1,
|
||||||
properties : !false_by_default,
|
properties : !false_by_default,
|
||||||
pure_getters : !false_by_default && "strict",
|
pure_getters : !false_by_default && "strict",
|
||||||
@@ -1041,7 +1042,8 @@ merge(Compressor.prototype, {
|
|||||||
|
|
||||||
var global_names = makePredicate("Array Boolean clearInterval clearTimeout console Date decodeURI decodeURIComponent encodeURI encodeURIComponent Error escape eval EvalError Function isFinite isNaN JSON Math Number parseFloat parseInt RangeError ReferenceError RegExp Object setInterval setTimeout String SyntaxError TypeError unescape URIError");
|
var global_names = makePredicate("Array Boolean clearInterval clearTimeout console Date decodeURI decodeURIComponent encodeURI encodeURIComponent Error escape eval EvalError Function isFinite isNaN JSON Math Number parseFloat parseInt RangeError ReferenceError RegExp Object setInterval setTimeout String SyntaxError TypeError unescape URIError");
|
||||||
AST_SymbolRef.DEFMETHOD("is_declared", function(compressor) {
|
AST_SymbolRef.DEFMETHOD("is_declared", function(compressor) {
|
||||||
return !this.definition().undeclared
|
return this.defined
|
||||||
|
|| !this.definition().undeclared
|
||||||
|| compressor.option("unsafe") && global_names[this.name];
|
|| compressor.option("unsafe") && global_names[this.name];
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1128,6 +1130,8 @@ merge(Compressor.prototype, {
|
|||||||
if (!stop_if_hit && in_conditional(node, parent)) {
|
if (!stop_if_hit && in_conditional(node, parent)) {
|
||||||
stop_if_hit = parent;
|
stop_if_hit = parent;
|
||||||
}
|
}
|
||||||
|
// Skip transient nodes caused by single-use variable replacement
|
||||||
|
if (node.single_use && parent instanceof AST_VarDef && parent.value === node) return node;
|
||||||
// Replace variable with assignment when found
|
// Replace variable with assignment when found
|
||||||
var hit_rhs;
|
var hit_rhs;
|
||||||
if (can_replace
|
if (can_replace
|
||||||
@@ -1226,6 +1230,7 @@ merge(Compressor.prototype, {
|
|||||||
var scan_lhs = lhs && !side_effects && !is_lhs_read_only(lhs, compressor);
|
var scan_lhs = lhs && !side_effects && !is_lhs_read_only(lhs, compressor);
|
||||||
var scan_rhs = foldable(get_rhs(candidate));
|
var scan_rhs = foldable(get_rhs(candidate));
|
||||||
if (!scan_lhs && !scan_rhs) continue;
|
if (!scan_lhs && !scan_rhs) continue;
|
||||||
|
var modify_toplevel = false;
|
||||||
// Locate symbols which may execute code outside of scanning range
|
// Locate symbols which may execute code outside of scanning range
|
||||||
var lvalues = get_lvalues(candidate);
|
var lvalues = get_lvalues(candidate);
|
||||||
var lhs_local = is_lhs_local(lhs);
|
var lhs_local = is_lhs_local(lhs);
|
||||||
@@ -1465,50 +1470,20 @@ merge(Compressor.prototype, {
|
|||||||
hit_stack.pop();
|
hit_stack.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
function find_stop(node, level, write_only) {
|
function find_stop(node, level) {
|
||||||
var parent = scanner.parent(level);
|
var parent = scanner.parent(level);
|
||||||
if (parent instanceof AST_Assign) {
|
if (parent instanceof AST_Assign) return node;
|
||||||
if (write_only
|
if (parent instanceof AST_Binary) return node;
|
||||||
&& !(parent.left instanceof AST_PropAccess
|
|
||||||
|| parent.left.name in lvalues)) {
|
|
||||||
return find_stop(parent, level + 1, write_only);
|
|
||||||
}
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
if (parent instanceof AST_Binary) {
|
|
||||||
if (write_only && (!lazy_op[parent.operator] || parent.left === node)) {
|
|
||||||
return find_stop(parent, level + 1, write_only);
|
|
||||||
}
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
if (parent instanceof AST_Call) return node;
|
if (parent instanceof AST_Call) return node;
|
||||||
if (parent instanceof AST_Case) return node;
|
if (parent instanceof AST_Case) return node;
|
||||||
if (parent instanceof AST_Conditional) {
|
if (parent instanceof AST_Conditional) return node;
|
||||||
if (write_only && parent.condition === node) {
|
if (parent instanceof AST_Definitions) return find_stop(parent, level + 1);
|
||||||
return find_stop(parent, level + 1, write_only);
|
if (parent instanceof AST_Exit) return node;
|
||||||
}
|
if (parent instanceof AST_If) return node;
|
||||||
return node;
|
|
||||||
}
|
|
||||||
if (parent instanceof AST_Definitions) {
|
|
||||||
return find_stop(parent, level + 1, true);
|
|
||||||
}
|
|
||||||
if (parent instanceof AST_Exit) {
|
|
||||||
return write_only ? find_stop(parent, level + 1, write_only) : node;
|
|
||||||
}
|
|
||||||
if (parent instanceof AST_If) {
|
|
||||||
if (write_only && parent.condition === node) {
|
|
||||||
return find_stop(parent, level + 1, write_only);
|
|
||||||
}
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
if (parent instanceof AST_IterationStatement) return node;
|
if (parent instanceof AST_IterationStatement) return node;
|
||||||
if (parent instanceof AST_PropAccess) return node;
|
if (parent instanceof AST_PropAccess) return node;
|
||||||
if (parent instanceof AST_Sequence) {
|
if (parent instanceof AST_Sequence) return find_stop(parent, level + 1);
|
||||||
return find_stop(parent, level + 1, parent.tail_node() !== node);
|
if (parent instanceof AST_SimpleStatement) return find_stop(parent, level + 1);
|
||||||
}
|
|
||||||
if (parent instanceof AST_SimpleStatement) {
|
|
||||||
return find_stop(parent, level + 1, true);
|
|
||||||
}
|
|
||||||
if (parent instanceof AST_Switch) return node;
|
if (parent instanceof AST_Switch) return node;
|
||||||
if (parent instanceof AST_Unary) return node;
|
if (parent instanceof AST_Unary) return node;
|
||||||
if (parent instanceof AST_VarDef) return node;
|
if (parent instanceof AST_VarDef) return node;
|
||||||
@@ -1608,7 +1583,16 @@ merge(Compressor.prototype, {
|
|||||||
if (candidate instanceof AST_VarDef) {
|
if (candidate instanceof AST_VarDef) {
|
||||||
lvalues[candidate.name.name] = lhs;
|
lvalues[candidate.name.name] = lhs;
|
||||||
}
|
}
|
||||||
|
var scan_iife = scope instanceof AST_Toplevel;
|
||||||
var tw = new TreeWalker(function(node) {
|
var tw = new TreeWalker(function(node) {
|
||||||
|
if (scan_iife && node.TYPE == "Call") {
|
||||||
|
var exp = node.expression;
|
||||||
|
if (exp instanceof AST_PropAccess) return;
|
||||||
|
if (exp instanceof AST_Function && !exp.contains_this()) return;
|
||||||
|
modify_toplevel = true;
|
||||||
|
scan_iife = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
var value;
|
var value;
|
||||||
if (node instanceof AST_SymbolRef) {
|
if (node instanceof AST_SymbolRef) {
|
||||||
value = node.fixed_value() || node;
|
value = node.fixed_value() || node;
|
||||||
@@ -1695,6 +1679,7 @@ merge(Compressor.prototype, {
|
|||||||
var def = sym.definition();
|
var def = sym.definition();
|
||||||
if (def.orig.length == 1 && def.orig[0] instanceof AST_SymbolDefun) return false;
|
if (def.orig.length == 1 && def.orig[0] instanceof AST_SymbolDefun) return false;
|
||||||
if (def.scope !== scope) return true;
|
if (def.scope !== scope) return true;
|
||||||
|
if (modify_toplevel && compressor.exposed(def)) return true;
|
||||||
return !all(def.references, function(ref) {
|
return !all(def.references, function(ref) {
|
||||||
return ref.scope.resolve() === scope;
|
return ref.scope.resolve() === scope;
|
||||||
});
|
});
|
||||||
@@ -1764,9 +1749,7 @@ merge(Compressor.prototype, {
|
|||||||
if (stat instanceof AST_If) {
|
if (stat instanceof AST_If) {
|
||||||
var ab = aborts(stat.body);
|
var ab = aborts(stat.body);
|
||||||
if (can_merge_flow(ab)) {
|
if (can_merge_flow(ab)) {
|
||||||
if (ab.label) {
|
if (ab.label) remove(ab.label.thedef.references, ab);
|
||||||
remove(ab.label.thedef.references, ab);
|
|
||||||
}
|
|
||||||
CHANGED = true;
|
CHANGED = true;
|
||||||
stat = stat.clone();
|
stat = stat.clone();
|
||||||
stat.condition = stat.condition.negate(compressor);
|
stat.condition = stat.condition.negate(compressor);
|
||||||
@@ -1794,23 +1777,34 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var ab = aborts(stat.alternative);
|
var alt = aborts(stat.alternative);
|
||||||
if (can_merge_flow(ab)) {
|
if (can_merge_flow(alt)) {
|
||||||
if (ab.label) {
|
if (alt.label) remove(alt.label.thedef.references, alt);
|
||||||
remove(ab.label.thedef.references, ab);
|
|
||||||
}
|
|
||||||
CHANGED = true;
|
CHANGED = true;
|
||||||
stat = stat.clone();
|
stat = stat.clone();
|
||||||
stat.body = make_node(AST_BlockStatement, stat.body, {
|
stat.body = make_node(AST_BlockStatement, stat.body, {
|
||||||
body: as_statement_array(stat.body).concat(extract_functions())
|
body: as_statement_array(stat.body).concat(extract_functions())
|
||||||
});
|
});
|
||||||
var body = as_statement_array_with_return(stat.alternative, ab);
|
var body = as_statement_array_with_return(stat.alternative, alt);
|
||||||
stat.alternative = make_node(AST_BlockStatement, stat.alternative, {
|
stat.alternative = make_node(AST_BlockStatement, stat.alternative, {
|
||||||
body: body
|
body: body
|
||||||
});
|
});
|
||||||
statements[i] = stat.transform(compressor);
|
statements[i] = stat.transform(compressor);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (compressor.option("typeofs")) {
|
||||||
|
if (ab && !alt) {
|
||||||
|
mark_locally_defined(stat.condition, null, make_node(AST_BlockStatement, self, {
|
||||||
|
body: statements.slice(i + 1)
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
if (!ab && alt) {
|
||||||
|
mark_locally_defined(stat.condition, make_node(AST_BlockStatement, self, {
|
||||||
|
body: statements.slice(i + 1)
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stat instanceof AST_If && stat.body instanceof AST_Return) {
|
if (stat instanceof AST_If && stat.body instanceof AST_Return) {
|
||||||
@@ -1955,9 +1949,7 @@ merge(Compressor.prototype, {
|
|||||||
&& loop_body(lct) === self
|
&& loop_body(lct) === self
|
||||||
|| stat instanceof AST_Continue
|
|| stat instanceof AST_Continue
|
||||||
&& loop_body(lct) === self) {
|
&& loop_body(lct) === self) {
|
||||||
if (stat.label) {
|
if (stat.label) remove(stat.label.thedef.references, stat);
|
||||||
remove(stat.label.thedef.references, stat);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
statements[n++] = stat;
|
statements[n++] = stat;
|
||||||
}
|
}
|
||||||
@@ -2454,9 +2446,10 @@ merge(Compressor.prototype, {
|
|||||||
|| this.operator == "=" && this.right.is_number(compressor);
|
|| this.operator == "=" && this.right.is_number(compressor);
|
||||||
});
|
});
|
||||||
def(AST_Binary, function(compressor) {
|
def(AST_Binary, function(compressor) {
|
||||||
return binary[this.operator] || this.operator == "+"
|
if (binary[this.operator]) return true;
|
||||||
&& this.left.is_number(compressor)
|
if (this.operator != "+") return false;
|
||||||
&& this.right.is_number(compressor);
|
return (this.left.is_boolean(compressor) || this.left.is_number(compressor))
|
||||||
|
&& (this.right.is_boolean(compressor) || this.right.is_number(compressor));
|
||||||
});
|
});
|
||||||
var fn = makePredicate([
|
var fn = makePredicate([
|
||||||
"charCodeAt",
|
"charCodeAt",
|
||||||
@@ -2876,10 +2869,10 @@ merge(Compressor.prototype, {
|
|||||||
case "+": return +v;
|
case "+": return +v;
|
||||||
case "++":
|
case "++":
|
||||||
case "--":
|
case "--":
|
||||||
if (e instanceof AST_SymbolRef) {
|
if (!(e instanceof AST_SymbolRef)) return this;
|
||||||
var refs = e.definition().references;
|
var refs = e.definition().references;
|
||||||
if (refs[refs.length - 1] === e) return v;
|
if (refs[refs.length - 1] !== e) return this;
|
||||||
}
|
return HOP(e, "_eval") ? +(this.operator[0] + 1) + +v : v;
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
});
|
});
|
||||||
@@ -2915,7 +2908,20 @@ merge(Compressor.prototype, {
|
|||||||
case ">=" : result = left >= right; break;
|
case ">=" : result = left >= right; break;
|
||||||
default : return this;
|
default : return this;
|
||||||
}
|
}
|
||||||
return isNaN(result) && compressor.find_parent(AST_With) ? this : result;
|
if (isNaN(result)) return compressor.find_parent(AST_With) ? this : result;
|
||||||
|
if (compressor.option("unsafe_math")
|
||||||
|
&& result
|
||||||
|
&& typeof result == "number"
|
||||||
|
&& (this.operator == "+" || this.operator == "-")) {
|
||||||
|
var digits = Math.max(0, decimals(left), decimals(right));
|
||||||
|
if (digits < 21) return +result.toFixed(digits);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
|
||||||
|
function decimals(operand) {
|
||||||
|
var match = /(\.[0-9]*)?(e.+)?$/.exec(+operand);
|
||||||
|
return (match[1] || ".").length - 1 - (match[2] || "").slice(1);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
def(AST_Conditional, function(compressor, cached, depth) {
|
def(AST_Conditional, function(compressor, cached, depth) {
|
||||||
var condition = this.condition._eval(compressor, cached, depth);
|
var condition = this.condition._eval(compressor, cached, depth);
|
||||||
@@ -3021,7 +3027,26 @@ merge(Compressor.prototype, {
|
|||||||
});
|
});
|
||||||
def(AST_Call, function(compressor, cached, depth) {
|
def(AST_Call, function(compressor, cached, depth) {
|
||||||
var exp = this.expression;
|
var exp = this.expression;
|
||||||
if (compressor.option("unsafe") && exp instanceof AST_PropAccess) {
|
if (exp instanceof AST_SymbolRef) {
|
||||||
|
var fn = exp.fixed_value();
|
||||||
|
if (!(fn instanceof AST_Lambda)) return this;
|
||||||
|
if (fn.name && fn.name.definition().recursive_refs > 0) return this;
|
||||||
|
if (fn.body.length != 1 || !fn.is_constant_expression()) return this;
|
||||||
|
var stat = fn.body[0];
|
||||||
|
if (!(stat instanceof AST_Return)) return this;
|
||||||
|
var args = eval_args(this.args);
|
||||||
|
if (!args) return this;
|
||||||
|
fn.argnames.forEach(function(sym, i) {
|
||||||
|
var value = args[i];
|
||||||
|
sym.definition().references.forEach(function(node) {
|
||||||
|
node._eval = function() {
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
cached.push(node);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return stat.value ? stat.value._eval(compressor, cached, depth) : undefined;
|
||||||
|
} else if (compressor.option("unsafe") && exp instanceof AST_PropAccess) {
|
||||||
var key = exp.property;
|
var key = exp.property;
|
||||||
if (key instanceof AST_Node) {
|
if (key instanceof AST_Node) {
|
||||||
key = key._eval(compressor, cached, depth);
|
key = key._eval(compressor, cached, depth);
|
||||||
@@ -3039,13 +3064,8 @@ merge(Compressor.prototype, {
|
|||||||
var native_fn = native_fns[val.constructor.name];
|
var native_fn = native_fns[val.constructor.name];
|
||||||
if (!native_fn || !native_fn[key]) return this;
|
if (!native_fn || !native_fn[key]) return this;
|
||||||
}
|
}
|
||||||
var args = [];
|
var args = eval_args(this.args);
|
||||||
for (var i = 0; i < this.args.length; i++) {
|
if (!args) return this;
|
||||||
var arg = this.args[i];
|
|
||||||
var value = arg._eval(compressor, cached, depth);
|
|
||||||
if (arg === value) return this;
|
|
||||||
args.push(value);
|
|
||||||
}
|
|
||||||
if (key == "replace" && typeof args[1] == "function") return this;
|
if (key == "replace" && typeof args[1] == "function") return this;
|
||||||
try {
|
try {
|
||||||
return val[key].apply(val, args);
|
return val[key].apply(val, args);
|
||||||
@@ -3059,6 +3079,17 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
|
|
||||||
|
function eval_args(args) {
|
||||||
|
var values = [];
|
||||||
|
for (var i = 0; i < args.length; i++) {
|
||||||
|
var arg = args[i];
|
||||||
|
var value = arg._eval(compressor, cached, depth);
|
||||||
|
if (arg === value) return;
|
||||||
|
values.push(value);
|
||||||
|
}
|
||||||
|
return values;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
def(AST_New, return_this);
|
def(AST_New, return_this);
|
||||||
})(function(node, func) {
|
})(function(node, func) {
|
||||||
@@ -3408,19 +3439,20 @@ merge(Compressor.prototype, {
|
|||||||
def(AST_Lambda, function(scope) {
|
def(AST_Lambda, function(scope) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var result = true;
|
var result = true;
|
||||||
var inner_scopes = [];
|
var scopes = [];
|
||||||
self.walk(new TreeWalker(function(node, descend) {
|
self.walk(new TreeWalker(function(node, descend) {
|
||||||
if (!result) return true;
|
if (!result) return true;
|
||||||
if (node instanceof AST_Catch) {
|
if (node instanceof AST_Catch) {
|
||||||
inner_scopes.push(node.argname.scope);
|
scopes.push(node.argname.scope);
|
||||||
descend();
|
descend();
|
||||||
inner_scopes.pop();
|
scopes.pop();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (node instanceof AST_Scope && node !== self) {
|
if (node instanceof AST_Scope) {
|
||||||
inner_scopes.push(node);
|
if (node === self) return;
|
||||||
|
scopes.push(node);
|
||||||
descend();
|
descend();
|
||||||
inner_scopes.pop();
|
scopes.pop();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (node instanceof AST_SymbolRef) {
|
if (node instanceof AST_SymbolRef) {
|
||||||
@@ -3428,8 +3460,9 @@ merge(Compressor.prototype, {
|
|||||||
result = false;
|
result = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (self.variables.has(node.name)) return true;
|
||||||
var def = node.definition();
|
var def = node.definition();
|
||||||
if (!self.variables.has(def.name) && !member(def.scope, inner_scopes)) {
|
if (member(def.scope, scopes)) return true;
|
||||||
if (scope) {
|
if (scope) {
|
||||||
var scope_def = scope.find_variable(node);
|
var scope_def = scope.find_variable(node);
|
||||||
if (def.undeclared ? !scope_def : scope_def === def) {
|
if (def.undeclared ? !scope_def : scope_def === def) {
|
||||||
@@ -3438,7 +3471,6 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
result = false;
|
result = false;
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
@@ -3673,8 +3705,8 @@ merge(Compressor.prototype, {
|
|||||||
if (!(sym.definition().id in in_use_ids)) {
|
if (!(sym.definition().id in in_use_ids)) {
|
||||||
sym.__unused = true;
|
sym.__unused = true;
|
||||||
if (trim) {
|
if (trim) {
|
||||||
|
log(sym, "Dropping unused function argument {name} [{file}:{line},{col}]", template(sym));
|
||||||
a.pop();
|
a.pop();
|
||||||
AST_Node[sym.unreferenced() ? "warn" : "info"]("Dropping unused function argument {name} [{file}:{line},{col}]", template(sym));
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
trim = false;
|
trim = false;
|
||||||
@@ -3684,7 +3716,7 @@ merge(Compressor.prototype, {
|
|||||||
if (drop_funcs && node instanceof AST_Defun && node !== self) {
|
if (drop_funcs && node instanceof AST_Defun && node !== self) {
|
||||||
var def = node.name.definition();
|
var def = node.name.definition();
|
||||||
if (!(def.id in in_use_ids)) {
|
if (!(def.id in in_use_ids)) {
|
||||||
AST_Node[node.name.unreferenced() ? "warn" : "info"]("Dropping unused function {name} [{file}:{line},{col}]", template(node.name));
|
log(node.name, "Dropping unused function {name} [{file}:{line},{col}]", template(node.name));
|
||||||
def.eliminated++;
|
def.eliminated++;
|
||||||
return make_node(AST_EmptyStatement, node);
|
return make_node(AST_EmptyStatement, node);
|
||||||
}
|
}
|
||||||
@@ -3772,7 +3804,7 @@ merge(Compressor.prototype, {
|
|||||||
AST_Node.warn("Side effects in initialization of unused variable {name} [{file}:{line},{col}]", template(def.name));
|
AST_Node.warn("Side effects in initialization of unused variable {name} [{file}:{line},{col}]", template(def.name));
|
||||||
side_effects.push(value);
|
side_effects.push(value);
|
||||||
} else {
|
} else {
|
||||||
AST_Node[def.name.unreferenced() ? "warn" : "info"]("Dropping unused variable {name} [{file}:{line},{col}]", template(def.name));
|
log(def.name, "Dropping unused variable {name} [{file}:{line},{col}]", template(def.name));
|
||||||
}
|
}
|
||||||
sym.eliminated++;
|
sym.eliminated++;
|
||||||
}
|
}
|
||||||
@@ -3850,6 +3882,10 @@ merge(Compressor.prototype, {
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function log(sym, text, props) {
|
||||||
|
AST_Node[sym.unreferenced() ? "warn" : "info"](text, props);
|
||||||
|
}
|
||||||
|
|
||||||
function template(sym) {
|
function template(sym) {
|
||||||
return {
|
return {
|
||||||
name : sym.name,
|
name : sym.name,
|
||||||
@@ -4222,7 +4258,7 @@ merge(Compressor.prototype, {
|
|||||||
var left = this.left;
|
var left = this.left;
|
||||||
if (left instanceof AST_PropAccess) {
|
if (left instanceof AST_PropAccess) {
|
||||||
var expr = left.expression;
|
var expr = left.expression;
|
||||||
if (expr instanceof AST_Assign && !expr.may_throw_on_access(compressor)) {
|
if (expr instanceof AST_Assign && expr.operator == "=" && !expr.may_throw_on_access(compressor)) {
|
||||||
expr.write_only = "p";
|
expr.write_only = "p";
|
||||||
}
|
}
|
||||||
if (compressor.has_directive("use strict") && expr.is_constant()) return this;
|
if (compressor.has_directive("use strict") && expr.is_constant()) return this;
|
||||||
@@ -4237,7 +4273,7 @@ merge(Compressor.prototype, {
|
|||||||
def(AST_Binary, function(compressor, first_in_statement) {
|
def(AST_Binary, function(compressor, first_in_statement) {
|
||||||
var right = this.right.drop_side_effect_free(compressor, first_in_statement);
|
var right = this.right.drop_side_effect_free(compressor, first_in_statement);
|
||||||
if (!right) return this.left.drop_side_effect_free(compressor, first_in_statement);
|
if (!right) return this.left.drop_side_effect_free(compressor, first_in_statement);
|
||||||
if (lazy_op[this.operator]) {
|
if (lazy_op[this.operator] && !(right instanceof AST_Function)) {
|
||||||
var node = this;
|
var node = this;
|
||||||
if (right !== node.right) {
|
if (right !== node.right) {
|
||||||
node = this.clone();
|
node = this.clone();
|
||||||
@@ -4542,6 +4578,49 @@ merge(Compressor.prototype, {
|
|||||||
return if_break_in_loop(self, compressor);
|
return if_break_in_loop(self, compressor);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function mark_locally_defined(condition, consequent, alternative, operator) {
|
||||||
|
if (!(condition instanceof AST_Binary)) return;
|
||||||
|
if (!(condition.left instanceof AST_String)) {
|
||||||
|
if (!operator) operator = condition.operator;
|
||||||
|
if (condition.operator != operator) return;
|
||||||
|
switch (operator) {
|
||||||
|
case "&&":
|
||||||
|
case "||":
|
||||||
|
mark_locally_defined(condition.left, consequent, alternative, operator);
|
||||||
|
mark_locally_defined(condition.right, consequent, alternative, operator);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!(condition.right instanceof AST_UnaryPrefix)) return;
|
||||||
|
if (condition.right.operator != "typeof") return;
|
||||||
|
var sym = condition.right.expression;
|
||||||
|
if (!is_undeclared_ref(sym)) return;
|
||||||
|
var body;
|
||||||
|
var undef = condition.left.getValue() == "undefined";
|
||||||
|
switch (condition.operator) {
|
||||||
|
case "==":
|
||||||
|
body = undef ? alternative : consequent;
|
||||||
|
break;
|
||||||
|
case "!=":
|
||||||
|
body = undef ? consequent : alternative;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!body) return;
|
||||||
|
var def = sym.definition();
|
||||||
|
var tw = new TreeWalker(function(node) {
|
||||||
|
if (node instanceof AST_Scope) {
|
||||||
|
var parent = tw.parent();
|
||||||
|
if (parent instanceof AST_Call && parent.expression === node) return;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (node instanceof AST_SymbolRef && node.definition() === def) node.defined = true;
|
||||||
|
});
|
||||||
|
body.walk(tw);
|
||||||
|
}
|
||||||
|
|
||||||
OPT(AST_If, function(self, compressor) {
|
OPT(AST_If, function(self, compressor) {
|
||||||
if (is_empty(self.alternative)) self.alternative = null;
|
if (is_empty(self.alternative)) self.alternative = null;
|
||||||
|
|
||||||
@@ -4593,11 +4672,6 @@ merge(Compressor.prototype, {
|
|||||||
self.body = self.alternative || make_node(AST_EmptyStatement, self);
|
self.body = self.alternative || make_node(AST_EmptyStatement, self);
|
||||||
self.alternative = tmp;
|
self.alternative = tmp;
|
||||||
}
|
}
|
||||||
if (is_empty(self.body) && is_empty(self.alternative)) {
|
|
||||||
return make_node(AST_SimpleStatement, self.condition, {
|
|
||||||
body: self.condition.clone()
|
|
||||||
}).optimize(compressor);
|
|
||||||
}
|
|
||||||
if (self.body instanceof AST_SimpleStatement
|
if (self.body instanceof AST_SimpleStatement
|
||||||
&& self.alternative instanceof AST_SimpleStatement) {
|
&& self.alternative instanceof AST_SimpleStatement) {
|
||||||
return make_node(AST_SimpleStatement, self, {
|
return make_node(AST_SimpleStatement, self, {
|
||||||
@@ -4631,15 +4705,22 @@ merge(Compressor.prototype, {
|
|||||||
}).transform(compressor)
|
}).transform(compressor)
|
||||||
}).optimize(compressor);
|
}).optimize(compressor);
|
||||||
}
|
}
|
||||||
if (self.body instanceof AST_EmptyStatement
|
if (is_empty(self.body)) {
|
||||||
&& self.alternative instanceof AST_SimpleStatement) {
|
if (is_empty(self.alternative)) return make_node(AST_SimpleStatement, self.condition, {
|
||||||
return make_node(AST_SimpleStatement, self, {
|
body: self.condition.clone()
|
||||||
|
}).optimize(compressor);
|
||||||
|
if (self.alternative instanceof AST_SimpleStatement) return make_node(AST_SimpleStatement, self, {
|
||||||
body: make_node(AST_Binary, self, {
|
body: make_node(AST_Binary, self, {
|
||||||
operator : "||",
|
operator : "||",
|
||||||
left : self.condition,
|
left : self.condition,
|
||||||
right : self.alternative.body
|
right : self.alternative.body
|
||||||
}).transform(compressor)
|
}).transform(compressor)
|
||||||
}).optimize(compressor);
|
}).optimize(compressor);
|
||||||
|
self = make_node(AST_If, self, {
|
||||||
|
condition: negated,
|
||||||
|
body: self.alternative,
|
||||||
|
alternative: null
|
||||||
|
});
|
||||||
}
|
}
|
||||||
if (self.body instanceof AST_Exit
|
if (self.body instanceof AST_Exit
|
||||||
&& self.alternative instanceof AST_Exit
|
&& self.alternative instanceof AST_Exit
|
||||||
@@ -4683,6 +4764,7 @@ merge(Compressor.prototype, {
|
|||||||
body: [ self, body ]
|
body: [ self, body ]
|
||||||
}).optimize(compressor);
|
}).optimize(compressor);
|
||||||
}
|
}
|
||||||
|
if (compressor.option("typeofs")) mark_locally_defined(self.condition, self.body, self.alternative);
|
||||||
return self;
|
return self;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -5232,7 +5314,7 @@ merge(Compressor.prototype, {
|
|||||||
if (stat instanceof AST_SimpleStatement) {
|
if (stat instanceof AST_SimpleStatement) {
|
||||||
return make_node(AST_UnaryPrefix, stat, {
|
return make_node(AST_UnaryPrefix, stat, {
|
||||||
operator: "void",
|
operator: "void",
|
||||||
expression: stat.body.clone(true)
|
expression: stat.body
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5670,7 +5752,7 @@ merge(Compressor.prototype, {
|
|||||||
// "undefined" == typeof x => undefined === x
|
// "undefined" == typeof x => undefined === x
|
||||||
else if (compressor.option("typeofs")
|
else if (compressor.option("typeofs")
|
||||||
&& self.left instanceof AST_String
|
&& self.left instanceof AST_String
|
||||||
&& self.left.value == "undefined"
|
&& self.left.getValue() == "undefined"
|
||||||
&& self.right instanceof AST_UnaryPrefix
|
&& self.right instanceof AST_UnaryPrefix
|
||||||
&& self.right.operator == "typeof") {
|
&& self.right.operator == "typeof") {
|
||||||
var expr = self.right.expression;
|
var expr = self.right.expression;
|
||||||
@@ -5790,6 +5872,7 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (compressor.option("evaluate")) {
|
if (compressor.option("evaluate")) {
|
||||||
|
var associative = true;
|
||||||
switch (self.operator) {
|
switch (self.operator) {
|
||||||
case "&&":
|
case "&&":
|
||||||
var ll = fuzzy_eval(self.left);
|
var ll = fuzzy_eval(self.left);
|
||||||
@@ -5858,9 +5941,6 @@ merge(Compressor.prototype, {
|
|||||||
}).optimize(compressor);
|
}).optimize(compressor);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
var associative = true;
|
|
||||||
switch (self.operator) {
|
|
||||||
case "+":
|
case "+":
|
||||||
// "foo" + ("bar" + x) => "foobar" + x
|
// "foo" + ("bar" + x) => "foobar" + x
|
||||||
if (self.left instanceof AST_Constant
|
if (self.left instanceof AST_Constant
|
||||||
@@ -5940,13 +6020,39 @@ merge(Compressor.prototype, {
|
|||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case "-":
|
||||||
|
// a - -b => a + b
|
||||||
|
if (self.right instanceof AST_UnaryPrefix
|
||||||
|
&& self.right.operator == "-"
|
||||||
|
&& self.left.is_number(compressor)
|
||||||
|
&& self.right.expression.is_number(compressor)) {
|
||||||
|
self = make_node(AST_Binary, self, {
|
||||||
|
operator: "+",
|
||||||
|
left: self.left,
|
||||||
|
right: self.right.expression
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
case "*":
|
case "*":
|
||||||
|
case "/":
|
||||||
associative = compressor.option("unsafe_math");
|
associative = compressor.option("unsafe_math");
|
||||||
|
// +a - b => a - b
|
||||||
|
// a - +b => a - b
|
||||||
|
if (self.operator != "+") {
|
||||||
|
if (self.left instanceof AST_UnaryPrefix && self.left.operator == "+") {
|
||||||
|
self.left = self.left.expression;
|
||||||
|
}
|
||||||
|
if (self.right instanceof AST_UnaryPrefix && self.right.operator == "+") {
|
||||||
|
self.right = self.right.expression;
|
||||||
|
}
|
||||||
|
}
|
||||||
case "&":
|
case "&":
|
||||||
case "|":
|
case "|":
|
||||||
case "^":
|
case "^":
|
||||||
// a + +b => +b + a
|
// a + +b => +b + a
|
||||||
if (self.left.is_number(compressor)
|
if (self.operator != "-"
|
||||||
|
&& self.operator != "/"
|
||||||
|
&& self.left.is_number(compressor)
|
||||||
&& self.right.is_number(compressor)
|
&& self.right.is_number(compressor)
|
||||||
&& reversible()
|
&& reversible()
|
||||||
&& !(self.left instanceof AST_Binary
|
&& !(self.left instanceof AST_Binary
|
||||||
@@ -5964,12 +6070,17 @@ merge(Compressor.prototype, {
|
|||||||
self = best_of(compressor, self, reversed);
|
self = best_of(compressor, self, reversed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (associative && self.is_number(compressor)) {
|
if (!associative || !self.is_number(compressor)) break;
|
||||||
// a + (b + c) => (a + b) + c
|
// a + (b + c) => (a + b) + c
|
||||||
if (self.right instanceof AST_Binary
|
if (self.right instanceof AST_Binary
|
||||||
&& self.right.operator == self.operator) {
|
&& self.right.operator != "%"
|
||||||
|
&& PRECEDENCE[self.right.operator] == PRECEDENCE[self.operator]
|
||||||
|
&& self.right.is_number(compressor)
|
||||||
|
&& (self.operator != "+"
|
||||||
|
|| self.right.left.is_boolean(compressor)
|
||||||
|
|| self.right.left.is_number(compressor))) {
|
||||||
self = make_node(AST_Binary, self, {
|
self = make_node(AST_Binary, self, {
|
||||||
operator: self.operator,
|
operator: align(self.operator, self.right.operator),
|
||||||
left: make_node(AST_Binary, self.left, {
|
left: make_node(AST_Binary, self.left, {
|
||||||
operator: self.operator,
|
operator: self.operator,
|
||||||
left: self.left,
|
left: self.left,
|
||||||
@@ -5979,15 +6090,28 @@ merge(Compressor.prototype, {
|
|||||||
}),
|
}),
|
||||||
right: self.right.right
|
right: self.right.right
|
||||||
});
|
});
|
||||||
|
if (self.operator == "+"
|
||||||
|
&& !self.right.is_boolean(compressor)
|
||||||
|
&& !self.right.is_number(compressor)) {
|
||||||
|
self.right = make_node(AST_UnaryPrefix, self.right, {
|
||||||
|
operator: "+",
|
||||||
|
expression: self.right
|
||||||
|
});
|
||||||
}
|
}
|
||||||
// (n + 2) + 3 => 5 + n
|
}
|
||||||
// (2 * n) * 3 => 6 + n
|
// (2 * n) * 3 => 6 * n
|
||||||
|
// (n + 2) + 3 => n + 5
|
||||||
if (self.right instanceof AST_Constant
|
if (self.right instanceof AST_Constant
|
||||||
&& self.left instanceof AST_Binary
|
&& self.left instanceof AST_Binary
|
||||||
&& self.left.operator == self.operator) {
|
&& self.left.operator != "%"
|
||||||
if (self.left.left instanceof AST_Constant) {
|
&& PRECEDENCE[self.left.operator] == PRECEDENCE[self.operator]
|
||||||
|
&& self.left.is_number(compressor)) {
|
||||||
|
if (self.left.left instanceof AST_Constant
|
||||||
|
&& (self.operator != "+"
|
||||||
|
|| self.left.left.is_boolean(compressor)
|
||||||
|
|| self.left.left.is_number(compressor))) {
|
||||||
self = make_node(AST_Binary, self, {
|
self = make_node(AST_Binary, self, {
|
||||||
operator: self.operator,
|
operator: self.left.operator,
|
||||||
left: make_node(AST_Binary, self.left, {
|
left: make_node(AST_Binary, self.left, {
|
||||||
operator: self.operator,
|
operator: self.operator,
|
||||||
left: self.left.left,
|
left: self.left.left,
|
||||||
@@ -5998,44 +6122,34 @@ merge(Compressor.prototype, {
|
|||||||
right: self.left.right
|
right: self.left.right
|
||||||
});
|
});
|
||||||
} else if (self.left.right instanceof AST_Constant) {
|
} else if (self.left.right instanceof AST_Constant) {
|
||||||
|
var op = align(self.left.operator, self.operator);
|
||||||
|
if (op != "+"
|
||||||
|
|| self.left.right.is_boolean(compressor)
|
||||||
|
|| self.left.right.is_number(compressor)) {
|
||||||
self = make_node(AST_Binary, self, {
|
self = make_node(AST_Binary, self, {
|
||||||
operator: self.operator,
|
operator: self.left.operator,
|
||||||
left: make_node(AST_Binary, self.left, {
|
left: self.left.left,
|
||||||
operator: self.operator,
|
right: make_node(AST_Binary, self.left, {
|
||||||
|
operator: op,
|
||||||
left: self.left.right,
|
left: self.left.right,
|
||||||
right: self.right,
|
right: self.right,
|
||||||
start: self.left.right.start,
|
start: self.left.right.start,
|
||||||
end: self.right.end
|
end: self.right.end
|
||||||
}),
|
})
|
||||||
right: self.left.left
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// (a | 1) | (2 | d) => (3 | a) | b
|
|
||||||
if (self.left instanceof AST_Binary
|
|
||||||
&& self.left.operator == self.operator
|
|
||||||
&& self.left.right instanceof AST_Constant
|
|
||||||
&& self.right instanceof AST_Binary
|
|
||||||
&& self.right.operator == self.operator
|
|
||||||
&& self.right.left instanceof AST_Constant) {
|
|
||||||
self = make_node(AST_Binary, self, {
|
|
||||||
operator: self.operator,
|
|
||||||
left: make_node(AST_Binary, self.left, {
|
|
||||||
operator: self.operator,
|
|
||||||
left: make_node(AST_Binary, self.left.left, {
|
|
||||||
operator: self.operator,
|
|
||||||
left: self.left.right,
|
|
||||||
right: self.right.left,
|
|
||||||
start: self.left.right.start,
|
|
||||||
end: self.right.left.end
|
|
||||||
}),
|
|
||||||
right: self.left.left
|
|
||||||
}),
|
|
||||||
right: self.right.right
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (compressor.option("typeofs")) switch (self.operator) {
|
||||||
|
case "&&":
|
||||||
|
mark_locally_defined(self.left, self.right, null, "&&");
|
||||||
|
break;
|
||||||
|
case "||":
|
||||||
|
mark_locally_defined(self.left, null, self.right, "||");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (compressor.option("unsafe")) {
|
if (compressor.option("unsafe")) {
|
||||||
var indexRight = is_indexFn(self.right);
|
var indexRight = is_indexFn(self.right);
|
||||||
@@ -6099,6 +6213,17 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
|
|
||||||
|
function align(ref, op) {
|
||||||
|
switch (ref) {
|
||||||
|
case "-":
|
||||||
|
return op == "+" ? "-" : "+";
|
||||||
|
case "/":
|
||||||
|
return op == "*" ? "/" : "*";
|
||||||
|
default:
|
||||||
|
return op;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function fuzzy_eval(node) {
|
function fuzzy_eval(node) {
|
||||||
if (node.truthy) return true;
|
if (node.truthy) return true;
|
||||||
if (node.falsy) return false;
|
if (node.falsy) return false;
|
||||||
@@ -6182,6 +6307,7 @@ merge(Compressor.prototype, {
|
|||||||
if (single_use && fixed) {
|
if (single_use && fixed) {
|
||||||
def.single_use = false;
|
def.single_use = false;
|
||||||
fixed._squeezed = true;
|
fixed._squeezed = true;
|
||||||
|
fixed.single_use = true;
|
||||||
if (fixed instanceof AST_Defun) {
|
if (fixed instanceof AST_Defun) {
|
||||||
fixed = make_node(AST_Function, fixed, fixed);
|
fixed = make_node(AST_Function, fixed, fixed);
|
||||||
fixed.name = make_node(AST_SymbolLambda, fixed.name, fixed.name);
|
fixed.name = make_node(AST_SymbolLambda, fixed.name, fixed.name);
|
||||||
@@ -6367,10 +6493,23 @@ merge(Compressor.prototype, {
|
|||||||
var ASSIGN_OPS = makePredicate("+ - / * % >> << >>> | ^ &");
|
var ASSIGN_OPS = makePredicate("+ - / * % >> << >>> | ^ &");
|
||||||
var ASSIGN_OPS_COMMUTATIVE = makePredicate("* | ^ &");
|
var ASSIGN_OPS_COMMUTATIVE = makePredicate("* | ^ &");
|
||||||
OPT(AST_Assign, function(self, compressor) {
|
OPT(AST_Assign, function(self, compressor) {
|
||||||
var def;
|
if (compressor.option("dead_code")) {
|
||||||
if (compressor.option("dead_code")
|
if (self.left instanceof AST_PropAccess) {
|
||||||
&& self.left instanceof AST_SymbolRef
|
if (self.operator == "=") {
|
||||||
&& (def = self.left.definition()).scope === compressor.find_parent(AST_Lambda)) {
|
var exp = self.left.expression;
|
||||||
|
if (exp instanceof AST_Lambda
|
||||||
|
|| !compressor.has_directive("use strict")
|
||||||
|
&& exp instanceof AST_Constant
|
||||||
|
&& !exp.may_throw_on_access(compressor)) {
|
||||||
|
return self.left instanceof AST_Dot ? self.right : make_sequence(self, [
|
||||||
|
self.left.property,
|
||||||
|
self.right
|
||||||
|
]).optimize(compressor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (self.left instanceof AST_SymbolRef) {
|
||||||
|
var def = self.left.definition();
|
||||||
|
if (def.scope === compressor.find_parent(AST_Lambda)) {
|
||||||
if (self.left.is_immutable()) return strip_assignment();
|
if (self.left.is_immutable()) return strip_assignment();
|
||||||
var level = 0, node, parent = self;
|
var level = 0, node, parent = self;
|
||||||
do {
|
do {
|
||||||
@@ -6386,6 +6525,8 @@ merge(Compressor.prototype, {
|
|||||||
|| parent instanceof AST_Sequence && parent.tail_node() === node
|
|| parent instanceof AST_Sequence && parent.tail_node() === node
|
||||||
|| parent instanceof AST_UnaryPrefix);
|
|| parent instanceof AST_UnaryPrefix);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
self = self.lift_sequences(compressor);
|
self = self.lift_sequences(compressor);
|
||||||
if (!compressor.option("assignments")) return self;
|
if (!compressor.option("assignments")) return self;
|
||||||
if (self.operator == "=" && self.left instanceof AST_SymbolRef && self.right instanceof AST_Binary) {
|
if (self.operator == "=" && self.left instanceof AST_SymbolRef && self.right instanceof AST_Binary) {
|
||||||
@@ -6572,8 +6713,8 @@ merge(Compressor.prototype, {
|
|||||||
}).optimize(compressor);
|
}).optimize(compressor);
|
||||||
}
|
}
|
||||||
var in_bool = compressor.option("booleans") && compressor.in_boolean_context();
|
var in_bool = compressor.option("booleans") && compressor.in_boolean_context();
|
||||||
if (is_true(self.consequent)) {
|
if (is_true(consequent)) {
|
||||||
if (is_false(self.alternative)) {
|
if (is_false(alternative)) {
|
||||||
// c ? true : false ---> !!c
|
// c ? true : false ---> !!c
|
||||||
return booleanize(condition);
|
return booleanize(condition);
|
||||||
}
|
}
|
||||||
@@ -6581,11 +6722,11 @@ merge(Compressor.prototype, {
|
|||||||
return make_node(AST_Binary, self, {
|
return make_node(AST_Binary, self, {
|
||||||
operator: "||",
|
operator: "||",
|
||||||
left: booleanize(condition),
|
left: booleanize(condition),
|
||||||
right: self.alternative
|
right: alternative
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (is_false(self.consequent)) {
|
if (is_false(consequent)) {
|
||||||
if (is_true(self.alternative)) {
|
if (is_true(alternative)) {
|
||||||
// c ? false : true ---> !c
|
// c ? false : true ---> !c
|
||||||
return booleanize(condition.negate(compressor));
|
return booleanize(condition.negate(compressor));
|
||||||
}
|
}
|
||||||
@@ -6593,26 +6734,26 @@ merge(Compressor.prototype, {
|
|||||||
return make_node(AST_Binary, self, {
|
return make_node(AST_Binary, self, {
|
||||||
operator: "&&",
|
operator: "&&",
|
||||||
left: booleanize(condition.negate(compressor)),
|
left: booleanize(condition.negate(compressor)),
|
||||||
right: self.alternative
|
right: alternative
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (is_true(self.alternative)) {
|
if (is_true(alternative)) {
|
||||||
// c ? x : true ---> !c || x
|
// c ? x : true ---> !c || x
|
||||||
return make_node(AST_Binary, self, {
|
return make_node(AST_Binary, self, {
|
||||||
operator: "||",
|
operator: "||",
|
||||||
left: booleanize(condition.negate(compressor)),
|
left: booleanize(condition.negate(compressor)),
|
||||||
right: self.consequent
|
right: consequent
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (is_false(self.alternative)) {
|
if (is_false(alternative)) {
|
||||||
// c ? x : false ---> !!c && x
|
// c ? x : false ---> !!c && x
|
||||||
return make_node(AST_Binary, self, {
|
return make_node(AST_Binary, self, {
|
||||||
operator: "&&",
|
operator: "&&",
|
||||||
left: booleanize(condition),
|
left: booleanize(condition),
|
||||||
right: self.consequent
|
right: consequent
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if (compressor.option("typeofs")) mark_locally_defined(condition, consequent, alternative);
|
||||||
return self;
|
return self;
|
||||||
|
|
||||||
function booleanize(node) {
|
function booleanize(node) {
|
||||||
@@ -6951,6 +7092,41 @@ merge(Compressor.prototype, {
|
|||||||
return self;
|
return self;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
OPT(AST_Object, function(self, compressor) {
|
||||||
|
if (!compressor.option("objects") || compressor.has_directive("use strict")) return self;
|
||||||
|
var props = self.properties;
|
||||||
|
var keys = new Dictionary();
|
||||||
|
var values = [];
|
||||||
|
self.properties.forEach(function(prop) {
|
||||||
|
if (typeof prop.key != "string") {
|
||||||
|
flush();
|
||||||
|
values.push(prop);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (prop.value.has_side_effects(compressor)) {
|
||||||
|
flush();
|
||||||
|
}
|
||||||
|
keys.add(prop.key, prop.value);
|
||||||
|
});
|
||||||
|
flush();
|
||||||
|
if (self.properties.length != values.length) {
|
||||||
|
return make_node(AST_Object, self, {
|
||||||
|
properties: values
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
|
||||||
|
function flush() {
|
||||||
|
keys.each(function(expressions, key) {
|
||||||
|
values.push(make_node(AST_ObjectKeyVal, self, {
|
||||||
|
key: key,
|
||||||
|
value: make_sequence(self, expressions)
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
keys = new Dictionary();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
OPT(AST_Return, function(self, compressor) {
|
OPT(AST_Return, function(self, compressor) {
|
||||||
if (self.value && is_undefined(self.value, compressor)) {
|
if (self.value && is_undefined(self.value, compressor)) {
|
||||||
self.value = null;
|
self.value = null;
|
||||||
|
|||||||
@@ -91,13 +91,11 @@ function OutputStream(options) {
|
|||||||
comment_filter = function(comment) {
|
comment_filter = function(comment) {
|
||||||
return comment.type != "comment5" && comments.test(comment.value);
|
return comment.type != "comment5" && comments.test(comment.value);
|
||||||
};
|
};
|
||||||
}
|
} else if (typeof comments === "function") {
|
||||||
else if (typeof comments === "function") {
|
|
||||||
comment_filter = function(comment) {
|
comment_filter = function(comment) {
|
||||||
return comment.type != "comment5" && comments(this, comment);
|
return comment.type != "comment5" && comments(this, comment);
|
||||||
};
|
};
|
||||||
}
|
} else if (comments === "some") {
|
||||||
else if (comments === "some") {
|
|
||||||
comment_filter = is_some_comments;
|
comment_filter = is_some_comments;
|
||||||
} else { // NOTE includes "all" option
|
} else { // NOTE includes "all" option
|
||||||
comment_filter = return_true;
|
comment_filter = return_true;
|
||||||
@@ -452,7 +450,7 @@ function OutputStream(options) {
|
|||||||
var self = this;
|
var self = this;
|
||||||
var scan = node instanceof AST_Exit && node.value;
|
var scan = node instanceof AST_Exit && node.value;
|
||||||
var comments = dump(node);
|
var comments = dump(node);
|
||||||
if (!comments) return;
|
if (!comments) comments = [];
|
||||||
|
|
||||||
if (scan) {
|
if (scan) {
|
||||||
var tw = new TreeWalker(function(node) {
|
var tw = new TreeWalker(function(node) {
|
||||||
@@ -643,8 +641,7 @@ function OutputStream(options) {
|
|||||||
var self = this, generator = self._codegen;
|
var self = this, generator = self._codegen;
|
||||||
if (self instanceof AST_Scope) {
|
if (self instanceof AST_Scope) {
|
||||||
active_scope = self;
|
active_scope = self;
|
||||||
}
|
} else if (!use_asm && self instanceof AST_Directive && self.value == "use asm") {
|
||||||
else if (!use_asm && self instanceof AST_Directive && self.value == "use asm") {
|
|
||||||
use_asm = active_scope;
|
use_asm = active_scope;
|
||||||
}
|
}
|
||||||
function doit() {
|
function doit() {
|
||||||
@@ -1043,11 +1040,9 @@ function OutputStream(options) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
b = b.alternative;
|
b = b.alternative;
|
||||||
}
|
} else if (b instanceof AST_StatementWithBody) {
|
||||||
else if (b instanceof AST_StatementWithBody) {
|
|
||||||
b = b.body;
|
b = b.body;
|
||||||
}
|
} else break;
|
||||||
else break;
|
|
||||||
}
|
}
|
||||||
force_statement(self.body, output);
|
force_statement(self.body, output);
|
||||||
}
|
}
|
||||||
|
|||||||
87
lib/parse.js
87
lib/parse.js
@@ -234,6 +234,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|||||||
directives : {},
|
directives : {},
|
||||||
directive_stack : []
|
directive_stack : []
|
||||||
};
|
};
|
||||||
|
var prev_was_dot = false;
|
||||||
|
|
||||||
function peek() {
|
function peek() {
|
||||||
return S.text.charAt(S.pos);
|
return S.text.charAt(S.pos);
|
||||||
@@ -286,16 +287,12 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|||||||
S.tokpos = S.pos;
|
S.tokpos = S.pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
var prev_was_dot = false;
|
|
||||||
function token(type, value, is_comment) {
|
function token(type, value, is_comment) {
|
||||||
S.regex_allowed = ((type == "operator" && !UNARY_POSTFIX[value]) ||
|
S.regex_allowed = type == "operator" && !UNARY_POSTFIX[value]
|
||||||
(type == "keyword" && KEYWORDS_BEFORE_EXPRESSION[value]) ||
|
|| type == "keyword" && KEYWORDS_BEFORE_EXPRESSION[value]
|
||||||
(type == "punc" && PUNC_BEFORE_EXPRESSION[value]));
|
|| type == "punc" && PUNC_BEFORE_EXPRESSION[value];
|
||||||
if (type == "punc" && value == ".") {
|
if (type == "punc" && value == ".") prev_was_dot = true;
|
||||||
prev_was_dot = true;
|
else if (!is_comment) prev_was_dot = false;
|
||||||
} else if (!is_comment) {
|
|
||||||
prev_was_dot = false;
|
|
||||||
}
|
|
||||||
var ret = {
|
var ret = {
|
||||||
type : type,
|
type : type,
|
||||||
value : value,
|
value : value,
|
||||||
@@ -358,12 +355,9 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|||||||
parse_error("Legacy octal literals are not allowed in strict mode");
|
parse_error("Legacy octal literals are not allowed in strict mode");
|
||||||
}
|
}
|
||||||
var valid = parse_js_number(num);
|
var valid = parse_js_number(num);
|
||||||
if (!isNaN(valid)) {
|
if (!isNaN(valid)) return token("num", valid);
|
||||||
return token("num", valid);
|
|
||||||
} else {
|
|
||||||
parse_error("Invalid syntax: " + num);
|
parse_error("Invalid syntax: " + num);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
function read_escaped_char(in_string) {
|
function read_escaped_char(in_string) {
|
||||||
var ch = next(true, in_string);
|
var ch = next(true, in_string);
|
||||||
@@ -463,8 +457,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|||||||
if (ch == "\\") escaped = backslash = true, next();
|
if (ch == "\\") escaped = backslash = true, next();
|
||||||
else if (is_identifier_char(ch)) name += next();
|
else if (is_identifier_char(ch)) name += next();
|
||||||
else break;
|
else break;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
if (ch != "u") parse_error("Expecting UnicodeEscapeSequence -- uXXXX");
|
if (ch != "u") parse_error("Expecting UnicodeEscapeSequence -- uXXXX");
|
||||||
ch = read_escaped_char();
|
ch = read_escaped_char();
|
||||||
if (!is_identifier_char(ch)) parse_error("Unicode char: " + ch.charCodeAt(0) + " is not valid in identifier");
|
if (!is_identifier_char(ch)) parse_error("Unicode char: " + ch.charCodeAt(0) + " is not valid in identifier");
|
||||||
@@ -538,9 +531,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|||||||
|
|
||||||
function handle_dot() {
|
function handle_dot() {
|
||||||
next();
|
next();
|
||||||
return is_digit(peek().charCodeAt(0))
|
return is_digit(peek().charCodeAt(0)) ? read_num(".") : token("punc", ".");
|
||||||
? read_num(".")
|
|
||||||
: token("punc", ".");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function read_word() {
|
function read_word() {
|
||||||
@@ -592,12 +583,11 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|||||||
switch (code) {
|
switch (code) {
|
||||||
case 34: case 39: return read_string(ch);
|
case 34: case 39: return read_string(ch);
|
||||||
case 46: return handle_dot();
|
case 46: return handle_dot();
|
||||||
case 47: {
|
case 47:
|
||||||
var tok = handle_slash();
|
var tok = handle_slash();
|
||||||
if (tok === next_token) continue;
|
if (tok === next_token) continue;
|
||||||
return tok;
|
return tok;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (is_digit(code)) return read_num();
|
if (is_digit(code)) return read_num();
|
||||||
if (PUNC_CHARS[ch]) return token("punc", next());
|
if (PUNC_CHARS[ch]) return token("punc", next());
|
||||||
if (OPERATOR_CHARS[ch]) return read_operator();
|
if (OPERATOR_CHARS[ch]) return read_operator();
|
||||||
@@ -614,12 +604,8 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|||||||
|
|
||||||
next_token.add_directive = function(directive) {
|
next_token.add_directive = function(directive) {
|
||||||
S.directive_stack[S.directive_stack.length - 1].push(directive);
|
S.directive_stack[S.directive_stack.length - 1].push(directive);
|
||||||
|
if (S.directives[directive]) S.directives[directive]++;
|
||||||
if (S.directives[directive] === undefined) {
|
else S.directives[directive] = 1;
|
||||||
S.directives[directive] = 1;
|
|
||||||
} else {
|
|
||||||
S.directives[directive]++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
next_token.push_directives_stack = function() {
|
next_token.push_directives_stack = function() {
|
||||||
@@ -627,13 +613,10 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
next_token.pop_directives_stack = function() {
|
next_token.pop_directives_stack = function() {
|
||||||
var directives = S.directive_stack[S.directive_stack.length - 1];
|
var directives = S.directive_stack.pop();
|
||||||
|
for (var i = directives.length; --i >= 0;) {
|
||||||
for (var i = 0; i < directives.length; i++) {
|
|
||||||
S.directives[directives[i]]--;
|
S.directives[directives[i]]--;
|
||||||
}
|
}
|
||||||
|
|
||||||
S.directive_stack.pop();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
next_token.has_directive = function(directive) {
|
next_token.has_directive = function(directive) {
|
||||||
@@ -645,27 +628,17 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|||||||
|
|
||||||
/* -----[ Parser (constants) ]----- */
|
/* -----[ Parser (constants) ]----- */
|
||||||
|
|
||||||
var UNARY_PREFIX = makePredicate([
|
var UNARY_PREFIX = makePredicate("typeof void delete -- ++ ! ~ - +");
|
||||||
"typeof",
|
|
||||||
"void",
|
|
||||||
"delete",
|
|
||||||
"--",
|
|
||||||
"++",
|
|
||||||
"!",
|
|
||||||
"~",
|
|
||||||
"-",
|
|
||||||
"+"
|
|
||||||
]);
|
|
||||||
|
|
||||||
var UNARY_POSTFIX = makePredicate([ "--", "++" ]);
|
var UNARY_POSTFIX = makePredicate("-- ++");
|
||||||
|
|
||||||
var ASSIGNMENT = makePredicate([ "=", "+=", "-=", "/=", "*=", "%=", ">>=", "<<=", ">>>=", "|=", "^=", "&=" ]);
|
var ASSIGNMENT = makePredicate("= += -= /= *= %= >>= <<= >>>= |= ^= &=");
|
||||||
|
|
||||||
var PRECEDENCE = function(a, ret) {
|
var PRECEDENCE = function(a, ret) {
|
||||||
for (var i = 0; i < a.length; ++i) {
|
for (var i = 0; i < a.length;) {
|
||||||
var b = a[i];
|
var b = a[i++];
|
||||||
for (var j = 0; j < b.length; ++j) {
|
for (var j = 0; j < b.length; j++) {
|
||||||
ret[b[j]] = i + 1;
|
ret[b[j]] = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
@@ -682,7 +655,7 @@ var PRECEDENCE = function(a, ret) {
|
|||||||
["*", "/", "%"]
|
["*", "/", "%"]
|
||||||
], {});
|
], {});
|
||||||
|
|
||||||
var ATOMIC_START_TOKEN = makePredicate([ "atom", "num", "string", "regexp", "name" ]);
|
var ATOMIC_START_TOKEN = makePredicate("atom num string regexp name");
|
||||||
|
|
||||||
/* -----[ Parser ]----- */
|
/* -----[ Parser ]----- */
|
||||||
|
|
||||||
@@ -698,10 +671,9 @@ function parse($TEXT, options) {
|
|||||||
}, true);
|
}, true);
|
||||||
|
|
||||||
var S = {
|
var S = {
|
||||||
input : (typeof $TEXT == "string"
|
input : typeof $TEXT == "string"
|
||||||
? tokenizer($TEXT, options.filename,
|
? tokenizer($TEXT, options.filename, options.html5_comments, options.shebang)
|
||||||
options.html5_comments, options.shebang)
|
: $TEXT,
|
||||||
: $TEXT),
|
|
||||||
token : null,
|
token : null,
|
||||||
prev : null,
|
prev : null,
|
||||||
peeked : null,
|
peeked : null,
|
||||||
@@ -757,15 +729,12 @@ function parse($TEXT, options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function unexpected(token) {
|
function unexpected(token) {
|
||||||
if (token == null)
|
if (token == null) token = S.token;
|
||||||
token = S.token;
|
|
||||||
token_error(token, "Unexpected token: " + token_to_string(token.type, token.value));
|
token_error(token, "Unexpected token: " + token_to_string(token.type, token.value));
|
||||||
}
|
}
|
||||||
|
|
||||||
function expect_token(type, val) {
|
function expect_token(type, val) {
|
||||||
if (is(type, val)) {
|
if (is(type, val)) return next();
|
||||||
return next();
|
|
||||||
}
|
|
||||||
token_error(S.token, "Unexpected token: " + token_to_string(S.token.type, S.token.value) + ", expected: " + token_to_string(type, val));
|
token_error(S.token, "Unexpected token: " + token_to_string(S.token.type, S.token.value) + ", expected: " + token_to_string(type, val));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1284,6 +1253,7 @@ function parse($TEXT, options) {
|
|||||||
var ex = expression(true);
|
var ex = expression(true);
|
||||||
var len = start.comments_before.length;
|
var len = start.comments_before.length;
|
||||||
[].unshift.apply(ex.start.comments_before, start.comments_before);
|
[].unshift.apply(ex.start.comments_before, start.comments_before);
|
||||||
|
start.comments_before.length = 0;
|
||||||
start.comments_before = ex.start.comments_before;
|
start.comments_before = ex.start.comments_before;
|
||||||
start.comments_before_length = len;
|
start.comments_before_length = len;
|
||||||
if (len == 0 && start.comments_before.length > 0) {
|
if (len == 0 && start.comments_before.length > 0) {
|
||||||
@@ -1299,6 +1269,7 @@ function parse($TEXT, options) {
|
|||||||
var end = prev();
|
var end = prev();
|
||||||
end.comments_before = ex.end.comments_before;
|
end.comments_before = ex.end.comments_before;
|
||||||
[].push.apply(ex.end.comments_after, end.comments_after);
|
[].push.apply(ex.end.comments_after, end.comments_after);
|
||||||
|
end.comments_after.length = 0;
|
||||||
end.comments_after = ex.end.comments_after;
|
end.comments_after = ex.end.comments_after;
|
||||||
ex.end = end;
|
ex.end = end;
|
||||||
if (ex instanceof AST_Call) mark_pure(ex);
|
if (ex instanceof AST_Call) mark_pure(ex);
|
||||||
|
|||||||
12
lib/scope.js
12
lib/scope.js
@@ -214,7 +214,13 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
|
|||||||
function redefine(node, scope) {
|
function redefine(node, scope) {
|
||||||
var name = node.name;
|
var name = node.name;
|
||||||
var old_def = node.thedef;
|
var old_def = node.thedef;
|
||||||
var new_def = scope.find_variable(name) || self.globals.get(name) || scope.def_variable(node);
|
var new_def = scope.find_variable(name);
|
||||||
|
if (new_def) {
|
||||||
|
var redef;
|
||||||
|
while (redef = new_def.redefined()) new_def = redef;
|
||||||
|
} else {
|
||||||
|
new_def = self.globals.get(name) || scope.def_variable(node);
|
||||||
|
}
|
||||||
old_def.orig.concat(old_def.references).forEach(function(node) {
|
old_def.orig.concat(old_def.references).forEach(function(node) {
|
||||||
node.thedef = new_def;
|
node.thedef = new_def;
|
||||||
node.reference(options);
|
node.reference(options);
|
||||||
@@ -292,9 +298,7 @@ AST_Scope.DEFMETHOD("def_variable", function(symbol, init) {
|
|||||||
var def = this.variables.get(symbol.name);
|
var def = this.variables.get(symbol.name);
|
||||||
if (def) {
|
if (def) {
|
||||||
def.orig.push(symbol);
|
def.orig.push(symbol);
|
||||||
if (def.init && (def.scope !== symbol.scope || def.init instanceof AST_Function)) {
|
if (def.init instanceof AST_Function) def.init = init;
|
||||||
def.init = init;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
def = new SymbolDef(this, symbol, init);
|
def = new SymbolDef(this, symbol, init);
|
||||||
this.variables.set(symbol.name, def);
|
this.variables.set(symbol.name, def);
|
||||||
|
|||||||
@@ -127,8 +127,7 @@ var MAP = (function() {
|
|||||||
} else {
|
} else {
|
||||||
top.push(val);
|
top.push(val);
|
||||||
}
|
}
|
||||||
}
|
} else if (val !== skip) {
|
||||||
else if (val !== skip) {
|
|
||||||
if (val instanceof Splice) {
|
if (val instanceof Splice) {
|
||||||
ret.push.apply(ret, backwards ? val.v.slice().reverse() : val.v);
|
ret.push.apply(ret, backwards ? val.v.slice().reverse() : val.v);
|
||||||
} else {
|
} else {
|
||||||
@@ -145,8 +144,7 @@ var MAP = (function() {
|
|||||||
} else {
|
} else {
|
||||||
for (i = 0; i < a.length; ++i) if (doit()) break;
|
for (i = 0; i < a.length; ++i) if (doit()) break;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
for (i in a) if (HOP(a, i)) if (doit()) break;
|
for (i in a) if (HOP(a, i)) if (doit()) break;
|
||||||
}
|
}
|
||||||
return top.concat(ret);
|
return top.concat(ret);
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"description": "JavaScript parser, mangler/compressor and beautifier toolkit",
|
"description": "JavaScript parser, mangler/compressor and beautifier toolkit",
|
||||||
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
|
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
|
||||||
"license": "BSD-2-Clause",
|
"license": "BSD-2-Clause",
|
||||||
"version": "3.6.3",
|
"version": "3.6.6",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.8.0"
|
"node": ">=0.8.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -94,6 +94,3 @@ urls.forEach(function(url) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
setInterval(function() {
|
|
||||||
process.stderr.write("\0");
|
|
||||||
}, 5 * 60 * 1000).unref();
|
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
require("../tools/exit");
|
||||||
|
|
||||||
var assert = require("assert");
|
var assert = require("assert");
|
||||||
var child_process = require("child_process");
|
var child_process = require("child_process");
|
||||||
var fs = require("fs");
|
var fs = require("fs");
|
||||||
@@ -9,7 +13,7 @@ var U = require("./node");
|
|||||||
var file = process.argv[2];
|
var file = process.argv[2];
|
||||||
var dir = path.resolve(path.dirname(module.filename), "compress");
|
var dir = path.resolve(path.dirname(module.filename), "compress");
|
||||||
if (file) {
|
if (file) {
|
||||||
var minify_options = require("./ufuzz.json").map(JSON.stringify);
|
var minify_options = require("./ufuzz/options.json").map(JSON.stringify);
|
||||||
log("--- {file}", { file: file });
|
log("--- {file}", { file: file });
|
||||||
var tests = parse_test(path.resolve(dir, file));
|
var tests = parse_test(path.resolve(dir, file));
|
||||||
process.exit(Object.keys(tests).filter(function(name) {
|
process.exit(Object.keys(tests).filter(function(name) {
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ asm_mixed: {
|
|||||||
return +sum;
|
return +sum;
|
||||||
}
|
}
|
||||||
function geometricMean(start, end) {
|
function geometricMean(start, end) {
|
||||||
return start |= 0, end |= 0, +exp(+logSum(start, end) / +(end - start | 0));
|
return start |= 0, end |= 0, +exp(logSum(start, end) / (end - start | 0));
|
||||||
}
|
}
|
||||||
var exp = stdlib.Math.exp, log = stdlib.Math.log, values = new stdlib.Float64Array(buffer);
|
var exp = stdlib.Math.exp, log = stdlib.Math.log, values = new stdlib.Float64Array(buffer);
|
||||||
return { geometricMean: geometricMean };
|
return { geometricMean: geometricMean };
|
||||||
|
|||||||
@@ -3511,7 +3511,7 @@ issue_2437_2: {
|
|||||||
conditionals: true,
|
conditionals: true,
|
||||||
inline: true,
|
inline: true,
|
||||||
join_vars: true,
|
join_vars: true,
|
||||||
passes: 2,
|
passes: 3,
|
||||||
reduce_funcs: true,
|
reduce_funcs: true,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
sequences: true,
|
sequences: true,
|
||||||
@@ -6237,3 +6237,114 @@ issue_3439_2: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "number"
|
expect_stdout: "number"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cond_sequence_return: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function(n) {
|
||||||
|
var c = 0;
|
||||||
|
for (var k in [0, 1])
|
||||||
|
if (c++, k == n) return c;
|
||||||
|
}(1));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function(n) {
|
||||||
|
var c = 0;
|
||||||
|
for (var k in [0, 1])
|
||||||
|
if (c++, k == n) return c;
|
||||||
|
}(1));
|
||||||
|
}
|
||||||
|
expect_stdout: "2"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3520: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 0;
|
||||||
|
var b = function(c) {
|
||||||
|
for (var i = 2; --i >= 0;) {
|
||||||
|
(function f() {
|
||||||
|
c = 0;
|
||||||
|
var i = void 0;
|
||||||
|
var f = f && f[i];
|
||||||
|
})();
|
||||||
|
a += b;
|
||||||
|
c && b++;
|
||||||
|
}
|
||||||
|
}(b = 1);
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 0;
|
||||||
|
var b = function(c) {
|
||||||
|
for (var i = 2; --i >= 0;) {
|
||||||
|
(function() {
|
||||||
|
c = 0;
|
||||||
|
var f = f && f[void 0];
|
||||||
|
})();
|
||||||
|
a += b;
|
||||||
|
c && b++;
|
||||||
|
}
|
||||||
|
}(b = 1);
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: "2"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3526_1: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var b = function() {
|
||||||
|
this.a = "FAIL";
|
||||||
|
}();
|
||||||
|
var a = "PASS";
|
||||||
|
var b;
|
||||||
|
var c = b;
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var b = function() {
|
||||||
|
this.a = "FAIL";
|
||||||
|
}();
|
||||||
|
var a = "PASS";
|
||||||
|
var b;
|
||||||
|
var c = b;
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3526_2: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
this.a = "FAIL";
|
||||||
|
}
|
||||||
|
var b = f();
|
||||||
|
var a = "PASS";
|
||||||
|
var b;
|
||||||
|
var c = b;
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f() {
|
||||||
|
this.a = "FAIL";
|
||||||
|
}
|
||||||
|
var b = f();
|
||||||
|
var a = "PASS";
|
||||||
|
var b;
|
||||||
|
var c = b;
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|||||||
@@ -161,6 +161,24 @@ ifs_6: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ifs_7: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
if (A); else;
|
||||||
|
if (A) while (B); else;
|
||||||
|
if (A); else while (C);
|
||||||
|
if (A) while (B); else while (C);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
A;
|
||||||
|
if (A) while (B);
|
||||||
|
if (!A) while (C);
|
||||||
|
if (A) while (B); else while (C);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cond_1: {
|
cond_1: {
|
||||||
options = {
|
options = {
|
||||||
conditionals: true,
|
conditionals: true,
|
||||||
|
|||||||
@@ -1013,3 +1013,54 @@ issue_3406: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "true"
|
expect_stdout: "true"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function_assign: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function() {
|
||||||
|
var a = "PASS";
|
||||||
|
function h(c) {
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
h.p = function(b) {
|
||||||
|
return b;
|
||||||
|
}.p = a;
|
||||||
|
return h;
|
||||||
|
}().p);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function() {
|
||||||
|
var a = "PASS";
|
||||||
|
function h(c) {
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
h.p = a;
|
||||||
|
return h;
|
||||||
|
}().p);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3552: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
pure_getters: "strict",
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "PASS";
|
||||||
|
(function() {
|
||||||
|
(1..p += 42) && (a = "FAIL");
|
||||||
|
})();
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = "PASS";
|
||||||
|
(function() {
|
||||||
|
(1..p += 42) && (a = "FAIL");
|
||||||
|
})();
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|||||||
@@ -2102,3 +2102,122 @@ issue_3497: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "undefined"
|
expect_stdout: "undefined"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3515_1: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var c = 0;
|
||||||
|
(function() {
|
||||||
|
this[c++] = 0;
|
||||||
|
var expr20 = !0;
|
||||||
|
for (var key20 in expr20);
|
||||||
|
})();
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var c = 0;
|
||||||
|
(function() {
|
||||||
|
this[c++] = 0;
|
||||||
|
for (var key20 in !0);
|
||||||
|
})();
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect_stdout: "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3515_2: {
|
||||||
|
options = {
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "FAIL";
|
||||||
|
function f() {
|
||||||
|
typeof b === "number";
|
||||||
|
delete a;
|
||||||
|
}
|
||||||
|
var b = f(a = "PASS");
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = "FAIL";
|
||||||
|
function f() {
|
||||||
|
delete a;
|
||||||
|
}
|
||||||
|
f(a = "PASS");
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3515_3: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var c = "FAIL";
|
||||||
|
(function() {
|
||||||
|
function f() {
|
||||||
|
c = "PASS";
|
||||||
|
}
|
||||||
|
var a = f();
|
||||||
|
var a = function g(b) {
|
||||||
|
b && (b.p = this);
|
||||||
|
}(a);
|
||||||
|
})();
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var c = "FAIL";
|
||||||
|
(function() {
|
||||||
|
function f() {
|
||||||
|
c = "PASS";
|
||||||
|
}
|
||||||
|
(function(b) {
|
||||||
|
b && (b.p = this);
|
||||||
|
})(f());
|
||||||
|
})();
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
function_assign: {
|
||||||
|
options = {
|
||||||
|
pure_getters: "strict",
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function() {
|
||||||
|
var a = "PASS";
|
||||||
|
function g(b) {
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
g.p = a;
|
||||||
|
function h(c) {
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
h.p = a;
|
||||||
|
return h;
|
||||||
|
}().p);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function() {
|
||||||
|
var a = "PASS";
|
||||||
|
function h(c) {
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
h.p = a;
|
||||||
|
return h;
|
||||||
|
}().p);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|||||||
@@ -1757,3 +1757,105 @@ issue_3387_2: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "NaN"
|
expect_stdout: "NaN"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
simple_function_1: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function sum(a, b) {
|
||||||
|
return a + b;
|
||||||
|
}
|
||||||
|
console.log(sum(1, 2) * sum(3, 4));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(21);
|
||||||
|
}
|
||||||
|
expect_stdout: "21"
|
||||||
|
}
|
||||||
|
|
||||||
|
simple_function_2: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var sum = function(a, b) {
|
||||||
|
return a + b;
|
||||||
|
}
|
||||||
|
console.log(sum(1, 2) * sum(3, 4));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(21);
|
||||||
|
}
|
||||||
|
expect_stdout: "21"
|
||||||
|
}
|
||||||
|
|
||||||
|
recursive_function_1: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function factorial(a) {
|
||||||
|
return a > 0 ? a * factorial(a - 1) : 1;
|
||||||
|
}
|
||||||
|
console.log(factorial(5));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function factorial(a) {
|
||||||
|
return a > 0 ? a * factorial(a - 1) : 1;
|
||||||
|
}(5));
|
||||||
|
}
|
||||||
|
expect_stdout: "120"
|
||||||
|
}
|
||||||
|
|
||||||
|
recursive_function_2: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var factorial = function(a) {
|
||||||
|
return a > 0 ? a * factorial(a - 1) : 1;
|
||||||
|
}
|
||||||
|
console.log(factorial(5));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var factorial = function(a) {
|
||||||
|
return a > 0 ? a * factorial(a - 1) : 1;
|
||||||
|
}
|
||||||
|
console.log(factorial(5));
|
||||||
|
}
|
||||||
|
expect_stdout: "120"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3558: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a) {
|
||||||
|
return 1 + --a;
|
||||||
|
}
|
||||||
|
console.log(f(true), f(false));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a) {
|
||||||
|
return 1 + --a;
|
||||||
|
}
|
||||||
|
console.log(1, 0);
|
||||||
|
}
|
||||||
|
expect_stdout: "1 0"
|
||||||
|
}
|
||||||
|
|||||||
@@ -3066,7 +3066,7 @@ class_iife: {
|
|||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_3400: {
|
issue_3400_1: {
|
||||||
options = {
|
options = {
|
||||||
collapse_vars: true,
|
collapse_vars: true,
|
||||||
inline: true,
|
inline: true,
|
||||||
@@ -3096,16 +3096,70 @@ issue_3400: {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
void console.log(function g() {
|
void console.log(function() {
|
||||||
|
function g() {
|
||||||
|
function h(u) {
|
||||||
|
var o = {
|
||||||
|
p: u
|
||||||
|
};
|
||||||
|
return console.log(o[g]), o;
|
||||||
|
}
|
||||||
function e() {
|
function e() {
|
||||||
return [42].map(function(v) {
|
return [ 42 ].map(function(v) {
|
||||||
return o = {
|
return h(v);
|
||||||
p: v
|
|
||||||
}, console.log(o[g]) , o;
|
|
||||||
var o;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return e();
|
return e();
|
||||||
|
}
|
||||||
|
return g;
|
||||||
|
}()()[0].p);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"undefined",
|
||||||
|
"42",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3400_2: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
inline: true,
|
||||||
|
passes: 2,
|
||||||
|
reduce_funcs: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function(f) {
|
||||||
|
console.log(f()()[0].p);
|
||||||
|
})(function() {
|
||||||
|
function g() {
|
||||||
|
function h(u) {
|
||||||
|
var o = {
|
||||||
|
p: u
|
||||||
|
};
|
||||||
|
return console.log(o[g]), o;
|
||||||
|
}
|
||||||
|
function e() {
|
||||||
|
return [ 42 ].map(function(v) {
|
||||||
|
return h(v);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return e();
|
||||||
|
}
|
||||||
|
return g;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
void console.log(function g() {
|
||||||
|
return [ 42 ].map(function(v) {
|
||||||
|
return function(u) {
|
||||||
|
var o = {
|
||||||
|
p: u
|
||||||
|
};
|
||||||
|
return console.log(o[g]), o;
|
||||||
|
}(v);
|
||||||
|
});
|
||||||
}()[0].p);
|
}()[0].p);
|
||||||
}
|
}
|
||||||
expect_stdout: [
|
expect_stdout: [
|
||||||
@@ -3196,3 +3250,123 @@ issue_3444: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3506_1: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "FAIL";
|
||||||
|
(function(b) {
|
||||||
|
(function(b) {
|
||||||
|
b && (a = "PASS");
|
||||||
|
})(b);
|
||||||
|
})(a);
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = "FAIL";
|
||||||
|
!function(b) {
|
||||||
|
b && (a = "PASS");
|
||||||
|
}(a);
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3506_2: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "FAIL";
|
||||||
|
(function(b) {
|
||||||
|
(function(c) {
|
||||||
|
var d = 1;
|
||||||
|
for (;c && (a = "PASS") && 0 < --d;);
|
||||||
|
})(b);
|
||||||
|
})(a);
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = "FAIL";
|
||||||
|
!function(c) {
|
||||||
|
var d = 1;
|
||||||
|
for (;c && (a = "PASS") && 0 < --d;);
|
||||||
|
}(a);
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3506_3: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
|
loops: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "FAIL";
|
||||||
|
(function(b) {
|
||||||
|
(function(c) {
|
||||||
|
var d = 1;
|
||||||
|
for (;c && (a = "PASS") && 0 < --d;);
|
||||||
|
})(b);
|
||||||
|
})(a);
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = "FAIL";
|
||||||
|
!function(c) {
|
||||||
|
var d = 1;
|
||||||
|
for (;c && (a = "PASS") && 0 < --d;);
|
||||||
|
}(a);
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3512: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
pure_getters: "strict",
|
||||||
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "PASS";
|
||||||
|
(function(b) {
|
||||||
|
(function() {
|
||||||
|
b <<= this || 1;
|
||||||
|
b.a = "FAIL";
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = "PASS";
|
||||||
|
(function(b) {
|
||||||
|
(function() {
|
||||||
|
(b <<= this || 1).a = "FAIL";
|
||||||
|
})();
|
||||||
|
})(),
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|||||||
@@ -1959,3 +1959,405 @@ issue_3493_ie8: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3523: {
|
||||||
|
mangle = {
|
||||||
|
ie8: false,
|
||||||
|
toplevel: false,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 0, b, c = "FAIL";
|
||||||
|
(function() {
|
||||||
|
var f, g, h, i, j, k, l, m, n, o, p, q, r, s;
|
||||||
|
})();
|
||||||
|
try {
|
||||||
|
throw 0;
|
||||||
|
} catch (t) {
|
||||||
|
(function() {
|
||||||
|
(function t() {
|
||||||
|
c = "PASS";
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
(function e() {
|
||||||
|
try {} catch (t) {}
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 0, b, c = "FAIL";
|
||||||
|
(function() {
|
||||||
|
var c, n, t, o, a, r, f, i, u, h, l, v, y, A;
|
||||||
|
})();
|
||||||
|
try {
|
||||||
|
throw 0;
|
||||||
|
} catch (n) {
|
||||||
|
(function() {
|
||||||
|
(function n() {
|
||||||
|
c = "PASS";
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
(function c() {
|
||||||
|
try {} catch (c) {}
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3523_ie8: {
|
||||||
|
mangle = {
|
||||||
|
ie8: true,
|
||||||
|
toplevel: false,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 0, b, c = "FAIL";
|
||||||
|
(function() {
|
||||||
|
var f, g, h, i, j, k, l, m, n, o, p, q, r, s;
|
||||||
|
})();
|
||||||
|
try {
|
||||||
|
throw 0;
|
||||||
|
} catch (t) {
|
||||||
|
(function() {
|
||||||
|
(function t() {
|
||||||
|
c = "PASS";
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
(function e() {
|
||||||
|
try {} catch (t) {}
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 0, b, c = "FAIL";
|
||||||
|
(function() {
|
||||||
|
var c, t, n, o, a, r, f, i, u, h, e, l, v, y;
|
||||||
|
})();
|
||||||
|
try {
|
||||||
|
throw 0;
|
||||||
|
} catch (t) {
|
||||||
|
(function() {
|
||||||
|
(function t() {
|
||||||
|
c = "PASS";
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
(function e() {
|
||||||
|
try {} catch (t) {}
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3523_toplevel: {
|
||||||
|
mangle = {
|
||||||
|
ie8: false,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 0, b, c = "FAIL";
|
||||||
|
(function() {
|
||||||
|
var f, g, h, i, j, k, l, m, n, o, p, q, r, s;
|
||||||
|
})();
|
||||||
|
try {
|
||||||
|
throw 0;
|
||||||
|
} catch (t) {
|
||||||
|
(function() {
|
||||||
|
(function t() {
|
||||||
|
c = "PASS";
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
(function e() {
|
||||||
|
try {} catch (t) {}
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var c = 0, n, t = "FAIL";
|
||||||
|
(function() {
|
||||||
|
var c, n, t, o, r, a, f, i, u, h, l, v, y, A;
|
||||||
|
})();
|
||||||
|
try {
|
||||||
|
throw 0;
|
||||||
|
} catch (c) {
|
||||||
|
(function() {
|
||||||
|
(function c() {
|
||||||
|
t = "PASS";
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
(function c() {
|
||||||
|
try {} catch (c) {}
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
console.log(t);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3523_ie8_toplevel: {
|
||||||
|
mangle = {
|
||||||
|
ie8: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 0, b, c = "FAIL";
|
||||||
|
(function() {
|
||||||
|
var f, g, h, i, j, k, l, m, n, o, p, q, r, s;
|
||||||
|
})();
|
||||||
|
try {
|
||||||
|
throw 0;
|
||||||
|
} catch (t) {
|
||||||
|
(function() {
|
||||||
|
(function t() {
|
||||||
|
c = "PASS";
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
(function e() {
|
||||||
|
try {} catch (t) {}
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var c = 0, n, t = "FAIL";
|
||||||
|
(function() {
|
||||||
|
var c, n, t, o, r, a, f, i, u, h, l, v, y, A;
|
||||||
|
})();
|
||||||
|
try {
|
||||||
|
throw 0;
|
||||||
|
} catch (o) {
|
||||||
|
(function() {
|
||||||
|
(function o() {
|
||||||
|
t = "PASS";
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
(function r() {
|
||||||
|
try {} catch (o) {}
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
console.log(t);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3523_rename: {
|
||||||
|
rename = true
|
||||||
|
mangle = {
|
||||||
|
ie8: false,
|
||||||
|
toplevel: false,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 0, b, c = "FAIL";
|
||||||
|
(function() {
|
||||||
|
var d, e, f, g, h, i, j, k, l, m, o, p, q, r;
|
||||||
|
})();
|
||||||
|
try {
|
||||||
|
throw 0;
|
||||||
|
} catch (e) {
|
||||||
|
(function() {
|
||||||
|
(function e() {
|
||||||
|
c = "PASS";
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
(function d() {
|
||||||
|
try {
|
||||||
|
} catch (e) {
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 0, b, c = "FAIL";
|
||||||
|
(function() {
|
||||||
|
var c, n, t, o, a, r, f, i, u, h, l, v, y, A;
|
||||||
|
})();
|
||||||
|
try {
|
||||||
|
throw 0;
|
||||||
|
} catch (n) {
|
||||||
|
(function() {
|
||||||
|
(function n() {
|
||||||
|
c = "PASS";
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
(function c() {
|
||||||
|
try {} catch (c) {}
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3523_rename_ie8: {
|
||||||
|
rename = true
|
||||||
|
mangle = {
|
||||||
|
ie8: true,
|
||||||
|
toplevel: false,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 0, b, c = "FAIL";
|
||||||
|
(function() {
|
||||||
|
var d, e, f, g, h, i, j, k, l, m, o, p, q, r;
|
||||||
|
})();
|
||||||
|
try {
|
||||||
|
throw 0;
|
||||||
|
} catch (e) {
|
||||||
|
(function() {
|
||||||
|
(function e() {
|
||||||
|
c = "PASS";
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
(function d() {
|
||||||
|
try {
|
||||||
|
} catch (e) {
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 0, b, c = "FAIL";
|
||||||
|
(function() {
|
||||||
|
var c, n, t, o, a, r, f, i, u, e, h, l, v, y;
|
||||||
|
})();
|
||||||
|
try {
|
||||||
|
throw 0;
|
||||||
|
} catch (e) {
|
||||||
|
(function() {
|
||||||
|
(function n() {
|
||||||
|
c = "PASS";
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
(function d() {
|
||||||
|
try {} catch (e) {}
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3523_rename_toplevel: {
|
||||||
|
rename = true
|
||||||
|
mangle = {
|
||||||
|
ie8: false,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 0, b, c = "FAIL";
|
||||||
|
(function() {
|
||||||
|
var d, e, f, g, h, i, j, k, l, m, o, p, q, r;
|
||||||
|
})();
|
||||||
|
try {
|
||||||
|
throw 0;
|
||||||
|
} catch (e) {
|
||||||
|
(function() {
|
||||||
|
(function e() {
|
||||||
|
c = "PASS";
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
(function d() {
|
||||||
|
try {
|
||||||
|
} catch (e) {
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var c = 0, n, t = "FAIL";
|
||||||
|
(function() {
|
||||||
|
var c, n, t, o, r, a, f, i, u, h, l, v, y, A;
|
||||||
|
})();
|
||||||
|
try {
|
||||||
|
throw 0;
|
||||||
|
} catch (c) {
|
||||||
|
(function() {
|
||||||
|
(function c() {
|
||||||
|
t = "PASS";
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
(function c() {
|
||||||
|
try {} catch (c) {}
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
console.log(t);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3523_rename_ie8_toplevel: {
|
||||||
|
rename = true
|
||||||
|
mangle = {
|
||||||
|
ie8: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 0, b, c = "FAIL";
|
||||||
|
(function() {
|
||||||
|
var d, e, f, g, h, i, j, k, l, m, o, p, q, r;
|
||||||
|
})();
|
||||||
|
try {
|
||||||
|
throw 0;
|
||||||
|
} catch (e) {
|
||||||
|
(function() {
|
||||||
|
(function e() {
|
||||||
|
c = "PASS";
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
(function d() {
|
||||||
|
try {
|
||||||
|
} catch (e) {
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var c = 0, n, t = "FAIL";
|
||||||
|
(function() {
|
||||||
|
var c, n, t, o, r, a, f, i, u, h, l, v, y, A;
|
||||||
|
})();
|
||||||
|
try {
|
||||||
|
throw 0;
|
||||||
|
} catch (o) {
|
||||||
|
(function() {
|
||||||
|
(function o() {
|
||||||
|
t = "PASS";
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
(function r() {
|
||||||
|
try {} catch (o) {}
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
console.log(t);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3542: {
|
||||||
|
options = {
|
||||||
|
ie8: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 0;
|
||||||
|
var b = a++;
|
||||||
|
var c = b && function a() {} || b;
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 0;
|
||||||
|
a++;
|
||||||
|
(function a() {});
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: "1"
|
||||||
|
}
|
||||||
|
|||||||
@@ -51,17 +51,20 @@ comparisons: {
|
|||||||
comparisons: true,
|
comparisons: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
|
var x = "42", y = "0x30";
|
||||||
console.log(
|
console.log(
|
||||||
~x === 42,
|
~x === 42,
|
||||||
x % n === 42
|
x % y === 42
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
|
var x = "42", y = "0x30";
|
||||||
console.log(
|
console.log(
|
||||||
42 == ~x,
|
42 == ~x,
|
||||||
x % n == 42
|
x % y == 42
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
expect_stdout: "false true"
|
||||||
}
|
}
|
||||||
|
|
||||||
evaluate_1: {
|
evaluate_1: {
|
||||||
@@ -103,7 +106,7 @@ evaluate_1: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
evaluate_2: {
|
evaluate_1_unsafe_math: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
unsafe_math: true,
|
unsafe_math: true,
|
||||||
@@ -118,6 +121,8 @@ evaluate_2: {
|
|||||||
1 + x-- + 2 + 3,
|
1 + x-- + 2 + 3,
|
||||||
1 + (x*y + 2) + 3,
|
1 + (x*y + 2) + 3,
|
||||||
1 + (2 + x + 3),
|
1 + (2 + x + 3),
|
||||||
|
1 + (2 + ~x + 3),
|
||||||
|
-y + (2 + ~x + 3),
|
||||||
1 & (2 & x & 3),
|
1 & (2 & x & 3),
|
||||||
1 + (2 + (x |= 0) + 3)
|
1 + (2 + (x |= 0) + 3)
|
||||||
);
|
);
|
||||||
@@ -126,18 +131,138 @@ evaluate_2: {
|
|||||||
console.log(
|
console.log(
|
||||||
x + 1 + 2,
|
x + 1 + 2,
|
||||||
2 * x,
|
2 * x,
|
||||||
3 + +x,
|
+x + 3,
|
||||||
1 + x + 2 + 3,
|
1 + x + 2 + 3,
|
||||||
3 | x,
|
3 | x,
|
||||||
6 + x--,
|
6 + x--,
|
||||||
6 + x*y,
|
x*y + 6,
|
||||||
1 + (2 + x + 3),
|
1 + (2 + x + 3),
|
||||||
|
6 + ~x,
|
||||||
|
5 - y + ~x,
|
||||||
0 & x,
|
0 & x,
|
||||||
6 + (x |= 0)
|
6 + (x |= 0)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
evaluate_2: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
unsafe_math: false,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var x = "42", y = null;
|
||||||
|
[
|
||||||
|
x + 1 + 2,
|
||||||
|
x * 1 * 2,
|
||||||
|
+x + 1 + 2,
|
||||||
|
1 + x + 2 + 3,
|
||||||
|
1 | x | 2 | 3,
|
||||||
|
1 + x-- + 2 + 3,
|
||||||
|
1 + (x*y + 2) + 3,
|
||||||
|
1 + (2 + x + 3),
|
||||||
|
1 + (2 + ~x + 3),
|
||||||
|
-y + (2 + ~x + 3),
|
||||||
|
1 & (2 & x & 3),
|
||||||
|
1 + (2 + (x |= 0) + 3),
|
||||||
|
].forEach(function(n) {
|
||||||
|
console.log(typeof n, n);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var x = "42", y = null;
|
||||||
|
[
|
||||||
|
x + 1 + 2,
|
||||||
|
1 * x * 2,
|
||||||
|
+x + 1 + 2,
|
||||||
|
1 + x + 2 + 3,
|
||||||
|
3 | x,
|
||||||
|
1 + x-- + 2 + 3,
|
||||||
|
x*y + 2 + 1 + 3,
|
||||||
|
1 + (2 + x + 3),
|
||||||
|
2 + ~x + 3 + 1,
|
||||||
|
2 + ~x + 3 - y,
|
||||||
|
0 & x,
|
||||||
|
2 + (x |= 0) + 3 + 1,
|
||||||
|
].forEach(function(n) {
|
||||||
|
console.log(typeof n, n);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"string 4212",
|
||||||
|
"number 84",
|
||||||
|
"number 45",
|
||||||
|
"string 14223",
|
||||||
|
"number 43",
|
||||||
|
"number 48",
|
||||||
|
"number 6",
|
||||||
|
"number 47",
|
||||||
|
"number -36",
|
||||||
|
"number -37",
|
||||||
|
"number 0",
|
||||||
|
"number 47",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
evaluate_2_unsafe_math: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
unsafe_math: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var x = "42", y = null;
|
||||||
|
[
|
||||||
|
x + 1 + 2,
|
||||||
|
x * 1 * 2,
|
||||||
|
+x + 1 + 2,
|
||||||
|
1 + x + 2 + 3,
|
||||||
|
1 | x | 2 | 3,
|
||||||
|
1 + x-- + 2 + 3,
|
||||||
|
1 + (x*y + 2) + 3,
|
||||||
|
1 + (2 + x + 3),
|
||||||
|
1 + (2 + ~x + 3),
|
||||||
|
-y + (2 + ~x + 3),
|
||||||
|
1 & (2 & x & 3),
|
||||||
|
1 + (2 + (x |= 0) + 3),
|
||||||
|
].forEach(function(n) {
|
||||||
|
console.log(typeof n, n);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var x = "42", y = null;
|
||||||
|
[
|
||||||
|
x + 1 + 2,
|
||||||
|
2 * x,
|
||||||
|
+x + 3,
|
||||||
|
1 + x + 2 + 3,
|
||||||
|
3 | x,
|
||||||
|
6 + x--,
|
||||||
|
x*y + 6,
|
||||||
|
1 + (2 + x + 3),
|
||||||
|
6 + ~x,
|
||||||
|
5 + ~x - y,
|
||||||
|
0 & x,
|
||||||
|
6 + (x |= 0),
|
||||||
|
].forEach(function(n) {
|
||||||
|
console.log(typeof n, n);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"string 4212",
|
||||||
|
"number 84",
|
||||||
|
"number 45",
|
||||||
|
"string 14223",
|
||||||
|
"number 43",
|
||||||
|
"number 48",
|
||||||
|
"number 6",
|
||||||
|
"number 47",
|
||||||
|
"number -36",
|
||||||
|
"number -37",
|
||||||
|
"number 0",
|
||||||
|
"number 47",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
evaluate_3: {
|
evaluate_3: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
@@ -148,7 +273,7 @@ evaluate_3: {
|
|||||||
console.log(1 + Number(x) + 2);
|
console.log(1 + Number(x) + 2);
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
console.log(3 + +x);
|
console.log(+x + 3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -182,6 +307,352 @@ evaluate_4: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
evaluate_5: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
unsafe_math: false,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "1";
|
||||||
|
[
|
||||||
|
+a + 2 + 3,
|
||||||
|
+a + 2 - 3,
|
||||||
|
+a - 2 + 3,
|
||||||
|
+a - 2 - 3,
|
||||||
|
2 + +a + 3,
|
||||||
|
2 + +a - 3,
|
||||||
|
2 - +a + 3,
|
||||||
|
2 - +a - 3,
|
||||||
|
2 + 3 + +a,
|
||||||
|
2 + 3 - +a,
|
||||||
|
2 - 3 + +a,
|
||||||
|
2 - 3 - +a,
|
||||||
|
].forEach(function(n) {
|
||||||
|
console.log(typeof n, n);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = "1";
|
||||||
|
[
|
||||||
|
+a + 2 + 3,
|
||||||
|
+a + 2 - 3,
|
||||||
|
a - 2 + 3,
|
||||||
|
a - 2 - 3,
|
||||||
|
+a + 2 + 3,
|
||||||
|
+a + 2 - 3,
|
||||||
|
2 - a + 3,
|
||||||
|
2 - a - 3,
|
||||||
|
+a + 5,
|
||||||
|
5 - a,
|
||||||
|
+a - 1,
|
||||||
|
-1 - a,
|
||||||
|
].forEach(function(n) {
|
||||||
|
console.log(typeof n, n);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"number 6",
|
||||||
|
"number 0",
|
||||||
|
"number 2",
|
||||||
|
"number -4",
|
||||||
|
"number 6",
|
||||||
|
"number 0",
|
||||||
|
"number 4",
|
||||||
|
"number -2",
|
||||||
|
"number 6",
|
||||||
|
"number 4",
|
||||||
|
"number 0",
|
||||||
|
"number -2",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
evaluate_5_unsafe_math: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
unsafe_math: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "1";
|
||||||
|
[
|
||||||
|
+a + 2 + 3,
|
||||||
|
+a + 2 - 3,
|
||||||
|
+a - 2 + 3,
|
||||||
|
+a - 2 - 3,
|
||||||
|
2 + +a + 3,
|
||||||
|
2 + +a - 3,
|
||||||
|
2 - +a + 3,
|
||||||
|
2 - +a - 3,
|
||||||
|
2 + 3 + +a,
|
||||||
|
2 + 3 - +a,
|
||||||
|
2 - 3 + +a,
|
||||||
|
2 - 3 - +a,
|
||||||
|
].forEach(function(n) {
|
||||||
|
console.log(typeof n, n);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = "1";
|
||||||
|
[
|
||||||
|
+a + 5,
|
||||||
|
+a + -1,
|
||||||
|
a - -1,
|
||||||
|
a - 5,
|
||||||
|
+a + 5,
|
||||||
|
+a + -1,
|
||||||
|
5 - a,
|
||||||
|
-1 - a,
|
||||||
|
+a + 5,
|
||||||
|
5 - a,
|
||||||
|
+a - 1,
|
||||||
|
-1 - a,
|
||||||
|
].forEach(function(n) {
|
||||||
|
console.log(typeof n, n);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"number 6",
|
||||||
|
"number 0",
|
||||||
|
"number 2",
|
||||||
|
"number -4",
|
||||||
|
"number 6",
|
||||||
|
"number 0",
|
||||||
|
"number 4",
|
||||||
|
"number -2",
|
||||||
|
"number 6",
|
||||||
|
"number 4",
|
||||||
|
"number 0",
|
||||||
|
"number -2",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
evaluate_6: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
unsafe_math: false,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "1";
|
||||||
|
[
|
||||||
|
-a + 2 + 3,
|
||||||
|
-a + 2 - 3,
|
||||||
|
-a - 2 + 3,
|
||||||
|
-a - 2 - 3,
|
||||||
|
2 + -a + 3,
|
||||||
|
2 + -a - 3,
|
||||||
|
2 - -a + 3,
|
||||||
|
2 - -a - 3,
|
||||||
|
2 + 3 + -a,
|
||||||
|
2 + 3 - -a,
|
||||||
|
2 - 3 + -a,
|
||||||
|
2 - 3 - -a,
|
||||||
|
].forEach(function(n) {
|
||||||
|
console.log(typeof n, n);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = "1";
|
||||||
|
[
|
||||||
|
2 - a + 3,
|
||||||
|
2 - a - 3,
|
||||||
|
-a - 2 + 3,
|
||||||
|
-a - 2 - 3,
|
||||||
|
2 - a + 3,
|
||||||
|
2 - a - 3,
|
||||||
|
2 - -a + 3,
|
||||||
|
2 - -a - 3,
|
||||||
|
5 - a,
|
||||||
|
5 - -a,
|
||||||
|
-1 - a,
|
||||||
|
-1 - -a,
|
||||||
|
].forEach(function(n) {
|
||||||
|
console.log(typeof n, n);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"number 4",
|
||||||
|
"number -2",
|
||||||
|
"number 0",
|
||||||
|
"number -6",
|
||||||
|
"number 4",
|
||||||
|
"number -2",
|
||||||
|
"number 6",
|
||||||
|
"number 0",
|
||||||
|
"number 4",
|
||||||
|
"number 6",
|
||||||
|
"number -2",
|
||||||
|
"number 0",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
evaluate_6_unsafe_math: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
unsafe_math: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "1";
|
||||||
|
[
|
||||||
|
-a + 2 + 3,
|
||||||
|
-a + 2 - 3,
|
||||||
|
-a - 2 + 3,
|
||||||
|
-a - 2 - 3,
|
||||||
|
2 + -a + 3,
|
||||||
|
2 + -a - 3,
|
||||||
|
2 - -a + 3,
|
||||||
|
2 - -a - 3,
|
||||||
|
2 + 3 + -a,
|
||||||
|
2 + 3 - -a,
|
||||||
|
2 - 3 + -a,
|
||||||
|
2 - 3 - -a,
|
||||||
|
].forEach(function(n) {
|
||||||
|
console.log(typeof n, n);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = "1";
|
||||||
|
[
|
||||||
|
5 - a,
|
||||||
|
-1 - a,
|
||||||
|
-a - -1,
|
||||||
|
-a - 5,
|
||||||
|
5 - a,
|
||||||
|
-1 - a,
|
||||||
|
5 - -a,
|
||||||
|
-1 - -a,
|
||||||
|
5 - a,
|
||||||
|
5 - -a,
|
||||||
|
-1 - a,
|
||||||
|
-1 - -a,
|
||||||
|
].forEach(function(n) {
|
||||||
|
console.log(typeof n, n);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"number 4",
|
||||||
|
"number -2",
|
||||||
|
"number 0",
|
||||||
|
"number -6",
|
||||||
|
"number 4",
|
||||||
|
"number -2",
|
||||||
|
"number 6",
|
||||||
|
"number 0",
|
||||||
|
"number 4",
|
||||||
|
"number 6",
|
||||||
|
"number -2",
|
||||||
|
"number 0",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
evaluate_7: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
unsafe_math: false,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var x = "42", y;
|
||||||
|
[
|
||||||
|
+x + 2 + (3 + !y),
|
||||||
|
+x + 2 + (3 - !y),
|
||||||
|
+x + 2 - (3 + !y),
|
||||||
|
+x + 2 - (3 - !y),
|
||||||
|
+x - 2 + (3 + !y),
|
||||||
|
+x - 2 + (3 - !y),
|
||||||
|
+x - 2 - (3 + !y),
|
||||||
|
+x - 2 - (3 - !y),
|
||||||
|
].forEach(function(n) {
|
||||||
|
console.log(typeof n, n);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var x = "42", y;
|
||||||
|
[
|
||||||
|
+x + 2 + (3 + !y),
|
||||||
|
+x + 2 + (3 - !y),
|
||||||
|
+x + 2 - (3 + !y),
|
||||||
|
+x + 2 - (3 - !y),
|
||||||
|
x - 2 + (3 + !y),
|
||||||
|
x - 2 + (3 - !y),
|
||||||
|
x - 2 - (3 + !y),
|
||||||
|
x - 2 - (3 - !y),
|
||||||
|
].forEach(function(n) {
|
||||||
|
console.log(typeof n, n);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"number 48",
|
||||||
|
"number 46",
|
||||||
|
"number 40",
|
||||||
|
"number 42",
|
||||||
|
"number 44",
|
||||||
|
"number 42",
|
||||||
|
"number 36",
|
||||||
|
"number 38",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
evaluate_7_unsafe_math: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
unsafe_math: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var x = "42", y;
|
||||||
|
[
|
||||||
|
+x + 2 + (3 + !y),
|
||||||
|
+x + 2 + (3 - !y),
|
||||||
|
+x + 2 - (3 + !y),
|
||||||
|
+x + 2 - (3 - !y),
|
||||||
|
+x - 2 + (3 + !y),
|
||||||
|
+x - 2 + (3 - !y),
|
||||||
|
+x - 2 - (3 + !y),
|
||||||
|
+x - 2 - (3 - !y),
|
||||||
|
].forEach(function(n) {
|
||||||
|
console.log(typeof n, n);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var x = "42", y;
|
||||||
|
[
|
||||||
|
+x + 5 + !y,
|
||||||
|
+x + 5 - !y,
|
||||||
|
+x + -1 - !y,
|
||||||
|
+x + -1 + !y,
|
||||||
|
x - -1 + !y,
|
||||||
|
x - -1 - !y,
|
||||||
|
x - 5 - !y,
|
||||||
|
x - 5 + !y,
|
||||||
|
].forEach(function(n) {
|
||||||
|
console.log(typeof n, n);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"number 48",
|
||||||
|
"number 46",
|
||||||
|
"number 40",
|
||||||
|
"number 42",
|
||||||
|
"number 44",
|
||||||
|
"number 42",
|
||||||
|
"number 36",
|
||||||
|
"number 38",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
NaN_redefined: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
unsafe_math: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var NaN;
|
||||||
|
console.log(1 / (0 / 0));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var NaN;
|
||||||
|
console.log(0 / 0);
|
||||||
|
}
|
||||||
|
expect_stdout: "NaN"
|
||||||
|
}
|
||||||
|
|
||||||
issue_1710: {
|
issue_1710: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
@@ -230,3 +701,219 @@ unary_binary_parenthesis: {
|
|||||||
}
|
}
|
||||||
expect_stdout: true
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3531_1: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
unsafe_math: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "1";
|
||||||
|
console.log(typeof (a + 1 - .1 - .1 - .1));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = "1";
|
||||||
|
console.log(typeof (a + 1 - .3));
|
||||||
|
}
|
||||||
|
expect_stdout: "number"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3531_2: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
unsafe_math: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(1 - (2 - {}));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(-1 + +{});
|
||||||
|
}
|
||||||
|
expect_stdout: "NaN"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3531_3: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
unsafe_math: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "3";
|
||||||
|
console.log(1 - (2 + a));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = "3";
|
||||||
|
console.log(1 - (2 + a));
|
||||||
|
}
|
||||||
|
expect_stdout: "-22"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3536: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
unsafe_math: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 100, b = 10;
|
||||||
|
var c = --a + ("23" - (b++, 1));
|
||||||
|
console.log(typeof c, a, b, c);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 100, b = 10;
|
||||||
|
var c = --a + ("23" - (b++, 1));
|
||||||
|
console.log(typeof c, a, b, c);
|
||||||
|
}
|
||||||
|
expect_stdout: "number 99 11 121"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3539: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
unsafe_math: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = -0 + -"";
|
||||||
|
console.log(0/a, 1/a, -1/a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = -0;
|
||||||
|
console.log(0/a, 1/a, -1/a);
|
||||||
|
}
|
||||||
|
expect_stdout: "NaN -Infinity Infinity"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3547_1: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
unsafe_math: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
[
|
||||||
|
1/0 + "1" + 0,
|
||||||
|
1/0 + "1" - 0,
|
||||||
|
1/0 - "1" + 0,
|
||||||
|
1/0 - "1" - 0,
|
||||||
|
].forEach(function(n) {
|
||||||
|
console.log(typeof n, n);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
[
|
||||||
|
1/0 + "10",
|
||||||
|
NaN,
|
||||||
|
1/0,
|
||||||
|
1/0,
|
||||||
|
].forEach(function(n) {
|
||||||
|
console.log(typeof n, n);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"string Infinity10",
|
||||||
|
"number NaN",
|
||||||
|
"number Infinity",
|
||||||
|
"number Infinity",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3547_2: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
unsafe_math: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
[
|
||||||
|
"1" + 1/0 + 0,
|
||||||
|
"1" + 1/0 - 0,
|
||||||
|
"1" - 1/0 + 0,
|
||||||
|
"1" - 1/0 - 0,
|
||||||
|
].forEach(function(n) {
|
||||||
|
console.log(typeof n, n);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
[
|
||||||
|
"1" + 1/0 + 0,
|
||||||
|
NaN,
|
||||||
|
-1/0,
|
||||||
|
-1/0,
|
||||||
|
].forEach(function(n) {
|
||||||
|
console.log(typeof n, n);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"string 1Infinity0",
|
||||||
|
"number NaN",
|
||||||
|
"number -Infinity",
|
||||||
|
"number -Infinity",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3547_3: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
unsafe_math: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "3";
|
||||||
|
[
|
||||||
|
a + "2" + 1,
|
||||||
|
a + "2" - 1,
|
||||||
|
a - "2" + 1,
|
||||||
|
a - "2" - 1,
|
||||||
|
].forEach(function(n) {
|
||||||
|
console.log(typeof n, n);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = "3";
|
||||||
|
[
|
||||||
|
a + "21",
|
||||||
|
a + "2" - 1,
|
||||||
|
a - 1,
|
||||||
|
a - "2" - 1,
|
||||||
|
].forEach(function(n) {
|
||||||
|
console.log(typeof n, n);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"string 321",
|
||||||
|
"number 31",
|
||||||
|
"number 2",
|
||||||
|
"number 0",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_3547_4: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
unsafe_math: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "2";
|
||||||
|
[
|
||||||
|
"3" + a + 1,
|
||||||
|
"3" + a - 1,
|
||||||
|
"3" - a + 1,
|
||||||
|
"3" - a - 1,
|
||||||
|
].forEach(function(n) {
|
||||||
|
console.log(typeof n, n);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = "2";
|
||||||
|
[
|
||||||
|
"3" + a + 1,
|
||||||
|
"3" + a - 1,
|
||||||
|
"3" - a + 1,
|
||||||
|
2 - a,
|
||||||
|
].forEach(function(n) {
|
||||||
|
console.log(typeof n, n);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"string 321",
|
||||||
|
"number 31",
|
||||||
|
"number 2",
|
||||||
|
"number 0",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|||||||
223
test/compress/objects.js
Normal file
223
test/compress/objects.js
Normal file
@@ -0,0 +1,223 @@
|
|||||||
|
duplicate_key: {
|
||||||
|
options = {
|
||||||
|
objects: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var o = {
|
||||||
|
a: 1,
|
||||||
|
b: 2,
|
||||||
|
a: 3,
|
||||||
|
};
|
||||||
|
for (var k in o)
|
||||||
|
console.log(k, o[k]);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var o = {
|
||||||
|
a: 3,
|
||||||
|
b: 2,
|
||||||
|
};
|
||||||
|
for (var k in o)
|
||||||
|
console.log(k, o[k]);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"a 3",
|
||||||
|
"b 2",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
duplicate_key_strict: {
|
||||||
|
options = {
|
||||||
|
objects: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
var o = {
|
||||||
|
a: 1,
|
||||||
|
b: 2,
|
||||||
|
a: 3,
|
||||||
|
};
|
||||||
|
for (var k in o)
|
||||||
|
console.log(k, o[k]);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
var o = {
|
||||||
|
a: 1,
|
||||||
|
b: 2,
|
||||||
|
a: 3,
|
||||||
|
};
|
||||||
|
for (var k in o)
|
||||||
|
console.log(k, o[k]);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
duplicate_key_side_effect: {
|
||||||
|
options = {
|
||||||
|
objects: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var o = {
|
||||||
|
a: 1,
|
||||||
|
b: o = 2,
|
||||||
|
a: 3,
|
||||||
|
};
|
||||||
|
for (var k in o)
|
||||||
|
console.log(k, o[k]);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var o = {
|
||||||
|
a: 1,
|
||||||
|
b: o = 2,
|
||||||
|
a: 3,
|
||||||
|
};
|
||||||
|
for (var k in o)
|
||||||
|
console.log(k, o[k]);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"a 3",
|
||||||
|
"b 2",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
duplicate_key_with_accessor: {
|
||||||
|
options = {
|
||||||
|
objects: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
[
|
||||||
|
{
|
||||||
|
a: 0,
|
||||||
|
b: 1,
|
||||||
|
a: 2,
|
||||||
|
set b(v) {},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
a: 3,
|
||||||
|
b: 4,
|
||||||
|
get a() {
|
||||||
|
return 5;
|
||||||
|
},
|
||||||
|
a: 6,
|
||||||
|
b: 7,
|
||||||
|
a: 8,
|
||||||
|
b: 9,
|
||||||
|
},
|
||||||
|
].forEach(function(o) {
|
||||||
|
for (var k in o)
|
||||||
|
console.log(k, o[k]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
[
|
||||||
|
{
|
||||||
|
a: 2,
|
||||||
|
b: 1,
|
||||||
|
set b(v) {},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
a: 3,
|
||||||
|
b: 4,
|
||||||
|
get a() {
|
||||||
|
return 5;
|
||||||
|
},
|
||||||
|
a: 8,
|
||||||
|
b: 9,
|
||||||
|
},
|
||||||
|
].forEach(function(o) {
|
||||||
|
for (var k in o)
|
||||||
|
console.log(k, o[k]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_object_repeated: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
objects: true,
|
||||||
|
reduce_funcs: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var o = { a: { b: 1 }, a: 1 };
|
||||||
|
console.log(
|
||||||
|
o + 1,
|
||||||
|
o.a + 1,
|
||||||
|
o.b + 1,
|
||||||
|
o.a.b + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var o = { a: 1 };
|
||||||
|
console.log(
|
||||||
|
o + 1,
|
||||||
|
2,
|
||||||
|
o.b + 1,
|
||||||
|
NaN
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
numeric_literal: {
|
||||||
|
options = {
|
||||||
|
objects: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
mangle = {
|
||||||
|
properties: true,
|
||||||
|
}
|
||||||
|
beautify = {
|
||||||
|
beautify: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var obj = {
|
||||||
|
0: 0,
|
||||||
|
"-0": 1,
|
||||||
|
42: 2,
|
||||||
|
"42": 3,
|
||||||
|
0x25: 4,
|
||||||
|
"0x25": 5,
|
||||||
|
1E42: 6,
|
||||||
|
"1E42": 7,
|
||||||
|
"1e+42": 8,
|
||||||
|
};
|
||||||
|
console.log(obj[-0], obj[-""], obj["-0"]);
|
||||||
|
console.log(obj[42], obj["42"]);
|
||||||
|
console.log(obj[0x25], obj["0x25"], obj[37], obj["37"]);
|
||||||
|
console.log(obj[1E42], obj["1E42"], obj["1e+42"]);
|
||||||
|
}
|
||||||
|
expect_exact: [
|
||||||
|
'var obj = {',
|
||||||
|
' 0: 0,',
|
||||||
|
' "-0": 1,',
|
||||||
|
' 42: 3,',
|
||||||
|
' 37: 4,',
|
||||||
|
' o: 5,',
|
||||||
|
' 1e42: 8,',
|
||||||
|
' b: 7',
|
||||||
|
'};',
|
||||||
|
'',
|
||||||
|
'console.log(obj[-0], obj[-""], obj["-0"]);',
|
||||||
|
'',
|
||||||
|
'console.log(obj[42], obj["42"]);',
|
||||||
|
'',
|
||||||
|
'console.log(obj[37], obj["o"], obj[37], obj["37"]);',
|
||||||
|
'',
|
||||||
|
'console.log(obj[1e42], obj["b"], obj["1e+42"]);',
|
||||||
|
]
|
||||||
|
expect_stdout: [
|
||||||
|
"0 0 1",
|
||||||
|
"3 3",
|
||||||
|
"4 5 4 4",
|
||||||
|
"8 7 8",
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -1193,6 +1193,7 @@ issue_3427: {
|
|||||||
assignments: true,
|
assignments: true,
|
||||||
collapse_vars: true,
|
collapse_vars: true,
|
||||||
inline: true,
|
inline: true,
|
||||||
|
passes: 2,
|
||||||
pure_getters: "strict",
|
pure_getters: "strict",
|
||||||
sequences: true,
|
sequences: true,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
@@ -1206,4 +1207,5 @@ issue_3427: {
|
|||||||
})(a || (a = {}));
|
})(a || (a = {}));
|
||||||
}
|
}
|
||||||
expect: {}
|
expect: {}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4947,7 +4947,7 @@ defun_single_use_loop: {
|
|||||||
unused: true,
|
unused: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
for (var x, i = 2; --i >= 0; ) {
|
for (var x, i = 2; --i >= 0;) {
|
||||||
var y = x;
|
var y = x;
|
||||||
x = f;
|
x = f;
|
||||||
console.log(x === y);
|
console.log(x === y);
|
||||||
@@ -4955,7 +4955,7 @@ defun_single_use_loop: {
|
|||||||
function f() {};
|
function f() {};
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
for (var x, i = 2; --i >= 0; ) {
|
for (var x, i = 2; --i >= 0;) {
|
||||||
var y = x;
|
var y = x;
|
||||||
x = f;
|
x = f;
|
||||||
console.log(x === y);
|
console.log(x === y);
|
||||||
@@ -6609,10 +6609,10 @@ issues_3267_1: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
!function(i) {
|
!function(i) {
|
||||||
if (i)
|
if (Object())
|
||||||
return console.log("PASS");
|
return console.log("PASS");
|
||||||
throw "FAIL";
|
throw "FAIL";
|
||||||
}(Object());
|
}();
|
||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
@@ -6752,3 +6752,31 @@ issue_3377: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "42"
|
expect_stdout: "42"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3509: {
|
||||||
|
options = {
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function a() {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
} catch (a) {
|
||||||
|
var a;
|
||||||
|
}
|
||||||
|
a();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
try {
|
||||||
|
} catch (a) {
|
||||||
|
var a;
|
||||||
|
}
|
||||||
|
(function() {
|
||||||
|
console.log("PASS");
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|||||||
@@ -295,3 +295,145 @@ issue_2728_6: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "function undefined"
|
expect_stdout: "function undefined"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typeof_defined_1: {
|
||||||
|
options = {
|
||||||
|
side_effects: true,
|
||||||
|
typeofs: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"undefined" == typeof A && A;
|
||||||
|
"undefined" != typeof A && A;
|
||||||
|
"undefined" == typeof A || A;
|
||||||
|
"undefined" != typeof A || A;
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"undefined" == typeof A && A;
|
||||||
|
"undefined" != typeof A || A;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
typeof_defined_2: {
|
||||||
|
options = {
|
||||||
|
side_effects: true,
|
||||||
|
typeofs: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"function" == typeof A && A;
|
||||||
|
"function" != typeof A && A;
|
||||||
|
"function" == typeof A || A;
|
||||||
|
"function" != typeof A || A;
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"function" != typeof A && A;
|
||||||
|
"function" == typeof A || A;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
typeof_defined_3: {
|
||||||
|
options = {
|
||||||
|
side_effects: true,
|
||||||
|
typeofs: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"undefined" == typeof A && "undefined" == typeof B && (A, B);
|
||||||
|
"undefined" == typeof A && "undefined" != typeof B && (A, B);
|
||||||
|
"undefined" != typeof A && "undefined" == typeof B && (A, B);
|
||||||
|
"undefined" != typeof A && "undefined" != typeof B && (A, B);
|
||||||
|
"undefined" == typeof A && "undefined" == typeof B || (A, B);
|
||||||
|
"undefined" == typeof A && "undefined" != typeof B || (A, B);
|
||||||
|
"undefined" != typeof A && "undefined" == typeof B || (A, B);
|
||||||
|
"undefined" != typeof A && "undefined" != typeof B || (A, B);
|
||||||
|
"undefined" == typeof A || "undefined" == typeof B && (A, B);
|
||||||
|
"undefined" == typeof A || "undefined" != typeof B && (A, B);
|
||||||
|
"undefined" != typeof A || "undefined" == typeof B && (A, B);
|
||||||
|
"undefined" != typeof A || "undefined" != typeof B && (A, B);
|
||||||
|
"undefined" == typeof A || "undefined" == typeof B || (A, B);
|
||||||
|
"undefined" == typeof A || "undefined" != typeof B || (A, B);
|
||||||
|
"undefined" != typeof A || "undefined" == typeof B || (A, B);
|
||||||
|
"undefined" != typeof A || "undefined" != typeof B || (A, B);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"undefined" == typeof A && "undefined" == typeof B && (A, B);
|
||||||
|
"undefined" == typeof A && "undefined" != typeof B && A;
|
||||||
|
"undefined" != typeof A && "undefined" == typeof B && B;
|
||||||
|
"undefined" == typeof A && "undefined" == typeof B || (A, B);
|
||||||
|
"undefined" == typeof A && "undefined" != typeof B || (A, B);
|
||||||
|
"undefined" != typeof A && "undefined" == typeof B || (A, B);
|
||||||
|
"undefined" != typeof A && "undefined" != typeof B || (A, B);
|
||||||
|
"undefined" == typeof A || "undefined" == typeof B && B;
|
||||||
|
"undefined" != typeof A || "undefined" == typeof B && (A, B);
|
||||||
|
"undefined" != typeof A || "undefined" != typeof B && A;
|
||||||
|
"undefined" == typeof A || "undefined" != typeof B || B;
|
||||||
|
"undefined" != typeof A || "undefined" == typeof B || A;
|
||||||
|
"undefined" != typeof A || "undefined" != typeof B || (A, B);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
typeof_defined_4: {
|
||||||
|
options = {
|
||||||
|
side_effects: true,
|
||||||
|
typeofs: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"object" == typeof A && "object" == typeof B && (A, B);
|
||||||
|
"object" == typeof A && "object" != typeof B && (A, B);
|
||||||
|
"object" != typeof A && "object" == typeof B && (A, B);
|
||||||
|
"object" != typeof A && "object" != typeof B && (A, B);
|
||||||
|
"object" == typeof A && "object" == typeof B || (A, B);
|
||||||
|
"object" == typeof A && "object" != typeof B || (A, B);
|
||||||
|
"object" != typeof A && "object" == typeof B || (A, B);
|
||||||
|
"object" != typeof A && "object" != typeof B || (A, B);
|
||||||
|
"object" == typeof A || "object" == typeof B && (A, B);
|
||||||
|
"object" == typeof A || "object" != typeof B && (A, B);
|
||||||
|
"object" != typeof A || "object" == typeof B && (A, B);
|
||||||
|
"object" != typeof A || "object" != typeof B && (A, B);
|
||||||
|
"object" == typeof A || "object" == typeof B || (A, B);
|
||||||
|
"object" == typeof A || "object" != typeof B || (A, B);
|
||||||
|
"object" != typeof A || "object" == typeof B || (A, B);
|
||||||
|
"object" != typeof A || "object" != typeof B || (A, B);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"object" == typeof A && "object" != typeof B && B;
|
||||||
|
"object" != typeof A && "object" == typeof B && A;
|
||||||
|
"object" != typeof A && "object" != typeof B && (A, B);
|
||||||
|
"object" == typeof A && "object" == typeof B || (A, B);
|
||||||
|
"object" == typeof A && "object" != typeof B || (A, B);
|
||||||
|
"object" != typeof A && "object" == typeof B || (A, B);
|
||||||
|
"object" != typeof A && "object" != typeof B || (A, B);
|
||||||
|
"object" == typeof A || "object" == typeof B && A;
|
||||||
|
"object" == typeof A || "object" != typeof B && (A, B);
|
||||||
|
"object" != typeof A || "object" != typeof B && B;
|
||||||
|
"object" == typeof A || "object" == typeof B || (A, B);
|
||||||
|
"object" == typeof A || "object" != typeof B || A;
|
||||||
|
"object" != typeof A || "object" == typeof B || B;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
emberjs_global: {
|
||||||
|
options = {
|
||||||
|
comparisons: true,
|
||||||
|
conditionals: true,
|
||||||
|
if_return: true,
|
||||||
|
passes: 2,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
typeofs: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a;
|
||||||
|
if (typeof A === "object") {
|
||||||
|
a = A;
|
||||||
|
} else if (typeof B === "object") {
|
||||||
|
a = B;
|
||||||
|
} else {
|
||||||
|
throw new Error("PASS");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
if ("object" != typeof A && "object" != typeof B)
|
||||||
|
throw new Error("PASS");
|
||||||
|
}
|
||||||
|
expect_stdout: Error("PASS")
|
||||||
|
}
|
||||||
|
|||||||
@@ -48,7 +48,8 @@ describe("comments", function() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Should handle comment within return correctly", function() {
|
describe("comment within return", function() {
|
||||||
|
it("Should handle leading return", function() {
|
||||||
var result = UglifyJS.minify([
|
var result = UglifyJS.minify([
|
||||||
"function unequal(x, y) {",
|
"function unequal(x, y) {",
|
||||||
" return (",
|
" return (",
|
||||||
@@ -75,7 +76,36 @@ describe("comments", function() {
|
|||||||
].join("\n"));
|
].join("\n"));
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Should handle comment folded into return correctly", function() {
|
it("Should handle trailing return", function() {
|
||||||
|
var result = UglifyJS.minify([
|
||||||
|
"function unequal(x) {",
|
||||||
|
" var y;",
|
||||||
|
" return (",
|
||||||
|
" // Either one",
|
||||||
|
" x < y",
|
||||||
|
" ||",
|
||||||
|
" y < x",
|
||||||
|
" );",
|
||||||
|
"}",
|
||||||
|
].join("\n"), {
|
||||||
|
compress: false,
|
||||||
|
mangle: false,
|
||||||
|
output: {
|
||||||
|
beautify: true,
|
||||||
|
comments: "all",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (result.error) throw result.error;
|
||||||
|
assert.strictEqual(result.code, [
|
||||||
|
"function unequal(x) {",
|
||||||
|
" var y;",
|
||||||
|
" // Either one",
|
||||||
|
" return x < y || y < x;",
|
||||||
|
"}",
|
||||||
|
].join("\n"));
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should handle comment folded into return", function() {
|
||||||
var result = UglifyJS.minify([
|
var result = UglifyJS.minify([
|
||||||
"function f() {",
|
"function f() {",
|
||||||
" /* boo */ x();",
|
" /* boo */ x();",
|
||||||
@@ -96,6 +126,7 @@ describe("comments", function() {
|
|||||||
"}",
|
"}",
|
||||||
].join("\n"));
|
].join("\n"));
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it("Should not drop comments after first OutputStream", function() {
|
it("Should not drop comments after first OutputStream", function() {
|
||||||
var code = "/* boo */\nx();";
|
var code = "/* boo */\nx();";
|
||||||
@@ -228,6 +259,30 @@ describe("comments", function() {
|
|||||||
assert.strictEqual(result.code, code);
|
assert.strictEqual(result.code, code);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("Should handle comments around parenthesis correctly", function() {
|
||||||
|
var code = [
|
||||||
|
"a();",
|
||||||
|
"/* foo */",
|
||||||
|
"(b())",
|
||||||
|
"/* bar */",
|
||||||
|
"c();",
|
||||||
|
].join("\n");
|
||||||
|
var result = UglifyJS.minify(code, {
|
||||||
|
compress: false,
|
||||||
|
mangle: false,
|
||||||
|
output: {
|
||||||
|
comments: "all",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (result.error) throw result.error;
|
||||||
|
assert.strictEqual(result.code, [
|
||||||
|
"a();",
|
||||||
|
"/* foo */",
|
||||||
|
"b()",
|
||||||
|
"/* bar */;c();",
|
||||||
|
].join("\n"));
|
||||||
|
});
|
||||||
|
|
||||||
it("Should preserve comments around IIFE", function() {
|
it("Should preserve comments around IIFE", function() {
|
||||||
var result = UglifyJS.minify("/*a*/(/*b*/function(){/*c*/}/*d*/)/*e*/();", {
|
var result = UglifyJS.minify("/*a*/(/*b*/function(){/*c*/}/*d*/)/*e*/();", {
|
||||||
compress: false,
|
compress: false,
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
setInterval(function() {
|
||||||
|
process.stderr.write("\0");
|
||||||
|
}, 8 * 60 * 1000).unref();
|
||||||
require("./run")([
|
require("./run")([
|
||||||
"-b",
|
"-b",
|
||||||
"-b braces",
|
"-b braces",
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
39
test/ufuzz/job.js
Normal file
39
test/ufuzz/job.js
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
var child_process = require("child_process");
|
||||||
|
|
||||||
|
var ping = 5 * 60 * 1000;
|
||||||
|
var period = +process.argv[2];
|
||||||
|
var endTime = Date.now() + period;
|
||||||
|
for (var i = 0; i < 2; i++) spawn(endTime);
|
||||||
|
|
||||||
|
function spawn(endTime) {
|
||||||
|
var child = child_process.spawn("node", [
|
||||||
|
"--max-old-space-size=2048",
|
||||||
|
"test/ufuzz"
|
||||||
|
], {
|
||||||
|
stdio: [ "ignore", "pipe", "pipe" ]
|
||||||
|
}).on("exit", respawn);
|
||||||
|
var line = "";
|
||||||
|
child.stdout.on("data", function(data) {
|
||||||
|
line += data;
|
||||||
|
});
|
||||||
|
child.stderr.once("data", function() {
|
||||||
|
process.exitCode = 1;
|
||||||
|
}).pipe(process.stdout);
|
||||||
|
var keepAlive = setInterval(function() {
|
||||||
|
var end = line.lastIndexOf("\r");
|
||||||
|
console.log(line.slice(line.lastIndexOf("\r", end - 1) + 1, end));
|
||||||
|
line = line.slice(end + 1);
|
||||||
|
}, ping);
|
||||||
|
var timer = setTimeout(function() {
|
||||||
|
clearInterval(keepAlive);
|
||||||
|
child.removeListener("exit", respawn);
|
||||||
|
child.kill();
|
||||||
|
}, endTime - Date.now());
|
||||||
|
|
||||||
|
function respawn() {
|
||||||
|
console.log(line);
|
||||||
|
clearInterval(keepAlive);
|
||||||
|
clearTimeout(timer);
|
||||||
|
spawn(endTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,13 +6,9 @@ var url = require("url");
|
|||||||
|
|
||||||
var period = 45 * 60 * 1000;
|
var period = 45 * 60 * 1000;
|
||||||
var wait = 2 * 60 * 1000;
|
var wait = 2 * 60 * 1000;
|
||||||
var ping = 5 * 60 * 1000;
|
if (process.argv.length > 2) {
|
||||||
if (process.argv[2] == "run") {
|
|
||||||
var endTime = Date.now() + period;
|
|
||||||
for (var i = 0; i < 2; i++) spawn(endTime);
|
|
||||||
} else if (process.argv.length > 2) {
|
|
||||||
var token = process.argv[2];
|
var token = process.argv[2];
|
||||||
var branch = process.argv[3] || "v" + require("../package.json").version;
|
var branch = process.argv[3] || "v" + require("../../package.json").version;
|
||||||
var repository = encodeURIComponent(process.argv[4] || "mishoo/UglifyJS2");
|
var repository = encodeURIComponent(process.argv[4] || "mishoo/UglifyJS2");
|
||||||
var concurrency = process.argv[5] || 1;
|
var concurrency = process.argv[5] || 1;
|
||||||
var platform = process.argv[6] || "latest";
|
var platform = process.argv[6] || "latest";
|
||||||
@@ -38,44 +34,11 @@ if (process.argv[2] == "run") {
|
|||||||
config: {
|
config: {
|
||||||
cache: false,
|
cache: false,
|
||||||
env: "NODE=" + platform,
|
env: "NODE=" + platform,
|
||||||
script: "node test/travis-ufuzz run"
|
script: "node test/ufuzz/job " + period
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
})();
|
})();
|
||||||
} else {
|
} else {
|
||||||
console.log("Usage: test/travis-ufuzz.js <token> [branch] [repository] [concurrency] [platform]");
|
console.log("Usage: test/ufuzz/travis.js <token> [branch] [repository] [concurrency] [platform]");
|
||||||
}
|
|
||||||
|
|
||||||
function spawn(endTime) {
|
|
||||||
var child = child_process.spawn("node", [
|
|
||||||
"--max-old-space-size=2048",
|
|
||||||
"test/ufuzz"
|
|
||||||
], {
|
|
||||||
stdio: [ "ignore", "pipe", "pipe" ]
|
|
||||||
}).on("exit", respawn);
|
|
||||||
var line = "";
|
|
||||||
child.stdout.on("data", function(data) {
|
|
||||||
line += data;
|
|
||||||
});
|
|
||||||
child.stderr.on("data", function() {
|
|
||||||
process.exitCode = 1;
|
|
||||||
}).pipe(process.stdout);
|
|
||||||
var keepAlive = setInterval(function() {
|
|
||||||
var end = line.lastIndexOf("\r");
|
|
||||||
console.log(line.slice(line.lastIndexOf("\r", end - 1) + 1, end));
|
|
||||||
line = line.slice(end + 1);
|
|
||||||
}, ping);
|
|
||||||
var timer = setTimeout(function() {
|
|
||||||
clearInterval(keepAlive);
|
|
||||||
child.removeListener("exit", respawn);
|
|
||||||
child.kill();
|
|
||||||
}, endTime - Date.now());
|
|
||||||
|
|
||||||
function respawn() {
|
|
||||||
console.log(line);
|
|
||||||
clearInterval(keepAlive);
|
|
||||||
clearTimeout(timer);
|
|
||||||
spawn(endTime);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user