Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
74e36e4456 | ||
|
|
4382bfe848 | ||
|
|
b6f250f5c9 | ||
|
|
5d69545299 | ||
|
|
139fad0c05 | ||
|
|
99946a3993 | ||
|
|
053cb27fe3 | ||
|
|
25017978e7 | ||
|
|
f749863cb2 | ||
|
|
123f9cf987 | ||
|
|
a758b40e3f | ||
|
|
44e5e99aae | ||
|
|
be53c4838b | ||
|
|
0c7b016fa7 | ||
|
|
00665766da | ||
|
|
88b4283200 | ||
|
|
d2bd0d1c1c |
35
README.md
35
README.md
@@ -519,7 +519,8 @@ if (result.error) throw result.error;
|
|||||||
Pass an object to specify custom [mangle property options](#mangle-properties-options).
|
Pass an object to specify custom [mangle property options](#mangle-properties-options).
|
||||||
|
|
||||||
- `module` (default: `false`) — set to `true` if you wish to process input as
|
- `module` (default: `false`) — set to `true` if you wish to process input as
|
||||||
ES module, i.e. implicit `"use strict";` alongside with `toplevel` enabled.
|
ES module, i.e. implicit `"use strict";` and support for top-level `await`,
|
||||||
|
alongside with `toplevel` enabled.
|
||||||
|
|
||||||
- `nameCache` (default: `null`) — pass an empty object `{}` or a previously
|
- `nameCache` (default: `null`) — pass an empty object `{}` or a previously
|
||||||
used `nameCache` object if you wish to cache mangled variable and
|
used `nameCache` object if you wish to cache mangled variable and
|
||||||
@@ -632,7 +633,13 @@ to be `false` and all symbol names will be omitted.
|
|||||||
|
|
||||||
- `bare_returns` (default: `false`) — support top level `return` statements
|
- `bare_returns` (default: `false`) — support top level `return` statements
|
||||||
|
|
||||||
- `html5_comments` (default: `true`)
|
- `expression` (default: `false`) — parse as a single expression, e.g. JSON
|
||||||
|
|
||||||
|
- `html5_comments` (default: `true`) — process HTML comment as workaround for
|
||||||
|
browsers which do not recognise `<script>` tags
|
||||||
|
|
||||||
|
- `module` (default: `false`) — set to `true` if you wish to process input as
|
||||||
|
ES module, i.e. implicit `"use strict";` and support for top-level `await`.
|
||||||
|
|
||||||
- `shebang` (default: `true`) — support `#!command` as the first line
|
- `shebang` (default: `true`) — support `#!command` as the first line
|
||||||
|
|
||||||
@@ -811,8 +818,9 @@ to be `false` and all symbol names will be omitted.
|
|||||||
|
|
||||||
- `unsafe` (default: `false`) — apply "unsafe" transformations (discussion below)
|
- `unsafe` (default: `false`) — apply "unsafe" transformations (discussion below)
|
||||||
|
|
||||||
- `unsafe_comps` (default: `false`) — compress expressions like `a <= b` assuming
|
- `unsafe_comps` (default: `false`) — assume operands cannot be (coerced to) `NaN`
|
||||||
none of the operands can be (coerced to) `NaN`.
|
in numeric comparisons, e.g. `a <= b`. In addition, expressions involving `in`
|
||||||
|
or `instanceof` would never throw.
|
||||||
|
|
||||||
- `unsafe_Function` (default: `false`) — compress and mangle `Function(args, code)`
|
- `unsafe_Function` (default: `false`) — compress and mangle `Function(args, code)`
|
||||||
when both `args` and `code` are string literals.
|
when both `args` and `code` are string literals.
|
||||||
@@ -1415,9 +1423,20 @@ To allow for better optimizations, the compiler makes various assumptions:
|
|||||||
function f() {
|
function f() {
|
||||||
throw 42;
|
throw 42;
|
||||||
}
|
}
|
||||||
} catch (e) {}
|
} catch (e) {
|
||||||
console.log(typeof f);
|
console.log(typeof f, e);
|
||||||
// Expected: "function"
|
}
|
||||||
// Actual: "undefined"
|
// Expected: "function 42"
|
||||||
|
// Actual: "undefined 42"
|
||||||
|
```
|
||||||
|
UglifyJS may modify the input which in turn may suppress those errors.
|
||||||
|
- Later versions of JavaScript will throw `SyntaxError` with the following:
|
||||||
|
```javascript
|
||||||
|
"use strict";
|
||||||
|
console.log(function f() {
|
||||||
|
return f = "PASS";
|
||||||
|
}());
|
||||||
|
// Expected: "PASS"
|
||||||
|
// Actual: TypeError: invalid assignment to const 'f'
|
||||||
```
|
```
|
||||||
UglifyJS may modify the input which in turn may suppress those errors.
|
UglifyJS may modify the input which in turn may suppress those errors.
|
||||||
|
|||||||
23
lib/ast.js
23
lib/ast.js
@@ -534,7 +534,7 @@ var AST_With = DEFNODE("With", "expression", {
|
|||||||
/* -----[ scope and functions ]----- */
|
/* -----[ scope and functions ]----- */
|
||||||
|
|
||||||
var AST_Scope = DEFNODE("Scope", "fn_defs may_call_this uses_eval uses_with", {
|
var AST_Scope = DEFNODE("Scope", "fn_defs may_call_this uses_eval uses_with", {
|
||||||
$documentation: "Base class for all statements introducing a lexical scope",
|
$documentation: "Base class for all statements introducing a lambda scope",
|
||||||
$propdoc: {
|
$propdoc: {
|
||||||
uses_eval: "[boolean/S] tells whether this scope contains a direct call to the global `eval`",
|
uses_eval: "[boolean/S] tells whether this scope contains a direct call to the global `eval`",
|
||||||
uses_with: "[boolean/S] tells whether this scope uses the `with` statement",
|
uses_with: "[boolean/S] tells whether this scope uses the `with` statement",
|
||||||
@@ -592,6 +592,10 @@ var AST_Toplevel = DEFNODE("Toplevel", "globals", {
|
|||||||
}
|
}
|
||||||
}, AST_Scope);
|
}, AST_Scope);
|
||||||
|
|
||||||
|
var AST_ClassInitBlock = DEFNODE("ClassInitBlock", null, {
|
||||||
|
$documentation: "Value for `class` static initialization blocks",
|
||||||
|
}, AST_Scope);
|
||||||
|
|
||||||
var AST_Lambda = DEFNODE("Lambda", "argnames length_read rest safe_ids uses_arguments", {
|
var AST_Lambda = DEFNODE("Lambda", "argnames length_read rest safe_ids uses_arguments", {
|
||||||
$documentation: "Base class for functions",
|
$documentation: "Base class for functions",
|
||||||
$propdoc: {
|
$propdoc: {
|
||||||
@@ -874,7 +878,7 @@ var AST_ClassExpression = DEFNODE("ClassExpression", null, {
|
|||||||
var AST_ClassProperty = DEFNODE("ClassProperty", "key private static value", {
|
var AST_ClassProperty = DEFNODE("ClassProperty", "key private static value", {
|
||||||
$documentation: "Base class for `class` properties",
|
$documentation: "Base class for `class` properties",
|
||||||
$propdoc: {
|
$propdoc: {
|
||||||
key: "[string|AST_Node] property name (AST_Node for computed property)",
|
key: "[string|AST_Node?] property name (AST_Node for computed property, null for initialization block)",
|
||||||
private: "[boolean] whether this is a private property",
|
private: "[boolean] whether this is a private property",
|
||||||
static: "[boolean] whether this is a static property",
|
static: "[boolean] whether this is a static property",
|
||||||
value: "[AST_Node?] property value (AST_Accessor for getters/setters, AST_LambdaExpression for methods, null if not specified for fields)",
|
value: "[AST_Node?] property value (AST_Accessor for getters/setters, AST_LambdaExpression for methods, null if not specified for fields)",
|
||||||
@@ -888,7 +892,9 @@ var AST_ClassProperty = DEFNODE("ClassProperty", "key private static value", {
|
|||||||
},
|
},
|
||||||
_validate: function() {
|
_validate: function() {
|
||||||
if (this.TYPE == "ClassProperty") throw new Error("should not instantiate AST_ClassProperty");
|
if (this.TYPE == "ClassProperty") throw new Error("should not instantiate AST_ClassProperty");
|
||||||
if (typeof this.key != "string") {
|
if (this instanceof AST_ClassInit) {
|
||||||
|
if (this.key != null) throw new Error("key must be null");
|
||||||
|
} else if (typeof this.key != "string") {
|
||||||
if (!(this.key instanceof AST_Node)) throw new Error("key must be string or AST_Node");
|
if (!(this.key instanceof AST_Node)) throw new Error("key must be string or AST_Node");
|
||||||
must_be_expression(this, "key");
|
must_be_expression(this, "key");
|
||||||
}
|
}
|
||||||
@@ -928,6 +934,17 @@ var AST_ClassMethod = DEFNODE("ClassMethod", null, {
|
|||||||
},
|
},
|
||||||
}, AST_ClassProperty);
|
}, AST_ClassProperty);
|
||||||
|
|
||||||
|
var AST_ClassInit = DEFNODE("ClassInit", null, {
|
||||||
|
$documentation: "A `class` static initialization block",
|
||||||
|
_validate: function() {
|
||||||
|
if (!this.static) throw new Error("static must be true");
|
||||||
|
if (!(this.value instanceof AST_ClassInitBlock)) throw new Error("value must be AST_ClassInitBlock");
|
||||||
|
},
|
||||||
|
initialize: function() {
|
||||||
|
this.static = true;
|
||||||
|
},
|
||||||
|
}, AST_ClassProperty);
|
||||||
|
|
||||||
/* -----[ JUMPS ]----- */
|
/* -----[ JUMPS ]----- */
|
||||||
|
|
||||||
var AST_Jump = DEFNODE("Jump", null, {
|
var AST_Jump = DEFNODE("Jump", null, {
|
||||||
|
|||||||
228
lib/compress.js
228
lib/compress.js
@@ -1146,7 +1146,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
props.forEach(function(prop) {
|
props.forEach(function(prop) {
|
||||||
if (!prop.static || prop instanceof AST_ClassField && prop.value.contains_this()) {
|
if (!prop.static || is_static_field_or_init(prop) && prop.value.contains_this()) {
|
||||||
push(tw);
|
push(tw);
|
||||||
prop.value.walk(tw);
|
prop.value.walk(tw);
|
||||||
pop(tw);
|
pop(tw);
|
||||||
@@ -1156,6 +1156,14 @@ Compressor.prototype.compress = function(node) {
|
|||||||
});
|
});
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
def(AST_ClassInitBlock, function(tw, descend, compressor) {
|
||||||
|
var node = this;
|
||||||
|
push(tw);
|
||||||
|
reset_variables(tw, compressor, node);
|
||||||
|
descend();
|
||||||
|
pop_scope(tw, node);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
def(AST_Conditional, function(tw) {
|
def(AST_Conditional, function(tw) {
|
||||||
this.condition.walk(tw);
|
this.condition.walk(tw);
|
||||||
push(tw);
|
push(tw);
|
||||||
@@ -1843,6 +1851,10 @@ Compressor.prototype.compress = function(node) {
|
|||||||
|| compressor.option("unsafe") && global_names[this.name];
|
|| compressor.option("unsafe") && global_names[this.name];
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function is_static_field_or_init(prop) {
|
||||||
|
return prop.static && prop.value && (prop instanceof AST_ClassField || prop instanceof AST_ClassInit);
|
||||||
|
}
|
||||||
|
|
||||||
function declarations_only(node) {
|
function declarations_only(node) {
|
||||||
return all(node.definitions, function(var_def) {
|
return all(node.definitions, function(var_def) {
|
||||||
return !var_def.value;
|
return !var_def.value;
|
||||||
@@ -1852,8 +1864,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
function is_declaration(stat, lexical) {
|
function is_declaration(stat, lexical) {
|
||||||
if (stat instanceof AST_DefClass) return lexical && !stat.extends && all(stat.properties, function(prop) {
|
if (stat instanceof AST_DefClass) return lexical && !stat.extends && all(stat.properties, function(prop) {
|
||||||
if (prop.key instanceof AST_Node) return false;
|
if (prop.key instanceof AST_Node) return false;
|
||||||
if (prop instanceof AST_ClassField && prop.static && prop.value) return false;
|
return !is_static_field_or_init(prop);
|
||||||
return true;
|
|
||||||
});
|
});
|
||||||
if (stat instanceof AST_Definitions) return (lexical || stat instanceof AST_Var) && declarations_only(stat);
|
if (stat instanceof AST_Definitions) return (lexical || stat instanceof AST_Var) && declarations_only(stat);
|
||||||
if (stat instanceof AST_ExportDeclaration) return is_declaration(stat.body, lexical);
|
if (stat instanceof AST_ExportDeclaration) return is_declaration(stat.body, lexical);
|
||||||
@@ -2172,7 +2183,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
can_replace = replace;
|
can_replace = replace;
|
||||||
return signal_abort(node);
|
return signal_abort(node);
|
||||||
}
|
}
|
||||||
return handle_custom_scan_order(node, scanner);
|
if (handle_custom_scan_order(node, scanner)) return signal_abort(node);
|
||||||
}, signal_abort);
|
}, signal_abort);
|
||||||
var multi_replacer = new TreeTransformer(function(node) {
|
var multi_replacer = new TreeTransformer(function(node) {
|
||||||
if (abort) return node;
|
if (abort) return node;
|
||||||
@@ -2334,14 +2345,33 @@ Compressor.prototype.compress = function(node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function handle_custom_scan_order(node, tt) {
|
function handle_custom_scan_order(node, tt) {
|
||||||
if (!(node instanceof AST_BlockScope)) {
|
if (!(node instanceof AST_BlockScope)) return;
|
||||||
if (!(node instanceof AST_ClassProperty && !node.static)) return;
|
|
||||||
// Skip non-static class property values
|
|
||||||
if (node.key instanceof AST_Node) node.key = node.key.transform(tt);
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
// Skip (non-executed) functions
|
// Skip (non-executed) functions
|
||||||
if (node instanceof AST_Scope) return node;
|
if (node instanceof AST_Scope) return node;
|
||||||
|
// Scan computed keys, static fields & initializers in class
|
||||||
|
if (node instanceof AST_Class) {
|
||||||
|
if (node.name) node.name = node.name.transform(tt);
|
||||||
|
if (!abort && node.extends) node.extends = node.extends.transform(tt);
|
||||||
|
var fields = [], stats = [];
|
||||||
|
for (var i = 0; !abort && i < node.properties.length; i++) {
|
||||||
|
var prop = node.properties[i];
|
||||||
|
if (prop.key instanceof AST_Node) prop.key = prop.key.transform(tt);
|
||||||
|
if (!prop.static) continue;
|
||||||
|
if (prop instanceof AST_ClassField) {
|
||||||
|
if (prop.value) fields.push(prop);
|
||||||
|
} else if (prop instanceof AST_ClassInit) {
|
||||||
|
[].push.apply(stats, prop.value.body);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (var i = 0; !abort && i < stats.length; i++) {
|
||||||
|
stats[i].transform(tt);
|
||||||
|
}
|
||||||
|
for (var i = 0; !abort && i < fields.length; i++) {
|
||||||
|
var prop = fields[i];
|
||||||
|
prop.value = prop.value.transform(tt);
|
||||||
|
}
|
||||||
|
return node;
|
||||||
|
}
|
||||||
// Scan object only in a for-in/of statement
|
// Scan object only in a for-in/of statement
|
||||||
if (node instanceof AST_ForEnumeration) {
|
if (node instanceof AST_ForEnumeration) {
|
||||||
node.object = node.object.transform(tt);
|
node.object = node.object.transform(tt);
|
||||||
@@ -2427,7 +2457,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
|
|
||||||
function is_last_node(node, parent) {
|
function is_last_node(node, parent) {
|
||||||
if (node instanceof AST_Await) return true;
|
if (node instanceof AST_Await) return true;
|
||||||
if (node.TYPE == "Binary") return node.operator == "in" && !is_object(node.right);
|
if (node.TYPE == "Binary") return !can_drop_op(node.operator, node.right, compressor);
|
||||||
if (node instanceof AST_Call) {
|
if (node instanceof AST_Call) {
|
||||||
var def, fn = node.expression;
|
var def, fn = node.expression;
|
||||||
if (fn instanceof AST_SymbolRef) {
|
if (fn instanceof AST_SymbolRef) {
|
||||||
@@ -2820,6 +2850,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
}
|
}
|
||||||
return find_stop_logical(parent, op, level);
|
return find_stop_logical(parent, op, level);
|
||||||
}
|
}
|
||||||
|
if (parent instanceof AST_Await) return find_stop_value(parent, level + 1);
|
||||||
if (parent instanceof AST_Binary) {
|
if (parent instanceof AST_Binary) {
|
||||||
var op;
|
var op;
|
||||||
if (parent.left === node || !lazy_op[op = parent.operator]) {
|
if (parent.left === node || !lazy_op[op = parent.operator]) {
|
||||||
@@ -5525,7 +5556,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
def(AST_Binary, function(compressor) {
|
def(AST_Binary, function(compressor) {
|
||||||
return this.left.has_side_effects(compressor)
|
return this.left.has_side_effects(compressor)
|
||||||
|| this.right.has_side_effects(compressor)
|
|| this.right.has_side_effects(compressor)
|
||||||
|| this.operator == "in" && !is_object(this.right);
|
|| !can_drop_op(this.operator, this.right, compressor);
|
||||||
});
|
});
|
||||||
def(AST_Block, function(compressor) {
|
def(AST_Block, function(compressor) {
|
||||||
return any(this.body, compressor);
|
return any(this.body, compressor);
|
||||||
@@ -5679,7 +5710,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
def(AST_Binary, function(compressor) {
|
def(AST_Binary, function(compressor) {
|
||||||
return this.left.may_throw(compressor)
|
return this.left.may_throw(compressor)
|
||||||
|| this.right.may_throw(compressor)
|
|| this.right.may_throw(compressor)
|
||||||
|| this.operator == "in" && !is_object(this.right);
|
|| !can_drop_op(this.operator, this.right, compressor);
|
||||||
});
|
});
|
||||||
def(AST_Block, function(compressor) {
|
def(AST_Block, function(compressor) {
|
||||||
return any(this.body, compressor);
|
return any(this.body, compressor);
|
||||||
@@ -5796,7 +5827,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
def(AST_Binary, function(scope) {
|
def(AST_Binary, function(scope) {
|
||||||
return this.left.is_constant_expression(scope)
|
return this.left.is_constant_expression(scope)
|
||||||
&& this.right.is_constant_expression(scope)
|
&& this.right.is_constant_expression(scope)
|
||||||
&& (this.operator != "in" || is_object(this.right));
|
&& can_drop_op(this.operator, this.right);
|
||||||
});
|
});
|
||||||
def(AST_Class, function(scope) {
|
def(AST_Class, function(scope) {
|
||||||
var base = this.extends;
|
var base = this.extends;
|
||||||
@@ -6608,6 +6639,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
var for_ins = Object.create(null);
|
var for_ins = Object.create(null);
|
||||||
var in_use = [];
|
var in_use = [];
|
||||||
var in_use_ids = Object.create(null); // avoid expensive linear scans of in_use
|
var in_use_ids = Object.create(null); // avoid expensive linear scans of in_use
|
||||||
|
var lambda_ids = Object.create(null);
|
||||||
var value_read = Object.create(null);
|
var value_read = Object.create(null);
|
||||||
var value_modified = Object.create(null);
|
var value_modified = Object.create(null);
|
||||||
var var_defs = Object.create(null);
|
var var_defs = Object.create(null);
|
||||||
@@ -6643,15 +6675,19 @@ Compressor.prototype.compress = function(node) {
|
|||||||
in_use_ids[def.id] = true;
|
in_use_ids[def.id] = true;
|
||||||
in_use.push(def);
|
in_use.push(def);
|
||||||
}
|
}
|
||||||
if (node.extends) node.extends.walk(tw);
|
|
||||||
var used = tw.parent() instanceof AST_ExportDefault;
|
var used = tw.parent() instanceof AST_ExportDefault;
|
||||||
if (used) export_defaults[def.id] = true;
|
if (used) {
|
||||||
|
export_defaults[def.id] = true;
|
||||||
|
} else if (drop && !(def.id in lambda_ids)) {
|
||||||
|
lambda_ids[def.id] = 1;
|
||||||
|
}
|
||||||
|
if (node.extends) node.extends.walk(tw);
|
||||||
var values = [];
|
var values = [];
|
||||||
node.properties.forEach(function(prop) {
|
node.properties.forEach(function(prop) {
|
||||||
if (prop.key instanceof AST_Node) prop.key.walk(tw);
|
if (prop.key instanceof AST_Node) prop.key.walk(tw);
|
||||||
var value = prop.value;
|
var value = prop.value;
|
||||||
if (!value) return;
|
if (!value) return;
|
||||||
if (prop instanceof AST_ClassField && prop.static) {
|
if (is_static_field_or_init(prop)) {
|
||||||
if (!used && value.contains_this()) used = true;
|
if (!used && value.contains_this()) used = true;
|
||||||
walk_class_prop(value);
|
walk_class_prop(value);
|
||||||
} else {
|
} else {
|
||||||
@@ -6665,16 +6701,18 @@ Compressor.prototype.compress = function(node) {
|
|||||||
}
|
}
|
||||||
if (node instanceof AST_LambdaDefinition) {
|
if (node instanceof AST_LambdaDefinition) {
|
||||||
var def = node.name.definition();
|
var def = node.name.definition();
|
||||||
if ((!drop_funcs || def.exported) && !(def.id in in_use_ids)) {
|
var drop = drop_funcs && !def.exported;
|
||||||
|
if (!drop && !(def.id in in_use_ids)) {
|
||||||
in_use_ids[def.id] = true;
|
in_use_ids[def.id] = true;
|
||||||
in_use.push(def);
|
in_use.push(def);
|
||||||
}
|
}
|
||||||
initializations.add(def.id, node);
|
initializations.add(def.id, node);
|
||||||
if (tw.parent() instanceof AST_ExportDefault) {
|
if (tw.parent() instanceof AST_ExportDefault) {
|
||||||
export_defaults[def.id] = true;
|
export_defaults[def.id] = true;
|
||||||
} else {
|
return;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
if (drop && !(def.id in lambda_ids)) lambda_ids[def.id] = 1;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
if (node instanceof AST_Definitions) {
|
if (node instanceof AST_Definitions) {
|
||||||
node.definitions.forEach(function(defn) {
|
node.definitions.forEach(function(defn) {
|
||||||
@@ -6704,6 +6742,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
}
|
}
|
||||||
assignments.add(def.id, defn);
|
assignments.add(def.id, defn);
|
||||||
}
|
}
|
||||||
|
unmark_lambda(def);
|
||||||
return true;
|
return true;
|
||||||
}, tw);
|
}, tw);
|
||||||
if (side_effects) value.walk(tw);
|
if (side_effects) value.walk(tw);
|
||||||
@@ -6895,6 +6934,14 @@ Compressor.prototype.compress = function(node) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (node instanceof AST_Binary && node.operator == "instanceof") {
|
||||||
|
var sym = node.right;
|
||||||
|
if (!(sym instanceof AST_SymbolRef)) return;
|
||||||
|
if (sym.definition().id in in_use_ids) return;
|
||||||
|
var lhs = node.left.drop_side_effect_free(compressor);
|
||||||
|
var value = make_node(AST_False, node).optimize(compressor);
|
||||||
|
return lhs ? make_sequence(node, [ lhs, value ]) : value;
|
||||||
|
}
|
||||||
if (node instanceof AST_Call) {
|
if (node instanceof AST_Call) {
|
||||||
calls_to_drop_args.push(node);
|
calls_to_drop_args.push(node);
|
||||||
node.args = node.args.map(function(arg) {
|
node.args = node.args.map(function(arg) {
|
||||||
@@ -7437,6 +7484,14 @@ Compressor.prototype.compress = function(node) {
|
|||||||
return nodes && nodes.indexOf(node);
|
return nodes && nodes.indexOf(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function unmark_lambda(def) {
|
||||||
|
if (lambda_ids[def.id] > 1 && !(def.id in in_use_ids)) {
|
||||||
|
in_use_ids[def.id] = true;
|
||||||
|
in_use.push(def);
|
||||||
|
}
|
||||||
|
lambda_ids[def.id] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
function verify_safe_usage(def, read, modified) {
|
function verify_safe_usage(def, read, modified) {
|
||||||
if (def.id in in_use_ids) return;
|
if (def.id in in_use_ids) return;
|
||||||
if (read && modified) {
|
if (read && modified) {
|
||||||
@@ -7488,17 +7543,18 @@ Compressor.prototype.compress = function(node) {
|
|||||||
var def = node.expression.definition();
|
var def = node.expression.definition();
|
||||||
if (def.scope.resolve() === self) assignments.add(def.id, node);
|
if (def.scope.resolve() === self) assignments.add(def.id, node);
|
||||||
}
|
}
|
||||||
var node_def, props = [], sym = assign_as_unused(node, props);
|
var props = [], sym = assign_as_unused(node, props);
|
||||||
if (sym && ((node_def = sym.definition()).scope.resolve() === self
|
if (sym) {
|
||||||
|| self.variables.get(sym.name) === node_def)
|
var node_def = sym.definition();
|
||||||
&& !(is_arguments(node_def) && !all(self.argnames, function(argname) {
|
if (node_def.scope.resolve() !== self && self.variables.get(sym.name) !== node_def) return;
|
||||||
|
if (is_arguments(node_def) && !all(self.argnames, function(argname) {
|
||||||
return !argname.match_symbol(function(node) {
|
return !argname.match_symbol(function(node) {
|
||||||
if (node instanceof AST_SymbolFunarg) {
|
if (node instanceof AST_SymbolFunarg) {
|
||||||
var def = node.definition();
|
var def = node.definition();
|
||||||
return def.references.length > def.replaced;
|
return def.references.length > def.replaced;
|
||||||
}
|
}
|
||||||
}, true);
|
}, true);
|
||||||
}))) {
|
})) return;
|
||||||
if (node.write_only === "p" && node.right.may_throw_on_access(compressor, true)) return;
|
if (node.write_only === "p" && node.right.may_throw_on_access(compressor, true)) return;
|
||||||
var assign = props.assign;
|
var assign = props.assign;
|
||||||
if (assign) {
|
if (assign) {
|
||||||
@@ -7528,6 +7584,17 @@ Compressor.prototype.compress = function(node) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (track_assigns(node_def, sym) && is_lhs(sym, node) !== sym) add_assigns(node_def, sym);
|
if (track_assigns(node_def, sym) && is_lhs(sym, node) !== sym) add_assigns(node_def, sym);
|
||||||
|
unmark_lambda(node_def);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (node instanceof AST_Binary) {
|
||||||
|
if (node.operator != "instanceof") return;
|
||||||
|
var sym = node.right;
|
||||||
|
if (!(sym instanceof AST_SymbolRef)) return;
|
||||||
|
var id = sym.definition().id;
|
||||||
|
if (!lambda_ids[id]) return;
|
||||||
|
node.left.walk(tw);
|
||||||
|
lambda_ids[id]++;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (node instanceof AST_ForIn) {
|
if (node instanceof AST_ForIn) {
|
||||||
@@ -7549,7 +7616,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (node instanceof AST_SymbolRef) {
|
if (node instanceof AST_SymbolRef) {
|
||||||
node_def = node.definition();
|
var node_def = node.definition();
|
||||||
if (!(node_def.id in in_use_ids)) {
|
if (!(node_def.id in in_use_ids)) {
|
||||||
in_use_ids[node_def.id] = true;
|
in_use_ids[node_def.id] = true;
|
||||||
in_use.push(node_def);
|
in_use.push(node_def);
|
||||||
@@ -8299,8 +8366,10 @@ Compressor.prototype.compress = function(node) {
|
|||||||
if (fixed.escaped && fixed.escaped.depth == 1) return;
|
if (fixed.escaped && fixed.escaped.depth == 1) return;
|
||||||
return right instanceof AST_Object
|
return right instanceof AST_Object
|
||||||
&& right.properties.length > 0
|
&& right.properties.length > 0
|
||||||
&& all(right.properties, can_hoist_property)
|
&& can_drop_symbol(sym, compressor)
|
||||||
&& can_drop_symbol(sym, compressor);
|
&& all(right.properties, function(prop) {
|
||||||
|
return can_hoist_property(prop) && prop.key !== "__proto__";
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -8505,7 +8574,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
var left = this.left;
|
var left = this.left;
|
||||||
var right = this.right;
|
var right = this.right;
|
||||||
var op = this.operator;
|
var op = this.operator;
|
||||||
if (op == "in" && !is_object(right)) {
|
if (!can_drop_op(op, right, compressor)) {
|
||||||
var lhs = left.drop_side_effect_free(compressor, first_in_statement);
|
var lhs = left.drop_side_effect_free(compressor, first_in_statement);
|
||||||
if (lhs === left) return this;
|
if (lhs === left) return this;
|
||||||
var node = this.clone();
|
var node = this.clone();
|
||||||
@@ -8595,16 +8664,20 @@ Compressor.prototype.compress = function(node) {
|
|||||||
});
|
});
|
||||||
def(AST_ClassExpression, function(compressor, first_in_statement) {
|
def(AST_ClassExpression, function(compressor, first_in_statement) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var exprs = [], values = [];
|
var exprs = [], values = [], init = 0;
|
||||||
var props = self.properties;
|
var props = self.properties;
|
||||||
for (var i = 0; i < props.length; i++) {
|
for (var i = 0; i < props.length; i++) {
|
||||||
var prop = props[i];
|
var prop = props[i];
|
||||||
if (prop.key instanceof AST_Node) exprs.push(prop.key);
|
if (prop.key instanceof AST_Node) exprs.push(prop.key);
|
||||||
if (prop.static && prop.value
|
if (!is_static_field_or_init(prop)) continue;
|
||||||
&& prop instanceof AST_ClassField
|
var value = prop.value;
|
||||||
&& prop.value.has_side_effects(compressor)) {
|
if (!value.has_side_effects(compressor)) continue;
|
||||||
if (prop.value.contains_this()) return self;
|
if (value.contains_this()) return self;
|
||||||
values.push(prop.value);
|
if (prop instanceof AST_ClassInit) {
|
||||||
|
init++;
|
||||||
|
values.push(prop);
|
||||||
|
} else {
|
||||||
|
values.push(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var base = self.extends;
|
var base = self.extends;
|
||||||
@@ -8625,31 +8698,47 @@ Compressor.prototype.compress = function(node) {
|
|||||||
if (!base) node.extends = null;
|
if (!base) node.extends = null;
|
||||||
node.properties = [];
|
node.properties = [];
|
||||||
if (values) {
|
if (values) {
|
||||||
node.properties.push(make_node(AST_ClassField, self, {
|
if (values.length == init) {
|
||||||
|
if (exprs.length) values.unshift(make_node(AST_ClassField, self, {
|
||||||
|
key: make_sequence(self, exprs),
|
||||||
|
value: null,
|
||||||
|
}));
|
||||||
|
node.properties = values;
|
||||||
|
} else node.properties.push(make_node(AST_ClassField, self, {
|
||||||
static: true,
|
static: true,
|
||||||
key: exprs.length ? make_sequence(self, exprs) : "c",
|
key: exprs.length ? make_sequence(self, exprs) : "c",
|
||||||
value: make_sequence(self, values),
|
value: make_value(),
|
||||||
}));
|
}));
|
||||||
} else if (exprs.length) {
|
} else if (exprs.length) node.properties.push(make_node(AST_ClassMethod, self, {
|
||||||
node.properties.push(make_node(AST_ClassMethod, self, {
|
key: make_sequence(self, exprs),
|
||||||
key: make_sequence(self, exprs),
|
value: make_node(AST_Function, self, {
|
||||||
value: make_node(AST_Function, self, {
|
argnames: [],
|
||||||
argnames: [],
|
body: [],
|
||||||
body: [],
|
}).init_vars(node),
|
||||||
}).init_vars(node),
|
}));
|
||||||
}));
|
|
||||||
}
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
if (values) exprs.push(make_node(AST_Call, self, {
|
if (values) exprs.push(make_node(AST_Call, self, {
|
||||||
expression: make_node(AST_Arrow, self, {
|
expression: make_node(AST_Arrow, self, {
|
||||||
argnames: [],
|
argnames: [],
|
||||||
body: [],
|
body: [],
|
||||||
value: make_sequence(self, values),
|
value: make_value(),
|
||||||
}).init_vars(self.parent_scope),
|
}).init_vars(self.parent_scope),
|
||||||
args: [],
|
args: [],
|
||||||
}));
|
}));
|
||||||
return make_sequence(self, exprs);
|
return make_sequence(self, exprs);
|
||||||
|
|
||||||
|
function make_value() {
|
||||||
|
return make_sequence(self, values.map(function(node) {
|
||||||
|
if (!(node instanceof AST_ClassInit)) return node;
|
||||||
|
var fn = make_node(AST_Arrow, node, node.value);
|
||||||
|
fn.argnames = [];
|
||||||
|
return make_node(AST_Call, node, {
|
||||||
|
expression: fn,
|
||||||
|
args: [],
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
def(AST_Conditional, function(compressor) {
|
def(AST_Conditional, function(compressor) {
|
||||||
var consequent = this.consequent.drop_side_effect_free(compressor);
|
var consequent = this.consequent.drop_side_effect_free(compressor);
|
||||||
@@ -9927,9 +10016,12 @@ Compressor.prototype.compress = function(node) {
|
|||||||
}) : arg);
|
}) : arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
function avoid_await_yield(parent_scope) {
|
function avoid_await_yield(compressor, parent_scope) {
|
||||||
|
if (!parent_scope) parent_scope = compressor.find_parent(AST_Scope);
|
||||||
var avoid = [];
|
var avoid = [];
|
||||||
if (is_async(parent_scope)) avoid.push("await");
|
if (is_async(parent_scope) || parent_scope instanceof AST_Toplevel && compressor.option("module")) {
|
||||||
|
avoid.push("await");
|
||||||
|
}
|
||||||
if (is_generator(parent_scope)) avoid.push("yield");
|
if (is_generator(parent_scope)) avoid.push("yield");
|
||||||
return avoid.length && makePredicate(avoid);
|
return avoid.length && makePredicate(avoid);
|
||||||
}
|
}
|
||||||
@@ -10291,7 +10383,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
if (exp === fn
|
if (exp === fn
|
||||||
&& !fn.name
|
&& !fn.name
|
||||||
&& (!value || value.is_constant_expression())
|
&& (!value || value.is_constant_expression())
|
||||||
&& safe_from_await_yield(fn, avoid_await_yield(compressor.find_parent(AST_Scope)))) {
|
&& safe_from_await_yield(fn, avoid_await_yield(compressor))) {
|
||||||
return make_sequence(self, convert_args(value)).optimize(compressor);
|
return make_sequence(self, convert_args(value)).optimize(compressor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -10369,7 +10461,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
&& all(fn.body, is_empty)
|
&& all(fn.body, is_empty)
|
||||||
&& (fn === exp ? fn_name_unused(fn, compressor) : !has_default && !has_destructured && !fn.rest)
|
&& (fn === exp ? fn_name_unused(fn, compressor) : !has_default && !has_destructured && !fn.rest)
|
||||||
&& !(is_arrow(fn) && fn.value)
|
&& !(is_arrow(fn) && fn.value)
|
||||||
&& safe_from_await_yield(fn, avoid_await_yield(compressor.find_parent(AST_Scope)))) {
|
&& safe_from_await_yield(fn, avoid_await_yield(compressor))) {
|
||||||
return make_sequence(self, convert_args()).optimize(compressor);
|
return make_sequence(self, convert_args()).optimize(compressor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -10528,7 +10620,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
})) return;
|
})) return;
|
||||||
var scope = compressor.find_parent(AST_Scope);
|
var scope = compressor.find_parent(AST_Scope);
|
||||||
var abort = false;
|
var abort = false;
|
||||||
var avoid = avoid_await_yield(scope);
|
var avoid = avoid_await_yield(compressor, scope);
|
||||||
var begin;
|
var begin;
|
||||||
var in_order = [];
|
var in_order = [];
|
||||||
var side_effects = false;
|
var side_effects = false;
|
||||||
@@ -10643,7 +10735,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
} while (!(scope instanceof AST_Scope));
|
} while (!(scope instanceof AST_Scope));
|
||||||
insert = scope.body.indexOf(child) + 1;
|
insert = scope.body.indexOf(child) + 1;
|
||||||
if (!insert) return false;
|
if (!insert) return false;
|
||||||
if (!safe_from_await_yield(fn, avoid_await_yield(scope))) return false;
|
if (!safe_from_await_yield(fn, avoid_await_yield(compressor, scope))) return false;
|
||||||
var safe_to_inject = (exp !== fn || fn.parent_scope.resolve() === scope) && !scope.pinned();
|
var safe_to_inject = (exp !== fn || fn.parent_scope.resolve() === scope) && !scope.pinned();
|
||||||
if (scope instanceof AST_Toplevel) {
|
if (scope instanceof AST_Toplevel) {
|
||||||
if (compressor.toplevel.vars) {
|
if (compressor.toplevel.vars) {
|
||||||
@@ -11151,6 +11243,18 @@ Compressor.prototype.compress = function(node) {
|
|||||||
|| node instanceof AST_Object;
|
|| node instanceof AST_Object;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function can_drop_op(op, rhs, compressor) {
|
||||||
|
switch (op) {
|
||||||
|
case "in":
|
||||||
|
return is_object(rhs) || compressor && compressor.option("unsafe_comps");
|
||||||
|
case "instanceof":
|
||||||
|
if (rhs instanceof AST_SymbolRef) rhs = rhs.fixed_value();
|
||||||
|
return is_lambda(rhs) || compressor && compressor.option("unsafe_comps");
|
||||||
|
default:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function is_primitive(compressor, node) {
|
function is_primitive(compressor, node) {
|
||||||
if (node.is_constant()) return true;
|
if (node.is_constant()) return true;
|
||||||
if (node instanceof AST_Assign) return node.operator != "=" || is_primitive(compressor, node.right);
|
if (node instanceof AST_Assign) return node.operator != "=" || is_primitive(compressor, node.right);
|
||||||
@@ -11657,6 +11761,12 @@ Compressor.prototype.compress = function(node) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case "instanceof":
|
||||||
|
if (is_lambda(self.right)) return make_sequence(self, [
|
||||||
|
self,
|
||||||
|
make_node(AST_False, self),
|
||||||
|
]).optimize(compressor);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (!(parent instanceof AST_UnaryPrefix && parent.operator == "delete")) {
|
if (!(parent instanceof AST_UnaryPrefix && parent.operator == "delete")) {
|
||||||
if (self.left instanceof AST_Number && !self.right.is_constant()) switch (self.operator) {
|
if (self.left instanceof AST_Number && !self.right.is_constant()) switch (self.operator) {
|
||||||
@@ -12278,7 +12388,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
parent = compressor.parent(level++);
|
parent = compressor.parent(level++);
|
||||||
if (parent instanceof AST_Assign) {
|
if (parent instanceof AST_Assign) {
|
||||||
if (parent.left instanceof AST_SymbolRef && parent.left.definition() === def) {
|
if (parent.left instanceof AST_SymbolRef && parent.left.definition() === def) {
|
||||||
if (in_try(level, parent)) break;
|
if (in_try(level, parent, !local)) break;
|
||||||
return strip_assignment(def);
|
return strip_assignment(def);
|
||||||
}
|
}
|
||||||
if (parent.left.match_symbol(function(node) {
|
if (parent.left.match_symbol(function(node) {
|
||||||
@@ -12390,14 +12500,16 @@ Compressor.prototype.compress = function(node) {
|
|||||||
if (parent instanceof AST_Try) return parent.bfinally ? parent.bfinally === stat : parent.bcatch === stat;
|
if (parent instanceof AST_Try) return parent.bfinally ? parent.bfinally === stat : parent.bcatch === stat;
|
||||||
}
|
}
|
||||||
|
|
||||||
function in_try(level, node) {
|
function in_try(level, node, sync) {
|
||||||
var right = self.right;
|
var right = self.right;
|
||||||
self.right = make_node(AST_Null, right);
|
self.right = make_node(AST_Null, right);
|
||||||
var may_throw = node.may_throw(compressor);
|
var may_throw = node.may_throw(compressor);
|
||||||
self.right = right;
|
self.right = right;
|
||||||
for (var parent; parent = compressor.parent(level++); node = parent) {
|
for (var parent; parent = compressor.parent(level++); node = parent) {
|
||||||
if (parent === scope) return false;
|
if (parent === scope) return false;
|
||||||
if (parent instanceof AST_Try) {
|
if (sync && parent instanceof AST_Lambda) {
|
||||||
|
if (parent.name || is_async(parent) || is_generator(parent)) return true;
|
||||||
|
} else if (parent instanceof AST_Try) {
|
||||||
if (parent.bfinally && parent.bfinally !== node) return true;
|
if (parent.bfinally && parent.bfinally !== node) return true;
|
||||||
if (may_throw && parent.bcatch && parent.bcatch !== node) return true;
|
if (may_throw && parent.bcatch && parent.bcatch !== node) return true;
|
||||||
}
|
}
|
||||||
@@ -13043,7 +13155,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
var arrow = !(value.uses_arguments || is_generator(value) || value.contains_this());
|
var arrow = !(value.uses_arguments || is_generator(value) || value.contains_this());
|
||||||
if (arrow) {
|
if (arrow) {
|
||||||
if (!scope) scope = compressor.find_parent(AST_Scope);
|
if (!scope) scope = compressor.find_parent(AST_Scope);
|
||||||
var avoid = avoid_await_yield(scope);
|
var avoid = avoid_await_yield(compressor, scope);
|
||||||
value.each_argname(function(argname) {
|
value.each_argname(function(argname) {
|
||||||
if (avoid[argname.name]) arrow = false;
|
if (avoid[argname.name]) arrow = false;
|
||||||
});
|
});
|
||||||
@@ -13460,7 +13572,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
}));
|
}));
|
||||||
return !abort;
|
return !abort;
|
||||||
})) return;
|
})) return;
|
||||||
if (!safe_from_await_yield(fn, avoid_await_yield(scope))) return;
|
if (!safe_from_await_yield(fn, avoid_await_yield(compressor, scope))) return;
|
||||||
fn.functions.each(function(def, name) {
|
fn.functions.each(function(def, name) {
|
||||||
scope.functions.set(name, def);
|
scope.functions.set(name, def);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -260,6 +260,15 @@ function OutputStream(options) {
|
|||||||
|
|
||||||
var require_semicolon = makePredicate("( [ + * / - , .");
|
var require_semicolon = makePredicate("( [ + * / - , .");
|
||||||
|
|
||||||
|
function require_space(prev, ch, str) {
|
||||||
|
return is_identifier_char(prev) && (is_identifier_char(ch) || ch == "\\")
|
||||||
|
|| (ch == "/" && ch == prev)
|
||||||
|
|| ((ch == "+" || ch == "-") && ch == last)
|
||||||
|
|| last == "--" && ch == ">"
|
||||||
|
|| last == "!" && str == "--"
|
||||||
|
|| prev == "/" && (str == "in" || str == "instanceof");
|
||||||
|
}
|
||||||
|
|
||||||
var print = options.beautify
|
var print = options.beautify
|
||||||
|| options.comments
|
|| options.comments
|
||||||
|| options.max_line_len
|
|| options.max_line_len
|
||||||
@@ -312,12 +321,7 @@ function OutputStream(options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (might_need_space) {
|
if (might_need_space) {
|
||||||
if (is_identifier_char(prev) && (is_identifier_char(ch) || ch == "\\")
|
if (require_space(prev, ch, str)) {
|
||||||
|| (ch == "/" && ch == prev)
|
|
||||||
|| ((ch == "+" || ch == "-") && ch == last)
|
|
||||||
|| str == "--" && last == "!"
|
|
||||||
|| str == "in" && prev == "/"
|
|
||||||
|| last == "--" && ch == ">") {
|
|
||||||
output += " ";
|
output += " ";
|
||||||
current_col++;
|
current_col++;
|
||||||
}
|
}
|
||||||
@@ -355,14 +359,7 @@ function OutputStream(options) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (might_need_space) {
|
if (might_need_space) {
|
||||||
if (is_identifier_char(prev) && (is_identifier_char(ch) || ch == "\\")
|
if (require_space(prev, ch, str)) output += " ";
|
||||||
|| (ch == "/" && ch == prev)
|
|
||||||
|| ((ch == "+" || ch == "-") && ch == last)
|
|
||||||
|| str == "--" && last == "!"
|
|
||||||
|| str == "in" && prev == "/"
|
|
||||||
|| last == "--" && ch == ">") {
|
|
||||||
output += " ";
|
|
||||||
}
|
|
||||||
if (prev != "<" || str != "!") might_need_space = false;
|
if (prev != "<" || str != "!") might_need_space = false;
|
||||||
}
|
}
|
||||||
output += str;
|
output += str;
|
||||||
@@ -1257,6 +1254,11 @@ function OutputStream(options) {
|
|||||||
}
|
}
|
||||||
print_method(self, output);
|
print_method(self, output);
|
||||||
});
|
});
|
||||||
|
DEFPRINT(AST_ClassInit, function(output) {
|
||||||
|
output.print("static");
|
||||||
|
output.space();
|
||||||
|
print_braced(this.value, output);
|
||||||
|
});
|
||||||
|
|
||||||
/* -----[ jumps ]----- */
|
/* -----[ jumps ]----- */
|
||||||
function print_jump(kind, prop) {
|
function print_jump(kind, prop) {
|
||||||
@@ -1814,9 +1816,6 @@ function OutputStream(options) {
|
|||||||
case "\u2029": return "\\u2029";
|
case "\u2029": return "\\u2029";
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
var p = output.parent();
|
|
||||||
if (p instanceof AST_Binary && /^in/.test(p.operator) && p.left === this)
|
|
||||||
output.print(" ");
|
|
||||||
});
|
});
|
||||||
|
|
||||||
function force_statement(stat, output) {
|
function force_statement(stat, output) {
|
||||||
|
|||||||
23
lib/parse.js
23
lib/parse.js
@@ -1119,6 +1119,18 @@ function parse($TEXT, options) {
|
|||||||
}));
|
}));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (fixed && is("punc", "{")) {
|
||||||
|
props.push(new AST_ClassInit({
|
||||||
|
start: start,
|
||||||
|
value: new AST_ClassInitBlock({
|
||||||
|
start: start,
|
||||||
|
body: block_(),
|
||||||
|
end: prev(),
|
||||||
|
}),
|
||||||
|
end: prev(),
|
||||||
|
}));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
var internal = is("name") && /^#/.test(S.token.value);
|
var internal = is("name") && /^#/.test(S.token.value);
|
||||||
var key = as_property_key();
|
var key = as_property_key();
|
||||||
if (is("punc", "(")) {
|
if (is("punc", "(")) {
|
||||||
@@ -1335,9 +1347,11 @@ function parse($TEXT, options) {
|
|||||||
var loop = S.in_loop;
|
var loop = S.in_loop;
|
||||||
var labels = S.labels;
|
var labels = S.labels;
|
||||||
++S.in_function;
|
++S.in_function;
|
||||||
|
S.input.push_directives_stack();
|
||||||
S.in_loop = 0;
|
S.in_loop = 0;
|
||||||
S.labels = [];
|
S.labels = [];
|
||||||
if (is("punc", "{")) {
|
if (is("punc", "{")) {
|
||||||
|
S.in_directives = true;
|
||||||
body = block_();
|
body = block_();
|
||||||
value = null;
|
value = null;
|
||||||
} else {
|
} else {
|
||||||
@@ -1345,6 +1359,8 @@ function parse($TEXT, options) {
|
|||||||
handle_regexp();
|
handle_regexp();
|
||||||
value = maybe_assign();
|
value = maybe_assign();
|
||||||
}
|
}
|
||||||
|
var is_strict = S.input.has_directive("use strict");
|
||||||
|
S.input.pop_directives_stack();
|
||||||
--S.in_function;
|
--S.in_function;
|
||||||
S.in_loop = loop;
|
S.in_loop = loop;
|
||||||
S.labels = labels;
|
S.labels = labels;
|
||||||
@@ -1358,7 +1374,7 @@ function parse($TEXT, options) {
|
|||||||
value: value,
|
value: value,
|
||||||
end: prev(),
|
end: prev(),
|
||||||
});
|
});
|
||||||
if (S.input.has_directive("use strict")) node.each_argname(strict_verify_symbol);
|
if (is_strict) node.each_argname(strict_verify_symbol);
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2541,7 +2557,10 @@ function parse($TEXT, options) {
|
|||||||
return function() {
|
return function() {
|
||||||
var start = S.token;
|
var start = S.token;
|
||||||
var body = [];
|
var body = [];
|
||||||
if (options.module) S.input.add_directive("use strict");
|
if (options.module) {
|
||||||
|
S.in_async = true;
|
||||||
|
S.input.add_directive("use strict");
|
||||||
|
}
|
||||||
S.input.push_directives_stack();
|
S.input.push_directives_stack();
|
||||||
while (!is("eof"))
|
while (!is("eof"))
|
||||||
body.push(statement());
|
body.push(statement());
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"description": "JavaScript parser, mangler/compressor and beautifier toolkit",
|
"description": "JavaScript parser, mangler/compressor and beautifier toolkit",
|
||||||
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
|
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
|
||||||
"license": "BSD-2-Clause",
|
"license": "BSD-2-Clause",
|
||||||
"version": "3.16.0",
|
"version": "3.16.1",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.8.0"
|
"node": ">=0.8.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1106,3 +1106,17 @@ issue_5416: {
|
|||||||
expect_stdout: "undefined"
|
expect_stdout: "undefined"
|
||||||
node_version: ">=4"
|
node_version: ">=4"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_5495: {
|
||||||
|
input: {
|
||||||
|
console.log((() => {
|
||||||
|
"use strict";
|
||||||
|
return function() {
|
||||||
|
return this;
|
||||||
|
}();
|
||||||
|
})());
|
||||||
|
}
|
||||||
|
expect_exact: 'console.log((()=>{"use strict";return function(){return this}()})());'
|
||||||
|
expect_stdout: "undefined"
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|||||||
@@ -1293,6 +1293,21 @@ functions_inner_var: {
|
|||||||
node_version: ">=8"
|
node_version: ">=8"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
instanceof_lambda: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(42 instanceof async function() {});
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(false);
|
||||||
|
}
|
||||||
|
expect_stdout: "false"
|
||||||
|
node_version: ">=8"
|
||||||
|
}
|
||||||
|
|
||||||
issue_4335_1: {
|
issue_4335_1: {
|
||||||
options = {
|
options = {
|
||||||
inline: true,
|
inline: true,
|
||||||
@@ -2961,3 +2976,48 @@ issue_5478: {
|
|||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
node_version: ">=8"
|
node_version: ">=8"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_5493: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(async function(a) {
|
||||||
|
var b = await [ 42 || b, a = b ];
|
||||||
|
console.log(a);
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(async function(a) {
|
||||||
|
var b = await [ 42 || b, a = b ];
|
||||||
|
console.log(a);
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: "undefined"
|
||||||
|
node_version: ">=8"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_5506: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function(a) {
|
||||||
|
(async function() {
|
||||||
|
a = null in (a = "PASS");
|
||||||
|
})();
|
||||||
|
return a;
|
||||||
|
}("FAIL"));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function(a) {
|
||||||
|
(async function() {
|
||||||
|
a = null in (a = "PASS");
|
||||||
|
})();
|
||||||
|
return a;
|
||||||
|
}("FAIL"));
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
node_version: ">=8"
|
||||||
|
}
|
||||||
|
|||||||
@@ -241,6 +241,208 @@ class_super: {
|
|||||||
node_version: ">=4"
|
node_version: ">=4"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static_init: {
|
||||||
|
input: {
|
||||||
|
var a = "foo";
|
||||||
|
var b = null;
|
||||||
|
class A {
|
||||||
|
static {
|
||||||
|
var a = "bar";
|
||||||
|
b = true;
|
||||||
|
var c = 42;
|
||||||
|
console.log(a, b, c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log(a, b, typeof c);
|
||||||
|
}
|
||||||
|
expect_exact: 'var a="foo";var b=null;class A{static{var a="bar";b=true;var c=42;console.log(a,b,c)}}console.log(a,b,typeof c);'
|
||||||
|
expect_stdout: [
|
||||||
|
"bar true 42",
|
||||||
|
"foo true undefined",
|
||||||
|
]
|
||||||
|
node_version: ">=16"
|
||||||
|
}
|
||||||
|
|
||||||
|
static_field_init: {
|
||||||
|
options = {
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(class {
|
||||||
|
static [console.log("foo")] = console.log("bar");
|
||||||
|
static {
|
||||||
|
console.log("baz");
|
||||||
|
}
|
||||||
|
static [console.log("moo")] = console.log("moz");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(class {
|
||||||
|
static [(console.log("foo"), console.log("moo"))] = (
|
||||||
|
console.log("bar"),
|
||||||
|
(() => {
|
||||||
|
console.log("baz");
|
||||||
|
})(),
|
||||||
|
console.log("moz")
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"foo",
|
||||||
|
"moo",
|
||||||
|
"bar",
|
||||||
|
"baz",
|
||||||
|
"moz",
|
||||||
|
]
|
||||||
|
node_version: ">=16"
|
||||||
|
}
|
||||||
|
|
||||||
|
static_field_init_strict: {
|
||||||
|
options = {
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
(class {
|
||||||
|
static [console.log("foo")] = console.log("bar");
|
||||||
|
static {
|
||||||
|
console.log("baz");
|
||||||
|
}
|
||||||
|
static [console.log("moo")] = console.log("moz");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
console.log("foo"),
|
||||||
|
console.log("moo"),
|
||||||
|
(() => (
|
||||||
|
console.log("bar"),
|
||||||
|
(() => {
|
||||||
|
console.log("baz");
|
||||||
|
})(),
|
||||||
|
console.log("moz")
|
||||||
|
))();
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"foo",
|
||||||
|
"moo",
|
||||||
|
"bar",
|
||||||
|
"baz",
|
||||||
|
"moz",
|
||||||
|
]
|
||||||
|
node_version: ">=16"
|
||||||
|
}
|
||||||
|
|
||||||
|
static_init_side_effects_1: {
|
||||||
|
options = {
|
||||||
|
merge_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "FAIL";
|
||||||
|
(class {
|
||||||
|
static {
|
||||||
|
a = "PASS";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = "FAIL";
|
||||||
|
(class {
|
||||||
|
static {
|
||||||
|
a = "PASS";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
node_version: ">=16"
|
||||||
|
}
|
||||||
|
|
||||||
|
static_init_side_effects_1_strict: {
|
||||||
|
options = {
|
||||||
|
merge_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
var a = "FAIL";
|
||||||
|
(class {
|
||||||
|
static {
|
||||||
|
a = "PASS";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
var a = "FAIL";
|
||||||
|
(() => (() => {
|
||||||
|
a = "PASS";
|
||||||
|
})())();
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
node_version: ">=16"
|
||||||
|
}
|
||||||
|
|
||||||
|
static_init_side_effects_2: {
|
||||||
|
options = {
|
||||||
|
hoist_props: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "FAIL";
|
||||||
|
(class {
|
||||||
|
static {
|
||||||
|
a = "PASS";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = "FAIL";
|
||||||
|
(class {
|
||||||
|
static {
|
||||||
|
a = "PASS";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
node_version: ">=16"
|
||||||
|
}
|
||||||
|
|
||||||
|
static_init_side_effects_2_strict: {
|
||||||
|
options = {
|
||||||
|
hoist_props: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
var a = "FAIL";
|
||||||
|
(class {
|
||||||
|
static {
|
||||||
|
a = "PASS";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
var a = "FAIL";
|
||||||
|
(() => (() => {
|
||||||
|
a = "PASS";
|
||||||
|
})())();
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
node_version: ">=16"
|
||||||
|
}
|
||||||
|
|
||||||
block_scoped: {
|
block_scoped: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
@@ -1064,6 +1266,105 @@ keep_fnames: {
|
|||||||
node_version: ">=4"
|
node_version: ">=4"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
instanceof_lambda: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
console.log(42 instanceof class {});
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
console.log(false);
|
||||||
|
}
|
||||||
|
expect_stdout: "false"
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|
||||||
|
drop_instanceof: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
class A {}
|
||||||
|
console.log({} instanceof A, Math instanceof A);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
console.log(!1, (Math, !1));
|
||||||
|
}
|
||||||
|
expect_stdout: "false false"
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|
||||||
|
keep_instanceof_1: {
|
||||||
|
options = {
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
class A {}
|
||||||
|
var A;
|
||||||
|
console.log({} instanceof A, Math instanceof A);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
class A {}
|
||||||
|
var A;
|
||||||
|
console.log({} instanceof A, Math instanceof A);
|
||||||
|
}
|
||||||
|
expect_stdout: SyntaxError("Identifier has already been declared")
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|
||||||
|
keep_instanceof_2: {
|
||||||
|
options = {
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
var A = Object;
|
||||||
|
class A {}
|
||||||
|
console.log({} instanceof A, Math instanceof A);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
var A = Object;
|
||||||
|
class A {}
|
||||||
|
console.log({} instanceof A, Math instanceof A);
|
||||||
|
}
|
||||||
|
expect_stdout: SyntaxError("Identifier has already been declared")
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|
||||||
|
keep_instanceof_3: {
|
||||||
|
options = {
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
class A {}
|
||||||
|
A = Object;
|
||||||
|
console.log({} instanceof A, Math instanceof A);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
class A {}
|
||||||
|
A = Object;
|
||||||
|
console.log({} instanceof A, Math instanceof A);
|
||||||
|
}
|
||||||
|
expect_stdout: "true true"
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|
||||||
issue_805_1: {
|
issue_805_1: {
|
||||||
options = {
|
options = {
|
||||||
inline: true,
|
inline: true,
|
||||||
@@ -2882,3 +3183,150 @@ issue_5481: {
|
|||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
node_version: ">=4"
|
node_version: ">=4"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_5489: {
|
||||||
|
options = {
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(class {
|
||||||
|
[console.log("foo")];
|
||||||
|
static {
|
||||||
|
console.log("bar");
|
||||||
|
}
|
||||||
|
static [console.log("baz")]() {}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(class {
|
||||||
|
[(console.log("foo"), console.log("baz"))];
|
||||||
|
static {
|
||||||
|
console.log("bar");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"foo",
|
||||||
|
"baz",
|
||||||
|
"bar",
|
||||||
|
]
|
||||||
|
node_version: ">=16"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_5489_strict: {
|
||||||
|
options = {
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
(class {
|
||||||
|
[console.log("foo")];
|
||||||
|
static {
|
||||||
|
console.log("bar");
|
||||||
|
}
|
||||||
|
static [console.log("baz")]() {}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
console.log("foo"),
|
||||||
|
console.log("baz"),
|
||||||
|
(() => (() => {
|
||||||
|
console.log("bar");
|
||||||
|
})())();
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"foo",
|
||||||
|
"baz",
|
||||||
|
"bar",
|
||||||
|
]
|
||||||
|
node_version: ">=16"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_5502: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
var a = "FAIL";
|
||||||
|
class A {
|
||||||
|
static p = a;
|
||||||
|
[a = "PASS"];
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
b++;
|
||||||
|
} finally {
|
||||||
|
var a, b = 42;
|
||||||
|
}
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
var a = "FAIL";
|
||||||
|
class A {
|
||||||
|
static p = a;
|
||||||
|
[a = "PASS"];
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
b++;
|
||||||
|
} finally {
|
||||||
|
var a, b = 42;
|
||||||
|
}
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS 42"
|
||||||
|
node_version: ">=12"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_5504: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
var a;
|
||||||
|
console.log((a = 42, class {
|
||||||
|
static p;
|
||||||
|
}).p);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
var a;
|
||||||
|
console.log((a = 42, class {
|
||||||
|
static p;
|
||||||
|
}).p);
|
||||||
|
}
|
||||||
|
expect_stdout: "undefined"
|
||||||
|
node_version: ">=12"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_5512: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
a = "PASS";
|
||||||
|
class A {
|
||||||
|
static {
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
static p = "PASS";
|
||||||
|
}
|
||||||
|
var a;
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
a = "PASS";
|
||||||
|
class A {
|
||||||
|
static {
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
static p = "PASS";
|
||||||
|
}
|
||||||
|
var a;
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
node_version: ">=16"
|
||||||
|
}
|
||||||
|
|||||||
@@ -40,6 +40,22 @@ unsafe_comps: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe_in_instanceof: {
|
||||||
|
options = {
|
||||||
|
side_effects: true,
|
||||||
|
unsafe_comps: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a;
|
||||||
|
42 in a;
|
||||||
|
f() instanceof "foo";
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a;
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
dont_change_in_or_instanceof_expressions: {
|
dont_change_in_or_instanceof_expressions: {
|
||||||
input: {
|
input: {
|
||||||
1 in 1;
|
1 in 1;
|
||||||
|
|||||||
@@ -1669,3 +1669,41 @@ issue_5106_2: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_5506: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
try {
|
||||||
|
(function(a) {
|
||||||
|
var b = 1;
|
||||||
|
(function f() {
|
||||||
|
try {
|
||||||
|
b-- && f();
|
||||||
|
} catch (c) {}
|
||||||
|
console.log(a);
|
||||||
|
a = 42 in (a = "bar");
|
||||||
|
})();
|
||||||
|
})("foo");
|
||||||
|
} catch (e) {}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
try {
|
||||||
|
(function(a) {
|
||||||
|
var b = 1;
|
||||||
|
(function f() {
|
||||||
|
try {
|
||||||
|
b-- && f();
|
||||||
|
} catch (c) {}
|
||||||
|
console.log(a);
|
||||||
|
a = 42 in (a = "bar");
|
||||||
|
})();
|
||||||
|
})("foo");
|
||||||
|
} catch (e) {}
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"foo",
|
||||||
|
"bar",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|||||||
@@ -671,6 +671,76 @@ iife: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
drop_instanceof: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {}
|
||||||
|
console.log({} instanceof f, Math instanceof f);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(!1, (Math, !1));
|
||||||
|
}
|
||||||
|
expect_stdout: "false false"
|
||||||
|
}
|
||||||
|
|
||||||
|
keep_instanceof_1: {
|
||||||
|
options = {
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {}
|
||||||
|
var f;
|
||||||
|
console.log({} instanceof f, Math instanceof f);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f() {}
|
||||||
|
var f;
|
||||||
|
console.log({} instanceof f, Math instanceof f);
|
||||||
|
}
|
||||||
|
expect_stdout: "false false"
|
||||||
|
}
|
||||||
|
|
||||||
|
keep_instanceof_2: {
|
||||||
|
options = {
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {}
|
||||||
|
var f = Object;
|
||||||
|
console.log({} instanceof f, Math instanceof f);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f() {}
|
||||||
|
var f = Object;
|
||||||
|
console.log({} instanceof f, Math instanceof f);
|
||||||
|
}
|
||||||
|
expect_stdout: "true true"
|
||||||
|
}
|
||||||
|
|
||||||
|
keep_instanceof_3: {
|
||||||
|
options = {
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
f = Object;
|
||||||
|
function f() {}
|
||||||
|
console.log({} instanceof f, Math instanceof f);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
f = Object;
|
||||||
|
function f() {}
|
||||||
|
console.log({} instanceof f, Math instanceof f);
|
||||||
|
}
|
||||||
|
expect_stdout: "true true"
|
||||||
|
}
|
||||||
|
|
||||||
issue_1539: {
|
issue_1539: {
|
||||||
options = {
|
options = {
|
||||||
collapse_vars: true,
|
collapse_vars: true,
|
||||||
|
|||||||
@@ -907,6 +907,20 @@ chained_side_effects: {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
instanceof_lambda: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(42 instanceof function() {});
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(false);
|
||||||
|
}
|
||||||
|
expect_stdout: "false"
|
||||||
|
}
|
||||||
|
|
||||||
issue_1649: {
|
issue_1649: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
|
|||||||
@@ -417,6 +417,46 @@ hoist_funs: {
|
|||||||
expect_exact: "export function f(){}export default async function*g(){}"
|
expect_exact: "export function f(){}export default async function*g(){}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
instanceof_default_class: {
|
||||||
|
options = {
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
export default class A {
|
||||||
|
f(a) {
|
||||||
|
return a instanceof A;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
export default class A {
|
||||||
|
f(a) {
|
||||||
|
return a instanceof A;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
instanceof_default_function: {
|
||||||
|
options = {
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
export default function f() {
|
||||||
|
if (!(this instanceof f))
|
||||||
|
throw new Error("must instantiate");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
export default function f() {
|
||||||
|
if (!(this instanceof f))
|
||||||
|
throw new Error("must instantiate");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
issue_4742_join_vars_1: {
|
issue_4742_join_vars_1: {
|
||||||
options = {
|
options = {
|
||||||
join_vars: true,
|
join_vars: true,
|
||||||
|
|||||||
@@ -1203,3 +1203,24 @@ issue_5441: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "object"
|
expect_stdout: "object"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_5498: {
|
||||||
|
options = {
|
||||||
|
hoist_props: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var o = {
|
||||||
|
__proto__: 42,
|
||||||
|
};
|
||||||
|
while (console.log(typeof o.__proto__));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var o = {
|
||||||
|
__proto__: 42,
|
||||||
|
};
|
||||||
|
while (console.log(typeof o.__proto__));
|
||||||
|
}
|
||||||
|
expect_stdout: "object"
|
||||||
|
}
|
||||||
|
|||||||
@@ -147,7 +147,7 @@ relational: {
|
|||||||
"bar" >= "bar";
|
"bar" >= "bar";
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
bar();
|
0 instanceof bar();
|
||||||
bar();
|
bar();
|
||||||
bar(), bar();
|
bar(), bar();
|
||||||
bar();
|
bar();
|
||||||
|
|||||||
@@ -50,6 +50,22 @@ regexp_properties: {
|
|||||||
expect_stdout: "abc true false 0 false"
|
expect_stdout: "abc true false 0 false"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
instanceof_1: {
|
||||||
|
input: {
|
||||||
|
console.log(/foo/ instanceof RegExp);
|
||||||
|
}
|
||||||
|
expect_exact: "console.log(/foo/ instanceof RegExp);"
|
||||||
|
expect_stdout: "true"
|
||||||
|
}
|
||||||
|
|
||||||
|
instanceof_2: {
|
||||||
|
input: {
|
||||||
|
console.log(42 + /foo/ instanceof Object);
|
||||||
|
}
|
||||||
|
expect_exact: "console.log(42+/foo/ instanceof Object);"
|
||||||
|
expect_stdout: "false"
|
||||||
|
}
|
||||||
|
|
||||||
issue_3434_1: {
|
issue_3434_1: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
|
|||||||
@@ -645,3 +645,56 @@ issue_4751: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
drop_instanceof: {
|
||||||
|
options = {
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
42 instanceof function() {};
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
drop_instanceof_reference: {
|
||||||
|
options = {
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {}
|
||||||
|
42 instanceof f;
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f() {}
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
retain_instanceof: {
|
||||||
|
options = {
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
try {
|
||||||
|
42 instanceof "foo";
|
||||||
|
} catch (e) {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
try {
|
||||||
|
0 instanceof "foo";
|
||||||
|
} catch (e) {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|||||||
@@ -934,6 +934,21 @@ drop_unused_call: {
|
|||||||
node_version: ">=4"
|
node_version: ">=4"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
instanceof_lambda: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(42 instanceof function*() {});
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(false);
|
||||||
|
}
|
||||||
|
expect_stdout: "false"
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|
||||||
issue_4454_1: {
|
issue_4454_1: {
|
||||||
rename = false
|
rename = false
|
||||||
options = {
|
options = {
|
||||||
@@ -1515,3 +1530,35 @@ issue_5456: {
|
|||||||
expect_stdout: "foo"
|
expect_stdout: "foo"
|
||||||
node_version: ">=4"
|
node_version: ">=4"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_5506: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function(a) {
|
||||||
|
var b = function*() {
|
||||||
|
a = null in (a = "PASS");
|
||||||
|
}();
|
||||||
|
try {
|
||||||
|
b.next();
|
||||||
|
} catch (e) {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
}("FAIL"));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function(a) {
|
||||||
|
var b = function*() {
|
||||||
|
a = null in (a = "PASS");
|
||||||
|
}();
|
||||||
|
try {
|
||||||
|
b.next();
|
||||||
|
} catch (e) {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
}("FAIL"));
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
var assert = require("assert");
|
var assert = require("assert");
|
||||||
var readFileSync = require("fs").readFileSync;
|
var readFileSync = require("fs").readFileSync;
|
||||||
var run_code = require("../sandbox").run_code;
|
var run_code = require("../sandbox").run_code;
|
||||||
|
var semver = require("semver");
|
||||||
var UglifyJS = require("../..");
|
var UglifyJS = require("../..");
|
||||||
|
|
||||||
function read(path) {
|
function read(path) {
|
||||||
@@ -320,6 +321,24 @@ describe("minify", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("module", function() {
|
||||||
|
it("Should not inline `await` variables", function() {
|
||||||
|
if (semver.satisfies(process.version, "<8")) return;
|
||||||
|
var code = [
|
||||||
|
"console.log(function() {",
|
||||||
|
" return typeof await;",
|
||||||
|
"}());",
|
||||||
|
].join("\n");
|
||||||
|
assert.strictEqual(run_code("(async function(){" + code + "})();"), "undefined\n");
|
||||||
|
var result = UglifyJS.minify(code, {
|
||||||
|
module: true,
|
||||||
|
});
|
||||||
|
if (result.error) throw result.error;
|
||||||
|
assert.strictEqual(result.code, "console.log(function(){return typeof await}());");
|
||||||
|
assert.strictEqual(run_code("(async function(){" + result.code + "})();"), "undefined\n");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe("rename", function() {
|
describe("rename", function() {
|
||||||
it("Should be repeatable", function() {
|
it("Should be repeatable", function() {
|
||||||
var code = "!function(x){return x(x)}(y);";
|
var code = "!function(x){return x(x)}(y);";
|
||||||
|
|||||||
@@ -760,9 +760,9 @@ function compare_run_code(code, minify_options, result_cache, max_timeout) {
|
|||||||
if (minified.error) return minified;
|
if (minified.error) return minified;
|
||||||
|
|
||||||
var toplevel = sandbox.has_toplevel(minify_options);
|
var toplevel = sandbox.has_toplevel(minify_options);
|
||||||
var unminified = run_code(code, toplevel, result_cache, max_timeout);
|
var unminified = run(code, max_timeout);
|
||||||
var timeout = Math.min(100 * unminified.elapsed, max_timeout);
|
var timeout = Math.min(100 * unminified.elapsed, max_timeout);
|
||||||
var minified_result = run_code(minified.code, toplevel, result_cache, timeout).result;
|
var minified_result = run(minified.code, timeout).result;
|
||||||
|
|
||||||
if (sandbox.same_stdout(unminified.result, minified_result)) {
|
if (sandbox.same_stdout(unminified.result, minified_result)) {
|
||||||
return is_timed_out(unminified.result) && is_timed_out(minified_result) && {
|
return is_timed_out(unminified.result) && is_timed_out(minified_result) && {
|
||||||
@@ -774,6 +774,16 @@ function compare_run_code(code, minify_options, result_cache, max_timeout) {
|
|||||||
minified_result: minified_result,
|
minified_result: minified_result,
|
||||||
elapsed: unminified.elapsed,
|
elapsed: unminified.elapsed,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function run(code, timeout) {
|
||||||
|
if (minify_options.module) code = [
|
||||||
|
'"use strict";',
|
||||||
|
"(async function(){",
|
||||||
|
code,
|
||||||
|
"})();"
|
||||||
|
].join("\n");
|
||||||
|
return run_code(code, toplevel, result_cache, timeout);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_minify(code, minify_options) {
|
function test_minify(code, minify_options) {
|
||||||
|
|||||||
@@ -140,6 +140,7 @@ var SUPPORT = function(matrix) {
|
|||||||
class: "class C { f() {} }",
|
class: "class C { f() {} }",
|
||||||
class_field: "class C { p = 0; }",
|
class_field: "class C { p = 0; }",
|
||||||
class_private: "class C { #f() {} }",
|
class_private: "class C { #f() {} }",
|
||||||
|
class_static_init: "class C { static {} }",
|
||||||
computed_key: "({[0]: 0});",
|
computed_key: "({[0]: 0});",
|
||||||
const_block: "var a; { const a = 0; }",
|
const_block: "var a; { const a = 0; }",
|
||||||
default_value: "[ a = 0 ] = [];",
|
default_value: "[ a = 0 ] = [];",
|
||||||
@@ -252,7 +253,7 @@ BINARY_OPS = BINARY_OPS.concat(BINARY_OPS);
|
|||||||
if (SUPPORT.exponentiation) BINARY_OPS.push("**");
|
if (SUPPORT.exponentiation) BINARY_OPS.push("**");
|
||||||
BINARY_OPS = BINARY_OPS.concat(BINARY_OPS);
|
BINARY_OPS = BINARY_OPS.concat(BINARY_OPS);
|
||||||
BINARY_OPS = BINARY_OPS.concat(BINARY_OPS);
|
BINARY_OPS = BINARY_OPS.concat(BINARY_OPS);
|
||||||
BINARY_OPS.push(" in ");
|
BINARY_OPS.push(" in ", " instanceof ");
|
||||||
|
|
||||||
var ASSIGNMENTS = [ "=" ];
|
var ASSIGNMENTS = [ "=" ];
|
||||||
ASSIGNMENTS = ASSIGNMENTS.concat(ASSIGNMENTS);
|
ASSIGNMENTS = ASSIGNMENTS.concat(ASSIGNMENTS);
|
||||||
@@ -405,7 +406,7 @@ function createTopLevelCode() {
|
|||||||
unique_vars.length = 0;
|
unique_vars.length = 0;
|
||||||
classes.length = 0;
|
classes.length = 0;
|
||||||
allow_this = true;
|
allow_this = true;
|
||||||
async = false;
|
async = SUPPORT.async && rng(200) == 0;
|
||||||
has_await = false;
|
has_await = false;
|
||||||
export_default = false;
|
export_default = false;
|
||||||
generator = false;
|
generator = false;
|
||||||
@@ -413,7 +414,7 @@ function createTopLevelCode() {
|
|||||||
funcs = 0;
|
funcs = 0;
|
||||||
clazz = 0;
|
clazz = 0;
|
||||||
imports = 0;
|
imports = 0;
|
||||||
in_class = 0;
|
in_class = async;
|
||||||
called = Object.create(null);
|
called = Object.create(null);
|
||||||
var s = [
|
var s = [
|
||||||
strictMode(),
|
strictMode(),
|
||||||
@@ -1181,7 +1182,11 @@ function createStatement(recurmax, canThrow, canBreak, canContinue, cannotReturn
|
|||||||
unique_vars.length = unique_len;
|
unique_vars.length = unique_len;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (n !== 0) s += " finally { " + createStatements(3, recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth) + " }";
|
if (n !== 0) s += [
|
||||||
|
" finally { ",
|
||||||
|
createStatements(rng(5) + 1, recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth),
|
||||||
|
" }",
|
||||||
|
].join("");
|
||||||
return s;
|
return s;
|
||||||
case STMT_C:
|
case STMT_C:
|
||||||
return "c = c + 1;";
|
return "c = c + 1;";
|
||||||
@@ -1839,6 +1844,16 @@ function createClassLiteral(recurmax, stmtDepth, canThrow, name) {
|
|||||||
async = save_async;
|
async = save_async;
|
||||||
}
|
}
|
||||||
s += ";\n";
|
s += ";\n";
|
||||||
|
} else if (SUPPORT.class_static_init && fixed && !internal && rng(10) == 0) {
|
||||||
|
async = false;
|
||||||
|
generator = false;
|
||||||
|
s += [
|
||||||
|
"{ ",
|
||||||
|
createStatements(rng(5) + 1, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CANNOT_RETURN, stmtDepth),
|
||||||
|
" }\n",
|
||||||
|
].join("");
|
||||||
|
generator = save_generator;
|
||||||
|
async = save_async;
|
||||||
} else {
|
} else {
|
||||||
if (!fixed && !internal && constructor && rng(10) == 0) {
|
if (!fixed && !internal && constructor && rng(10) == 0) {
|
||||||
internal = constructor;
|
internal = constructor;
|
||||||
@@ -1994,7 +2009,7 @@ function createBinaryOp(noComma, canThrow) {
|
|||||||
var op;
|
var op;
|
||||||
do {
|
do {
|
||||||
op = BINARY_OPS[rng(BINARY_OPS.length)];
|
op = BINARY_OPS[rng(BINARY_OPS.length)];
|
||||||
} while (noComma && op == "," || !canThrow && op == " in ");
|
} while (noComma && op == "," || !canThrow && /^ in/.test(op));
|
||||||
return op;
|
return op;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2087,6 +2102,12 @@ if (require.main !== module) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function run_code(code, toplevel, timeout) {
|
function run_code(code, toplevel, timeout) {
|
||||||
|
if (async && has_await) code = [
|
||||||
|
'"use strict";',
|
||||||
|
"(async function(){",
|
||||||
|
code,
|
||||||
|
"})();"
|
||||||
|
].join("\n");
|
||||||
return sandbox.run_code(sandbox.patch_module_statements(code), toplevel, timeout);
|
return sandbox.run_code(sandbox.patch_module_statements(code), toplevel, timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2106,7 +2127,9 @@ function errorln(msg) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function try_beautify(code, toplevel, result, printfn, options) {
|
function try_beautify(code, toplevel, result, printfn, options) {
|
||||||
var beautified = UglifyJS.minify(code, JSON.parse(beautify_options));
|
var o = JSON.parse(beautify_options);
|
||||||
|
if (async && has_await) o.module = true;
|
||||||
|
var beautified = UglifyJS.minify(code, o);
|
||||||
if (beautified.error) {
|
if (beautified.error) {
|
||||||
printfn("// !!! beautify failed !!!");
|
printfn("// !!! beautify failed !!!");
|
||||||
printfn(beautified.error);
|
printfn(beautified.error);
|
||||||
@@ -2259,12 +2282,27 @@ function log(options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function sort_globals(code) {
|
function sort_globals(code) {
|
||||||
var globals = run_code("throw Object.keys(this).sort(" + function(global) {
|
var injected = "throw Object.keys(this).sort(" + function(global) {
|
||||||
return function(m, n) {
|
return function(m, n) {
|
||||||
return (typeof global[n] == "function") - (typeof global[m] == "function")
|
return (typeof global[n] == "function") - (typeof global[m] == "function")
|
||||||
|| (m < n ? -1 : m > n ? 1 : 0);
|
|| (m < n ? -1 : m > n ? 1 : 0);
|
||||||
};
|
};
|
||||||
} + "(this));\n" + code);
|
} + "(this));";
|
||||||
|
var save_async = async;
|
||||||
|
if (async && has_await) {
|
||||||
|
async = false;
|
||||||
|
injected = [
|
||||||
|
'"use strict";',
|
||||||
|
injected,
|
||||||
|
"(async function(){",
|
||||||
|
code,
|
||||||
|
"})();"
|
||||||
|
].join("\n");
|
||||||
|
} else {
|
||||||
|
injected += "\n" + code;
|
||||||
|
}
|
||||||
|
var globals = run_code(injected);
|
||||||
|
async = save_async;
|
||||||
if (!Array.isArray(globals)) {
|
if (!Array.isArray(globals)) {
|
||||||
errorln();
|
errorln();
|
||||||
errorln();
|
errorln();
|
||||||
@@ -2466,6 +2504,9 @@ var bug_class_static_await = SUPPORT.async && SUPPORT.class_field && sandbox.is_
|
|||||||
var bug_class_static_nontrivial = SUPPORT.class_field && sandbox.is_error(sandbox.run_code("class A { static 42; static get 42() {} }"));
|
var bug_class_static_nontrivial = SUPPORT.class_field && sandbox.is_error(sandbox.run_code("class A { static 42; static get 42() {} }"));
|
||||||
var bug_for_of_async = SUPPORT.for_await_of && sandbox.is_error(sandbox.run_code("var async; for (async of []);"));
|
var bug_for_of_async = SUPPORT.for_await_of && sandbox.is_error(sandbox.run_code("var async; for (async of []);"));
|
||||||
var bug_for_of_var = SUPPORT.for_of && SUPPORT.let && sandbox.is_error(sandbox.run_code("try {} catch (e) { for (var e of []); }"));
|
var bug_for_of_var = SUPPORT.for_of && SUPPORT.let && sandbox.is_error(sandbox.run_code("try {} catch (e) { for (var e of []); }"));
|
||||||
|
var bug_proto_stream = function(ex) {
|
||||||
|
return ex.name == "TypeError" && ex.message == "callback is not a function";
|
||||||
|
}
|
||||||
if (SUPPORT.destructuring && sandbox.is_error(sandbox.run_code("console.log([ 1 ], {} = 2);"))) {
|
if (SUPPORT.destructuring && sandbox.is_error(sandbox.run_code("console.log([ 1 ], {} = 2);"))) {
|
||||||
beautify_options.output.v8 = true;
|
beautify_options.output.v8 = true;
|
||||||
minify_options.forEach(function(o) {
|
minify_options.forEach(function(o) {
|
||||||
@@ -2496,11 +2537,17 @@ for (var round = 1; round <= num_iterations; round++) {
|
|||||||
println();
|
println();
|
||||||
// ignore v8 parser bug
|
// ignore v8 parser bug
|
||||||
return bug_async_arrow_rest(result)
|
return bug_async_arrow_rest(result)
|
||||||
|
// ignore Node.js `__proto__` quirks
|
||||||
|
|| bug_proto_stream(result)
|
||||||
// ignore runtime platform bugs
|
// ignore runtime platform bugs
|
||||||
|| result.message == "Script execution aborted.";
|
|| result.message == "Script execution aborted.";
|
||||||
})) continue;
|
})) continue;
|
||||||
minify_options.forEach(function(options) {
|
minify_options.forEach(function(options) {
|
||||||
var o = JSON.parse(options);
|
var o = JSON.parse(options);
|
||||||
|
if (async && has_await) {
|
||||||
|
o.module = true;
|
||||||
|
options = JSON.stringify(o);
|
||||||
|
}
|
||||||
var toplevel = sandbox.has_toplevel(o);
|
var toplevel = sandbox.has_toplevel(o);
|
||||||
o.validate = true;
|
o.validate = true;
|
||||||
uglify_code = UglifyJS.minify(original_code, o);
|
uglify_code = UglifyJS.minify(original_code, o);
|
||||||
@@ -2513,6 +2560,8 @@ for (var round = 1; round <= num_iterations; round++) {
|
|||||||
var uglify_erred = sandbox.is_error(uglify_result);
|
var uglify_erred = sandbox.is_error(uglify_result);
|
||||||
// ignore v8 parser bug
|
// ignore v8 parser bug
|
||||||
if (!ok && uglify_erred && bug_async_arrow_rest(uglify_result)) ok = true;
|
if (!ok && uglify_erred && bug_async_arrow_rest(uglify_result)) ok = true;
|
||||||
|
// ignore Node.js `__proto__` quirks
|
||||||
|
if (!ok && uglify_erred && bug_proto_stream(uglify_result)) ok = true;
|
||||||
// ignore runtime platform bugs
|
// ignore runtime platform bugs
|
||||||
if (!ok && uglify_erred && uglify_result.message == "Script execution aborted.") ok = true;
|
if (!ok && uglify_erred && uglify_result.message == "Script execution aborted.") ok = true;
|
||||||
// handle difference caused by time-outs
|
// handle difference caused by time-outs
|
||||||
|
|||||||
Reference in New Issue
Block a user