Compare commits
53 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
6b4886c908 | ||
|
|
0201cb4b52 | ||
|
|
cd072317d0 | ||
|
|
0785a15ace | ||
|
|
b1279a46d9 | ||
|
|
b571619d31 | ||
|
|
7b5350b459 | ||
|
|
1549db70e6 | ||
|
|
8ff9a3c8fb | ||
|
|
91cae51d8f | ||
|
|
8af2f5fbcf | ||
|
|
86a8016323 | ||
|
|
009dcdae01 | ||
|
|
f86f615d83 | ||
|
|
d3d1d11926 | ||
|
|
736019b767 | ||
|
|
a39bdb5840 | ||
|
|
e8ab0a44b2 | ||
|
|
c3ca293e6b | ||
|
|
516b67a43b | ||
|
|
eba3a37bb5 | ||
|
|
6d57ca1a59 | ||
|
|
3320251b4b | ||
|
|
33c94d3bd9 | ||
|
|
b18f717b46 | ||
|
|
a0d4b648bb | ||
|
|
6db880e16d |
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
|
||||
@@ -1,6 +1,6 @@
|
||||
cache:
|
||||
directories: tmp
|
||||
language: generic
|
||||
language: shell
|
||||
matrix:
|
||||
fast_finish: true
|
||||
env:
|
||||
|
||||
12
lib/ast.js
12
lib/ast.js
@@ -837,11 +837,10 @@ var AST_String = DEFNODE("String", "value quote", {
|
||||
}
|
||||
}, AST_Constant);
|
||||
|
||||
var AST_Number = DEFNODE("Number", "value literal", {
|
||||
var AST_Number = DEFNODE("Number", "value", {
|
||||
$documentation: "A number literal",
|
||||
$propdoc: {
|
||||
value: "[number] the numeric value",
|
||||
literal: "[string] numeric value as string (optional)"
|
||||
}
|
||||
}, AST_Constant);
|
||||
|
||||
@@ -980,6 +979,15 @@ TreeWalker.prototype = {
|
||||
|| p instanceof AST_Conditional
|
||||
|| p.tail_node() === self) {
|
||||
self = p;
|
||||
} else if (p instanceof AST_Return) {
|
||||
var fn;
|
||||
do {
|
||||
fn = this.parent(++i);
|
||||
if (!fn) return false;
|
||||
} while (!(fn instanceof AST_Lambda));
|
||||
if (fn.name) return false;
|
||||
self = this.parent(++i);
|
||||
if (!self || self.TYPE != "Call" || self.expression !== fn) return false;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
359
lib/compress.js
359
lib/compress.js
@@ -888,16 +888,17 @@ merge(Compressor.prototype, {
|
||||
});
|
||||
|
||||
AST_SymbolRef.DEFMETHOD("is_immutable", function() {
|
||||
var orig = this.definition().orig;
|
||||
return orig.length == 1 && orig[0] instanceof AST_SymbolLambda;
|
||||
var def = this.definition();
|
||||
if (def.orig.length != 1) return false;
|
||||
var sym = def.orig[0];
|
||||
return sym instanceof AST_SymbolLambda && def.scope.name === sym;
|
||||
});
|
||||
|
||||
function is_lhs_read_only(lhs, compressor) {
|
||||
if (lhs instanceof AST_This) return true;
|
||||
if (lhs instanceof AST_SymbolRef) {
|
||||
var def = lhs.definition();
|
||||
return def.orig[0] instanceof AST_SymbolLambda
|
||||
|| compressor.exposed(def) && identifier_atom[def.name];
|
||||
return def.lambda || compressor.exposed(def) && identifier_atom[def.name];
|
||||
}
|
||||
if (lhs instanceof AST_PropAccess) {
|
||||
lhs = lhs.expression;
|
||||
@@ -1127,6 +1128,8 @@ merge(Compressor.prototype, {
|
||||
if (!stop_if_hit && in_conditional(node, 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
|
||||
var hit_rhs;
|
||||
if (can_replace
|
||||
@@ -1225,6 +1228,7 @@ merge(Compressor.prototype, {
|
||||
var scan_lhs = lhs && !side_effects && !is_lhs_read_only(lhs, compressor);
|
||||
var scan_rhs = foldable(get_rhs(candidate));
|
||||
if (!scan_lhs && !scan_rhs) continue;
|
||||
var modify_toplevel = false;
|
||||
// Locate symbols which may execute code outside of scanning range
|
||||
var lvalues = get_lvalues(candidate);
|
||||
var lhs_local = is_lhs_local(lhs);
|
||||
@@ -1464,50 +1468,20 @@ merge(Compressor.prototype, {
|
||||
hit_stack.pop();
|
||||
}
|
||||
|
||||
function find_stop(node, level, write_only) {
|
||||
function find_stop(node, level) {
|
||||
var parent = scanner.parent(level);
|
||||
if (parent instanceof AST_Assign) {
|
||||
if (write_only
|
||||
&& !(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_Assign) return node;
|
||||
if (parent instanceof AST_Binary) return node;
|
||||
if (parent instanceof AST_Call) return node;
|
||||
if (parent instanceof AST_Case) return node;
|
||||
if (parent instanceof AST_Conditional) {
|
||||
if (write_only && parent.condition === node) {
|
||||
return find_stop(parent, level + 1, write_only);
|
||||
}
|
||||
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_Conditional) return node;
|
||||
if (parent instanceof AST_Definitions) return find_stop(parent, level + 1);
|
||||
if (parent instanceof AST_Exit) return node;
|
||||
if (parent instanceof AST_If) return node;
|
||||
if (parent instanceof AST_IterationStatement) return node;
|
||||
if (parent instanceof AST_PropAccess) return node;
|
||||
if (parent instanceof AST_Sequence) {
|
||||
return find_stop(parent, level + 1, parent.tail_node() !== node);
|
||||
}
|
||||
if (parent instanceof AST_SimpleStatement) {
|
||||
return find_stop(parent, level + 1, true);
|
||||
}
|
||||
if (parent instanceof AST_Sequence) return find_stop(parent, level + 1);
|
||||
if (parent instanceof AST_SimpleStatement) return find_stop(parent, level + 1);
|
||||
if (parent instanceof AST_Switch) return node;
|
||||
if (parent instanceof AST_Unary) return node;
|
||||
if (parent instanceof AST_VarDef) return node;
|
||||
@@ -1607,7 +1581,16 @@ merge(Compressor.prototype, {
|
||||
if (candidate instanceof AST_VarDef) {
|
||||
lvalues[candidate.name.name] = lhs;
|
||||
}
|
||||
var scan_iife = scope instanceof AST_Toplevel;
|
||||
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;
|
||||
if (node instanceof AST_SymbolRef) {
|
||||
value = node.fixed_value() || node;
|
||||
@@ -1694,6 +1677,7 @@ merge(Compressor.prototype, {
|
||||
var def = sym.definition();
|
||||
if (def.orig.length == 1 && def.orig[0] instanceof AST_SymbolDefun) return false;
|
||||
if (def.scope !== scope) return true;
|
||||
if (modify_toplevel && compressor.exposed(def)) return true;
|
||||
return !all(def.references, function(ref) {
|
||||
return ref.scope.resolve() === scope;
|
||||
});
|
||||
@@ -2031,14 +2015,14 @@ merge(Compressor.prototype, {
|
||||
n--;
|
||||
CHANGED = true;
|
||||
var left = prev.body;
|
||||
return make_sequence(left, [ left, right ]).transform(compressor);
|
||||
return make_sequence(left, [ left, right ]);
|
||||
}
|
||||
var n = 0, prev;
|
||||
for (var i = 0; i < statements.length; i++) {
|
||||
var stat = statements[i];
|
||||
if (prev) {
|
||||
if (stat instanceof AST_Exit) {
|
||||
stat.value = cons_seq(stat.value || make_node(AST_Undefined, stat).transform(compressor));
|
||||
stat.value = cons_seq(stat.value || make_node(AST_Undefined, stat)).transform(compressor);
|
||||
} else if (stat instanceof AST_For) {
|
||||
if (!(stat.init instanceof AST_Definitions)) {
|
||||
var abort = false;
|
||||
@@ -2302,7 +2286,14 @@ merge(Compressor.prototype, {
|
||||
return true;
|
||||
});
|
||||
def(AST_Binary, function(compressor) {
|
||||
return lazy_op[this.operator] && (this.left._dot_throw(compressor) || this.right._dot_throw(compressor));
|
||||
switch (this.operator) {
|
||||
case "&&":
|
||||
return this.left._dot_throw(compressor) || this.right._dot_throw(compressor);
|
||||
case "||":
|
||||
return this.right._dot_throw(compressor);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
});
|
||||
def(AST_Conditional, function(compressor) {
|
||||
return this.consequent._dot_throw(compressor) || this.alternative._dot_throw(compressor);
|
||||
@@ -2446,9 +2437,10 @@ merge(Compressor.prototype, {
|
||||
|| this.operator == "=" && this.right.is_number(compressor);
|
||||
});
|
||||
def(AST_Binary, function(compressor) {
|
||||
return binary[this.operator] || this.operator == "+"
|
||||
&& this.left.is_number(compressor)
|
||||
&& this.right.is_number(compressor);
|
||||
if (binary[this.operator]) return true;
|
||||
if (this.operator != "+") return false;
|
||||
return (this.left.is_boolean(compressor) || this.left.is_number(compressor))
|
||||
&& (this.right.is_boolean(compressor) || this.right.is_number(compressor));
|
||||
});
|
||||
var fn = makePredicate([
|
||||
"charCodeAt",
|
||||
@@ -2907,7 +2899,20 @@ merge(Compressor.prototype, {
|
||||
case ">=" : result = left >= right; break;
|
||||
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) {
|
||||
var condition = this.condition._eval(compressor, cached, depth);
|
||||
@@ -3527,10 +3532,10 @@ merge(Compressor.prototype, {
|
||||
var drop_vars = !(self instanceof AST_Toplevel) || compressor.toplevel.vars;
|
||||
var assign_as_unused = /keep_assign/.test(compressor.option("unused")) ? return_false : function(node, props) {
|
||||
var sym;
|
||||
if (node instanceof AST_Assign && (node.write_only || node.operator == "=")) {
|
||||
sym = node.left;
|
||||
} else if (node instanceof AST_Unary && node.write_only) {
|
||||
sym = node.expression;
|
||||
if (node instanceof AST_Assign) {
|
||||
if (node.write_only || node.operator == "=") sym = node.left;
|
||||
} else if (node instanceof AST_Unary) {
|
||||
if (node.write_only) sym = node.expression;
|
||||
}
|
||||
if (!/strict/.test(compressor.option("pure_getters"))) return sym instanceof AST_SymbolRef && sym;
|
||||
while (sym instanceof AST_PropAccess && !sym.expression.may_throw_on_access(compressor)) {
|
||||
@@ -3628,6 +3633,7 @@ merge(Compressor.prototype, {
|
||||
return !(def.id in in_use_ids) || def.orig.length > 1;
|
||||
};
|
||||
// pass 3: we should drop declarations not in_use
|
||||
var unused_fn_names = [];
|
||||
var tt = new TreeTransformer(function(node, descend, in_list) {
|
||||
var parent = tt.parent();
|
||||
if (drop_vars) {
|
||||
@@ -3635,7 +3641,7 @@ merge(Compressor.prototype, {
|
||||
if (sym) {
|
||||
var def = sym.definition();
|
||||
var in_use = def.id in in_use_ids;
|
||||
var value = null;
|
||||
var value;
|
||||
if (node instanceof AST_Assign) {
|
||||
if (!in_use || node.left === sym && def.id in fixed_ids && fixed_ids[def.id] !== node) {
|
||||
value = get_rhs(node);
|
||||
@@ -3655,7 +3661,7 @@ merge(Compressor.prototype, {
|
||||
}
|
||||
if (scope !== self) return;
|
||||
if (node instanceof AST_Function && node.name && drop_fn_name(node.name.definition())) {
|
||||
node.name = null;
|
||||
unused_fn_names.push(node);
|
||||
}
|
||||
if (node instanceof AST_Lambda && !(node instanceof AST_Accessor)) {
|
||||
var trim = compressor.drop_fargs(node, parent);
|
||||
@@ -3664,8 +3670,8 @@ merge(Compressor.prototype, {
|
||||
if (!(sym.definition().id in in_use_ids)) {
|
||||
sym.__unused = true;
|
||||
if (trim) {
|
||||
log(sym, "Dropping unused function argument {name} [{file}:{line},{col}]", template(sym));
|
||||
a.pop();
|
||||
AST_Node[sym.unreferenced() ? "warn" : "info"]("Dropping unused function argument {name} [{file}:{line},{col}]", template(sym));
|
||||
}
|
||||
} else {
|
||||
trim = false;
|
||||
@@ -3675,7 +3681,7 @@ merge(Compressor.prototype, {
|
||||
if (drop_funcs && node instanceof AST_Defun && node !== self) {
|
||||
var def = node.name.definition();
|
||||
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++;
|
||||
return make_node(AST_EmptyStatement, node);
|
||||
}
|
||||
@@ -3717,6 +3723,7 @@ merge(Compressor.prototype, {
|
||||
if (!def.value) {
|
||||
head.push(def);
|
||||
} else if (compressor.option("functions")
|
||||
&& !compressor.option("ie8")
|
||||
&& def.value === def.name.fixed_value()
|
||||
&& def.value instanceof AST_Function
|
||||
&& !(def.value.name && def.value.name.definition().assignments)
|
||||
@@ -3762,7 +3769,7 @@ merge(Compressor.prototype, {
|
||||
AST_Node.warn("Side effects in initialization of unused variable {name} [{file}:{line},{col}]", template(def.name));
|
||||
side_effects.push(value);
|
||||
} 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++;
|
||||
}
|
||||
@@ -3840,6 +3847,10 @@ merge(Compressor.prototype, {
|
||||
return node;
|
||||
}
|
||||
|
||||
function log(sym, text, props) {
|
||||
AST_Node[sym.unreferenced() ? "warn" : "info"](text, props);
|
||||
}
|
||||
|
||||
function template(sym) {
|
||||
return {
|
||||
name : sym.name,
|
||||
@@ -3851,6 +3862,9 @@ merge(Compressor.prototype, {
|
||||
});
|
||||
tt.push(compressor.parent());
|
||||
self.transform(tt);
|
||||
unused_fn_names.forEach(function(fn) {
|
||||
fn.name = null;
|
||||
});
|
||||
|
||||
function verify_safe_usage(def, read, modified) {
|
||||
if (def.id in in_use_ids) return;
|
||||
@@ -3879,6 +3893,7 @@ merge(Compressor.prototype, {
|
||||
prop.walk(tw);
|
||||
});
|
||||
if (node instanceof AST_Assign) {
|
||||
if (node.write_only === "p" && node.right.may_throw_on_access(compressor)) return;
|
||||
var right = get_rhs(node);
|
||||
right.walk(tw);
|
||||
if (node.left === sym) {
|
||||
@@ -4167,6 +4182,15 @@ merge(Compressor.prototype, {
|
||||
}
|
||||
});
|
||||
|
||||
function safe_to_drop(fn, compressor) {
|
||||
if (!fn.name || !compressor.option("ie8")) return true;
|
||||
var def = fn.name.definition();
|
||||
if (compressor.exposed(def)) return false;
|
||||
return all(def.references, function(sym) {
|
||||
return !(sym instanceof AST_SymbolRef);
|
||||
});
|
||||
}
|
||||
|
||||
// drop_side_effect_free()
|
||||
// remove side-effect-free parts which only affects return value
|
||||
(function(def) {
|
||||
@@ -4199,8 +4223,8 @@ merge(Compressor.prototype, {
|
||||
var left = this.left;
|
||||
if (left instanceof AST_PropAccess) {
|
||||
var expr = left.expression;
|
||||
if (expr instanceof AST_Assign && !expr.may_throw_on_access(compressor)) {
|
||||
expr.write_only = true;
|
||||
if (expr instanceof AST_Assign && expr.operator == "=" && !expr.may_throw_on_access(compressor)) {
|
||||
expr.write_only = "p";
|
||||
}
|
||||
if (compressor.has_directive("use strict") && expr.is_constant()) return this;
|
||||
}
|
||||
@@ -4214,7 +4238,7 @@ merge(Compressor.prototype, {
|
||||
def(AST_Binary, function(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 (lazy_op[this.operator]) {
|
||||
if (lazy_op[this.operator] && !(right instanceof AST_Function)) {
|
||||
var node = this;
|
||||
if (right !== node.right) {
|
||||
node = this.clone();
|
||||
@@ -4284,7 +4308,7 @@ merge(Compressor.prototype, {
|
||||
return expr.drop_side_effect_free(compressor, first_in_statement);
|
||||
});
|
||||
def(AST_Function, function(compressor) {
|
||||
return this.name && compressor.option("ie8") ? this : null;
|
||||
return safe_to_drop(this, compressor) ? null : this;
|
||||
});
|
||||
def(AST_Object, function(compressor, first_in_statement) {
|
||||
var values = trim(this.properties, compressor, first_in_statement);
|
||||
@@ -5170,7 +5194,9 @@ merge(Compressor.prototype, {
|
||||
fn._squeezed = true;
|
||||
return make_sequence(self, flatten_fn()).optimize(compressor);
|
||||
}
|
||||
if (compressor.option("side_effects") && all(fn.body, is_empty)) {
|
||||
if (compressor.option("side_effects")
|
||||
&& all(fn.body, is_empty)
|
||||
&& (fn !== exp || safe_to_drop(fn, compressor))) {
|
||||
var args = self.args.concat(make_node(AST_Undefined, self));
|
||||
return make_sequence(self, args).optimize(compressor);
|
||||
}
|
||||
@@ -5207,7 +5233,7 @@ merge(Compressor.prototype, {
|
||||
if (stat instanceof AST_SimpleStatement) {
|
||||
return make_node(AST_UnaryPrefix, stat, {
|
||||
operator: "void",
|
||||
expression: stat.body.clone(true)
|
||||
expression: stat.body
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -5696,7 +5722,8 @@ merge(Compressor.prototype, {
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (compressor.option("booleans") && compressor.in_boolean_context()) switch (self.operator) {
|
||||
var in_bool = compressor.option("booleans") && compressor.in_boolean_context();
|
||||
if (in_bool) switch (self.operator) {
|
||||
case "+":
|
||||
var ll = self.left.evaluate(compressor);
|
||||
var rr = self.right.evaluate(compressor);
|
||||
@@ -5729,9 +5756,9 @@ merge(Compressor.prototype, {
|
||||
}
|
||||
break;
|
||||
}
|
||||
var parent = compressor.parent();
|
||||
if (compressor.option("comparisons") && self.is_boolean(compressor)) {
|
||||
if (!(compressor.parent() instanceof AST_Binary)
|
||||
|| compressor.parent() instanceof AST_Assign) {
|
||||
if (!(parent instanceof AST_Binary) || parent instanceof AST_Assign) {
|
||||
var negated = make_node(AST_UnaryPrefix, self, {
|
||||
operator: "!",
|
||||
expression: self.negate(compressor, first_in_statement(compressor))
|
||||
@@ -5764,19 +5791,20 @@ merge(Compressor.prototype, {
|
||||
}
|
||||
}
|
||||
if (compressor.option("evaluate")) {
|
||||
var associative = true;
|
||||
switch (self.operator) {
|
||||
case "&&":
|
||||
var ll = fuzzy_eval(self.left);
|
||||
if (!ll) {
|
||||
AST_Node.warn("Condition left of && always false [{file}:{line},{col}]", self.start);
|
||||
return maintain_this_binding(compressor, compressor.parent(), compressor.self(), self.left).optimize(compressor);
|
||||
return maintain_this_binding(compressor, parent, compressor.self(), self.left).optimize(compressor);
|
||||
} else if (!(ll instanceof AST_Node)) {
|
||||
AST_Node.warn("Condition left of && always true [{file}:{line},{col}]", self.start);
|
||||
return make_sequence(self, [ self.left, self.right ]).optimize(compressor);
|
||||
}
|
||||
var rr = self.right.evaluate(compressor);
|
||||
if (!rr) {
|
||||
if (compressor.option("booleans") && compressor.in_boolean_context()) {
|
||||
if (in_bool) {
|
||||
AST_Node.warn("Boolean && always false [{file}:{line},{col}]", self.start);
|
||||
return make_sequence(self, [
|
||||
self.left,
|
||||
@@ -5784,9 +5812,7 @@ merge(Compressor.prototype, {
|
||||
]).optimize(compressor);
|
||||
} else self.falsy = true;
|
||||
} else if (!(rr instanceof AST_Node)) {
|
||||
var parent = compressor.parent();
|
||||
if (parent.operator == "&&" && parent.left === compressor.self()
|
||||
|| compressor.option("booleans") && compressor.in_boolean_context()) {
|
||||
if (in_bool || parent.operator == "&&" && parent.left === compressor.self()) {
|
||||
AST_Node.warn("Dropping side-effect-free && [{file}:{line},{col}]", self.start);
|
||||
return self.left.optimize(compressor);
|
||||
}
|
||||
@@ -5808,18 +5834,16 @@ merge(Compressor.prototype, {
|
||||
return make_sequence(self, [ self.left, self.right ]).optimize(compressor);
|
||||
} else if (!(ll instanceof AST_Node)) {
|
||||
AST_Node.warn("Condition left of || always true [{file}:{line},{col}]", self.start);
|
||||
return maintain_this_binding(compressor, compressor.parent(), compressor.self(), self.left).optimize(compressor);
|
||||
return maintain_this_binding(compressor, parent, compressor.self(), self.left).optimize(compressor);
|
||||
}
|
||||
var rr = self.right.evaluate(compressor);
|
||||
if (!rr) {
|
||||
var parent = compressor.parent();
|
||||
if (parent.operator == "||" && parent.left === compressor.self()
|
||||
|| compressor.option("booleans") && compressor.in_boolean_context()) {
|
||||
if (in_bool || parent.operator == "||" && parent.left === compressor.self()) {
|
||||
AST_Node.warn("Dropping side-effect-free || [{file}:{line},{col}]", self.start);
|
||||
return self.left.optimize(compressor);
|
||||
}
|
||||
} else if (!(rr instanceof AST_Node)) {
|
||||
if (compressor.option("booleans") && compressor.in_boolean_context()) {
|
||||
if (in_bool) {
|
||||
AST_Node.warn("Boolean || always true [{file}:{line},{col}]", self.start);
|
||||
return make_sequence(self, [
|
||||
self.left,
|
||||
@@ -5836,9 +5860,6 @@ merge(Compressor.prototype, {
|
||||
}).optimize(compressor);
|
||||
}
|
||||
break;
|
||||
}
|
||||
var associative = true;
|
||||
switch (self.operator) {
|
||||
case "+":
|
||||
// "foo" + ("bar" + x) => "foobar" + x
|
||||
if (self.left instanceof AST_Constant
|
||||
@@ -5918,13 +5939,39 @@ merge(Compressor.prototype, {
|
||||
});
|
||||
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 "/":
|
||||
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 "^":
|
||||
// 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)
|
||||
&& reversible()
|
||||
&& !(self.left instanceof AST_Binary
|
||||
@@ -5942,87 +5989,79 @@ merge(Compressor.prototype, {
|
||||
self = best_of(compressor, self, reversed);
|
||||
}
|
||||
}
|
||||
if (associative && self.is_number(compressor)) {
|
||||
// a + (b + c) => (a + b) + c
|
||||
if (self.right instanceof AST_Binary
|
||||
&& self.right.operator == self.operator) {
|
||||
self = make_node(AST_Binary, self, {
|
||||
if (!associative || !self.is_number(compressor)) break;
|
||||
// a + (b + c) => (a + b) + c
|
||||
if (self.right instanceof AST_Binary
|
||||
&& 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, {
|
||||
operator: align(self.operator, self.right.operator),
|
||||
left: make_node(AST_Binary, self.left, {
|
||||
operator: self.operator,
|
||||
left: make_node(AST_Binary, self.left, {
|
||||
operator: self.operator,
|
||||
left: self.left,
|
||||
right: self.right.left,
|
||||
start: self.left.start,
|
||||
end: self.right.left.end
|
||||
}),
|
||||
right: self.right.right
|
||||
});
|
||||
}
|
||||
// (n + 2) + 3 => 5 + n
|
||||
// (2 * n) * 3 => 6 + n
|
||||
if (self.right instanceof AST_Constant
|
||||
&& self.left instanceof AST_Binary
|
||||
&& self.left.operator == self.operator) {
|
||||
if (self.left.left instanceof AST_Constant) {
|
||||
self = make_node(AST_Binary, self, {
|
||||
operator: self.operator,
|
||||
left: make_node(AST_Binary, self.left, {
|
||||
operator: self.operator,
|
||||
left: self.left.left,
|
||||
right: self.right,
|
||||
start: self.left.left.start,
|
||||
end: self.right.end
|
||||
}),
|
||||
right: self.left.right
|
||||
});
|
||||
} else if (self.left.right instanceof AST_Constant) {
|
||||
self = make_node(AST_Binary, self, {
|
||||
operator: self.operator,
|
||||
left: make_node(AST_Binary, self.left, {
|
||||
operator: self.operator,
|
||||
left: self.left.right,
|
||||
right: self.right,
|
||||
start: self.left.right.start,
|
||||
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
|
||||
left: self.left,
|
||||
right: self.right.left,
|
||||
start: self.left.start,
|
||||
end: self.right.left.end
|
||||
}),
|
||||
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
|
||||
});
|
||||
}
|
||||
}
|
||||
// (2 * n) * 3 => 6 * n
|
||||
// (n + 2) + 3 => n + 5
|
||||
if (self.right instanceof AST_Constant
|
||||
&& self.left instanceof AST_Binary
|
||||
&& self.left.operator != "%"
|
||||
&& PRECEDENCE[self.left.operator] == PRECEDENCE[self.operator]) {
|
||||
if (self.left.left instanceof AST_Constant
|
||||
&& (self.left.operator != "+" || self.left.right.is_number(compressor))) {
|
||||
self = make_node(AST_Binary, self, {
|
||||
operator: self.left.operator,
|
||||
left: make_node(AST_Binary, self.left, {
|
||||
operator: self.operator,
|
||||
left: self.left.left,
|
||||
right: self.right,
|
||||
start: self.left.left.start,
|
||||
end: self.right.end
|
||||
}),
|
||||
right: self.left.right
|
||||
});
|
||||
} else if (self.left.right instanceof AST_Constant
|
||||
&& (self.left.operator != "+" || self.left.left.is_number(compressor))) {
|
||||
self = make_node(AST_Binary, self, {
|
||||
operator: self.left.operator,
|
||||
left: self.left.left,
|
||||
right: make_node(AST_Binary, self.left, {
|
||||
operator: align(self.left.operator, self.operator),
|
||||
left: self.left.right,
|
||||
right: self.right,
|
||||
start: self.left.right.start,
|
||||
end: self.right.end
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (compressor.option("unsafe")) {
|
||||
var indexRight = is_indexFn(self.right);
|
||||
if (compressor.option("booleans")
|
||||
if (in_bool
|
||||
&& indexRight
|
||||
&& (self.operator == "==" || self.operator == "!=")
|
||||
&& self.left instanceof AST_Number
|
||||
&& self.left.getValue() == 0
|
||||
&& compressor.in_boolean_context()) {
|
||||
&& self.left.getValue() == 0) {
|
||||
return (self.operator == "==" ? make_node(AST_UnaryPrefix, self, {
|
||||
operator: "!",
|
||||
expression: self.right
|
||||
@@ -6078,6 +6117,17 @@ merge(Compressor.prototype, {
|
||||
}
|
||||
return self;
|
||||
|
||||
function align(ref, op) {
|
||||
switch (ref) {
|
||||
case "-":
|
||||
return op == "+" ? "-" : "+";
|
||||
case "/":
|
||||
return op == "*" ? "/" : "*";
|
||||
default:
|
||||
return op;
|
||||
}
|
||||
}
|
||||
|
||||
function fuzzy_eval(node) {
|
||||
if (node.truthy) return true;
|
||||
if (node.falsy) return false;
|
||||
@@ -6161,6 +6211,7 @@ merge(Compressor.prototype, {
|
||||
if (single_use && fixed) {
|
||||
def.single_use = false;
|
||||
fixed._squeezed = true;
|
||||
fixed.single_use = true;
|
||||
if (fixed instanceof AST_Defun) {
|
||||
fixed = make_node(AST_Function, fixed, fixed);
|
||||
fixed.name = make_node(AST_SymbolLambda, fixed.name, fixed.name);
|
||||
@@ -6188,7 +6239,9 @@ merge(Compressor.prototype, {
|
||||
var fn = node.fixed_value();
|
||||
if (!(fn instanceof AST_Lambda)) return;
|
||||
if (!fn.name) return;
|
||||
if (fixed.variables.get(fn.name.name) !== fn.name.definition()) return;
|
||||
var fn_def = fn.name.definition();
|
||||
if (fn_def.scope !== fn.name.scope) return;
|
||||
if (fixed.variables.get(fn.name.name) !== fn_def) return;
|
||||
fn.name = fn.name.clone();
|
||||
var value_def = value.variables.get(fn.name.name) || value.def_function(fn.name);
|
||||
node.thedef = value_def;
|
||||
|
||||
@@ -1,19 +1,39 @@
|
||||
"use strict";
|
||||
|
||||
var to_ascii = typeof atob == "undefined" ? function(b64) {
|
||||
return new Buffer(b64, "base64").toString();
|
||||
} : atob;
|
||||
var to_base64 = typeof btoa == "undefined" ? function(str) {
|
||||
return new Buffer(str).toString("base64");
|
||||
} : btoa;
|
||||
var to_ascii, to_base64;
|
||||
if (typeof Buffer == "undefined") {
|
||||
to_ascii = atob;
|
||||
to_base64 = btoa;
|
||||
} else if (typeof Buffer.alloc == "undefined") {
|
||||
to_ascii = function(b64) {
|
||||
return new Buffer(b64, "base64").toString();
|
||||
};
|
||||
to_base64 = function(str) {
|
||||
return new Buffer(str).toString("base64");
|
||||
};
|
||||
} else {
|
||||
to_ascii = function(b64) {
|
||||
return Buffer.from(b64, "base64").toString();
|
||||
};
|
||||
to_base64 = function(str) {
|
||||
return Buffer.from(str).toString("base64");
|
||||
};
|
||||
}
|
||||
|
||||
function read_source_map(name, code) {
|
||||
var match = /\n\/\/# sourceMappingURL=data:application\/json(;.*?)?;base64,(\S+)\s*$/.exec(code);
|
||||
if (!match) {
|
||||
AST_Node.warn("inline source map not found: " + name);
|
||||
return null;
|
||||
function read_source_map(name, toplevel) {
|
||||
var comments = toplevel.end.comments_after;
|
||||
for (var i = comments.length; --i >= 0;) {
|
||||
var comment = comments[i];
|
||||
if (comment.type != "comment1") break;
|
||||
var match = /^# ([^\s=]+)=(\S+)\s*$/.exec(comment.value);
|
||||
if (!match) break;
|
||||
if (match[1] == "sourceMappingURL") {
|
||||
match = /^data:application\/json(;.*?)?;base64,(\S+)$/.exec(match[2]);
|
||||
if (!match) break;
|
||||
return to_ascii(match[2]);
|
||||
}
|
||||
}
|
||||
return to_ascii(match[2]);
|
||||
AST_Node.warn("inline source map not found: " + name);
|
||||
}
|
||||
|
||||
function parse_source_map(content) {
|
||||
@@ -134,10 +154,10 @@ function minify(files, options) {
|
||||
source_maps = source_map_content && Object.create(null);
|
||||
for (var name in files) if (HOP(files, name)) {
|
||||
options.parse.filename = name;
|
||||
options.parse.toplevel = parse(files[name], options.parse);
|
||||
options.parse.toplevel = toplevel = parse(files[name], options.parse);
|
||||
if (source_maps) {
|
||||
if (source_map_content == "inline") {
|
||||
var inlined_content = read_source_map(name, files[name]);
|
||||
var inlined_content = read_source_map(name, toplevel);
|
||||
if (inlined_content) {
|
||||
source_maps[name] = parse_source_map(inlined_content);
|
||||
}
|
||||
@@ -146,7 +166,6 @@ function minify(files, options) {
|
||||
}
|
||||
}
|
||||
}
|
||||
toplevel = options.parse.toplevel;
|
||||
}
|
||||
if (quoted_props) {
|
||||
reserve_quoted_keys(toplevel, quoted_props);
|
||||
|
||||
@@ -403,7 +403,7 @@
|
||||
var def = M.definition();
|
||||
return {
|
||||
type: "Identifier",
|
||||
name: def ? def.mangled_name || def.name : M.name
|
||||
name: def && def.mangled_name || M.name
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
@@ -91,13 +91,11 @@ function OutputStream(options) {
|
||||
comment_filter = function(comment) {
|
||||
return comment.type != "comment5" && comments.test(comment.value);
|
||||
};
|
||||
}
|
||||
else if (typeof comments === "function") {
|
||||
} else if (typeof comments === "function") {
|
||||
comment_filter = function(comment) {
|
||||
return comment.type != "comment5" && comments(this, comment);
|
||||
};
|
||||
}
|
||||
else if (comments === "some") {
|
||||
} else if (comments === "some") {
|
||||
comment_filter = is_some_comments;
|
||||
} else { // NOTE includes "all" option
|
||||
comment_filter = return_true;
|
||||
@@ -452,7 +450,7 @@ function OutputStream(options) {
|
||||
var self = this;
|
||||
var scan = node instanceof AST_Exit && node.value;
|
||||
var comments = dump(node);
|
||||
if (!comments) return;
|
||||
if (!comments) comments = [];
|
||||
|
||||
if (scan) {
|
||||
var tw = new TreeWalker(function(node) {
|
||||
@@ -643,8 +641,7 @@ function OutputStream(options) {
|
||||
var self = this, generator = self._codegen;
|
||||
if (self instanceof AST_Scope) {
|
||||
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;
|
||||
}
|
||||
function doit() {
|
||||
@@ -1043,11 +1040,9 @@ function OutputStream(options) {
|
||||
return;
|
||||
}
|
||||
b = b.alternative;
|
||||
}
|
||||
else if (b instanceof AST_StatementWithBody) {
|
||||
} else if (b instanceof AST_StatementWithBody) {
|
||||
b = b.body;
|
||||
}
|
||||
else break;
|
||||
} else break;
|
||||
}
|
||||
force_statement(self.body, output);
|
||||
}
|
||||
@@ -1355,7 +1350,7 @@ function OutputStream(options) {
|
||||
});
|
||||
DEFPRINT(AST_Symbol, function(self, output) {
|
||||
var def = self.definition();
|
||||
output.print_name(def ? def.mangled_name || def.name : self.name);
|
||||
output.print_name(def && def.mangled_name || self.name);
|
||||
});
|
||||
DEFPRINT(AST_Hole, noop);
|
||||
DEFPRINT(AST_This, function(self, output) {
|
||||
|
||||
93
lib/parse.js
93
lib/parse.js
@@ -234,6 +234,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
directives : {},
|
||||
directive_stack : []
|
||||
};
|
||||
var prev_was_dot = false;
|
||||
|
||||
function peek() {
|
||||
return S.text.charAt(S.pos);
|
||||
@@ -286,16 +287,12 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
S.tokpos = S.pos;
|
||||
}
|
||||
|
||||
var prev_was_dot = false;
|
||||
function token(type, value, is_comment) {
|
||||
S.regex_allowed = ((type == "operator" && !UNARY_POSTFIX[value]) ||
|
||||
(type == "keyword" && KEYWORDS_BEFORE_EXPRESSION[value]) ||
|
||||
(type == "punc" && PUNC_BEFORE_EXPRESSION[value]));
|
||||
if (type == "punc" && value == ".") {
|
||||
prev_was_dot = true;
|
||||
} else if (!is_comment) {
|
||||
prev_was_dot = false;
|
||||
}
|
||||
S.regex_allowed = type == "operator" && !UNARY_POSTFIX[value]
|
||||
|| type == "keyword" && KEYWORDS_BEFORE_EXPRESSION[value]
|
||||
|| type == "punc" && PUNC_BEFORE_EXPRESSION[value];
|
||||
if (type == "punc" && value == ".") prev_was_dot = true;
|
||||
else if (!is_comment) prev_was_dot = false;
|
||||
var ret = {
|
||||
type : type,
|
||||
value : value,
|
||||
@@ -358,11 +355,8 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
parse_error("Legacy octal literals are not allowed in strict mode");
|
||||
}
|
||||
var valid = parse_js_number(num);
|
||||
if (!isNaN(valid)) {
|
||||
return token("num", valid);
|
||||
} else {
|
||||
parse_error("Invalid syntax: " + num);
|
||||
}
|
||||
if (!isNaN(valid)) return token("num", valid);
|
||||
parse_error("Invalid syntax: " + num);
|
||||
}
|
||||
|
||||
function read_escaped_char(in_string) {
|
||||
@@ -463,8 +457,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
if (ch == "\\") escaped = backslash = true, next();
|
||||
else if (is_identifier_char(ch)) name += next();
|
||||
else break;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (ch != "u") parse_error("Expecting UnicodeEscapeSequence -- uXXXX");
|
||||
ch = read_escaped_char();
|
||||
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() {
|
||||
next();
|
||||
return is_digit(peek().charCodeAt(0))
|
||||
? read_num(".")
|
||||
: token("punc", ".");
|
||||
return is_digit(peek().charCodeAt(0)) ? read_num(".") : token("punc", ".");
|
||||
}
|
||||
|
||||
function read_word() {
|
||||
@@ -592,11 +583,10 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
switch (code) {
|
||||
case 34: case 39: return read_string(ch);
|
||||
case 46: return handle_dot();
|
||||
case 47: {
|
||||
var tok = handle_slash();
|
||||
if (tok === next_token) continue;
|
||||
return tok;
|
||||
}
|
||||
case 47:
|
||||
var tok = handle_slash();
|
||||
if (tok === next_token) continue;
|
||||
return tok;
|
||||
}
|
||||
if (is_digit(code)) return read_num();
|
||||
if (PUNC_CHARS[ch]) return token("punc", next());
|
||||
@@ -614,12 +604,8 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
|
||||
next_token.add_directive = function(directive) {
|
||||
S.directive_stack[S.directive_stack.length - 1].push(directive);
|
||||
|
||||
if (S.directives[directive] === undefined) {
|
||||
S.directives[directive] = 1;
|
||||
} else {
|
||||
S.directives[directive]++;
|
||||
}
|
||||
if (S.directives[directive]) S.directives[directive]++;
|
||||
else S.directives[directive] = 1;
|
||||
}
|
||||
|
||||
next_token.push_directives_stack = function() {
|
||||
@@ -627,13 +613,10 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
}
|
||||
|
||||
next_token.pop_directives_stack = function() {
|
||||
var directives = S.directive_stack[S.directive_stack.length - 1];
|
||||
|
||||
for (var i = 0; i < directives.length; i++) {
|
||||
var directives = S.directive_stack.pop();
|
||||
for (var i = directives.length; --i >= 0;) {
|
||||
S.directives[directives[i]]--;
|
||||
}
|
||||
|
||||
S.directive_stack.pop();
|
||||
}
|
||||
|
||||
next_token.has_directive = function(directive) {
|
||||
@@ -645,27 +628,17 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
|
||||
/* -----[ Parser (constants) ]----- */
|
||||
|
||||
var UNARY_PREFIX = makePredicate([
|
||||
"typeof",
|
||||
"void",
|
||||
"delete",
|
||||
"--",
|
||||
"++",
|
||||
"!",
|
||||
"~",
|
||||
"-",
|
||||
"+"
|
||||
]);
|
||||
var UNARY_PREFIX = makePredicate("typeof void delete -- ++ ! ~ - +");
|
||||
|
||||
var UNARY_POSTFIX = makePredicate([ "--", "++" ]);
|
||||
var UNARY_POSTFIX = makePredicate("-- ++");
|
||||
|
||||
var ASSIGNMENT = makePredicate([ "=", "+=", "-=", "/=", "*=", "%=", ">>=", "<<=", ">>>=", "|=", "^=", "&=" ]);
|
||||
var ASSIGNMENT = makePredicate("= += -= /= *= %= >>= <<= >>>= |= ^= &=");
|
||||
|
||||
var PRECEDENCE = function(a, ret) {
|
||||
for (var i = 0; i < a.length; ++i) {
|
||||
var b = a[i];
|
||||
for (var j = 0; j < b.length; ++j) {
|
||||
ret[b[j]] = i + 1;
|
||||
for (var i = 0; i < a.length;) {
|
||||
var b = a[i++];
|
||||
for (var j = 0; j < b.length; j++) {
|
||||
ret[b[j]] = i;
|
||||
}
|
||||
}
|
||||
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 ]----- */
|
||||
|
||||
@@ -698,10 +671,9 @@ function parse($TEXT, options) {
|
||||
}, true);
|
||||
|
||||
var S = {
|
||||
input : (typeof $TEXT == "string"
|
||||
? tokenizer($TEXT, options.filename,
|
||||
options.html5_comments, options.shebang)
|
||||
: $TEXT),
|
||||
input : typeof $TEXT == "string"
|
||||
? tokenizer($TEXT, options.filename, options.html5_comments, options.shebang)
|
||||
: $TEXT,
|
||||
token : null,
|
||||
prev : null,
|
||||
peeked : null,
|
||||
@@ -757,15 +729,12 @@ function parse($TEXT, options) {
|
||||
}
|
||||
|
||||
function unexpected(token) {
|
||||
if (token == null)
|
||||
token = S.token;
|
||||
if (token == null) token = S.token;
|
||||
token_error(token, "Unexpected token: " + token_to_string(token.type, token.value));
|
||||
}
|
||||
|
||||
function expect_token(type, val) {
|
||||
if (is(type, val)) {
|
||||
return next();
|
||||
}
|
||||
if (is(type, val)) return next();
|
||||
token_error(S.token, "Unexpected token: " + token_to_string(S.token.type, S.token.value) + ", expected: " + token_to_string(type, val));
|
||||
}
|
||||
|
||||
|
||||
70
lib/scope.js
70
lib/scope.js
@@ -55,6 +55,7 @@ function SymbolDef(scope, orig, init) {
|
||||
this.mangled_name = null;
|
||||
this.undeclared = false;
|
||||
this.id = SymbolDef.next_id++;
|
||||
this.lambda = orig instanceof AST_SymbolLambda;
|
||||
}
|
||||
|
||||
SymbolDef.next_id = 1;
|
||||
@@ -191,13 +192,21 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
|
||||
// pass 3: fix up any scoping issue with IE8
|
||||
if (options.ie8) self.walk(new TreeWalker(function(node) {
|
||||
if (node instanceof AST_SymbolCatch) {
|
||||
redefine(node, node.thedef.defun);
|
||||
var scope = node.thedef.defun;
|
||||
if (scope.name instanceof AST_SymbolLambda && scope.name.name == node.name) {
|
||||
scope = scope.parent_scope.resolve();
|
||||
}
|
||||
redefine(node, scope);
|
||||
return true;
|
||||
}
|
||||
if (node instanceof AST_SymbolLambda) {
|
||||
var def = node.thedef;
|
||||
redefine(node, node.scope.parent_scope);
|
||||
node.thedef.init = def.init;
|
||||
redefine(node, node.scope.parent_scope.resolve());
|
||||
if (typeof node.thedef.init !== "undefined") {
|
||||
node.thedef.init = false;
|
||||
} else if (def.init) {
|
||||
node.thedef.init = def.init;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}));
|
||||
@@ -205,11 +214,19 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
|
||||
function redefine(node, scope) {
|
||||
var name = node.name;
|
||||
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) {
|
||||
node.thedef = new_def;
|
||||
node.reference(options);
|
||||
});
|
||||
if (old_def.lambda) new_def.lambda = true;
|
||||
if (new_def.undeclared) self.variables.set(name, new_def);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -281,9 +298,7 @@ AST_Scope.DEFMETHOD("def_variable", function(symbol, init) {
|
||||
var def = this.variables.get(symbol.name);
|
||||
if (def) {
|
||||
def.orig.push(symbol);
|
||||
if (def.init && (def.scope !== symbol.scope || def.init instanceof AST_Function)) {
|
||||
def.init = init;
|
||||
}
|
||||
if (def.init instanceof AST_Function) def.init = init;
|
||||
} else {
|
||||
def = new SymbolDef(this, symbol, init);
|
||||
this.variables.set(symbol.name, def);
|
||||
@@ -413,7 +428,9 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options) {
|
||||
if (options.cache && node instanceof AST_Toplevel) {
|
||||
node.globals.each(mangle);
|
||||
}
|
||||
node.variables.each(mangle);
|
||||
node.variables.each(function(def) {
|
||||
if (!defer_redef(def)) mangle(def);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
if (node instanceof AST_Label) {
|
||||
@@ -426,22 +443,11 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options) {
|
||||
}
|
||||
if (!options.ie8 && node instanceof AST_Catch) {
|
||||
var def = node.argname.definition();
|
||||
var redef = def.redefined();
|
||||
if (redef) {
|
||||
redefined.push(def);
|
||||
reference(node.argname);
|
||||
def.references.forEach(reference);
|
||||
}
|
||||
var redef = defer_redef(def, node.argname);
|
||||
descend();
|
||||
if (!redef) mangle(def);
|
||||
return true;
|
||||
}
|
||||
|
||||
function reference(sym) {
|
||||
sym.thedef = redef;
|
||||
sym.reference(options);
|
||||
sym.thedef = def;
|
||||
}
|
||||
});
|
||||
this.walk(tw);
|
||||
redefined.forEach(mangle);
|
||||
@@ -450,6 +456,21 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options) {
|
||||
if (options.reserved.has[def.name]) return;
|
||||
def.mangle(options);
|
||||
}
|
||||
|
||||
function defer_redef(def, node) {
|
||||
var redef = def.redefined();
|
||||
if (!redef) return false;
|
||||
redefined.push(def);
|
||||
def.references.forEach(reference);
|
||||
if (node) reference(node);
|
||||
return true;
|
||||
|
||||
function reference(sym) {
|
||||
sym.thedef = redef;
|
||||
sym.reference(options);
|
||||
sym.thedef = def;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
AST_Toplevel.DEFMETHOD("find_colliding_names", function(options) {
|
||||
@@ -499,13 +520,14 @@ AST_Toplevel.DEFMETHOD("expand_names", function(options) {
|
||||
if (def.global && options.cache) return;
|
||||
if (def.unmangleable(options)) return;
|
||||
if (options.reserved.has[def.name]) return;
|
||||
var d = def.redefined();
|
||||
def.name = d ? d.name : next_name();
|
||||
var redef = def.redefined();
|
||||
var name = redef ? redef.rename || redef.name : next_name();
|
||||
def.rename = name;
|
||||
def.orig.forEach(function(sym) {
|
||||
sym.name = def.name;
|
||||
sym.name = name;
|
||||
});
|
||||
def.references.forEach(function(sym) {
|
||||
sym.name = def.name;
|
||||
sym.name = name;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -127,8 +127,7 @@ var MAP = (function() {
|
||||
} else {
|
||||
top.push(val);
|
||||
}
|
||||
}
|
||||
else if (val !== skip) {
|
||||
} else if (val !== skip) {
|
||||
if (val instanceof Splice) {
|
||||
ret.push.apply(ret, backwards ? val.v.slice().reverse() : val.v);
|
||||
} else {
|
||||
@@ -145,8 +144,7 @@ var MAP = (function() {
|
||||
} else {
|
||||
for (i = 0; i < a.length; ++i) if (doit()) break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
for (i in a) if (HOP(a, i)) if (doit()) break;
|
||||
}
|
||||
return top.concat(ret);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"description": "JavaScript parser, mangler/compressor and beautifier toolkit",
|
||||
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
|
||||
"license": "BSD-2-Clause",
|
||||
"version": "3.6.1",
|
||||
"version": "3.6.5",
|
||||
"engines": {
|
||||
"node": ">=0.8.0"
|
||||
},
|
||||
@@ -23,7 +23,7 @@
|
||||
"LICENSE"
|
||||
],
|
||||
"dependencies": {
|
||||
"commander": "2.20.0",
|
||||
"commander": "~2.20.3",
|
||||
"source-map": "~0.6.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -13,15 +13,15 @@ if (!args.length) {
|
||||
}
|
||||
args.push("--timings");
|
||||
var urls = [
|
||||
"https://code.jquery.com/jquery-3.2.1.js",
|
||||
"https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.4/angular.js",
|
||||
"https://cdnjs.cloudflare.com/ajax/libs/mathjs/3.9.0/math.js",
|
||||
"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.js",
|
||||
"https://code.jquery.com/jquery-3.4.1.js",
|
||||
"https://code.angularjs.org/1.7.8/angular.js",
|
||||
"https://unpkg.com/mathjs@6.2.3/dist/math.js",
|
||||
"https://unpkg.com/react@15.3.2/dist/react.js",
|
||||
"http://builds.emberjs.com/tags/v2.11.0/ember.prod.js",
|
||||
"https://cdn.jsdelivr.net/lodash/4.17.4/lodash.js",
|
||||
"https://cdnjs.cloudflare.com/ajax/libs/d3/4.5.0/d3.js",
|
||||
"https://raw.githubusercontent.com/kangax/html-minifier/v3.5.7/dist/htmlminifier.js",
|
||||
"https://cdnjs.cloudflare.com/ajax/libs/d3/5.12.0/d3.js",
|
||||
"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.js",
|
||||
"https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js",
|
||||
"https://cdnjs.cloudflare.com/ajax/libs/ember.js/2.12.2/ember.prod.js",
|
||||
"https://raw.githubusercontent.com/kangax/html-minifier/v4.0.0/dist/htmlminifier.js",
|
||||
];
|
||||
var results = {};
|
||||
var remaining = 2 * urls.length;
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
"use strict";
|
||||
|
||||
require("../tools/exit");
|
||||
|
||||
var assert = require("assert");
|
||||
var child_process = require("child_process");
|
||||
var fs = require("fs");
|
||||
@@ -9,7 +13,7 @@ var U = require("./node");
|
||||
var file = process.argv[2];
|
||||
var dir = path.resolve(path.dirname(module.filename), "compress");
|
||||
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 });
|
||||
var tests = parse_test(path.resolve(dir, file));
|
||||
process.exit(Object.keys(tests).filter(function(name) {
|
||||
|
||||
@@ -96,7 +96,7 @@ asm_mixed: {
|
||||
return +sum;
|
||||
}
|
||||
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);
|
||||
return { geometricMean: geometricMean };
|
||||
|
||||
88
test/compress/booleans.js
Normal file
88
test/compress/booleans.js
Normal file
@@ -0,0 +1,88 @@
|
||||
iife_boolean_context: {
|
||||
options = {
|
||||
booleans: true,
|
||||
evaluate: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function() {
|
||||
return Object(1) || false;
|
||||
}() ? "PASS" : "FAIL");
|
||||
console.log(function() {
|
||||
return [].length || true;
|
||||
}() ? "PASS" : "FAIL");
|
||||
}
|
||||
expect: {
|
||||
console.log(function() {
|
||||
return Object(1);
|
||||
}() ? "PASS" : "FAIL");
|
||||
console.log(function() {
|
||||
return [].length, 1;
|
||||
}() ? "PASS" : "FAIL");
|
||||
}
|
||||
expect_stdout: [
|
||||
"PASS",
|
||||
"PASS",
|
||||
]
|
||||
expect_warnings: [
|
||||
"WARN: Dropping side-effect-free || [test/compress/booleans.js:2,19]",
|
||||
"WARN: Boolean || always true [test/compress/booleans.js:5,19]",
|
||||
]
|
||||
}
|
||||
|
||||
issue_3465_1: {
|
||||
options = {
|
||||
booleans: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function(a) {
|
||||
return typeof a;
|
||||
}() ? "PASS" : "FAIL");
|
||||
}
|
||||
expect: {
|
||||
console.log(function(a) {
|
||||
return 1;
|
||||
}() ? "PASS" : "FAIL");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3465_2: {
|
||||
options = {
|
||||
booleans: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function f(a) {
|
||||
if (!a) console.log(f(42));
|
||||
return typeof a;
|
||||
}() ? "PASS" : "FAIL");
|
||||
}
|
||||
expect: {
|
||||
console.log(function f(a) {
|
||||
if (!a) console.log(f(42));
|
||||
return typeof a;
|
||||
}() ? "PASS" : "FAIL");
|
||||
}
|
||||
expect_stdout: [
|
||||
"number",
|
||||
"PASS",
|
||||
]
|
||||
}
|
||||
|
||||
issue_3465_3: {
|
||||
options = {
|
||||
booleans: true,
|
||||
passes: 2,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function f(a) {
|
||||
return typeof a;
|
||||
}() ? "PASS" : "FAIL");
|
||||
}
|
||||
expect: {
|
||||
console.log(function(a) {
|
||||
return 1;
|
||||
}() ? "PASS" : "FAIL");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
@@ -3511,7 +3511,7 @@ issue_2437_2: {
|
||||
conditionals: true,
|
||||
inline: true,
|
||||
join_vars: true,
|
||||
passes: 2,
|
||||
passes: 3,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
sequences: true,
|
||||
@@ -4388,7 +4388,7 @@ replace_all_var: {
|
||||
}
|
||||
|
||||
replace_all_var_scope: {
|
||||
rename = true;
|
||||
rename = true
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
unused: true,
|
||||
@@ -6237,3 +6237,114 @@ issue_3439_2: {
|
||||
}
|
||||
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"
|
||||
}
|
||||
|
||||
@@ -2062,3 +2062,128 @@ issue_3427_2: {
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3495: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
pure_getters: "strict",
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function f() {
|
||||
f = 0;
|
||||
var a = f.p;
|
||||
}());
|
||||
}
|
||||
expect: {
|
||||
console.log(void 0);
|
||||
}
|
||||
expect_stdout: "undefined"
|
||||
}
|
||||
|
||||
issue_3497: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a;
|
||||
console.log(function(b) {
|
||||
(b += a).p = 0;
|
||||
}());
|
||||
}
|
||||
expect: {
|
||||
var a;
|
||||
console.log(function(b) {
|
||||
(b += a).p = 0;
|
||||
}());
|
||||
}
|
||||
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"
|
||||
}
|
||||
|
||||
@@ -1150,7 +1150,7 @@ issue_2620_3: {
|
||||
}
|
||||
|
||||
issue_2620_4: {
|
||||
rename = true,
|
||||
rename = true
|
||||
options = {
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
@@ -3066,7 +3066,7 @@ class_iife: {
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3400: {
|
||||
issue_3400_1: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
inline: true,
|
||||
@@ -3096,16 +3096,70 @@ issue_3400: {
|
||||
});
|
||||
}
|
||||
expect: {
|
||||
void console.log(function g() {
|
||||
function e() {
|
||||
return [42].map(function(v) {
|
||||
return o = {
|
||||
p: v
|
||||
}, console.log(o[g]) , o;
|
||||
var o;
|
||||
});
|
||||
void console.log(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 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);
|
||||
}
|
||||
expect_stdout: [
|
||||
@@ -3196,3 +3250,123 @@ issue_3444: {
|
||||
}
|
||||
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"
|
||||
}
|
||||
|
||||
1432
test/compress/ie8.js
1432
test/compress/ie8.js
File diff suppressed because it is too large
Load Diff
@@ -51,17 +51,20 @@ comparisons: {
|
||||
comparisons: true,
|
||||
}
|
||||
input: {
|
||||
var x = "42", y = "0x30";
|
||||
console.log(
|
||||
~x === 42,
|
||||
x % n === 42
|
||||
x % y === 42
|
||||
);
|
||||
}
|
||||
expect: {
|
||||
var x = "42", y = "0x30";
|
||||
console.log(
|
||||
42 == ~x,
|
||||
x % n == 42
|
||||
x % y == 42
|
||||
);
|
||||
}
|
||||
expect_stdout: "false true"
|
||||
}
|
||||
|
||||
evaluate_1: {
|
||||
@@ -103,7 +106,7 @@ evaluate_1: {
|
||||
}
|
||||
}
|
||||
|
||||
evaluate_2: {
|
||||
evaluate_1_unsafe_math: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe_math: true,
|
||||
@@ -118,6 +121,8 @@ evaluate_2: {
|
||||
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)
|
||||
);
|
||||
@@ -126,18 +131,138 @@ evaluate_2: {
|
||||
console.log(
|
||||
x + 1 + 2,
|
||||
2 * x,
|
||||
3 + +x,
|
||||
+x + 3,
|
||||
1 + x + 2 + 3,
|
||||
3 | x,
|
||||
6 + x--,
|
||||
6 + x*y,
|
||||
x*y + 6,
|
||||
1 + (2 + x + 3),
|
||||
6 + ~x,
|
||||
5 - y + ~x,
|
||||
0 & x,
|
||||
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: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
@@ -148,7 +273,7 @@ evaluate_3: {
|
||||
console.log(1 + Number(x) + 2);
|
||||
}
|
||||
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: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
@@ -230,3 +701,83 @@ unary_binary_parenthesis: {
|
||||
}
|
||||
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"
|
||||
}
|
||||
|
||||
@@ -1193,6 +1193,7 @@ issue_3427: {
|
||||
assignments: true,
|
||||
collapse_vars: true,
|
||||
inline: true,
|
||||
passes: 2,
|
||||
pure_getters: "strict",
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
@@ -1206,4 +1207,5 @@ issue_3427: {
|
||||
})(a || (a = {}));
|
||||
}
|
||||
expect: {}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
@@ -4947,7 +4947,7 @@ defun_single_use_loop: {
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
for (var x, i = 2; --i >= 0; ) {
|
||||
for (var x, i = 2; --i >= 0;) {
|
||||
var y = x;
|
||||
x = f;
|
||||
console.log(x === y);
|
||||
@@ -4955,7 +4955,7 @@ defun_single_use_loop: {
|
||||
function f() {};
|
||||
}
|
||||
expect: {
|
||||
for (var x, i = 2; --i >= 0; ) {
|
||||
for (var x, i = 2; --i >= 0;) {
|
||||
var y = x;
|
||||
x = f;
|
||||
console.log(x === y);
|
||||
@@ -6609,10 +6609,10 @@ issues_3267_1: {
|
||||
}
|
||||
expect: {
|
||||
!function(i) {
|
||||
if (i)
|
||||
if (Object())
|
||||
return console.log("PASS");
|
||||
throw "FAIL";
|
||||
}(Object());
|
||||
}();
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
@@ -6752,3 +6752,31 @@ issue_3377: {
|
||||
}
|
||||
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"
|
||||
}
|
||||
|
||||
@@ -579,7 +579,7 @@ function_do_catch_ie8: {
|
||||
console.log(b, c);
|
||||
}
|
||||
expect: {
|
||||
var t = 1, u = 1, y = 0;
|
||||
var u = 1, y = 1, a = 0;
|
||||
function c(c) {
|
||||
var d;
|
||||
do {
|
||||
@@ -587,7 +587,7 @@ function_do_catch_ie8: {
|
||||
try {
|
||||
var e = void 0;
|
||||
} catch (i) {
|
||||
--t && w("ddddddddeeeeeeegggggggggiiiiilllllllnnnnntuuuuuuuuyyyyyyy");
|
||||
--u && w("ddddddddeeeeeeegggggggggiiiiilllllllnnnnntuuuuuuuuyyyyyyy");
|
||||
0;
|
||||
0;
|
||||
0;
|
||||
@@ -596,18 +596,146 @@ function_do_catch_ie8: {
|
||||
d[1];
|
||||
} catch (l) {
|
||||
var g;
|
||||
switch(function x() {
|
||||
y++;
|
||||
switch (function n() {
|
||||
a++;
|
||||
}()) {
|
||||
case e + --g:
|
||||
case e + --g:
|
||||
}
|
||||
}
|
||||
} catch (n) {}
|
||||
} catch (t) {}
|
||||
} while (--d);
|
||||
u--;
|
||||
y--;
|
||||
}
|
||||
c();
|
||||
console.log(u, y);
|
||||
console.log(y, a);
|
||||
}
|
||||
expect_stdout: "0 1"
|
||||
}
|
||||
|
||||
issue_3480: {
|
||||
rename = true,
|
||||
mangle = {
|
||||
ie8: false,
|
||||
toplevel: false,
|
||||
}
|
||||
input: {
|
||||
var d, a, b, c = "FAIL";
|
||||
(function b() {
|
||||
(function() {
|
||||
try {
|
||||
c = "PASS";
|
||||
} catch (b) {
|
||||
}
|
||||
})();
|
||||
})();
|
||||
console.log(c);
|
||||
}
|
||||
expect: {
|
||||
var d, a, b, c = "FAIL";
|
||||
(function n() {
|
||||
(function() {
|
||||
try {
|
||||
c = "PASS";
|
||||
} catch (c) {}
|
||||
})();
|
||||
})();
|
||||
console.log(c);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3480_ie8: {
|
||||
rename = true,
|
||||
mangle = {
|
||||
ie8: true,
|
||||
toplevel: false,
|
||||
}
|
||||
input: {
|
||||
var d, a, b, c = "FAIL";
|
||||
(function b() {
|
||||
(function() {
|
||||
try {
|
||||
c = "PASS";
|
||||
} catch (b) {
|
||||
}
|
||||
})();
|
||||
})();
|
||||
console.log(c);
|
||||
}
|
||||
expect: {
|
||||
var d, a, b, c = "FAIL";
|
||||
(function b() {
|
||||
(function() {
|
||||
try {
|
||||
c = "PASS";
|
||||
} catch (b) {}
|
||||
})();
|
||||
})();
|
||||
console.log(c);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3480_toplevel: {
|
||||
rename = true,
|
||||
mangle = {
|
||||
ie8: false,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var d, a, b, c = "FAIL";
|
||||
(function b() {
|
||||
(function() {
|
||||
try {
|
||||
c = "PASS";
|
||||
} catch (b) {
|
||||
}
|
||||
})();
|
||||
})();
|
||||
console.log(c);
|
||||
}
|
||||
expect: {
|
||||
var c, n, o, t = "FAIL";
|
||||
(function c() {
|
||||
(function() {
|
||||
try {
|
||||
t = "PASS";
|
||||
} catch (c) {}
|
||||
})();
|
||||
})();
|
||||
console.log(t);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3480_ie8_toplevel: {
|
||||
rename = true,
|
||||
mangle = {
|
||||
ie8: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var d, a, b, c = "FAIL";
|
||||
(function b() {
|
||||
(function() {
|
||||
try {
|
||||
c = "PASS";
|
||||
} catch (b) {
|
||||
}
|
||||
})();
|
||||
})();
|
||||
console.log(c);
|
||||
}
|
||||
expect: {
|
||||
var c, n, o, t = "FAIL";
|
||||
(function o() {
|
||||
(function() {
|
||||
try {
|
||||
t = "PASS";
|
||||
} catch (o) {}
|
||||
})();
|
||||
})();
|
||||
console.log(t);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
@@ -1006,3 +1006,66 @@ angularjs_chain: {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
issue_3490_1: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
inline: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var b = 42, c = "FAIL";
|
||||
if ({
|
||||
3: function() {
|
||||
var a;
|
||||
return (a && a.p) < this;
|
||||
}(),
|
||||
}) c = "PASS";
|
||||
if (b) while ("" == typeof d);
|
||||
console.log(c, b);
|
||||
}
|
||||
expect: {
|
||||
var b = 42, c = "FAIL";
|
||||
if (function() {
|
||||
var a;
|
||||
a && a.p;
|
||||
}(), c = "PASS", b) while ("" == typeof d);
|
||||
console.log(c, b);
|
||||
}
|
||||
expect_stdout: "PASS 42"
|
||||
}
|
||||
|
||||
issue_3490_2: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
reduce_vars: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var b = 42, c = "FAIL";
|
||||
if ({
|
||||
3: function() {
|
||||
var a;
|
||||
return (a && a.p) < this;
|
||||
}(),
|
||||
}) c = "PASS";
|
||||
if (b) for (; "" == typeof d;);
|
||||
console.log(c, b);
|
||||
}
|
||||
expect: {
|
||||
var b = 42, c = "FAIL";
|
||||
for (function() {
|
||||
var a;
|
||||
}(), c = "PASS", b; "" == typeof d;);
|
||||
console.log(c, b);
|
||||
}
|
||||
expect_stdout: "PASS 42"
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ exports["parse"] = parse;
|
||||
exports["push_uniq"] = push_uniq;
|
||||
exports["reserve_quoted_keys"] = reserve_quoted_keys;
|
||||
exports["string_template"] = string_template;
|
||||
exports["to_ascii"] = to_ascii;
|
||||
exports["tokenizer"] = tokenizer;
|
||||
exports["TreeTransformer"] = TreeTransformer;
|
||||
exports["TreeWalker"] = TreeWalker;
|
||||
|
||||
8
test/input/issue-3441/input.js
Normal file
8
test/input/issue-3441/input.js
Normal file
@@ -0,0 +1,8 @@
|
||||
// Generated by CoffeeScript 2.4.1
|
||||
(function() {
|
||||
console.log('hello');
|
||||
|
||||
}).call(this);
|
||||
|
||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFpbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIm1haW4uY29mZmVlIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTtFQUFBLE9BQU8sQ0FBQyxHQUFSLENBQVksT0FBWjtBQUFBIiwic291cmNlc0NvbnRlbnQiOlsiY29uc29sZS5sb2cgJ2hlbGxvJ1xuIl19
|
||||
//# sourceURL=/Users/mohamed/Downloads/main.coffee
|
||||
@@ -48,53 +48,84 @@ describe("comments", function() {
|
||||
}
|
||||
});
|
||||
|
||||
it("Should handle comment within return correctly", function() {
|
||||
var result = UglifyJS.minify([
|
||||
"function unequal(x, y) {",
|
||||
" return (",
|
||||
" // Either one",
|
||||
" x < y",
|
||||
" ||",
|
||||
" y < x",
|
||||
" );",
|
||||
"}",
|
||||
].join("\n"), {
|
||||
compress: false,
|
||||
mangle: false,
|
||||
output: {
|
||||
beautify: true,
|
||||
comments: "all",
|
||||
},
|
||||
describe("comment within return", function() {
|
||||
it("Should handle leading return", function() {
|
||||
var result = UglifyJS.minify([
|
||||
"function unequal(x, 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, y) {",
|
||||
" // Either one",
|
||||
" return x < y || y < x;",
|
||||
"}",
|
||||
].join("\n"));
|
||||
});
|
||||
if (result.error) throw result.error;
|
||||
assert.strictEqual(result.code, [
|
||||
"function unequal(x, y) {",
|
||||
" // Either one",
|
||||
" return x < y || y < x;",
|
||||
"}",
|
||||
].join("\n"));
|
||||
});
|
||||
|
||||
it("Should handle comment folded into return correctly", function() {
|
||||
var result = UglifyJS.minify([
|
||||
"function f() {",
|
||||
" /* boo */ x();",
|
||||
" return y();",
|
||||
"}",
|
||||
].join("\n"), {
|
||||
mangle: false,
|
||||
output: {
|
||||
beautify: true,
|
||||
comments: "all",
|
||||
},
|
||||
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([
|
||||
"function f() {",
|
||||
" /* boo */ x();",
|
||||
" return y();",
|
||||
"}",
|
||||
].join("\n"), {
|
||||
mangle: false,
|
||||
output: {
|
||||
beautify: true,
|
||||
comments: "all",
|
||||
},
|
||||
});
|
||||
if (result.error) throw result.error;
|
||||
assert.strictEqual(result.code, [
|
||||
"function f() {",
|
||||
" /* boo */",
|
||||
" return x(), y();",
|
||||
"}",
|
||||
].join("\n"));
|
||||
});
|
||||
if (result.error) throw result.error;
|
||||
assert.strictEqual(result.code, [
|
||||
"function f() {",
|
||||
" /* boo */",
|
||||
" return x(), y();",
|
||||
"}",
|
||||
].join("\n"));
|
||||
});
|
||||
|
||||
it("Should not drop comments after first OutputStream", function() {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
var assert = require("assert");
|
||||
var readFileSync = require("fs").readFileSync;
|
||||
var SourceMapConsumer = require("source-map").SourceMapConsumer;
|
||||
var UglifyJS = require("../..");
|
||||
var UglifyJS = require("../node");
|
||||
|
||||
function read(path) {
|
||||
return readFileSync(path, "utf8");
|
||||
@@ -181,6 +181,18 @@ describe("sourcemaps", function() {
|
||||
if (result.error) throw result.error;
|
||||
assert.strictEqual(result.code + "\n", readFileSync("test/input/issue-3294/output.js", "utf8"));
|
||||
});
|
||||
it("Should work in presence of unrecognised annotations", function() {
|
||||
var result = UglifyJS.minify(read("./test/input/issue-3441/input.js"), {
|
||||
compress: false,
|
||||
mangle: false,
|
||||
sourceMap: {
|
||||
content: "inline",
|
||||
},
|
||||
});
|
||||
if (result.error) throw result.error;
|
||||
assert.strictEqual(result.code, '(function(){console.log("hello")}).call(this);');
|
||||
assert.strictEqual(result.map, '{"version":3,"sources":["main.coffee"],"names":["console","log"],"mappings":"CAAA,WAAAA,QAAQC,IAAI"}');
|
||||
});
|
||||
});
|
||||
|
||||
describe("sourceMapInline", function() {
|
||||
@@ -232,7 +244,7 @@ describe("sourcemaps", function() {
|
||||
assert.strictEqual(map.sourcesContent.length, 1);
|
||||
assert.strictEqual(map.sourcesContent[0], code);
|
||||
var encoded = result.code.slice(result.code.lastIndexOf(",") + 1);
|
||||
map = JSON.parse(new Buffer(encoded, "base64").toString());
|
||||
map = JSON.parse(UglifyJS.to_ascii(encoded));
|
||||
assert.strictEqual(map.sourcesContent.length, 1);
|
||||
assert.strictEqual(map.sourcesContent[0], code);
|
||||
result = UglifyJS.minify(result.code, {
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
setInterval(function() {
|
||||
process.stderr.write("\0");
|
||||
}, 8 * 60 * 1000).unref();
|
||||
require("./run")([
|
||||
"-b",
|
||||
"-b braces",
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
var child_process = require("child_process");
|
||||
var https = require("https");
|
||||
var url = require("url");
|
||||
|
||||
var period = 45 * 60 * 1000;
|
||||
var wait = 2 * 60 * 1000;
|
||||
var ping = 5 * 60 * 1000;
|
||||
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 branch = process.argv[3] || "v" + require("../package.json").version;
|
||||
var repository = encodeURIComponent(process.argv[4] || "mishoo/UglifyJS2");
|
||||
var concurrency = process.argv[5] || 1;
|
||||
var platform = process.argv[6] || "node/latest";
|
||||
(function request() {
|
||||
setTimeout(request, (period + wait) / concurrency);
|
||||
var options = url.parse("https://api.travis-ci.org/repo/" + repository + "/requests");
|
||||
options.method = "POST";
|
||||
options.headers = {
|
||||
"Content-Type": "application/json",
|
||||
"Travis-API-Version": 3,
|
||||
"Authorization": "token " + token
|
||||
};
|
||||
https.request(options, function(res) {
|
||||
console.log("HTTP", res.statusCode);
|
||||
console.log(JSON.stringify(res.headers, null, 2));
|
||||
console.log();
|
||||
res.setEncoding("utf8");
|
||||
res.on("data", console.log);
|
||||
}).on("error", console.error).end(JSON.stringify({
|
||||
request: {
|
||||
message: "ufuzz testing",
|
||||
branch: branch,
|
||||
config: {
|
||||
cache: false,
|
||||
env: "NODEJS_VER=" + platform,
|
||||
script: "node test/travis-ufuzz run"
|
||||
}
|
||||
}
|
||||
}));
|
||||
})();
|
||||
} else {
|
||||
console.log("Usage: test/travis-ufuzz.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);
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
44
test/ufuzz/travis.js
Normal file
44
test/ufuzz/travis.js
Normal file
@@ -0,0 +1,44 @@
|
||||
"use strict";
|
||||
|
||||
var child_process = require("child_process");
|
||||
var https = require("https");
|
||||
var url = require("url");
|
||||
|
||||
var period = 45 * 60 * 1000;
|
||||
var wait = 2 * 60 * 1000;
|
||||
if (process.argv.length > 2) {
|
||||
var token = process.argv[2];
|
||||
var branch = process.argv[3] || "v" + require("../../package.json").version;
|
||||
var repository = encodeURIComponent(process.argv[4] || "mishoo/UglifyJS2");
|
||||
var concurrency = process.argv[5] || 1;
|
||||
var platform = process.argv[6] || "latest";
|
||||
(function request() {
|
||||
setTimeout(request, (period + wait) / concurrency);
|
||||
var options = url.parse("https://api.travis-ci.org/repo/" + repository + "/requests");
|
||||
options.method = "POST";
|
||||
options.headers = {
|
||||
"Content-Type": "application/json",
|
||||
"Travis-API-Version": 3,
|
||||
"Authorization": "token " + token
|
||||
};
|
||||
https.request(options, function(res) {
|
||||
console.log("HTTP", res.statusCode);
|
||||
console.log(JSON.stringify(res.headers, null, 2));
|
||||
console.log();
|
||||
res.setEncoding("utf8");
|
||||
res.on("data", console.log);
|
||||
}).on("error", console.error).end(JSON.stringify({
|
||||
request: {
|
||||
message: "ufuzz testing",
|
||||
branch: branch,
|
||||
config: {
|
||||
cache: false,
|
||||
env: "NODE=" + platform,
|
||||
script: "node test/ufuzz/job " + period
|
||||
}
|
||||
}
|
||||
}));
|
||||
})();
|
||||
} else {
|
||||
console.log("Usage: test/ufuzz/travis.js <token> [branch] [repository] [concurrency] [platform]");
|
||||
}
|
||||
@@ -2702,8 +2702,10 @@
|
||||
"attrChange",
|
||||
"attrName",
|
||||
"attributeChangedCallback",
|
||||
"attributeFilter",
|
||||
"attributeName",
|
||||
"attributeNamespace",
|
||||
"attributeOldValue",
|
||||
"attributeStyleMap",
|
||||
"attributes",
|
||||
"audioTracks",
|
||||
@@ -3025,6 +3027,8 @@
|
||||
"charCode",
|
||||
"charCodeAt",
|
||||
"charIndex",
|
||||
"characterData",
|
||||
"characterDataOldValue",
|
||||
"characterSet",
|
||||
"charging",
|
||||
"chargingTime",
|
||||
@@ -3036,6 +3040,7 @@
|
||||
"checkValidity",
|
||||
"checked",
|
||||
"childElementCount",
|
||||
"childList",
|
||||
"childNodes",
|
||||
"children",
|
||||
"chrome",
|
||||
@@ -6150,6 +6155,7 @@
|
||||
"substring",
|
||||
"substringData",
|
||||
"subtle",
|
||||
"subtree",
|
||||
"suffix",
|
||||
"suffixes",
|
||||
"summary",
|
||||
|
||||
@@ -46,7 +46,9 @@ function describe_ast() {
|
||||
if (ctor.SUBCLASSES.length > 0) {
|
||||
out.space();
|
||||
out.with_block(function() {
|
||||
ctor.SUBCLASSES.forEach(function(ctor, i) {
|
||||
ctor.SUBCLASSES.sort(function(a, b) {
|
||||
return a.TYPE < b.TYPE ? -1 : 1;
|
||||
}).forEach(function(ctor, i) {
|
||||
out.indent();
|
||||
doitem(ctor);
|
||||
out.newline();
|
||||
|
||||
Reference in New Issue
Block a user