Compare commits
60 Commits
harmony-v3
...
harmony-v3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
873755b35c | ||
|
|
744032755d | ||
|
|
4fac8076b8 | ||
|
|
6920e898d1 | ||
|
|
dd71639264 | ||
|
|
2dcc552ce0 | ||
|
|
a020d2ead3 | ||
|
|
68645b28d3 | ||
|
|
aaa8212837 | ||
|
|
bd84007cf4 | ||
|
|
55387e8fd0 | ||
|
|
1241600013 | ||
|
|
7e3e9da860 | ||
|
|
a784717fe2 | ||
|
|
00f509405b | ||
|
|
e8235657e4 | ||
|
|
c46b9f361a | ||
|
|
3b0b4d6abf | ||
|
|
d73500e8d1 | ||
|
|
aceb0af36b | ||
|
|
4f0953f7e9 | ||
|
|
182a47bfb1 | ||
|
|
d8685f528d | ||
|
|
8891495789 | ||
|
|
cd27f4ec38 | ||
|
|
8158b1bdcf | ||
|
|
aacf3edc68 | ||
|
|
8b89072190 | ||
|
|
395a17ccda | ||
|
|
3f355866cf | ||
|
|
2779a29a86 | ||
|
|
71d52f147d | ||
|
|
eb7adaa6fc | ||
|
|
e5cf7972ea | ||
|
|
067d52b6ba | ||
|
|
e0e009ace2 | ||
|
|
f81ff10a9b | ||
|
|
ae0f117da6 | ||
|
|
a5461e0adc | ||
|
|
16d40915b4 | ||
|
|
2bf8216e50 | ||
|
|
2ed3f8db44 | ||
|
|
4700c14855 | ||
|
|
e7c21e87e3 | ||
|
|
f54ab16843 | ||
|
|
69cb459c16 | ||
|
|
1eae8f2dcc | ||
|
|
c4c2ef44d0 | ||
|
|
a845897758 | ||
|
|
d600c78d7b | ||
|
|
32ea2c5530 | ||
|
|
d3df2f985d | ||
|
|
69861824b5 | ||
|
|
1e0c7d2bc5 | ||
|
|
98b850580b | ||
|
|
29011ea60a | ||
|
|
77d18be073 | ||
|
|
bc61deeca9 | ||
|
|
6a5e74b44e | ||
|
|
54446341ee |
9
.github/ISSUE_TEMPLATE.md
vendored
9
.github/ISSUE_TEMPLATE.md
vendored
@@ -8,7 +8,14 @@
|
||||
|
||||
**Uglify version (`uglifyjs -V`)**
|
||||
|
||||
**JavaScript input** <!-- ideally as small as possible -->
|
||||
**JavaScript input**
|
||||
|
||||
<!--
|
||||
A complete parsable JS program exhibiting the issue with
|
||||
UglifyJS alone - without third party tools or libraries.
|
||||
Ideally the input should be as small as possible.
|
||||
Post a link to a gist if necessary.
|
||||
-->
|
||||
|
||||
**The `uglifyjs` CLI command executed or `minify()` options used.**
|
||||
|
||||
|
||||
34
README.md
34
README.md
@@ -148,19 +148,19 @@ debugging your compressed JavaScript. To get a source map, pass
|
||||
|
||||
Additional options:
|
||||
|
||||
- `--source-map filename=<NAME>` to specify the name of the source map.
|
||||
- `--source-map "filename='<NAME>'"` to specify the name of the source map.
|
||||
|
||||
- `--source-map root=<URL>` to pass the URL where the original files can be found.
|
||||
- `--source-map "root='<URL>'"` to pass the URL where the original files can be found.
|
||||
Otherwise UglifyJS assumes HTTP `X-SourceMap` is being used and will omit the
|
||||
`//# sourceMappingURL=` directive.
|
||||
|
||||
- `--source-map url=<URL>` to specify the URL where the source map can be found.
|
||||
- `--source-map "url='<URL>'"` to specify the URL where the source map can be found.
|
||||
|
||||
For example:
|
||||
|
||||
uglifyjs js/file1.js js/file2.js \
|
||||
-o foo.min.js -c -m \
|
||||
--source-map root="http://foo.com/src",url=foo.min.js.map
|
||||
--source-map "root='http://foo.com/src',url='foo.min.js.map'"
|
||||
|
||||
The above will compress and mangle `file1.js` and `file2.js`, will drop the
|
||||
output in `foo.min.js` and the source map in `foo.min.js.map`. The source
|
||||
@@ -179,8 +179,8 @@ CoffeeScript → compiled JS, UglifyJS can generate a map from CoffeeScript →
|
||||
compressed JS by mapping every token in the compiled JS to its original
|
||||
location.
|
||||
|
||||
To use this feature pass `--source-map content="/path/to/input/source.map"`
|
||||
or `--source-map content=inline` if the source map is included inline with
|
||||
To use this feature pass `--source-map "content='/path/to/input/source.map'"`
|
||||
or `--source-map "content=inline"` if the source map is included inline with
|
||||
the sources.
|
||||
|
||||
## CLI compress options
|
||||
@@ -211,7 +211,7 @@ When mangling is enabled but you want to prevent certain names from being
|
||||
mangled, you can declare those names with `--mangle reserved` — pass a
|
||||
comma-separated list of names. For example:
|
||||
|
||||
uglifyjs ... -m reserved=[$,require,exports]
|
||||
uglifyjs ... -m reserved=['$','require','exports']
|
||||
|
||||
to prevent the `require`, `exports` and `$` names from being changed.
|
||||
|
||||
@@ -631,6 +631,13 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
|
||||
- `unsafe_math` (default: false) -- optimize numerical expressions like
|
||||
`2 * x * 3` into `6 * x`, which may give imprecise floating point results.
|
||||
|
||||
- `unsafe_methods` (default: false) -- Converts `{ m: function(){} }` to
|
||||
`{ m(){} }`. `ecma` must be set to `6` or greater to enable this transform.
|
||||
If `unsafe_methods` is a RegExp then key/value pairs with keys matching the
|
||||
RegExp will be converted to concise methods.
|
||||
Note: if enabled there is a risk of getting a "`<method name>` is not a
|
||||
constructor" TypeError should any code try to `new` the former function.
|
||||
|
||||
- `unsafe_proto` (default: false) -- optimize expressions like
|
||||
`Array.prototype.slice.call(a)` into `[].slice.call(a)`
|
||||
|
||||
@@ -646,9 +653,16 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
|
||||
|
||||
- `evaluate` -- attempt to evaluate constant expressions
|
||||
|
||||
- `arrows` (default `true`) -- convert ES5 style anonymous function expressions
|
||||
to arrow functions if permissible by language semantics.
|
||||
Note: `arrows` requires that the `ecma` compress option is set to `6` or greater.
|
||||
- `arrows` (default `true`) -- Converts `()=>{return x}` to `()=>x`. Class
|
||||
and object literal methods will also be converted to arrow expressions if
|
||||
the resultant code is shorter: `m(){return x}` becomes `m:()=>x`.
|
||||
This transform requires that the `ecma` compress option is set to `6` or greater.
|
||||
|
||||
- `unsafe_arrows` (default `false`) -- Convert ES5 style anonymous function
|
||||
expressions to arrow functions if the function body does not reference `this`.
|
||||
Note: it is not always safe to perform this conversion if code relies on the
|
||||
the function having a `prototype`, which arrow functions lack.
|
||||
This transform requires that the `ecma` compress option is set to `6` or greater.
|
||||
|
||||
- `booleans` -- various optimizations for boolean context, for example `!!a
|
||||
? b : c → a ? b : c`
|
||||
|
||||
@@ -134,11 +134,10 @@ var AST_Debugger = DEFNODE("Debugger", null, {
|
||||
$documentation: "Represents a debugger statement",
|
||||
}, AST_Statement);
|
||||
|
||||
var AST_Directive = DEFNODE("Directive", "value scope quote", {
|
||||
var AST_Directive = DEFNODE("Directive", "value quote", {
|
||||
$documentation: "Represents a directive, like \"use strict\";",
|
||||
$propdoc: {
|
||||
value: "[string] The value of this directive as a plain string (it's not an AST_String!)",
|
||||
scope: "[AST_Scope/S] The scope that this directive affects",
|
||||
quote: "[string] the original quote character"
|
||||
},
|
||||
}, AST_Statement);
|
||||
@@ -303,10 +302,9 @@ var AST_With = DEFNODE("With", "expression", {
|
||||
|
||||
/* -----[ scope and functions ]----- */
|
||||
|
||||
var AST_Scope = DEFNODE("Scope", "directives variables functions uses_with uses_eval parent_scope enclosed cname", {
|
||||
var AST_Scope = DEFNODE("Scope", "variables functions uses_with uses_eval parent_scope enclosed cname", {
|
||||
$documentation: "Base class for all statements introducing a lexical scope",
|
||||
$propdoc: {
|
||||
directives: "[string*/S] an array of directives declared in this scope",
|
||||
variables: "[Object/S] a map of name -> SymbolDef for all variables/functions defined in this scope",
|
||||
functions: "[Object/S] like `variables`, but only lists function declarations",
|
||||
uses_with: "[boolean/S] tells whether this scope uses the `with` statement",
|
||||
@@ -697,7 +695,7 @@ var AST_Export = DEFNODE("Export", "exported_definition exported_value is_defaul
|
||||
var AST_VarDef = DEFNODE("VarDef", "name value", {
|
||||
$documentation: "A variable declaration; only appears in a AST_Definitions node",
|
||||
$propdoc: {
|
||||
name: "[AST_SymbolVar|AST_SymbolConst|AST_Destructuring] name of the variable",
|
||||
name: "[AST_Destructuring|AST_SymbolConst|AST_SymbolLet|AST_SymbolVar] name of the variable",
|
||||
value: "[AST_Node?] initializer, or null of there's no initializer"
|
||||
},
|
||||
_walk: function(visitor) {
|
||||
|
||||
@@ -84,9 +84,11 @@ function Compressor(options, false_by_default) {
|
||||
toplevel : !!(options && options["top_retain"]),
|
||||
typeofs : !false_by_default,
|
||||
unsafe : false,
|
||||
unsafe_arrows : false,
|
||||
unsafe_comps : false,
|
||||
unsafe_Func : false,
|
||||
unsafe_math : false,
|
||||
unsafe_methods: false,
|
||||
unsafe_proto : false,
|
||||
unsafe_regexp : false,
|
||||
unused : !false_by_default,
|
||||
@@ -288,6 +290,10 @@ merge(Compressor.prototype, {
|
||||
|
||||
AST_Node.DEFMETHOD("reset_opt_flags", function(compressor, rescan) {
|
||||
var reduce_vars = rescan && compressor.option("reduce_vars");
|
||||
// Stack of look-up tables to keep track of whether a `SymbolDef` has been
|
||||
// properly assigned before use:
|
||||
// - `push()` & `pop()` when visiting conditional branches
|
||||
// - backup & restore via `save_ids` when visiting out-of-order sections
|
||||
var safe_ids = Object.create(null);
|
||||
var suppressor = new TreeWalker(function(node) {
|
||||
if (!(node instanceof AST_Symbol)) return;
|
||||
@@ -302,6 +308,7 @@ merge(Compressor.prototype, {
|
||||
if (reduce_vars) {
|
||||
if (node instanceof AST_Toplevel) node.globals.each(reset_def);
|
||||
if (node instanceof AST_Scope) node.variables.each(reset_def);
|
||||
if (node.block_scope) node.block_scope.variables.each(reset_def);
|
||||
if (node instanceof AST_SymbolRef) {
|
||||
var d = node.definition();
|
||||
d.references.push(node);
|
||||
@@ -402,10 +409,9 @@ merge(Compressor.prototype, {
|
||||
return true;
|
||||
}
|
||||
if (node instanceof AST_Accessor) {
|
||||
var save_ids = safe_ids;
|
||||
safe_ids = Object.create(null);
|
||||
push();
|
||||
descend();
|
||||
safe_ids = save_ids;
|
||||
pop();
|
||||
return true;
|
||||
}
|
||||
if (node instanceof AST_Binary
|
||||
@@ -577,6 +583,8 @@ merge(Compressor.prototype, {
|
||||
}
|
||||
|
||||
function is_lhs_read_only(lhs) {
|
||||
if (lhs instanceof AST_Super) return true;
|
||||
if (lhs instanceof AST_This) return true;
|
||||
if (lhs instanceof AST_SymbolRef) return lhs.definition().orig[0] instanceof AST_SymbolLambda;
|
||||
if (lhs instanceof AST_PropAccess) {
|
||||
lhs = lhs.expression;
|
||||
@@ -728,7 +736,7 @@ merge(Compressor.prototype, {
|
||||
return node instanceof AST_SymbolRef && node.definition().undeclared;
|
||||
}
|
||||
|
||||
var global_names = makePredicate("Array Boolean console Error Function Math Number RegExp Object String");
|
||||
var global_names = makePredicate("Array Boolean clearInterval clearTimeout console Date decodeURI decodeURIComponent encodeURI encodeURIComponent Error escape eval EvalError Function isFinite isNaN JSON Math Number parseFloat parseInt RangeError ReferenceError RegExp Object setInterval setTimeout String SyntaxError TypeError unescape URIError");
|
||||
AST_SymbolRef.DEFMETHOD("is_declared", function(compressor) {
|
||||
return !this.definition().undeclared
|
||||
|| compressor.option("unsafe") && global_names(this.name);
|
||||
@@ -780,7 +788,7 @@ merge(Compressor.prototype, {
|
||||
while (candidates.length > 0) {
|
||||
var candidate = candidates.pop();
|
||||
var lhs = get_lhs(candidate);
|
||||
if (!lhs || is_lhs_read_only(lhs)) continue;
|
||||
if (!lhs || is_lhs_read_only(lhs) || lhs.has_side_effects(compressor)) continue;
|
||||
// Locate symbols which may execute code outside of scanning range
|
||||
var lvalues = get_lvalues(candidate);
|
||||
if (lhs instanceof AST_SymbolRef) lvalues[lhs.name] = false;
|
||||
@@ -870,7 +878,7 @@ merge(Compressor.prototype, {
|
||||
}
|
||||
}
|
||||
|
||||
function has_overlapping_symbol(fn, arg) {
|
||||
function has_overlapping_symbol(fn, arg, fn_strict) {
|
||||
var found = false, scan_this = !(fn instanceof AST_Arrow);
|
||||
arg.walk(new TreeWalker(function(node, descend) {
|
||||
if (found) return true;
|
||||
@@ -881,7 +889,7 @@ merge(Compressor.prototype, {
|
||||
}
|
||||
return found = true;
|
||||
}
|
||||
if (scan_this && node instanceof AST_This) {
|
||||
if ((fn_strict || scan_this) && node instanceof AST_This) {
|
||||
return found = true;
|
||||
}
|
||||
if (node instanceof AST_Scope && !(node instanceof AST_Arrow)) {
|
||||
@@ -906,6 +914,8 @@ merge(Compressor.prototype, {
|
||||
&& all(iife.args, function(arg) {
|
||||
return !(arg instanceof AST_Expansion);
|
||||
})) {
|
||||
var fn_strict = compressor.has_directive("use strict");
|
||||
if (fn_strict && fn.body.indexOf(fn_strict) < 0) fn_strict = false;
|
||||
var names = Object.create(null);
|
||||
for (var i = fn.argnames.length; --i >= 0;) {
|
||||
var sym = fn.argnames[i];
|
||||
@@ -914,7 +924,7 @@ merge(Compressor.prototype, {
|
||||
if (sym instanceof AST_Expansion) {
|
||||
var elements = iife.args.slice(i);
|
||||
if (all(elements, function(arg) {
|
||||
return !has_overlapping_symbol(fn, arg);
|
||||
return !has_overlapping_symbol(fn, arg, fn_strict);
|
||||
})) {
|
||||
candidates.unshift(make_node(AST_VarDef, sym, {
|
||||
name: sym.expression,
|
||||
@@ -925,8 +935,8 @@ merge(Compressor.prototype, {
|
||||
}
|
||||
} else {
|
||||
var arg = iife.args[i];
|
||||
if (!arg) arg = make_node(AST_Undefined, sym);
|
||||
else if (has_overlapping_symbol(fn, arg)) arg = null;
|
||||
if (!arg) arg = make_node(AST_Undefined, sym).transform(compressor);
|
||||
else if (has_overlapping_symbol(fn, arg, fn_strict)) arg = null;
|
||||
if (arg) candidates.unshift(make_node(AST_VarDef, sym, {
|
||||
name: sym,
|
||||
value: arg
|
||||
@@ -1426,9 +1436,14 @@ merge(Compressor.prototype, {
|
||||
def(AST_Object, function(compressor) {
|
||||
if (!is_strict(compressor)) return false;
|
||||
for (var i = this.properties.length; --i >=0;)
|
||||
if (this.properties[i].value instanceof AST_Accessor) return true;
|
||||
if (this.properties[i]._dot_throw(compressor)) return true;
|
||||
return false;
|
||||
});
|
||||
def(AST_ObjectProperty, return_false);
|
||||
def(AST_ObjectGetter, return_true);
|
||||
def(AST_Expansion, function(compressor) {
|
||||
return this.expression._dot_throw(compressor);
|
||||
});
|
||||
def(AST_Function, return_false);
|
||||
def(AST_Arrow, return_false);
|
||||
def(AST_UnaryPostfix, return_false);
|
||||
@@ -1730,6 +1745,7 @@ merge(Compressor.prototype, {
|
||||
var val = {};
|
||||
for (var i = 0, len = this.properties.length; i < len; i++) {
|
||||
var prop = this.properties[i];
|
||||
if (prop instanceof AST_Expansion) return this;
|
||||
var key = prop.key;
|
||||
if (key instanceof AST_Symbol) {
|
||||
key = key.name;
|
||||
@@ -2073,26 +2089,38 @@ merge(Compressor.prototype, {
|
||||
if (!compressor.option("side_effects")) return false;
|
||||
if (this.pure !== undefined) return this.pure;
|
||||
var pure = false;
|
||||
var comments, last_comment;
|
||||
var comments, pure_comment;
|
||||
if (this.start
|
||||
&& (comments = this.start.comments_before)
|
||||
&& comments.length
|
||||
&& /[@#]__PURE__/.test((last_comment = comments[comments.length - 1]).value)) {
|
||||
pure = last_comment;
|
||||
&& (pure_comment = find_if(function (comment) {
|
||||
return /[@#]__PURE__/.test(comment.value);
|
||||
}, comments))) {
|
||||
pure = pure_comment;
|
||||
}
|
||||
return this.pure = pure;
|
||||
});
|
||||
|
||||
var global_pure_fns = makePredicate("Boolean decodeURI decodeURIComponent Date encodeURI encodeURIComponent Error escape EvalError isFinite isNaN Number Object parseFloat parseInt RangeError ReferenceError String SyntaxError TypeError unescape URIError");
|
||||
AST_Call.DEFMETHOD("is_expr_pure", function(compressor) {
|
||||
if (compressor.option("unsafe")) {
|
||||
var expr = this.expression;
|
||||
if (is_undeclared_ref(expr) && global_pure_fns(expr.name)) return true;
|
||||
}
|
||||
return this.has_pure_annotation(compressor) || !compressor.pure_funcs(this);
|
||||
});
|
||||
|
||||
// determine if expression has side effects
|
||||
(function(def){
|
||||
def(AST_Node, return_true);
|
||||
|
||||
def(AST_EmptyStatement, return_false);
|
||||
def(AST_Constant, return_false);
|
||||
def(AST_Super, return_false);
|
||||
def(AST_This, return_false);
|
||||
|
||||
def(AST_Call, function(compressor){
|
||||
if (!this.has_pure_annotation(compressor) && compressor.pure_funcs(this)) return true;
|
||||
if (!this.is_expr_pure(compressor)) return true;
|
||||
for (var i = this.args.length; --i >= 0;) {
|
||||
if (this.args[i].has_side_effects(compressor))
|
||||
return true;
|
||||
@@ -2562,17 +2590,18 @@ merge(Compressor.prototype, {
|
||||
// We fix it at this stage by moving the `var` outside the `for`.
|
||||
if (node instanceof AST_For) {
|
||||
descend(node, this);
|
||||
var block;
|
||||
if (node.init instanceof AST_BlockStatement) {
|
||||
var block = node.init;
|
||||
block = node.init;
|
||||
node.init = block.body.pop();
|
||||
block.body.push(node);
|
||||
return in_list ? MAP.splice(block.body) : block;
|
||||
} else if (node.init instanceof AST_SimpleStatement) {
|
||||
}
|
||||
if (node.init instanceof AST_SimpleStatement) {
|
||||
node.init = node.init.body;
|
||||
} else if (is_empty(node.init)) {
|
||||
node.init = null;
|
||||
}
|
||||
return node;
|
||||
return !block ? node : in_list ? MAP.splice(block.body) : block;
|
||||
}
|
||||
if (node instanceof AST_LabeledStatement && node.body instanceof AST_For) {
|
||||
descend(node, this);
|
||||
@@ -2766,9 +2795,10 @@ merge(Compressor.prototype, {
|
||||
|
||||
def(AST_Node, return_this);
|
||||
def(AST_Constant, return_null);
|
||||
def(AST_Super, return_null);
|
||||
def(AST_This, return_null);
|
||||
def(AST_Call, function(compressor, first_in_statement){
|
||||
if (!this.has_pure_annotation(compressor) && compressor.pure_funcs(this)) {
|
||||
if (!this.is_expr_pure(compressor)) {
|
||||
if (is_func_expr(this.expression)
|
||||
&& (!this.expression.name || !this.expression.name.definition().references.length)) {
|
||||
var node = this.clone();
|
||||
@@ -3278,6 +3308,7 @@ merge(Compressor.prototype, {
|
||||
});
|
||||
a.push(var_);
|
||||
}
|
||||
remove(def.name.definition().orig, def.name);
|
||||
return a;
|
||||
}, []);
|
||||
if (assignments.length == 0) return null;
|
||||
@@ -3689,7 +3720,10 @@ merge(Compressor.prototype, {
|
||||
&& (left.operator == "++" || left.operator == "--")) {
|
||||
left = left.expression;
|
||||
} else left = null;
|
||||
if (!left || is_lhs_read_only(left) || is_ref_of(left, AST_SymbolConst)) {
|
||||
if (!left
|
||||
|| is_lhs_read_only(left)
|
||||
|| left.has_side_effects(compressor)
|
||||
|| is_ref_of(left, AST_SymbolConst)) {
|
||||
expressions[++i] = cdr;
|
||||
continue;
|
||||
}
|
||||
@@ -4492,6 +4526,8 @@ merge(Compressor.prototype, {
|
||||
&& alternative.TYPE === consequent.TYPE
|
||||
&& consequent.args.length == 1
|
||||
&& alternative.args.length == 1
|
||||
&& !(consequent.args[0] instanceof AST_Expansion)
|
||||
&& !(alternative.args[0] instanceof AST_Expansion)
|
||||
&& consequent.expression.equivalent_to(alternative.expression)
|
||||
&& !consequent.expression.has_side_effects(compressor)) {
|
||||
consequent.args[0] = make_node(AST_Conditional, self, {
|
||||
@@ -4741,7 +4777,7 @@ merge(Compressor.prototype, {
|
||||
|
||||
OPT(AST_Function, function(self, compressor){
|
||||
tighten_body(self.body, compressor);
|
||||
if (compressor.option("arrows")
|
||||
if (compressor.option("unsafe_arrows")
|
||||
&& compressor.option("ecma") >= 6
|
||||
&& !self.name
|
||||
&& !self.is_generator
|
||||
@@ -4823,7 +4859,8 @@ merge(Compressor.prototype, {
|
||||
arrow.is_generator = self.is_generator;
|
||||
return make_node(AST_ObjectKeyVal, self, {
|
||||
key: self.key instanceof AST_SymbolMethod ? self.key.name : self.key,
|
||||
value: arrow
|
||||
value: arrow,
|
||||
quote: self.quote,
|
||||
});
|
||||
}
|
||||
return self;
|
||||
@@ -4835,7 +4872,10 @@ merge(Compressor.prototype, {
|
||||
// p:async function(){} ---> async p(){}
|
||||
// p:()=>{} ---> p(){}
|
||||
// p:async()=>{} ---> async p(){}
|
||||
if (compressor.option("ecma") >= 6) {
|
||||
var unsafe_methods = compressor.option("unsafe_methods");
|
||||
if (unsafe_methods
|
||||
&& compressor.option("ecma") >= 6
|
||||
&& (!(unsafe_methods instanceof RegExp) || unsafe_methods.test(self.key + ""))) {
|
||||
var key = self.key;
|
||||
var value = self.value;
|
||||
var is_arrow_with_block = value instanceof AST_Arrow
|
||||
@@ -4849,6 +4889,7 @@ merge(Compressor.prototype, {
|
||||
name: key,
|
||||
}),
|
||||
value: make_node(AST_Accessor, value, value),
|
||||
quote: self.quote,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,6 +70,7 @@ function minify(files, options) {
|
||||
set_shorthand("keep_fnames", options, [ "compress", "mangle" ]);
|
||||
set_shorthand("toplevel", options, [ "compress", "mangle" ]);
|
||||
set_shorthand("warnings", options, [ "compress" ]);
|
||||
var quoted_props;
|
||||
if (options.mangle) {
|
||||
options.mangle = defaults(options.mangle, {
|
||||
cache: options.nameCache && (options.nameCache.vars || {}),
|
||||
@@ -82,11 +83,16 @@ function minify(files, options) {
|
||||
safari10: false,
|
||||
toplevel: false,
|
||||
}, true);
|
||||
if (options.nameCache && options.mangle.properties) {
|
||||
if (options.mangle.properties) {
|
||||
if (typeof options.mangle.properties != "object") {
|
||||
options.mangle.properties = {};
|
||||
}
|
||||
if (!("cache" in options.mangle.properties)) {
|
||||
if (options.mangle.properties.keep_quoted) {
|
||||
quoted_props = options.mangle.properties.reserved;
|
||||
if (!Array.isArray(quoted_props)) quoted_props = [];
|
||||
options.mangle.properties.reserved = quoted_props;
|
||||
}
|
||||
if (options.nameCache && !("cache" in options.mangle.properties)) {
|
||||
options.mangle.properties.cache = options.nameCache.props || {};
|
||||
}
|
||||
}
|
||||
@@ -129,6 +135,9 @@ function minify(files, options) {
|
||||
}
|
||||
toplevel = options.parse.toplevel;
|
||||
}
|
||||
if (quoted_props) {
|
||||
reserve_quoted_keys(toplevel, quoted_props);
|
||||
}
|
||||
if (options.wrap) {
|
||||
toplevel = toplevel.wrap_commonjs(options.wrap);
|
||||
}
|
||||
|
||||
@@ -54,7 +54,6 @@ function OutputStream(options) {
|
||||
|
||||
options = defaults(options, {
|
||||
ascii_only : false,
|
||||
ascii_identifiers: undefined,
|
||||
beautify : false,
|
||||
bracketize : false,
|
||||
comments : false,
|
||||
@@ -78,9 +77,6 @@ function OutputStream(options) {
|
||||
wrap_iife : false,
|
||||
}, true);
|
||||
|
||||
if (typeof options.ascii_identifiers === 'undefined')
|
||||
options.ascii_identifiers = options.ascii_only;
|
||||
|
||||
if (options.shorthand === undefined)
|
||||
options.shorthand = options.ecma > 5;
|
||||
|
||||
@@ -118,20 +114,16 @@ function OutputStream(options) {
|
||||
var current_pos = 0;
|
||||
var OUTPUT = "";
|
||||
|
||||
function to_ascii(str, identifier) {
|
||||
return str.replace(/[\ud800-\udbff][\udc00-\udfff]|[\u0000-\u001f\u007f-\uffff]/g, function(ch) {
|
||||
var to_utf8 = options.ascii_only ? function(str, identifier) {
|
||||
if (options.ecma >= 6) {
|
||||
str = str.replace(/[\ud800-\udbff][\udc00-\udfff]/g, function(ch) {
|
||||
var code = get_full_char_code(ch, 0).toString(16);
|
||||
|
||||
if ((identifier && code.length === 1 && options.ecma >= 6) || code.length > 4) {
|
||||
if (options.ecma < 6) {
|
||||
if (identifier) {
|
||||
return ch; // no \u{} support
|
||||
}
|
||||
return "\\u" + ch.charCodeAt(0).toString(16) + "\\u"
|
||||
+ ch.charCodeAt(1).toString(16);
|
||||
}
|
||||
return "\\u{" + code + "}";
|
||||
} else if (code.length <= 2 && !identifier) {
|
||||
});
|
||||
}
|
||||
return str.replace(/[\u0000-\u001f\u007f-\uffff]/g, function(ch) {
|
||||
var code = ch.charCodeAt(0).toString(16);
|
||||
if (code.length <= 2 && !identifier) {
|
||||
while (code.length < 2) code = "0" + code;
|
||||
return "\\x" + code;
|
||||
} else {
|
||||
@@ -139,6 +131,12 @@ function OutputStream(options) {
|
||||
return "\\u" + code;
|
||||
}
|
||||
});
|
||||
} : function(str) {
|
||||
return str.replace(/[\ud800-\udbff](?![\udc00-\udfff])/g, function(ch) {
|
||||
return "\\u" + ch.charCodeAt(0).toString(16);
|
||||
}).replace(/(^|[^\ud800-\udbff])([\udc00-\udfff])/g, function(match, prefix, ch) {
|
||||
return prefix + "\\u" + ch.charCodeAt(0).toString(16);
|
||||
});
|
||||
};
|
||||
|
||||
function make_string(str, quote) {
|
||||
@@ -159,7 +157,7 @@ function OutputStream(options) {
|
||||
case "\u2029": return "\\u2029";
|
||||
case "\ufeff": return "\\ufeff";
|
||||
case "\0":
|
||||
return /[0-7]/.test(get_full_char(str, i+1)) ? "\\x00" : "\\0";
|
||||
return /[0-9]/.test(get_full_char(str, i+1)) ? "\\x00" : "\\0";
|
||||
}
|
||||
return s;
|
||||
});
|
||||
@@ -172,7 +170,7 @@ function OutputStream(options) {
|
||||
function quote_template() {
|
||||
return '`' + str.replace(/`/g, '\\`') + '`';
|
||||
}
|
||||
if (options.ascii_only) str = to_ascii(str);
|
||||
str = to_utf8(str);
|
||||
if (quote === "`") return quote_template();
|
||||
switch (options.quote_style) {
|
||||
case 1:
|
||||
@@ -198,8 +196,7 @@ function OutputStream(options) {
|
||||
|
||||
function make_name(name) {
|
||||
name = name.toString();
|
||||
if (options.ascii_identifiers)
|
||||
name = to_ascii(name, true);
|
||||
name = to_utf8(name, true);
|
||||
return name;
|
||||
};
|
||||
|
||||
@@ -461,7 +458,7 @@ function OutputStream(options) {
|
||||
last : function() { return last },
|
||||
semicolon : semicolon,
|
||||
force_semicolon : force_semicolon,
|
||||
to_ascii : to_ascii,
|
||||
to_utf8 : to_utf8,
|
||||
print_name : function(name) { print(make_name(name)) },
|
||||
print_string : function(str, quote, escape_directive) {
|
||||
var encoded = encode_string(str, quote);
|
||||
@@ -509,13 +506,17 @@ function OutputStream(options) {
|
||||
nodetype.DEFMETHOD("_codegen", generator);
|
||||
};
|
||||
|
||||
var use_asm = false;
|
||||
var in_directive = false;
|
||||
var active_scope = null;
|
||||
var use_asm = null;
|
||||
|
||||
AST_Node.DEFMETHOD("print", function(stream, force_parens){
|
||||
var self = this, generator = self._codegen, prev_use_asm = use_asm;
|
||||
if (self instanceof AST_Directive && self.value == "use asm" && stream.parent() instanceof AST_Scope) {
|
||||
use_asm = true;
|
||||
var self = this, generator = self._codegen;
|
||||
if (self instanceof AST_Scope) {
|
||||
active_scope = self;
|
||||
}
|
||||
else if (!use_asm && self instanceof AST_Directive && self.value == "use asm") {
|
||||
use_asm = active_scope;
|
||||
}
|
||||
function doit() {
|
||||
self.add_comments(stream);
|
||||
@@ -529,8 +530,8 @@ function OutputStream(options) {
|
||||
doit();
|
||||
}
|
||||
stream.pop_node();
|
||||
if (self instanceof AST_Scope) {
|
||||
use_asm = prev_use_asm;
|
||||
if (self === use_asm) {
|
||||
use_asm = null;
|
||||
}
|
||||
});
|
||||
AST_Node.DEFMETHOD("_print", AST_Node.prototype.print);
|
||||
@@ -692,6 +693,7 @@ function OutputStream(options) {
|
||||
* ==> 20 (side effect, set a := 10 and b := 20) */
|
||||
|| p instanceof AST_Arrow // x => (x, x)
|
||||
|| p instanceof AST_DefaultAssign // x => (x = (0, function(){}))
|
||||
|| p instanceof AST_Expansion // [...(a, b)]
|
||||
;
|
||||
});
|
||||
|
||||
@@ -1400,7 +1402,7 @@ function OutputStream(options) {
|
||||
self.expression.print(output);
|
||||
if (self instanceof AST_New && !need_constructor_parens(self, output))
|
||||
return;
|
||||
if (self.expression instanceof AST_Lambda) {
|
||||
if (self.expression instanceof AST_Call || self.expression instanceof AST_Lambda) {
|
||||
output.add_mapping(self.start);
|
||||
}
|
||||
output.with_parens(function(){
|
||||
@@ -1713,9 +1715,7 @@ function OutputStream(options) {
|
||||
if (regexp.raw_source) {
|
||||
str = "/" + regexp.raw_source + str.slice(str.lastIndexOf("/"));
|
||||
}
|
||||
if (output.option("ascii_only")) {
|
||||
str = output.to_ascii(str);
|
||||
}
|
||||
str = output.to_utf8(str);
|
||||
output.print(str);
|
||||
var p = output.parent();
|
||||
if (p instanceof AST_Binary && /^in/.test(p.operator) && p.left === self)
|
||||
|
||||
71
lib/parse.js
71
lib/parse.js
@@ -44,9 +44,9 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
var KEYWORDS = 'break case catch class const continue debugger default delete do else export extends finally for function if in instanceof new return switch throw try typeof var let void while with import';
|
||||
var KEYWORDS = 'break case catch class const continue debugger default delete do else export extends finally for function if in instanceof let new return switch throw try typeof var void while with';
|
||||
var KEYWORDS_ATOM = 'false null true';
|
||||
var RESERVED_WORDS = 'enum implements interface package private protected public static super this ' + KEYWORDS_ATOM + " " + KEYWORDS;
|
||||
var RESERVED_WORDS = 'enum implements import interface package private protected public static super this ' + KEYWORDS_ATOM + " " + KEYWORDS;
|
||||
var KEYWORDS_BEFORE_EXPRESSION = 'return new delete throw else case yield await';
|
||||
|
||||
KEYWORDS = makePredicate(KEYWORDS);
|
||||
@@ -1013,6 +1013,12 @@ function parse($TEXT, options) {
|
||||
next();
|
||||
return function_(AST_Defun, false, true);
|
||||
}
|
||||
if (S.token.value == "import" && !is_token(peek(), "punc", "(")) {
|
||||
next();
|
||||
var node = import_();
|
||||
semicolon();
|
||||
return node;
|
||||
}
|
||||
return is_token(peek(), "punc", ":")
|
||||
? labeled_statement()
|
||||
: simple_statement();
|
||||
@@ -1149,17 +1155,13 @@ function parse($TEXT, options) {
|
||||
body : statement()
|
||||
});
|
||||
|
||||
case "import":
|
||||
next();
|
||||
var node = import_();
|
||||
semicolon();
|
||||
return node;
|
||||
|
||||
case "export":
|
||||
if (!is_token(peek(), "punc", "(")) {
|
||||
next();
|
||||
return export_();
|
||||
}
|
||||
}
|
||||
}
|
||||
unexpected();
|
||||
});
|
||||
|
||||
@@ -1320,6 +1322,9 @@ function parse($TEXT, options) {
|
||||
if (in_statement && !name)
|
||||
unexpected();
|
||||
|
||||
if (name && ctor !== AST_Accessor && !(name instanceof AST_SymbolDeclaration))
|
||||
unexpected(prev());
|
||||
|
||||
var args = parameters();
|
||||
var body = _function_body(true, is_generator || is_generator_property, is_async, name, args);
|
||||
return new ctor({
|
||||
@@ -1522,7 +1527,7 @@ function parse($TEXT, options) {
|
||||
}
|
||||
if (is_expand) {
|
||||
if (!is("punc", "]")) {
|
||||
unexpected(); // Must be last element
|
||||
croak("Rest element must be last element");
|
||||
}
|
||||
elements[elements.length - 1] = new AST_Expansion({
|
||||
start: expand_token,
|
||||
@@ -1547,18 +1552,33 @@ function parse($TEXT, options) {
|
||||
} else {
|
||||
expect(",");
|
||||
}
|
||||
if (is("expand", "...")) {
|
||||
is_expand = true;
|
||||
expand_token = S.token;
|
||||
used_parameters.mark_spread(S.token);
|
||||
next();
|
||||
}
|
||||
if (is("name") && (is_token(peek(), "punc") || is_token(peek(), "operator")) && [",", "}", "="].indexOf(peek().value) !== -1) {
|
||||
used_parameters.add_parameter(S.token);
|
||||
var value = new symbol_type({
|
||||
start: S.token,
|
||||
name: S.token.value,
|
||||
end: S.token,
|
||||
});
|
||||
if (is_expand) {
|
||||
elements.push(new AST_Expansion({
|
||||
start: expand_token,
|
||||
expression: value,
|
||||
end: value.end,
|
||||
}));
|
||||
} else {
|
||||
elements.push(new AST_ObjectKeyVal({
|
||||
start: prev(),
|
||||
key: S.token.value,
|
||||
value: new symbol_type({
|
||||
start: S.token,
|
||||
name: S.token.value,
|
||||
end: S.token
|
||||
}),
|
||||
end: prev()
|
||||
value: value,
|
||||
end: value.end,
|
||||
}));
|
||||
}
|
||||
next();
|
||||
} else if (is("punc", "}")) {
|
||||
continue; // Allow trailing hole
|
||||
@@ -1589,7 +1609,12 @@ function parse($TEXT, options) {
|
||||
}));
|
||||
}
|
||||
}
|
||||
if (is("operator", "=")) {
|
||||
if (is_expand) {
|
||||
if (!is("punc", "}")) {
|
||||
croak("Rest element must be last element");
|
||||
}
|
||||
}
|
||||
else if (is("operator", "=")) {
|
||||
used_parameters.mark_default_assignment(S.token);
|
||||
next();
|
||||
elements[elements.length - 1].value = new AST_DefaultAssign({
|
||||
@@ -1855,7 +1880,8 @@ function parse($TEXT, options) {
|
||||
: !no_in && kind === "const" && S.input.has_directive("use strict")
|
||||
? croak("Missing initializer in const declaration") : null,
|
||||
end : prev()
|
||||
})
|
||||
});
|
||||
if (def.name.name == "import") croak("Unexpected token: import");
|
||||
}
|
||||
a.push(def);
|
||||
if (!is("punc", ","))
|
||||
@@ -2143,7 +2169,18 @@ function parse($TEXT, options) {
|
||||
if (!options.strict && is("punc", "}"))
|
||||
// allow trailing comma
|
||||
break;
|
||||
|
||||
start = S.token;
|
||||
if (start.type == "expand") {
|
||||
next();
|
||||
a.push(new AST_Expansion({
|
||||
start: start,
|
||||
expression: expression(false),
|
||||
end: prev(),
|
||||
}));
|
||||
continue;
|
||||
}
|
||||
|
||||
var name = as_property_name();
|
||||
var value;
|
||||
|
||||
|
||||
@@ -85,6 +85,36 @@ function find_builtins(reserved) {
|
||||
}
|
||||
}
|
||||
|
||||
function reserve_quoted_keys(ast, reserved) {
|
||||
function add(name) {
|
||||
push_uniq(reserved, name);
|
||||
}
|
||||
|
||||
ast.walk(new TreeWalker(function(node) {
|
||||
if (node instanceof AST_ObjectKeyVal && node.quote) {
|
||||
add(node.key);
|
||||
} else if (node instanceof AST_ObjectProperty && node.quote) {
|
||||
add(node.key.name);
|
||||
} else if (node instanceof AST_Sub) {
|
||||
addStrings(node.property, add);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
function addStrings(node, add) {
|
||||
node.walk(new TreeWalker(function(node) {
|
||||
if (node instanceof AST_Sequence) {
|
||||
addStrings(node.expressions[node.expressions.length - 1], add);
|
||||
} else if (node instanceof AST_String) {
|
||||
add(node.value);
|
||||
} else if (node instanceof AST_Conditional) {
|
||||
addStrings(node.consequent, add);
|
||||
addStrings(node.alternative, add);
|
||||
}
|
||||
return true;
|
||||
}));
|
||||
}
|
||||
|
||||
function mangle_properties(ast, options) {
|
||||
options = defaults(options, {
|
||||
builtins: false,
|
||||
@@ -109,7 +139,6 @@ function mangle_properties(ast, options) {
|
||||
}
|
||||
|
||||
var regex = options.regex;
|
||||
var keep_quoted = options.keep_quoted;
|
||||
|
||||
// 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'
|
||||
@@ -122,12 +151,11 @@ function mangle_properties(ast, options) {
|
||||
|
||||
var names_to_mangle = [];
|
||||
var unmangleable = [];
|
||||
var to_keep = {};
|
||||
|
||||
// step 1: find candidates to mangle
|
||||
ast.walk(new TreeWalker(function(node){
|
||||
if (node instanceof AST_ObjectKeyVal) {
|
||||
add(node.key, keep_quoted && node.quote);
|
||||
add(node.key);
|
||||
}
|
||||
else if (node instanceof AST_ObjectProperty) {
|
||||
// setter or getter, since KeyVal is handled above
|
||||
@@ -137,17 +165,13 @@ function mangle_properties(ast, options) {
|
||||
add(node.property);
|
||||
}
|
||||
else if (node instanceof AST_Sub) {
|
||||
addStrings(node.property, keep_quoted);
|
||||
}
|
||||
else if (node instanceof AST_ConciseMethod) {
|
||||
add(node.name.name);
|
||||
addStrings(node.property, add);
|
||||
}
|
||||
}));
|
||||
|
||||
// step 2: transform the tree, renaming properties
|
||||
return ast.transform(new TreeTransformer(function(node){
|
||||
if (node instanceof AST_ObjectKeyVal) {
|
||||
if (!(keep_quoted && node.quote))
|
||||
node.key = mangle(node.key);
|
||||
}
|
||||
else if (node instanceof AST_ObjectProperty) {
|
||||
@@ -157,27 +181,9 @@ function mangle_properties(ast, options) {
|
||||
else if (node instanceof AST_Dot) {
|
||||
node.property = mangle(node.property);
|
||||
}
|
||||
else if (node instanceof AST_Sub) {
|
||||
if (!keep_quoted)
|
||||
else if (!options.keep_quoted && node instanceof AST_Sub) {
|
||||
node.property = mangleStrings(node.property);
|
||||
}
|
||||
else if (node instanceof AST_ConciseMethod) {
|
||||
if (should_mangle(node.name.name)) {
|
||||
node.name.name = mangle(node.name.name);
|
||||
}
|
||||
}
|
||||
// else if (node instanceof AST_String) {
|
||||
// if (should_mangle(node.value)) {
|
||||
// AST_Node.warn(
|
||||
// "Found \"{prop}\" property candidate for mangling in an arbitrary string [{file}:{line},{col}]", {
|
||||
// file : node.start.file,
|
||||
// line : node.start.line,
|
||||
// col : node.start.col,
|
||||
// prop : node.value
|
||||
// }
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
}));
|
||||
|
||||
// only function declarations after this line
|
||||
@@ -193,19 +199,13 @@ function mangle_properties(ast, options) {
|
||||
}
|
||||
|
||||
function should_mangle(name) {
|
||||
if (keep_quoted && name in to_keep) return false;
|
||||
if (regex && !regex.test(name)) return false;
|
||||
if (reserved.indexOf(name) >= 0) return false;
|
||||
return cache.props.has(name)
|
||||
|| names_to_mangle.indexOf(name) >= 0;
|
||||
}
|
||||
|
||||
function add(name, keep) {
|
||||
if (keep) {
|
||||
to_keep[name] = true;
|
||||
return;
|
||||
}
|
||||
|
||||
function add(name) {
|
||||
if (can_mangle(name))
|
||||
push_uniq(names_to_mangle, name);
|
||||
|
||||
@@ -225,19 +225,16 @@ function mangle_properties(ast, options) {
|
||||
// debug mode: use a prefix and suffix to preserve readability, e.g. o.foo -> o._$foo$NNN_.
|
||||
var debug_mangled = "_$" + name + "$" + debug_name_suffix + "_";
|
||||
|
||||
if (can_mangle(debug_mangled) && !(keep_quoted && debug_mangled in to_keep)) {
|
||||
if (can_mangle(debug_mangled)) {
|
||||
mangled = debug_mangled;
|
||||
}
|
||||
}
|
||||
|
||||
// either debug mode is off, or it is on and we could not use the mangled name
|
||||
if (!mangled) {
|
||||
// Note: `can_mangle()` does not check if the name collides with the `to_keep` set
|
||||
// (filled with quoted properties when `keep_quoted` is set). Make sure we add this
|
||||
// check so we don't collide with a quoted name.
|
||||
do {
|
||||
mangled = base54(++cache.cname);
|
||||
} while (!can_mangle(mangled) || keep_quoted && mangled in to_keep);
|
||||
} while (!can_mangle(mangled));
|
||||
}
|
||||
|
||||
cache.props.set(name, mangled);
|
||||
@@ -245,32 +242,6 @@ function mangle_properties(ast, options) {
|
||||
return mangled;
|
||||
}
|
||||
|
||||
function addStrings(node, keep) {
|
||||
var out = {};
|
||||
try {
|
||||
(function walk(node){
|
||||
node.walk(new TreeWalker(function(node){
|
||||
if (node instanceof AST_Sequence) {
|
||||
walk(node.expressions[node.expressions.length - 1]);
|
||||
return true;
|
||||
}
|
||||
if (node instanceof AST_String) {
|
||||
add(node.value, keep);
|
||||
return true;
|
||||
}
|
||||
if (node instanceof AST_Conditional) {
|
||||
walk(node.consequent);
|
||||
walk(node.alternative);
|
||||
return true;
|
||||
}
|
||||
throw out;
|
||||
}));
|
||||
})(node);
|
||||
} catch(ex) {
|
||||
if (ex !== out) throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
function mangleStrings(node) {
|
||||
return node.transform(new TreeTransformer(function(node){
|
||||
if (node instanceof AST_Sequence) {
|
||||
|
||||
22
lib/scope.js
22
lib/scope.js
@@ -116,7 +116,7 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
|
||||
var tw = new TreeWalker(function(node, descend){
|
||||
if (node.is_block_scope()) {
|
||||
var save_scope = scope;
|
||||
scope = new AST_Scope(node);
|
||||
node.block_scope = scope = new AST_Scope(node);
|
||||
scope.init_scope_vars(save_scope);
|
||||
if (!(node instanceof AST_Scope)) {
|
||||
scope.uses_with = save_scope.uses_with;
|
||||
@@ -203,6 +203,21 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
|
||||
|| node instanceof AST_SymbolLet
|
||||
|| node instanceof AST_SymbolConst) {
|
||||
var def = ((node instanceof AST_SymbolBlockDeclaration) ? scope : defun).def_variable(node);
|
||||
if (!all(def.orig, function(sym) {
|
||||
if (sym === node) return true;
|
||||
if (node instanceof AST_SymbolBlockDeclaration) {
|
||||
return sym instanceof AST_SymbolLambda;
|
||||
}
|
||||
return !(sym instanceof AST_SymbolLet || sym instanceof AST_SymbolConst);
|
||||
})) {
|
||||
js_error(
|
||||
node.name + " redeclared",
|
||||
node.start.file,
|
||||
node.start.line,
|
||||
node.start.col,
|
||||
node.start.pos
|
||||
);
|
||||
}
|
||||
if (!(node instanceof AST_SymbolFunarg)) mark_export(def, 2);
|
||||
def.destructuring = in_destructuring;
|
||||
if (defun !== scope) {
|
||||
@@ -300,6 +315,7 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
|
||||
ref.reference(options);
|
||||
});
|
||||
node.thedef = def;
|
||||
node.reference(options);
|
||||
return true;
|
||||
}
|
||||
}));
|
||||
@@ -357,7 +373,7 @@ AST_IterationStatement.DEFMETHOD("is_block_scope", return_true);
|
||||
AST_Lambda.DEFMETHOD("init_scope_vars", function(){
|
||||
AST_Scope.prototype.init_scope_vars.apply(this, arguments);
|
||||
this.uses_arguments = false;
|
||||
this.def_variable(new AST_SymbolConst({
|
||||
this.def_variable(new AST_SymbolFunarg({
|
||||
name: "arguments",
|
||||
start: this.start,
|
||||
end: this.end
|
||||
@@ -530,7 +546,7 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options){
|
||||
var mangle_with_block_scope =
|
||||
(!options.ie8 && node instanceof AST_SymbolCatch) ||
|
||||
node instanceof AST_SymbolBlockDeclaration;
|
||||
if (mangle_with_block_scope) {
|
||||
if (mangle_with_block_scope && options.reserved.indexOf(node.name) < 0) {
|
||||
to_mangle.push(node.definition());
|
||||
return;
|
||||
}
|
||||
|
||||
10
package.json
10
package.json
@@ -4,7 +4,7 @@
|
||||
"homepage": "https://github.com/mishoo/UglifyJS2/tree/harmony",
|
||||
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
|
||||
"license": "BSD-2-Clause",
|
||||
"version": "3.0.25",
|
||||
"version": "3.1.3",
|
||||
"engines": {
|
||||
"node": ">=0.8.0"
|
||||
},
|
||||
@@ -26,13 +26,13 @@
|
||||
"LICENSE"
|
||||
],
|
||||
"dependencies": {
|
||||
"commander": "~2.9.0",
|
||||
"commander": "~2.11.0",
|
||||
"source-map": "~0.5.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"acorn": "~5.0.3",
|
||||
"mocha": "~2.3.4",
|
||||
"semver": "~5.3.0"
|
||||
"acorn": "~5.1.1",
|
||||
"mocha": "~3.5.1",
|
||||
"semver": "~5.4.1"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "node test/run-tests.js"
|
||||
|
||||
@@ -213,7 +213,7 @@ no_leading_parentheses: {
|
||||
|
||||
async_identifiers: {
|
||||
options = {
|
||||
arrows: true,
|
||||
unsafe_arrows: true,
|
||||
ecma: 6,
|
||||
}
|
||||
input: {
|
||||
@@ -237,7 +237,7 @@ async_identifiers: {
|
||||
|
||||
async_function_expression: {
|
||||
options = {
|
||||
arrows: true,
|
||||
unsafe_arrows: true,
|
||||
ecma: 6,
|
||||
evaluate: true,
|
||||
side_effects: true,
|
||||
@@ -262,7 +262,7 @@ async_function_expression: {
|
||||
|
||||
issue_27: {
|
||||
options = {
|
||||
arrows: true,
|
||||
unsafe_arrows: true,
|
||||
collapse_vars: true,
|
||||
ecma: 6,
|
||||
unused: true,
|
||||
@@ -283,13 +283,14 @@ issue_27: {
|
||||
|
||||
issue_2105_1: {
|
||||
options = {
|
||||
arrows: true,
|
||||
unsafe_arrows: true,
|
||||
collapse_vars: true,
|
||||
ecma: 6,
|
||||
inline: true,
|
||||
passes: 3,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
unsafe_methods: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
@@ -501,7 +502,7 @@ issue_485_crashing_1530: {
|
||||
|
||||
issue_2084: {
|
||||
options = {
|
||||
arrows: true,
|
||||
unsafe_arrows: true,
|
||||
collapse_vars: true,
|
||||
conditionals: true,
|
||||
ecma: 6,
|
||||
@@ -577,6 +578,7 @@ concise_methods_with_computed_property2: {
|
||||
async_object_literal: {
|
||||
options = {
|
||||
arrows: true,
|
||||
unsafe_arrows: true,
|
||||
ecma: 6,
|
||||
evaluate: true,
|
||||
}
|
||||
@@ -597,3 +599,35 @@ async_object_literal: {
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
issue_2271: {
|
||||
options = {
|
||||
arrows: true,
|
||||
ecma: 6,
|
||||
evaluate: true,
|
||||
unsafe_arrows: false,
|
||||
}
|
||||
input: {
|
||||
var Foo = function() {};
|
||||
Foo.prototype.set = function(value) {
|
||||
this.value = value;
|
||||
return this;
|
||||
}
|
||||
Foo.prototype.print = function() {
|
||||
console.log(this.value);
|
||||
}
|
||||
new Foo().set("PASS").print();
|
||||
}
|
||||
expect: {
|
||||
var Foo = function() {};
|
||||
Foo.prototype.set = function(value) {
|
||||
this.value = value;
|
||||
return this;
|
||||
}
|
||||
Foo.prototype.print = function() {
|
||||
console.log(this.value);
|
||||
}
|
||||
new Foo().set("PASS").print();
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ ascii_only_true: {
|
||||
"\x20\x21\x22\x23 ... \x7d\x7e\x7f\x80\x81 ... \xfe\xff\u0fff\uffff";
|
||||
}
|
||||
}
|
||||
expect_exact: 'function f(){return"\\x000\\x001\\x007\\08\\0"+"\\0\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\b\\t\\n\\v\\f\\r\\x0e\\x0f"+"\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f"+\' !"# ... }~\\x7f\\x80\\x81 ... \\xfe\\xff\\u0fff\\uffff\'}'
|
||||
expect_exact: 'function f(){return"\\x000\\x001\\x007\\x008\\0"+"\\0\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\b\\t\\n\\v\\f\\r\\x0e\\x0f"+"\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f"+\' !"# ... }~\\x7f\\x80\\x81 ... \\xfe\\xff\\u0fff\\uffff\'}'
|
||||
}
|
||||
|
||||
ascii_only_false: {
|
||||
@@ -31,5 +31,5 @@ ascii_only_false: {
|
||||
"\x20\x21\x22\x23 ... \x7d\x7e\x7f\x80\x81 ... \xfe\xff\u0fff\uffff";
|
||||
}
|
||||
}
|
||||
expect_exact: 'function f(){return"\\x000\\x001\\x007\\08\\0"+"\\0\x01\x02\x03\x04\x05\x06\x07\\b\\t\\n\\v\\f\\r\x0e\x0f"+"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"+\' !"# ... }~\x7f\x80\x81 ... \xfe\xff\u0fff\uffff\'}'
|
||||
expect_exact: 'function f(){return"\\x000\\x001\\x007\\x008\\0"+"\\0\x01\x02\x03\x04\x05\x06\x07\\b\\t\\n\\v\\f\\r\x0e\x0f"+"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"+\' !"# ... }~\x7f\x80\x81 ... \xfe\xff\u0fff\uffff\'}'
|
||||
}
|
||||
|
||||
@@ -104,3 +104,65 @@ asm_mixed: {
|
||||
}
|
||||
}
|
||||
|
||||
asm_toplevel: {
|
||||
options = {}
|
||||
input: {
|
||||
"use asm";
|
||||
0.0;
|
||||
function f() {
|
||||
0.0;
|
||||
(function(){
|
||||
0.0;
|
||||
});
|
||||
}
|
||||
0.0;
|
||||
}
|
||||
expect_exact: '"use asm";0.0;function f(){0.0;(function(){0.0})}0.0;'
|
||||
}
|
||||
|
||||
asm_function_expression: {
|
||||
options = {}
|
||||
input: {
|
||||
0.0;
|
||||
var a = function() {
|
||||
"use asm";
|
||||
0.0;
|
||||
}
|
||||
function f() {
|
||||
0.0;
|
||||
return function(){
|
||||
"use asm";
|
||||
0.0;
|
||||
}
|
||||
0.0;
|
||||
}
|
||||
0.0;
|
||||
}
|
||||
expect_exact: '0;var a=function(){"use asm";0.0};function f(){0;return function(){"use asm";0.0};0}0;'
|
||||
}
|
||||
|
||||
asm_nested_functions: {
|
||||
options = {}
|
||||
input: {
|
||||
0.0;
|
||||
function a() {
|
||||
"use asm";
|
||||
0.0;
|
||||
}
|
||||
0.0;
|
||||
function b() {
|
||||
0.0;
|
||||
function c(){
|
||||
"use asm";
|
||||
0.0;
|
||||
}
|
||||
0.0;
|
||||
function d(){
|
||||
0.0;
|
||||
}
|
||||
0.0;
|
||||
}
|
||||
0.0;
|
||||
}
|
||||
expect_exact: '0;function a(){"use asm";0.0}0;function b(){0;function c(){"use asm";0.0}0;function d(){0}0}0;'
|
||||
}
|
||||
|
||||
@@ -2548,3 +2548,250 @@ duplicate_argname: {
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_2250_1: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
conditionals: true,
|
||||
reduce_vars: true,
|
||||
}
|
||||
input: {
|
||||
function f(x) {
|
||||
if (x) {
|
||||
const a = foo();
|
||||
x(a);
|
||||
}
|
||||
}
|
||||
function g(x) {
|
||||
if (x) {
|
||||
let a = foo();
|
||||
x(a);
|
||||
}
|
||||
}
|
||||
function h(x) {
|
||||
if (x) {
|
||||
var a = foo();
|
||||
x(a);
|
||||
}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f(x) {
|
||||
x && x(foo());
|
||||
}
|
||||
function g(x) {
|
||||
x && x(foo());
|
||||
}
|
||||
function h(x) {
|
||||
x && x(foo());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
issue_2250_2: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
passes: 2,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
{
|
||||
const foo = function(){};
|
||||
foo(bar());
|
||||
}
|
||||
{
|
||||
let foo = function(){};
|
||||
foo(bar());
|
||||
}
|
||||
{
|
||||
var foo = function(){};
|
||||
foo(bar());
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
bar();
|
||||
bar();
|
||||
bar();
|
||||
}
|
||||
}
|
||||
|
||||
issue_2298: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
!function() {
|
||||
function f() {
|
||||
var a = undefined;
|
||||
var undefined = a++;
|
||||
try {
|
||||
!function g(b) {
|
||||
b[1] = "foo";
|
||||
}();
|
||||
console.log("FAIL");
|
||||
} catch (e) {
|
||||
console.log("PASS");
|
||||
}
|
||||
}
|
||||
f();
|
||||
}();
|
||||
}
|
||||
expect: {
|
||||
!function() {
|
||||
(function() {
|
||||
var a = undefined;
|
||||
var undefined = a++;
|
||||
try {
|
||||
!function(b) {
|
||||
(void 0)[1] = "foo";
|
||||
}();
|
||||
console.log("FAIL");
|
||||
} catch (e) {
|
||||
console.log("PASS");
|
||||
}
|
||||
})();
|
||||
}();
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_2313_1: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
conditionals: true,
|
||||
}
|
||||
input: {
|
||||
var a = 0, b = 0;
|
||||
var foo = {
|
||||
get c() {
|
||||
a++;
|
||||
return 42;
|
||||
},
|
||||
set c(c) {
|
||||
b++;
|
||||
},
|
||||
d: function() {
|
||||
this.c++;
|
||||
if (this.c) console.log(a, b);
|
||||
}
|
||||
}
|
||||
foo.d();
|
||||
}
|
||||
expect: {
|
||||
var a = 0, b = 0;
|
||||
var foo = {
|
||||
get c() {
|
||||
a++;
|
||||
return 42;
|
||||
},
|
||||
set c(c) {
|
||||
b++;
|
||||
},
|
||||
d: function() {
|
||||
this.c++;
|
||||
this.c && console.log(a, b);
|
||||
}
|
||||
}
|
||||
foo.d();
|
||||
}
|
||||
expect_stdout: "2 1"
|
||||
}
|
||||
|
||||
issue_2313_2: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
}
|
||||
input: {
|
||||
var c = 0;
|
||||
!function a() {
|
||||
a && c++;
|
||||
var a = 0;
|
||||
a && c++;
|
||||
}();
|
||||
console.log(c);
|
||||
}
|
||||
expect: {
|
||||
var c = 0;
|
||||
!function a() {
|
||||
a && c++;
|
||||
var a = 0;
|
||||
a && c++;
|
||||
}();
|
||||
console.log(c);
|
||||
}
|
||||
expect_stdout: "0"
|
||||
}
|
||||
|
||||
issue_2319_1: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function(a) {
|
||||
return a;
|
||||
}(!function() {
|
||||
return this;
|
||||
}()));
|
||||
}
|
||||
expect: {
|
||||
console.log(function(a) {
|
||||
return !function() {
|
||||
return this;
|
||||
}();
|
||||
}());
|
||||
}
|
||||
expect_stdout: "false"
|
||||
}
|
||||
|
||||
issue_2319_2: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function(a) {
|
||||
"use strict";
|
||||
return a;
|
||||
}(!function() {
|
||||
return this;
|
||||
}()));
|
||||
}
|
||||
expect: {
|
||||
console.log(function(a) {
|
||||
"use strict";
|
||||
return a;
|
||||
}(!function() {
|
||||
return this;
|
||||
}()));
|
||||
}
|
||||
expect_stdout: "false"
|
||||
}
|
||||
|
||||
issue_2319_3: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
"use strict";
|
||||
console.log(function(a) {
|
||||
return a;
|
||||
}(!function() {
|
||||
return this;
|
||||
}()));
|
||||
}
|
||||
expect: {
|
||||
"use strict";
|
||||
console.log(function(a) {
|
||||
return !function() {
|
||||
return this;
|
||||
}();
|
||||
}());
|
||||
}
|
||||
expect_stdout: "true"
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ concat_1: {
|
||||
var c = 1 + x() + 2 + "boo";
|
||||
var d = 1 + x() + 2 + 3 + "boo";
|
||||
var e = 1 + x() + 2 + "X3boo";
|
||||
var f = "\x00360\08\0";
|
||||
var f = "\x00360\x008\0";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -388,18 +388,54 @@ issue_2233_1: {
|
||||
Array.isArray;
|
||||
Boolean;
|
||||
console.log;
|
||||
Date;
|
||||
decodeURI;
|
||||
decodeURIComponent;
|
||||
encodeURI;
|
||||
encodeURIComponent;
|
||||
Error.name;
|
||||
escape;
|
||||
eval;
|
||||
EvalError;
|
||||
Function.length;
|
||||
isFinite;
|
||||
isNaN;
|
||||
JSON;
|
||||
Math.random;
|
||||
Number.isNaN;
|
||||
parseFloat;
|
||||
parseInt;
|
||||
RegExp;
|
||||
Object.defineProperty;
|
||||
String.fromCharCode;
|
||||
RangeError;
|
||||
ReferenceError;
|
||||
SyntaxError;
|
||||
TypeError;
|
||||
unescape;
|
||||
URIError;
|
||||
}
|
||||
expect: {}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
global_timeout_and_interval_symbols: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
side_effects: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
// These global symbols do not exist in the test sandbox
|
||||
// and must be tested separately.
|
||||
clearInterval;
|
||||
clearTimeout;
|
||||
setInterval;
|
||||
setTimeout;
|
||||
}
|
||||
expect: {}
|
||||
}
|
||||
|
||||
issue_2233_2: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
@@ -456,3 +492,71 @@ issue_2233_3: {
|
||||
UndeclaredGlobal;
|
||||
}
|
||||
}
|
||||
|
||||
global_fns: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
Boolean(1, 2);
|
||||
decodeURI(1, 2);
|
||||
decodeURIComponent(1, 2);
|
||||
Date(1, 2);
|
||||
encodeURI(1, 2);
|
||||
encodeURIComponent(1, 2);
|
||||
Error(1, 2);
|
||||
escape(1, 2);
|
||||
EvalError(1, 2);
|
||||
isFinite(1, 2);
|
||||
isNaN(1, 2);
|
||||
Number(1, 2);
|
||||
Object(1, 2);
|
||||
parseFloat(1, 2);
|
||||
parseInt(1, 2);
|
||||
RangeError(1, 2);
|
||||
ReferenceError(1, 2);
|
||||
String(1, 2);
|
||||
SyntaxError(1, 2);
|
||||
TypeError(1, 2);
|
||||
unescape(1, 2);
|
||||
URIError(1, 2);
|
||||
try {
|
||||
Function(1, 2);
|
||||
} catch (e) {
|
||||
console.log(e.name);
|
||||
}
|
||||
try {
|
||||
RegExp(1, 2);
|
||||
} catch (e) {
|
||||
console.log(e.name);
|
||||
}
|
||||
try {
|
||||
Array(NaN);
|
||||
} catch (e) {
|
||||
console.log(e.name);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
try {
|
||||
Function(1, 2);
|
||||
} catch (e) {
|
||||
console.log(e.name);
|
||||
}
|
||||
try {
|
||||
RegExp(1, 2);
|
||||
} catch (e) {
|
||||
console.log(e.name);
|
||||
}
|
||||
try {
|
||||
Array(NaN);
|
||||
} catch (e) {
|
||||
console.log(e.name);
|
||||
}
|
||||
}
|
||||
expect_stdout: [
|
||||
"SyntaxError",
|
||||
"SyntaxError",
|
||||
"RangeError",
|
||||
]
|
||||
}
|
||||
|
||||
@@ -65,10 +65,10 @@ nested_destructuring_objects: {
|
||||
}
|
||||
input: {
|
||||
const [{a},b] = c;
|
||||
let [{a},b] = c;
|
||||
var [{a},b] = c;
|
||||
let [{d},e] = f;
|
||||
var [{g},h] = i;
|
||||
}
|
||||
expect_exact: 'const[{a},b]=c;let[{a},b]=c;var[{a},b]=c;';
|
||||
expect_exact: 'const[{a},b]=c;let[{d},e]=f;var[{g},h]=i;';
|
||||
}
|
||||
|
||||
destructuring_constdef_in_loops: {
|
||||
@@ -274,8 +274,8 @@ reduce_vars: {
|
||||
var {aa, bb: {cc, dd}} = {aa:1, bb: {cc:2, dd: 3}};
|
||||
({aa, bb: {cc, dd}} = {aa:1, bb: {cc:2, dd: 3}});
|
||||
const [{a},b] = c;
|
||||
let [{a},b] = c;
|
||||
var [{a},b] = c;
|
||||
let [{d},e] = f;
|
||||
var [{g},h] = i;
|
||||
[{a},b] = c;
|
||||
for (const [x,y] in pairs);
|
||||
for (let [x,y] in pairs);
|
||||
@@ -292,8 +292,8 @@ reduce_vars: {
|
||||
var {aa, bb: {cc, dd}} = {aa:1, bb: {cc:2, dd: 3}};
|
||||
({aa, bb: {cc, dd}} = {aa:1, bb: {cc:2, dd: 3}});
|
||||
const [{a},b] = c;
|
||||
let [{a},b] = c;
|
||||
var [{a},b] = c;
|
||||
let [{d},e] = f;
|
||||
var [{g},h] = i;
|
||||
[{a},b] = c;
|
||||
for (const [x,y] in pairs);
|
||||
for (let [x,y] in pairs);
|
||||
|
||||
@@ -1513,3 +1513,25 @@ issue_2226_3: {
|
||||
}
|
||||
expect_stdout: "3"
|
||||
}
|
||||
|
||||
issue_2288: {
|
||||
options = {
|
||||
unused: true,
|
||||
}
|
||||
beautify = {
|
||||
beautify: true,
|
||||
}
|
||||
input: {
|
||||
function foo(o) {
|
||||
for (var j = o.a, i = 0; i < 0; i++);
|
||||
for (var i = 0; i < 0; i++);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function foo(o) {
|
||||
o.a;
|
||||
for (i = 0; i < 0; i++);
|
||||
for (var i = 0; i < 0; i++);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,3 +26,46 @@ expand_parameters: {
|
||||
expect_exact: "(function(a,...b){});(function(...args){});"
|
||||
}
|
||||
|
||||
avoid_spread_in_ternary: {
|
||||
options = {
|
||||
comparisons: true,
|
||||
conditionals: true,
|
||||
evaluate: true,
|
||||
}
|
||||
input: {
|
||||
function print(...x) {
|
||||
console.log(...x);
|
||||
}
|
||||
var a = [1, 2], b = [3, 4];
|
||||
|
||||
if (Math)
|
||||
print(a);
|
||||
else
|
||||
print(b);
|
||||
|
||||
if (Math)
|
||||
print(...a);
|
||||
else
|
||||
print(b);
|
||||
|
||||
if (Math.no_such_property)
|
||||
print(a);
|
||||
else
|
||||
print(...b);
|
||||
}
|
||||
expect: {
|
||||
function print(...x) {
|
||||
console.log(...x);
|
||||
}
|
||||
var a = [ 1, 2 ], b = [ 3, 4 ];
|
||||
print(Math ? a : b);
|
||||
Math ? print(...a) : print(b);
|
||||
Math.no_such_property ? print(a) : print(...b);
|
||||
}
|
||||
expect_stdout: [
|
||||
"[ 1, 2 ]",
|
||||
"1 2",
|
||||
"3 4",
|
||||
]
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
@@ -226,3 +226,27 @@ keyword_valid_3: {
|
||||
export { default as default } from "module.js";
|
||||
}
|
||||
}
|
||||
|
||||
dynamic_import: {
|
||||
mangle = {
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
import traditional from './traditional.js';
|
||||
function imp(x) {
|
||||
return import(x);
|
||||
}
|
||||
import("module_for_side_effects.js");
|
||||
let dynamic = import("some/module.js");
|
||||
dynamic.foo();
|
||||
}
|
||||
expect: {
|
||||
import o from "./traditional.js";
|
||||
function t(o) {
|
||||
return import(o);
|
||||
}
|
||||
import("module_for_side_effects.js");
|
||||
let r = import("some/module.js");
|
||||
r.foo();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -211,13 +211,13 @@ export_statement: {
|
||||
}
|
||||
input: {
|
||||
export default 1 + 2;
|
||||
export var foo = 4;
|
||||
export let foo = 6;
|
||||
export const foo = 6;
|
||||
export function foo() {};
|
||||
export class foo { };
|
||||
export var a = 4;
|
||||
export let b = 6;
|
||||
export const c = 6;
|
||||
export function d() {};
|
||||
export class e {};
|
||||
}
|
||||
expect_exact: "export default 3;export var foo=4;export let foo=6;export const foo=6;export function foo(){};export class foo{};"
|
||||
expect_exact: "export default 3;export var a=4;export let b=6;export const c=6;export function d(){};export class e{};"
|
||||
}
|
||||
|
||||
export_default_object_expression: {
|
||||
@@ -695,3 +695,147 @@ export_default_class_decl: {
|
||||
}
|
||||
expect_exact: "export default class Car{};export class Cab{};"
|
||||
}
|
||||
|
||||
object_rest_spread: {
|
||||
mangle = {
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var { w: w1, ...V } = { w: 7, x: 1, y: 2 }; console.log(w1, V);
|
||||
let { w: w2, ...L } = { w: 8, x: 3, y: 4 }; console.log(w2, L);
|
||||
const { w: w3, ...C } = { w: 9, x: 5, y: 6 }; console.log(w3, C);
|
||||
|
||||
let b;
|
||||
({ b, ...V } = { a: 1, b: 2, c: 3 }); console.log(V);
|
||||
({ b, ...L } = { a: 4, b: 5, c: 6 }); console.log(L);
|
||||
|
||||
(function({ y, ...p }){ console.log(p); })({ x: 1, y: 2, z: 3 });
|
||||
(({ y, ...p }) => { console.log(p); })({ x: 4, y: 5, z: 6 });
|
||||
|
||||
const T = { a: 1, b: 2 }; console.log({ ...T, w: 0, ...{}, ...L, ...{K: 9} });
|
||||
}
|
||||
expect: {
|
||||
var { w: o, ...l } = { w: 7, x: 1, y: 2 }; console.log(o, l);
|
||||
let { w: c, ...n } = { w: 8, x: 3, y: 4 }; console.log(c, n);
|
||||
const { w: e, ...s } = { w: 9, x: 5, y: 6 }; console.log(e, s);
|
||||
|
||||
let g;
|
||||
({ b: g, ...l } = { a: 1, b: 2, c: 3 }); console.log(l);
|
||||
({ b: g, ...n } = { a: 4, b: 5, c: 6 }); console.log(n);
|
||||
|
||||
(function({ y: o, ...l }) { console.log(l); })({ x: 1, y: 2, z: 3 });
|
||||
(({ y: o, ...l }) => { console.log(l); })({ x: 4, y: 5, z: 6 });
|
||||
|
||||
const w = { a: 1, b: 2 }; console.log({ ...w, w: 0, ...{}, ...n, ...{ K: 9 } });
|
||||
}
|
||||
}
|
||||
|
||||
object_spread_unsafe: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
evaluate: true,
|
||||
join_vars: true,
|
||||
passes: 3,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
unsafe: true,
|
||||
unused: true,
|
||||
}
|
||||
mangle = {
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var o1 = { x: 1, y: 2 };
|
||||
var o2 = { x: 3, z: 4 };
|
||||
var cloned = { ...o1 };
|
||||
var merged = { ...o1, ...o2 };
|
||||
console.log(cloned, merged);
|
||||
}
|
||||
expect: {
|
||||
var o = { x: 1, y: 2 }, l = { ...o }, x = { ...o, ...{ x: 3, z: 4 } };
|
||||
console.log(l, x);
|
||||
}
|
||||
}
|
||||
|
||||
array_spread_of_sequence: {
|
||||
mangle = {
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var a = [1];
|
||||
console.log([...(a, a)]);
|
||||
console.log([...a, a]);
|
||||
console.log([...(a || a)]);
|
||||
console.log([...a || a]);
|
||||
}
|
||||
expect: {
|
||||
var o = [1];
|
||||
console.log([...(o, o)]);
|
||||
console.log([...o, o]);
|
||||
console.log([...o || o]);
|
||||
console.log([...o || o]);
|
||||
}
|
||||
expect_stdout: [
|
||||
"[ 1 ]",
|
||||
"[ 1, [ 1 ] ]",
|
||||
"[ 1 ]",
|
||||
"[ 1 ]",
|
||||
]
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
object_spread_of_sequence: {
|
||||
mangle = {
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var a = {x: 1};
|
||||
console.log({ ...(a, a) });
|
||||
console.log({ ...a, a });
|
||||
console.log({ ...(a || a) });
|
||||
console.log({ ...a || a });
|
||||
}
|
||||
expect: {
|
||||
var o = { x: 1 };
|
||||
console.log({ ...(o, o) });
|
||||
console.log({ ...o, a: o });
|
||||
console.log({ ...o || o });
|
||||
console.log({ ...o || o });
|
||||
}
|
||||
}
|
||||
|
||||
// issue 2316
|
||||
class_name_can_be_preserved_with_reserved: {
|
||||
mangle = {
|
||||
reserved: [ "Foo" ],
|
||||
}
|
||||
input: {
|
||||
function x() {
|
||||
class Foo {}
|
||||
Foo.bar;
|
||||
class Bar {}
|
||||
Bar.foo;
|
||||
}
|
||||
function y() {
|
||||
var Foo = class Foo {};
|
||||
Foo.bar;
|
||||
var Bar = class Bar {};
|
||||
Bar.bar;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function x() {
|
||||
class Foo {}
|
||||
Foo.bar;
|
||||
class a {}
|
||||
a.foo;
|
||||
}
|
||||
function y() {
|
||||
var Foo = class Foo {};
|
||||
Foo.bar;
|
||||
var a = class a {};
|
||||
a.bar;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,3 +88,24 @@ sequences_funs: {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
issue_2295: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
hoist_vars: true,
|
||||
}
|
||||
input: {
|
||||
function foo(o) {
|
||||
var a = o.a;
|
||||
if (a) return a;
|
||||
var a = 1;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function foo(o) {
|
||||
var a = o.a;
|
||||
if (a) return a;
|
||||
a = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,6 +96,13 @@ pure_function_calls_toplevel: {
|
||||
})();
|
||||
})();
|
||||
|
||||
// pure top-level calls will be dropped regardless of the leading comments position
|
||||
var MyClass = /*#__PURE__*//*@class*/(function(){
|
||||
function MyClass() {}
|
||||
MyClass.prototype.method = function() {};
|
||||
return MyClass;
|
||||
})();
|
||||
|
||||
// comment #__PURE__ comment
|
||||
bar(), baz(), quux();
|
||||
a.b(), /* @__PURE__ */ c.d.e(), f.g();
|
||||
@@ -110,10 +117,12 @@ pure_function_calls_toplevel: {
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:92,37]",
|
||||
"WARN: Dropping unused variable iife2 [test/compress/issue-1261.js:92,16]",
|
||||
"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:90,8]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:100,8]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:101,31]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:107,8]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:108,31]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:84,33]",
|
||||
"WARN: Dropping unused variable iife1 [test/compress/issue-1261.js:84,12]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:100,45]",
|
||||
"WARN: Dropping unused variable MyClass [test/compress/issue-1261.js:100,12]",
|
||||
]
|
||||
}
|
||||
|
||||
@@ -148,29 +157,29 @@ should_warn: {
|
||||
baz();
|
||||
}
|
||||
expect_warnings: [
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:128,61]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:128,23]",
|
||||
"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:128,23]",
|
||||
"WARN: Boolean || always true [test/compress/issue-1261.js:129,23]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:129,23]",
|
||||
"WARN: Condition always true [test/compress/issue-1261.js:129,23]",
|
||||
"WARN: Condition left of || always true [test/compress/issue-1261.js:130,8]",
|
||||
"WARN: Condition always true [test/compress/issue-1261.js:130,8]",
|
||||
"WARN: Boolean && always false [test/compress/issue-1261.js:131,23]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:131,23]",
|
||||
"WARN: Condition always false [test/compress/issue-1261.js:131,23]",
|
||||
"WARN: Condition left of && always false [test/compress/issue-1261.js:132,8]",
|
||||
"WARN: Condition always false [test/compress/issue-1261.js:132,8]",
|
||||
"WARN: + in boolean context always true [test/compress/issue-1261.js:133,23]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:133,23]",
|
||||
"WARN: Condition always true [test/compress/issue-1261.js:133,23]",
|
||||
"WARN: + in boolean context always true [test/compress/issue-1261.js:134,8]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:134,31]",
|
||||
"WARN: Condition always true [test/compress/issue-1261.js:134,8]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:135,23]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:136,24]",
|
||||
"WARN: Condition always true [test/compress/issue-1261.js:136,8]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:137,31]",
|
||||
"WARN: Condition always false [test/compress/issue-1261.js:137,8]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:137,61]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:137,23]",
|
||||
"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:137,23]",
|
||||
"WARN: Boolean || always true [test/compress/issue-1261.js:138,23]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:138,23]",
|
||||
"WARN: Condition always true [test/compress/issue-1261.js:138,23]",
|
||||
"WARN: Condition left of || always true [test/compress/issue-1261.js:139,8]",
|
||||
"WARN: Condition always true [test/compress/issue-1261.js:139,8]",
|
||||
"WARN: Boolean && always false [test/compress/issue-1261.js:140,23]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:140,23]",
|
||||
"WARN: Condition always false [test/compress/issue-1261.js:140,23]",
|
||||
"WARN: Condition left of && always false [test/compress/issue-1261.js:141,8]",
|
||||
"WARN: Condition always false [test/compress/issue-1261.js:141,8]",
|
||||
"WARN: + in boolean context always true [test/compress/issue-1261.js:142,23]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:142,23]",
|
||||
"WARN: Condition always true [test/compress/issue-1261.js:142,23]",
|
||||
"WARN: + in boolean context always true [test/compress/issue-1261.js:143,8]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:143,31]",
|
||||
"WARN: Condition always true [test/compress/issue-1261.js:143,8]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:144,23]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:145,24]",
|
||||
"WARN: Condition always true [test/compress/issue-1261.js:145,8]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:146,31]",
|
||||
"WARN: Condition always false [test/compress/issue-1261.js:146,8]",
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
issue_1321_no_debug: {
|
||||
mangle_props = {
|
||||
keep_quoted: true
|
||||
mangle = {
|
||||
properties: {
|
||||
keep_quoted: true,
|
||||
},
|
||||
}
|
||||
input: {
|
||||
var x = {};
|
||||
@@ -10,17 +12,19 @@ issue_1321_no_debug: {
|
||||
}
|
||||
expect: {
|
||||
var x = {};
|
||||
x.o = 1;
|
||||
x["a"] = 2 * x.o;
|
||||
console.log(x.o, x["a"]);
|
||||
x.x = 1;
|
||||
x["a"] = 2 * x.x;
|
||||
console.log(x.x, x["a"]);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
issue_1321_debug: {
|
||||
mangle_props = {
|
||||
mangle = {
|
||||
properties: {
|
||||
debug: "",
|
||||
keep_quoted: true,
|
||||
debug: ""
|
||||
},
|
||||
}
|
||||
input: {
|
||||
var x = {};
|
||||
@@ -30,16 +34,18 @@ issue_1321_debug: {
|
||||
}
|
||||
expect: {
|
||||
var x = {};
|
||||
x.o = 1;
|
||||
x["_$foo$_"] = 2 * x.o;
|
||||
console.log(x.o, x["_$foo$_"]);
|
||||
x.x = 1;
|
||||
x["_$foo$_"] = 2 * x.x;
|
||||
console.log(x.x, x["_$foo$_"]);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
issue_1321_with_quoted: {
|
||||
mangle_props = {
|
||||
keep_quoted: false
|
||||
mangle = {
|
||||
properties: {
|
||||
keep_quoted: false,
|
||||
},
|
||||
}
|
||||
input: {
|
||||
var x = {};
|
||||
@@ -49,9 +55,9 @@ issue_1321_with_quoted: {
|
||||
}
|
||||
expect: {
|
||||
var x = {};
|
||||
x.o = 1;
|
||||
x["x"] = 2 * x.o;
|
||||
console.log(x.o, x["x"]);
|
||||
x.x = 1;
|
||||
x["o"] = 2 * x.x;
|
||||
console.log(x.x, x["o"]);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
mangle_props: {
|
||||
mangle_props = {}
|
||||
mangle = {
|
||||
properties: true,
|
||||
}
|
||||
input: {
|
||||
var obj = {
|
||||
undefined: 1,
|
||||
@@ -54,10 +56,12 @@ mangle_props: {
|
||||
}
|
||||
|
||||
numeric_literal: {
|
||||
mangle = {
|
||||
properties: true,
|
||||
}
|
||||
beautify = {
|
||||
beautify: true,
|
||||
}
|
||||
mangle_props = {}
|
||||
input: {
|
||||
var obj = {
|
||||
0: 0,
|
||||
|
||||
@@ -36,9 +36,10 @@ compress_new_function_with_destruct: {
|
||||
compress_new_function_with_destruct_arrows: {
|
||||
options = {
|
||||
arrows: true,
|
||||
unsafe_arrows: true,
|
||||
unsafe: true,
|
||||
unsafe_Func: true,
|
||||
ecma: 6
|
||||
ecma: 6,
|
||||
}
|
||||
beautify = {
|
||||
ecma: 6
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
dont_reuse_prop: {
|
||||
mangle_props = {
|
||||
regex: /asd/
|
||||
mangle = {
|
||||
properties: {
|
||||
regex: /asd/,
|
||||
},
|
||||
}
|
||||
input: {
|
||||
"aaaaaaaaaabbbbb";
|
||||
@@ -20,8 +22,10 @@ dont_reuse_prop: {
|
||||
}
|
||||
|
||||
unmangleable_props_should_always_be_reserved: {
|
||||
mangle_props = {
|
||||
regex: /asd/
|
||||
mangle = {
|
||||
properties: {
|
||||
regex: /asd/,
|
||||
},
|
||||
}
|
||||
input: {
|
||||
"aaaaaaaaaabbbbb";
|
||||
|
||||
@@ -284,9 +284,11 @@ concise_methods_with_various_property_names: {
|
||||
}
|
||||
|
||||
concise_methods_and_mangle_props: {
|
||||
mangle_props = {
|
||||
regex: /_/
|
||||
};
|
||||
mangle = {
|
||||
properties: {
|
||||
regex: /_/,
|
||||
},
|
||||
}
|
||||
input: {
|
||||
function x() {
|
||||
obj = {
|
||||
@@ -514,6 +516,7 @@ variable_as_computed_property: {
|
||||
prop_func_to_concise_method: {
|
||||
options = {
|
||||
ecma: 6,
|
||||
unsafe_methods: true,
|
||||
}
|
||||
input: {
|
||||
({
|
||||
@@ -542,6 +545,7 @@ prop_func_to_concise_method: {
|
||||
prop_arrow_to_concise_method: {
|
||||
options = {
|
||||
ecma: 6,
|
||||
unsafe_methods: true,
|
||||
}
|
||||
input: {
|
||||
({
|
||||
@@ -590,6 +594,7 @@ concise_method_to_prop_arrow: {
|
||||
prop_func_to_async_concise_method: {
|
||||
options = {
|
||||
ecma: 8,
|
||||
unsafe_methods: true,
|
||||
}
|
||||
input: {
|
||||
({
|
||||
@@ -612,6 +617,7 @@ prop_func_to_async_concise_method: {
|
||||
prop_func_to_concise_method_various: {
|
||||
options = {
|
||||
ecma: 6,
|
||||
unsafe_methods: true,
|
||||
}
|
||||
input: {
|
||||
({
|
||||
@@ -644,6 +650,7 @@ prop_func_to_concise_method_various: {
|
||||
prop_arrows_to_concise_method_various: {
|
||||
options = {
|
||||
ecma: 6,
|
||||
unsafe_methods: true,
|
||||
}
|
||||
input: {
|
||||
({
|
||||
@@ -672,6 +679,7 @@ prop_arrows_to_concise_method_various: {
|
||||
prop_arrow_with_this: {
|
||||
options = {
|
||||
ecma: 6,
|
||||
unsafe_methods: true,
|
||||
}
|
||||
input: {
|
||||
function run(arg) {
|
||||
@@ -709,6 +717,7 @@ prop_arrow_with_this: {
|
||||
prop_arrow_with_nested_this: {
|
||||
options = {
|
||||
ecma: 6,
|
||||
unsafe_methods: true,
|
||||
}
|
||||
input: {
|
||||
function run(arg) {
|
||||
|
||||
@@ -142,11 +142,11 @@ destructuring_arguments_3: {
|
||||
}
|
||||
input: {
|
||||
function fn3({x: {y: {z: {} = 42}}}) {}
|
||||
const { cover = (function () {}), xCover = (0, function() {}) } = {};
|
||||
let { cover = (function () {}), xCover = (0, function() {}) } = {};
|
||||
var { cover = (function () {}), xCover = (0, function() {}) } = {};
|
||||
const { a = (function () {}), b = (0, function() {}) } = {};
|
||||
let { c = (function () {}), d = (0, function() {}) } = {};
|
||||
var { e = (function () {}), f = (0, function() {}) } = {};
|
||||
}
|
||||
expect_exact: "function fn3({x:{y:{z:{}=42}}}){}const{cover=function(){},xCover=(0,function(){})}={};let{cover=function(){},xCover=(0,function(){})}={};var{cover=function(){},xCover=(0,function(){})}={};"
|
||||
expect_exact: "function fn3({x:{y:{z:{}=42}}}){}const{a=function(){},b=(0,function(){})}={};let{c=function(){},d=(0,function(){})}={};var{e=function(){},f=(0,function(){})}={};"
|
||||
}
|
||||
|
||||
default_arguments: {
|
||||
|
||||
@@ -128,9 +128,11 @@ evaluate_string_length: {
|
||||
}
|
||||
|
||||
mangle_properties: {
|
||||
mangle_props = {
|
||||
keep_quoted: false
|
||||
};
|
||||
mangle = {
|
||||
properties: {
|
||||
keep_quoted: false,
|
||||
},
|
||||
}
|
||||
input: {
|
||||
a["foo"] = "bar";
|
||||
a.color = "red";
|
||||
@@ -139,11 +141,11 @@ mangle_properties: {
|
||||
a['run']({color: "blue", foo: "baz"});
|
||||
}
|
||||
expect: {
|
||||
a["o"] = "bar";
|
||||
a.a = "red";
|
||||
x = {r: 10};
|
||||
a.b(x.r, a.o);
|
||||
a['b']({a: "blue", o: "baz"});
|
||||
a["a"] = "bar";
|
||||
a.b = "red";
|
||||
x = {o: 10};
|
||||
a.r(x.o, a.a);
|
||||
a['r']({b: "blue", a: "baz"});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,9 +153,11 @@ mangle_unquoted_properties: {
|
||||
options = {
|
||||
properties: false
|
||||
}
|
||||
mangle_props = {
|
||||
mangle = {
|
||||
properties: {
|
||||
builtins: true,
|
||||
keep_quoted: true
|
||||
keep_quoted: true,
|
||||
},
|
||||
}
|
||||
beautify = {
|
||||
beautify: false,
|
||||
@@ -182,24 +186,26 @@ mangle_unquoted_properties: {
|
||||
function f1() {
|
||||
a["foo"] = "bar";
|
||||
a.color = "red";
|
||||
a.o = 2;
|
||||
x = {"bar": 10, f: 7};
|
||||
a.f = 9;
|
||||
a.r = 2;
|
||||
x = {"bar": 10, b: 7};
|
||||
a.b = 9;
|
||||
}
|
||||
function f2() {
|
||||
a.foo = "bar";
|
||||
a['color'] = "red";
|
||||
x = {bar: 10, f: 7};
|
||||
a.f = 9;
|
||||
a.o = 3;
|
||||
x = {bar: 10, b: 7};
|
||||
a.b = 9;
|
||||
a.r = 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mangle_debug: {
|
||||
mangle_props = {
|
||||
debug: ""
|
||||
};
|
||||
mangle = {
|
||||
properties: {
|
||||
debug: "",
|
||||
},
|
||||
}
|
||||
input: {
|
||||
a.foo = "bar";
|
||||
x = { baz: "ban" };
|
||||
@@ -211,9 +217,11 @@ mangle_debug: {
|
||||
}
|
||||
|
||||
mangle_debug_true: {
|
||||
mangle_props = {
|
||||
debug: true
|
||||
};
|
||||
mangle = {
|
||||
properties: {
|
||||
debug: true,
|
||||
},
|
||||
}
|
||||
input: {
|
||||
a.foo = "bar";
|
||||
x = { baz: "ban" };
|
||||
@@ -225,9 +233,11 @@ mangle_debug_true: {
|
||||
}
|
||||
|
||||
mangle_debug_suffix: {
|
||||
mangle_props = {
|
||||
debug: "XYZ"
|
||||
};
|
||||
mangle = {
|
||||
properties: {
|
||||
debug: "XYZ",
|
||||
},
|
||||
}
|
||||
input: {
|
||||
a.foo = "bar";
|
||||
x = { baz: "ban" };
|
||||
@@ -242,11 +252,13 @@ mangle_debug_suffix_keep_quoted: {
|
||||
options = {
|
||||
properties: false
|
||||
}
|
||||
mangle_props = {
|
||||
mangle = {
|
||||
properties: {
|
||||
builtins: true,
|
||||
keep_quoted: true,
|
||||
debug: "XYZ",
|
||||
reserved: []
|
||||
keep_quoted: true,
|
||||
reserved: [],
|
||||
},
|
||||
}
|
||||
beautify = {
|
||||
beautify: false,
|
||||
@@ -870,3 +882,173 @@ issue_2208_9: {
|
||||
expect_stdout: "42"
|
||||
node_version: ">=4"
|
||||
}
|
||||
|
||||
methods_keep_quoted_true: {
|
||||
options = {
|
||||
arrows: true,
|
||||
ecma: 6,
|
||||
unsafe_methods: true,
|
||||
}
|
||||
mangle = {
|
||||
properties: {
|
||||
keep_quoted: true,
|
||||
},
|
||||
}
|
||||
input: {
|
||||
class C { "Quoted"(){} Unquoted(){} }
|
||||
f1({ "Quoted"(){}, Unquoted(){}, "Prop": 3 });
|
||||
f2({ "Quoted": function(){} });
|
||||
f3({ "Quoted": ()=>{} });
|
||||
}
|
||||
expect_exact: "class C{Quoted(){}o(){}}f1({Quoted(){},o(){},Prop:3});f2({Quoted(){}});f3({Quoted(){}});"
|
||||
}
|
||||
|
||||
methods_keep_quoted_false: {
|
||||
options = {
|
||||
arrows: true,
|
||||
ecma: 6,
|
||||
unsafe_methods: true,
|
||||
}
|
||||
mangle = {
|
||||
properties: {
|
||||
keep_quoted: false,
|
||||
},
|
||||
}
|
||||
input: {
|
||||
class C { "Quoted"(){} Unquoted(){} }
|
||||
f1({ "Quoted"(){}, Unquoted(){}, "Prop": 3 });
|
||||
f2({ "Quoted": function(){} });
|
||||
f3({ "Quoted": ()=>{} });
|
||||
}
|
||||
expect_exact: "class C{o(){}d(){}}f1({o(){},d(){},e:3});f2({o(){}});f3({o(){}});"
|
||||
}
|
||||
|
||||
methods_keep_quoted_from_dead_code: {
|
||||
options = {
|
||||
arrows: true,
|
||||
booleans: true,
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
ecma: 6,
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
unsafe_methods: true,
|
||||
}
|
||||
mangle = {
|
||||
properties: {
|
||||
keep_quoted: true,
|
||||
},
|
||||
}
|
||||
input: {
|
||||
class C { Quoted(){} Unquoted(){} }
|
||||
f1({ Quoted(){}, Unquoted(){}, "Prop": 3 });
|
||||
f2({ Quoted: function(){} });
|
||||
f3({ Quoted: ()=>{} });
|
||||
0 && obj["Quoted"];
|
||||
}
|
||||
expect_exact: "class C{Quoted(){}o(){}}f1({Quoted(){},o(){},Prop:3});f2({Quoted(){}});f3({Quoted(){}});"
|
||||
}
|
||||
|
||||
issue_2256: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
}
|
||||
mangle = {
|
||||
properties: {
|
||||
keep_quoted: true,
|
||||
},
|
||||
}
|
||||
input: {
|
||||
({ "keep": 1 });
|
||||
g.keep = g.change;
|
||||
}
|
||||
expect: {
|
||||
g.keep = g.g;
|
||||
}
|
||||
}
|
||||
|
||||
issue_2321: {
|
||||
options = {
|
||||
ecma: 6,
|
||||
unsafe_methods: false,
|
||||
}
|
||||
input: {
|
||||
var f = {
|
||||
foo: function(){ console.log("foo") },
|
||||
bar() { console.log("bar") }
|
||||
};
|
||||
var foo = new f.foo();
|
||||
var bar = f.bar();
|
||||
}
|
||||
expect: {
|
||||
var f = {
|
||||
foo: function() {
|
||||
console.log("foo");
|
||||
},
|
||||
bar() {
|
||||
console.log("bar");
|
||||
}
|
||||
};
|
||||
var foo = new f.foo();
|
||||
var bar = f.bar();
|
||||
}
|
||||
expect_stdout: [
|
||||
"foo",
|
||||
"bar",
|
||||
]
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
unsafe_methods_regex: {
|
||||
options = {
|
||||
ecma: 6,
|
||||
unsafe_methods: /^[A-Z1]/,
|
||||
}
|
||||
input: {
|
||||
var f = {
|
||||
123: function(){ console.log("123") },
|
||||
foo: function(){ console.log("foo") },
|
||||
bar() { console.log("bar") },
|
||||
Baz: function(){ console.log("baz") },
|
||||
BOO: function(){ console.log("boo") },
|
||||
null: function(){ console.log("null") },
|
||||
undefined: function(){ console.log("undefined") },
|
||||
};
|
||||
f[123]();
|
||||
new f.foo();
|
||||
f.bar();
|
||||
f.Baz();
|
||||
f.BOO();
|
||||
new f.null();
|
||||
new f.undefined();
|
||||
}
|
||||
expect: {
|
||||
var f = {
|
||||
123() { console.log("123") },
|
||||
foo: function(){ console.log("foo") },
|
||||
bar() { console.log("bar"); },
|
||||
Baz() { console.log("baz") },
|
||||
BOO() { console.log("boo") },
|
||||
null: function(){ console.log("null") },
|
||||
undefined: function(){ console.log("undefined") },
|
||||
};
|
||||
f[123]();
|
||||
new f.foo();
|
||||
f.bar();
|
||||
f.Baz();
|
||||
f.BOO();
|
||||
new f.null();
|
||||
new f.undefined();
|
||||
}
|
||||
expect_stdout: [
|
||||
"123",
|
||||
"foo",
|
||||
"bar",
|
||||
"baz",
|
||||
"boo",
|
||||
"null",
|
||||
"undefined",
|
||||
]
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
@@ -385,3 +385,338 @@ set_mutable_2: {
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_2265_1: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
({ ...{} }).p;
|
||||
({ ...g }).p;
|
||||
}
|
||||
expect: {
|
||||
({ ...g }).p;
|
||||
}
|
||||
}
|
||||
|
||||
issue_2265_2: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var a = {
|
||||
get b() {
|
||||
throw 0;
|
||||
}
|
||||
};
|
||||
({...a}).b;
|
||||
}
|
||||
expect: {
|
||||
var a = {
|
||||
get b() {
|
||||
throw 0;
|
||||
}
|
||||
};
|
||||
({...a}).b;
|
||||
}
|
||||
}
|
||||
|
||||
issue_2265_3: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = {
|
||||
set b() {
|
||||
throw 0;
|
||||
}
|
||||
};
|
||||
({...a}).b;
|
||||
}
|
||||
expect: {}
|
||||
}
|
||||
|
||||
issue_2265_4: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = { b: 1 };
|
||||
({...a}).b;
|
||||
}
|
||||
expect: {}
|
||||
}
|
||||
|
||||
issue_2313_1: {
|
||||
options = {
|
||||
cascade: true,
|
||||
conditionals: true,
|
||||
pure_getters: "strict",
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
function x() {
|
||||
console.log(1);
|
||||
return {
|
||||
y: function() {
|
||||
console.log(2);
|
||||
return {
|
||||
z: 0
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
x().y().z++;
|
||||
if (x().y().z) {
|
||||
console.log(3);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function x() {
|
||||
return console.log(1), {
|
||||
y: function() {
|
||||
return console.log(2), {
|
||||
z: 0
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
x().y().z++,
|
||||
x().y().z && console.log(3);
|
||||
}
|
||||
expect_stdout: [
|
||||
"1",
|
||||
"2",
|
||||
"1",
|
||||
"2",
|
||||
]
|
||||
}
|
||||
|
||||
issue_2313_2: {
|
||||
options = {
|
||||
cascade: true,
|
||||
conditionals: true,
|
||||
pure_getters: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
function x() {
|
||||
console.log(1);
|
||||
return {
|
||||
y: function() {
|
||||
console.log(2);
|
||||
return {
|
||||
z: 0
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
x().y().z++;
|
||||
if (x().y().z) {
|
||||
console.log(3);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function x() {
|
||||
return console.log(1), {
|
||||
y: function() {
|
||||
return console.log(2), {
|
||||
z: 0
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
x().y().z++,
|
||||
x().y().z && console.log(3);
|
||||
}
|
||||
expect_stdout: [
|
||||
"1",
|
||||
"2",
|
||||
"1",
|
||||
"2",
|
||||
]
|
||||
}
|
||||
|
||||
issue_2313_3: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
conditionals: true,
|
||||
pure_getters: "strict",
|
||||
}
|
||||
input: {
|
||||
function x() {
|
||||
console.log(1);
|
||||
return {
|
||||
y: function() {
|
||||
console.log(2);
|
||||
return {
|
||||
z: 0
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
x().y().z++;
|
||||
if (x().y().z) {
|
||||
console.log(3);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function x() {
|
||||
console.log(1);
|
||||
return {
|
||||
y: function() {
|
||||
console.log(2);
|
||||
return {
|
||||
z: 0
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
x().y().z++;
|
||||
x().y().z && console.log(3);
|
||||
}
|
||||
expect_stdout: [
|
||||
"1",
|
||||
"2",
|
||||
"1",
|
||||
"2",
|
||||
]
|
||||
}
|
||||
|
||||
issue_2313_4: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
conditionals: true,
|
||||
pure_getters: true,
|
||||
}
|
||||
input: {
|
||||
function x() {
|
||||
console.log(1);
|
||||
return {
|
||||
y: function() {
|
||||
console.log(2);
|
||||
return {
|
||||
z: 0
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
x().y().z++;
|
||||
if (x().y().z) {
|
||||
console.log(3);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function x() {
|
||||
console.log(1);
|
||||
return {
|
||||
y: function() {
|
||||
console.log(2);
|
||||
return {
|
||||
z: 0
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
x().y().z++;
|
||||
x().y().z && console.log(3);
|
||||
}
|
||||
expect_stdout: [
|
||||
"1",
|
||||
"2",
|
||||
"1",
|
||||
"2",
|
||||
]
|
||||
}
|
||||
|
||||
issue_2313_5: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
x().y++;
|
||||
x().y;
|
||||
}
|
||||
expect: {
|
||||
x().y++;
|
||||
x().y;
|
||||
}
|
||||
}
|
||||
|
||||
issue_2313_6: {
|
||||
options = {
|
||||
pure_getters: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
x().y++;
|
||||
x().y;
|
||||
}
|
||||
expect: {
|
||||
x().y++;
|
||||
x();
|
||||
}
|
||||
}
|
||||
|
||||
issue_2313_7: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
conditionals: true,
|
||||
pure_getters: true,
|
||||
}
|
||||
input: {
|
||||
var a = 0, b = 0;
|
||||
class foo {
|
||||
get c() {
|
||||
a++;
|
||||
return 42;
|
||||
}
|
||||
set c(c) {
|
||||
b++;
|
||||
}
|
||||
}
|
||||
class bar extends foo {
|
||||
d() {
|
||||
super.c++;
|
||||
if (super.c) console.log(a, b);
|
||||
}
|
||||
}
|
||||
new bar().d();
|
||||
}
|
||||
expect: {
|
||||
var a = 0, b = 0;
|
||||
class foo {
|
||||
get c() {
|
||||
a++;
|
||||
return 42;
|
||||
}
|
||||
set c(c) {
|
||||
b++;
|
||||
}
|
||||
}
|
||||
class bar extends foo {
|
||||
d() {
|
||||
super.c++;
|
||||
super.c && console.log(a, b);
|
||||
}
|
||||
}
|
||||
new bar().d();
|
||||
}
|
||||
expect_stdout: "2 1"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
@@ -2549,7 +2549,7 @@ issue_1922_2: {
|
||||
expect_stdout: "1"
|
||||
}
|
||||
|
||||
accessor: {
|
||||
accessor_1: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
@@ -2578,6 +2578,89 @@ accessor: {
|
||||
expect_stdout: "1 1"
|
||||
}
|
||||
|
||||
accessor_2: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var A = 1;
|
||||
var B = {
|
||||
get c() {
|
||||
console.log(A);
|
||||
}
|
||||
};
|
||||
B.c;
|
||||
}
|
||||
expect: {
|
||||
({
|
||||
get c() {
|
||||
console.log(1);
|
||||
}
|
||||
}).c;
|
||||
}
|
||||
expect_stdout: "1"
|
||||
}
|
||||
|
||||
method_1: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var a = 1;
|
||||
console.log(new class {
|
||||
a() {
|
||||
a = 2;
|
||||
return a;
|
||||
}
|
||||
}().a(), a);
|
||||
}
|
||||
expect: {
|
||||
var a = 1;
|
||||
console.log(new class {
|
||||
a() {
|
||||
a = 2;
|
||||
return a;
|
||||
}
|
||||
}().a(), a);
|
||||
}
|
||||
expect_stdout: "2 2"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
method_2: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var A = 1;
|
||||
var B = class {
|
||||
c() {
|
||||
console.log(A);
|
||||
}
|
||||
};
|
||||
new B().c();
|
||||
}
|
||||
expect: {
|
||||
new class {
|
||||
c() {
|
||||
console.log(1);
|
||||
}
|
||||
}().c();
|
||||
}
|
||||
expect_stdout: "1"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_2090_1: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
|
||||
@@ -325,3 +325,69 @@ issue_2120_2: {
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_2254_1: {
|
||||
mangle = {
|
||||
ie8: false,
|
||||
}
|
||||
input: {
|
||||
"eeeeee";
|
||||
try {
|
||||
console.log(f("PASS"));
|
||||
} catch (e) {}
|
||||
function f(s) {
|
||||
try {
|
||||
throw "FAIL";
|
||||
} catch (e) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
"eeeeee";
|
||||
try {
|
||||
console.log(f("PASS"));
|
||||
} catch (e) {}
|
||||
function f(e) {
|
||||
try {
|
||||
throw "FAIL";
|
||||
} catch (t) {
|
||||
return e;
|
||||
}
|
||||
}
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_2254_2: {
|
||||
mangle = {
|
||||
ie8: true,
|
||||
}
|
||||
input: {
|
||||
"eeeeee";
|
||||
try {
|
||||
console.log(f("PASS"));
|
||||
} catch (e) {}
|
||||
function f(s) {
|
||||
try {
|
||||
throw "FAIL";
|
||||
} catch (e) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
"eeeeee";
|
||||
try {
|
||||
console.log(f("PASS"));
|
||||
} catch (e) {}
|
||||
function f(t) {
|
||||
try {
|
||||
throw "FAIL";
|
||||
} catch (e) {
|
||||
return t;
|
||||
}
|
||||
}
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
@@ -763,3 +763,44 @@ issue_2062: {
|
||||
}
|
||||
expect_stdout: "1"
|
||||
}
|
||||
|
||||
issue_2313: {
|
||||
options = {
|
||||
cascade: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
var a = 0, b = 0;
|
||||
var foo = {
|
||||
get c() {
|
||||
a++;
|
||||
return 42;
|
||||
},
|
||||
set c(c) {
|
||||
b++;
|
||||
},
|
||||
d: function() {
|
||||
this.c++;
|
||||
if (this.c) console.log(a, b);
|
||||
}
|
||||
}
|
||||
foo.d();
|
||||
}
|
||||
expect: {
|
||||
var a = 0, b = 0;
|
||||
var foo = {
|
||||
get c() {
|
||||
return a++, 42;
|
||||
},
|
||||
set c(c) {
|
||||
b++;
|
||||
},
|
||||
d: function() {
|
||||
if (this.c++, this.c) console.log(a, b);
|
||||
}
|
||||
}
|
||||
foo.d();
|
||||
}
|
||||
expect_stdout: "2 1"
|
||||
}
|
||||
|
||||
@@ -43,15 +43,6 @@ unicode_string_literals: {
|
||||
expect_exact: 'var a="6 length unicode character: \\u{101111}";'
|
||||
}
|
||||
|
||||
// Don't escape identifiers below es6 (or in this case double escaped in expect_exact)
|
||||
unicode_output_es5_surrogates: {
|
||||
beautify = {ascii_only: true, ecma: 5}
|
||||
input: {
|
||||
var \u{10000} = "6 length unicode character: \u{10FFFF}";
|
||||
}
|
||||
expect_exact: 'var \u{10000}="6 length unicode character: \\udbff\\udfff";'
|
||||
}
|
||||
|
||||
check_escape_style: {
|
||||
beautify = {ascii_only: true, ecma: 6}
|
||||
input: {
|
||||
@@ -65,20 +56,6 @@ check_escape_style: {
|
||||
expect_exact: 'var a="\\x01";var \\ua0081="\\x10";var \\u0100="\\u0100";var \\u1000="\\u1000";var \\u{10000}="\\u{10000}";var \\u{2f800}="\\u{100000}";'
|
||||
}
|
||||
|
||||
// Don't escape identifiers below es6, no escaped identifiers support and no \u{} syntax
|
||||
check_escape_style_es5: {
|
||||
beautify = {ascii_only: true, ecma: 5}
|
||||
input: {
|
||||
var a = "\x01";
|
||||
var \ua0081 = "\x10"; // \u0081 only in ID_Continue
|
||||
var \u0100 = "\u0100";
|
||||
var \u1000 = "\u1000";
|
||||
var \u{10000} = "\u{10000}"; // Identifier won't be escaped in es 5.1
|
||||
var \u{2f800} = "\u{100000}"; // Same
|
||||
}
|
||||
expect_exact: 'var a="\\x01";var \\ua0081="\\x10";var \\u0100="\\u0100";var \\u1000="\\u1000";var \ud800\udc00="\\ud800\\udc00";var \ud87e\udc00="\\udbc0\\udc00";'
|
||||
}
|
||||
|
||||
ID_continue_with_surrogate_pair: {
|
||||
beautify = {ascii_only: true, ecma: 6}
|
||||
input: {
|
||||
@@ -103,18 +80,42 @@ non_escape_2_non_escape: {
|
||||
expect_exact: 'var µþ="µþ";'
|
||||
}
|
||||
|
||||
non_escape_2_half_escape1: {
|
||||
beautify = {ascii_only: false, ascii_identifiers: true, ecma: 6}
|
||||
input: {
|
||||
var µþ = "µþ";
|
||||
issue_2242_1: {
|
||||
beautify = {
|
||||
ascii_only: false,
|
||||
}
|
||||
expect_exact: 'var \\u00b5\\u00fe="µþ";'
|
||||
input: {
|
||||
console.log("\ud83d", "\ude00", "\ud83d\ude00", "\ud83d@\ude00");
|
||||
}
|
||||
expect_exact: 'console.log("\\ud83d","\\ude00","\ud83d\ude00","\\ud83d@\\ude00");'
|
||||
}
|
||||
|
||||
non_escape_2_half_escape2: {
|
||||
beautify = {ascii_only: true, ascii_identifiers: false, ecma: 6}
|
||||
issue_2242_2: {
|
||||
beautify = {
|
||||
ascii_only: true,
|
||||
}
|
||||
input: {
|
||||
var µþ = "µþ";
|
||||
console.log("\ud83d", "\ude00", "\ud83d\ude00", "\ud83d@\ude00");
|
||||
}
|
||||
expect_exact: 'var µþ="\\xb5\\xfe";'
|
||||
expect_exact: 'console.log("\\ud83d","\\ude00","\\ud83d\\ude00","\\ud83d@\\ude00");'
|
||||
}
|
||||
|
||||
issue_2242_3: {
|
||||
options = {
|
||||
evaluate: false,
|
||||
}
|
||||
input: {
|
||||
console.log("\ud83d" + "\ude00", "\ud83d" + "@" + "\ude00");
|
||||
}
|
||||
expect_exact: 'console.log("\\ud83d"+"\\ude00","\\ud83d"+"@"+"\\ude00");'
|
||||
}
|
||||
|
||||
issue_2242_4: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
}
|
||||
input: {
|
||||
console.log("\ud83d" + "\ude00", "\ud83d" + "@" + "\ude00");
|
||||
}
|
||||
expect_exact: 'console.log("\ud83d\ude00","\\ud83d@\\ude00");'
|
||||
}
|
||||
@@ -8,6 +8,7 @@ exports["defaults"] = defaults;
|
||||
exports["mangle_properties"] = mangle_properties;
|
||||
exports["minify"] = minify;
|
||||
exports["parse"] = parse;
|
||||
exports["reserve_quoted_keys"] = reserve_quoted_keys;
|
||||
exports["string_template"] = string_template;
|
||||
exports["tokenizer"] = tokenizer;
|
||||
exports["is_identifier"] = is_identifier;
|
||||
|
||||
10
test/input/issue-2310/input.js
Normal file
10
test/input/issue-2310/input.js
Normal file
@@ -0,0 +1,10 @@
|
||||
function foo() {
|
||||
return function() {
|
||||
console.log("PASS");
|
||||
};
|
||||
}
|
||||
|
||||
(function() {
|
||||
var f = foo();
|
||||
f();
|
||||
})();
|
||||
@@ -666,6 +666,25 @@ describe("bin/uglifyjs", function () {
|
||||
return JSON.stringify(map).replace(/"/g, '\\"');
|
||||
}
|
||||
});
|
||||
it("Should include function calls in source map", function(done) {
|
||||
var command = [
|
||||
uglifyjscmd,
|
||||
"test/input/issue-2310/input.js",
|
||||
"-c",
|
||||
"--source-map", "url=inline",
|
||||
].join(" ");
|
||||
|
||||
exec(command, function(err, stdout, stderr) {
|
||||
if (err) throw err;
|
||||
|
||||
assert.strictEqual(stdout, [
|
||||
'function foo(){return function(){console.log("PASS")}}foo()();',
|
||||
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvaW5wdXQvaXNzdWUtMjMxMC9pbnB1dC5qcyJdLCJuYW1lcyI6WyJmb28iLCJjb25zb2xlIiwibG9nIiwiZiJdLCJtYXBwaW5ncyI6IkFBQUEsU0FBU0EsTUFDTCxPQUFPLFdBQ0hDLFFBQVFDLElBQUksU0FLUkYsS0FDUkcifQ==",
|
||||
""
|
||||
].join("\n"));
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should dump AST as JSON", function(done) {
|
||||
var command = uglifyjscmd + " test/input/global_defs/simple.js -mco ast";
|
||||
exec(command, function (err, stdout) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
var assert = require("assert");
|
||||
var uglify = require("../node");
|
||||
|
||||
describe("Export", function() {
|
||||
describe("Export/Import", function() {
|
||||
it("Should parse export directives", function() {
|
||||
var inputs = [
|
||||
['export * from "a.js"', ['*'], "a.js"],
|
||||
@@ -36,4 +36,22 @@ describe("Export", function() {
|
||||
assert.equal(st.module_name.value, filename);
|
||||
}
|
||||
});
|
||||
|
||||
it("Should not parse invalid uses of export", function() {
|
||||
assert.equal(uglify.minify("export").error.message, "Unexpected token: eof (undefined)");
|
||||
assert.equal(uglify.minify("export;").error.message, "Unexpected token: punc (;)");
|
||||
assert.equal(uglify.minify("export();").error.message, "Unexpected token: keyword (export)");
|
||||
assert.equal(uglify.minify("export(1);").error.message, "Unexpected token: keyword (export)");
|
||||
assert.equal(uglify.minify("var export;").error.message, "Name expected");
|
||||
assert.equal(uglify.minify("var export = 1;").error.message, "Name expected");
|
||||
assert.equal(uglify.minify("function f(export){}").error.message, "Invalid function parameter");
|
||||
});
|
||||
|
||||
it("Should not parse invalid uses of import", function() {
|
||||
assert.equal(uglify.minify("import").error.message, "Unexpected token: eof (undefined)");
|
||||
assert.equal(uglify.minify("import;").error.message, "Unexpected token: punc (;)");
|
||||
assert.equal(uglify.minify("var import;").error.message, "Unexpected token: import");
|
||||
assert.equal(uglify.minify("var import = 1;").error.message, "Unexpected token: import");
|
||||
assert.equal(uglify.minify("function f(import){}").error.message, "Unexpected token: name (import)");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -253,13 +253,19 @@ describe("Left-hand side expressions", function () {
|
||||
// Multiple spreads are not allowed in destructuring array
|
||||
expect("[...a, ...b] = [1, 2, 3, 4]", "Spread must the be last element in destructuring array");
|
||||
|
||||
// Spread in obvious object pattern
|
||||
expect("({...a} = foo)", "Unexpected token: expand (...)");
|
||||
// Array spread must be last in destructuring declaration
|
||||
expect("let [ ...x, a ] = o;", "Rest element must be last element");
|
||||
|
||||
// Only one spread per destructuring array declaration
|
||||
expect("let [ a, ...x, ...y ] = o;", "Rest element must be last element");
|
||||
|
||||
// Spread in block should not be allowed
|
||||
expect("{...a} = foo", "Unexpected token: expand (...)");
|
||||
|
||||
// Not in standard yet
|
||||
expect("let foo = {bar: 42}, bar; bar = {...foo}", "Unexpected token: expand (...)");
|
||||
// Object spread must be last in destructuring declaration
|
||||
expect("let { ...x, a } = o;", "Rest element must be last element");
|
||||
|
||||
// Only one spread per destructuring declaration
|
||||
expect("let { a, ...x, ...y } = o;", "Rest element must be last element");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -73,6 +73,13 @@ describe("minify", function() {
|
||||
assert.strictEqual(run_code(compressed), run_code(original));
|
||||
});
|
||||
|
||||
it("should not parse invalid use of reserved words", function() {
|
||||
assert.strictEqual(Uglify.minify("function enum(){}").error, undefined);
|
||||
assert.strictEqual(Uglify.minify("function static(){}").error, undefined);
|
||||
assert.strictEqual(Uglify.minify("function super(){}").error.message, "Unexpected token: name (super)");
|
||||
assert.strictEqual(Uglify.minify("function this(){}").error.message, "Unexpected token: name (this)");
|
||||
});
|
||||
|
||||
describe("keep_quoted_props", function() {
|
||||
it("Should preserve quotes in object literals", function() {
|
||||
var js = 'var foo = {"x": 1, y: 2, \'z\': 3};';
|
||||
@@ -124,6 +131,17 @@ describe("minify", function() {
|
||||
assert.strictEqual(result.code,
|
||||
'a["foo"]="bar",a.a="red",x={"bar":10};');
|
||||
});
|
||||
it("Should not mangle quoted property within dead code", function() {
|
||||
var result = Uglify.minify('({ "keep": 1 }); g.keep = g.change;', {
|
||||
mangle: {
|
||||
properties: {
|
||||
keep_quoted: true
|
||||
}
|
||||
}
|
||||
});
|
||||
if (result.error) throw result.error;
|
||||
assert.strictEqual(result.code, "g.keep=g.g;");
|
||||
});
|
||||
});
|
||||
|
||||
describe("inSourceMap", function() {
|
||||
@@ -280,4 +298,34 @@ describe("minify", function() {
|
||||
assert.strictEqual(result.code, "alert({bar:42});");
|
||||
});
|
||||
});
|
||||
|
||||
describe("duplicated block-scoped declarations", function() {
|
||||
[
|
||||
"let a=1;let a=2;",
|
||||
"let a=1;var a=2;",
|
||||
"var a=1;let a=2;",
|
||||
"let[a]=[1];var a=2;",
|
||||
"let a=1;var[a]=[2];",
|
||||
"let[a]=[1];var[a]=[2];",
|
||||
"const a=1;const a=2;",
|
||||
"const a=1;var a=2;",
|
||||
"var a=1;const a=2;",
|
||||
"const[a]=[1];var a=2;",
|
||||
"const a=1;var[a]=[2];",
|
||||
"const[a]=[1];var[a]=[2];",
|
||||
].forEach(function(code) {
|
||||
it(code, function() {
|
||||
var result = Uglify.minify(code, {
|
||||
compress: false,
|
||||
mangle: false
|
||||
});
|
||||
assert.strictEqual(result.error, undefined);
|
||||
assert.strictEqual(result.code, code);
|
||||
result = Uglify.minify(code);
|
||||
var err = result.error;
|
||||
assert.ok(err instanceof Error);
|
||||
assert.strictEqual(err.stack.split(/\n/)[0], "SyntaxError: a redeclared");
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -61,9 +61,9 @@ describe("String literals", function() {
|
||||
var tests = [
|
||||
['"\\76";', ';">";'],
|
||||
['"\\0"', '"\\0";'],
|
||||
['"\\08"', '"\\08";'],
|
||||
['"\\008"', '"\\08";'],
|
||||
['"\\0008"', '"\\08";'],
|
||||
['"\\08"', '"\\x008";'],
|
||||
['"\\008"', '"\\x008";'],
|
||||
['"\\0008"', '"\\x008";'],
|
||||
['"use strict" === "use strict";\n"\\76";', '"use strict"==="use strict";">";'],
|
||||
['"use\\\n strict";\n"\\07";', ';"use strict";"\07";']
|
||||
];
|
||||
@@ -75,7 +75,44 @@ describe("String literals", function() {
|
||||
});
|
||||
|
||||
it("Should not throw error when digit is 8 or 9", function() {
|
||||
assert.equal(UglifyJS.parse('"use strict";"\\08"').print_to_string(), '"use strict";"\\08";');
|
||||
assert.equal(UglifyJS.parse('"use strict";"\\09"').print_to_string(), '"use strict";"\\09";');
|
||||
assert.equal(UglifyJS.parse('"use strict";"\\08"').print_to_string(), '"use strict";"\\x008";');
|
||||
assert.equal(UglifyJS.parse('"use strict";"\\09"').print_to_string(), '"use strict";"\\x009";');
|
||||
});
|
||||
|
||||
it("Should not unescape unpaired surrogates", function() {
|
||||
var code = [];
|
||||
for (var i = 0; i <= 0xF; i++) {
|
||||
code.push("\\u000" + i.toString(16));
|
||||
}
|
||||
for (;i <= 0xFF; i++) {
|
||||
code.push("\\u00" + i.toString(16));
|
||||
}
|
||||
for (;i <= 0xFFF; i++) {
|
||||
code.push("\\u0" + i.toString(16));
|
||||
}
|
||||
for (; i <= 0xFFFF; i++) {
|
||||
code.push("\\u" + i.toString(16));
|
||||
}
|
||||
code = '"' + code.join() + '"';
|
||||
var normal = UglifyJS.minify(code, {
|
||||
compress: false,
|
||||
mangle: false,
|
||||
output: {
|
||||
ascii_only: false
|
||||
}
|
||||
});
|
||||
if (normal.error) throw normal.error;
|
||||
assert.ok(code.length > normal.code.length);
|
||||
assert.strictEqual(eval(code), eval(normal.code));
|
||||
var ascii = UglifyJS.minify(code, {
|
||||
compress: false,
|
||||
mangle: false,
|
||||
output: {
|
||||
ascii_only: false
|
||||
}
|
||||
});
|
||||
if (ascii.error) throw ascii.error;
|
||||
assert.ok(code.length > ascii.code.length);
|
||||
assert.strictEqual(eval(code), eval(ascii.code));
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
var assert = require("assert");
|
||||
var semver = require("semver");
|
||||
var uglify = require("../node");
|
||||
|
||||
describe("Unicode", function() {
|
||||
@@ -138,8 +139,34 @@ describe("Unicode", function() {
|
||||
|
||||
it("Should parse raw characters correctly", function() {
|
||||
var ast = uglify.parse('console.log("\\udbff");');
|
||||
assert.strictEqual(ast.print_to_string(), 'console.log("\udbff");');
|
||||
assert.strictEqual(ast.print_to_string(), 'console.log("\\udbff");');
|
||||
ast = uglify.parse(ast.print_to_string());
|
||||
assert.strictEqual(ast.print_to_string(), 'console.log("\udbff");');
|
||||
assert.strictEqual(ast.print_to_string(), 'console.log("\\udbff");');
|
||||
});
|
||||
|
||||
if (semver.satisfies(process.version, ">=4")) {
|
||||
it("Should not unescape unpaired surrogates", function() {
|
||||
this.timeout(5000);
|
||||
var code = [];
|
||||
for (var i = 0; i <= 0x20001; i++) {
|
||||
code.push("\\u{" + i.toString(16) + "}");
|
||||
}
|
||||
code = '"' + code.join() + '"';
|
||||
[true, false].forEach(function(ascii_only) {
|
||||
[5, 6].forEach(function(ecma) {
|
||||
var result = uglify.minify(code, {
|
||||
compress: false,
|
||||
mangle: false,
|
||||
output: {
|
||||
ascii_only: ascii_only
|
||||
},
|
||||
ecma: ecma
|
||||
});
|
||||
if (result.error) throw result.error;
|
||||
if (ecma > 5) assert.ok(code.length > result.code.length);
|
||||
assert.strictEqual(eval(code), eval(result.code));
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -111,18 +111,22 @@ function run_compress_tests() {
|
||||
};
|
||||
if (!options.warnings) options.warnings = true;
|
||||
}
|
||||
if (test.mangle && test.mangle.properties && test.mangle.properties.keep_quoted) {
|
||||
var quoted_props = test.mangle.properties.reserved;
|
||||
if (!Array.isArray(quoted_props)) quoted_props = [];
|
||||
test.mangle.properties.reserved = quoted_props;
|
||||
U.reserve_quoted_keys(input, quoted_props);
|
||||
}
|
||||
var cmp = new U.Compressor(options, true);
|
||||
var output = cmp.compress(input);
|
||||
output.figure_out_scope(test.mangle);
|
||||
if (test.mangle || test.mangle_props) {
|
||||
if (test.mangle) {
|
||||
U.base54.reset();
|
||||
output.compute_char_frequency(test.mangle);
|
||||
}
|
||||
if (test.mangle) {
|
||||
output.mangle_names(test.mangle);
|
||||
if (test.mangle.properties) {
|
||||
output = U.mangle_properties(output, test.mangle.properties);
|
||||
}
|
||||
if (test.mangle_props) {
|
||||
output = U.mangle_properties(output, test.mangle_props);
|
||||
}
|
||||
output = make_code(output, output_options);
|
||||
if (expect != output) {
|
||||
|
||||
Reference in New Issue
Block a user