Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4a1da492dd | ||
|
|
94a954c3d1 | ||
|
|
be8ccc3ab5 | ||
|
|
58d997a3d6 | ||
|
|
dabcc39b51 | ||
|
|
140e4e0da8 | ||
|
|
80fc862547 | ||
|
|
6cdc035b2f | ||
|
|
e1e3516397 | ||
|
|
bd5fc4cb1b | ||
|
|
a570c00251 | ||
|
|
3fa2086681 | ||
|
|
8e65413b99 | ||
|
|
8ca40070a4 |
@@ -3,7 +3,7 @@ Contributing
|
||||
|
||||
## Documentation
|
||||
|
||||
Every new feature and API change should be accompanied by a README additon.
|
||||
Every new feature and API change should be accompanied by a README addition.
|
||||
|
||||
## Testing
|
||||
|
||||
|
||||
13
README.md
13
README.md
@@ -646,7 +646,7 @@ to be `false` and all symbol names will be omitted.
|
||||
- `bare_returns` (default: `false`) — support top level `return` statements
|
||||
|
||||
- `html5_comments` (default: `true`) — process HTML comment as workaround for
|
||||
browsers which do not recognise `<script>` tags
|
||||
browsers which do not recognize `<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`.
|
||||
@@ -753,7 +753,7 @@ to be `false` and all symbol names will be omitted.
|
||||
ES module, i.e. implicit `"use strict";` alongside with `toplevel` enabled.
|
||||
|
||||
- `negate_iife` (default: `true`) — negate "Immediately-Called Function Expressions"
|
||||
where the return value is discarded, to avoid the parens that the
|
||||
where the return value is discarded, to avoid the parentheses that the
|
||||
code generator would insert.
|
||||
|
||||
- `objects` (default: `true`) — compact duplicate keys in object literals.
|
||||
@@ -851,7 +851,7 @@ to be `false` and all symbol names will be omitted.
|
||||
- `unused` (default: `true`) — drop unreferenced functions and variables (simple
|
||||
direct variable assignments do not count as references unless set to `"keep_assign"`)
|
||||
|
||||
- `varify` (default: `true`) — convert block-scoped declaractions into `var`
|
||||
- `varify` (default: `true`) — convert block-scoped declarations into `var`
|
||||
whenever safe to do so
|
||||
|
||||
- `yields` (default: `true`) — apply optimizations to `yield` expressions
|
||||
@@ -891,12 +891,15 @@ UglifyJS.minify(code, { mangle: { toplevel: true } }).code;
|
||||
|
||||
### Mangle properties options
|
||||
|
||||
- `builtins` (default: `false`) — Use `true` to allow the mangling of builtin
|
||||
DOM properties. Not recommended to override this setting.
|
||||
- `builtins` (default: `false`) — Use `true` to allow the mangling of built-in
|
||||
properties of JavaScript API. Not recommended to override this setting.
|
||||
|
||||
- `debug` (default: `false`) — Mangle names with the original name still present.
|
||||
Pass an empty string `""` to enable, or a non-empty string to set the debug suffix.
|
||||
|
||||
- `domprops` (default: `false`) — Use `true` to allow the mangling of properties
|
||||
commonly found in Document Object Model. Not recommended to override this setting.
|
||||
|
||||
- `keep_fargs` (default: `false`) — Use `true` to prevent mangling of function
|
||||
arguments.
|
||||
|
||||
|
||||
11
bin/uglifyjs
11
bin/uglifyjs
@@ -238,17 +238,6 @@ if (specified["beautify"] && specified["output-opts"]) fatal("--beautify cannot
|
||||
[ "compress", "mangle" ].forEach(function(name) {
|
||||
if (!(name in options)) options[name] = false;
|
||||
});
|
||||
if (options.mangle && options.mangle.properties) {
|
||||
if (options.mangle.properties.domprops) {
|
||||
delete options.mangle.properties.domprops;
|
||||
} else {
|
||||
if (typeof options.mangle.properties != "object") options.mangle.properties = {};
|
||||
if (!Array.isArray(options.mangle.properties.reserved)) options.mangle.properties.reserved = [];
|
||||
require("../tools/domprops").forEach(function(name) {
|
||||
UglifyJS.push_uniq(options.mangle.properties.reserved, name);
|
||||
});
|
||||
}
|
||||
}
|
||||
if (/^ast|spidermonkey$/.test(output)) {
|
||||
if (typeof options.output != "object") options.output = {};
|
||||
options.output.ast = true;
|
||||
|
||||
@@ -332,7 +332,7 @@ var AST_SimpleStatement = DEFNODE("SimpleStatement", "body", {
|
||||
var AST_BlockScope = DEFNODE("BlockScope", "_var_names enclosed functions make_def parent_scope variables", {
|
||||
$documentation: "Base class for all statements introducing a lexical scope",
|
||||
$propdoc: {
|
||||
enclosed: "[SymbolDef*/S] a list of all symbol definitions that are accessed from this scope or any subscopes",
|
||||
enclosed: "[SymbolDef*/S] a list of all symbol definitions that are accessed from this scope or any inner scopes",
|
||||
functions: "[Dictionary/S] like `variables`, but only lists function declarations",
|
||||
parent_scope: "[AST_Scope?/S] link to the parent scope",
|
||||
variables: "[Dictionary/S] a map of name ---> SymbolDef for all variables/functions defined in this scope",
|
||||
|
||||
187
lib/compress.js
187
lib/compress.js
@@ -368,7 +368,6 @@ Compressor.prototype.compress = function(node) {
|
||||
args: [],
|
||||
});
|
||||
}
|
||||
return self;
|
||||
});
|
||||
AST_Node.DEFMETHOD("wrap_expression", function() {
|
||||
var self = this;
|
||||
@@ -497,6 +496,7 @@ Compressor.prototype.compress = function(node) {
|
||||
function has_escaped(d, scope, node, parent) {
|
||||
if (parent instanceof AST_Assign) return parent.operator == "=" && parent.right === node;
|
||||
if (parent instanceof AST_Call) return parent.expression !== node || parent instanceof AST_New;
|
||||
if (parent instanceof AST_ClassField) return parent.value === node && !parent.static;
|
||||
if (parent instanceof AST_Exit) return parent.value === node && scope.resolve() !== d.scope.resolve();
|
||||
if (parent instanceof AST_VarDef) return parent.value === node;
|
||||
}
|
||||
@@ -1164,7 +1164,11 @@ Compressor.prototype.compress = function(node) {
|
||||
if (node.extends) node.extends.walk(tw);
|
||||
var props = node.properties.filter(function(prop) {
|
||||
reset_flags(prop);
|
||||
if (prop.key instanceof AST_Node) prop.key.walk(tw);
|
||||
if (prop.key instanceof AST_Node) {
|
||||
tw.push(prop);
|
||||
prop.key.walk(tw);
|
||||
tw.pop();
|
||||
}
|
||||
return prop.value;
|
||||
});
|
||||
if (node.name) {
|
||||
@@ -1184,6 +1188,7 @@ Compressor.prototype.compress = function(node) {
|
||||
}
|
||||
}
|
||||
props.forEach(function(prop) {
|
||||
tw.push(prop);
|
||||
if (!prop.static || is_static_field_or_init(prop) && prop.value.contains_this()) {
|
||||
push(tw);
|
||||
prop.value.walk(tw);
|
||||
@@ -1191,6 +1196,7 @@ Compressor.prototype.compress = function(node) {
|
||||
} else {
|
||||
prop.value.walk(tw);
|
||||
}
|
||||
tw.pop();
|
||||
});
|
||||
return true;
|
||||
});
|
||||
@@ -1741,6 +1747,7 @@ Compressor.prototype.compress = function(node) {
|
||||
|
||||
var identifier_atom = makePredicate("Infinity NaN undefined");
|
||||
function is_lhs_read_only(lhs, compressor) {
|
||||
if (lhs instanceof AST_Atom) return true;
|
||||
if (lhs instanceof AST_ObjectIdentity) return true;
|
||||
if (lhs instanceof AST_PropAccess) {
|
||||
if (lhs.property === "__proto__") return true;
|
||||
@@ -3529,6 +3536,7 @@ Compressor.prototype.compress = function(node) {
|
||||
var declare_only, jump, merge_jump;
|
||||
var in_iife = in_lambda && parent && parent.TYPE == "Call" && parent.expression === self;
|
||||
var chain_if_returns = in_lambda && compressor.option("conditionals") && compressor.option("sequences");
|
||||
var drop_return_void = !(in_try && in_try.bfinally && in_async_generator(in_lambda));
|
||||
var multiple_if_returns = has_multiple_if_returns(statements);
|
||||
for (var i = statements.length; --i >= 0;) {
|
||||
var stat = statements[i];
|
||||
@@ -3536,8 +3544,7 @@ Compressor.prototype.compress = function(node) {
|
||||
var next = statements[j];
|
||||
|
||||
if (in_lambda && declare_only && !next && stat instanceof AST_Return
|
||||
&& !(self instanceof AST_SwitchBranch)
|
||||
&& !(in_try && in_try.bfinally && in_async_generator(in_lambda))) {
|
||||
&& drop_return_void && !(self instanceof AST_SwitchBranch)) {
|
||||
var body = stat.value;
|
||||
if (!body) {
|
||||
changed = true;
|
||||
@@ -3632,7 +3639,8 @@ Compressor.prototype.compress = function(node) {
|
||||
var value = stat.body.value;
|
||||
var in_bool = stat.body.in_bool || next instanceof AST_Return && next.in_bool;
|
||||
// if (foo()) return x; return y; ---> return foo() ? x : y;
|
||||
if (!stat.alternative && next instanceof AST_Return) {
|
||||
if (!stat.alternative && next instanceof AST_Return
|
||||
&& (drop_return_void || !value == !next.value)) {
|
||||
changed = true;
|
||||
stat = stat.clone();
|
||||
stat.alternative = make_node(AST_BlockStatement, next, {
|
||||
@@ -3737,14 +3745,17 @@ Compressor.prototype.compress = function(node) {
|
||||
return true;
|
||||
}
|
||||
if (!(ab instanceof AST_LoopControl)) return false;
|
||||
if (jump && self instanceof AST_SwitchBranch) {
|
||||
if (self instanceof AST_SwitchBranch) {
|
||||
if (jump instanceof AST_Exit) {
|
||||
if (!in_lambda) return false;
|
||||
if (jump.value) return false;
|
||||
} else if (compressor.loopcontrol_target(jump) !== parent) {
|
||||
merge_jump = true;
|
||||
} else if (jump) {
|
||||
if (compressor.loopcontrol_target(jump) !== parent) return false;
|
||||
merge_jump = true;
|
||||
} else if (jump === false) {
|
||||
return false;
|
||||
}
|
||||
merge_jump = true;
|
||||
}
|
||||
var lct = compressor.loopcontrol_target(ab);
|
||||
if (ab instanceof AST_Continue) return match_target(loop_body(lct));
|
||||
@@ -3781,7 +3792,7 @@ Compressor.prototype.compress = function(node) {
|
||||
end = statements.lastIndexOf(stop);
|
||||
} else {
|
||||
stop = statements[end];
|
||||
if (stop !== jump) jump = null;
|
||||
if (stop !== jump) jump = false;
|
||||
}
|
||||
var tail = statements.splice(start, end - start).filter(function(stat) {
|
||||
if (stat instanceof AST_LambdaDefinition) {
|
||||
@@ -5071,7 +5082,7 @@ Compressor.prototype.compress = function(node) {
|
||||
return static_fn && (static_fn[node.property] || expr.name == "Math" && node.property == "random");
|
||||
}
|
||||
|
||||
// Accomodate when compress option evaluate=false
|
||||
// Accommodate when compress option evaluate=false
|
||||
// as well as the common constant expressions !0 and -1
|
||||
(function(def) {
|
||||
def(AST_Node, return_false);
|
||||
@@ -9335,7 +9346,7 @@ Compressor.prototype.compress = function(node) {
|
||||
return !same_scope(def) || may_overlap(compressor, def);
|
||||
}
|
||||
}, true)) {
|
||||
self.init = to_var(self.init);
|
||||
self.init = to_var(self.init, self.resolve());
|
||||
}
|
||||
}
|
||||
return self;
|
||||
@@ -9677,16 +9688,25 @@ Compressor.prototype.compress = function(node) {
|
||||
alternative: null,
|
||||
});
|
||||
if (self.alternative instanceof AST_Exit && self.body.TYPE == self.alternative.TYPE) {
|
||||
var exit = make_node(self.body.CTOR, self, {
|
||||
value: make_node(AST_Conditional, self, {
|
||||
condition: self.condition,
|
||||
consequent: self.body.value || make_node(AST_Undefined, self.body).transform(compressor),
|
||||
alternative: self.alternative.value
|
||||
|| make_node(AST_Undefined, self.alternative).transform(compressor),
|
||||
}),
|
||||
});
|
||||
if (exit instanceof AST_Return) exit.in_bool = self.body.in_bool || self.alternative.in_bool;
|
||||
return exit;
|
||||
var cons_value = self.body.value;
|
||||
var alt_value = self.alternative.value;
|
||||
if (!cons_value && !alt_value) return make_node(AST_BlockStatement, self, {
|
||||
body: [
|
||||
make_node(AST_SimpleStatement, self, { body: self.condition }),
|
||||
self.body,
|
||||
],
|
||||
}).optimize(compressor);
|
||||
if (cons_value && alt_value || !keep_return_void()) {
|
||||
var exit = make_node(self.body.CTOR, self, {
|
||||
value: make_node(AST_Conditional, self, {
|
||||
condition: self.condition,
|
||||
consequent: cons_value || make_node(AST_Undefined, self.body).transform(compressor),
|
||||
alternative: alt_value || make_node(AST_Undefined, self.alternative).transform(compressor),
|
||||
}),
|
||||
});
|
||||
if (exit instanceof AST_Return) exit.in_bool = self.body.in_bool || self.alternative.in_bool;
|
||||
return exit;
|
||||
}
|
||||
}
|
||||
if (self.body instanceof AST_If && !self.body.alternative && !self.alternative) {
|
||||
self = make_node(AST_If, self, {
|
||||
@@ -9752,6 +9772,22 @@ Compressor.prototype.compress = function(node) {
|
||||
return node instanceof AST_BlockStatement ? node.body : [ node ];
|
||||
}
|
||||
|
||||
function keep_return_void() {
|
||||
var has_finally = false, level = 0, node = compressor.self();
|
||||
do {
|
||||
if (node instanceof AST_Catch) {
|
||||
if (compressor.parent(level).bfinally) has_finally = true;
|
||||
level++;
|
||||
} else if (node instanceof AST_Finally) {
|
||||
level++;
|
||||
} else if (node instanceof AST_Scope) {
|
||||
return has_finally && in_async_generator(node);
|
||||
} else if (node instanceof AST_Try) {
|
||||
if (node.bfinally) has_finally = true;
|
||||
}
|
||||
} while (node = compressor.parent(level++));
|
||||
}
|
||||
|
||||
function last_index(stats) {
|
||||
for (var index = stats.length; --index >= 0;) {
|
||||
if (!is_declaration(stats[index], true)) break;
|
||||
@@ -10124,14 +10160,13 @@ Compressor.prototype.compress = function(node) {
|
||||
}
|
||||
}
|
||||
|
||||
function to_var(stat) {
|
||||
function to_var(stat, scope) {
|
||||
return make_node(AST_Var, stat, {
|
||||
definitions: stat.definitions.map(function(defn) {
|
||||
return make_node(AST_VarDef, defn, {
|
||||
name: defn.name.convert_symbol(AST_SymbolVar, function(name, node) {
|
||||
var def = name.definition();
|
||||
def.orig[def.orig.indexOf(node)] = name;
|
||||
var scope = def.scope.resolve();
|
||||
if (def.scope === scope) return;
|
||||
def.scope = scope;
|
||||
scope.variables.set(def.name, def);
|
||||
@@ -10157,7 +10192,7 @@ Compressor.prototype.compress = function(node) {
|
||||
return !defn.name.match_symbol(function(node) {
|
||||
if (node instanceof AST_SymbolDeclaration) return !can_varify(compressor, node);
|
||||
}, true);
|
||||
}) ? to_var(self) : self;
|
||||
}) ? to_var(self, compressor.find_parent(AST_Scope)) : self;
|
||||
}
|
||||
|
||||
OPT(AST_Const, varify);
|
||||
@@ -11553,6 +11588,15 @@ Compressor.prototype.compress = function(node) {
|
||||
if (node instanceof AST_Unary) return true;
|
||||
}
|
||||
|
||||
function extract_lhs(node, compressor) {
|
||||
if (node instanceof AST_Assign) return is_lhs_read_only(node.left, compressor) ? node : node.left;
|
||||
if (node instanceof AST_Sequence) return extract_lhs(node.tail_node(), compressor);
|
||||
if (node instanceof AST_UnaryPrefix && UNARY_POSTFIX[node.operator]) {
|
||||
return is_lhs_read_only(node.expression, compressor) ? node : node.expression;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
function repeatable(compressor, node) {
|
||||
if (node instanceof AST_Dot) return repeatable(compressor, node.expression);
|
||||
if (node instanceof AST_Sub) {
|
||||
@@ -11595,31 +11639,32 @@ Compressor.prototype.compress = function(node) {
|
||||
if (seq !== self) return seq.optimize(compressor);
|
||||
}
|
||||
if (compressor.option("assignments") && lazy_op[self.operator]) {
|
||||
var lhs = extract_lhs(self.left, compressor);
|
||||
var right = self.right;
|
||||
// a || (a = x) ---> a = a || x
|
||||
// a && (a = x) ---> a = a && x
|
||||
if (self.left instanceof AST_SymbolRef
|
||||
// (a = x) && (a = y) ---> a = (a = x) && y
|
||||
if (lhs instanceof AST_SymbolRef
|
||||
&& right instanceof AST_Assign
|
||||
&& right.operator == "="
|
||||
&& self.left.equals(right.left)) {
|
||||
var left = right.left.clone();
|
||||
&& lhs.equals(right.left)) {
|
||||
lhs = lhs.clone();
|
||||
var assign = make_node(AST_Assign, self, {
|
||||
operator: "=",
|
||||
left: left,
|
||||
left: lhs,
|
||||
right: make_node(AST_Binary, self, {
|
||||
operator: self.operator,
|
||||
left: self.left,
|
||||
right: right.right,
|
||||
}),
|
||||
});
|
||||
if (left.fixed) {
|
||||
left.fixed = function() {
|
||||
if (lhs.fixed) {
|
||||
lhs.fixed = function() {
|
||||
return assign.right;
|
||||
};
|
||||
left.fixed.assigns = [ assign ];
|
||||
lhs.fixed.assigns = [ assign ];
|
||||
}
|
||||
var def = left.definition();
|
||||
def.references.push(left);
|
||||
var def = lhs.definition();
|
||||
def.references.push(lhs);
|
||||
def.replaced++;
|
||||
return assign.optimize(compressor);
|
||||
}
|
||||
@@ -11674,31 +11719,32 @@ Compressor.prototype.compress = function(node) {
|
||||
case "||":
|
||||
// void 0 !== x && null !== x ---> null != x
|
||||
// void 0 === x || null === x ---> null == x
|
||||
var lhs = self.left;
|
||||
if (lhs.operator == self.operator) lhs = lhs.right;
|
||||
var expr = lhs.right;
|
||||
if (expr instanceof AST_Assign && expr.operator == "=") expr = expr.left;
|
||||
if (lhs instanceof AST_Binary
|
||||
&& lhs.operator == (self.operator == "&&" ? "!==" : "===")
|
||||
&& self.right instanceof AST_Binary
|
||||
&& lhs.operator == self.right.operator
|
||||
&& (is_undefined(lhs.left, compressor) && self.right.left instanceof AST_Null
|
||||
|| lhs.left instanceof AST_Null && is_undefined(self.right.left, compressor))
|
||||
&& !expr.has_side_effects(compressor)
|
||||
&& expr.equals(self.right.right)) {
|
||||
lhs.operator = lhs.operator.slice(0, -1);
|
||||
lhs.left = make_node(AST_Null, self);
|
||||
return self.left;
|
||||
var left = self.left;
|
||||
if (!(left instanceof AST_Binary)) break;
|
||||
if (left.operator != (self.operator == "&&" ? "!==" : "===")) break;
|
||||
if (!(self.right instanceof AST_Binary)) break;
|
||||
if (left.operator != self.right.operator) break;
|
||||
if (is_undefined(left.left, compressor) && self.right.left instanceof AST_Null
|
||||
|| left.left instanceof AST_Null && is_undefined(self.right.left, compressor)) {
|
||||
var expr = left.right;
|
||||
if (expr instanceof AST_Assign && expr.operator == "=") expr = expr.left;
|
||||
if (expr.has_side_effects(compressor)) break;
|
||||
if (!expr.equals(self.right.right)) break;
|
||||
left.operator = left.operator.slice(0, -1);
|
||||
left.left = make_node(AST_Null, self);
|
||||
return left;
|
||||
}
|
||||
break;
|
||||
}
|
||||
var in_bool = false;
|
||||
var parent = compressor.parent();
|
||||
if (compressor.option("booleans")) {
|
||||
var lhs = self.left;
|
||||
var lhs = extract_lhs(self.left, compressor);
|
||||
if (lazy_op[self.operator] && !lhs.has_side_effects(compressor)) {
|
||||
// a || a ---> a
|
||||
// (a = x) && a --> a = x
|
||||
if (lhs.equals(self.right)) {
|
||||
return maintain_this_binding(parent, compressor.self(), lhs).optimize(compressor);
|
||||
return maintain_this_binding(parent, compressor.self(), self.left).optimize(compressor);
|
||||
}
|
||||
mark_duplicate_condition(compressor, lhs);
|
||||
}
|
||||
@@ -11746,13 +11792,22 @@ Compressor.prototype.compress = function(node) {
|
||||
case ">=": reverse("<="); break;
|
||||
}
|
||||
}
|
||||
// x && (y && z) ---> x && y && z
|
||||
// x || (y || z) ---> x || y || z
|
||||
if (compressor.option("conditionals")
|
||||
&& lazy_op[self.operator]
|
||||
&& self.right instanceof AST_Binary
|
||||
&& self.operator == self.right.operator) {
|
||||
swap_chain(self, compressor);
|
||||
if (compressor.option("conditionals") && lazy_op[self.operator]) {
|
||||
if (self.left instanceof AST_Binary && self.operator == self.left.operator) {
|
||||
var before = make_node(AST_Binary, self, {
|
||||
operator: self.operator,
|
||||
left: self.left.right,
|
||||
right: self.right,
|
||||
});
|
||||
var after = before.optimize(compressor);
|
||||
if (before !== after) {
|
||||
self.left = self.left.left;
|
||||
self.right = after;
|
||||
}
|
||||
}
|
||||
// x && (y && z) ---> x && y && z
|
||||
// x || (y || z) ---> x || y || z
|
||||
if (self.right instanceof AST_Binary && self.operator == self.right.operator) swap_chain(self, compressor);
|
||||
}
|
||||
if (compressor.option("strings") && self.operator == "+") {
|
||||
// "foo" + 42 + "" ---> "foo" + 42
|
||||
@@ -11826,7 +11881,7 @@ Compressor.prototype.compress = function(node) {
|
||||
if (nullish ? ll == null : !ll) {
|
||||
AST_Node.warn("Condition left of {operator} always {value} [{start}]", {
|
||||
operator: self.operator,
|
||||
value: nullish ? "nulish" : "false",
|
||||
value: nullish ? "nullish" : "false",
|
||||
start: self.start,
|
||||
});
|
||||
return make_sequence(self, [ self.left, self.right ]).optimize(compressor);
|
||||
@@ -12270,7 +12325,7 @@ Compressor.prototype.compress = function(node) {
|
||||
var single_use = def.single_use && !(parent instanceof AST_Call && parent.is_expr_pure(compressor));
|
||||
if (single_use) {
|
||||
if (is_lambda(fixed)) {
|
||||
if ((def.scope !== self.scope.resolve() || def.in_loop)
|
||||
if ((def.scope !== self.scope.resolve(true) || def.in_loop)
|
||||
&& (!compressor.option("reduce_funcs") || def.escaped.depth == 1 || fixed.inlined)) {
|
||||
single_use = false;
|
||||
} else if (def.redefined()) {
|
||||
@@ -12845,15 +12900,16 @@ Compressor.prototype.compress = function(node) {
|
||||
}
|
||||
var consequent = self.consequent;
|
||||
var alternative = self.alternative;
|
||||
if (repeatable(compressor, condition)) {
|
||||
var cond_lhs = extract_lhs(condition, compressor);
|
||||
if (repeatable(compressor, cond_lhs)) {
|
||||
// x ? x : y ---> x || y
|
||||
if (condition.equals(consequent)) return make_node(AST_Binary, self, {
|
||||
if (cond_lhs.equals(consequent)) return make_node(AST_Binary, self, {
|
||||
operator: "||",
|
||||
left: condition,
|
||||
right: alternative,
|
||||
}).optimize(compressor);
|
||||
// x ? y : x ---> x && y
|
||||
if (condition.equals(alternative)) return make_node(AST_Binary, self, {
|
||||
if (cond_lhs.equals(alternative)) return make_node(AST_Binary, self, {
|
||||
operator: "&&",
|
||||
left: condition,
|
||||
right: consequent,
|
||||
@@ -13834,7 +13890,10 @@ Compressor.prototype.compress = function(node) {
|
||||
var abort = false;
|
||||
stat.walk(new TreeWalker(function(node) {
|
||||
if (abort) return true;
|
||||
if (async && node instanceof AST_Await || node instanceof AST_Return) return abort = true;
|
||||
if (async && (node instanceof AST_Await || node instanceof AST_ForAwaitOf)
|
||||
|| node instanceof AST_Return) {
|
||||
return abort = true;
|
||||
}
|
||||
if (node instanceof AST_Scope) return true;
|
||||
}));
|
||||
return !abort;
|
||||
|
||||
@@ -76,7 +76,7 @@ function OutputStream(options) {
|
||||
wrap_iife : false,
|
||||
}, true);
|
||||
|
||||
// Convert comment option to RegExp if neccessary and set up comments filter
|
||||
// Convert comment option to RegExp if necessary and set up comments filter
|
||||
var comment_filter = return_false; // Default case, throw all comments away
|
||||
if (options.comments) {
|
||||
var comments = options.comments;
|
||||
@@ -997,7 +997,7 @@ function OutputStream(options) {
|
||||
if (self.init instanceof AST_Definitions) {
|
||||
self.init.print(output);
|
||||
} else {
|
||||
parenthesize_for_noin(self.init, output, true);
|
||||
parenthesize_for_no_in(self.init, output, true);
|
||||
}
|
||||
output.print(";");
|
||||
output.space();
|
||||
@@ -1413,7 +1413,7 @@ function OutputStream(options) {
|
||||
print_braced(this, output);
|
||||
});
|
||||
|
||||
function print_definitinos(type) {
|
||||
function print_definitions(type) {
|
||||
return function(output) {
|
||||
var self = this;
|
||||
output.print(type);
|
||||
@@ -1426,15 +1426,15 @@ function OutputStream(options) {
|
||||
if (!(p instanceof AST_IterationStatement && p.init === self)) output.semicolon();
|
||||
};
|
||||
}
|
||||
DEFPRINT(AST_Const, print_definitinos("const"));
|
||||
DEFPRINT(AST_Let, print_definitinos("let"));
|
||||
DEFPRINT(AST_Var, print_definitinos("var"));
|
||||
DEFPRINT(AST_Const, print_definitions("const"));
|
||||
DEFPRINT(AST_Let, print_definitions("let"));
|
||||
DEFPRINT(AST_Var, print_definitions("var"));
|
||||
|
||||
function parenthesize_for_noin(node, output, noin) {
|
||||
function parenthesize_for_no_in(node, output, no_in) {
|
||||
var parens = false;
|
||||
// need to take some precautions here:
|
||||
// https://github.com/mishoo/UglifyJS/issues/60
|
||||
if (noin) node.walk(new TreeWalker(function(node) {
|
||||
if (no_in) node.walk(new TreeWalker(function(node) {
|
||||
if (parens) return true;
|
||||
if (node instanceof AST_Binary && node.operator == "in") return parens = true;
|
||||
if (node instanceof AST_Scope && !(is_arrow(node) && node.value)) return true;
|
||||
@@ -1450,8 +1450,8 @@ function OutputStream(options) {
|
||||
output.print("=");
|
||||
output.space();
|
||||
var p = output.parent(1);
|
||||
var noin = p instanceof AST_For || p instanceof AST_ForEnumeration;
|
||||
parenthesize_for_noin(self.value, output, noin);
|
||||
var no_in = p instanceof AST_For || p instanceof AST_ForEnumeration;
|
||||
parenthesize_for_no_in(self.value, output, no_in);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
48
lib/parse.js
48
lib/parse.js
@@ -782,7 +782,7 @@ function parse($TEXT, options) {
|
||||
else if (!optional && !can_insert_semicolon()) expect(";");
|
||||
}
|
||||
|
||||
function parenthesised() {
|
||||
function parenthesized() {
|
||||
expect("(");
|
||||
var exp = expression();
|
||||
expect(")");
|
||||
@@ -920,18 +920,18 @@ function parse($TEXT, options) {
|
||||
next();
|
||||
var body = in_loop(statement);
|
||||
expect_token("keyword", "while");
|
||||
var condition = parenthesised();
|
||||
var condition = parenthesized();
|
||||
semicolon(true);
|
||||
return new AST_Do({
|
||||
body : body,
|
||||
condition : condition
|
||||
condition : condition,
|
||||
});
|
||||
|
||||
case "while":
|
||||
next();
|
||||
return new AST_While({
|
||||
condition : parenthesised(),
|
||||
body : in_loop(statement)
|
||||
condition : parenthesized(),
|
||||
body : in_loop(statement),
|
||||
});
|
||||
|
||||
case "for":
|
||||
@@ -959,15 +959,13 @@ function parse($TEXT, options) {
|
||||
value = expression();
|
||||
semicolon();
|
||||
}
|
||||
return new AST_Return({
|
||||
value: value
|
||||
});
|
||||
return new AST_Return({ value: value });
|
||||
|
||||
case "switch":
|
||||
next();
|
||||
return new AST_Switch({
|
||||
expression : parenthesised(),
|
||||
body : in_loop(switch_body_)
|
||||
expression : parenthesized(),
|
||||
body : in_loop(switch_body_),
|
||||
});
|
||||
|
||||
case "throw":
|
||||
@@ -976,9 +974,7 @@ function parse($TEXT, options) {
|
||||
croak("Illegal newline after 'throw'");
|
||||
var value = expression();
|
||||
semicolon();
|
||||
return new AST_Throw({
|
||||
value: value
|
||||
});
|
||||
return new AST_Throw({ value: value });
|
||||
|
||||
case "try":
|
||||
next();
|
||||
@@ -996,8 +992,8 @@ function parse($TEXT, options) {
|
||||
}
|
||||
next();
|
||||
return new AST_With({
|
||||
expression : parenthesised(),
|
||||
body : statement()
|
||||
expression : parenthesized(),
|
||||
body : statement(),
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1421,15 +1417,15 @@ function parse($TEXT, options) {
|
||||
};
|
||||
|
||||
function if_() {
|
||||
var cond = parenthesised(), body = statement(), belse = null;
|
||||
var cond = parenthesized(), body = statement(), alt = null;
|
||||
if (is("keyword", "else")) {
|
||||
next();
|
||||
belse = statement();
|
||||
alt = statement();
|
||||
}
|
||||
return new AST_If({
|
||||
condition : cond,
|
||||
body : body,
|
||||
alternative : belse
|
||||
alternative : alt,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2171,9 +2167,9 @@ function parse($TEXT, options) {
|
||||
token_error(sym.start, "Unexpected " + sym.name + " in strict mode");
|
||||
}
|
||||
|
||||
function as_symbol(type, noerror) {
|
||||
function as_symbol(type, no_error) {
|
||||
if (!is("name")) {
|
||||
if (!noerror) croak("Name expected");
|
||||
if (!no_error) croak("Name expected");
|
||||
return null;
|
||||
}
|
||||
var sym = _make_symbol(type, S.token);
|
||||
@@ -2409,20 +2405,20 @@ function parse($TEXT, options) {
|
||||
return new ctor({ operator: op, expression: expr });
|
||||
}
|
||||
|
||||
var expr_op = function(left, min_prec, no_in) {
|
||||
var expr_op = function(left, min_precision, no_in) {
|
||||
var op = is("operator") ? S.token.value : null;
|
||||
if (op == "in" && no_in) op = null;
|
||||
var prec = op != null ? PRECEDENCE[op] : null;
|
||||
if (prec != null && prec > min_prec) {
|
||||
var precision = op != null ? PRECEDENCE[op] : null;
|
||||
if (precision != null && precision > min_precision) {
|
||||
next();
|
||||
var right = expr_op(maybe_unary(no_in), op == "**" ? prec - 1 : prec, no_in);
|
||||
var right = expr_op(maybe_unary(no_in), op == "**" ? precision - 1 : precision, no_in);
|
||||
return expr_op(new AST_Binary({
|
||||
start : left.start,
|
||||
left : left,
|
||||
operator : op,
|
||||
right : right,
|
||||
end : right.end
|
||||
}), min_prec, no_in);
|
||||
end : right.end,
|
||||
}), min_precision, no_in);
|
||||
}
|
||||
return left;
|
||||
};
|
||||
|
||||
@@ -124,12 +124,16 @@ function get_builtins() {
|
||||
|
||||
function reserve_quoted_keys(ast, reserved) {
|
||||
ast.walk(new TreeWalker(function(node) {
|
||||
if (node instanceof AST_ClassProperty) {
|
||||
if (node.start && node.start.quote) add(node.key);
|
||||
if (node instanceof AST_ClassProperty
|
||||
|| node instanceof AST_DestructuredKeyVal
|
||||
|| node instanceof AST_ObjectProperty) {
|
||||
if (node.key instanceof AST_Node) {
|
||||
addStrings(node.key, add);
|
||||
} else if (node.start && node.start.quote) {
|
||||
add(node.key);
|
||||
}
|
||||
} else if (node instanceof AST_Dot) {
|
||||
if (node.quoted) add(node.property);
|
||||
} else if (node instanceof AST_ObjectProperty) {
|
||||
if (node.start && node.start.quote) add(node.key);
|
||||
} else if (node instanceof AST_Sub) {
|
||||
addStrings(node.property, add);
|
||||
}
|
||||
@@ -156,12 +160,16 @@ function mangle_properties(ast, options) {
|
||||
builtins: false,
|
||||
cache: null,
|
||||
debug: false,
|
||||
domprops: false,
|
||||
keep_quoted: false,
|
||||
regex: null,
|
||||
reserved: null,
|
||||
}, true);
|
||||
|
||||
var reserved = options.builtins ? new Dictionary() : get_builtins();
|
||||
if (!options.domprops && typeof domprops !== "undefined") domprops.forEach(function(name) {
|
||||
reserved.set(name, true);
|
||||
});
|
||||
if (Array.isArray(options.reserved)) options.reserved.forEach(function(name) {
|
||||
reserved.set(name, true);
|
||||
});
|
||||
@@ -180,7 +188,7 @@ function mangle_properties(ast, options) {
|
||||
var regex = options.regex;
|
||||
|
||||
// note debug is either false (disabled), or a string of the debug suffix to use (enabled).
|
||||
// note debug may be enabled as an empty string, which is falsey. Also treat passing 'true'
|
||||
// note debug may be enabled as an empty string, which is falsy. Also treat passing 'true'
|
||||
// the same as passing an empty string.
|
||||
var debug = options.debug !== false;
|
||||
var debug_suffix;
|
||||
@@ -191,9 +199,7 @@ function mangle_properties(ast, options) {
|
||||
|
||||
// step 1: find candidates to mangle
|
||||
ast.walk(new TreeWalker(function(node) {
|
||||
if (node instanceof AST_Binary) {
|
||||
if (node.operator == "in") addStrings(node.left, add);
|
||||
} else if (node.TYPE == "Call") {
|
||||
if (node.TYPE == "Call") {
|
||||
var exp = node.expression;
|
||||
if (exp instanceof AST_Dot) switch (exp.property) {
|
||||
case "defineProperty":
|
||||
@@ -210,14 +216,18 @@ function mangle_properties(ast, options) {
|
||||
addStrings(node.args[0], add);
|
||||
break;
|
||||
}
|
||||
} else if (node instanceof AST_ClassProperty) {
|
||||
if (typeof node.key == "string") add(node.key);
|
||||
} else if (node instanceof AST_ClassProperty
|
||||
|| node instanceof AST_DestructuredKeyVal
|
||||
|| node instanceof AST_ObjectProperty) {
|
||||
if (node.key instanceof AST_Node) {
|
||||
addStrings(node.key, add);
|
||||
} else {
|
||||
add(node.key);
|
||||
}
|
||||
} else if (node instanceof AST_Dot) {
|
||||
add(node.property);
|
||||
} else if (node instanceof AST_ObjectProperty) {
|
||||
if (typeof node.key == "string") add(node.key);
|
||||
if (is_lhs(node, this.parent())) add(node.property);
|
||||
} else if (node instanceof AST_Sub) {
|
||||
addStrings(node.property, add);
|
||||
if (is_lhs(node, this.parent())) addStrings(node.property, add);
|
||||
}
|
||||
}));
|
||||
|
||||
@@ -242,12 +252,16 @@ function mangle_properties(ast, options) {
|
||||
mangleStrings(node.args[0]);
|
||||
break;
|
||||
}
|
||||
} else if (node instanceof AST_ClassProperty) {
|
||||
if (typeof node.key == "string") node.key = mangle(node.key);
|
||||
} else if (node instanceof AST_ClassProperty
|
||||
|| node instanceof AST_DestructuredKeyVal
|
||||
|| node instanceof AST_ObjectProperty) {
|
||||
if (node.key instanceof AST_Node) {
|
||||
mangleStrings(node.key);
|
||||
} else {
|
||||
node.key = mangle(node.key);
|
||||
}
|
||||
} else if (node instanceof AST_Dot) {
|
||||
node.property = mangle(node.property);
|
||||
} else if (node instanceof AST_ObjectProperty) {
|
||||
if (typeof node.key == "string") node.key = mangle(node.key);
|
||||
} else if (node instanceof AST_Sub) {
|
||||
if (!options.keep_quoted) mangleStrings(node.property);
|
||||
}
|
||||
@@ -303,7 +317,7 @@ function mangle_properties(ast, options) {
|
||||
|
||||
function mangleStrings(node) {
|
||||
if (node instanceof AST_Sequence) {
|
||||
mangleStrings(node.expressions.tail_node());
|
||||
mangleStrings(node.tail_node());
|
||||
} else if (node instanceof AST_String) {
|
||||
node.value = mangle(node.value);
|
||||
} else if (node instanceof AST_Conditional) {
|
||||
|
||||
@@ -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.17.2",
|
||||
"version": "3.17.3",
|
||||
"engines": {
|
||||
"node": ">=0.8.0"
|
||||
},
|
||||
|
||||
@@ -126,6 +126,17 @@ function parse_test(file) {
|
||||
croak(node);
|
||||
}
|
||||
var name = node.left.name;
|
||||
assert.ok([
|
||||
"beautify",
|
||||
"expression",
|
||||
"mangle",
|
||||
"options",
|
||||
"rename",
|
||||
].indexOf(name) >= 0, tmpl("Unsupported setting {name} [{line},{col}]", {
|
||||
name: name,
|
||||
line: node.start.line,
|
||||
col: node.start.col,
|
||||
}));
|
||||
test[name] = evaluate(node.right);
|
||||
return true;
|
||||
}
|
||||
@@ -271,7 +282,9 @@ function test_case(test) {
|
||||
expect = test.expect_exact;
|
||||
}
|
||||
var input = to_toplevel(test.input, test.mangle, test.expression);
|
||||
var input_code = make_code(input, {}, test.expression);
|
||||
var input_code = make_code(input, {
|
||||
keep_quoted_props: true,
|
||||
}, test.expression);
|
||||
var input_formatted = make_code(test.input, {
|
||||
annotations: true,
|
||||
beautify: true,
|
||||
|
||||
@@ -290,6 +290,45 @@ increment_decrement_2: {
|
||||
expect_stdout: "42"
|
||||
}
|
||||
|
||||
lazily_chained_assignments: {
|
||||
options = {
|
||||
assignments: true,
|
||||
collapse_vars: true,
|
||||
conditionals: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f(a) {
|
||||
if (a = console.log("foo"))
|
||||
a = console.log("bar");
|
||||
return a;
|
||||
}
|
||||
function g(b) {
|
||||
if (b = console.log("baz"))
|
||||
;
|
||||
else
|
||||
b = console.log("moo");
|
||||
return b;
|
||||
}
|
||||
console.log(f(), g());
|
||||
}
|
||||
expect: {
|
||||
function f(a) {
|
||||
return console.log("foo") && console.log("bar");
|
||||
}
|
||||
function g(b) {
|
||||
return console.log("baz") || console.log("moo");
|
||||
}
|
||||
console.log(f(), g());
|
||||
}
|
||||
expect_stdout: [
|
||||
"foo",
|
||||
"baz",
|
||||
"moo",
|
||||
"undefined undefined",
|
||||
]
|
||||
}
|
||||
|
||||
issue_3375_1: {
|
||||
options = {
|
||||
assignments: true,
|
||||
|
||||
@@ -3540,3 +3540,61 @@ issue_5634_3_side_effects: {
|
||||
]
|
||||
node_version: ">=8"
|
||||
}
|
||||
|
||||
issue_5692_1: {
|
||||
options = {
|
||||
awaits: true,
|
||||
inline: true,
|
||||
}
|
||||
input: {
|
||||
(async function() {
|
||||
(async function() {
|
||||
for await (var k of []);
|
||||
})();
|
||||
console.log("foo");
|
||||
})();
|
||||
console.log("bar");
|
||||
}
|
||||
expect: {
|
||||
(async function() {
|
||||
(async function() {
|
||||
for await (var k of []);
|
||||
})();
|
||||
console.log("foo");
|
||||
})();
|
||||
console.log("bar");
|
||||
}
|
||||
expect_stdout: [
|
||||
"foo",
|
||||
"bar",
|
||||
]
|
||||
node_version: ">=10"
|
||||
}
|
||||
|
||||
issue_5692_2: {
|
||||
options = {
|
||||
awaits: true,
|
||||
inline: true,
|
||||
}
|
||||
input: {
|
||||
(async function() {
|
||||
(async function() {
|
||||
for (var k of []);
|
||||
})();
|
||||
console.log("foo");
|
||||
})();
|
||||
console.log("bar");
|
||||
}
|
||||
expect: {
|
||||
(async function() {
|
||||
for (var k of []);
|
||||
console.log("foo");
|
||||
})();
|
||||
console.log("bar");
|
||||
}
|
||||
expect_stdout: [
|
||||
"foo",
|
||||
"bar",
|
||||
]
|
||||
node_version: ">=8"
|
||||
}
|
||||
|
||||
@@ -80,6 +80,25 @@ de_morgan_1c: {
|
||||
expect_stdout: "true"
|
||||
}
|
||||
|
||||
de_morgan_1d: {
|
||||
options = {
|
||||
booleans: true,
|
||||
}
|
||||
input: {
|
||||
function f(a) {
|
||||
return (a = false) || a;
|
||||
}
|
||||
console.log(f(null), f(42));
|
||||
}
|
||||
expect: {
|
||||
function f(a) {
|
||||
return a = !1;
|
||||
}
|
||||
console.log(f(null), f(42));
|
||||
}
|
||||
expect_stdout: "false false"
|
||||
}
|
||||
|
||||
de_morgan_2a: {
|
||||
options = {
|
||||
booleans: true,
|
||||
@@ -181,6 +200,31 @@ de_morgan_2d: {
|
||||
]
|
||||
}
|
||||
|
||||
de_morgan_2e: {
|
||||
options = {
|
||||
booleans: true,
|
||||
conditionals: true,
|
||||
}
|
||||
input: {
|
||||
function f(a, b) {
|
||||
return (a && b) && b;
|
||||
}
|
||||
console.log(f(null), f(null, {}));
|
||||
console.log(f(42), f(42, {}));
|
||||
}
|
||||
expect: {
|
||||
function f(a, b) {
|
||||
return a && b;
|
||||
}
|
||||
console.log(f(null), f(null, {}));
|
||||
console.log(f(42), f(42, {}));
|
||||
}
|
||||
expect_stdout: [
|
||||
"null null",
|
||||
"undefined {}",
|
||||
]
|
||||
}
|
||||
|
||||
de_morgan_3a: {
|
||||
options = {
|
||||
booleans: true,
|
||||
@@ -786,3 +830,37 @@ issue_5469: {
|
||||
}
|
||||
expect_stdout: "undefined"
|
||||
}
|
||||
|
||||
issue_5694_1: {
|
||||
options = {
|
||||
booleans: true,
|
||||
conditionals: true,
|
||||
}
|
||||
input: {
|
||||
var Infinity;
|
||||
// Node.js v0.12~6 (vm): 42
|
||||
console.log((Infinity = 42) && Infinity);
|
||||
}
|
||||
expect: {
|
||||
var Infinity;
|
||||
console.log((Infinity = 42) && Infinity);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
issue_5694_2: {
|
||||
options = {
|
||||
booleans: true,
|
||||
conditionals: true,
|
||||
}
|
||||
input: {
|
||||
var undefined;
|
||||
// Node.js v0.12~6 (vm): NaN
|
||||
console.log(("foo", ++undefined) || undefined);
|
||||
}
|
||||
expect: {
|
||||
var undefined;
|
||||
console.log(("foo", ++undefined) || undefined);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
@@ -599,6 +599,7 @@ drop_extends: {
|
||||
inline: true,
|
||||
passes: 2,
|
||||
pure_getters: "strict",
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
@@ -921,6 +922,7 @@ single_use_3: {
|
||||
|
||||
single_use_4: {
|
||||
options = {
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
@@ -1503,6 +1505,218 @@ keep_instanceof_3: {
|
||||
node_version: ">=4"
|
||||
}
|
||||
|
||||
keep_field_reference_1: {
|
||||
options = {
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
"use strict";
|
||||
function f() {}
|
||||
class A {
|
||||
p = f;
|
||||
}
|
||||
console.log(new A().p === new A().p ? "PASS" : "FAIL");
|
||||
}
|
||||
expect: {
|
||||
"use strict";
|
||||
function f() {}
|
||||
class A {
|
||||
p = f;
|
||||
}
|
||||
console.log(new A().p === new A().p ? "PASS" : "FAIL");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=12"
|
||||
}
|
||||
|
||||
keep_field_reference_2: {
|
||||
options = {
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
"use strict";
|
||||
function f() {}
|
||||
var A = class {
|
||||
p = f;
|
||||
};
|
||||
console.log(new A().p === new A().p ? "PASS" : "FAIL");
|
||||
}
|
||||
expect: {
|
||||
"use strict";
|
||||
function f() {}
|
||||
var A = class {
|
||||
p = f;
|
||||
};
|
||||
console.log(new A().p === new A().p ? "PASS" : "FAIL");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=12"
|
||||
}
|
||||
|
||||
keep_field_reference_3: {
|
||||
options = {
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
"use strict";
|
||||
class A {}
|
||||
class B {
|
||||
p = A;
|
||||
}
|
||||
console.log(new B().p === new B().p ? "PASS" : "FAIL");
|
||||
}
|
||||
expect: {
|
||||
"use strict";
|
||||
class A {}
|
||||
class B {
|
||||
p = A;
|
||||
}
|
||||
console.log(new B().p === new B().p ? "PASS" : "FAIL");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=12"
|
||||
}
|
||||
|
||||
keep_field_reference_4: {
|
||||
options = {
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
"use strict";
|
||||
var A = class {};
|
||||
var B = class {
|
||||
p = A;
|
||||
};
|
||||
console.log(new B().p === new B().p ? "PASS" : "FAIL");
|
||||
}
|
||||
expect: {
|
||||
"use strict";
|
||||
var A = class {};
|
||||
var B = class {
|
||||
p = A;
|
||||
};
|
||||
console.log(new B().p === new B().p ? "PASS" : "FAIL");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=12"
|
||||
}
|
||||
|
||||
keep_static_field_reference_1: {
|
||||
options = {
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
"use strict";
|
||||
function f() {}
|
||||
class A {
|
||||
static P = f;
|
||||
}
|
||||
console.log(A.P === A.P ? "PASS" : "FAIL");
|
||||
}
|
||||
expect: {
|
||||
"use strict";
|
||||
class A {
|
||||
static P = function() {};
|
||||
}
|
||||
console.log(A.P === A.P ? "PASS" : "FAIL");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=12"
|
||||
}
|
||||
|
||||
keep_static_field_reference_2: {
|
||||
options = {
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
"use strict";
|
||||
function f() {}
|
||||
var A = class {
|
||||
static P = f;
|
||||
};
|
||||
console.log(A.P === A.P ? "PASS" : "FAIL");
|
||||
}
|
||||
expect: {
|
||||
"use strict";
|
||||
var A = class {
|
||||
static P = function() {};
|
||||
};
|
||||
console.log(A.P === A.P ? "PASS" : "FAIL");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=12"
|
||||
}
|
||||
|
||||
keep_static_field_reference_3: {
|
||||
options = {
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
"use strict";
|
||||
class A {}
|
||||
class B {
|
||||
static P = A;
|
||||
}
|
||||
console.log(B.P === B.P ? "PASS" : "FAIL");
|
||||
}
|
||||
expect: {
|
||||
"use strict";
|
||||
class B {
|
||||
static P = class {};
|
||||
}
|
||||
console.log(B.P === B.P ? "PASS" : "FAIL");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=12"
|
||||
}
|
||||
|
||||
keep_static_field_reference_4: {
|
||||
options = {
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
"use strict";
|
||||
var A = class {};
|
||||
var B = class {
|
||||
static P = A;
|
||||
};
|
||||
console.log(B.P === B.P ? "PASS" : "FAIL");
|
||||
}
|
||||
expect: {
|
||||
"use strict";
|
||||
var B = class {
|
||||
static P = class {};
|
||||
};
|
||||
console.log(B.P === B.P ? "PASS" : "FAIL");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=12"
|
||||
}
|
||||
|
||||
issue_805_1: {
|
||||
options = {
|
||||
inline: true,
|
||||
@@ -2164,6 +2378,7 @@ issue_4829_2: {
|
||||
mangle_properties: {
|
||||
mangle = {
|
||||
properties: {
|
||||
domprops: true,
|
||||
keep_quoted: true,
|
||||
},
|
||||
}
|
||||
@@ -2202,11 +2417,11 @@ mangle_properties: {
|
||||
expect_stdout: "PASS 42"
|
||||
expect_warnings: [
|
||||
"INFO: Preserving reserved property q",
|
||||
"INFO: Preserving reserved property log",
|
||||
"INFO: Mapping property #P to #t",
|
||||
"INFO: Mapping property Q to s",
|
||||
"INFO: Mapping property #p to #i",
|
||||
"INFO: Mapping property r to e",
|
||||
"INFO: Preserving reserved property log",
|
||||
]
|
||||
node_version: ">=14.6"
|
||||
}
|
||||
@@ -2312,6 +2527,7 @@ issue_4962_1: {
|
||||
options = {
|
||||
ie: true,
|
||||
inline: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
@@ -2343,6 +2559,7 @@ issue_4962_1_strict: {
|
||||
options = {
|
||||
ie: true,
|
||||
inline: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
@@ -2370,6 +2587,7 @@ issue_4962_1_strict_direct: {
|
||||
options = {
|
||||
ie: true,
|
||||
inline: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
@@ -2401,6 +2619,7 @@ issue_4962_2: {
|
||||
options = {
|
||||
ie: true,
|
||||
inline: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
@@ -2432,6 +2651,7 @@ issue_4962_2_strict: {
|
||||
options = {
|
||||
ie: true,
|
||||
inline: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
@@ -2460,6 +2680,7 @@ issue_4962_2_strict_direct: {
|
||||
options = {
|
||||
ie: true,
|
||||
inline: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
@@ -2494,6 +2715,7 @@ issue_4962_2_strict_direct_inline: {
|
||||
ie: true,
|
||||
inline: true,
|
||||
passes: 2,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
@@ -2877,6 +3099,7 @@ issue_5053_4: {
|
||||
issue_5082_1: {
|
||||
options = {
|
||||
inline: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
@@ -2909,6 +3132,7 @@ issue_5082_1: {
|
||||
issue_5082_1_strict: {
|
||||
options = {
|
||||
inline: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
@@ -2942,6 +3166,7 @@ issue_5082_2: {
|
||||
options = {
|
||||
inline: true,
|
||||
passes: 2,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
@@ -2975,6 +3200,7 @@ issue_5082_2_static: {
|
||||
options = {
|
||||
inline: true,
|
||||
passes: 2,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
@@ -3619,3 +3845,59 @@ issue_5662: {
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_5682_class_key: {
|
||||
mangle = {
|
||||
properties: true,
|
||||
}
|
||||
input: {
|
||||
"use strict";
|
||||
function f(a) {
|
||||
return "foo" in a;
|
||||
}
|
||||
class A {
|
||||
foo() {}
|
||||
}
|
||||
console.log(f(new A()) ? "PASS" : "FAIL");
|
||||
}
|
||||
expect: {
|
||||
"use strict";
|
||||
function f(o) {
|
||||
return "o" in o;
|
||||
}
|
||||
class A {
|
||||
o() {}
|
||||
}
|
||||
console.log(f(new A()) ? "PASS" : "FAIL");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=4"
|
||||
}
|
||||
|
||||
issue_5682_class_key_computed: {
|
||||
mangle = {
|
||||
properties: true,
|
||||
}
|
||||
input: {
|
||||
"use strict";
|
||||
function f(a) {
|
||||
return "foo" in a;
|
||||
}
|
||||
class A {
|
||||
["foo"]() {}
|
||||
}
|
||||
console.log(f(new A()) ? "PASS" : "FAIL");
|
||||
}
|
||||
expect: {
|
||||
"use strict";
|
||||
function f(o) {
|
||||
return "o" in o;
|
||||
}
|
||||
class A {
|
||||
["o"]() {}
|
||||
}
|
||||
console.log(f(new A()) ? "PASS" : "FAIL");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=4"
|
||||
}
|
||||
|
||||
@@ -275,6 +275,7 @@ issue_2857_3: {
|
||||
issue_2857_4: {
|
||||
options = {
|
||||
comparisons: true,
|
||||
conditionals: true,
|
||||
}
|
||||
input: {
|
||||
function f(a, p) {
|
||||
@@ -305,6 +306,7 @@ issue_2857_4: {
|
||||
issue_2857_5: {
|
||||
options = {
|
||||
comparisons: true,
|
||||
conditionals: true,
|
||||
}
|
||||
input: {
|
||||
function f(a, p) {
|
||||
@@ -528,6 +530,7 @@ nullish_assign: {
|
||||
nullish_chain: {
|
||||
options = {
|
||||
comparisons: true,
|
||||
conditionals: true,
|
||||
}
|
||||
input: {
|
||||
var a;
|
||||
|
||||
@@ -12,7 +12,7 @@ concat_1: {
|
||||
|
||||
var e = 1 + x() + 2 + "X" + 3 + "boo";
|
||||
|
||||
// be careful with concatentation with "\0" with octal-looking strings.
|
||||
// be careful with concatenation with "\0" with octal-looking strings.
|
||||
var f = "\0" + 360 + "\0" + 8 + "\0";
|
||||
}
|
||||
expect: {
|
||||
|
||||
@@ -3028,8 +3028,26 @@ issue_5673_2: {
|
||||
expect: {
|
||||
var a = "PASS";
|
||||
console.log(function(b) {
|
||||
return ((b = a) || (b = a)) && b;
|
||||
return a || (b = a) && b;
|
||||
}());
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_5694: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
}
|
||||
input: {
|
||||
FORCE_EXEC = "async()=>{}";
|
||||
var a = "foo";
|
||||
// Node.js v0.12~6 (vm): foo
|
||||
console.log((NaN = a) ? NaN : 42);
|
||||
}
|
||||
expect: {
|
||||
FORCE_EXEC = "async()=>{}";
|
||||
var a = "foo";
|
||||
console.log((NaN = a) ? NaN : 42);
|
||||
}
|
||||
expect_stdout: "NaN"
|
||||
}
|
||||
|
||||
@@ -1737,6 +1737,23 @@ singleton_side_effects: {
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
mangle_properties: {
|
||||
mangle = {
|
||||
properties: {
|
||||
domprops: true,
|
||||
},
|
||||
}
|
||||
input: {
|
||||
function f({ p: a }) {
|
||||
return a;
|
||||
}
|
||||
console.log(f({ p: "PASS" }));
|
||||
}
|
||||
expect_exact: 'function f({n}){return n}console.log(f({n:"PASS"}));'
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_4280: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
|
||||
@@ -8719,3 +8719,24 @@ single_use_inline_collision: {
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_5692: {
|
||||
options = {
|
||||
inline: true,
|
||||
}
|
||||
input: {
|
||||
(function() {
|
||||
while (console.log("PASS"))
|
||||
if (console)
|
||||
return;
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
(function() {
|
||||
while (console.log("PASS"))
|
||||
if (console)
|
||||
return;
|
||||
})();
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
@@ -525,7 +525,7 @@ if_var_return_2: {
|
||||
}
|
||||
}
|
||||
|
||||
if_var_retrn_3: {
|
||||
if_var_return_3: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
if_return: true,
|
||||
@@ -2442,3 +2442,41 @@ issue_5649: {
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_5688: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
if_return: true,
|
||||
}
|
||||
input: {
|
||||
L: do {
|
||||
switch (console) {
|
||||
default:
|
||||
if (console)
|
||||
break;
|
||||
if (FAIL_1)
|
||||
;
|
||||
else
|
||||
break L;
|
||||
break;
|
||||
case 42:
|
||||
FAIL_2;
|
||||
}
|
||||
} while (console.log("PASS"));
|
||||
}
|
||||
expect: {
|
||||
L: do {
|
||||
switch (console) {
|
||||
default:
|
||||
if (console)
|
||||
break;
|
||||
if (FAIL_1)
|
||||
break;
|
||||
break L;
|
||||
case 42:
|
||||
FAIL_2;
|
||||
}
|
||||
} while (console.log("PASS"));
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
@@ -140,12 +140,12 @@ mangle: {
|
||||
}
|
||||
input: {
|
||||
import foo, { bar } from "baz";
|
||||
consoe.log(moo);
|
||||
console.log(moo);
|
||||
import * as moo from "moz";
|
||||
}
|
||||
expect: {
|
||||
import o, { bar as m } from "baz";
|
||||
consoe.log(r);
|
||||
console.log(r);
|
||||
import * as r from "moz";
|
||||
}
|
||||
}
|
||||
@@ -157,12 +157,12 @@ rename_mangle: {
|
||||
}
|
||||
input: {
|
||||
import foo, { bar } from "baz";
|
||||
consoe.log(moo);
|
||||
console.log(moo);
|
||||
import * as moo from "moz";
|
||||
}
|
||||
expect: {
|
||||
import o, { bar as m } from "baz";
|
||||
consoe.log(r);
|
||||
console.log(r);
|
||||
import * as r from "moz";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
issue_1321_no_debug: {
|
||||
mangle = {
|
||||
properties: {
|
||||
domprops: true,
|
||||
keep_quoted: true,
|
||||
},
|
||||
}
|
||||
@@ -23,6 +24,7 @@ issue_1321_debug: {
|
||||
mangle = {
|
||||
properties: {
|
||||
debug: "",
|
||||
domprops: true,
|
||||
keep_quoted: true,
|
||||
},
|
||||
}
|
||||
@@ -44,6 +46,7 @@ issue_1321_debug: {
|
||||
issue_1321_with_quoted: {
|
||||
mangle = {
|
||||
properties: {
|
||||
domprops: true,
|
||||
keep_quoted: false,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* There was an incorrect sort behaviour documented in issue #143:
|
||||
* There was an incorrect sort behavior documented in issue #143:
|
||||
* (x = f(…)) <= x → x >= (x = f(…))
|
||||
*
|
||||
* For example, let the equation be:
|
||||
@@ -12,37 +12,54 @@
|
||||
* a >= (a = parseInt('100')) → 99 >= 100 → false
|
||||
*/
|
||||
|
||||
tranformation_sort_order_equal: {
|
||||
transformation_sort_order_equal: {
|
||||
options = {
|
||||
comparisons: true,
|
||||
}
|
||||
|
||||
input: { (a = parseInt('100')) == a }
|
||||
expect: { (a = parseInt('100')) == a }
|
||||
input: {
|
||||
console.log((a = parseInt("100")) == a);
|
||||
}
|
||||
expect: {
|
||||
console.log((a = parseInt("100")) == a);
|
||||
}
|
||||
expect_stdout: "true"
|
||||
}
|
||||
|
||||
tranformation_sort_order_unequal: {
|
||||
transformation_sort_order_unequal: {
|
||||
options = {
|
||||
comparisons: true,
|
||||
}
|
||||
|
||||
input: { (a = parseInt('100')) != a }
|
||||
expect: { (a = parseInt('100')) != a }
|
||||
input: {
|
||||
console.log((a = parseInt("100")) != a);
|
||||
}
|
||||
expect: {
|
||||
console.log((a = parseInt("100")) != a);
|
||||
}
|
||||
expect_stdout: "false"
|
||||
}
|
||||
|
||||
tranformation_sort_order_lesser_or_equal: {
|
||||
transformation_sort_order_lesser_or_equal: {
|
||||
options = {
|
||||
comparisons: true,
|
||||
}
|
||||
|
||||
input: { (a = parseInt('100')) <= a }
|
||||
expect: { (a = parseInt('100')) <= a }
|
||||
input: {
|
||||
console.log((a = parseInt("100")) <= a);
|
||||
}
|
||||
expect: {
|
||||
console.log((a = parseInt("100")) <= a);
|
||||
}
|
||||
expect_stdout: "true"
|
||||
}
|
||||
tranformation_sort_order_greater_or_equal: {
|
||||
|
||||
transformation_sort_order_greater_or_equal: {
|
||||
options = {
|
||||
comparisons: true,
|
||||
}
|
||||
|
||||
input: { (a = parseInt('100')) >= a }
|
||||
expect: { (a = parseInt('100')) >= a }
|
||||
}
|
||||
input: {
|
||||
console.log((a = parseInt("100")) >= a);
|
||||
}
|
||||
expect: {
|
||||
console.log((a = parseInt("100")) >= a);
|
||||
}
|
||||
expect_stdout: "true"
|
||||
}
|
||||
|
||||
@@ -65,7 +65,9 @@ mangle_props: {
|
||||
|
||||
numeric_literal: {
|
||||
mangle = {
|
||||
properties: true,
|
||||
properties: {
|
||||
domprops: true,
|
||||
},
|
||||
}
|
||||
beautify = {
|
||||
beautify: true,
|
||||
@@ -115,9 +117,9 @@ numeric_literal: {
|
||||
"8 7 8",
|
||||
]
|
||||
expect_warnings: [
|
||||
"INFO: Preserving reserved property log",
|
||||
"INFO: Mapping property 0x25 to o",
|
||||
"INFO: Mapping property 1E42 to b",
|
||||
"INFO: Preserving reserved property log",
|
||||
]
|
||||
}
|
||||
|
||||
@@ -125,6 +127,7 @@ identifier: {
|
||||
mangle = {
|
||||
properties: {
|
||||
builtins: true,
|
||||
domprops: true,
|
||||
},
|
||||
}
|
||||
input: {
|
||||
|
||||
@@ -15,7 +15,7 @@ collapse: {
|
||||
var a;
|
||||
b = c();
|
||||
a = typeof b === 'function' ? b() : b;
|
||||
return 'stirng' == typeof a && d();
|
||||
return 'string' == typeof a && d();
|
||||
}
|
||||
function f3(c) {
|
||||
var a;
|
||||
@@ -41,7 +41,7 @@ collapse: {
|
||||
return void 0 !== ('function' === typeof b ? b() : b) && c();
|
||||
}
|
||||
function f2(b) {
|
||||
return 'stirng' == typeof ('function' === typeof (b = c()) ? b() : b) && d();
|
||||
return 'string' == typeof ('function' === typeof (b = c()) ? b() : b) && d();
|
||||
}
|
||||
function f3(c) {
|
||||
var a;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
dont_reuse_prop: {
|
||||
mangle = {
|
||||
properties: {
|
||||
domprops: true,
|
||||
regex: /asd/,
|
||||
},
|
||||
}
|
||||
@@ -21,14 +22,15 @@ dont_reuse_prop: {
|
||||
expect_stdout: "123"
|
||||
expect_warnings: [
|
||||
"INFO: Preserving excluded property a",
|
||||
"INFO: Preserving reserved property log",
|
||||
"INFO: Mapping property asd to b",
|
||||
"INFO: Preserving reserved property log",
|
||||
]
|
||||
}
|
||||
|
||||
unmangleable_props_should_always_be_reserved: {
|
||||
mangle = {
|
||||
properties: {
|
||||
domprops: true,
|
||||
regex: /asd/,
|
||||
},
|
||||
}
|
||||
@@ -49,7 +51,7 @@ unmangleable_props_should_always_be_reserved: {
|
||||
expect_stdout: "123"
|
||||
expect_warnings: [
|
||||
"INFO: Preserving excluded property a",
|
||||
"INFO: Preserving reserved property log",
|
||||
"INFO: Mapping property asd to b",
|
||||
"INFO: Preserving reserved property log",
|
||||
]
|
||||
}
|
||||
|
||||
@@ -570,7 +570,7 @@ inlined_assignments: {
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
inilne_for: {
|
||||
inline_for: {
|
||||
options = {
|
||||
inline: true,
|
||||
join_vars: true,
|
||||
@@ -590,7 +590,7 @@ inilne_for: {
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
inilne_var: {
|
||||
inline_var: {
|
||||
options = {
|
||||
inline: true,
|
||||
join_vars: true,
|
||||
|
||||
@@ -173,7 +173,9 @@ numeric_literal: {
|
||||
side_effects: true,
|
||||
}
|
||||
mangle = {
|
||||
properties: true,
|
||||
properties: {
|
||||
domprops: true,
|
||||
},
|
||||
}
|
||||
beautify = {
|
||||
beautify: true,
|
||||
|
||||
@@ -133,6 +133,7 @@ evaluate_string_length: {
|
||||
mangle_properties_1: {
|
||||
mangle = {
|
||||
properties: {
|
||||
domprops: true,
|
||||
keep_quoted: false,
|
||||
},
|
||||
}
|
||||
@@ -147,17 +148,18 @@ mangle_properties_1: {
|
||||
a["a"] = "bar";
|
||||
a.b = "red";
|
||||
x = {o: 10};
|
||||
a.r(x.o, a.a);
|
||||
a['r']({b: "blue", a: "baz"});
|
||||
a.run(x.o, a.a);
|
||||
a['run']({b: "blue", a: "baz"});
|
||||
}
|
||||
}
|
||||
|
||||
mangle_properties_2: {
|
||||
mangle = {
|
||||
properties: {
|
||||
domprops: true,
|
||||
reserved: [
|
||||
"value",
|
||||
]
|
||||
],
|
||||
},
|
||||
}
|
||||
input: {
|
||||
@@ -199,6 +201,24 @@ mangle_properties_2: {
|
||||
]
|
||||
}
|
||||
|
||||
mangle_properties_3: {
|
||||
mangle = {
|
||||
properties: true,
|
||||
}
|
||||
input: {
|
||||
console.log({
|
||||
[(console, "foo")]: "PASS",
|
||||
}.foo);
|
||||
}
|
||||
expect: {
|
||||
console.log({
|
||||
[(console, "o")]: "PASS",
|
||||
}.o);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=4"
|
||||
}
|
||||
|
||||
mangle_unquoted_properties: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
@@ -207,6 +227,7 @@ mangle_unquoted_properties: {
|
||||
mangle = {
|
||||
properties: {
|
||||
builtins: true,
|
||||
domprops: true,
|
||||
keep_quoted: true,
|
||||
},
|
||||
}
|
||||
@@ -308,6 +329,7 @@ mangle_debug_suffix_keep_quoted: {
|
||||
properties: {
|
||||
builtins: true,
|
||||
debug: "XYZ",
|
||||
domprops: true,
|
||||
keep_quoted: true,
|
||||
reserved: [],
|
||||
},
|
||||
@@ -962,14 +984,14 @@ issue_2256: {
|
||||
}
|
||||
input: {
|
||||
({ "keep": 42 });
|
||||
global.keep = global.change;
|
||||
global.keep = global.change = "PASS";
|
||||
console.log(keep);
|
||||
}
|
||||
expect: {
|
||||
global.keep = global.l;
|
||||
global.keep = global.l = "PASS";
|
||||
console.log(keep);
|
||||
}
|
||||
expect_stdout: "undefined"
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
lhs_prop_1: {
|
||||
@@ -1645,3 +1667,163 @@ issue_5177: {
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=4"
|
||||
}
|
||||
|
||||
issue_5682_in_1: {
|
||||
mangle = {
|
||||
properties: true,
|
||||
}
|
||||
input: {
|
||||
function f(a) {
|
||||
return "foo" in a;
|
||||
}
|
||||
var o = {};
|
||||
var p = "foo";
|
||||
o[p] = 42;
|
||||
console.log(f(o) ? "PASS" : "FAIL");
|
||||
}
|
||||
expect: {
|
||||
function f(o) {
|
||||
return "foo" in o;
|
||||
}
|
||||
var o = {};
|
||||
var p = "foo";
|
||||
o[p] = 42;
|
||||
console.log(f(o) ? "PASS" : "FAIL");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_5682_in_2: {
|
||||
mangle = {
|
||||
properties: true,
|
||||
}
|
||||
input: {
|
||||
function f(a) {
|
||||
return "foo" in a;
|
||||
}
|
||||
var o = { foo: 42 };
|
||||
console.log(f(o) ? "PASS" : "FAIL");
|
||||
}
|
||||
expect: {
|
||||
function f(o) {
|
||||
return "o" in o;
|
||||
}
|
||||
var o = { o: 42 };
|
||||
console.log(f(o) ? "PASS" : "FAIL");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_5682_dot_1: {
|
||||
mangle = {
|
||||
properties: true,
|
||||
}
|
||||
input: {
|
||||
function f(a) {
|
||||
return a.foo;
|
||||
}
|
||||
var o = {};
|
||||
var p = "foo";
|
||||
o[p] = "PASS";
|
||||
console.log(f(o));
|
||||
}
|
||||
expect: {
|
||||
function f(o) {
|
||||
return o.foo;
|
||||
}
|
||||
var o = {};
|
||||
var p = "foo";
|
||||
o[p] = "PASS";
|
||||
console.log(f(o));
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_5682_dot_2: {
|
||||
mangle = {
|
||||
properties: true,
|
||||
}
|
||||
input: {
|
||||
function f(a) {
|
||||
return a.foo;
|
||||
}
|
||||
var o = { foo: "PASS" };
|
||||
console.log(f(o));
|
||||
}
|
||||
expect: {
|
||||
function f(o) {
|
||||
return o.o;
|
||||
}
|
||||
var o = { o: "PASS" };
|
||||
console.log(f(o));
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_5682_dot_2_computed: {
|
||||
mangle = {
|
||||
properties: true,
|
||||
}
|
||||
input: {
|
||||
function f(a) {
|
||||
return a.foo;
|
||||
}
|
||||
var o = { ["foo"]: "PASS" };
|
||||
console.log(f(o));
|
||||
}
|
||||
expect: {
|
||||
function f(o) {
|
||||
return o.o;
|
||||
}
|
||||
var o = { ["o"]: "PASS" };
|
||||
console.log(f(o));
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=4"
|
||||
}
|
||||
|
||||
issue_5682_sub_1: {
|
||||
mangle = {
|
||||
properties: true,
|
||||
}
|
||||
input: {
|
||||
function f(a) {
|
||||
return a["foo"];
|
||||
}
|
||||
var o = {};
|
||||
var p = "foo";
|
||||
o[p] = "PASS";
|
||||
console.log(f(o));
|
||||
}
|
||||
expect: {
|
||||
function f(o) {
|
||||
return o["foo"];
|
||||
}
|
||||
var o = {};
|
||||
var p = "foo";
|
||||
o[p] = "PASS";
|
||||
console.log(f(o));
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_5682_sub_2: {
|
||||
mangle = {
|
||||
properties: true,
|
||||
}
|
||||
input: {
|
||||
function f(a) {
|
||||
return a["foo"];
|
||||
}
|
||||
var o = { foo: "PASS" };
|
||||
console.log(f(o));
|
||||
}
|
||||
expect: {
|
||||
function f(o) {
|
||||
return o["o"];
|
||||
}
|
||||
var o = { o: "PASS" };
|
||||
console.log(f(o));
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
@@ -682,3 +682,165 @@ issue_5516: {
|
||||
expect_stdout: "function"
|
||||
node_version: ">=4"
|
||||
}
|
||||
|
||||
issue_5697_1: {
|
||||
options = {
|
||||
if_return: true,
|
||||
inline: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
varify: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function() {
|
||||
f();
|
||||
return typeof a;
|
||||
function f() {
|
||||
(function() {
|
||||
for (var k in { foo: 42 }) {
|
||||
const a = k;
|
||||
console.log(a);
|
||||
}
|
||||
})();
|
||||
}
|
||||
}());
|
||||
}
|
||||
expect: {
|
||||
console.log(function() {
|
||||
(function() {
|
||||
for (var k in { foo: 42 }) {
|
||||
var a = k;
|
||||
console.log(a);
|
||||
}
|
||||
})();
|
||||
return typeof a;
|
||||
}());
|
||||
}
|
||||
expect_stdout: [
|
||||
"foo",
|
||||
"undefined",
|
||||
]
|
||||
}
|
||||
|
||||
issue_5697_2: {
|
||||
options = {
|
||||
if_return: true,
|
||||
inline: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
varify: true,
|
||||
}
|
||||
input: {
|
||||
"use strict";
|
||||
console.log(function() {
|
||||
f();
|
||||
return typeof a;
|
||||
function f() {
|
||||
(function() {
|
||||
for (var k in { foo: 42 }) {
|
||||
let a = k;
|
||||
console.log(a);
|
||||
}
|
||||
})();
|
||||
}
|
||||
}());
|
||||
}
|
||||
expect: {
|
||||
"use strict";
|
||||
console.log(function() {
|
||||
(function() {
|
||||
for (var k in { foo: 42 }) {
|
||||
var a = k;
|
||||
console.log(a);
|
||||
}
|
||||
})();
|
||||
return typeof a;
|
||||
}());
|
||||
}
|
||||
expect_stdout: [
|
||||
"foo",
|
||||
"undefined",
|
||||
]
|
||||
node_version: ">=4"
|
||||
}
|
||||
|
||||
issue_5697_3: {
|
||||
options = {
|
||||
inline: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
varify: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function() {
|
||||
f();
|
||||
return typeof a;
|
||||
function f() {
|
||||
(function() {
|
||||
for (var k in { foo: 42 }) {
|
||||
const a = k;
|
||||
console.log(a);
|
||||
}
|
||||
})();
|
||||
}
|
||||
}());
|
||||
}
|
||||
expect: {
|
||||
console.log(function() {
|
||||
(function() {
|
||||
for (var k in { foo: 42 }) {
|
||||
var a = k;
|
||||
console.log(a);
|
||||
}
|
||||
})();
|
||||
return typeof a;
|
||||
}());
|
||||
}
|
||||
expect_stdout: [
|
||||
"foo",
|
||||
"undefined",
|
||||
]
|
||||
}
|
||||
|
||||
issue_5697_4: {
|
||||
options = {
|
||||
inline: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
varify: true,
|
||||
}
|
||||
input: {
|
||||
"use strict";
|
||||
console.log(function() {
|
||||
f();
|
||||
return typeof a;
|
||||
function f() {
|
||||
(function() {
|
||||
for (var k in { foo: 42 }) {
|
||||
let a = k;
|
||||
console.log(a);
|
||||
}
|
||||
})();
|
||||
}
|
||||
}());
|
||||
}
|
||||
expect: {
|
||||
"use strict";
|
||||
console.log(function() {
|
||||
(function() {
|
||||
for (var k in { foo: 42 }) {
|
||||
var a = k;
|
||||
console.log(a);
|
||||
}
|
||||
})();
|
||||
return typeof a;
|
||||
}());
|
||||
}
|
||||
expect_stdout: [
|
||||
"foo",
|
||||
"undefined",
|
||||
]
|
||||
node_version: ">=4"
|
||||
}
|
||||
|
||||
@@ -1769,3 +1769,252 @@ issue_5663: {
|
||||
]
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_5679_1: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
}
|
||||
input: {
|
||||
var a = "FAIL";
|
||||
async function* f(b) {
|
||||
try {
|
||||
if (b)
|
||||
return;
|
||||
else
|
||||
return;
|
||||
} finally {
|
||||
a = "PASS";
|
||||
}
|
||||
}
|
||||
f().next();
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
var a = "FAIL";
|
||||
async function* f(b) {
|
||||
try {
|
||||
b;
|
||||
return;
|
||||
} finally {
|
||||
a = "PASS";
|
||||
}
|
||||
}
|
||||
f().next();
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=10"
|
||||
}
|
||||
|
||||
issue_5679_2: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
}
|
||||
input: {
|
||||
var a = "FAIL";
|
||||
async function* f(b) {
|
||||
try {
|
||||
if (b)
|
||||
return undefined;
|
||||
else
|
||||
return;
|
||||
} finally {
|
||||
a = "PASS";
|
||||
}
|
||||
}
|
||||
f().next();
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
var a = "FAIL";
|
||||
async function* f(b) {
|
||||
try {
|
||||
if (b)
|
||||
return void 0;
|
||||
return;
|
||||
} finally {
|
||||
a = "PASS";
|
||||
}
|
||||
}
|
||||
f().next();
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=10"
|
||||
}
|
||||
|
||||
issue_5679_3: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
}
|
||||
input: {
|
||||
var a = "FAIL";
|
||||
async function* f(b) {
|
||||
try {
|
||||
if (b)
|
||||
return;
|
||||
else
|
||||
return undefined;
|
||||
} finally {
|
||||
a = "PASS";
|
||||
}
|
||||
}
|
||||
f(42).next();
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
var a = "FAIL";
|
||||
async function* f(b) {
|
||||
try {
|
||||
if (b)
|
||||
return;
|
||||
return void 0;
|
||||
} finally {
|
||||
a = "PASS";
|
||||
}
|
||||
}
|
||||
f(42).next();
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=10"
|
||||
}
|
||||
|
||||
issue_5679_4: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
}
|
||||
input: {
|
||||
var a = "PASS";
|
||||
async function* f(b) {
|
||||
try {
|
||||
if (b)
|
||||
return undefined;
|
||||
else
|
||||
return undefined;
|
||||
} finally {
|
||||
a = "FAIL";
|
||||
}
|
||||
}
|
||||
f(null).next();
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
var a = "PASS";
|
||||
async function* f(b) {
|
||||
try {
|
||||
return b, void 0;
|
||||
} finally {
|
||||
a = "FAIL";
|
||||
}
|
||||
}
|
||||
f(null).next();
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=10"
|
||||
}
|
||||
|
||||
issue_5679_5: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
if_return: true,
|
||||
}
|
||||
input: {
|
||||
var a = "FAIL";
|
||||
async function* f(b) {
|
||||
try {
|
||||
if (b)
|
||||
return console;
|
||||
else
|
||||
return;
|
||||
} finally {
|
||||
a = "PASS";
|
||||
}
|
||||
}
|
||||
f().next();
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
var a = "FAIL";
|
||||
async function* f(b) {
|
||||
try {
|
||||
if (b)
|
||||
return console;
|
||||
return;
|
||||
} finally {
|
||||
a = "PASS";
|
||||
}
|
||||
}
|
||||
f().next();
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=10"
|
||||
}
|
||||
|
||||
issue_5679_6: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
if_return: true,
|
||||
}
|
||||
input: {
|
||||
var a = "PASS";
|
||||
async function* f(b) {
|
||||
try {
|
||||
if (b)
|
||||
return;
|
||||
else
|
||||
return console;
|
||||
} finally {
|
||||
a = "FAIL";
|
||||
}
|
||||
}
|
||||
f().next();
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
var a = "PASS";
|
||||
async function* f(b) {
|
||||
try {
|
||||
if (!b)
|
||||
return console;
|
||||
} finally {
|
||||
a = "FAIL";
|
||||
}
|
||||
}
|
||||
f().next();
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=10"
|
||||
}
|
||||
|
||||
issue_5684: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
if_return: true,
|
||||
}
|
||||
input: {
|
||||
(async function*() {
|
||||
switch (42) {
|
||||
default:
|
||||
if (console.log("PASS"))
|
||||
return;
|
||||
return null;
|
||||
case false:
|
||||
}
|
||||
})().next();
|
||||
}
|
||||
expect: {
|
||||
(async function*() {
|
||||
switch (42) {
|
||||
default:
|
||||
return console.log("PASS") ? void 0 : null;
|
||||
case false:
|
||||
}
|
||||
})().next();
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=10"
|
||||
}
|
||||
|
||||
@@ -400,7 +400,7 @@ describe("comments", function() {
|
||||
assert.strictEqual(ast.print_to_string({comments: "all"}), "/*!test1*/\n/*test2*/\n//!test3\n//test4\n//test5\n//!test6\n//test7\n//!test8");
|
||||
});
|
||||
|
||||
it("Should be able to filter commments with the 'some' option", function() {
|
||||
it("Should be able to filter comments with the 'some' option", function() {
|
||||
var ast = UglifyJS.parse("// foo\n/*@preserve*/\n// bar\n/*@license*/\n//@license with the wrong comment type\n/*@cc_on something*/");
|
||||
assert.strictEqual(ast.print_to_string({comments: "some"}), "/*@preserve*/\n/*@license*/\n/*@cc_on something*/");
|
||||
});
|
||||
|
||||
@@ -348,7 +348,7 @@ describe("Directives", function() {
|
||||
'"use strict";doSomething("foo");'
|
||||
],
|
||||
[
|
||||
// Nothing gets optimised in the compressor because "use asm" is the first statement
|
||||
// Nothing gets optimized in the compressor because "use asm" is the first statement
|
||||
'"use asm";"use\\x20strict";1+1;',
|
||||
'"use asm";"use\\x20strict";1+1;'
|
||||
],
|
||||
|
||||
@@ -12,17 +12,16 @@ describe("let", function() {
|
||||
s += '}';
|
||||
var result = UglifyJS.minify(s, {
|
||||
compress: false,
|
||||
}).code;
|
||||
|
||||
});
|
||||
if (result.error) throw result.error;
|
||||
// Verify that select keywords and reserved keywords not produced
|
||||
[
|
||||
"do",
|
||||
"let",
|
||||
"var",
|
||||
].forEach(function(name) {
|
||||
assert.strictEqual(result.indexOf("var " + name + "="), -1);
|
||||
assert.strictEqual(result.code.indexOf("var " + name + "="), -1);
|
||||
});
|
||||
|
||||
// Verify that the variable names that appeared immediately before
|
||||
// and after the erroneously generated variable name still exist
|
||||
// to show the test generated enough symbols.
|
||||
@@ -31,27 +30,29 @@ describe("let", function() {
|
||||
"eet", "fet",
|
||||
"rar", "oar",
|
||||
].forEach(function(name) {
|
||||
assert.notStrictEqual(result.indexOf("var " + name + "="), -1);
|
||||
assert.notStrictEqual(result.code.indexOf("var " + name + "="), -1);
|
||||
});
|
||||
});
|
||||
it("Should quote mangled properties that are reserved keywords", function() {
|
||||
var s = '"rrrrrnnnnniiiiiaaaaa";';
|
||||
for (var i = 0; i < 18000; i++) {
|
||||
s += "v.b" + i + ";";
|
||||
s += "v.b" + i + "=v;";
|
||||
}
|
||||
var result = UglifyJS.minify(s, {
|
||||
compress: false,
|
||||
ie: true,
|
||||
mangle: {
|
||||
properties: true,
|
||||
}
|
||||
}).code;
|
||||
properties: {
|
||||
domprops: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
if (result.error) throw result.error;
|
||||
[
|
||||
"in",
|
||||
"var",
|
||||
].forEach(function(name) {
|
||||
assert.notStrictEqual(result.indexOf(name), -1);
|
||||
assert.notStrictEqual(result.indexOf('v["' + name + '"]'), -1);
|
||||
assert.notStrictEqual(result.code.indexOf('v["' + name + '"]'), -1);
|
||||
});
|
||||
});
|
||||
it("Should parse `let` as name correctly", function() {
|
||||
|
||||
@@ -110,10 +110,12 @@ describe("minify", function() {
|
||||
var result = UglifyJS.minify(code, {
|
||||
compress: false,
|
||||
mangle: {
|
||||
properties: true,
|
||||
toplevel: true
|
||||
properties: {
|
||||
domprops: true,
|
||||
},
|
||||
toplevel: true,
|
||||
},
|
||||
nameCache: cache
|
||||
nameCache: cache,
|
||||
});
|
||||
if (result.error) throw result.error;
|
||||
original += code;
|
||||
@@ -188,32 +190,30 @@ describe("minify", function() {
|
||||
it("Shouldn't mangle quoted properties", function() {
|
||||
var js = 'a["foo"] = "bar"; a.color = "red"; x = {"bar": 10};';
|
||||
var result = UglifyJS.minify(js, {
|
||||
compress: {
|
||||
properties: false
|
||||
},
|
||||
compress: true,
|
||||
mangle: {
|
||||
properties: {
|
||||
keep_quoted: true
|
||||
}
|
||||
domprops: true,
|
||||
keep_quoted: true,
|
||||
},
|
||||
},
|
||||
output: {
|
||||
keep_quoted_props: true,
|
||||
quote_style: 3
|
||||
}
|
||||
quote_style: 3,
|
||||
},
|
||||
});
|
||||
assert.strictEqual(result.code,
|
||||
'a["foo"]="bar",a.a="red",x={"bar":10};');
|
||||
assert.strictEqual(result.code, 'a["foo"]="bar",a.a="red",x={"bar":10};');
|
||||
});
|
||||
it("Should not mangle quoted property within dead code", function() {
|
||||
var result = UglifyJS.minify('({ "keep": 1 }); g.keep = g.change;', {
|
||||
var result = UglifyJS.minify('({ "keep": 1 }); g.keep = g.change = 42;', {
|
||||
mangle: {
|
||||
properties: {
|
||||
keep_quoted: true
|
||||
}
|
||||
}
|
||||
keep_quoted: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
if (result.error) throw result.error;
|
||||
assert.strictEqual(result.code, "g.keep=g.g;");
|
||||
assert.strictEqual(result.code, "g.keep=g.g=42;");
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -245,7 +245,7 @@ describe("sourcemaps", function() {
|
||||
if (result.error) throw result.error;
|
||||
assert.strictEqual(result.code + "\n", read("test/input/issue-3294/output.js"));
|
||||
});
|
||||
it("Should work in presence of unrecognised annotations", function() {
|
||||
it("Should work in presence of unrecognized annotations", function() {
|
||||
var result = UglifyJS.minify(read("test/input/issue-3441/input.js"), {
|
||||
compress: false,
|
||||
mangle: false,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
var fs = require("fs");
|
||||
|
||||
new Function("exports", require("../tools/node").FILES.map(function(file) {
|
||||
new Function("domprops", "exports", require("../tools/node").FILES.map(function(file) {
|
||||
if (/exports\.js$/.test(file)) file = require.resolve("./exports");
|
||||
return fs.readFileSync(file, "utf8");
|
||||
}).join("\n\n"))(exports);
|
||||
}).join("\n\n"))(require("../tools/domprops.json"), exports);
|
||||
|
||||
@@ -25,7 +25,7 @@ exports.run_code = semver.satisfies(process.version, "0.8") ? function(code, top
|
||||
} while (prev !== stdout);
|
||||
return stdout;
|
||||
} : semver.satisfies(process.version, "<0.12") ? run_code_vm : function(code, toplevel, timeout) {
|
||||
if ([
|
||||
var stdout = ([
|
||||
/\b(async[ \t]+function|Promise|setImmediate|setInterval|setTimeout)\b/,
|
||||
/\basync([ \t]+|[ \t]*#)[^\s()[\]{}#:;,.&|!~=*%/+-]+(\s*\(|[ \t]*=>)/,
|
||||
/\basync[ \t]*\*[ \t]*[^\s()[\]{}#:;,.&|!~=*%/+-]+\s*\(/,
|
||||
@@ -33,11 +33,8 @@ exports.run_code = semver.satisfies(process.version, "0.8") ? function(code, top
|
||||
/\basync[ \t]*\([\s\S]*?\)[ \t]*=>/,
|
||||
].some(function(pattern) {
|
||||
return pattern.test(code);
|
||||
})) {
|
||||
return run_code_exec(code, toplevel, timeout);
|
||||
} else {
|
||||
return run_code_vm(code, toplevel, timeout);
|
||||
}
|
||||
}) ? run_code_exec : run_code_vm)(code, toplevel, timeout);
|
||||
return stdout.length > 1000 ? stdout.slice(0, 1000) + "…《" + stdout.length + "》" : stdout;
|
||||
};
|
||||
exports.same_stdout = semver.satisfies(process.version, "0.12") ? function(expected, actual) {
|
||||
if (typeof expected != typeof actual) return false;
|
||||
@@ -286,6 +283,7 @@ function run_code_exec(code, toplevel, timeout) {
|
||||
var result = spawnSync(process.argv[0], [ '--max-old-space-size=2048' ], {
|
||||
encoding: "utf8",
|
||||
input: code,
|
||||
maxBuffer: 1073741824,
|
||||
stdio: "pipe",
|
||||
timeout: timeout || 5000,
|
||||
});
|
||||
|
||||
@@ -1142,7 +1142,7 @@ function createStatement(recurmax, canThrow, canBreak, canContinue, cannotReturn
|
||||
}
|
||||
case STMT_FUNC_EXPR:
|
||||
// "In non-strict mode code, functions can only be declared at top level, inside a block, or ..."
|
||||
// (dont both with func decls in `if`; it's only a parser thing because you cant call them without a block)
|
||||
// (don't make func decls in `if`; it's only a parser thing because you can't call them without a block)
|
||||
return "{" + createFunction(recurmax, NO_DEFUN, canThrow, stmtDepth) + "}";
|
||||
case STMT_TRY:
|
||||
// catch var could cause some problems
|
||||
|
||||
@@ -15,13 +15,13 @@ exports.FILES = [
|
||||
require.resolve("./exports.js"),
|
||||
];
|
||||
|
||||
new Function("exports", function() {
|
||||
new Function("domprops", "exports", function() {
|
||||
var code = exports.FILES.map(function(file) {
|
||||
return fs.readFileSync(file, "utf8");
|
||||
});
|
||||
code.push("exports.describe_ast = " + describe_ast.toString());
|
||||
return code.join("\n\n");
|
||||
}())(exports);
|
||||
}())(require("./domprops.json"), exports);
|
||||
|
||||
function to_comment(value) {
|
||||
if (typeof value != "string") value = JSON.stringify(value, function(key, value) {
|
||||
|
||||
Reference in New Issue
Block a user