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
|
## 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
|
## 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
|
- `bare_returns` (default: `false`) — support top level `return` statements
|
||||||
|
|
||||||
- `html5_comments` (default: `true`) — process HTML comment as workaround for
|
- `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
|
- `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`.
|
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.
|
ES module, i.e. implicit `"use strict";` alongside with `toplevel` enabled.
|
||||||
|
|
||||||
- `negate_iife` (default: `true`) — negate "Immediately-Called Function Expressions"
|
- `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.
|
code generator would insert.
|
||||||
|
|
||||||
- `objects` (default: `true`) — compact duplicate keys in object literals.
|
- `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
|
- `unused` (default: `true`) — drop unreferenced functions and variables (simple
|
||||||
direct variable assignments do not count as references unless set to `"keep_assign"`)
|
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
|
whenever safe to do so
|
||||||
|
|
||||||
- `yields` (default: `true`) — apply optimizations to `yield` expressions
|
- `yields` (default: `true`) — apply optimizations to `yield` expressions
|
||||||
@@ -891,12 +891,15 @@ UglifyJS.minify(code, { mangle: { toplevel: true } }).code;
|
|||||||
|
|
||||||
### Mangle properties options
|
### Mangle properties options
|
||||||
|
|
||||||
- `builtins` (default: `false`) — Use `true` to allow the mangling of builtin
|
- `builtins` (default: `false`) — Use `true` to allow the mangling of built-in
|
||||||
DOM properties. Not recommended to override this setting.
|
properties of JavaScript API. Not recommended to override this setting.
|
||||||
|
|
||||||
- `debug` (default: `false`) — Mangle names with the original name still present.
|
- `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.
|
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
|
- `keep_fargs` (default: `false`) — Use `true` to prevent mangling of function
|
||||||
arguments.
|
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) {
|
[ "compress", "mangle" ].forEach(function(name) {
|
||||||
if (!(name in options)) options[name] = false;
|
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 (/^ast|spidermonkey$/.test(output)) {
|
||||||
if (typeof options.output != "object") options.output = {};
|
if (typeof options.output != "object") options.output = {};
|
||||||
options.output.ast = true;
|
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", {
|
var AST_BlockScope = DEFNODE("BlockScope", "_var_names enclosed functions make_def parent_scope variables", {
|
||||||
$documentation: "Base class for all statements introducing a lexical scope",
|
$documentation: "Base class for all statements introducing a lexical scope",
|
||||||
$propdoc: {
|
$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",
|
functions: "[Dictionary/S] like `variables`, but only lists function declarations",
|
||||||
parent_scope: "[AST_Scope?/S] link to the parent scope",
|
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",
|
variables: "[Dictionary/S] a map of name ---> SymbolDef for all variables/functions defined in this scope",
|
||||||
|
|||||||
167
lib/compress.js
167
lib/compress.js
@@ -368,7 +368,6 @@ Compressor.prototype.compress = function(node) {
|
|||||||
args: [],
|
args: [],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return self;
|
|
||||||
});
|
});
|
||||||
AST_Node.DEFMETHOD("wrap_expression", function() {
|
AST_Node.DEFMETHOD("wrap_expression", function() {
|
||||||
var self = this;
|
var self = this;
|
||||||
@@ -497,6 +496,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
function has_escaped(d, scope, node, parent) {
|
function has_escaped(d, scope, node, parent) {
|
||||||
if (parent instanceof AST_Assign) return parent.operator == "=" && parent.right === node;
|
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_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_Exit) return parent.value === node && scope.resolve() !== d.scope.resolve();
|
||||||
if (parent instanceof AST_VarDef) return parent.value === node;
|
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);
|
if (node.extends) node.extends.walk(tw);
|
||||||
var props = node.properties.filter(function(prop) {
|
var props = node.properties.filter(function(prop) {
|
||||||
reset_flags(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;
|
return prop.value;
|
||||||
});
|
});
|
||||||
if (node.name) {
|
if (node.name) {
|
||||||
@@ -1184,6 +1188,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
props.forEach(function(prop) {
|
props.forEach(function(prop) {
|
||||||
|
tw.push(prop);
|
||||||
if (!prop.static || is_static_field_or_init(prop) && 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);
|
||||||
@@ -1191,6 +1196,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
} else {
|
} else {
|
||||||
prop.value.walk(tw);
|
prop.value.walk(tw);
|
||||||
}
|
}
|
||||||
|
tw.pop();
|
||||||
});
|
});
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
@@ -1741,6 +1747,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
|
|
||||||
var identifier_atom = makePredicate("Infinity NaN undefined");
|
var identifier_atom = makePredicate("Infinity NaN undefined");
|
||||||
function is_lhs_read_only(lhs, compressor) {
|
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_ObjectIdentity) return true;
|
||||||
if (lhs instanceof AST_PropAccess) {
|
if (lhs instanceof AST_PropAccess) {
|
||||||
if (lhs.property === "__proto__") return true;
|
if (lhs.property === "__proto__") return true;
|
||||||
@@ -3529,6 +3536,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
var declare_only, jump, merge_jump;
|
var declare_only, jump, merge_jump;
|
||||||
var in_iife = in_lambda && parent && parent.TYPE == "Call" && parent.expression === self;
|
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 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);
|
var multiple_if_returns = has_multiple_if_returns(statements);
|
||||||
for (var i = statements.length; --i >= 0;) {
|
for (var i = statements.length; --i >= 0;) {
|
||||||
var stat = statements[i];
|
var stat = statements[i];
|
||||||
@@ -3536,8 +3544,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
var next = statements[j];
|
var next = statements[j];
|
||||||
|
|
||||||
if (in_lambda && declare_only && !next && stat instanceof AST_Return
|
if (in_lambda && declare_only && !next && stat instanceof AST_Return
|
||||||
&& !(self instanceof AST_SwitchBranch)
|
&& drop_return_void && !(self instanceof AST_SwitchBranch)) {
|
||||||
&& !(in_try && in_try.bfinally && in_async_generator(in_lambda))) {
|
|
||||||
var body = stat.value;
|
var body = stat.value;
|
||||||
if (!body) {
|
if (!body) {
|
||||||
changed = true;
|
changed = true;
|
||||||
@@ -3632,7 +3639,8 @@ Compressor.prototype.compress = function(node) {
|
|||||||
var value = stat.body.value;
|
var value = stat.body.value;
|
||||||
var in_bool = stat.body.in_bool || next instanceof AST_Return && next.in_bool;
|
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 (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;
|
changed = true;
|
||||||
stat = stat.clone();
|
stat = stat.clone();
|
||||||
stat.alternative = make_node(AST_BlockStatement, next, {
|
stat.alternative = make_node(AST_BlockStatement, next, {
|
||||||
@@ -3737,14 +3745,17 @@ Compressor.prototype.compress = function(node) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (!(ab instanceof AST_LoopControl)) return false;
|
if (!(ab instanceof AST_LoopControl)) return false;
|
||||||
if (jump && self instanceof AST_SwitchBranch) {
|
if (self instanceof AST_SwitchBranch) {
|
||||||
if (jump instanceof AST_Exit) {
|
if (jump instanceof AST_Exit) {
|
||||||
if (!in_lambda) return false;
|
if (!in_lambda) return false;
|
||||||
if (jump.value) 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;
|
return false;
|
||||||
}
|
}
|
||||||
merge_jump = true;
|
|
||||||
}
|
}
|
||||||
var lct = compressor.loopcontrol_target(ab);
|
var lct = compressor.loopcontrol_target(ab);
|
||||||
if (ab instanceof AST_Continue) return match_target(loop_body(lct));
|
if (ab instanceof AST_Continue) return match_target(loop_body(lct));
|
||||||
@@ -3781,7 +3792,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
end = statements.lastIndexOf(stop);
|
end = statements.lastIndexOf(stop);
|
||||||
} else {
|
} else {
|
||||||
stop = statements[end];
|
stop = statements[end];
|
||||||
if (stop !== jump) jump = null;
|
if (stop !== jump) jump = false;
|
||||||
}
|
}
|
||||||
var tail = statements.splice(start, end - start).filter(function(stat) {
|
var tail = statements.splice(start, end - start).filter(function(stat) {
|
||||||
if (stat instanceof AST_LambdaDefinition) {
|
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");
|
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
|
// as well as the common constant expressions !0 and -1
|
||||||
(function(def) {
|
(function(def) {
|
||||||
def(AST_Node, return_false);
|
def(AST_Node, return_false);
|
||||||
@@ -9335,7 +9346,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
return !same_scope(def) || may_overlap(compressor, def);
|
return !same_scope(def) || may_overlap(compressor, def);
|
||||||
}
|
}
|
||||||
}, true)) {
|
}, true)) {
|
||||||
self.init = to_var(self.init);
|
self.init = to_var(self.init, self.resolve());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
@@ -9677,17 +9688,26 @@ Compressor.prototype.compress = function(node) {
|
|||||||
alternative: null,
|
alternative: null,
|
||||||
});
|
});
|
||||||
if (self.alternative instanceof AST_Exit && self.body.TYPE == self.alternative.TYPE) {
|
if (self.alternative instanceof AST_Exit && self.body.TYPE == self.alternative.TYPE) {
|
||||||
|
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, {
|
var exit = make_node(self.body.CTOR, self, {
|
||||||
value: make_node(AST_Conditional, self, {
|
value: make_node(AST_Conditional, self, {
|
||||||
condition: self.condition,
|
condition: self.condition,
|
||||||
consequent: self.body.value || make_node(AST_Undefined, self.body).transform(compressor),
|
consequent: cons_value || make_node(AST_Undefined, self.body).transform(compressor),
|
||||||
alternative: self.alternative.value
|
alternative: alt_value || make_node(AST_Undefined, self.alternative).transform(compressor),
|
||||||
|| make_node(AST_Undefined, self.alternative).transform(compressor),
|
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
if (exit instanceof AST_Return) exit.in_bool = self.body.in_bool || self.alternative.in_bool;
|
if (exit instanceof AST_Return) exit.in_bool = self.body.in_bool || self.alternative.in_bool;
|
||||||
return exit;
|
return exit;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (self.body instanceof AST_If && !self.body.alternative && !self.alternative) {
|
if (self.body instanceof AST_If && !self.body.alternative && !self.alternative) {
|
||||||
self = make_node(AST_If, self, {
|
self = make_node(AST_If, self, {
|
||||||
condition: make_node(AST_Binary, self.condition, {
|
condition: make_node(AST_Binary, self.condition, {
|
||||||
@@ -9752,6 +9772,22 @@ Compressor.prototype.compress = function(node) {
|
|||||||
return node instanceof AST_BlockStatement ? node.body : [ 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) {
|
function last_index(stats) {
|
||||||
for (var index = stats.length; --index >= 0;) {
|
for (var index = stats.length; --index >= 0;) {
|
||||||
if (!is_declaration(stats[index], true)) break;
|
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, {
|
return make_node(AST_Var, stat, {
|
||||||
definitions: stat.definitions.map(function(defn) {
|
definitions: stat.definitions.map(function(defn) {
|
||||||
return make_node(AST_VarDef, defn, {
|
return make_node(AST_VarDef, defn, {
|
||||||
name: defn.name.convert_symbol(AST_SymbolVar, function(name, node) {
|
name: defn.name.convert_symbol(AST_SymbolVar, function(name, node) {
|
||||||
var def = name.definition();
|
var def = name.definition();
|
||||||
def.orig[def.orig.indexOf(node)] = name;
|
def.orig[def.orig.indexOf(node)] = name;
|
||||||
var scope = def.scope.resolve();
|
|
||||||
if (def.scope === scope) return;
|
if (def.scope === scope) return;
|
||||||
def.scope = scope;
|
def.scope = scope;
|
||||||
scope.variables.set(def.name, def);
|
scope.variables.set(def.name, def);
|
||||||
@@ -10157,7 +10192,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
return !defn.name.match_symbol(function(node) {
|
return !defn.name.match_symbol(function(node) {
|
||||||
if (node instanceof AST_SymbolDeclaration) return !can_varify(compressor, node);
|
if (node instanceof AST_SymbolDeclaration) return !can_varify(compressor, node);
|
||||||
}, true);
|
}, true);
|
||||||
}) ? to_var(self) : self;
|
}) ? to_var(self, compressor.find_parent(AST_Scope)) : self;
|
||||||
}
|
}
|
||||||
|
|
||||||
OPT(AST_Const, varify);
|
OPT(AST_Const, varify);
|
||||||
@@ -11553,6 +11588,15 @@ Compressor.prototype.compress = function(node) {
|
|||||||
if (node instanceof AST_Unary) return true;
|
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) {
|
function repeatable(compressor, node) {
|
||||||
if (node instanceof AST_Dot) return repeatable(compressor, node.expression);
|
if (node instanceof AST_Dot) return repeatable(compressor, node.expression);
|
||||||
if (node instanceof AST_Sub) {
|
if (node instanceof AST_Sub) {
|
||||||
@@ -11595,31 +11639,32 @@ Compressor.prototype.compress = function(node) {
|
|||||||
if (seq !== self) return seq.optimize(compressor);
|
if (seq !== self) return seq.optimize(compressor);
|
||||||
}
|
}
|
||||||
if (compressor.option("assignments") && lazy_op[self.operator]) {
|
if (compressor.option("assignments") && lazy_op[self.operator]) {
|
||||||
|
var lhs = extract_lhs(self.left, compressor);
|
||||||
var right = self.right;
|
var right = self.right;
|
||||||
// a || (a = x) ---> a = a || x
|
// a || (a = x) ---> a = a || x
|
||||||
// a && (a = x) ---> a = a && x
|
// (a = x) && (a = y) ---> a = (a = x) && y
|
||||||
if (self.left instanceof AST_SymbolRef
|
if (lhs instanceof AST_SymbolRef
|
||||||
&& right instanceof AST_Assign
|
&& right instanceof AST_Assign
|
||||||
&& right.operator == "="
|
&& right.operator == "="
|
||||||
&& self.left.equals(right.left)) {
|
&& lhs.equals(right.left)) {
|
||||||
var left = right.left.clone();
|
lhs = lhs.clone();
|
||||||
var assign = make_node(AST_Assign, self, {
|
var assign = make_node(AST_Assign, self, {
|
||||||
operator: "=",
|
operator: "=",
|
||||||
left: left,
|
left: lhs,
|
||||||
right: make_node(AST_Binary, self, {
|
right: make_node(AST_Binary, self, {
|
||||||
operator: self.operator,
|
operator: self.operator,
|
||||||
left: self.left,
|
left: self.left,
|
||||||
right: right.right,
|
right: right.right,
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
if (left.fixed) {
|
if (lhs.fixed) {
|
||||||
left.fixed = function() {
|
lhs.fixed = function() {
|
||||||
return assign.right;
|
return assign.right;
|
||||||
};
|
};
|
||||||
left.fixed.assigns = [ assign ];
|
lhs.fixed.assigns = [ assign ];
|
||||||
}
|
}
|
||||||
var def = left.definition();
|
var def = lhs.definition();
|
||||||
def.references.push(left);
|
def.references.push(lhs);
|
||||||
def.replaced++;
|
def.replaced++;
|
||||||
return assign.optimize(compressor);
|
return assign.optimize(compressor);
|
||||||
}
|
}
|
||||||
@@ -11674,31 +11719,32 @@ Compressor.prototype.compress = function(node) {
|
|||||||
case "||":
|
case "||":
|
||||||
// void 0 !== x && null !== x ---> null != x
|
// void 0 !== x && null !== x ---> null != x
|
||||||
// void 0 === x || null === x ---> null == x
|
// void 0 === x || null === x ---> null == x
|
||||||
var lhs = self.left;
|
var left = self.left;
|
||||||
if (lhs.operator == self.operator) lhs = lhs.right;
|
if (!(left instanceof AST_Binary)) break;
|
||||||
var expr = lhs.right;
|
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 instanceof AST_Assign && expr.operator == "=") expr = expr.left;
|
||||||
if (lhs instanceof AST_Binary
|
if (expr.has_side_effects(compressor)) break;
|
||||||
&& lhs.operator == (self.operator == "&&" ? "!==" : "===")
|
if (!expr.equals(self.right.right)) break;
|
||||||
&& self.right instanceof AST_Binary
|
left.operator = left.operator.slice(0, -1);
|
||||||
&& lhs.operator == self.right.operator
|
left.left = make_node(AST_Null, self);
|
||||||
&& (is_undefined(lhs.left, compressor) && self.right.left instanceof AST_Null
|
return left;
|
||||||
|| 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;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
var in_bool = false;
|
var in_bool = false;
|
||||||
var parent = compressor.parent();
|
var parent = compressor.parent();
|
||||||
if (compressor.option("booleans")) {
|
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)) {
|
if (lazy_op[self.operator] && !lhs.has_side_effects(compressor)) {
|
||||||
|
// a || a ---> a
|
||||||
|
// (a = x) && a --> a = x
|
||||||
if (lhs.equals(self.right)) {
|
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);
|
mark_duplicate_condition(compressor, lhs);
|
||||||
}
|
}
|
||||||
@@ -11746,13 +11792,22 @@ Compressor.prototype.compress = function(node) {
|
|||||||
case ">=": reverse("<="); break;
|
case ">=": reverse("<="); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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
|
||||||
// x || (y || z) ---> x || y || z
|
// x || (y || z) ---> x || y || z
|
||||||
if (compressor.option("conditionals")
|
if (self.right instanceof AST_Binary && self.operator == self.right.operator) swap_chain(self, compressor);
|
||||||
&& lazy_op[self.operator]
|
|
||||||
&& self.right instanceof AST_Binary
|
|
||||||
&& self.operator == self.right.operator) {
|
|
||||||
swap_chain(self, compressor);
|
|
||||||
}
|
}
|
||||||
if (compressor.option("strings") && self.operator == "+") {
|
if (compressor.option("strings") && self.operator == "+") {
|
||||||
// "foo" + 42 + "" ---> "foo" + 42
|
// "foo" + 42 + "" ---> "foo" + 42
|
||||||
@@ -11826,7 +11881,7 @@ Compressor.prototype.compress = function(node) {
|
|||||||
if (nullish ? ll == null : !ll) {
|
if (nullish ? ll == null : !ll) {
|
||||||
AST_Node.warn("Condition left of {operator} always {value} [{start}]", {
|
AST_Node.warn("Condition left of {operator} always {value} [{start}]", {
|
||||||
operator: self.operator,
|
operator: self.operator,
|
||||||
value: nullish ? "nulish" : "false",
|
value: nullish ? "nullish" : "false",
|
||||||
start: self.start,
|
start: self.start,
|
||||||
});
|
});
|
||||||
return make_sequence(self, [ self.left, self.right ]).optimize(compressor);
|
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));
|
var single_use = def.single_use && !(parent instanceof AST_Call && parent.is_expr_pure(compressor));
|
||||||
if (single_use) {
|
if (single_use) {
|
||||||
if (is_lambda(fixed)) {
|
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)) {
|
&& (!compressor.option("reduce_funcs") || def.escaped.depth == 1 || fixed.inlined)) {
|
||||||
single_use = false;
|
single_use = false;
|
||||||
} else if (def.redefined()) {
|
} else if (def.redefined()) {
|
||||||
@@ -12845,15 +12900,16 @@ Compressor.prototype.compress = function(node) {
|
|||||||
}
|
}
|
||||||
var consequent = self.consequent;
|
var consequent = self.consequent;
|
||||||
var alternative = self.alternative;
|
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
|
// 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: "||",
|
operator: "||",
|
||||||
left: condition,
|
left: condition,
|
||||||
right: alternative,
|
right: alternative,
|
||||||
}).optimize(compressor);
|
}).optimize(compressor);
|
||||||
// x ? y : x ---> x && y
|
// 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: "&&",
|
operator: "&&",
|
||||||
left: condition,
|
left: condition,
|
||||||
right: consequent,
|
right: consequent,
|
||||||
@@ -13834,7 +13890,10 @@ Compressor.prototype.compress = function(node) {
|
|||||||
var abort = false;
|
var abort = false;
|
||||||
stat.walk(new TreeWalker(function(node) {
|
stat.walk(new TreeWalker(function(node) {
|
||||||
if (abort) return true;
|
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;
|
if (node instanceof AST_Scope) return true;
|
||||||
}));
|
}));
|
||||||
return !abort;
|
return !abort;
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ function OutputStream(options) {
|
|||||||
wrap_iife : false,
|
wrap_iife : false,
|
||||||
}, true);
|
}, 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
|
var comment_filter = return_false; // Default case, throw all comments away
|
||||||
if (options.comments) {
|
if (options.comments) {
|
||||||
var comments = options.comments;
|
var comments = options.comments;
|
||||||
@@ -997,7 +997,7 @@ function OutputStream(options) {
|
|||||||
if (self.init instanceof AST_Definitions) {
|
if (self.init instanceof AST_Definitions) {
|
||||||
self.init.print(output);
|
self.init.print(output);
|
||||||
} else {
|
} else {
|
||||||
parenthesize_for_noin(self.init, output, true);
|
parenthesize_for_no_in(self.init, output, true);
|
||||||
}
|
}
|
||||||
output.print(";");
|
output.print(";");
|
||||||
output.space();
|
output.space();
|
||||||
@@ -1413,7 +1413,7 @@ function OutputStream(options) {
|
|||||||
print_braced(this, output);
|
print_braced(this, output);
|
||||||
});
|
});
|
||||||
|
|
||||||
function print_definitinos(type) {
|
function print_definitions(type) {
|
||||||
return function(output) {
|
return function(output) {
|
||||||
var self = this;
|
var self = this;
|
||||||
output.print(type);
|
output.print(type);
|
||||||
@@ -1426,15 +1426,15 @@ function OutputStream(options) {
|
|||||||
if (!(p instanceof AST_IterationStatement && p.init === self)) output.semicolon();
|
if (!(p instanceof AST_IterationStatement && p.init === self)) output.semicolon();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
DEFPRINT(AST_Const, print_definitinos("const"));
|
DEFPRINT(AST_Const, print_definitions("const"));
|
||||||
DEFPRINT(AST_Let, print_definitinos("let"));
|
DEFPRINT(AST_Let, print_definitions("let"));
|
||||||
DEFPRINT(AST_Var, print_definitinos("var"));
|
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;
|
var parens = false;
|
||||||
// need to take some precautions here:
|
// need to take some precautions here:
|
||||||
// https://github.com/mishoo/UglifyJS/issues/60
|
// 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 (parens) return true;
|
||||||
if (node instanceof AST_Binary && node.operator == "in") return parens = true;
|
if (node instanceof AST_Binary && node.operator == "in") return parens = true;
|
||||||
if (node instanceof AST_Scope && !(is_arrow(node) && node.value)) return true;
|
if (node instanceof AST_Scope && !(is_arrow(node) && node.value)) return true;
|
||||||
@@ -1450,8 +1450,8 @@ function OutputStream(options) {
|
|||||||
output.print("=");
|
output.print("=");
|
||||||
output.space();
|
output.space();
|
||||||
var p = output.parent(1);
|
var p = output.parent(1);
|
||||||
var noin = p instanceof AST_For || p instanceof AST_ForEnumeration;
|
var no_in = p instanceof AST_For || p instanceof AST_ForEnumeration;
|
||||||
parenthesize_for_noin(self.value, output, noin);
|
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(";");
|
else if (!optional && !can_insert_semicolon()) expect(";");
|
||||||
}
|
}
|
||||||
|
|
||||||
function parenthesised() {
|
function parenthesized() {
|
||||||
expect("(");
|
expect("(");
|
||||||
var exp = expression();
|
var exp = expression();
|
||||||
expect(")");
|
expect(")");
|
||||||
@@ -920,18 +920,18 @@ function parse($TEXT, options) {
|
|||||||
next();
|
next();
|
||||||
var body = in_loop(statement);
|
var body = in_loop(statement);
|
||||||
expect_token("keyword", "while");
|
expect_token("keyword", "while");
|
||||||
var condition = parenthesised();
|
var condition = parenthesized();
|
||||||
semicolon(true);
|
semicolon(true);
|
||||||
return new AST_Do({
|
return new AST_Do({
|
||||||
body : body,
|
body : body,
|
||||||
condition : condition
|
condition : condition,
|
||||||
});
|
});
|
||||||
|
|
||||||
case "while":
|
case "while":
|
||||||
next();
|
next();
|
||||||
return new AST_While({
|
return new AST_While({
|
||||||
condition : parenthesised(),
|
condition : parenthesized(),
|
||||||
body : in_loop(statement)
|
body : in_loop(statement),
|
||||||
});
|
});
|
||||||
|
|
||||||
case "for":
|
case "for":
|
||||||
@@ -959,15 +959,13 @@ function parse($TEXT, options) {
|
|||||||
value = expression();
|
value = expression();
|
||||||
semicolon();
|
semicolon();
|
||||||
}
|
}
|
||||||
return new AST_Return({
|
return new AST_Return({ value: value });
|
||||||
value: value
|
|
||||||
});
|
|
||||||
|
|
||||||
case "switch":
|
case "switch":
|
||||||
next();
|
next();
|
||||||
return new AST_Switch({
|
return new AST_Switch({
|
||||||
expression : parenthesised(),
|
expression : parenthesized(),
|
||||||
body : in_loop(switch_body_)
|
body : in_loop(switch_body_),
|
||||||
});
|
});
|
||||||
|
|
||||||
case "throw":
|
case "throw":
|
||||||
@@ -976,9 +974,7 @@ function parse($TEXT, options) {
|
|||||||
croak("Illegal newline after 'throw'");
|
croak("Illegal newline after 'throw'");
|
||||||
var value = expression();
|
var value = expression();
|
||||||
semicolon();
|
semicolon();
|
||||||
return new AST_Throw({
|
return new AST_Throw({ value: value });
|
||||||
value: value
|
|
||||||
});
|
|
||||||
|
|
||||||
case "try":
|
case "try":
|
||||||
next();
|
next();
|
||||||
@@ -996,8 +992,8 @@ function parse($TEXT, options) {
|
|||||||
}
|
}
|
||||||
next();
|
next();
|
||||||
return new AST_With({
|
return new AST_With({
|
||||||
expression : parenthesised(),
|
expression : parenthesized(),
|
||||||
body : statement()
|
body : statement(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1421,15 +1417,15 @@ function parse($TEXT, options) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function if_() {
|
function if_() {
|
||||||
var cond = parenthesised(), body = statement(), belse = null;
|
var cond = parenthesized(), body = statement(), alt = null;
|
||||||
if (is("keyword", "else")) {
|
if (is("keyword", "else")) {
|
||||||
next();
|
next();
|
||||||
belse = statement();
|
alt = statement();
|
||||||
}
|
}
|
||||||
return new AST_If({
|
return new AST_If({
|
||||||
condition : cond,
|
condition : cond,
|
||||||
body : body,
|
body : body,
|
||||||
alternative : belse
|
alternative : alt,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2171,9 +2167,9 @@ function parse($TEXT, options) {
|
|||||||
token_error(sym.start, "Unexpected " + sym.name + " in strict mode");
|
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 (!is("name")) {
|
||||||
if (!noerror) croak("Name expected");
|
if (!no_error) croak("Name expected");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
var sym = _make_symbol(type, S.token);
|
var sym = _make_symbol(type, S.token);
|
||||||
@@ -2409,20 +2405,20 @@ function parse($TEXT, options) {
|
|||||||
return new ctor({ operator: op, expression: expr });
|
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;
|
var op = is("operator") ? S.token.value : null;
|
||||||
if (op == "in" && no_in) op = null;
|
if (op == "in" && no_in) op = null;
|
||||||
var prec = op != null ? PRECEDENCE[op] : null;
|
var precision = op != null ? PRECEDENCE[op] : null;
|
||||||
if (prec != null && prec > min_prec) {
|
if (precision != null && precision > min_precision) {
|
||||||
next();
|
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({
|
return expr_op(new AST_Binary({
|
||||||
start : left.start,
|
start : left.start,
|
||||||
left : left,
|
left : left,
|
||||||
operator : op,
|
operator : op,
|
||||||
right : right,
|
right : right,
|
||||||
end : right.end
|
end : right.end,
|
||||||
}), min_prec, no_in);
|
}), min_precision, no_in);
|
||||||
}
|
}
|
||||||
return left;
|
return left;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -124,12 +124,16 @@ function get_builtins() {
|
|||||||
|
|
||||||
function reserve_quoted_keys(ast, reserved) {
|
function reserve_quoted_keys(ast, reserved) {
|
||||||
ast.walk(new TreeWalker(function(node) {
|
ast.walk(new TreeWalker(function(node) {
|
||||||
if (node instanceof AST_ClassProperty) {
|
if (node instanceof AST_ClassProperty
|
||||||
if (node.start && node.start.quote) add(node.key);
|
|| 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) {
|
} else if (node instanceof AST_Dot) {
|
||||||
if (node.quoted) add(node.property);
|
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) {
|
} else if (node instanceof AST_Sub) {
|
||||||
addStrings(node.property, add);
|
addStrings(node.property, add);
|
||||||
}
|
}
|
||||||
@@ -156,12 +160,16 @@ function mangle_properties(ast, options) {
|
|||||||
builtins: false,
|
builtins: false,
|
||||||
cache: null,
|
cache: null,
|
||||||
debug: false,
|
debug: false,
|
||||||
|
domprops: false,
|
||||||
keep_quoted: false,
|
keep_quoted: false,
|
||||||
regex: null,
|
regex: null,
|
||||||
reserved: null,
|
reserved: null,
|
||||||
}, true);
|
}, true);
|
||||||
|
|
||||||
var reserved = options.builtins ? new Dictionary() : get_builtins();
|
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) {
|
if (Array.isArray(options.reserved)) options.reserved.forEach(function(name) {
|
||||||
reserved.set(name, true);
|
reserved.set(name, true);
|
||||||
});
|
});
|
||||||
@@ -180,7 +188,7 @@ function mangle_properties(ast, options) {
|
|||||||
var regex = options.regex;
|
var regex = options.regex;
|
||||||
|
|
||||||
// note debug is either false (disabled), or a string of the debug suffix to use (enabled).
|
// 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.
|
// the same as passing an empty string.
|
||||||
var debug = options.debug !== false;
|
var debug = options.debug !== false;
|
||||||
var debug_suffix;
|
var debug_suffix;
|
||||||
@@ -191,9 +199,7 @@ function mangle_properties(ast, options) {
|
|||||||
|
|
||||||
// step 1: find candidates to mangle
|
// step 1: find candidates to mangle
|
||||||
ast.walk(new TreeWalker(function(node) {
|
ast.walk(new TreeWalker(function(node) {
|
||||||
if (node instanceof AST_Binary) {
|
if (node.TYPE == "Call") {
|
||||||
if (node.operator == "in") addStrings(node.left, add);
|
|
||||||
} else if (node.TYPE == "Call") {
|
|
||||||
var exp = node.expression;
|
var exp = node.expression;
|
||||||
if (exp instanceof AST_Dot) switch (exp.property) {
|
if (exp instanceof AST_Dot) switch (exp.property) {
|
||||||
case "defineProperty":
|
case "defineProperty":
|
||||||
@@ -210,14 +216,18 @@ function mangle_properties(ast, options) {
|
|||||||
addStrings(node.args[0], add);
|
addStrings(node.args[0], add);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if (node instanceof AST_ClassProperty) {
|
} else if (node instanceof AST_ClassProperty
|
||||||
if (typeof node.key == "string") add(node.key);
|
|| 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) {
|
} else if (node instanceof AST_Dot) {
|
||||||
add(node.property);
|
if (is_lhs(node, this.parent())) add(node.property);
|
||||||
} else if (node instanceof AST_ObjectProperty) {
|
|
||||||
if (typeof node.key == "string") add(node.key);
|
|
||||||
} else if (node instanceof AST_Sub) {
|
} 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]);
|
mangleStrings(node.args[0]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if (node instanceof AST_ClassProperty) {
|
} else if (node instanceof AST_ClassProperty
|
||||||
if (typeof node.key == "string") node.key = mangle(node.key);
|
|| 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) {
|
} else if (node instanceof AST_Dot) {
|
||||||
node.property = mangle(node.property);
|
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) {
|
} else if (node instanceof AST_Sub) {
|
||||||
if (!options.keep_quoted) mangleStrings(node.property);
|
if (!options.keep_quoted) mangleStrings(node.property);
|
||||||
}
|
}
|
||||||
@@ -303,7 +317,7 @@ function mangle_properties(ast, options) {
|
|||||||
|
|
||||||
function mangleStrings(node) {
|
function mangleStrings(node) {
|
||||||
if (node instanceof AST_Sequence) {
|
if (node instanceof AST_Sequence) {
|
||||||
mangleStrings(node.expressions.tail_node());
|
mangleStrings(node.tail_node());
|
||||||
} else if (node instanceof AST_String) {
|
} else if (node instanceof AST_String) {
|
||||||
node.value = mangle(node.value);
|
node.value = mangle(node.value);
|
||||||
} else if (node instanceof AST_Conditional) {
|
} else if (node instanceof AST_Conditional) {
|
||||||
|
|||||||
@@ -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.17.2",
|
"version": "3.17.3",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.8.0"
|
"node": ">=0.8.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -126,6 +126,17 @@ function parse_test(file) {
|
|||||||
croak(node);
|
croak(node);
|
||||||
}
|
}
|
||||||
var name = node.left.name;
|
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);
|
test[name] = evaluate(node.right);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -271,7 +282,9 @@ function test_case(test) {
|
|||||||
expect = test.expect_exact;
|
expect = test.expect_exact;
|
||||||
}
|
}
|
||||||
var input = to_toplevel(test.input, test.mangle, test.expression);
|
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, {
|
var input_formatted = make_code(test.input, {
|
||||||
annotations: true,
|
annotations: true,
|
||||||
beautify: true,
|
beautify: true,
|
||||||
|
|||||||
@@ -290,6 +290,45 @@ increment_decrement_2: {
|
|||||||
expect_stdout: "42"
|
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: {
|
issue_3375_1: {
|
||||||
options = {
|
options = {
|
||||||
assignments: true,
|
assignments: true,
|
||||||
|
|||||||
@@ -3540,3 +3540,61 @@ issue_5634_3_side_effects: {
|
|||||||
]
|
]
|
||||||
node_version: ">=8"
|
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"
|
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: {
|
de_morgan_2a: {
|
||||||
options = {
|
options = {
|
||||||
booleans: true,
|
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: {
|
de_morgan_3a: {
|
||||||
options = {
|
options = {
|
||||||
booleans: true,
|
booleans: true,
|
||||||
@@ -786,3 +830,37 @@ issue_5469: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "undefined"
|
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,
|
inline: true,
|
||||||
passes: 2,
|
passes: 2,
|
||||||
pure_getters: "strict",
|
pure_getters: "strict",
|
||||||
|
reduce_funcs: true,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
sequences: true,
|
sequences: true,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
@@ -921,6 +922,7 @@ single_use_3: {
|
|||||||
|
|
||||||
single_use_4: {
|
single_use_4: {
|
||||||
options = {
|
options = {
|
||||||
|
reduce_funcs: true,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
toplevel: true,
|
toplevel: true,
|
||||||
unused: true,
|
unused: true,
|
||||||
@@ -1503,6 +1505,218 @@ keep_instanceof_3: {
|
|||||||
node_version: ">=4"
|
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: {
|
issue_805_1: {
|
||||||
options = {
|
options = {
|
||||||
inline: true,
|
inline: true,
|
||||||
@@ -2164,6 +2378,7 @@ issue_4829_2: {
|
|||||||
mangle_properties: {
|
mangle_properties: {
|
||||||
mangle = {
|
mangle = {
|
||||||
properties: {
|
properties: {
|
||||||
|
domprops: true,
|
||||||
keep_quoted: true,
|
keep_quoted: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -2202,11 +2417,11 @@ mangle_properties: {
|
|||||||
expect_stdout: "PASS 42"
|
expect_stdout: "PASS 42"
|
||||||
expect_warnings: [
|
expect_warnings: [
|
||||||
"INFO: Preserving reserved property q",
|
"INFO: Preserving reserved property q",
|
||||||
"INFO: Preserving reserved property log",
|
|
||||||
"INFO: Mapping property #P to #t",
|
"INFO: Mapping property #P to #t",
|
||||||
"INFO: Mapping property Q to s",
|
"INFO: Mapping property Q to s",
|
||||||
"INFO: Mapping property #p to #i",
|
"INFO: Mapping property #p to #i",
|
||||||
"INFO: Mapping property r to e",
|
"INFO: Mapping property r to e",
|
||||||
|
"INFO: Preserving reserved property log",
|
||||||
]
|
]
|
||||||
node_version: ">=14.6"
|
node_version: ">=14.6"
|
||||||
}
|
}
|
||||||
@@ -2312,6 +2527,7 @@ issue_4962_1: {
|
|||||||
options = {
|
options = {
|
||||||
ie: true,
|
ie: true,
|
||||||
inline: true,
|
inline: true,
|
||||||
|
reduce_funcs: true,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
unused: true,
|
unused: true,
|
||||||
}
|
}
|
||||||
@@ -2343,6 +2559,7 @@ issue_4962_1_strict: {
|
|||||||
options = {
|
options = {
|
||||||
ie: true,
|
ie: true,
|
||||||
inline: true,
|
inline: true,
|
||||||
|
reduce_funcs: true,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
unused: true,
|
unused: true,
|
||||||
}
|
}
|
||||||
@@ -2370,6 +2587,7 @@ issue_4962_1_strict_direct: {
|
|||||||
options = {
|
options = {
|
||||||
ie: true,
|
ie: true,
|
||||||
inline: true,
|
inline: true,
|
||||||
|
reduce_funcs: true,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
unused: true,
|
unused: true,
|
||||||
}
|
}
|
||||||
@@ -2401,6 +2619,7 @@ issue_4962_2: {
|
|||||||
options = {
|
options = {
|
||||||
ie: true,
|
ie: true,
|
||||||
inline: true,
|
inline: true,
|
||||||
|
reduce_funcs: true,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
unused: true,
|
unused: true,
|
||||||
}
|
}
|
||||||
@@ -2432,6 +2651,7 @@ issue_4962_2_strict: {
|
|||||||
options = {
|
options = {
|
||||||
ie: true,
|
ie: true,
|
||||||
inline: true,
|
inline: true,
|
||||||
|
reduce_funcs: true,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
unused: true,
|
unused: true,
|
||||||
}
|
}
|
||||||
@@ -2460,6 +2680,7 @@ issue_4962_2_strict_direct: {
|
|||||||
options = {
|
options = {
|
||||||
ie: true,
|
ie: true,
|
||||||
inline: true,
|
inline: true,
|
||||||
|
reduce_funcs: true,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
unused: true,
|
unused: true,
|
||||||
}
|
}
|
||||||
@@ -2494,6 +2715,7 @@ issue_4962_2_strict_direct_inline: {
|
|||||||
ie: true,
|
ie: true,
|
||||||
inline: true,
|
inline: true,
|
||||||
passes: 2,
|
passes: 2,
|
||||||
|
reduce_funcs: true,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
unused: true,
|
unused: true,
|
||||||
}
|
}
|
||||||
@@ -2877,6 +3099,7 @@ issue_5053_4: {
|
|||||||
issue_5082_1: {
|
issue_5082_1: {
|
||||||
options = {
|
options = {
|
||||||
inline: true,
|
inline: true,
|
||||||
|
reduce_funcs: true,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
unused: true,
|
unused: true,
|
||||||
}
|
}
|
||||||
@@ -2909,6 +3132,7 @@ issue_5082_1: {
|
|||||||
issue_5082_1_strict: {
|
issue_5082_1_strict: {
|
||||||
options = {
|
options = {
|
||||||
inline: true,
|
inline: true,
|
||||||
|
reduce_funcs: true,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
unused: true,
|
unused: true,
|
||||||
}
|
}
|
||||||
@@ -2942,6 +3166,7 @@ issue_5082_2: {
|
|||||||
options = {
|
options = {
|
||||||
inline: true,
|
inline: true,
|
||||||
passes: 2,
|
passes: 2,
|
||||||
|
reduce_funcs: true,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
unused: true,
|
unused: true,
|
||||||
}
|
}
|
||||||
@@ -2975,6 +3200,7 @@ issue_5082_2_static: {
|
|||||||
options = {
|
options = {
|
||||||
inline: true,
|
inline: true,
|
||||||
passes: 2,
|
passes: 2,
|
||||||
|
reduce_funcs: true,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
unused: true,
|
unused: true,
|
||||||
}
|
}
|
||||||
@@ -3619,3 +3845,59 @@ issue_5662: {
|
|||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
node_version: ">=6"
|
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: {
|
issue_2857_4: {
|
||||||
options = {
|
options = {
|
||||||
comparisons: true,
|
comparisons: true,
|
||||||
|
conditionals: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
function f(a, p) {
|
function f(a, p) {
|
||||||
@@ -305,6 +306,7 @@ issue_2857_4: {
|
|||||||
issue_2857_5: {
|
issue_2857_5: {
|
||||||
options = {
|
options = {
|
||||||
comparisons: true,
|
comparisons: true,
|
||||||
|
conditionals: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
function f(a, p) {
|
function f(a, p) {
|
||||||
@@ -528,6 +530,7 @@ nullish_assign: {
|
|||||||
nullish_chain: {
|
nullish_chain: {
|
||||||
options = {
|
options = {
|
||||||
comparisons: true,
|
comparisons: true,
|
||||||
|
conditionals: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
var a;
|
var a;
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ concat_1: {
|
|||||||
|
|
||||||
var e = 1 + x() + 2 + "X" + 3 + "boo";
|
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";
|
var f = "\0" + 360 + "\0" + 8 + "\0";
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
|
|||||||
@@ -3028,8 +3028,26 @@ issue_5673_2: {
|
|||||||
expect: {
|
expect: {
|
||||||
var a = "PASS";
|
var a = "PASS";
|
||||||
console.log(function(b) {
|
console.log(function(b) {
|
||||||
return ((b = a) || (b = a)) && b;
|
return a || (b = a) && b;
|
||||||
}());
|
}());
|
||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
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"
|
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: {
|
issue_4280: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
|
|||||||
@@ -8719,3 +8719,24 @@ single_use_inline_collision: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
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 = {
|
options = {
|
||||||
conditionals: true,
|
conditionals: true,
|
||||||
if_return: true,
|
if_return: true,
|
||||||
@@ -2442,3 +2442,41 @@ issue_5649: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
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: {
|
input: {
|
||||||
import foo, { bar } from "baz";
|
import foo, { bar } from "baz";
|
||||||
consoe.log(moo);
|
console.log(moo);
|
||||||
import * as moo from "moz";
|
import * as moo from "moz";
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
import o, { bar as m } from "baz";
|
import o, { bar as m } from "baz";
|
||||||
consoe.log(r);
|
console.log(r);
|
||||||
import * as r from "moz";
|
import * as r from "moz";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -157,12 +157,12 @@ rename_mangle: {
|
|||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
import foo, { bar } from "baz";
|
import foo, { bar } from "baz";
|
||||||
consoe.log(moo);
|
console.log(moo);
|
||||||
import * as moo from "moz";
|
import * as moo from "moz";
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
import o, { bar as m } from "baz";
|
import o, { bar as m } from "baz";
|
||||||
consoe.log(r);
|
console.log(r);
|
||||||
import * as r from "moz";
|
import * as r from "moz";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
issue_1321_no_debug: {
|
issue_1321_no_debug: {
|
||||||
mangle = {
|
mangle = {
|
||||||
properties: {
|
properties: {
|
||||||
|
domprops: true,
|
||||||
keep_quoted: true,
|
keep_quoted: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -23,6 +24,7 @@ issue_1321_debug: {
|
|||||||
mangle = {
|
mangle = {
|
||||||
properties: {
|
properties: {
|
||||||
debug: "",
|
debug: "",
|
||||||
|
domprops: true,
|
||||||
keep_quoted: true,
|
keep_quoted: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -44,6 +46,7 @@ issue_1321_debug: {
|
|||||||
issue_1321_with_quoted: {
|
issue_1321_with_quoted: {
|
||||||
mangle = {
|
mangle = {
|
||||||
properties: {
|
properties: {
|
||||||
|
domprops: true,
|
||||||
keep_quoted: false,
|
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(…))
|
* (x = f(…)) <= x → x >= (x = f(…))
|
||||||
*
|
*
|
||||||
* For example, let the equation be:
|
* For example, let the equation be:
|
||||||
@@ -12,37 +12,54 @@
|
|||||||
* a >= (a = parseInt('100')) → 99 >= 100 → false
|
* a >= (a = parseInt('100')) → 99 >= 100 → false
|
||||||
*/
|
*/
|
||||||
|
|
||||||
tranformation_sort_order_equal: {
|
transformation_sort_order_equal: {
|
||||||
options = {
|
options = {
|
||||||
comparisons: true,
|
comparisons: true,
|
||||||
}
|
}
|
||||||
|
input: {
|
||||||
input: { (a = parseInt('100')) == a }
|
console.log((a = parseInt("100")) == a);
|
||||||
expect: { (a = parseInt('100')) == a }
|
}
|
||||||
|
expect: {
|
||||||
|
console.log((a = parseInt("100")) == a);
|
||||||
|
}
|
||||||
|
expect_stdout: "true"
|
||||||
}
|
}
|
||||||
|
|
||||||
tranformation_sort_order_unequal: {
|
transformation_sort_order_unequal: {
|
||||||
options = {
|
options = {
|
||||||
comparisons: true,
|
comparisons: true,
|
||||||
}
|
}
|
||||||
|
input: {
|
||||||
input: { (a = parseInt('100')) != a }
|
console.log((a = parseInt("100")) != a);
|
||||||
expect: { (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 = {
|
options = {
|
||||||
comparisons: true,
|
comparisons: true,
|
||||||
}
|
}
|
||||||
|
input: {
|
||||||
input: { (a = parseInt('100')) <= a }
|
console.log((a = parseInt("100")) <= a);
|
||||||
expect: { (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 = {
|
options = {
|
||||||
comparisons: true,
|
comparisons: true,
|
||||||
}
|
}
|
||||||
|
input: {
|
||||||
input: { (a = parseInt('100')) >= a }
|
console.log((a = parseInt("100")) >= a);
|
||||||
expect: { (a = parseInt('100')) >= a }
|
}
|
||||||
|
expect: {
|
||||||
|
console.log((a = parseInt("100")) >= a);
|
||||||
|
}
|
||||||
|
expect_stdout: "true"
|
||||||
}
|
}
|
||||||
@@ -65,7 +65,9 @@ mangle_props: {
|
|||||||
|
|
||||||
numeric_literal: {
|
numeric_literal: {
|
||||||
mangle = {
|
mangle = {
|
||||||
properties: true,
|
properties: {
|
||||||
|
domprops: true,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
beautify = {
|
beautify = {
|
||||||
beautify: true,
|
beautify: true,
|
||||||
@@ -115,9 +117,9 @@ numeric_literal: {
|
|||||||
"8 7 8",
|
"8 7 8",
|
||||||
]
|
]
|
||||||
expect_warnings: [
|
expect_warnings: [
|
||||||
"INFO: Preserving reserved property log",
|
|
||||||
"INFO: Mapping property 0x25 to o",
|
"INFO: Mapping property 0x25 to o",
|
||||||
"INFO: Mapping property 1E42 to b",
|
"INFO: Mapping property 1E42 to b",
|
||||||
|
"INFO: Preserving reserved property log",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,6 +127,7 @@ identifier: {
|
|||||||
mangle = {
|
mangle = {
|
||||||
properties: {
|
properties: {
|
||||||
builtins: true,
|
builtins: true,
|
||||||
|
domprops: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ collapse: {
|
|||||||
var a;
|
var a;
|
||||||
b = c();
|
b = c();
|
||||||
a = typeof b === 'function' ? b() : b;
|
a = typeof b === 'function' ? b() : b;
|
||||||
return 'stirng' == typeof a && d();
|
return 'string' == typeof a && d();
|
||||||
}
|
}
|
||||||
function f3(c) {
|
function f3(c) {
|
||||||
var a;
|
var a;
|
||||||
@@ -41,7 +41,7 @@ collapse: {
|
|||||||
return void 0 !== ('function' === typeof b ? b() : b) && c();
|
return void 0 !== ('function' === typeof b ? b() : b) && c();
|
||||||
}
|
}
|
||||||
function f2(b) {
|
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) {
|
function f3(c) {
|
||||||
var a;
|
var a;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
dont_reuse_prop: {
|
dont_reuse_prop: {
|
||||||
mangle = {
|
mangle = {
|
||||||
properties: {
|
properties: {
|
||||||
|
domprops: true,
|
||||||
regex: /asd/,
|
regex: /asd/,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -21,14 +22,15 @@ dont_reuse_prop: {
|
|||||||
expect_stdout: "123"
|
expect_stdout: "123"
|
||||||
expect_warnings: [
|
expect_warnings: [
|
||||||
"INFO: Preserving excluded property a",
|
"INFO: Preserving excluded property a",
|
||||||
"INFO: Preserving reserved property log",
|
|
||||||
"INFO: Mapping property asd to b",
|
"INFO: Mapping property asd to b",
|
||||||
|
"INFO: Preserving reserved property log",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
unmangleable_props_should_always_be_reserved: {
|
unmangleable_props_should_always_be_reserved: {
|
||||||
mangle = {
|
mangle = {
|
||||||
properties: {
|
properties: {
|
||||||
|
domprops: true,
|
||||||
regex: /asd/,
|
regex: /asd/,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -49,7 +51,7 @@ unmangleable_props_should_always_be_reserved: {
|
|||||||
expect_stdout: "123"
|
expect_stdout: "123"
|
||||||
expect_warnings: [
|
expect_warnings: [
|
||||||
"INFO: Preserving excluded property a",
|
"INFO: Preserving excluded property a",
|
||||||
"INFO: Preserving reserved property log",
|
|
||||||
"INFO: Mapping property asd to b",
|
"INFO: Mapping property asd to b",
|
||||||
|
"INFO: Preserving reserved property log",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -570,7 +570,7 @@ inlined_assignments: {
|
|||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
inilne_for: {
|
inline_for: {
|
||||||
options = {
|
options = {
|
||||||
inline: true,
|
inline: true,
|
||||||
join_vars: true,
|
join_vars: true,
|
||||||
@@ -590,7 +590,7 @@ inilne_for: {
|
|||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
inilne_var: {
|
inline_var: {
|
||||||
options = {
|
options = {
|
||||||
inline: true,
|
inline: true,
|
||||||
join_vars: true,
|
join_vars: true,
|
||||||
|
|||||||
@@ -173,7 +173,9 @@ numeric_literal: {
|
|||||||
side_effects: true,
|
side_effects: true,
|
||||||
}
|
}
|
||||||
mangle = {
|
mangle = {
|
||||||
properties: true,
|
properties: {
|
||||||
|
domprops: true,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
beautify = {
|
beautify = {
|
||||||
beautify: true,
|
beautify: true,
|
||||||
|
|||||||
@@ -133,6 +133,7 @@ evaluate_string_length: {
|
|||||||
mangle_properties_1: {
|
mangle_properties_1: {
|
||||||
mangle = {
|
mangle = {
|
||||||
properties: {
|
properties: {
|
||||||
|
domprops: true,
|
||||||
keep_quoted: false,
|
keep_quoted: false,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -147,17 +148,18 @@ mangle_properties_1: {
|
|||||||
a["a"] = "bar";
|
a["a"] = "bar";
|
||||||
a.b = "red";
|
a.b = "red";
|
||||||
x = {o: 10};
|
x = {o: 10};
|
||||||
a.r(x.o, a.a);
|
a.run(x.o, a.a);
|
||||||
a['r']({b: "blue", a: "baz"});
|
a['run']({b: "blue", a: "baz"});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mangle_properties_2: {
|
mangle_properties_2: {
|
||||||
mangle = {
|
mangle = {
|
||||||
properties: {
|
properties: {
|
||||||
|
domprops: true,
|
||||||
reserved: [
|
reserved: [
|
||||||
"value",
|
"value",
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
input: {
|
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: {
|
mangle_unquoted_properties: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
@@ -207,6 +227,7 @@ mangle_unquoted_properties: {
|
|||||||
mangle = {
|
mangle = {
|
||||||
properties: {
|
properties: {
|
||||||
builtins: true,
|
builtins: true,
|
||||||
|
domprops: true,
|
||||||
keep_quoted: true,
|
keep_quoted: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -308,6 +329,7 @@ mangle_debug_suffix_keep_quoted: {
|
|||||||
properties: {
|
properties: {
|
||||||
builtins: true,
|
builtins: true,
|
||||||
debug: "XYZ",
|
debug: "XYZ",
|
||||||
|
domprops: true,
|
||||||
keep_quoted: true,
|
keep_quoted: true,
|
||||||
reserved: [],
|
reserved: [],
|
||||||
},
|
},
|
||||||
@@ -962,14 +984,14 @@ issue_2256: {
|
|||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
({ "keep": 42 });
|
({ "keep": 42 });
|
||||||
global.keep = global.change;
|
global.keep = global.change = "PASS";
|
||||||
console.log(keep);
|
console.log(keep);
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
global.keep = global.l;
|
global.keep = global.l = "PASS";
|
||||||
console.log(keep);
|
console.log(keep);
|
||||||
}
|
}
|
||||||
expect_stdout: "undefined"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
lhs_prop_1: {
|
lhs_prop_1: {
|
||||||
@@ -1645,3 +1667,163 @@ issue_5177: {
|
|||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
node_version: ">=4"
|
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"
|
expect_stdout: "function"
|
||||||
node_version: ">=4"
|
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"
|
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");
|
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*/");
|
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*/");
|
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");'
|
'"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;',
|
||||||
'"use asm";"use\\x20strict";1+1;'
|
'"use asm";"use\\x20strict";1+1;'
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -12,17 +12,16 @@ describe("let", function() {
|
|||||||
s += '}';
|
s += '}';
|
||||||
var result = UglifyJS.minify(s, {
|
var result = UglifyJS.minify(s, {
|
||||||
compress: false,
|
compress: false,
|
||||||
}).code;
|
});
|
||||||
|
if (result.error) throw result.error;
|
||||||
// Verify that select keywords and reserved keywords not produced
|
// Verify that select keywords and reserved keywords not produced
|
||||||
[
|
[
|
||||||
"do",
|
"do",
|
||||||
"let",
|
"let",
|
||||||
"var",
|
"var",
|
||||||
].forEach(function(name) {
|
].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
|
// Verify that the variable names that appeared immediately before
|
||||||
// and after the erroneously generated variable name still exist
|
// and after the erroneously generated variable name still exist
|
||||||
// to show the test generated enough symbols.
|
// to show the test generated enough symbols.
|
||||||
@@ -31,27 +30,29 @@ describe("let", function() {
|
|||||||
"eet", "fet",
|
"eet", "fet",
|
||||||
"rar", "oar",
|
"rar", "oar",
|
||||||
].forEach(function(name) {
|
].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() {
|
it("Should quote mangled properties that are reserved keywords", function() {
|
||||||
var s = '"rrrrrnnnnniiiiiaaaaa";';
|
var s = '"rrrrrnnnnniiiiiaaaaa";';
|
||||||
for (var i = 0; i < 18000; i++) {
|
for (var i = 0; i < 18000; i++) {
|
||||||
s += "v.b" + i + ";";
|
s += "v.b" + i + "=v;";
|
||||||
}
|
}
|
||||||
var result = UglifyJS.minify(s, {
|
var result = UglifyJS.minify(s, {
|
||||||
compress: false,
|
compress: false,
|
||||||
ie: true,
|
ie: true,
|
||||||
mangle: {
|
mangle: {
|
||||||
properties: true,
|
properties: {
|
||||||
}
|
domprops: true,
|
||||||
}).code;
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (result.error) throw result.error;
|
||||||
[
|
[
|
||||||
"in",
|
"in",
|
||||||
"var",
|
"var",
|
||||||
].forEach(function(name) {
|
].forEach(function(name) {
|
||||||
assert.notStrictEqual(result.indexOf(name), -1);
|
assert.notStrictEqual(result.code.indexOf('v["' + name + '"]'), -1);
|
||||||
assert.notStrictEqual(result.indexOf('v["' + name + '"]'), -1);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("Should parse `let` as name correctly", function() {
|
it("Should parse `let` as name correctly", function() {
|
||||||
|
|||||||
@@ -110,10 +110,12 @@ describe("minify", function() {
|
|||||||
var result = UglifyJS.minify(code, {
|
var result = UglifyJS.minify(code, {
|
||||||
compress: false,
|
compress: false,
|
||||||
mangle: {
|
mangle: {
|
||||||
properties: true,
|
properties: {
|
||||||
toplevel: true
|
domprops: true,
|
||||||
},
|
},
|
||||||
nameCache: cache
|
toplevel: true,
|
||||||
|
},
|
||||||
|
nameCache: cache,
|
||||||
});
|
});
|
||||||
if (result.error) throw result.error;
|
if (result.error) throw result.error;
|
||||||
original += code;
|
original += code;
|
||||||
@@ -188,32 +190,30 @@ describe("minify", function() {
|
|||||||
it("Shouldn't mangle quoted properties", function() {
|
it("Shouldn't mangle quoted properties", function() {
|
||||||
var js = 'a["foo"] = "bar"; a.color = "red"; x = {"bar": 10};';
|
var js = 'a["foo"] = "bar"; a.color = "red"; x = {"bar": 10};';
|
||||||
var result = UglifyJS.minify(js, {
|
var result = UglifyJS.minify(js, {
|
||||||
compress: {
|
compress: true,
|
||||||
properties: false
|
|
||||||
},
|
|
||||||
mangle: {
|
mangle: {
|
||||||
properties: {
|
properties: {
|
||||||
keep_quoted: true
|
domprops: true,
|
||||||
}
|
keep_quoted: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
output: {
|
output: {
|
||||||
keep_quoted_props: true,
|
keep_quoted_props: true,
|
||||||
quote_style: 3
|
quote_style: 3,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
assert.strictEqual(result.code,
|
assert.strictEqual(result.code, 'a["foo"]="bar",a.a="red",x={"bar":10};');
|
||||||
'a["foo"]="bar",a.a="red",x={"bar":10};');
|
|
||||||
});
|
});
|
||||||
it("Should not mangle quoted property within dead code", function() {
|
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: {
|
mangle: {
|
||||||
properties: {
|
properties: {
|
||||||
keep_quoted: true
|
keep_quoted: true,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
if (result.error) throw result.error;
|
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;
|
if (result.error) throw result.error;
|
||||||
assert.strictEqual(result.code + "\n", read("test/input/issue-3294/output.js"));
|
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"), {
|
var result = UglifyJS.minify(read("test/input/issue-3441/input.js"), {
|
||||||
compress: false,
|
compress: false,
|
||||||
mangle: false,
|
mangle: false,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
var fs = require("fs");
|
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");
|
if (/exports\.js$/.test(file)) file = require.resolve("./exports");
|
||||||
return fs.readFileSync(file, "utf8");
|
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);
|
} while (prev !== stdout);
|
||||||
return stdout;
|
return stdout;
|
||||||
} : semver.satisfies(process.version, "<0.12") ? run_code_vm : function(code, toplevel, timeout) {
|
} : 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/,
|
/\b(async[ \t]+function|Promise|setImmediate|setInterval|setTimeout)\b/,
|
||||||
/\basync([ \t]+|[ \t]*#)[^\s()[\]{}#:;,.&|!~=*%/+-]+(\s*\(|[ \t]*=>)/,
|
/\basync([ \t]+|[ \t]*#)[^\s()[\]{}#:;,.&|!~=*%/+-]+(\s*\(|[ \t]*=>)/,
|
||||||
/\basync[ \t]*\*[ \t]*[^\s()[\]{}#:;,.&|!~=*%/+-]+\s*\(/,
|
/\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]*=>/,
|
/\basync[ \t]*\([\s\S]*?\)[ \t]*=>/,
|
||||||
].some(function(pattern) {
|
].some(function(pattern) {
|
||||||
return pattern.test(code);
|
return pattern.test(code);
|
||||||
})) {
|
}) ? run_code_exec : run_code_vm)(code, toplevel, timeout);
|
||||||
return run_code_exec(code, toplevel, timeout);
|
return stdout.length > 1000 ? stdout.slice(0, 1000) + "…《" + stdout.length + "》" : stdout;
|
||||||
} else {
|
|
||||||
return run_code_vm(code, toplevel, timeout);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
exports.same_stdout = semver.satisfies(process.version, "0.12") ? function(expected, actual) {
|
exports.same_stdout = semver.satisfies(process.version, "0.12") ? function(expected, actual) {
|
||||||
if (typeof expected != typeof actual) return false;
|
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' ], {
|
var result = spawnSync(process.argv[0], [ '--max-old-space-size=2048' ], {
|
||||||
encoding: "utf8",
|
encoding: "utf8",
|
||||||
input: code,
|
input: code,
|
||||||
|
maxBuffer: 1073741824,
|
||||||
stdio: "pipe",
|
stdio: "pipe",
|
||||||
timeout: timeout || 5000,
|
timeout: timeout || 5000,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1142,7 +1142,7 @@ function createStatement(recurmax, canThrow, canBreak, canContinue, cannotReturn
|
|||||||
}
|
}
|
||||||
case STMT_FUNC_EXPR:
|
case STMT_FUNC_EXPR:
|
||||||
// "In non-strict mode code, functions can only be declared at top level, inside a block, or ..."
|
// "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) + "}";
|
return "{" + createFunction(recurmax, NO_DEFUN, canThrow, stmtDepth) + "}";
|
||||||
case STMT_TRY:
|
case STMT_TRY:
|
||||||
// catch var could cause some problems
|
// catch var could cause some problems
|
||||||
|
|||||||
@@ -15,13 +15,13 @@ exports.FILES = [
|
|||||||
require.resolve("./exports.js"),
|
require.resolve("./exports.js"),
|
||||||
];
|
];
|
||||||
|
|
||||||
new Function("exports", function() {
|
new Function("domprops", "exports", function() {
|
||||||
var code = exports.FILES.map(function(file) {
|
var code = exports.FILES.map(function(file) {
|
||||||
return fs.readFileSync(file, "utf8");
|
return fs.readFileSync(file, "utf8");
|
||||||
});
|
});
|
||||||
code.push("exports.describe_ast = " + describe_ast.toString());
|
code.push("exports.describe_ast = " + describe_ast.toString());
|
||||||
return code.join("\n\n");
|
return code.join("\n\n");
|
||||||
}())(exports);
|
}())(require("./domprops.json"), exports);
|
||||||
|
|
||||||
function to_comment(value) {
|
function to_comment(value) {
|
||||||
if (typeof value != "string") value = JSON.stringify(value, function(key, value) {
|
if (typeof value != "string") value = JSON.stringify(value, function(key, value) {
|
||||||
|
|||||||
Reference in New Issue
Block a user