Compare commits

..

3 Commits

Author SHA1 Message Date
Alex Lam S.L
2dde41615a v3.0.23 2017-07-02 17:24:22 +08:00
Alex Lam S.L
8b69a3d18e drop argument value after collapse_vars (#2190) 2017-07-02 04:28:11 +08:00
Alex Lam S.L
d40950b741 improve inline efficiency (#2188)
... by teaching `collapse_vars` some new tricks.

fixes #2187
2017-07-02 01:05:14 +08:00
88 changed files with 653 additions and 11326 deletions

View File

@@ -1,11 +1,14 @@
uglify-es
=========
UglifyJS 3
==========
**uglify-es** is an ECMAScript parser, minifier, compressor and beautifier toolkit for ES6+.
UglifyJS is a JavaScript parser, minifier, compressor and beautifier toolkit.
#### Note:
- **`uglify-es` is API/CLI compatible with `uglify-js@3`.**
- **`uglify-es` is not backwards compatible with `uglify-js@2`.**
- **`uglify-js@3` has a simplified [API](#api-reference) and [CLI](#command-line-usage) that is not backwards compatible with [`uglify-js@2`](https://github.com/mishoo/UglifyJS2/tree/v2.x)**.
- **Documentation for UglifyJS `2.x` releases can be found [here](https://github.com/mishoo/UglifyJS2/tree/v2.x)**.
- `uglify-js` only supports ECMAScript 5 (ES5).
- Those wishing to minify
ES2015+ (ES6+) should use the `npm` package [**uglify-es**](https://github.com/mishoo/UglifyJS2/tree/harmony).
Install
-------
@@ -15,11 +18,11 @@ First make sure you have installed the latest version of [node.js](http://nodejs
From NPM for use as a command line app:
npm install uglify-es -g
npm install uglify-js -g
From NPM for programmatic use:
npm install uglify-es
npm install uglify-js
# Command line usage
@@ -102,7 +105,6 @@ a double dash to prevent input files being used as option arguments:
sequences.
--config-file <file> Read `minify()` options from JSON file.
-d, --define <expr>[=value] Global definitions.
--ecma <version> Specifiy ECMAScript release: 5, 6, 7 or 8.
--ie8 Support non-standard Internet Explorer 8.
Equivalent to setting `ie8: true` in `minify()`
for `compress`, `mangle` and `output` options.
@@ -345,7 +347,7 @@ identify mistakes like writing mangled keys to storage.
Assuming installation via NPM, you can load UglifyJS in your application
like this:
```javascript
var UglifyJS = require("uglify-es");
var UglifyJS = require("uglify-js");
```
There is a single high level function, **`minify(code, options)`**,
@@ -474,9 +476,6 @@ if (result.error) throw result.error;
## Minify options
- `ecma` (default `undefined`) - pass `5`, `6`, `7` or `8` to override `parse`,
`compress` and `output` options.
- `warnings` (default `false`) — pass `true` to return compressor warnings
in `result.warnings`. Use the value `"verbose"` for more detailed warnings.
@@ -515,6 +514,7 @@ if (result.error) throw result.error;
```javascript
{
warnings: false,
parse: {
// parse options
},
@@ -534,11 +534,9 @@ if (result.error) throw result.error;
sourceMap: {
// source map options
},
ecma: 5, // specify one of: 5, 6, 7 or 8
nameCache: null, // or specify a name cache object
toplevel: false,
ie8: false,
warnings: false,
}
```
@@ -592,9 +590,6 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
## Parse options
- `bare_returns` (default `false`) -- support top level `return` statements
- `ecma` (default: `8`) -- specify one of `5`, `6`, `7` or `8`. Note: this setting
is not presently enforced except for ES8 optional trailing commas in function
parameter lists and calls with `ecma` `8`.
- `html5_comments` (default `true`)
- `shebang` (default `true`) -- support `#!command` as the first line
@@ -646,10 +641,6 @@ 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.
- `booleans` -- various optimizations for boolean context, for example `!!a
? b : c → a ? b : c`
@@ -738,9 +729,6 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
annotation `/*@__PURE__*/` or `/*#__PURE__*/` immediately precedes the call. For
example: `/*@__PURE__*/foo();`
- `ecma` -- default `5`. Pass `6` or greater to enable `compress` options that
will transform ES5 code into smaller ES6+ equivalent forms.
## Mangle options
- `reserved` (default `[]`). Pass an array of identifiers that should be
@@ -749,8 +737,6 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
- `toplevel` (default `false`). Pass `true` to mangle names declared in the
top level scope.
- `keep_classnames` (default `false`). Pass `true` to not mangle class names.
- `keep_fnames` (default `false`). Pass `true` to not mangle function names.
Useful for code relying on `Function.prototype.name`. See also: the `keep_fnames`
[compress option](#compress-options).
@@ -758,10 +744,6 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
- `eval` (default `false`). Pass `true` to mangle names visible in scopes
where `eval` or `with` are used.
- `safari10` (default `false`). Pass `true` to work around the Safari 10 loop
iterator [bug](https://bugs.webkit.org/show_bug.cgi?id=171041)
"Cannot declare a let variable twice".
Examples:
```javascript
@@ -814,12 +796,6 @@ can pass additional arguments that control the code output:
- `comments` (default `false`) -- pass `true` or `"all"` to preserve all
comments, `"some"` to preserve some comments, a regular expression string
(e.g. `/^!/`) or a function.
- `ecma` (default `5`) -- set output printing mode. Set `ecma` to `6` or
greater to emit shorthand object properties - i.e.: `{a}` instead of `{a: a}`.
The `ecma` option will only change the output in direct control of the
beautifier. Non-compatible features in the abstract syntax tree will still
be output as is. For example: an `ecma` setting of `5` will **not** convert
ES6+ code to ES5.
- `indent_level` (default 4)
- `indent_start` (default 0) -- prefix all lines by that many spaces
- `inline_script` (default `false`) -- escape the slash in occurrences of

View File

@@ -44,7 +44,6 @@ program.option("-o, --output <file>", "Output file (default STDOUT).");
program.option("--comments [filter]", "Preserve copyright comments in the output.");
program.option("--config-file <file>", "Read minify() options from JSON file.");
program.option("-d, --define <expr>[=value]", "Global definitions.", parse_js("define"));
program.option("--ecma <version>", "Specifiy ECMAScript release: 5, 6, 7 or 8.");
program.option("--ie8", "Support non-standard Internet Explorer 8.");
program.option("--keep-fnames", "Do not mangle/drop function names. Useful for code relying on Function.prototype.name.");
program.option("--name-cache <file>", "File to hold mangled name mappings.");
@@ -74,10 +73,6 @@ if (!program.output && program.sourceMap && program.sourceMap.url != "inline") {
options[name] = program[name];
}
});
if ("ecma" in program) {
if (program.ecma != (program.ecma | 0)) fatal("ERROR: ecma must be an integer");
options.ecma = program.ecma | 0;
}
if (program.beautify) {
options.output = typeof program.beautify == "object" ? program.beautify : {};
if (!("beautify" in options.output)) {

View File

@@ -157,7 +157,7 @@ var AST_SimpleStatement = DEFNODE("SimpleStatement", "body", {
function walk_body(node, visitor) {
var body = node.body;
if (body instanceof AST_Node) {
if (body instanceof AST_Statement) {
body._walk(visitor);
}
else for (var i = 0, len = body.length; i < len; i++) {
@@ -284,10 +284,6 @@ var AST_ForIn = DEFNODE("ForIn", "init name object", {
}
}, AST_IterationStatement);
var AST_ForOf = DEFNODE("ForOf", null, {
$documentation: "A `for ... of` statement",
}, AST_ForIn);
var AST_With = DEFNODE("With", "expression", {
$documentation: "A `with` statement",
$propdoc: {
@@ -315,13 +311,6 @@ var AST_Scope = DEFNODE("Scope", "directives variables functions uses_with uses_
enclosed: "[SymbolDef*/S] a list of all symbol definitions that are accessed from this scope or any subscopes",
cname: "[integer/S] current index for mangling variables (used internally by the mangler)",
},
get_defun_scope: function () {
var self = this;
while (self.is_block_scope() && self.parent_scope) {
self = self.parent_scope;
}
return self;
}
}, AST_Block);
var AST_Toplevel = DEFNODE("Toplevel", "globals", {
@@ -342,38 +331,12 @@ var AST_Toplevel = DEFNODE("Toplevel", "globals", {
}
}, AST_Scope);
var AST_Expansion = DEFNODE("Expansion", "expression", {
$documentation: "An expandible argument, such as ...rest, a splat, such as [1,2,...all], or an expansion in a variable declaration, such as var [first, ...rest] = list",
$propdoc: {
expression: "[AST_Node] the thing to be expanded"
},
_walk: function(visitor) {
var self = this;
return visitor._visit(this, function(){
self.expression.walk(visitor);
});
}
});
var AST_Lambda = DEFNODE("Lambda", "name argnames uses_arguments is_generator async", {
var AST_Lambda = DEFNODE("Lambda", "name argnames uses_arguments", {
$documentation: "Base class for functions",
$propdoc: {
name: "[AST_SymbolDeclaration?] the name of this function",
argnames: "[AST_SymbolFunarg|AST_Destructuring|AST_Expansion|AST_DefaultAssign*] array of function arguments, destructurings, or expanding arguments",
uses_arguments: "[boolean/S] tells whether this function accesses the arguments array",
is_generator: "[boolean] is this a generator method",
async: "[boolean] is this method async",
},
args_as_names: function () {
var out = [];
for (var i = 0; i < this.argnames.length; i++) {
if (this.argnames[i] instanceof AST_Destructuring) {
out = out.concat(this.argnames[i].all_symbols());
} else {
out.push(this.argnames[i]);
}
}
return out;
argnames: "[AST_SymbolFunarg*] array of function arguments",
uses_arguments: "[boolean/S] tells whether this function accesses the arguments array"
},
_walk: function(visitor) {
return visitor._visit(this, function(){
@@ -395,78 +358,10 @@ var AST_Function = DEFNODE("Function", null, {
$documentation: "A function expression"
}, AST_Lambda);
var AST_Arrow = DEFNODE("Arrow", null, {
$documentation: "An ES6 Arrow function ((a) => b)"
}, AST_Lambda);
var AST_Defun = DEFNODE("Defun", null, {
$documentation: "A function definition"
}, AST_Lambda);
/* -----[ DESTRUCTURING ]----- */
var AST_Destructuring = DEFNODE("Destructuring", "names is_array", {
$documentation: "A destructuring of several names. Used in destructuring assignment and with destructuring function argument names",
$propdoc: {
"names": "[AST_Node*] Array of properties or elements",
"is_array": "[Boolean] Whether the destructuring represents an object or array"
},
_walk: function(visitor) {
return visitor._visit(this, function(){
this.names.forEach(function(name){
name._walk(visitor);
});
});
},
all_symbols: function() {
var out = [];
this.walk(new TreeWalker(function (node) {
if (node instanceof AST_Symbol) {
out.push(node);
}
if (node instanceof AST_Expansion) {
out.push(node.expression);
}
}));
return out;
}
});
var AST_PrefixedTemplateString = DEFNODE("PrefixedTemplateString", "template_string prefix", {
$documentation: "A templatestring with a prefix, such as String.raw`foobarbaz`",
$propdoc: {
template_string: "[AST_TemplateString] The template string",
prefix: "[AST_SymbolRef|AST_PropAccess] The prefix, which can be a symbol such as `foo` or a dotted expression such as `String.raw`."
},
_walk: function(visitor) {
this.prefix._walk(visitor);
this.template_string._walk(visitor);
}
})
var AST_TemplateString = DEFNODE("TemplateString", "segments", {
$documentation: "A template string literal",
$propdoc: {
segments: "[AST_Node*] One or more segments, starting with AST_TemplateSegment. AST_Node may follow AST_TemplateSegment, but each AST_Node must be followed by AST_TemplateSegment."
},
_walk: function(visitor) {
return visitor._visit(this, function(){
this.segments.forEach(function(seg, i){
if (i % 2 !== 0) {
seg._walk(visitor);
}
});
});
}
});
var AST_TemplateSegment = DEFNODE("TemplateSegment", "value raw", {
$documentation: "A segment of a template string literal",
$propdoc: {
value: "Content of the segment",
raw: "Raw content of the segment"
}
});
/* -----[ JUMPS ]----- */
var AST_Jump = DEFNODE("Jump", null, {
@@ -586,7 +481,7 @@ var AST_Try = DEFNODE("Try", "bcatch bfinally", {
var AST_Catch = DEFNODE("Catch", "argname", {
$documentation: "A `catch` node; only makes sense as part of a `try` statement",
$propdoc: {
argname: "[AST_SymbolCatch|AST_Destructuring|AST_Expansion|AST_DefaultAssign] symbol for the exception"
argname: "[AST_SymbolCatch] symbol for the exception"
},
_walk: function(visitor) {
return visitor._visit(this, function(){
@@ -600,10 +495,10 @@ var AST_Finally = DEFNODE("Finally", null, {
$documentation: "A `finally` node; only makes sense as part of a `try` statement"
}, AST_Block);
/* -----[ VAR/CONST ]----- */
/* -----[ VAR ]----- */
var AST_Definitions = DEFNODE("Definitions", "definitions", {
$documentation: "Base class for `var` or `const` nodes (variable declarations/initializations)",
$documentation: "Base class for `var` nodes (variable declarations/initializations)",
$propdoc: {
definitions: "[AST_VarDef*] array of variable definitions"
},
@@ -621,83 +516,10 @@ var AST_Var = DEFNODE("Var", null, {
$documentation: "A `var` statement"
}, AST_Definitions);
var AST_Let = DEFNODE("Let", null, {
$documentation: "A `let` statement"
}, AST_Definitions);
var AST_Const = DEFNODE("Const", null, {
$documentation: "A `const` statement"
}, AST_Definitions);
var AST_NameMapping = DEFNODE("NameMapping", "foreign_name name", {
$documentation: "The part of the export/import statement that declare names from a module.",
$propdoc: {
foreign_name: "[AST_SymbolExportForeign|AST_SymbolImportForeign] The name being exported/imported (as specified in the module)",
name: "[AST_SymbolExport|AST_SymbolImport] The name as it is visible to this module."
},
_walk: function (visitor) {
return visitor._visit(this, function() {
this.foreign_name._walk(visitor);
this.name._walk(visitor);
});
}
})
var AST_Import = DEFNODE("Import", "imported_name imported_names module_name", {
$documentation: "An `import` statement",
$propdoc: {
imported_name: "[AST_SymbolImport] The name of the variable holding the module's default export.",
imported_names: "[AST_NameMapping*] The names of non-default imported variables",
module_name: "[AST_String] String literal describing where this module came from",
},
_walk: function(visitor) {
return visitor._visit(this, function() {
if (this.imported_name) {
this.imported_name._walk(visitor);
}
if (this.imported_names) {
this.imported_names.forEach(function(name_import) {
name_import._walk(visitor);
});
}
this.module_name._walk(visitor);
});
}
});
var AST_Export = DEFNODE("Export", "exported_definition exported_value is_default exported_names module_name", {
$documentation: "An `export` statement",
$propdoc: {
exported_definition: "[AST_Defun|AST_Definitions|AST_DefClass?] An exported definition",
exported_value: "[AST_Node?] An exported value",
exported_names: "[AST_NameMapping*?] List of exported names",
module_name: "[AST_String?] Name of the file to load exports from",
is_default: "[Boolean] Whether this is the default exported value of this module"
},
_walk: function (visitor) {
visitor._visit(this, function () {
if (this.exported_definition) {
this.exported_definition._walk(visitor);
}
if (this.exported_value) {
this.exported_value._walk(visitor);
}
if (this.exported_names) {
this.exported_names.forEach(function(name_export) {
name_export._walk(visitor);
});
}
if (this.module_name) {
this.module_name._walk(visitor);
}
});
}
}, AST_Statement);
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_SymbolVar] name of the variable",
value: "[AST_Node?] initializer, or null of there's no initializer"
},
_walk: function(visitor) {
@@ -828,10 +650,6 @@ var AST_Assign = DEFNODE("Assign", null, {
$documentation: "An assignment expression — `a = b + 5`",
}, AST_Binary);
var AST_DefaultAssign = DEFNODE("DefaultAssign", null, {
$documentation: "A default assignment expression like in `(a = 3) => a`"
}, AST_Binary);
/* -----[ LITERALS ]----- */
var AST_Array = DEFNODE("Array", "elements", {
@@ -867,13 +685,11 @@ var AST_Object = DEFNODE("Object", "properties", {
var AST_ObjectProperty = DEFNODE("ObjectProperty", "key value", {
$documentation: "Base class for literal object properties",
$propdoc: {
key: "[string|AST_Node] the property name converted to a string for ObjectKeyVal. For setters, getters and computed property this is an arbitrary AST_Node",
key: "[string] the property name converted to a string for ObjectKeyVal. For setters and getters this is an AST_SymbolAccessor.",
value: "[AST_Node] property value. For setters and getters this is an AST_Accessor."
},
_walk: function(visitor) {
return visitor._visit(this, function(){
if (this.key instanceof AST_Node)
this.key._walk(visitor);
this.value._walk(visitor);
});
}
@@ -886,95 +702,35 @@ var AST_ObjectKeyVal = DEFNODE("ObjectKeyVal", "quote", {
}
}, AST_ObjectProperty);
var AST_ObjectSetter = DEFNODE("ObjectSetter", "quote static", {
$propdoc: {
quote: "[string|undefined] the original quote character, if any",
static: "[boolean] whether this is a static setter (classes only)"
},
var AST_ObjectSetter = DEFNODE("ObjectSetter", null, {
$documentation: "An object setter property",
}, AST_ObjectProperty);
var AST_ObjectGetter = DEFNODE("ObjectGetter", "quote static", {
$propdoc: {
quote: "[string|undefined] the original quote character, if any",
static: "[boolean] whether this is a static getter (classes only)"
},
var AST_ObjectGetter = DEFNODE("ObjectGetter", null, {
$documentation: "An object getter property",
}, AST_ObjectProperty);
var AST_ConciseMethod = DEFNODE("ConciseMethod", "quote static is_generator async", {
$propdoc: {
quote: "[string|undefined] the original quote character, if any",
static: "[boolean] is this method static (classes only)",
is_generator: "[boolean] is this a generator method",
async: "[boolean] is this method async",
},
$documentation: "An ES6 concise method inside an object or class"
}, AST_ObjectProperty);
var AST_Class = DEFNODE("Class", "name extends properties", {
$propdoc: {
name: "[AST_SymbolClass|AST_SymbolDefClass?] optional class name.",
extends: "[AST_Node]? optional parent class",
properties: "[AST_ObjectProperty*] array of properties"
},
$documentation: "An ES6 class",
_walk: function(visitor) {
return visitor._visit(this, function(){
if (this.name) {
this.name._walk(visitor);
}
if (this.extends) {
this.extends._walk(visitor);
}
this.properties.forEach(function(prop){
prop._walk(visitor);
});
});
},
}, AST_Scope);
var AST_DefClass = DEFNODE("DefClass", null, {
$documentation: "A class definition",
}, AST_Class);
var AST_ClassExpression = DEFNODE("ClassExpression", null, {
$documentation: "A class expression."
}, AST_Class);
var AST_Symbol = DEFNODE("Symbol", "scope name thedef", {
$propdoc: {
name: "[string] name of this symbol",
scope: "[AST_Scope/S] the current scope (not necessarily the definition scope)",
thedef: "[SymbolDef/S] the definition of this symbol"
},
$documentation: "Base class for all symbols"
$documentation: "Base class for all symbols",
});
var AST_NewTarget = DEFNODE("NewTarget", null, {
$documentation: "A reference to new.target"
});
var AST_SymbolAccessor = DEFNODE("SymbolAccessor", null, {
$documentation: "The name of a property accessor (setter/getter function)"
}, AST_Symbol);
var AST_SymbolDeclaration = DEFNODE("SymbolDeclaration", "init", {
$documentation: "A declaration symbol (symbol in var/const, function name or argument, symbol in catch)",
$documentation: "A declaration symbol (symbol in var, function name or argument, symbol in catch)",
}, AST_Symbol);
var AST_SymbolVar = DEFNODE("SymbolVar", null, {
$documentation: "Symbol defining a variable",
}, AST_SymbolDeclaration);
var AST_SymbolBlockDeclaration = DEFNODE("SymbolBlockDeclaration", null, {
$documentation: "Base class for block-scoped declaration symbols"
}, AST_SymbolDeclaration);
var AST_SymbolConst = DEFNODE("SymbolConst", null, {
$documentation: "A constant declaration"
}, AST_SymbolBlockDeclaration);
var AST_SymbolLet = DEFNODE("SymbolLet", null, {
$documentation: "A block-scoped `let` declaration"
}, AST_SymbolBlockDeclaration);
var AST_SymbolFunarg = DEFNODE("SymbolFunarg", null, {
$documentation: "Symbol naming a function argument",
}, AST_SymbolVar);
@@ -983,33 +739,13 @@ var AST_SymbolDefun = DEFNODE("SymbolDefun", null, {
$documentation: "Symbol defining a function",
}, AST_SymbolDeclaration);
var AST_SymbolMethod = DEFNODE("SymbolMethod", null, {
$documentation: "Symbol in an object defining a method",
}, AST_Symbol);
var AST_SymbolLambda = DEFNODE("SymbolLambda", null, {
$documentation: "Symbol naming a function expression",
}, AST_SymbolDeclaration);
var AST_SymbolDefClass = DEFNODE("SymbolDefClass", null, {
$documentation: "Symbol naming a class's name in a class declaration. Lexically scoped to its containing scope, and accessible within the class."
}, AST_SymbolBlockDeclaration);
var AST_SymbolClass = DEFNODE("SymbolClass", null, {
$documentation: "Symbol naming a class's name. Lexically scoped to the class."
}, AST_SymbolDeclaration);
var AST_SymbolCatch = DEFNODE("SymbolCatch", null, {
$documentation: "Symbol naming the exception in catch",
}, AST_SymbolBlockDeclaration);
var AST_SymbolImport = DEFNODE("SymbolImport", null, {
$documentation: "Symbol referring to an imported name",
}, AST_SymbolBlockDeclaration);
var AST_SymbolImportForeign = DEFNODE("SymbolImportForeign", null, {
$documentation: "A symbol imported from a module, but it is defined in the other module, and its real name is irrelevant for this module's purposes",
}, AST_Symbol);
}, AST_SymbolDeclaration);
var AST_Label = DEFNODE("Label", "references", {
$documentation: "Symbol naming a label (declaration)",
@@ -1026,14 +762,6 @@ var AST_SymbolRef = DEFNODE("SymbolRef", null, {
$documentation: "Reference to some symbol (not definition/declaration)",
}, AST_Symbol);
var AST_SymbolExport = DEFNODE("SymbolExport", null, {
$documentation: "Symbol referring to a name to export",
}, AST_SymbolRef);
var AST_SymbolExportForeign = DEFNODE("SymbolExportForeign", null, {
$documentation: "A symbol exported from this module, but it is used in the other module, and its real name is irrelevant for this module's purposes",
}, AST_Symbol);
var AST_LabelRef = DEFNODE("LabelRef", null, {
$documentation: "Reference to a label symbol",
}, AST_Symbol);
@@ -1042,10 +770,6 @@ var AST_This = DEFNODE("This", null, {
$documentation: "The `this` symbol",
}, AST_Symbol);
var AST_Super = DEFNODE("Super", null, {
$documentation: "The `super` symbol",
}, AST_Symbol);
var AST_Constant = DEFNODE("Constant", null, {
$documentation: "Base class for all constants",
getValue: function() {
@@ -1119,31 +843,6 @@ var AST_True = DEFNODE("True", null, {
value: true
}, AST_Boolean);
var AST_Await = DEFNODE("Await", "expression", {
$documentation: "An `await` statement",
$propdoc: {
expression: "[AST_Node] the mandatory expression being awaited",
},
_walk: function(visitor) {
return visitor._visit(this, function(){
this.expression._walk(visitor);
});
}
});
var AST_Yield = DEFNODE("Yield", "expression is_star", {
$documentation: "A `yield` statement",
$propdoc: {
expression: "[AST_Node?] the value returned or thrown by this statement; could be null (representing undefined) but only when is_star is set to false",
is_star: "[Boolean] Whether this is a yield or yield* statement"
},
_walk: function(visitor) {
return visitor._visit(this, this.expression && function(){
this.expression._walk(visitor);
});
}
});
/* -----[ TreeWalker ]----- */
function TreeWalker(callback) {
@@ -1171,17 +870,12 @@ TreeWalker.prototype = {
this.directives = Object.create(this.directives);
} else if (node instanceof AST_Directive && !this.directives[node.value]) {
this.directives[node.value] = node;
} else if (node instanceof AST_Class) {
this.directives = Object.create(this.directives);
if (!this.directives["use strict"]) {
this.directives["use strict"] = node;
}
}
this.stack.push(node);
},
pop: function(node) {
this.stack.pop();
if (node instanceof AST_Lambda || node instanceof AST_Class) {
if (node instanceof AST_Lambda) {
this.directives = Object.getPrototypeOf(this.directives);
}
},
@@ -1199,7 +893,7 @@ TreeWalker.prototype = {
var dir = this.directives[type];
if (dir) return dir;
var node = this.stack[this.stack.length - 1];
if (node instanceof AST_Scope && node.body) {
if (node instanceof AST_Scope) {
for (var i = 0; i < node.body.length; ++i) {
var st = node.body[i];
if (!(st instanceof AST_Directive)) break;

File diff suppressed because it is too large Load Diff

View File

@@ -49,7 +49,6 @@ function minify(files, options) {
try {
options = defaults(options, {
compress: {},
ecma: undefined,
ie8: false,
keep_fnames: false,
mangle: {},
@@ -65,7 +64,6 @@ function minify(files, options) {
var timings = options.timings && {
start: Date.now()
};
set_shorthand("ecma", options, [ "parse", "compress", "output" ]);
set_shorthand("ie8", options, [ "compress", "mangle", "output" ]);
set_shorthand("keep_fnames", options, [ "compress", "mangle" ]);
set_shorthand("toplevel", options, [ "compress", "mangle" ]);
@@ -75,11 +73,9 @@ function minify(files, options) {
cache: options.nameCache && (options.nameCache.vars || {}),
eval: false,
ie8: false,
keep_classnames: false,
keep_fnames: false,
properties: false,
reserved: [],
safari10: false,
toplevel: false,
}, true);
if (options.nameCache && options.mangle.properties) {

View File

@@ -118,7 +118,7 @@
value : from_moz(M.value)
};
if (M.kind == "init") return new AST_ObjectKeyVal(args);
args.key = new AST_SymbolMethod({
args.key = new AST_SymbolAccessor({
name: args.key
});
args.value = new AST_Accessor(args.value);
@@ -168,7 +168,7 @@
});
},
VariableDeclaration: function(M) {
return new (M.kind === "const" ? AST_Const : AST_Var)({
return new AST_Var({
start : my_start_token(M),
end : my_end_token(M),
definitions : M.declarations.map(from_moz)
@@ -204,7 +204,7 @@
Identifier: function(M) {
var p = FROM_MOZ_STACK[FROM_MOZ_STACK.length - 2];
return new ( p.type == "LabeledStatement" ? AST_Label
: p.type == "VariableDeclarator" && p.id === M ? (p.kind == "const" ? AST_SymbolConst : AST_SymbolVar)
: p.type == "VariableDeclarator" && p.id === M ? AST_SymbolVar
: p.type == "FunctionExpression" ? (p.id === M ? AST_SymbolLambda : AST_SymbolFunarg)
: p.type == "FunctionDeclaration" ? (p.id === M ? AST_SymbolDefun : AST_SymbolFunarg)
: p.type == "CatchClause" ? AST_SymbolCatch
@@ -324,7 +324,7 @@
def_to_moz(AST_Definitions, function To_Moz_VariableDeclaration(M) {
return {
type: "VariableDeclaration",
kind: M instanceof AST_Const ? "const" : "var",
kind: "var",
declarations: M.definitions.map(to_moz)
};
});
@@ -381,7 +381,7 @@
def_to_moz(AST_ObjectProperty, function To_Moz_Property(M) {
var key = {
type: "Literal",
value: M.key instanceof AST_SymbolMethod ? M.key.name : M.key
value: M.key instanceof AST_SymbolAccessor ? M.key.name : M.key
};
var kind;
if (M instanceof AST_ObjectKeyVal) {

View File

@@ -54,11 +54,9 @@ function OutputStream(options) {
options = defaults(options, {
ascii_only : false,
ascii_identifiers: undefined,
beautify : false,
bracketize : false,
comments : false,
ecma : 5,
ie8 : false,
indent_level : 4,
indent_start : 0,
@@ -71,19 +69,12 @@ function OutputStream(options) {
quote_style : 0,
semicolons : true,
shebang : true,
shorthand : undefined,
source_map : null,
webkit : false,
width : 80,
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;
// Convert comment option to RegExp if neccessary and set up comments filter
var comment_filter = return_false; // Default case, throw all comments away
if (options.comments) {
@@ -119,19 +110,9 @@ function OutputStream(options) {
var OUTPUT = "";
function to_ascii(str, identifier) {
return str.replace(/[\ud800-\udbff][\udc00-\udfff]|[\u0000-\u001f\u007f-\uffff]/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 {
@@ -159,7 +140,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-7]/.test(str.charAt(i+1)) ? "\\x00" : "\\0";
}
return s;
});
@@ -169,11 +150,7 @@ function OutputStream(options) {
function quote_double() {
return '"' + str.replace(/\x22/g, '\\"') + '"';
}
function quote_template() {
return '`' + str.replace(/`/g, '\\`') + '`';
}
if (options.ascii_only) str = to_ascii(str);
if (quote === "`") return quote_template();
switch (options.quote_style) {
case 1:
return quote_single();
@@ -198,7 +175,7 @@ function OutputStream(options) {
function make_name(name) {
name = name.toString();
if (options.ascii_identifiers)
if (options.ascii_only)
name = to_ascii(name, true);
return name;
};
@@ -269,8 +246,8 @@ function OutputStream(options) {
function print(str) {
str = String(str);
var ch = get_full_char(str, 0);
var prev = get_full_char(last, last.length - 1);
var ch = str.charAt(0);
var prev = last.charAt(last.length - 1);
if (might_need_semicolon) {
might_need_semicolon = false;
@@ -346,10 +323,6 @@ function OutputStream(options) {
last = str;
};
var star = function(){
print("*");
}
var space = options.beautify ? function() {
print(" ");
} : function() {
@@ -454,7 +427,6 @@ function OutputStream(options) {
should_break : function() { return options.width && this.current_width() >= options.width },
newline : newline,
print : print,
star : star,
space : space,
comma : comma,
colon : colon,
@@ -474,10 +446,6 @@ function OutputStream(options) {
}
print(encoded);
},
print_template_string_chars: function(str) {
var encoded = encode_string(str, '`').replace(/\${/g, "\\${");
return print(encoded.substr(1, encoded.length - 2));
},
encode_string : encode_string,
next_indent : next_indent,
with_indent : with_indent,
@@ -646,15 +614,6 @@ function OutputStream(options) {
return false;
});
PARENS(AST_Arrow, function(output){
var p = output.parent();
return p instanceof AST_PropAccess && p.expression === this;
});
PARENS(AST_ClassExpression, function(output){
return output.parent() instanceof AST_SimpleStatement;
});
// same goes for an object literal, because otherwise it would be
// interpreted as a block of code.
PARENS(AST_Object, function(output){
@@ -662,18 +621,6 @@ function OutputStream(options) {
});
PARENS(AST_Unary, function(output){
var p = output.parent();
return p instanceof AST_PropAccess && p.expression === this
|| p instanceof AST_Call && p.expression === this
|| p instanceof AST_Binary
&& p.operator === "**"
&& this instanceof AST_UnaryPrefix
&& p.left === this
&& this.operator !== "++"
&& this.operator !== "--";
});
PARENS(AST_Await, function(output){
var p = output.parent();
return p instanceof AST_PropAccess && p.expression === this
|| p instanceof AST_Call && p.expression === this;
@@ -681,17 +628,15 @@ function OutputStream(options) {
PARENS(AST_Sequence, function(output){
var p = output.parent();
return p instanceof AST_Call // (foo, bar)() or foo(1, (2, 3), 4)
|| p instanceof AST_Unary // !(foo, bar, baz)
|| p instanceof AST_Binary // 1 + (2, 3) + 4 ==> 8
|| p instanceof AST_VarDef // var a = (1, 2), b = a + a; ==> b == 4
|| p instanceof AST_PropAccess // (1, {foo:2}).foo or (1, {foo:2})["foo"] ==> 2
|| p instanceof AST_Array // [ 1, (2, 3), 4 ] ==> [ 1, 3, 4 ]
|| p instanceof AST_ObjectProperty // { foo: (1, 2) }.foo ==> 2
|| p instanceof AST_Conditional /* (false, true) ? (a = 10, b = 20) : (c = 30)
* ==> 20 (side effect, set a := 10 and b := 20) */
|| p instanceof AST_Arrow // x => (x, x)
|| p instanceof AST_DefaultAssign // x => (x = (0, function(){}))
return p instanceof AST_Call // (foo, bar)() or foo(1, (2, 3), 4)
|| p instanceof AST_Unary // !(foo, bar, baz)
|| p instanceof AST_Binary // 1 + (2, 3) + 4 ==> 8
|| p instanceof AST_VarDef // var a = (1, 2), b = a + a; ==> b == 4
|| p instanceof AST_PropAccess // (1, {foo:2}).foo or (1, {foo:2})["foo"] ==> 2
|| p instanceof AST_Array // [ 1, (2, 3), 4 ] ==> [ 1, 3, 4 ]
|| p instanceof AST_ObjectProperty // { foo: (1, 2) }.foo ==> 2
|| p instanceof AST_Conditional /* (false, true) ? (a = 10, b = 20) : (c = 30)
* ==> 20 (side effect, set a := 10 and b := 20) */
;
});
@@ -718,24 +663,6 @@ function OutputStream(options) {
}
});
PARENS(AST_Yield, function(output){
var p = output.parent();
// (yield 1) + (yield 2)
// a = yield 3
if (p instanceof AST_Binary && p.operator !== "=")
return true;
// (yield 1) ? yield 2 : yield 3
if (p instanceof AST_Conditional && p.condition === this)
return true;
// -(yield 4)
if (p instanceof AST_Unary)
return true;
// (yield x).foo
// (yield x)['foo']
if (p instanceof AST_PropAccess && p.expression === this)
return true;
});
PARENS(AST_PropAccess, function(output){
var p = output.parent();
if (p instanceof AST_New && p.expression === this) {
@@ -805,9 +732,6 @@ function OutputStream(options) {
// (a = foo)["prop"] —or— (a = foo).prop
if (p instanceof AST_PropAccess && p.expression === this)
return true;
// ({a, b} = {a: 1, b: 2}), a destructuring assignment
if (this instanceof AST_Assign && this.left instanceof AST_Destructuring && this.left.is_array === false)
return true;
});
/* -----[ PRINTERS ]----- */
@@ -816,26 +740,6 @@ function OutputStream(options) {
output.print_string(self.value, self.quote);
output.semicolon();
});
DEFPRINT(AST_Expansion, function (self, output) {
output.print('...');
self.expression.print(output);
});
DEFPRINT(AST_Destructuring, function (self, output) {
output.print(self.is_array ? "[" : "{");
var len = self.names.length;
self.names.forEach(function (name, i) {
if (i > 0) output.comma();
name.print(output);
// If the final element is a hole, we need to make sure it
// doesn't look like a trailing comma, by inserting an actual
// trailing comma.
if (i == len - 1 && name instanceof AST_Hole) output.comma();
});
output.print(self.is_array ? "]" : "}");
});
DEFPRINT(AST_Debugger, function(self, output){
output.print("debugger");
output.semicolon();
@@ -960,11 +864,7 @@ function OutputStream(options) {
output.with_parens(function(){
self.init.print(output);
output.space();
if (self instanceof AST_ForOf) {
output.print("of");
} else {
output.print("in");
}
output.print("in");
output.space();
self.object.print(output);
});
@@ -985,24 +885,11 @@ function OutputStream(options) {
AST_Lambda.DEFMETHOD("_do_print", function(output, nokeyword){
var self = this;
if (!nokeyword) {
if (self.async) {
output.print("async");
output.space();
}
output.print("function");
if (self.is_generator) {
output.star();
}
if (self.name) {
output.space();
}
}
if (self.name instanceof AST_Symbol) {
if (self.name) {
output.space();
self.name.print(output);
} else if (nokeyword && self.name instanceof AST_Node) {
output.with_square(function() {
self.name.print(output); // Computed method name
});
}
output.with_parens(function(){
self.argnames.forEach(function(arg, i){
@@ -1017,60 +904,6 @@ function OutputStream(options) {
self._do_print(output);
});
DEFPRINT(AST_PrefixedTemplateString, function(self, output) {
self.prefix.print(output);
self.template_string.print(output);
});
DEFPRINT(AST_TemplateString, function(self, output) {
var is_tagged = output.parent() instanceof AST_PrefixedTemplateString;
output.print("`");
for (var i = 0; i < self.segments.length; i++) {
if (!(self.segments[i] instanceof AST_TemplateSegment)) {
output.print("${");
self.segments[i].print(output);
output.print("}");
} else if (is_tagged) {
output.print(self.segments[i].raw);
} else {
output.print_template_string_chars(self.segments[i].value);
}
}
output.print("`");
});
AST_Arrow.DEFMETHOD("_do_print", function(output){
var self = this;
var parent = output.parent();
var needs_parens = parent instanceof AST_Binary ||
parent instanceof AST_Unary ||
(parent instanceof AST_Call && self === parent.expression);
if (needs_parens) { output.print("(") }
if (self.async) {
output.print("async");
output.space();
}
if (self.argnames.length === 1 && self.argnames[0] instanceof AST_Symbol) {
self.argnames[0].print(output);
} else {
output.with_parens(function(){
self.argnames.forEach(function(arg, i){
if (i) output.comma();
arg.print(output);
});
});
}
output.space();
output.print('=>');
output.space();
if (self.body instanceof AST_Node) {
self.body.print(output);
} else {
print_bracketed(self.body, output);
}
if (needs_parens) { output.print(")") }
});
/* -----[ exits ]----- */
AST_Exit.DEFMETHOD("_do_print", function(output, kind){
output.print(kind);
@@ -1087,33 +920,6 @@ function OutputStream(options) {
self._do_print(output, "throw");
});
/* -----[ yield ]----- */
DEFPRINT(AST_Yield, function(self, output){
var star = self.is_star ? "*" : "";
output.print("yield" + star);
if (self.expression) {
output.space();
self.expression.print(output);
}
});
DEFPRINT(AST_Await, function(self, output){
output.print("await");
output.space();
var e = self.expression;
var parens = !(
e instanceof AST_Call
|| e instanceof AST_SymbolRef
|| e instanceof AST_PropAccess
|| e instanceof AST_Unary
|| e instanceof AST_Constant
);
if (parens) output.print("(");
self.expression.print(output);
if (parens) output.print(")");
});
/* -----[ loop control ]----- */
AST_LoopControl.DEFMETHOD("_do_print", function(output, kind){
output.print(kind);
@@ -1262,111 +1068,9 @@ function OutputStream(options) {
if (!avoid_semicolon)
output.semicolon();
});
DEFPRINT(AST_Let, function(self, output){
self._do_print(output, "let");
});
DEFPRINT(AST_Var, function(self, output){
self._do_print(output, "var");
});
DEFPRINT(AST_Const, function(self, output){
self._do_print(output, "const");
});
DEFPRINT(AST_Import, function(self, output) {
output.print("import");
output.space();
if (self.imported_name) {
self.imported_name.print(output);
}
if (self.imported_name && self.imported_names) {
output.print(",");
output.space();
}
if (self.imported_names) {
if (self.imported_names.length === 1 && self.imported_names[0].foreign_name.name === "*") {
self.imported_names[0].print(output);
} else {
output.print("{");
self.imported_names.forEach(function (name_import, i) {
output.space();
name_import.print(output);
if (i < self.imported_names.length - 1) {
output.print(",");
}
});
output.space();
output.print("}");
}
}
if (self.imported_name || self.imported_names) {
output.space();
output.print("from")
output.space();
}
self.module_name.print(output);
output.semicolon();
});
DEFPRINT(AST_NameMapping, function(self, output) {
var is_import = output.parent() instanceof AST_Import;
var definition = self.name.definition();
var names_are_different =
(definition && definition.mangled_name || self.name.name) !==
self.foreign_name.name;
if (names_are_different) {
if (is_import) {
output.print(self.foreign_name.name);
} else {
self.name.print(output);
}
output.space();
output.print("as");
output.space();
if (is_import) {
self.name.print(output);
} else {
output.print(self.foreign_name.name);
}
} else {
self.name.print(output);
}
});
DEFPRINT(AST_Export, function(self, output) {
output.print("export");
output.space();
if (self.is_default) {
output.print("default");
output.space();
}
if (self.exported_names) {
if (self.exported_names.length === 1 && self.exported_names[0].name.name === "*") {
self.exported_names[0].print(output);
} else {
output.print("{");
self.exported_names.forEach(function(name_export, i) {
output.space();
name_export.print(output);
if (i < self.exported_names.length - 1) {
output.print(",");
}
});
output.space();
output.print("}");
}
}
else if (self.exported_value) {
self.exported_value.print(output);
} else if (self.exported_definition) {
self.exported_definition.print(output);
}
if (self.module_name) {
output.space();
output.print("from");
output.space();
self.module_name.print(output);
}
output.semicolon();
});
function parenthesize_for_noin(node, output, noin) {
if (!noin) node.print(output);
@@ -1539,48 +1243,6 @@ function OutputStream(options) {
});
else output.print("{}");
});
DEFPRINT(AST_Class, function(self, output){
output.print("class");
output.space();
if (self.name) {
self.name.print(output);
output.space();
}
if (self.extends) {
var parens = (
!(self.extends instanceof AST_SymbolRef)
&& !(self.extends instanceof AST_PropAccess)
&& !(self.extends instanceof AST_ClassExpression)
&& !(self.extends instanceof AST_Function)
);
output.print("extends");
if (parens) {
output.print("(");
} else {
output.space();
}
self.extends.print(output);
if (parens) {
output.print(")");
} else {
output.space();
}
}
if (self.properties.length > 0) output.with_block(function(){
self.properties.forEach(function(prop, i){
if (i) {
output.newline();
}
output.indent();
prop.print(output);
});
output.newline();
});
else output.print("{}");
});
DEFPRINT(AST_NewTarget, function(self, output) {
output.print("new.target");
});
function print_property_name(key, quote, output) {
if (output.option("quote_keys")) {
@@ -1602,60 +1264,15 @@ function OutputStream(options) {
}
DEFPRINT(AST_ObjectKeyVal, function(self, output){
function get_name(self) {
var def = self.definition();
return def ? def.mangled_name || def.name : self.name;
}
var allowShortHand = output.option("shorthand");
if (allowShortHand &&
self.value instanceof AST_Symbol &&
is_identifier_string(self.key) &&
get_name(self.value) === self.key
) {
print_property_name(self.key, self.quote, output);
} else if (allowShortHand &&
self.value instanceof AST_DefaultAssign &&
self.value.left instanceof AST_Symbol &&
is_identifier_string(self.key) &&
get_name(self.value.left) === self.key
) {
print_property_name(self.key, self.quote, output);
output.space();
output.print("=");
output.space();
self.value.right.print(output);
} else {
if (!(self.key instanceof AST_Node)) {
print_property_name(self.key, self.quote, output);
} else {
output.with_square(function() {
self.key.print(output);
});
}
output.colon();
self.value.print(output);
}
print_property_name(self.key, self.quote, output);
output.colon();
self.value.print(output);
});
AST_ObjectProperty.DEFMETHOD("_print_getter_setter", function(type, output) {
var self = this;
if (self.static) {
output.print("static");
output.space();
}
if (type) {
output.print(type);
output.space();
}
if (self.key instanceof AST_SymbolMethod) {
print_property_name(self.key.name, self.quote, output);
} else {
output.with_square(function() {
self.key.print(output);
});
}
self.value._do_print(output, true);
output.print(type);
output.space();
print_property_name(this.key.name, this.quote, output);
this.value._do_print(output, true);
});
DEFPRINT(AST_ObjectSetter, function(self, output){
self._print_getter_setter("set", output);
@@ -1663,26 +1280,14 @@ function OutputStream(options) {
DEFPRINT(AST_ObjectGetter, function(self, output){
self._print_getter_setter("get", output);
});
DEFPRINT(AST_ConciseMethod, function(self, output){
self._print_getter_setter(self.is_generator && "*" || self.async && "async", output);
});
AST_Symbol.DEFMETHOD("_do_print", function(output){
var def = this.definition();
output.print_name(def ? def.mangled_name || def.name : this.name);
});
DEFPRINT(AST_Symbol, function (self, output) {
self._do_print(output);
});
DEFPRINT(AST_SymbolDeclaration, function(self, output){
self._do_print(output);
DEFPRINT(AST_Symbol, function(self, output){
var def = self.definition();
output.print_name(def ? def.mangled_name || def.name : self.name);
});
DEFPRINT(AST_Hole, noop);
DEFPRINT(AST_This, function(self, output){
output.print("this");
});
DEFPRINT(AST_Super, function(self, output){
output.print("super");
});
DEFPRINT(AST_Constant, function(self, output){
output.print(self.getValue());
});

File diff suppressed because one or more lines are too long

View File

@@ -44,16 +44,6 @@
"use strict";
function find_builtins(reserved) {
// Compatibility fix for some standard defined globals not defined on every js environment
var new_globals = ["Symbol", "Map", "Promise", "Proxy", "Reflect", "Set", "WeakMap", "WeakSet"];
var objects = {};
var global_ref = typeof global === "object" ? global : self;
new_globals.forEach(function (new_global) {
objects[new_global] = global_ref[new_global] || new Function();
});
// NaN will be included due to Number.NaN
[
"null",
@@ -65,15 +55,7 @@ function find_builtins(reserved) {
].forEach(add);
[ Object, Array, Function, Number,
String, Boolean, Error, Math,
Date, RegExp, objects.Symbol, ArrayBuffer,
DataView, decodeURI, decodeURIComponent,
encodeURI, encodeURIComponent, eval, EvalError,
Float32Array, Float64Array, Int8Array, Int16Array,
Int32Array, isFinite, isNaN, JSON, objects.Map, parseFloat,
parseInt, objects.Promise, objects.Proxy, RangeError, ReferenceError,
objects.Reflect, objects.Set, SyntaxError, TypeError, Uint8Array,
Uint8ClampedArray, Uint16Array, Uint32Array, URIError,
objects.WeakMap, objects.WeakSet
Date, RegExp
].forEach(function(ctor){
Object.getOwnPropertyNames(ctor).map(add);
if (ctor.prototype) {
@@ -139,9 +121,6 @@ function mangle_properties(ast, options) {
else if (node instanceof AST_Sub) {
addStrings(node.property, keep_quoted);
}
else if (node instanceof AST_ConciseMethod) {
add(node.name.name);
}
}));
// step 2: transform the tree, renaming properties
@@ -161,11 +140,6 @@ function mangle_properties(ast, options) {
if (!keep_quoted)
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(

View File

@@ -49,7 +49,6 @@ function SymbolDef(scope, index, orig) {
this.scope = scope;
this.references = [];
this.global = false;
this.export = false;
this.mangled_name = null;
this.undeclared = false;
this.index = index;
@@ -63,16 +62,11 @@ SymbolDef.prototype = {
if (!options) options = {};
return (this.global && !options.toplevel)
|| this.export
|| this.undeclared
|| (!options.eval && (this.scope.uses_eval || this.scope.uses_with))
|| (options.keep_fnames
&& (this.orig[0] instanceof AST_SymbolLambda
|| this.orig[0] instanceof AST_SymbolDefun))
|| this.orig[0] instanceof AST_SymbolMethod
|| (options.keep_classnames
&& (this.orig[0] instanceof AST_SymbolClass
|| this.orig[0] instanceof AST_SymbolDefClass));
|| this.orig[0] instanceof AST_SymbolDefun));
},
mangle: function(options) {
var cache = options.cache && options.cache.props;
@@ -103,7 +97,6 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
options = defaults(options, {
cache: null,
ie8: false,
safari10: false,
});
// pass 1: setup scope chaining and handle definitions
@@ -111,33 +104,15 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
var scope = self.parent_scope = null;
var labels = new Dictionary();
var defun = null;
var in_destructuring = null;
var for_scopes = [];
var tw = new TreeWalker(function(node, descend){
if (node.is_block_scope()) {
if (node instanceof AST_Catch) {
var save_scope = scope;
scope = new AST_Scope(node);
scope.init_scope_vars(save_scope);
if (!(node instanceof AST_Scope)) {
scope.uses_with = save_scope.uses_with;
scope.uses_eval = save_scope.uses_eval;
scope.directives = save_scope.directives;
}
if (options.safari10) {
if (node instanceof AST_For || node instanceof AST_ForIn) {
for_scopes.push(scope);
}
}
descend();
scope = save_scope;
return true;
}
if (node instanceof AST_Destructuring) {
in_destructuring = node; // These don't nest
descend();
in_destructuring = null;
return true;
}
if (node instanceof AST_Scope) {
node.init_scope_vars(scope);
var save_scope = scope;
@@ -182,29 +157,10 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
// scope when we encounter the AST_Defun node (which is
// instanceof AST_Scope) but we get to the symbol a bit
// later.
var parent_lambda = defun.parent_scope;
while (parent_lambda.is_block_scope()) {
parent_lambda = parent_lambda.parent_scope;
}
mark_export((node.scope = parent_lambda).def_function(node), 1);
(node.scope = defun.parent_scope).def_function(node);
}
else if (node instanceof AST_SymbolClass) {
mark_export(defun.def_variable(node), 1);
}
else if (node instanceof AST_SymbolImport) {
scope.def_variable(node);
}
else if (node instanceof AST_SymbolDefClass) {
// This deals with the name of the class being available
// inside the class.
mark_export((node.scope = defun.parent_scope).def_function(node), 1);
}
else if (node instanceof AST_SymbolVar
|| node instanceof AST_SymbolLet
|| node instanceof AST_SymbolConst) {
var def = ((node instanceof AST_SymbolBlockDeclaration) ? scope : defun).def_variable(node);
if (!(node instanceof AST_SymbolFunarg)) mark_export(def, 2);
def.destructuring = in_destructuring;
else if (node instanceof AST_SymbolVar) {
defun.def_variable(node);
if (defun !== scope) {
node.mark_enclosed(options);
var def = scope.find_variable(node);
@@ -226,26 +182,6 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
}));
node.thedef = sym;
}
if (!(scope instanceof AST_Toplevel) && (node instanceof AST_Export || node instanceof AST_Import)) {
js_error(
node.TYPE + " statement may only appear at top level",
node.start.file,
node.start.line,
node.start.col,
node.start.pos
);
}
function mark_export(def, level) {
if (in_destructuring) {
var i = 0;
do {
level++;
} while (tw.parent(i++) !== in_destructuring);
}
var node = tw.parent(level);
def.export = node instanceof AST_Export;
}
});
self.walk(tw);
@@ -263,9 +199,8 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
s.uses_eval = true;
}
}
var sym;
if (tw.parent() instanceof AST_NameMapping && tw.parent(1).module_name
|| !(sym = node.scope.find_variable(name))) {
var sym = node.scope.find_variable(name);
if (!sym) {
sym = self.def_global(node);
} else if (sym.scope instanceof AST_Lambda && name == "arguments") {
sym.scope.uses_arguments = true;
@@ -305,19 +240,6 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
}));
}
// pass 4: add symbol definitions to loop scopes
// Safari/Webkit bug workaround - loop init let variable shadowing argument.
// https://github.com/mishoo/UglifyJS2/issues/1753
// https://bugs.webkit.org/show_bug.cgi?id=171041
if (options.safari10) {
for (var i = 0; i < for_scopes.length; i++) {
var scope = for_scopes[i];
scope.parent_scope.variables.each(function(def) {
push_uniq(scope.enclosed, def);
});
}
}
if (options.cache) {
this.cname = options.cache.cname;
}
@@ -346,18 +268,10 @@ AST_Scope.DEFMETHOD("init_scope_vars", function(parent_scope){
this.cname = -1; // the current index for mangling functions/variables
});
AST_Node.DEFMETHOD("is_block_scope", return_false);
AST_Class.DEFMETHOD("is_block_scope", return_false);
AST_Lambda.DEFMETHOD("is_block_scope", return_false);
AST_Toplevel.DEFMETHOD("is_block_scope", return_false);
AST_SwitchBranch.DEFMETHOD("is_block_scope", return_false);
AST_Block.DEFMETHOD("is_block_scope", return_true);
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
@@ -391,9 +305,7 @@ AST_Scope.DEFMETHOD("find_variable", function(name){
});
AST_Scope.DEFMETHOD("def_function", function(symbol){
var def = this.def_variable(symbol);
this.functions.set(symbol.name, def);
return def;
this.functions.set(symbol.name, this.def_variable(symbol));
});
AST_Scope.DEFMETHOD("def_variable", function(symbol){
@@ -481,7 +393,6 @@ AST_Toplevel.DEFMETHOD("_default_mangler_options", function(options){
options = defaults(options, {
eval : false,
ie8 : false,
keep_classnames: false,
keep_fnames : false,
reserved : [],
toplevel : false,
@@ -535,18 +446,13 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options){
node.mangled_name = name;
return true;
}
var mangle_with_block_scope =
(!options.ie8 && node instanceof AST_SymbolCatch) ||
node instanceof AST_SymbolBlockDeclaration;
if (mangle_with_block_scope) {
if (!options.ie8 && node instanceof AST_SymbolCatch) {
to_mangle.push(node.definition());
return;
}
});
this.walk(tw);
to_mangle.forEach(function(def){
def.mangle(options);
});
to_mangle.forEach(function(def){ def.mangle(options) });
if (options.cache) {
options.cache.cname = this.cname;

View File

@@ -163,18 +163,10 @@ TreeTransformer.prototype = new TreeWalker;
if (self.value) self.value = self.value.transform(tw);
});
_(AST_Destructuring, function(self, tw) {
self.names = do_list(self.names, tw);
});
_(AST_Lambda, function(self, tw){
if (self.name) self.name = self.name.transform(tw);
self.argnames = do_list(self.argnames, tw);
if (self.body instanceof AST_Node) {
self.body = self.body.transform(tw);
} else {
self.body = do_list(self.body, tw);
}
self.body = do_list(self.body, tw);
});
_(AST_Call, function(self, tw){
@@ -195,14 +187,6 @@ TreeTransformer.prototype = new TreeWalker;
self.property = self.property.transform(tw);
});
_(AST_Yield, function(self, tw){
if (self.expression) self.expression = self.expression.transform(tw);
});
_(AST_Await, function(self, tw){
self.expression = self.expression.transform(tw);
});
_(AST_Unary, function(self, tw){
self.expression = self.expression.transform(tw);
});
@@ -227,50 +211,7 @@ TreeTransformer.prototype = new TreeWalker;
});
_(AST_ObjectProperty, function(self, tw){
if (self.key instanceof AST_Node) {
self.key = self.key.transform(tw);
}
self.value = self.value.transform(tw);
});
_(AST_Class, function(self, tw){
if (self.name) self.name = self.name.transform(tw);
if (self.extends) self.extends = self.extends.transform(tw);
self.properties = do_list(self.properties, tw);
});
_(AST_Expansion, function(self, tw){
self.expression = self.expression.transform(tw);
});
_(AST_NameMapping, function(self, tw) {
self.foreign_name = self.foreign_name.transform(tw);
self.name = self.name.transform(tw);
});
_(AST_Import, function(self, tw) {
if (self.imported_name) self.imported_name = self.imported_name.transform(tw);
if (self.imported_names) do_list(self.imported_names, tw);
self.module_name = self.module_name.transform(tw);
});
_(AST_Export, function(self, tw) {
if (self.exported_definition) self.exported_definition = self.exported_definition.transform(tw);
if (self.exported_value) self.exported_value = self.exported_value.transform(tw);
if (self.exported_names) do_list(self.exported_names, tw);
if (self.module_name) self.module_name = self.module_name.transform(tw);
});
_(AST_TemplateString, function(self, tw) {
for (var i = 0; i < self.segments.length; i++) {
if (!(self.segments[i] instanceof AST_TemplateSegment)) {
self.segments[i] = self.segments[i].transform(tw);
}
}
});
_(AST_PrefixedTemplateString, function(self, tw) {
self.template_string = self.template_string.transform(tw);
});
})();

View File

@@ -1,10 +1,10 @@
{
"name": "uglify-es",
"name": "uglify-js",
"description": "JavaScript parser, mangler/compressor and beautifier toolkit",
"homepage": "https://github.com/mishoo/UglifyJS2/tree/harmony",
"homepage": "http://lisperator.net/uglifyjs",
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
"license": "BSD-2-Clause",
"version": "3.0.22",
"version": "3.0.23",
"engines": {
"node": ">=0.8.0"
},
@@ -40,18 +40,5 @@
"scripts": {
"test": "node test/run-tests.js"
},
"keywords": [
"uglify",
"uglify-js",
"uglify-es",
"minify",
"minifier",
"es5",
"es6",
"es2015",
"es2016",
"es2017",
"async",
"await"
]
"keywords": ["uglify", "uglify-js", "minify", "minifier", "es5"]
}

View File

@@ -1,5 +1,3 @@
// NOTE trailing comma doesn't contribute to length of an array
// That also means the array changes length if previous element is a hole too and got cut off
holes_and_undefined: {
input: {
w = [1,,];
@@ -93,79 +91,6 @@ constant_join_2: {
}
}
spread_with_variable_as_last_element: {
input: {
var values = [4, 5, 6];
var a = [1, 2, 3, ...values];
}
expect: {
var values = [4, 5, 6];
var a = [1, 2, 3, ...values];
}
}
spread_with_variable_in_middle: {
input: {
var values = [4, 5, 6];
var a = [1, 2, 3, ...values, 7,,,];
}
expect: {
var values = [4, 5, 6];
var a = [1, 2, 3, ...values, 7,,,];
}
}
spread_with_variable_at_front: {
input: {
var values = [1, 2, 3];
var a = [...values, 4, 5, 6];
}
expect: {
var values = [1, 2, 3];
var a = [...values, 4, 5, 6];
}
}
spread_with_variable_at_front_after_elisions: {
input: {
var values = [1, 2, 3];
var a = [,,,...values, 4, 5, 6];
}
expect: {
var values = [1, 2, 3];
var a = [,,,...values, 4, 5, 6];
}
}
spread_with_array_at_end: {
input: {
var a = [1, 2, ...[4, 5, 6]];
}
expect: {
var a = [1, 2, ...[4, 5, 6]];
}
}
spread_with_logical_expression_at_end: {
options = { evaluate: true }
input: {
var a = [1, 2, 3, ...[2+2]]
}
expect: {
var a = [1, 2, 3, ...[4]]
}
}
spread_with_logical_expression_at_middle: {
options = { evaluate: true }
input: {
var a = [1, 1, ...[1+1, 1+2, 2+3], 8]
}
expect: {
var a = [1, 1, ...[2, 3, 5], 8]
}
}
constant_join_3: {
options = {
unsafe: true,

View File

@@ -1,540 +0,0 @@
arrow_functions_without_body: {
input: {
var a1 = () => 42;
var a2 = (p) => p;
var a3 = p => p;
var a4 = (...p) => p;
var a5 = (b, c) => b + c;
var a6 = (b, ...c) => b + c[0];
var a7 = (...b) => b.join();
}
expect: {
var a1 = () => 42;
var a2 = (p) => p;
var a3 = p => p;
var a4 = (...p) => p;
var a5 = (b, c) => b + c;
var a6 = (b, ...c) => b + c[0];
var a7 = (...b) => b.join();
}
}
arrow_functions_with_body: {
input: {
var a1 = () => {
var a = 42 * Math.random();
return a;
};
var a2 = (p) => {
var a = Math.random() * p;
return a;
};
var a3 = p => {
var a = Math.random() * p;
return a;
};
var a4 = (...p) => {
var a = Math.random() * p;
return a;
};
var a5 = (b, c) => {
var result = b * c + b / c;
return result
};
var a6 = (b, ...c) => {
var result = b;
for (var i = 0; i < c.length; i++)
result += c[i];
return result
};
var a7 = (...b) => {
b.join();
}
}
expect: {
var a1 = () => {
var a = 42 * Math.random();
return a;
};
var a2 = (p) => {
var a = Math.random() * p;
return a;
};
var a3 = p => {
var a = Math.random() * p;
return a;
};
var a4 = (...p) => {
var a = Math.random() * p;
return a;
};
var a5 = (b, c) => {
var result = b * c + b / c;
return result
};
var a6 = (b, ...c) => {
var result = b;
for (var i = 0; i < c.length; i++)
result += c[i];
return result
};
var a7 = (...b) => {
b.join();
};
}
}
arrow_function_with_single_parameter_with_default: {
input: {
var foo = (a = 0) => doSomething(a);
}
expect_exact: "var foo=(a=0)=>doSomething(a);"
}
arrow_binding_pattern: {
input: {
var foo = ([]) => "foo";
var bar = ({}) => "bar";
var with_default = (foo = "default") => foo;
var object_with_default = ({foo = "default", bar: baz = "default"}) => foo;
var array_after_spread = (...[foo]) => foo;
var array_after_spread = (...{foo}) => foo;
var computed = ({ [compute()]: x }) => {};
var array_hole = ([, , ...x] = [1, 2]) => {};
var object_trailing_elision = ({foo,}) => {};
var spread_empty_array = (...[]) => "foo";
var spread_empty_object = (...{}) => "foo";
}
expect: {
var foo = ([]) => "foo";
var bar = ({}) => "bar";
var with_default = (foo = "default") => foo;
var object_with_default = ({foo = "default", bar: baz = "default"}) => foo;
var array_after_spread = (...[foo]) => foo;
var array_after_spread = (...{foo}) => foo;
var computed = ({ [compute()]: x }) => {};
var array_hole = ([, , ...x] = [1, 2]) => {};
var object_trailing_elision = ({foo,}) => {};
var spread_empty_array = (...[]) => "foo";
var spread_empty_object = (...{}) => "foo";
}
}
arrow_binding_pattern_strict: {
input: {
var foo = ([,]) => "foo";
}
expect_exact: 'var foo=([,])=>"foo";'
}
arrow_with_regexp: {
input: {
num => /\d{11,14}/.test( num )
}
expect: {
num => /\d{11,14}/.test( num )
}
}
arrow_unused: {
options = {
toplevel: false,
side_effects: true,
unused: true,
}
input: {
top => dog;
let fn = a => { console.log(a * a); };
let u = (x, y) => x - y + g;
(() => { console.log("0"); })();
!function(x) {
(() => { console.log("1"); })();
let unused = x => { console.log(x); };
let baz = e => e + e;
console.log(baz(x));
}(1);
fn(3);
}
expect: {
let fn = a => { console.log(a * a); };
let u = (x, y) => x - y + g;
(() => { console.log("0"); })();
!function(x) {
(() => { console.log("1"); })();
let baz = e => e + e;
console.log(baz(x));
}(1);
fn(3);
}
expect_stdout: [ "0", "1", "2", "9" ]
node_version: ">=6"
}
arrow_unused_toplevel: {
options = {
toplevel: true,
side_effects: true,
unused: true,
}
input: {
top => dog;
let fn = a => { console.log(a * a); };
let u = (x, y) => x - y + g;
(() => { console.log("0"); })();
!function(x) {
(() => { console.log("1"); })();
let unused = x => { console.log(x); };
let baz = e => e + e;
console.log(baz(x));
}(1);
fn(3);
}
expect: {
let fn = a => { console.log(a * a); };
(() => { console.log("0"); })();
!function(x) {
(() => { console.log("1"); })();
let baz = e => e + e;
console.log(baz(x));
}(1);
fn(3);
}
expect_stdout: [ "0", "1", "2", "9" ]
node_version: ">=6"
}
no_leading_parentheses: {
input: {
(x,y) => x(y);
async (x,y) => await x(y);
}
expect_exact: "(x,y)=>x(y);async(x,y)=>await x(y);"
}
async_identifiers: {
options = {
arrows: true,
ecma: 6,
}
input: {
var async = function(x){ console.log("async", x); };
var await = function(x){ console.log("await", x); };
async(1);
await(2);
}
expect: {
var async = x => { console.log("async", x); };
var await = x => { console.log("await", x); };
async(1);
await(2);
}
expect_stdout: [
"async 1",
"await 2",
]
node_version: ">=4"
}
async_function_expression: {
options = {
arrows: true,
ecma: 6,
evaluate: true,
side_effects: true,
}
input: {
var named = async function foo() {
await bar(1 + 0) + (2 + 0);
}
var anon = async function() {
await (1 + 0) + bar(2 + 0);
}
}
expect: {
var named = async function foo() {
await bar(1);
};
var anon = async () => {
await 1, bar(2);
};
}
}
issue_27: {
options = {
arrows: true,
collapse_vars: true,
ecma: 6,
unused: true,
}
input: {
(function(jQuery) {
var $;
$ = jQuery;
$("body").addClass("foo");
})(jQuery);
}
expect: {
(jQuery => {
jQuery("body").addClass("foo");
})(jQuery);
}
}
issue_2105_1: {
options = {
arrows: true,
collapse_vars: true,
ecma: 6,
inline: true,
reduce_vars: true,
side_effects: true,
unused: true,
}
input: {
!function(factory) {
factory();
}( function() {
return function(fn) {
fn()().prop();
}( function() {
function bar() {
var quux = function() {
console.log("PASS");
}, foo = function() {
console.log;
quux();
};
return { prop: foo };
}
return bar;
} );
});
}
expect: {
void (() => {
var quux = () => {
console.log("PASS");
};
return {
prop: () => {
console.log;
quux();
}
};
})().prop();
}
expect_stdout: "PASS"
node_version: ">=4"
}
issue_2105_2: {
options = {
collapse_vars: true,
inline: true,
reduce_vars: true,
side_effects: true,
unused: true,
}
input: {
((factory) => {
factory();
})( () => {
return ((fn) => {
fn()().prop();
})( () => {
let bar = () => {
var quux = () => {
console.log("PASS");
}, foo = () => {
console.log;
quux();
};
return { prop: foo };
};
return bar;
} );
});
}
expect: {
void (() => {
var quux = () => {
console.log("PASS");
};
return {
prop: () => {
console.log;
quux();
}
};
})().prop();
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_2136_2: {
options = {
arrows: true,
collapse_vars: true,
ecma: 6,
inline: true,
side_effects: true,
unused: true,
}
input: {
function f(x) {
console.log(x);
}
!function(a, ...b) {
f(b[0]);
}(1, 2, 3);
}
expect: {
function f(x) {
console.log(x);
}
f([2,3][0]);
}
expect_stdout: "2"
node_version: ">=6"
}
issue_2136_3: {
options = {
arrows: true,
collapse_vars: true,
ecma: 6,
evaluate: true,
inline: true,
passes: 3,
reduce_vars: true,
side_effects: true,
toplevel: true,
unsafe: true,
unused: true,
}
input: {
function f(x) {
console.log(x);
}
!function(a, ...b) {
f(b[0]);
}(1, 2, 3);
}
expect: {
console.log(2);
}
expect_stdout: "2"
node_version: ">=6"
}
call_args: {
options = {
arrows: true,
ecma: 6,
evaluate: true,
inline: true,
reduce_vars: true,
}
input: {
const a = 1;
console.log(a);
+function(a) {
return a;
}(a);
}
expect: {
const a = 1;
console.log(1);
+(1, 1);
}
expect_stdout: true
}
call_args_drop_param: {
options = {
arrows: true,
ecma: 6,
evaluate: true,
inline: true,
keep_fargs: false,
reduce_vars: true,
unused: true,
}
input: {
const a = 1;
console.log(a);
+function(a) {
return a;
}(a, b);
}
expect: {
const a = 1;
console.log(1);
+(b, 1);
}
expect_stdout: true
}
issue_485_crashing_1530: {
options = {
arrows: true,
conditionals: true,
dead_code: true,
ecma: 6,
evaluate: true,
inline: true,
}
input: {
(function(a) {
if (true) return;
var b = 42;
})(this);
}
expect: {
this, void 0;
}
}
issue_2084: {
options = {
arrows: true,
collapse_vars: true,
conditionals: true,
ecma: 6,
evaluate: true,
inline: true,
passes: 2,
reduce_vars: true,
sequences: true,
side_effects: true,
unused: true,
}
input: {
var c = 0;
!function() {
!function(c) {
c = 1 + c;
var c = 0;
function f14(a_1) {
if (c = 1 + c, 0 !== 23..toString())
c = 1 + c, a_1 && (a_1[0] = 0);
}
f14();
}(-1);
}();
console.log(c);
}
expect: {
var c = 0;
((c) => {
c = 1 + c,
c = 1 + (c = 0),
0 !== 23..toString() && (c = 1 + c);
})(-1),
console.log(c);
}
expect_stdout: "0"
node_version: ">=4"
}

View File

@@ -1,294 +0,0 @@
await_precedence: {
input: {
async function f1() { await x + y; }
async function f2() { await (x + y); }
}
expect_exact: "async function f1(){await x+y}async function f2(){await(x+y)}"
}
await_precedence_prop: {
input: {
async function f1(){ return (await foo()).bar; }
async function f2(){ return (await foo().bar); }
}
expect_exact: "async function f1(){return(await foo()).bar}async function f2(){return await foo().bar}"
}
await_precedence_call: {
input: {
async function f3(){ return (await foo())(); }
async function f4(){ return await (foo()()); }
}
expect_exact: "async function f3(){return(await foo())()}async function f4(){return await foo()()}"
}
async_function_declaration: {
options = {
side_effects: true,
unused: true,
}
input: {
async function f0() {}
async function f1() { await x + y; }
async function f2() { await (x + y); }
async function f3() { await x + await y; }
async function f4() { await (x + await y); }
async function f5() { await x; await y; }
async function f6() { await x, await y; }
}
expect: {
async function f0() {}
async function f1() { await x, y; }
async function f2() { await (x + y); }
async function f3() { await x, await y; }
async function f4() { await (x + await y); }
async function f5() { await x; await y; }
async function f6() { await x, await y; }
}
}
async_function_expression: {
options = {
evaluate: true,
side_effects: true,
unused: true,
}
input: {
var named = async function foo() {
await bar(1 + 0) + (2 + 0);
}
var anon = async function() {
await (1 + 0) + bar(2 + 0);
}
}
expect: {
var named = async function() {
await bar(1);
};
var anon = async function() {
await 1, bar(2);
};
}
}
async_class: {
options = {
evaluate: true,
}
input: {
class Foo {
async m1() {
return await foo(1 + 2);
}
static async m2() {
return await foo(3 + 4);
}
}
}
expect: {
class Foo {
async m1() {
return await foo(3);
}
static async m2() {
return await foo(7);
}
}
}
}
async_object_literal: {
options = {
evaluate: true,
}
input: {
var obj = {
async a() {
await foo(1 + 0);
},
anon: async function(){
await foo(2 + 0);
}
};
}
expect: {
var obj = {
async a() {
await foo(1);
},
anon: async function() {
await foo(2);
}
};
}
}
async_export: {
input: {
export async function run() {};
export default async function def() {};
}
expect: {
export async function run() {};
export default async function def() {};
}
}
async_inline: {
options = {
collapse_vars: true,
conditionals: true,
evaluate: true,
inline: true,
negate_iife: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
(async function(){ return await 3; })();
(async function(x){ await console.log(x); })(4);
function echo(x) { return x; }
echo( async function(){ return await 1; }() );
echo( async function(x){ await console.log(x); }(2) );
function top() { console.log("top"); }
top();
async function async_top() { console.log("async_top"); }
async_top();
}
expect: {
!async function(){await 3}();
!async function(x){await console.log(4)}();
function echo(x){return x}
echo(async function(){return await 1}());
echo(async function(x){await console.log(2)}());
console.log("top");
!async function(){console.log("async_top")}();
}
expect_stdout: [
"4",
"2",
"top",
"async_top",
]
node_version: ">=8"
}
async_identifiers: {
input: {
var async = function(x){ console.log("async", x); };
var await = function(x){ console.log("await", x); };
async(1);
await(2);
}
expect: {
var async = function(x){ console.log("async", x); };
var await = function(x){ console.log("await", x); };
async(1);
await(2);
}
expect_stdout: [
"async 1",
"await 2",
]
}
async_shorthand_property: {
mangle = {
toplevel: true,
}
input: {
function print(o) { console.log(o.async + " " + o.await); }
var async = "Async", await = "Await";
print({ async });
print({ await });
print({ async, await });
print({ await, async });
print({ async: async });
print({ await: await });
print({ async: async, await: await });
print({ await: await, async: async });
}
expect: {
function a(a) { console.log(a.async + " " + a.await); }
var n = "Async", c = "Await";
a({ async: n });
a({ await: c });
a({ async: n, await: c });
a({ await: c, async: n });
a({ async: n });
a({ await: c });
a({ async: n, await: c });
a({ await: c, async: n });
}
expect_stdout: [
"Async undefined",
"undefined Await",
"Async Await",
"Async Await",
"Async undefined",
"undefined Await",
"Async Await",
"Async Await",
]
node_version: ">=4"
}
async_arrow: {
input: {
let a1 = async x => await foo(x);
let a2 = async () => await bar();
let a3 = async (x) => await baz(x);
let a4 = async (x, y) => { await far(x, y); }
let a5 = async ({x = [1], y: z = 2}) => { await wow(x, z); }
}
expect: {
let a1 = async x => await foo(x);
let a2 = async () => await bar();
let a3 = async (x) => await baz(x);
let a4 = async (x, y) => { await far(x, y); }
let a5 = async ({x = [1], y: z = 2}) => { await wow(x, z); }
}
}
async_arrow_wait: {
input: {
var a = async (x, y) => await x(y);
}
expect_exact: "var a=async(x,y)=>await x(y);"
}
async_arrow_iife: {
input: {
(async () => {
await fetch({});
})();
}
expect_exact: "(async()=>{await fetch({})})();"
}
async_arrow_iife_negate_iife: {
options = {
negate_iife: true,
}
input: {
(async () => {
await fetch();
})();
(() => {
plain();
})();
}
expect_exact: "(async()=>{await fetch()})();(()=>{plain()})();"
}

View File

@@ -1,191 +0,0 @@
let_statement: {
input: {
let x = 6;
}
expect_exact: "let x=6;"
}
do_not_hoist_let: {
options = {
hoist_vars: true,
};
input: {
function x() {
if (FOO) {
let let1;
let let2;
var var1;
var var2;
}
}
}
expect: {
function x() {
var var1, var2;
if (FOO) {
let let1;
let let2;
}
}
}
}
do_not_remove_anon_blocks_if_they_have_decls: {
input: {
function x() {
{
let x;
}
{
var x;
}
{
const y;
class Zee {};
}
}
{
let y;
}
{
var y;
}
}
expect: {
function x(){
{
let x
}
var x;
{
const y;
class Zee {}
}
}
{
let y
}
var y;
}
}
remove_unused_in_global_block: {
options = {
unused: true,
}
input: {
{
let x;
const y;
class Zee {};
var w;
}
let ex;
const why;
class Zed {};
var wut;
console.log(x, y, Zee);
}
expect: {
var w;
let ex;
const why;
class Zed {};
var wut;
console.log(x, y, Zee);
}
}
regression_block_scope_resolves: {
mangle = { };
options = {
dead_code: false
};
input: {
(function () {
if (1) {
let x;
const y = 1;
class Zee {};
}
if (1) {
let ex;
const why = 2;
class Zi {};
}
console.log(typeof x, typeof y, typeof Zee, typeof ex, typeof why, typeof Zi);
}());
}
expect: {
(function () {
if (1) {
let e;
const o = 1;
class t {};
}
if (1) {
let e;
const o = 2;
class t {};
}
console.log(typeof x, typeof y, typeof Zee, typeof ex, typeof why, typeof Zi);
}());
}
expect_stdout: "undefined undefined undefined undefined undefined undefined"
node_version: ">=6"
}
switch_block_scope_mangler: {
mangle = {}
input: {
var fn = function(code) {
switch (code) {
case 1:
let apple = code + 1;
let dog = code + 4;
console.log(apple, dog);
break;
case 2:
let banana = code + 2;
console.log(banana);
break;
default:
let cat = code + 3;
console.log(cat);
}
};
fn(1);
fn(2);
fn(3);
}
expect: {
var fn = function(e) {
switch (e) {
case 1:
let l = e + 1
let o = e + 4;
console.log(l, o);
break;
case 2:
let n = e + 2;
console.log(n);
break;
default:
let c = e + 3;
console.log(c);
}
};
fn(1);
fn(2);
fn(3);
}
expect_stdout: [
"2 5",
"4",
"6",
]
node_version: ">=6"
}

View File

@@ -47,142 +47,3 @@ keep_some_blocks: {
} else stuff();
}
}
issue_1664: {
input: {
var a = 1;
function f() {
if (undefined) a = 2;
{
function undefined() {}
undefined();
}
}
f();
console.log(a);
}
expect: {
var a = 1;
function f() {
if (undefined) a = 2;
{
function undefined() {}
undefined();
}
}
f();
console.log(a);
}
expect_stdout: "1"
node_version: ">=6"
}
issue_1672_for: {
input: {
switch (function() {
return xxx;
}) {
case xxx:
for (; console.log("FAIL");) {
function xxx() {}
}
break;
}
}
expect: {
switch (function() {
return xxx;
}) {
case xxx:
for (; console.log("FAIL");) {
function xxx() {}
}
break;
}
}
expect_stdout: true
node_version: ">=6"
}
issue_1672_for_strict: {
input: {
"use strict";
switch (function() {
return xxx;
}) {
case xxx:
for (; console.log("FAIL");) {
function xxx() {}
}
break;
}
}
expect: {
"use strict";
switch (function() {
return xxx;
}) {
case xxx:
for (; console.log("FAIL");) {
function xxx() {}
}
break;
}
}
expect_stdout: true
node_version: ">=6"
}
issue_1672_if: {
input: {
switch (function() {
return xxx;
}) {
case xxx:
if (console.log("FAIL")) {
function xxx() {}
}
break;
}
}
expect: {
switch (function() {
return xxx;
}) {
case xxx:
if (console.log("FAIL")) function xxx() {}
break;
}
}
expect_stdout: true
node_version: ">=6"
}
issue_1672_if_strict: {
input: {
"use strict";
switch (function() {
return xxx;
}) {
case xxx:
if (console.log("FAIL")) {
function xxx() {}
}
break;
}
}
expect: {
"use strict";
switch (function() {
return xxx;
}) {
case xxx:
if (console.log("FAIL")) {
function xxx() {}
}
break;
}
}
expect_stdout: true
node_version: ">=6"
}

View File

@@ -583,8 +583,8 @@ collapse_vars_assignment: {
return a = a;
}
function f1(c) {
const a = 3 / c;
const b = 1 - a;
var a = 3 / c;
var b = 1 - a;
return b;
}
function f2(c) {
@@ -724,10 +724,10 @@ collapse_vars_misc1: {
return t;
}
function f1(x) { var y = 5 - x; return y; }
function f2(x) { const z = foo(), y = z / (5 - x); return y; }
function f2(x) { var z = foo(), y = z / (5 - x); return y; }
function f3(x) { var z = foo(), y = (5 - x) / z; return y; }
function f4(x) { var z = foo(), y = (5 - u) / z; return y; }
function f5(x) { const z = foo(), y = (5 - window.x) / z; return y; }
function f5(x) { var z = foo(), y = (5 - window.x) / z; return y; }
function f6() { var b = window.a * window.z; return b && zap(); }
function f7() { var b = window.a * window.z; return b + b; }
function f8() { var b = window.a * window.z; var c = b + 5; return b + c; }
@@ -744,7 +744,7 @@ collapse_vars_misc1: {
function f2(x) { return foo() / (5 - x) }
function f3(x) { return (5 - x) / foo() }
function f4(x) { var z = foo(); return (5 - u) / z }
function f5(x) { const z = foo(); return (5 - window.x) / z }
function f5(x) { var z = foo(); return (5 - window.x) / z }
function f6() { return window.a * window.z && zap() }
function f7() { var b = window.a * window.z; return b + b }
function f8() { var b = window.a * window.z; return b + (b + 5) }
@@ -1328,7 +1328,6 @@ collapse_vars_regexp: {
issue_1537: {
options = {
collapse_vars: true,
toplevel: true,
}
input: {
var k = '';
@@ -1340,104 +1339,6 @@ issue_1537: {
}
}
issue_1537_for_of: {
options = {
collapse_vars: true,
toplevel: true,
}
input: {
var k = '';
for (k of {prop: 'val'}){}
}
expect: {
var k = '';
for (k of {prop: 'val'});
}
}
issue_1537_destructuring_1: {
options = {
collapse_vars: true,
toplevel: true,
}
input: {
var x = 1, y = 2;
[x] = [y];
}
expect: {
var x = 1, y = 2;
[x] = [y];
}
}
issue_1537_destructuring_2: {
options = {
collapse_vars: true,
toplevel: true,
}
input: {
var x = foo();
[x] = [1];
}
expect: {
var x = foo();
[x] = [1];
}
}
issue_1537_destructuring_3: {
options = {
collapse_vars: true,
toplevel: true,
}
input: {
var x = Math.random();
({p: x = 9} = {v: 1});
}
expect: {
var x = Math.random();
({p: x = 9} = {v: 1});
}
}
issue_1537_destructuring_for_in: {
options = {
collapse_vars: true,
toplevel: true,
}
input: {
var x = 1, y = 2;
(function() {
for ([[x], y] in a);
})();
}
expect: {
var x = 1, y = 2;
(function() {
for ([[x], y] in a);
})();
}
}
issue_1537_destructuring_for_of: {
options = {
collapse_vars: true,
toplevel: true,
}
input: {
var x = 1, y = 2;
(function() {
for ([[x], y] of a);
})();
}
expect: {
var x = 1, y = 2;
(function() {
for ([[x], y] of a);
})();
}
}
issue_1562: {
options = {
collapse_vars: true,
@@ -2077,10 +1978,10 @@ chained_3: {
}
expect: {
console.log(function(a, b) {
var c = a, c = b;
var c = 1, c = b;
b++;
return c;
}(1, 2));
}(0, 2));
}
expect_stdout: "2"
}
@@ -2203,10 +2104,11 @@ unused_orig: {
expect: {
var a = 1;
console.log(function(b) {
var a;
var c = b;
for (var d in c)
return --b + (a = c[0]);
for (var d in c) {
var a = c[0];
return --b + a;
}
a && a.NaN;
}([2]), a);
}
@@ -2285,48 +2187,72 @@ compound_assignment: {
expect_stdout: "4"
}
reassign_const_1: {
issue_2187_1: {
options = {
collapse_vars: true,
unused: true,
}
input: {
function f() {
const a = 1;
a = 2;
return a;
}
console.log(f());
var a = 1;
!function(foo) {
foo();
var a = 2;
console.log(a);
}(function() {
console.log(a);
});
}
expect: {
function f() {
const a = 1;
a = 2;
return a;
}
console.log(f());
var a = 1;
!function(foo) {
foo();
var a = 2;
console.log(a);
}(function() {
console.log(a);
});
}
expect_stdout: true
expect_stdout: [
"1",
"2",
]
}
reassign_const_2: {
issue_2187_2: {
options = {
collapse_vars: true,
unused: true,
}
input: {
function f() {
const a = 1;
++a;
return a;
}
console.log(f());
var b = 1;
console.log(function(a) {
return a && ++b;
}(b--));
}
expect: {
function f() {
const a = 1;
++a;
return a;
}
console.log(f());
var b = 1;
console.log(function(a) {
return b-- && ++b;
}());
}
expect_stdout: true
expect_stdout: "1"
}
issue_2187_3: {
options = {
collapse_vars: true,
inline: true,
unused: true,
}
input: {
var b = 1;
console.log(function(a) {
return a && ++b;
}(b--));
}
expect: {
var b = 1;
console.log(b-- && ++b);
}
expect_stdout: "1"
}

View File

@@ -1,166 +0,0 @@
issue_1191: {
options = {
evaluate : true,
booleans : true,
comparisons : true,
dead_code : true,
conditionals : true,
side_effects : true,
unused : true,
hoist_funs : true,
if_return : true,
join_vars : true,
sequences : false,
collapse_vars : false,
reduce_vars : true,
}
input: {
function foo(rot) {
const rotTol = 5;
if (rot < -rotTol || rot > rotTol)
bar();
baz();
}
}
expect: {
function foo(rot) {
(rot < -5 || rot > 5) && bar();
baz();
}
}
}
issue_1194: {
options = {
evaluate : true,
booleans : true,
comparisons : true,
dead_code : true,
conditionals : true,
side_effects : true,
unused : true,
hoist_funs : true,
if_return : true,
join_vars : true,
sequences : false,
collapse_vars : false,
reduce_vars : true,
}
input: {
function f1() {const a = "X"; return a + a;}
function f2() {const aa = "X"; return aa + aa;}
function f3() {const aaa = "X"; return aaa + aaa;}
}
expect: {
function f1(){return"XX"}
function f2(){return"XX"}
function f3(){return"XX"}
}
}
issue_1396: {
options = {
evaluate : true,
booleans : true,
comparisons : true,
dead_code : true,
conditionals : true,
side_effects : true,
unused : true,
hoist_funs : true,
if_return : true,
join_vars : true,
sequences : false,
collapse_vars : false,
reduce_vars : true,
}
input: {
function foo(a) {
const VALUE = 1;
console.log(2 | VALUE);
console.log(VALUE + 1);
console.log(VALUE);
console.log(a & VALUE);
}
function bar() {
const s = "01234567890123456789";
console.log(s + s + s + s + s);
const CONSTANT = "abc";
console.log(CONSTANT + CONSTANT + CONSTANT + CONSTANT + CONSTANT);
}
}
expect: {
function foo(a) {
console.log(3);
console.log(2);
console.log(1);
console.log(1 & a);
}
function bar() {
const s = "01234567890123456789";
console.log(s + s + s + s + s);
console.log("abcabcabcabcabc");
}
}
}
unused_regexp_literal: {
options = {
evaluate : true,
booleans : true,
comparisons : true,
dead_code : true,
conditionals : true,
side_effects : true,
unused : true,
hoist_funs : true,
if_return : true,
join_vars : true,
sequences : false,
collapse_vars : false,
}
input: {
function f(){ var a = /b/; }
}
expect: {
function f(){}
}
}
regexp_literal_not_const: {
options = {
evaluate : true,
booleans : true,
comparisons : true,
dead_code : true,
conditionals : true,
side_effects : true,
unused : true,
hoist_funs : true,
if_return : true,
join_vars : true,
sequences : false,
collapse_vars : false,
reduce_vars : true,
}
input: {
(function(){
var result;
const s = 'acdabcdeabbb';
const REGEXP_LITERAL = /ab*/g;
while (result = REGEXP_LITERAL.exec(s)) {
console.log(result[0]);
}
})();
}
expect: {
(function() {
var result;
const REGEXP_LITERAL = /ab*/g;
while (result = REGEXP_LITERAL.exec("acdabcdeabbb")) console.log(result[0]);
})();
}
expect_stdout: true
}

View File

@@ -54,12 +54,12 @@ dead_code_2_should_warn: {
x = 10;
throw new Error("foo");
var x;
var g;
function g(){};
}
f();
}
expect_stdout: true
node_version: ">=6"
node_version: "<=4"
}
dead_code_2_should_warn_strict: {
@@ -126,7 +126,7 @@ dead_code_constant_boolean_should_warn_more: {
}
expect: {
var foo;
var bar;
function bar() {}
// nothing for the while
// as for the for, it should keep:
var x = 10, y;
@@ -134,7 +134,7 @@ dead_code_constant_boolean_should_warn_more: {
bar();
}
expect_stdout: true
node_version: ">=6"
node_version: "<=4"
}
dead_code_constant_boolean_should_warn_more_strict: {
@@ -173,153 +173,6 @@ dead_code_constant_boolean_should_warn_more_strict: {
node_version: ">=4"
}
dead_code_block_decls_die: {
options = {
dead_code : true,
conditionals : true,
booleans : true,
evaluate : true
};
input: {
if (0) {
let foo = 6;
const bar = 12;
class Baz {};
var qux;
}
console.log(foo, bar, Baz);
}
expect: {
var qux;
console.log(foo, bar, Baz);
}
}
dead_code_const_declaration: {
options = {
dead_code : true,
loops : true,
booleans : true,
conditionals : true,
evaluate : true,
reduce_vars : true,
};
input: {
var unused;
const CONST_FOO = false;
if (CONST_FOO) {
console.log("unreachable");
var moo;
function bar() {}
}
}
expect: {
var unused;
const CONST_FOO = !1;
var moo;
var bar;
}
expect_stdout: true
}
dead_code_const_annotation: {
options = {
dead_code : true,
loops : true,
booleans : true,
conditionals : true,
evaluate : true,
reduce_vars : true,
toplevel : true,
};
input: {
var unused;
/** @const */ var CONST_FOO_ANN = false;
if (CONST_FOO_ANN) {
console.log("unreachable");
var moo;
function bar() {}
}
}
expect: {
var unused;
var CONST_FOO_ANN = !1;
var moo;
var bar;
}
expect_stdout: true
}
dead_code_const_annotation_regex: {
options = {
dead_code : true,
loops : true,
booleans : true,
conditionals : true,
evaluate : true
};
input: {
var unused;
// @constraint this shouldn't be a constant
var CONST_FOO_ANN = false;
if (CONST_FOO_ANN) {
console.log("reachable");
}
}
expect: {
var unused;
var CONST_FOO_ANN = !1;
CONST_FOO_ANN && console.log('reachable');
}
expect_stdout: true
}
dead_code_const_annotation_complex_scope: {
options = {
dead_code : true,
loops : true,
booleans : true,
conditionals : true,
evaluate : true,
reduce_vars : true,
toplevel : true,
};
input: {
var unused_var;
/** @const */ var test = 'test';
// @const
var CONST_FOO_ANN = false;
var unused_var_2;
if (CONST_FOO_ANN) {
console.log("unreachable");
var moo;
function bar() {}
}
if (test === 'test') {
var beef = 'good';
/** @const */ var meat = 'beef';
var pork = 'bad';
if (meat === 'pork') {
console.log('also unreachable');
} else if (pork === 'good') {
console.log('reached, not const');
}
}
}
expect: {
var unused_var;
var test = 'test';
var CONST_FOO_ANN = !1;
var unused_var_2;
var moo;
var bar;
var beef = 'good';
var meat = 'beef';
var pork = 'bad';
}
expect_stdout: true
}
try_catch_finally: {
options = {
conditionals: true,

View File

@@ -1,661 +0,0 @@
destructuring_arrays: {
input: {
{const [aa, bb] = cc;}
{const [aa, [bb, cc]] = dd;}
{let [aa, bb] = cc;}
{let [aa, [bb, cc]] = dd;}
var [aa, bb] = cc;
var [aa, [bb, cc]] = dd;
var [,[,,,,,],,,zz,] = xx; // Trailing comma
var [,,zzz,,] = xxx; // Trailing comma after hole
}
expect: {
{const [aa, bb] = cc;}
{const [aa, [bb, cc]] = dd;}
{let [aa, bb] = cc;}
{let [aa, [bb, cc]] = dd;}
var [aa, bb] = cc;
var [aa, [bb, cc]] = dd;
var [,[,,,,,],,,zz] = xx;
var [,,zzz,,] = xxx;
}
}
destructuring_arrays_holes: {
input: {
var [,,,,] = a;
var [,,b,] = c;
var [d,,] = e;
}
expect_exact: "var[,,,,]=a;var[,,b]=c;var[d,,]=e;"
}
destructuring_objects: {
input: {
{const {aa, bb} = {aa:1, bb:2};}
{const {aa, bb: {cc, dd}} = {aa:1, bb: {cc:2, dd: 3}};}
{let {aa, bb} = {aa:1, bb:2};}
{let {aa, bb: {cc, dd}} = {aa:1, bb: {cc:2, dd: 3}};}
var {aa, bb} = {aa:1, bb:2};
var {aa, bb: {cc, dd}} = {aa:1, bb: {cc:2, dd: 3}};
}
expect: {
{const {aa, bb} = {aa:1, bb:2};}
{const {aa, bb: {cc, dd}} = {aa:1, bb: {cc:2, dd: 3}};}
{let {aa, bb} = {aa:1, bb:2};}
{let {aa, bb: {cc, dd}} = {aa:1, bb: {cc:2, dd: 3}};}
var {aa, bb} = {aa:1, bb:2};
var {aa, bb: {cc, dd}} = {aa:1, bb: {cc:2, dd: 3}};
}
}
destructuring_objects_trailing_elision: {
beautify = {
ecma: 6
}
input: {
var {cc,} = foo;
}
expect_exact: "var{cc}=foo;"
}
nested_destructuring_objects: {
beautify = {
ecma: 6
}
input: {
const [{a},b] = c;
let [{a},b] = c;
var [{a},b] = c;
}
expect_exact: 'const[{a},b]=c;let[{a},b]=c;var[{a},b]=c;';
}
destructuring_constdef_in_loops: {
beautify = {
ecma: 6
}
input: {
for (const [x,y] in pairs);
for (const [a] = 0;;);
for (const {c} of cees);
}
expect_exact: "for(const[x,y]in pairs);for(const[a]=0;;);for(const{c}of cees);"
}
destructuring_letdef_in_loops: {
beautify = {
ecma: 6
}
input: {
for (let [x,y] in pairs);
for (let [a] = 0;;);
for (let {c} of cees);
}
expect_exact: "for(let[x,y]in pairs);for(let[a]=0;;);for(let{c}of cees);"
}
destructuring_vardef_in_loops: {
beautify = {
ecma: 6
}
input: {
for (var [x,y] in pairs);
for (var [a] = 0;;);
for (var {c} of cees);
}
expect_exact: "for(var[x,y]in pairs);for(var[a]=0;;);for(var{c}of cees);"
}
destructuring_expressions: {
beautify = {
ecma: 6
}
input: {
({a, b});
[{a}];
f({x});
}
expect_exact: "({a,b});[{a}];f({x});"
}
destructuring_remove_unused_1: {
options = {
unused: true
}
input: {
function a() {
var unused = "foo";
var a = [1];
var [b] = a;
f(b);
}
function b() {
var unused = "foo";
var a = {b: 1};
var {b} = a;
f(b);
}
function c() {
var unused = "foo";
var a = [[1]];
var [[b]] = a;
f(b);
}
function d() {
var unused = "foo";
var a = {b: {b:1}};
var {b:{b}} = a;
f(b);
}
function e() {
var unused = "foo";
var a = [1, 2, 3, 4, 5];
var x = [[1, 2, 3]];
var y = {h: 1};
var [b, ...c] = a;
var [...[e, f]] = x;
var [...{g: h}] = y;
f(b, c, e, f, g);
}
}
expect: {
function a() {
var a = [1];
var [b] = a;
f(b);
}
function b() {
var a = {b: 1};
var {b} = a;
f(b);
}
function c() {
var a = [[1]];
var [[b]] = a;
f(b);
}
function d() {
var a = {b: {b:1}};
var {b:{b}} = a;
f(b);
}
function e() {
var a = [1, 2, 3, 4, 5];
var x = [[1, 2, 3]];
var y = {h: 1};
var [b, ...c] = a;
var [...[e, f]] = x;
var [...{g: h}] = y;
f(b, c, e, f, g);
}
}
}
destructuring_remove_unused_2: {
options = {
unused: true
}
input: {
function a() {
var unused = "foo";
var a = [,,1];
var [b] = a;
f(b);
}
function b() {
var unused = "foo";
var a = [{a: [1]}];
var [{b: a}] = a;
f(b);
}
}
expect: {
function a() {
var a = [,,1];
var [b] = a;
f(b);
}
function b() {
var a = [{a: [1]}];
var [{b: a}] = a;
f(b);
}
}
}
object_destructuring_may_need_parentheses: {
beautify = {
ecma: 6
}
input: {
({a, b} = {a: 1, b: 2});
}
expect_exact: "({a,b}={a:1,b:2});"
}
destructuring_with_undefined_as_default_assignment: {
options = {
evaluate: true
}
input: {
[foo = undefined] = bar;
[foo = void 0] = bar;
}
expect: {
[foo] = bar;
[foo] = bar;
}
}
destructuring_dont_evaluate_with_undefined_as_default_assignment: {
options = {
evaluate: false
}
input: {
[foo = undefined] = bar;
}
expect: {
[foo = void 0] = bar;
}
}
reduce_vars: {
options = {
reduce_vars: true,
}
input: {
{const [aa, [bb, cc]] = dd;}
{let [aa, [bb, cc]] = dd;}
var [aa, [bb, cc]] = dd;
[aa, [bb, cc]] = dd;
{const {aa, bb: {cc, dd}} = {aa:1, bb: {cc:2, dd: 3}};}
{let {aa, bb: {cc, dd}} = {aa:1, bb: {cc:2, dd: 3}};}
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;
[{a},b] = c;
for (const [x,y] in pairs);
for (let [x,y] in pairs);
for (var [x,y] in pairs);
for ([x,y] in pairs);
}
expect: {
{const [aa, [bb, cc]] = dd;}
{let [aa, [bb, cc]] = dd;}
var [aa, [bb, cc]] = dd;
[aa, [bb, cc]] = dd;
{const {aa, bb: {cc, dd}} = {aa:1, bb: {cc:2, dd: 3}};}
{let {aa, bb: {cc, dd}} = {aa:1, bb: {cc:2, dd: 3}};}
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;
[{a},b] = c;
for (const [x,y] in pairs);
for (let [x,y] in pairs);
for (var [x,y] in pairs);
for ([x,y] in pairs);
}
}
unused: {
options = {
unused: true,
}
input: {
let { foo: [, , ...a] } = { foo: [1, 2, 3, 4], bar: 5 };
console.log(a);
}
expect: {
let { foo: [, , ...a] } = { foo: [1, 2, 3, 4], bar: 5 };
console.log(a);
}
}
issue_1886: {
options = {
collapse_vars: true,
}
input: {
let [a] = [1];
console.log(a);
}
expect: {
let [a] = [1];
console.log(a);
}
}
destructuring_decl_of_numeric_key: {
options = {
evaluate: true,
unused: true,
}
input: {
let { 3: x } = { [1 + 2]: 42 };
console.log(x);
}
expect: {
let { 3: x } = { [3]: 42 };
console.log(x);
}
expect_stdout: "42"
node_version: ">=6"
}
destructuring_decl_of_computed_key: {
options = {
evaluate: true,
unused: true,
}
input: {
let four = 4;
let { [7 - four]: x } = { [1 + 2]: 42 };
console.log(x);
}
expect: {
let four = 4;
let { [7 - four]: x } = { [3]: 42 };
console.log(x);
}
expect_stdout: "42"
node_version: ">=6"
}
destructuring_assign_of_numeric_key: {
options = {
evaluate: true,
unused: true,
}
input: {
let x;
({ 3: x } = { [1 + 2]: 42 });
console.log(x);
}
expect: {
let x;
({ 3: x } = { [3]: 42 });
console.log(x);
}
expect_stdout: "42"
node_version: ">=6"
}
destructuring_assign_of_computed_key: {
options = {
evaluate: true,
unused: true,
}
input: {
let x;
let four = 4;
({ [(5 + 2) - four]: x } = { [1 + 2]: 42 });
console.log(x);
}
expect: {
let x;
let four = 4;
({ [7 - four]: x } = { [3]: 42 });
console.log(x);
}
expect_stdout: "42"
node_version: ">=6"
}
mangle_destructuring_decl: {
options = {
evaluate: true,
unused: true,
}
mangle = {
}
input: {
function test(opts) {
let a = opts.a || { e: 7, n: 8 };
let { t, e, n, s = 5 + 4, o, r } = a;
console.log(t, e, n, s, o, r);
}
test({a: { t: 1, e: 2, n: 3, s: 4, o: 5, r: 6 }});
test({});
}
expect: {
function test(t) {
let e = t.a || { e: 7, n: 8 };
let {t: n, e: o, n: s, s: l = 9, o: a, r: c} = e;
console.log(n, o, s, l, a, c);
}
test({ a: { t: 1, e: 2, n: 3, s: 4, o: 5, r: 6 } });
test({});
}
expect_stdout: [
"1 2 3 4 5 6",
"undefined 7 8 9 undefined undefined",
]
node_version: ">=6"
}
mangle_destructuring_assign_toplevel_true: {
options = {
toplevel: true,
evaluate: true,
unused: true,
}
mangle = {
toplevel: true,
}
beautify = {
ecma: 6
}
input: {
function test(opts) {
let s, o, r;
let a = opts.a || { e: 7, n: 8 };
({ t, e, n, s = 5 + 4, o, r } = a);
console.log(t, e, n, s, o, r);
}
let t, e, n;
test({a: { t: 1, e: 2, n: 3, s: 4, o: 5, r: 6 }});
test({});
}
expect: {
function e(e) {
let l, s, a;
let c = e.a || { e: 7, n: 8 };
({t: n, e: o, n: t, s: l = 9, o: s, r: a} = c);
console.log(n, o, t, l, s, a);
}
let n, o, t;
e({ a: { t: 1, e: 2, n: 3, s: 4, o: 5, r: 6 } });
e({});
}
expect_stdout: [
"1 2 3 4 5 6",
"undefined 7 8 9 undefined undefined",
]
node_version: ">=6"
}
mangle_destructuring_assign_toplevel_false: {
options = {
toplevel: false,
evaluate: true,
unused: true,
}
mangle = {
toplevel: false,
}
beautify = {
ecma: 6
}
input: {
function test(opts) {
let s, o, r;
let a = opts.a || { e: 7, n: 8 };
({ t, e, n, s = 9, o, r } = a);
console.log(t, e, n, s, o, r);
}
let t, e, n;
test({a: { t: 1, e: 2, n: 3, s: 4, o: 5, r: 6 }});
test({});
}
expect: {
function test(o) {
let s, l, a;
let c = o.a || { e: 7, n: 8 };
({t, e, n, s = 9, o: l, r: a} = c);
console.log(t, e, n, s, l, a);
}
let t, e, n;
test({ a: { t: 1, e: 2, n: 3, s: 4, o: 5, r: 6 } });
test({});
}
expect_stdout: [
"1 2 3 4 5 6",
"undefined 7 8 9 undefined undefined",
]
node_version: ">=6"
}
mangle_destructuring_decl_array: {
options = {
evaluate: true,
unused: true,
toplevel: true,
}
mangle = {
toplevel: true,
}
beautify = {
ecma: 6
}
input: {
var [, t, e, n, s, o = 2, r = [ 1 + 2 ]] = [ 9, 8, 7, 6 ];
console.log(t, e, n, s, o, r);
}
expect: {
var [, o, l, a, c, e = 2, g = [ 3 ]] = [ 9, 8, 7, 6 ];
console.log(o, l, a, c, e, g);
}
expect_stdout: "8 7 6 undefined 2 [ 3 ]"
node_version: ">=6"
}
anon_func_with_destructuring_args: {
options = {
evaluate: true,
unused: true,
toplevel: true,
}
mangle = {
toplevel: true,
}
beautify = {
ecma: 5,
}
input: {
(function({foo = 1 + 0, bar = 2}, [car = 3, far = 4]) {
console.log(foo, bar, car, far);
})({bar: 5 - 0}, [, 6]);
}
expect: {
(function({foo: o = 1, bar: n = 2}, [a = 3, b = 4]) {
console.log(o, n, a, b);
})({bar: 5}, [, 6]);
}
expect_stdout: "1 5 3 6"
node_version: ">=6"
}
arrow_func_with_destructuring_args: {
options = {
evaluate: true,
unused: true,
toplevel: true,
}
mangle = {
toplevel: true,
}
beautify = {
ecma: 5,
}
input: {
(({foo = 1 + 0, bar = 2}, [car = 3, far = 4]) => {
console.log(foo, bar, car, far);
})({bar: 5 - 0}, [, 6]);
}
expect: {
(({foo: o = 1, bar: a = 2}, [b = 3, l = 4]) => {
console.log(o, a, b, l);
})({bar: 5}, [, 6]);
}
expect_stdout: "1 5 3 6"
node_version: ">=6"
}
issue_2044_ecma_5: {
beautify = {
beautify: false,
ecma: 5,
}
input: {
({x : a = 1, y = 2 + b, z = 3 - c} = obj);
}
expect_exact: "({x:a=1,y:y=2+b,z:z=3-c}=obj);"
}
issue_2044_ecma_6: {
beautify = {
beautify: false,
ecma: 6,
}
input: {
({x : a = 1, y = 2 + b, z = 3 - c} = obj);
}
expect_exact: "({x:a=1,y=2+b,z=3-c}=obj);"
}
issue_2044_ecma_5_beautify: {
beautify = {
beautify: true,
ecma: 5,
}
input: {
({x : a = 1, y = 2 + b, z = 3 - c} = obj);
}
expect_exact: "({x: a = 1, y: y = 2 + b, z: z = 3 - c} = obj);"
}
issue_2044_ecma_6_beautify: {
beautify = {
beautify: true,
ecma: 6,
}
input: {
({x : a = 1, y = 2 + b, z = 3 - c} = obj);
}
expect_exact: "({x: a = 1, y = 2 + b, z = 3 - c} = obj);"
}
issue_2140: {
options = {
unused: true,
}
input: {
!function() {
var t = {};
console.log(([t.a] = [42])[0]);
}();
}
expect: {
!function() {
var t = {};
console.log(([t.a] = [42])[0]);
}();
}
expect_stdout: "42"
node_version: ">=6"
}

View File

@@ -1,10 +0,0 @@
class_directives_compression: {
input: {
class foo {
foo() {
"use strict";
}
}
}
expect_exact: "class foo{foo(){}}"
}

View File

@@ -164,87 +164,6 @@ used_var_in_catch: {
}
}
unused_block_decls_in_catch: {
options = { unused: true };
input: {
function foo() {
try {
foo();
} catch(ex) {
let x = 10;
const y = 10;
class Zee {};
}
}
}
expect: {
function foo() {
try {
foo();
} catch(ex) {}
}
}
}
used_block_decls_in_catch: {
options = { unused: true };
input: {
function foo() {
try {
foo();
} catch(ex) {
let x = 10;
const y = 10;
class Zee {};
}
console.log(x, y, Zee);
}
}
expect: {
function foo() {
try {
foo();
} catch(ex) {}
console.log(x, y, Zee);
}
}
}
unused_block_decls: {
options = { unused: true };
input: {
function foo() {
{
const x;
}
{
let y;
}
console.log(x, y);
}
}
expect: {
function foo() {
console.log(x, y);
}
}
}
unused_keep_harmony_destructuring: {
options = { unused: true };
input: {
function foo() {
var {x, y} = foo;
var a = foo;
}
}
expect: {
function foo() {
var {x, y} = foo;
}
}
}
keep_fnames: {
options = { unused: true, keep_fnames: true, unsafe: true };
input: {
@@ -730,37 +649,6 @@ drop_value: {
}
}
const_assign: {
options = {
evaluate: true,
reduce_vars: true,
unused: true,
}
input: {
function f() {
const b = 2;
return 1 + b;
}
function g() {
const b = 2;
b = 3;
return 1 + b;
}
}
expect: {
function f() {
return 3;
}
function g() {
const b = 2;
b = 3;
return 1 + b;
}
}
}
issue_1539: {
options = {
cascade: true,
@@ -897,10 +785,6 @@ issue_1709: {
var x = 1;
return x;
}(),
function y() {
const y = 2;
return y;
}(),
function z() {
function z() {}
return z;
@@ -913,10 +797,6 @@ issue_1709: {
var x = 1;
return x;
}(),
function() {
const y = 2;
return y;
}(),
function() {
function z() {}
return z;
@@ -1229,76 +1109,11 @@ var_catch_toplevel: {
}
}
reassign_const: {
options = {
cascade: true,
sequences: true,
side_effects: true,
unused: true,
}
input: {
function f() {
const a = 1;
a = 2;
return a;
}
console.log(f());
}
expect: {
function f() {
const a = 1;
return a = 2, a;
}
console.log(f());
}
expect_stdout: true
}
issue_1968: {
options = {
unused: true,
}
input: {
function f(c) {
var a;
if (c) {
let b;
return (a = 2) + (b = 3);
}
}
console.log(f(1));
}
expect: {
function f(c) {
if (c) {
let b;
return 2 + (b = 3);
}
}
console.log(f(1));
}
expect_stdout: "5"
node_version: ">=6"
}
issue_2063: {
options = {
unused: true,
}
input: {
var a;
var a;
}
expect: {
var a;
var a;
}
}
issue_2105: {
options = {
collapse_vars: true,
inline: true,
passes: 3,
reduce_vars: true,
side_effects: true,
unused: true,
@@ -1324,7 +1139,7 @@ issue_2105: {
});
}
expect: {
!void function() {
(function() {
var quux = function() {
console.log("PASS");
};
@@ -1334,95 +1149,7 @@ issue_2105: {
quux();
}
};
}().prop();
})().prop();
}
expect_stdout: "PASS"
}
issue_2136_1: {
options = {
inline: true,
unused: true,
}
input: {
!function(a, ...b) {
console.log(b);
}();
}
expect: {
!function(a, ...b) {
console.log(b);
}();
}
expect_stdout: "[]"
node_version: ">=6"
}
issue_2136_2: {
options = {
collapse_vars: true,
inline: true,
side_effects: true,
unused: true,
}
input: {
function f(x) {
console.log(x);
}
!function(a, ...b) {
f(b[0]);
}(1, 2, 3);
}
expect: {
function f(x) {
console.log(x);
}
f([2,3][0]);
}
expect_stdout: "2"
node_version: ">=6"
}
issue_2136_3: {
options = {
collapse_vars: true,
evaluate: true,
inline: true,
passes: 3,
reduce_vars: true,
side_effects: true,
toplevel: true,
unsafe: true,
unused: true,
}
input: {
function f(x) {
console.log(x);
}
!function(a, ...b) {
f(b[0]);
}(1, 2, 3);
}
expect: {
console.log(2);
}
expect_stdout: "2"
node_version: ">=6"
}
issue_2163: {
options = {
pure_funcs: [ "pure" ],
side_effects: true,
}
input: {
var c;
/*@__PURE__*/f(...a);
pure(b, ...c);
}
expect: {
var c;
a;
b;
}
}

View File

@@ -224,100 +224,6 @@ positive_zero: {
expect_stdout: true
}
pow: {
options = { evaluate: true }
input: {
var a = 5 ** 3;
}
expect: {
var a = 125;
}
}
pow_sequence: {
options = {
evaluate: true
}
input: {
var a = 2 ** 3 ** 2;
}
expect: {
var a = 512;
}
}
pow_mixed: {
options = {
evaluate: true
}
input: {
var a = 5 + 2 ** 3 + 5;
var b = 5 * 3 ** 2;
var c = 5 ** 3 * 2;
var d = 5 ** +3;
}
expect: {
var a = 18;
var b = 45;
var c = 250;
var d = 125;
}
}
pow_with_right_side_evaluating_to_unary: {
options = {
evaluate: true
}
input: {
var a = (4 - 7) ** foo;
var b = ++bar ** 3;
var c = --baz ** 2;
}
expect_exact: "var a=(-3)**foo;var b=++bar**3;var c=--baz**2;"
}
pow_with_number_constants: {
options = {
evaluate: true
}
input: {
var a = 5 ** NaN;
/* NaN exponent results to NaN */
var b = 42 ** +0;
/* +0 exponent results to NaN */
var c = 42 ** -0;
/* -0 exponent results to NaN */
var d = NaN ** 1;
/* NaN with non-zero exponent is NaN */
var e = 2 ** Infinity;
/* abs(base) > 1 with Infinity as exponent is Infinity */
var f = 2 ** -Infinity;
/* abs(base) > 1 with -Infinity as exponent is +0 */
var g = (-7) ** (0.5);
var h = 2324334 ** 34343443;
var i = (-2324334) ** 34343443;
var j = 2 ** (-3);
var k = 2.0 ** -3;
var l = 2.0 ** (5 - 7);
var m = 3 ** -10; // Result will be 0.000016935087808430286, which is too long
}
expect: {
var a = NaN;
var b = 1;
var c = 1;
var d = NaN;
var e = 1/0;
var f = 0;
var g = NaN;
var h = 1/0;
var i = -1/0;
var j = .125;
var k = .125;
var l = .25;
var m = 3 ** -10;
}
}
unsafe_constant: {
options = {
evaluate : true,
@@ -740,16 +646,17 @@ call_args: {
evaluate: true,
inline: true,
reduce_vars: true,
toplevel: true,
}
input: {
const a = 1;
var a = 1;
console.log(a);
+function(a) {
return a;
}(a);
}
expect: {
const a = 1;
var a = 1;
console.log(1);
+(1, 1);
}
@@ -762,17 +669,17 @@ call_args_drop_param: {
inline: true,
keep_fargs: false,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
const a = 1;
var a = 1;
console.log(a);
+function(a) {
return a;
}(a, b);
}
expect: {
const a = 1;
console.log(1);
+(b, 1);
}

View File

@@ -1,28 +0,0 @@
expand_arguments: {
input: {
func(a, ...rest);
func(...all);
}
expect_exact: "func(a,...rest);func(...all);"
}
expand_expression_arguments: {
input: {
f(...a.b);
f(...a.b());
f(...(a));
f(...(a.b));
f(...a[i]);
}
expect_exact: "f(...a.b);f(...a.b());f(...a);f(...a.b);f(...a[i]);"
}
expand_parameters: {
input: {
(function (a, ...b){});
(function (...args){});
}
expect_exact: "(function(a,...b){});(function(...args){});"
}

View File

@@ -1,228 +0,0 @@
issue_2038_1: {
options = {
toplevel: true,
unused: true,
}
mangle = {
toplevel: true,
}
input: {
export var V = 1;
export let L = 2;
export const C = 3;
}
expect: {
export var V = 1;
export let L = 2;
export const C = 3;
}
}
issue_2038_2: {
options = {
toplevel: true,
unused: true,
}
mangle = {
toplevel: true,
}
input: {
let LET = 1;
const CONST = 2;
var VAR = 3;
export { LET, CONST, VAR };
}
expect: {
let t = 1;
const e = 2;
var o = 3;
export { t as LET, e as CONST, o as VAR };
}
}
issue_2126: {
mangle = {
toplevel: true,
}
input: {
import { foo as bar, cat as dog } from "stuff";
console.log(bar, dog);
export { bar as qux };
export { dog };
}
expect: {
import { foo as o, cat as s } from "stuff";
console.log(o, s);
export { o as qux };
export { s as dog };
}
}
beautify: {
beautify = {
beautify: true,
}
input: {
export { A as B, C as D };
}
expect_exact: "export { A as B, C as D };"
}
issue_2131: {
options = {
toplevel: true,
unused: true,
}
input: {
function no() {
console.log(42);
}
function go() {
console.log(42);
}
var X = 1, Y = 2;
export function main() {
go(X);
};
}
expect: {
function go() {
console.log(42);
}
var X = 1;
export function main() {
go(X);
};
}
}
issue_2129: {
mangle = {
toplevel: true,
}
input: {
export const { keys } = Object;
}
expect: {
export const { keys } = Object;
}
}
async_func: {
options = {
keep_fargs: false,
unused: true,
}
input: {
export async function Foo(x){};
}
expect: {
export async function Foo(){};
}
}
issue_2134_1: {
options = {
keep_fargs: false,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
export function Foo(x){};
Foo.prototype = {};
}
expect: {
export function Foo(){};
Foo.prototype = {};
}
}
issue_2134_2: {
options = {
keep_fargs: false,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
export async function Foo(x){};
Foo.prototype = {};
}
expect: {
export async function Foo(){};
Foo.prototype = {};
}
}
redirection: {
mangle = {
toplevel: true,
}
input: {
let foo = 1, bar = 2;
export { foo as delete };
export { bar as default };
export { foo as var } from "module.js";
}
expect: {
let e = 1, o = 2;
export { e as delete };
export { o as default };
export { foo as var } from "module.js";
}
}
keyword_invalid_1: {
input: {
export { default };
}
expect: {
export { default };
}
}
keyword_invalid_2: {
input: {
export { default as Alias };
}
expect: {
export { default as Alias };
}
}
keyword_invalid_3: {
input: {
export { default as default };
}
expect: {
export { default as default };
}
}
keyword_valid_1: {
input: {
export { default } from "module.js";
}
expect: {
export { default } from "module.js";
}
}
keyword_valid_2: {
input: {
export { default as Alias } from "module.js";
}
expect: {
export { default as Alias } from "module.js";
}
}
keyword_valid_3: {
input: {
export { default as default } from "module.js";
}
expect: {
export { default as default } from "module.js";
}
}

View File

@@ -1,52 +0,0 @@
pow: {
input: {
var a = 2 ** 7;
var b = 3;
b **= 2;
}
expect: {
var a = 2 ** 7;
var b = 3;
b **= 2;
}
}
pow_with_number_constants: {
input: {
var a = 5 ** NaN;
var b = 42 ** +0;
var c = 42 ** -0;
var d = NaN ** 1;
var e = 2 ** Infinity;
var f = 2 ** -Infinity;
}
expect: {
var a = 5 ** NaN;
var b = 42 ** +0;
var c = 42 ** -0;
var d = NaN ** 1;
var e = 2 ** (1/0);
var f = 2 ** (-1/0);
}
}
pow_with_parentheses: {
input: {
var g = (-7) ** (0.5);
var h = 2324334 ** 34343443;
var i = (-2324334) ** 34343443;
var j = 2 ** (-3);
var k = 2.0 ** -3;
var l = 2.0 ** (5 - 7);
}
expect_exact: "var g=(-7)**.5;var h=2324334**34343443;var i=(-2324334)**34343443;var j=2**-3;var k=2**-3;var l=2**(5-7);"
}
pow_with_unary_between_brackets: {
input: {
var a = (-(+5)) ** 3;
}
expect: {
var a = (-+5)**3;
}
}

View File

@@ -189,25 +189,25 @@ hoist_funs: {
console.log(6, typeof f, typeof g);
}
expect: {
function f() {}
function g() {}
console.log(1, typeof f, typeof g);
if (console.log(2, typeof f, typeof g))
console.log(3, typeof f, typeof g);
else {
console.log(4, typeof f, typeof g);
function f() {}
console.log(5, typeof f, typeof g);
}
console.log(6, typeof f, typeof g);
}
expect_stdout: [
"1 'undefined' 'function'",
"2 'undefined' 'function'",
"1 'function' 'function'",
"2 'function' 'function'",
"4 'function' 'function'",
"5 'function' 'function'",
"6 'function' 'function'",
]
node_version: ">=6"
node_version: "<=4"
}
hoist_funs_strict: {
@@ -468,11 +468,9 @@ issue_2114_1: {
}
expect: {
var c = 0;
!function() {
0;
}((c += 1, c = 1 + c, function() {
c = 1 + (c += 1), function() {
var b = void (b && (b.b += (c += 1, 0)));
}()));
}();
console.log(c);
}
expect_stdout: "2"

View File

@@ -120,7 +120,7 @@ mixed: {
properties: true,
}
input: {
const FOO = { BAR: 0 };
var FOO = { BAR: 0 };
console.log(FOO.BAR);
console.log(++CONFIG.DEBUG);
console.log(++CONFIG.VALUE);
@@ -130,7 +130,7 @@ mixed: {
console.log(CONFIG);
}
expect: {
const FOO = { BAR: 0 };
var FOO = { BAR: 0 };
console.log("moo");
console.log(++CONFIG.DEBUG);
console.log(++CONFIG.VALUE);

View File

@@ -1,697 +0,0 @@
arrow_function_parens: {
input: {
something && (() => {});
}
expect_exact: "something&&(()=>{});"
}
arrow_function_parens_2: {
input: {
(() => null)();
}
expect_exact: "(()=>null)();"
}
typeof_arrow_functions: {
options = {
evaluate: true
}
input: {
var foo = typeof (x => null);
console.log(foo);
}
expect_exact: "var foo=\"function\";console.log(foo);"
expect_stdout: "function"
node_version: ">=4"
}
classes: {
input: {
class SomeClass {
constructor() {
};
foo() {};
};
class NoSemi {
constructor(...args) {
}
foo() {}
};
class ChildClass extends SomeClass {};
var asExpression = class AsExpression {};
var nameless = class {};
}
expect_exact: "class SomeClass{constructor(){}foo(){}}class NoSemi{constructor(...args){}foo(){}}class ChildClass extends SomeClass{}var asExpression=class AsExpression{};var nameless=class{};"
}
class_statics: {
input: {
x = class {
static staticMethod() {}
static get foo() {}
static set bar() {}
static() { /* "static" can be a method name! */ }
get() { /* "get" can be a method name! */ }
set() { /* "set" can be a method name! */ }
}
}
expect_exact: "x=class{static staticMethod(){}static get foo(){}static set bar(){}static(){}get(){}set(){}};"
}
class_name_can_be_mangled: {
mangle = { };
input: {
function x() {
class Foo {
}
var class1 = Foo;
var class2 = class Bar {};
}
}
expect: {
function x() {
class a { }
var s = a;
var c = class a {};
}
}
}
class_name_can_be_preserved: {
mangle = {
keep_classnames: true
}
input: {
function x() {
(class Baz { });
class Foo {};
}
}
expect: {
function x() {
(class Baz { });
class Foo {};
}
}
}
classes_can_have_generators: {
input: {
class Foo {
*bar() {}
static *baz() {}
}
}
expect: {
class Foo {
*bar() {}
static *baz() {}
}
}
}
classes_can_have_computed_generators: {
input: {
class C4 {
*['constructor']() {}
}
}
expect: {
class C4 {
*['constructor']() {}
}
}
}
classes_can_have_computed_static: {
input: {
class C4 {
static ['constructor']() {}
}
}
expect: {
class C4 {
static ['constructor']() {}
}
}
}
class_methods_and_getters_with_keep_quoted_props_enabled: {
beautify = {
quote_style: 3,
keep_quoted_props: true,
}
input: {
class clss {
a() {}
"b"() {}
get c() { return "c"}
get "d"() { return "d"}
set e(a) { doSomething(a); }
set 'f'(a) { doSomething(b); }
static g() {}
static "h"() {}
}
}
expect_exact: 'class clss{a(){}"b"(){}get c(){return"c"}get"d"(){return"d"}set e(a){doSomething(a)}set\'f\'(a){doSomething(b)}static g(){}static"h"(){}}'
}
classes_with_expression_as_expand: {
input: {
class D extends (calls++, C) {}
}
expect_exact: "class D extends(calls++,C){}"
}
new_target: {
input: {
new.target;
new.target.name;
}
expect_exact: "new.target;new.target.name;"
}
number_literals: {
input: {
0b1001;
0B1001;
0o11;
0O11;
}
expect: {
9;
9;
9;
9;
}
}
import_statement: {
input: {
import "mod-name";
import Foo from "bar";
import { Bar, Baz } from 'lel';
import Bar, { Foo } from 'lel';
import { Bar as kex, Baz as food } from 'lel';
}
expect_exact: 'import"mod-name";import Foo from"bar";import{Bar,Baz}from"lel";import Bar,{Foo}from"lel";import{Bar as kex,Baz as food}from"lel";'
}
import_all_statement: {
input: {
import * from 'lel';
import * as Lel from 'lel';
}
expect_exact: 'import*from"lel";import*as Lel from"lel";'
}
export_statement: {
options = {
evaluate: true,
}
input: {
export default 1 + 2;
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 foo=4;export let foo=6;export const foo=6;export function foo(){};export class foo{};"
}
export_default_object_expression: {
options = {
evaluate: true,
}
input: {
export default {
foo: 1 + 2,
bar() { return 4; },
get baz() { return this.foo; },
};
}
expect_exact: "export default{foo:3,bar(){return 4},get baz(){return this.foo}};"
}
export_default_array: {
options = {
evaluate: true,
}
input: {
export default [ 1 + 2, foo ];
}
expect_exact: "export default[3,foo];"
}
export_default_anon_function: {
options = {
evaluate: true,
}
input: {
export default function(){
console.log(1 + 2);
}
}
expect_exact: "export default function(){console.log(3)};"
}
export_default_anon_class: {
options = {
evaluate: true,
}
input: {
export default class {
foo() { console.log(1 + 2); }
}
}
expect_exact: "export default class{foo(){console.log(3)}};"
}
export_module_statement: {
input: {
export * from "a.js";
export {A} from "a.js";
export {A, B} from "a.js";
export {C};
}
expect_exact: 'export*from"a.js";export{A}from"a.js";export{A,B}from"a.js";export{C};'
}
import_statement_mangling: {
mangle = { toplevel: true };
input: {
import Foo from "foo";
import Bar, {Food} from "lel";
import {What as Whatever} from "lel";
Foo();
Bar();
Food();
Whatever();
}
expect: {
import o from "foo";
import m, {Food as r} from "lel";
import {What as f} from "lel";
o();
m();
r();
f();
}
}
export_statement_mangling: {
mangle = { };
input: {
export var foo = 6;
export function bar() { }
export class Baz { }
bar(foo, Baz)
}
expect: {
export var foo = 6;
export function bar() { }
export class Baz { }
bar(foo, Baz)
}
}
// https://github.com/mishoo/UglifyJS2/issues/1021
regression_for_of_const: {
input: {
for (const x of y) {}
for (const x in y) {}
}
expect: {
for (const x of y);for (const x in y);
}
}
// Fabio: My patches accidentally caused a crash whenever
// there's an extraneous set of parens around an object.
regression_cannot_destructure: {
input: {
var x = ({ x : 3 });
x(({ x: 3 }));
}
expect_exact: "var x={x:3};x({x:3});";
}
regression_cannot_use_of: {
input: {
function of() {
}
var of = "is a valid variable name";
of = { of: "is ok" };
x.of;
of: foo()
}
expect: {
function of(){}
var of="is a valid variable name";
of={of:"is ok"};
x.of;
foo(); /* Label statement missing? No prob. */
}
}
fat_arrow_as_param: {
input: {
foo(x => x);
foo(x => x, y => y);
foo(x => (x, x));
foo(x => (x, x), y => (y, y));
}
expect_exact: "foo(x=>x);foo(x=>x,y=>y);foo(x=>(x,x));foo(x=>(x,x),y=>(y,y));"
}
default_assign: {
options = {
keep_fargs: false,
unused: true,
}
input: {
function f(a, b = 3) {
console.log(a);
}
g = ([[] = 123]) => {};
h = ([[x, y, z] = [4, 5, 6]] = []) => {};
function i([[x, y, z] = [4, 5, 6]] = []) {
console.log(b);
};
}
expect: {
function f(a) {
console.log(a);
}
g = ([[] = 123]) => {};
h = ([[x, y, z] = [4, 5, 6]] = []) => {};
function i([[x, y, z] = [4, 5, 6]] = []) {
console.log(b);
};
}
}
expansion: {
options = {
keep_fargs: false,
unused: true,
}
input: {
function f(a, ...b) {
console.log(a);
}
}
expect: {
function f(a) {
console.log(a);
}
}
}
issue_1613: {
mangle = { toplevel: true };
input: {
const name = 1;
const foo = {
name
};
}
expect_exact: "const n=1;const c={name:n};"
}
format_methods: {
beautify = {
beautify: true,
}
input: {
class A extends B {constructor(a){x()} static s(b,c){y()} run(d,e,f){z()}}
}
expect_exact: [
"class A extends B {",
" constructor(a) {",
" x();",
" }",
" static s(b, c) {",
" y();",
" }",
" run(d, e, f) {",
" z();",
" }",
"}",
]
}
issue_1898: {
options = {
}
mangle = {
}
input: {
class Foo {
bar() {
for (const x of [ 6, 5 ]) {
for (let y of [ 4, 3 ]) {
for (var z of [ 2, 1 ]) {
console.log(x, y, z);
}
}
}
}
}
new Foo().bar();
}
expect: {
class Foo {
bar() {
for (const f of [ 6, 5 ])
for (let r of [ 4, 3 ])
for (var o of [ 2, 1 ])
console.log(f, r, o);
}
}
new Foo().bar();
}
}
issue_1753: {
mangle = { safari10: true };
input: {
class SomeClass {
constructor(props) {
let pickedSets = [];
for (let i = 0; i < 6; i++) {
pickedSets.push({
mainDrawNumbers: [],
extraDrawNumbers: []
});
}
}
}
}
expect: {
class SomeClass {
constructor(r) {
let s = [];
for (let a = 0; a < 6; a++)
s.push({
mainDrawNumbers: [],
extraDrawNumbers: []
});
}
}
}
}
issue_1753_disable: {
mangle = { safari10: false }
input: {
class SomeClass {
constructor(props) {
let pickedSets = [];
for (let i = 0; i < 6; i++) {
pickedSets.push({
mainDrawNumbers: [],
extraDrawNumbers: []
});
}
}
}
}
expect: {
class SomeClass {
constructor(r) {
let s = [];
for (let r = 0; r < 6; r++)
s.push({
mainDrawNumbers: [],
extraDrawNumbers: []
});
}
}
}
}
class_extends: {
options = {
evaluate: true,
}
input: {
function f() {
class foo extends bar {}
class pro extends some.prop {}
class arr extends stuff[1 - 1] {}
class bin extends (a || b) {}
class seq extends (a, b) {}
class ter extends (a ? b : c) {}
class uni extends (!0) {}
}
}
expect_exact: "function f(){class foo extends bar{}class pro extends some.prop{}class arr extends stuff[0]{}class bin extends(a||b){}class seq extends(a,b){}class ter extends(a?b:c){}class uni extends(!0){}}"
}
class_extends_class: {
options = {
}
input: {
class anon extends class {} {}
class named extends class base {} {}
}
expect_exact: "class anon extends class{}{}class named extends class base{}{}"
}
class_extends_function: {
options = {
}
input: {
class anon extends function(){} {}
class named extends function base(){} {}
}
expect_exact: "class anon extends function(){}{}class named extends function base(){}{}"
}
class_extends_regex: {
options = {
}
input: {
function f() {
class rx1 extends (/rx/) {}
// class rx2 extends /rx/ {} // FIXME - parse error
}
}
expect_exact: "function f(){class rx1 extends(/rx/){}}"
}
issue_2028: {
options = {
side_effects: true,
}
input: {
var a = {};
(function(x) {
x.X = function() {
return X;
};
class X {
static hello() {
console.log("hello");
}
}
}(a));
a.X().hello();
}
expect: {
var a = {};
(function(x) {
x.X = function() {
return X;
};
class X {
static hello() {
console.log("hello");
}
}
}(a));
a.X().hello();
}
expect_stdout: "hello"
node_version: ">=6"
}
class_expression_statement: {
options = {
toplevel: false,
side_effects: false,
unused: false,
}
input: {
(class {});
(class NamedClassExpr {});
let expr = (class AnotherClassExpr {});
class C {}
}
expect_exact: "(class{});(class NamedClassExpr{});let expr=class AnotherClassExpr{};class C{}"
}
class_expression_statement_unused: {
options = {
toplevel: false,
side_effects: true,
unused: true,
}
input: {
(class {});
(class NamedClassExpr {});
let expr = (class AnotherClassExpr {});
class C {}
}
expect_exact: "let expr=class{};class C{}"
}
class_expression_statement_unused_toplevel: {
options = {
toplevel: true,
side_effects: true,
unused: true,
}
input: {
(class {});
(class NamedClassExpr {});
let expr = (class AnotherClassExpr {});
class C {}
}
expect_exact: ""
}
export_default_function_decl: {
options = {
toplevel: true,
passes: 3,
unused: true,
}
input: {
// do not drop "unused" exports
export default function Foo() {};
export function Far() {};
}
expect_exact: "export default function Foo(){};export function Far(){};"
}
export_default_class_decl: {
options = {
toplevel: true,
passes: 3,
unused: true,
}
input: {
// do not drop "unused" exports
export default class Car {};
export class Cab {};
}
expect_exact: "export default class Car{};export class Cab{};"
}

View File

@@ -1,85 +0,0 @@
hoist_vars: {
options = {
hoist_vars: true
}
input: {
function a() {
bar();
var var1;
var var2;
}
function b(anArg) {
bar();
var var1;
var anArg;
}
}
expect: {
function a() {
var var1, var2; // Vars go up and are joined
bar();
}
function b(anArg) {
var var1;
bar();
// But vars named like arguments go away!
}
}
}
hoist_funs: {
options = {
hoist_funs: true
}
input: {
function a() {
bar();
function foo() {}
}
}
expect: {
function a() {
function foo() {} // Funs go up
bar();
}
}
}
hoist_no_destructurings: {
options = {
hoist_vars: true,
hoist_funs: true
}
input: {
function a([anArg]) {
bar();
var var1;
var anArg; // Because anArg is already declared, this goes away!
}
}
expect: {
function a([anArg]) {
var var1;
bar();
}
}
}
dont_hoist_var_destructurings: {
options = {
hoist_vars: true,
hoist_funs: true
}
input: {
function x() {
// If foo is null or undefined, this should be an exception
var {x,y} = foo;
}
}
expect: {
function x() {
var {x,y} = foo;
}
}
}

View File

@@ -53,12 +53,3 @@ html_comment_in_string_literal: {
}
expect_exact: 'function f(){return"\\x3c!--HTML--\\x3ecomment in\\x3c!--string literal--\\x3e"}';
}
html_comment_after_multiline_comment: {
input: {
var foo; /*
*/--> var bar;
var foobar;
}
expect_exact: "var foo;var foobar;"
}

View File

@@ -326,61 +326,3 @@ issue_512: {
}
}
}
issue_1317: {
options = {
if_return: true,
}
input: {
!function(a) {
if (a) return;
let b = 1;
function g() {
return b;
}
console.log(g());
}();
}
expect: {
!function(a) {
if (a) return;
let b = 1;
function g() {
return b;
}
console.log(g());
}();
}
expect_stdout: "1"
node_version: ">=6"
}
issue_1317_strict: {
options = {
if_return: true,
}
input: {
"use strict";
!function(a) {
if (a) return;
let b = 1;
function g() {
return b;
}
console.log(g());
}();
}
expect: {
"use strict";
!function(a) {
if (a) return;
let b = 1;
function g() {
return b;
}
console.log(g());
}();
}
expect_stdout: "1"
node_version: ">=4"
}

View File

@@ -1,8 +0,0 @@
parenthesis_strings_in_parenthesis: {
input: {
var foo = ('(');
a(')');
}
expect_exact: 'var foo="(";a(")");'
}

View File

@@ -1,16 +1,3 @@
const_declaration: {
options = {
evaluate: true
};
input: {
const goog = goog || {};
}
expect: {
const goog = goog || {};
}
}
const_pragma: {
options = {
evaluate: true,

View File

@@ -1,30 +0,0 @@
issue_1043: {
options = {
side_effects: true
};
input: {
function* range(start = 0, end = null, step = 1) {
if (end == null) {
end = start;
start = 0;
}
for (let i = start; i < end; i += step) {
yield i;
}
}
}
expect: {
function* range(start = 0, end = null, step = 1) {
if (null == end) {
end = start;
start = 0;
}
for (let i = start; i < end; i += step)
yield i;
}
}
}

View File

@@ -1,9 +0,0 @@
issue_1044: {
options = { evaluate: true, conditionals: true };
input: {
const mixed = Base ? class extends Base {} : class {}
}
expect: {
const mixed = Base ? class extends Base {} : class {}
}
}

View File

@@ -134,8 +134,9 @@ defun_hoist_funs: {
expect: {
function e() {
function f() {}
function g() {}
function h() {}
if (window) function g() {}
if (window);
}
}
}

View File

@@ -1,76 +0,0 @@
issue_1212_debug_false: {
options = {
global_defs : { DEBUG: false },
sequences : true,
properties : true,
dead_code : true,
conditionals : true,
comparisons : true,
evaluate : true,
booleans : true,
loops : true,
unused : true,
hoist_funs : true,
keep_fargs : true,
if_return : true,
join_vars : true,
cascade : true,
side_effects : true,
}
input: {
class foo {
bar() {
if (DEBUG)
console.log("DEV");
else
console.log("PROD");
}
}
new foo().bar();
}
expect: {
class foo{
bar() { console.log("PROD") }
}
(new foo).bar();
}
}
issue_1212_debug_true: {
options = {
global_defs : { DEBUG: true },
sequences : true,
properties : true,
dead_code : true,
conditionals : true,
comparisons : true,
evaluate : true,
booleans : true,
loops : true,
unused : true,
hoist_funs : true,
keep_fargs : true,
if_return : true,
join_vars : true,
cascade : true,
side_effects : true,
}
input: {
class foo {
bar() {
if (DEBUG)
console.log("DEV");
else
console.log("PROD");
}
}
new foo().bar();
}
expect: {
class foo{
bar() { console.log("DEV") }
}
(new foo).bar();
}
}

View File

@@ -1,291 +0,0 @@
same_variable_in_multiple_for_loop: {
options = {
hoist_funs: true,
dead_code: true,
conditionals: true,
comparisons: true,
evaluate: true,
booleans: true,
loops: true,
unused: true,
keep_fargs: true,
if_return: true,
join_vars: true,
cascade: true,
side_effects: true,
collapse_vars: true,
}
mangle = {}
input: {
for (let i = 0; i < 3; i++) {
let a = 100;
console.log(i, a);
for (let i = 0; i < 2; i++) {
console.log(i, a);
let c = 2;
console.log(c);
}
}
}
expect: {
for (let o = 0; o < 3; o++) {
let l = 100;
console.log(o, l);
for (let o = 0; o < 2; o++) {
console.log(o, l);
let e = 2;
console.log(e);
}
}
}
expect_stdout: true
}
same_variable_in_multiple_forOf: {
options = {
hoist_funs: true,
dead_code: true,
conditionals: true,
comparisons: true,
evaluate: true,
booleans: true,
loops: true,
unused: true,
keep_fargs: true,
if_return: true,
join_vars: true,
cascade: true,
side_effects: true,
collapse_vars: true,
}
mangle = {}
input: {
var test = [ "a", "b", "c" ];
for (let tmp of test) {
console.log(tmp);
let dd;
dd = [ "e", "f", "g" ];
for (let tmp of dd) {
console.log(tmp);
}
}
}
expect: {
var test = [ "a", "b", "c" ];
for (let o of test) {
console.log(o);
let e;
e = [ "e", "f", "g" ];
for (let o of e)
console.log(o);
}
}
expect_stdout: true
}
same_variable_in_multiple_forIn: {
options = {
hoist_funs: true,
dead_code: true,
conditionals: true,
comparisons: true,
evaluate: true,
booleans: true,
loops: true,
unused: false,
keep_fargs: true,
if_return: true,
join_vars: true,
cascade: true,
side_effects: true,
collapse_vars: true,
}
mangle = {}
input: {
var test = [ "a", "b", "c" ];
for (let tmp in test) {
console.log(tmp);
let dd;
dd = [ "e", "f", "g" ];
for (let tmp in test) {
console.log(tmp);
}
}
}
expect: {
var test = [ "a", "b", "c" ];
for (let e in test) {
console.log(e);
let t;
t = [ "e", "f", "g" ];
for (let e in test)
console.log(e);
}
}
expect_stdout: true
}
different_variable_in_multiple_for_loop: {
options = {
hoist_funs: true,
dead_code: true,
conditionals: true,
comparisons: true,
evaluate: true,
booleans: true,
loops: true,
unused: true,
keep_fargs: true,
if_return: true,
join_vars: true,
cascade: true,
side_effects: true,
collapse_vars: true,
}
mangle = {}
input: {
for (let i = 0; i < 3; i++) {
let a = 100;
console.log(i, a);
for (let j = 0; j < 2; j++) {
console.log(j, a);
let c = 2;
console.log(c);
}
}
}
expect: {
for (let o = 0; o < 3; o++) {
let l = 100;
console.log(o, l);
for (let o = 0; o < 2; o++) {
console.log(o, l);
let e = 2;
console.log(e);
}
}
}
expect_stdout: true
}
different_variable_in_multiple_forOf: {
options = {
hoist_funs: true,
dead_code: true,
conditionals: true,
comparisons: true,
evaluate: true,
booleans: true,
loops: true,
unused: true,
keep_fargs: true,
if_return: true,
join_vars: true,
cascade: true,
side_effects: true,
collapse_vars: true,
}
mangle = {}
input: {
var test = [ "a", "b", "c" ];
for (let tmp of test) {
console.log(tmp);
let dd;
dd = [ "e", "f", "g" ];
for (let t of dd) {
console.log(t);
}
}
}
expect: {
var test = [ "a", "b", "c" ];
for (let o of test) {
console.log(o);
let e;
e = [ "e", "f", "g" ];
for (let o of e)
console.log(o);
}
}
expect_stdout: true
}
different_variable_in_multiple_forIn: {
options = {
hoist_funs: true,
dead_code: true,
conditionals: true,
comparisons: true,
evaluate: true,
booleans: true,
loops: true,
unused: false,
keep_fargs: true,
if_return: true,
join_vars: true,
cascade: true,
side_effects: true,
collapse_vars: true,
}
mangle = {}
input: {
var test = [ "a", "b", "c" ];
for (let tmp in test) {
console.log(tmp);
let dd;
dd = [ "e", "f", "g" ];
for (let t in test) {
console.log(t);
}
}
}
expect: {
var test = [ "a", "b", "c" ];
for (let e in test) {
console.log(e);
let t;
t = [ "e", "f", "g" ];
for (let e in test)
console.log(e);
}
}
expect_stdout: true
}
more_variable_in_multiple_for: {
options = {
hoist_funs: true,
dead_code: true,
conditionals: true,
comparisons: true,
evaluate: true,
booleans: true,
loops: true,
unused: false,
keep_fargs: true,
if_return: true,
join_vars: true,
cascade: true,
side_effects: true,
collapse_vars: true,
}
mangle = {}
input: {
for (let a = 9, i = 0; i < 20; i += a) {
let b = a++ + i;
console.log(a, b, i);
for (let k = b, m = b*b, i = 0; i < 10; i++) {
console.log(a, b, m, k, i);
}
}
}
expect: {
for (let o = 9, l = 0; l < 20; l += o) {
let e = o++ + l;
console.log(o, e, l);
for (let l = e, t = e * e, c = 0; c < 10; c++)
console.log(o, e, t, l, c);
}
}
expect_stdout: true
}

View File

@@ -85,15 +85,3 @@ unsafe_undefined: {
}
expect_stdout: true
}
runtime_error: {
input: {
const a = 1;
console.log(a++);
}
expect: {
const a = 1;
console.log(a++);
}
expect_stdout: true
}

View File

@@ -103,3 +103,137 @@ numeric_literal: {
"8 7 8",
]
}
identifier: {
mangle_props = {}
input: {
var obj = {
abstract: 1,
boolean: 2,
byte: 3,
char: 4,
class: 5,
double: 6,
enum: 7,
export: 8,
extends: 9,
final: 10,
float: 11,
goto: 12,
implements: 13,
import: 14,
int: 15,
interface: 16,
let: 17,
long: 18,
native: 19,
package: 20,
private: 21,
protected: 22,
public: 23,
short: 24,
static: 25,
super: 26,
synchronized: 27,
this: 28,
throws: 29,
transient: 30,
volatile: 31,
yield: 32,
false: 33,
null: 34,
true: 35,
break: 36,
case: 37,
catch: 38,
const: 39,
continue: 40,
debugger: 41,
default: 42,
delete: 43,
do: 44,
else: 45,
finally: 46,
for: 47,
function: 48,
if: 49,
in: 50,
instanceof: 51,
new: 52,
return: 53,
switch: 54,
throw: 55,
try: 56,
typeof: 57,
var: 58,
void: 59,
while: 60,
with: 61,
};
}
expect: {
var obj = {
e: 1,
t: 2,
n: 3,
a: 4,
i: 5,
o: 6,
r: 7,
l: 8,
s: 9,
c: 10,
f: 11,
u: 12,
d: 13,
h: 14,
p: 15,
b: 16,
v: 17,
w: 18,
y: 19,
g: 20,
m: 21,
k: 22,
x: 23,
j: 24,
z: 25,
q: 26,
A: 27,
B: 28,
C: 29,
D: 30,
F: 31,
G: 32,
false: 33,
null: 34,
true: 35,
H: 36,
I: 37,
J: 38,
K: 39,
L: 40,
M: 41,
N: 42,
O: 43,
P: 44,
Q: 45,
R: 46,
S: 47,
T: 48,
U: 49,
V: 50,
W: 51,
X: 52,
Y: 53,
Z: 54,
$: 55,
_: 56,
ee: 57,
te: 58,
ne: 59,
ae: 60,
ie: 61,
};
}
}

View File

@@ -1,281 +0,0 @@
export_func_1: {
options = {
hoist_funs: true,
toplevel: true,
unused: true,
}
input: {
export function f(){};
}
expect_exact: "export function f(){};"
}
export_func_2: {
options = {
hoist_funs: true,
side_effects: false,
toplevel: true,
unused: true,
}
input: {
export function f(){}(1);
}
expect_exact: "export function f(){};1;"
}
export_func_3: {
options = {
hoist_funs: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
export function f(){}(1);
}
expect_exact: "export function f(){};"
}
export_default_func_1: {
options = {
hoist_funs: true,
toplevel: true,
unused: true,
}
input: {
export default function f(){};
}
expect_exact: "export default function f(){};"
}
export_default_func_2: {
options = {
hoist_funs: true,
side_effects: false,
toplevel: true,
unused: true,
}
input: {
export default function f(){}(1);
}
expect_exact: "export default function f(){};1;"
}
export_default_func_3: {
options = {
hoist_funs: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
export default function f(){}(1);
}
expect_exact: "export default function f(){};"
}
export_class_1: {
options = {
hoist_funs: true,
toplevel: true,
unused: true,
}
input: {
export class C {};
}
expect_exact: "export class C{};"
}
export_class_2: {
options = {
hoist_funs: true,
side_effects: false,
toplevel: true,
unused: true,
}
input: {
export class C {}(1);
}
expect_exact: "export class C{};1;"
}
export_class_3: {
options = {
hoist_funs: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
export class C {}(1);
}
expect_exact: "export class C{};"
}
export_default_class_1: {
options = {
hoist_funs: true,
toplevel: true,
unused: true,
}
input: {
export default class C {};
}
expect_exact: "export default class C{};"
}
export_default_class_2: {
options = {
hoist_funs: true,
side_effects: false,
toplevel: true,
unused: true,
}
input: {
export default class C {}(1);
}
expect_exact: "export default class C{};1;"
}
export_default_class_3: {
options = {
hoist_funs: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
export default class C {}(1);
}
expect_exact: "export default class C{};"
}
export_mangle_1: {
mangle = {
toplevel: true,
}
input: {
export function foo(one, two) {
return one - two;
};
}
expect_exact: "export function foo(o,n){return o-n};"
}
export_mangle_2: {
mangle = {
toplevel: true,
}
input: {
export default function foo(one, two) {
return one - two;
};
}
expect_exact: "export default function foo(o,t){return o-t};"
}
export_mangle_3: {
options = {
collapse_vars: true,
}
mangle = {
toplevel: true,
}
input: {
export class C {
go(one, two) {
var z = one;
return one - two + z;
}
};
}
expect_exact: "export class C{go(r,e){return r-e+r}};"
}
export_mangle_4: {
options = {
collapse_vars: true,
}
mangle = {
toplevel: true,
}
input: {
export default class C {
go(one, two) {
var z = one;
return one - two + z;
}
};
}
expect_exact: "export default class C{go(e,r){return e-r+e}};"
}
export_mangle_5: {
mangle = {
toplevel: true,
}
input: {
export default {
prop: function(one, two) {
return one - two;
}
};
}
expect_exact: "export default{prop:function(r,t){return r-t}};"
}
export_mangle_6: {
mangle = {
toplevel: true,
}
input: {
var baz = 2;
export let foo = 1, bar = baz;
}
expect_exact: "var o=2;export let foo=1,bar=o;"
}
export_toplevel_1: {
options = {
toplevel: true,
unused: true,
}
input: {
function f(){}
export function g(){};
export default function h(){};
}
expect: {
export function g(){};
export default function h(){};
}
}
export_toplevel_2: {
options = {
toplevel: true,
unused: true,
}
input: {
class A {}
export class B {};
export default class C {};
}
expect: {
export class B {};
export default class C {};
}
}
export_default_func_ref: {
options = {
hoist_funs: true,
toplevel: true,
unused: true,
}
input: {
export default function f(){};
f();
}
expect_exact: "export default function f(){};f();"
}

View File

@@ -1,56 +0,0 @@
compress_new_function: {
options = {
unsafe: true,
unsafe_Func: true,
}
input: {
new Function("aa, bb", 'return aa;');
}
expect: {
Function("n,r", "return n");
}
}
compress_new_function_with_destruct: {
options = {
unsafe: true,
unsafe_Func: true,
ecma: 6
}
beautify = {
ecma: 6
}
input: {
new Function("aa, [bb]", 'return aa;');
new Function("aa, {bb}", 'return aa;');
new Function("[[aa]], [{bb}]", 'return aa;');
}
expect: {
Function("n,[r]", "return n");
Function("n,{bb:b}", "return n");
Function("[[n]],[{bb:b}]", "return n");
}
}
compress_new_function_with_destruct_arrows: {
options = {
arrows: true,
unsafe: true,
unsafe_Func: true,
ecma: 6
}
beautify = {
ecma: 6
}
input: {
new Function("aa, [bb]", 'return aa;');
new Function("aa, {bb}", 'return aa;');
new Function("[[aa]], [{bb}]", 'return aa;');
}
expect: {
Function("n,[a]", "return n");
Function("b,{bb:n}", "return b");
Function("[[b]],[{bb:n}]", "return b");
}
}

View File

@@ -38,7 +38,7 @@ mixed: {
}
}
input: {
const ENV = 3;
var ENV = 3;
var FOO = 4;
f(ENV * 10);
--FOO;
@@ -49,7 +49,7 @@ mixed: {
x = DEBUG;
}
expect: {
const ENV = 3;
var ENV = 3;
var FOO = 4;
f(10);
--FOO;
@@ -60,7 +60,7 @@ mixed: {
x = 0;
}
expect_warnings: [
'WARN: global_defs ENV redefined [test/compress/issue-208.js:41,14]',
'WARN: global_defs ENV redefined [test/compress/issue-208.js:41,12]',
'WARN: global_defs FOO redefined [test/compress/issue-208.js:42,12]',
'WARN: global_defs FOO redefined [test/compress/issue-208.js:44,10]',
'WARN: global_defs DEBUG redefined [test/compress/issue-208.js:45,8]',

View File

@@ -419,7 +419,7 @@ wrap_iife_in_return_call: {
expect_exact: '(void console.log("test"))();'
}
pure_annotation: {
pure_annotation_1: {
options = {
inline: true,
side_effects: true,
@@ -432,6 +432,20 @@ pure_annotation: {
expect_exact: ""
}
pure_annotation_2: {
options = {
collapse_vars: true,
inline: true,
side_effects: true,
}
input: {
/*@__PURE__*/(function(n) {
console.log("hello", n);
}(42));
}
expect_exact: ""
}
drop_fargs: {
options = {
cascade: true,
@@ -449,9 +463,7 @@ drop_fargs: {
}
expect: {
var a = 1;
!function() {
a++;
}(++a && a.var);
++a && a.var, a++;
console.log(a);
}
expect_stdout: "3"
@@ -474,9 +486,7 @@ keep_fargs: {
}
expect: {
var a = 1;
!function(a_1) {
a++;
}(++a && a.var);
++a && a.var, a++;
console.log(a);
}
expect_stdout: "3"

View File

@@ -1,9 +0,0 @@
template_strings: {
input: {
foo(
`<span>${contents}</span>`,
`<a href="${url}">${text}</a>`
);
}
expect_exact: "foo(`<span>${contents}</span>`,`<a href=\"${url}\">${text}</a>`);"
}

View File

@@ -1,40 +0,0 @@
only_vars: {
options = { join_vars: true };
input: {
let netmaskBinary = '';
for (let i = 0; i < netmaskBits; ++i) {
netmaskBinary += '1';
}
}
expect: {
let netmaskBinary = '';
for (let i = 0; i < netmaskBits; ++i) netmaskBinary += '1';
}
}
issue_1079_with_vars: {
options = { join_vars: true };
input: {
var netmaskBinary = '';
for (var i = 0; i < netmaskBits; ++i) {
netmaskBinary += '1';
}
}
expect: {
for (var netmaskBinary = '', i = 0; i < netmaskBits; ++i) netmaskBinary += '1';
}
}
issue_1079_with_mixed: {
options = { join_vars: true };
input: {
var netmaskBinary = '';
for (let i = 0; i < netmaskBits; ++i) {
netmaskBinary += '1';
}
}
expect: {
var netmaskBinary = ''
for (let i = 0; i < netmaskBits; ++i) netmaskBinary += '1';
}
}

View File

@@ -146,50 +146,6 @@ parse_do_while_without_semicolon: {
}
}
keep_collapse_const_in_own_block_scope: {
options = {
join_vars: true,
loops: true
}
input: {
var i=2;
const c=5;
while(i--)
console.log(i);
console.log(c);
}
expect: {
var i=2;
const c=5;
for(;i--;)
console.log(i);
console.log(c);
}
expect_stdout: true
}
keep_collapse_const_in_own_block_scope_2: {
options = {
join_vars: true,
loops: true
}
input: {
const c=5;
var i=2; // Moves to loop, while it did not in previous test
while(i--)
console.log(i);
console.log(c);
}
expect: {
const c=5;
for(var i=2;i--;)
console.log(i);
console.log(c);
}
expect_stdout: true
}
evaluate: {
options = {
loops: true,

View File

@@ -82,19 +82,3 @@ new_with_unary_prefix: {
}
expect_exact: 'var bar=(+new Date).toString(32);';
}
new_with_assignement_expression: {
options = {
evaluate: true
}
input: {
var a;
new x(a = 5 * 2, b = [1, 2, 3], c = {a: "a", b: "b", cd: "c" + "d"});
new y([a, b] = [3, 4]);
}
expect: {
var a;
new x(a = 10, b = [1, 2, 3], c = {a: "a", b: "b", cd: "cd"});
new y([a, b] = [3, 4]);
}
}

View File

@@ -1,512 +0,0 @@
getter_setter: {
input: {
var get = "bar";
var a = {
get,
set: "foo",
get bar() {
return this.get;
},
get 5() {
return "five";
},
get 0xf55() {
return "f five five";
},
get "five"() {
return 5;
},
set one(value) {
this._one = value;
},
set 9(value) {
this._nine = value;
},
set 0b1010(value) {
this._ten = value;
},
set "eleven"(value) {
this._eleven = value;
}
};
var b = {
get() { return "gift"; },
set: function(code) { return "Storing code " + code; }
};
var c = {
["get"]: "foo",
["set"]: "bar"
};
var d = {
get: "foo",
set: "bar"
};
}
expect: {
var get = "bar";
var a = {
get,
set: "foo",
get bar() {
return this.get;
},
get 5() {
return "five";
},
get 0xf55() {
return "f five five";
},
get "five"() {
return 5;
},
set one(value) {
this._one = value;
},
set 9(value) {
this._nine = value;
},
set 0b1010(value) {
this._ten = value;
},
set "eleven"(value) {
this._eleven = value;
}
};
var b = {
get() { return "gift"; },
set: function(code) { return "Storing code " + code; }
};
var c = {
["get"]: "foo",
["set"]: "bar"
};
var d = {
get: "foo",
set: "bar"
};
}
}
getter_setter_mangler: {
mangle = {}
beautify = {
ecma: 6
}
input: {
function f(get,set) {
return {
get,
set,
get g(){},
set s(n){},
c,
a:1,
m(){}
};
}
}
expect_exact: "function f(t,e){return{get:t,set:e,get g(){},set s(t){},c,a:1,m(){}}}"
}
use_shorthand_opportunity: {
beautify = {
ecma: 6
}
input: {
var foo = 123;
var obj = {foo: foo};
}
expect_exact: "var foo=123;var obj={foo};"
}
computed_property_names: {
input: {
obj({ ["x" + "x"]: 6 });
}
expect_exact: 'obj({["x"+"x"]:6});'
}
computed_property_names_evaluated_1: {
options = {
evaluate: true
}
input: {
obj({
[1 + 1]: 2,
["x" + "x"]: 6
});
}
expect_exact: 'obj({[2]:2,["xx"]:6});'
}
computed_property_names_evaluated_2: {
options = {
evaluate: true
}
input: {
var foo = something();
var obj = {
[foo]() {
return "blah";
}
}
}
expect_exact: 'var foo=something();var obj={[foo](){return"blah"}};'
}
shorthand_properties: {
mangle = true;
input: {
(function() {
var prop = 1;
const value = {prop};
return value;
})();
}
expect: {
(function() {
var n = 1;
const r = {prop:n};
return r;
})();
}
}
concise_methods: {
beautify = {
ecma: 6
}
input: {
x = {
foo(a, b) {
return x;
}
}
y = {
foo([{a}]) {
return a;
},
bar(){}
}
}
expect_exact: "x={foo(a,b){return x}};y={foo([{a}]){return a},bar(){}};"
}
concise_methods_with_computed_property: {
options = {
evaluate: true
}
input: {
var foo = {
[Symbol.iterator]() {
return { /* stuff */ }
},
[1 + 2]() {
return 3;
},
["1" + "4"]() {
return 14;
}
}
}
expect: {
var foo = {
[Symbol.iterator]() {
return { /* stuff */ }
},
[3]() {
return 3;
},
["14"]() {
return 14;
}
}
}
}
concise_methods_with_computed_property2: {
options = {
evaluate: true
}
input: {
var foo = {
[[1]](){
return "success";
}
};
doSomething(foo[[1]]());
}
expect_exact: 'var foo={[[1]](){return"success"}};doSomething(foo[[1]]());'
}
concise_methods_with_various_property_names: {
input: {
var get = "bar";
var a = {
bar() {
return this.get;
},
5() {
return "five";
},
0xf55() {
return "f five five";
},
"five"() {
return 5;
},
0b1010(value) {
this._ten = value;
}
};
}
expect: {
var get = "bar";
var a = {
bar() {
return this.get;
},
5() {
return "five";
},
0xf55() {
return "f five five";
},
"five"() {
return 5;
},
0b1010(value) {
this._ten = value;
}
};
}
}
concise_methods_and_mangle_props: {
mangle_props = {
regex: /_/
};
input: {
function x() {
obj = {
_foo() { return 1; }
}
}
}
expect: {
function x() {
obj = {
o() { return 1; }
}
}
}
}
concise_generators: {
beautify = {
ecma: 6
}
input: {
x = {
*foo(a, b) {
return x;
}
}
y = {
*foo([{a}]) {
yield a;
},
bar(){}
}
}
expect_exact: "x={*foo(a,b){return x}};y={*foo([{a}]){yield a},bar(){}};"
}
concise_methods_and_keyword_names: {
input: {
x = {
catch() {},
throw() {}
}
}
expect: {
x={catch(){},throw(){}};
}
}
getter_setter_with_computed_value: {
input: {
class C {
get ['a']() {
return 'A';
}
set ['a'](value) {
do_something(a);
}
}
var x = {
get [a.b]() {
return 42;
}
};
class MyArray extends Array {
get [Symbol.species]() {
return Array;
}
}
}
expect_exact: 'class C{get["a"](){return"A"}set["a"](value){do_something(a)}}var x={get[a.b](){return 42}};class MyArray extends Array{get[Symbol.species](){return Array}}'
}
property_with_operator_value: {
input: {
var foo = {
"*": 1,
get "*"() {
return 2;
},
*"*"() {
return 3;
},
"%": 1,
get "%"() {
return 2;
},
*"%"() {
return 3;
}
}
class bar {
get "*"() {
return 1
}
*"*"() {
return 2;
}
get "%"() {
return 1
}
*"%"() {
return 2;
}
}
}
expect_exact: 'var foo={"*":1,get"*"(){return 2},*"*"(){return 3},"%":1,get"%"(){return 2},*"%"(){return 3}};class bar{get"*"(){return 1}*"*"(){return 2}get"%"(){return 1}*"%"(){return 2}}'
}
property_with_unprintable: {
input: {
var foo = {
"\x00\x01": "foo",
get "\x00\x01"() {
return "bar";
},
set "\x00\x01"(foo) {
save(foo);
},
*"\x00\x01"() {
return "foobar";
}
}
class bar {
get "\x00\x01"() {
return "bar"
}
set "\x00\x01"(foo) {
save(foo);
}
*"\x00\x01"() {
return "foobar";
}
}
}
expect_exact: 'var foo={"\\0\x01":"foo",get"\\0\x01"(){return"bar"},set"\\0\x01"(foo){save(foo)},*"\\0\x01"(){return"foobar"}};class bar{get"\\0\x01"(){return"bar"}set"\\0\x01"(foo){save(foo)}*"\\0\x01"(){return"foobar"}}'
}
property_with_unprintable_ascii_only: {
beautify = {
ascii_only: true,
}
input: {
var foo = {
"\x00\x01": "foo",
get "\x00\x01"() {
return "bar";
},
set "\x00\x01"(foo) {
save(foo);
},
*"\x00\x01"() {
return "foobar";
}
}
class bar {
get "\x00\x01"() {
return "bar"
}
set "\x00\x01"(foo) {
save(foo);
}
*"\x00\x01"() {
return "foobar";
}
}
}
expect_exact: 'var foo={"\\0\\x01":"foo",get"\\0\\x01"(){return"bar"},set"\\0\\x01"(foo){save(foo)},*"\\0\\x01"(){return"foobar"}};class bar{get"\\0\\x01"(){return"bar"}set"\\0\\x01"(foo){save(foo)}*"\\0\\x01"(){return"foobar"}}'
}
property_with_unprintable_ascii_only_static: {
beautify = {
ascii_only: true
}
input: {
class foo {
static get "\x02\x03"() {
return "bar";
}
static set "\x04\x05"(foo) {
save(foo);
}
}
}
expect_exact: 'class foo{static get"\\x02\\x03"(){return"bar"}static set"\\x04\\x05"(foo){save(foo)}}'
}
methods_and_getters_with_keep_quoted_props_enabled: {
beautify = {
quote_style: 3,
keep_quoted_props: true,
}
input: {
var obj = {
a() {},
"b"() {},
get c() { return "c"},
get "d"() { return "d"},
set e(a) { doSomething(a); },
set f(a) { doSomething(b); }
}
}
expect_exact: 'var obj={a(){},"b"(){},get c(){return"c"},get"d"(){return"d"},set e(a){doSomething(a)},set f(a){doSomething(b)}};'
}
allow_assignments_to_property_values: {
input: {
var foo = {123: foo = 123} = {foo: "456"};
}
expect: {
var foo = {123: foo = 123} = {foo: "456"};
}
}
variable_as_computed_property: {
input: {
function getLine(header) {
return {
[header]: {}
};
}
}
expect_exact: "function getLine(header){return{[header]:{}}}"
}

View File

@@ -1,186 +0,0 @@
arrow_functions: {
options = {
arrows: true,
}
input: {
(a) => b; // 1 args
(a, b) => c; // n args
() => b; // 0 args
(a) => (b) => c; // func returns func returns func
(a) => ((b) => c); // So these parens are dropped
() => (b,c) => d; // func returns func returns func
a=>{return b;}
a => 'lel'; // Dropping the parens
}
expect_exact: "a=>b;(a,b)=>c;()=>b;a=>b=>c;a=>b=>c;()=>(b,c)=>d;a=>b;a=>\"lel\";"
}
arrow_return: {
options = {
arrows: true,
}
input: {
() => {};
() => { return; };
a => { return 1; }
a => { return -b }
a => { return b; var b; }
(x, y) => { return x - y; }
}
expect_exact: "()=>{};()=>{};a=>1;a=>-b;a=>{return b;var b};(x,y)=>x-y;"
}
regression_arrow_functions_and_hoist: {
options = {
hoist_vars: true,
hoist_funs: true
}
input: {
(a) => b;
}
expect_exact: "a=>b;"
}
regression_assign_arrow_functions: {
input: {
oninstall = e => false;
oninstall = () => false;
}
expect: {
oninstall=e=>false;
oninstall=()=>false;
}
}
destructuring_arguments_1: {
input: {
(function ( a ) { });
(function ( [ a ] ) { });
(function ( [ a, b ] ) { });
(function ( [ [ a ] ] ) { });
(function ( [ [ a, b ] ] ) { });
(function ( [ a, [ b ] ] ) { });
(function ( [ [ b ], a ] ) { });
(function ( { a } ) { });
(function ( { a, b } ) { });
(function ( [ { a } ] ) { });
(function ( [ { a, b } ] ) { });
(function ( [ a, { b } ] ) { });
(function ( [ { b }, a ] ) { });
( [ a ] ) => { };
( [ a, b ] ) => { };
( { a } ) => { };
( { a, b, c, d, e } ) => { };
( [ a ] ) => b;
( [ a, b ] ) => c;
( { a } ) => b;
( { a, b } ) => c;
}
expect: {
(function(a){});
(function([a]){});
(function([a,b]){});
(function([[a]]){});
(function([[a,b]]){});
(function([a,[b]]){});
(function([[b],a]){});
(function({a}){});
(function({a,b}){});
(function([{a}]){});
(function([{a,b}]){});
(function([a,{b}]){});
(function([{b},a]){});
([a])=>{};
([a,b])=>{};
({a})=>{};
({a,b,c,d,e})=>{};
([a])=>b;
([a,b])=>c;
({a})=>b;
({a,b})=>c;
}
}
destructuring_arguments_2: {
input: {
(function([]) {});
(function({}) {});
(function([,,,,,]) {});
(function ([a, {b: c}]) {});
(function ([...args]) {});
(function ({x,}) {});
class a { *method({ [thrower()]: x } = {}) {}};
(function(a, b, c, d, [{e: [...f]}]){})(1, 2, 3, 4, [{e: [1, 2, 3]}]);
}
expect: {
(function([]) {});
(function({}) {});
(function([,,,,,]) {});
(function ([a, {b: c}]) {});
(function ([...args]) {});
(function ({x,}) {});
class a { *method({ [thrower()]: x } = {}) {}};
(function(a, b, c, d, [{e: [...f]}]){})(1, 2, 3, 4, [{e: [1, 2, 3]}]);
}
}
destructuring_arguments_3: {
beautify = {
ecma: 6
}
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() {}) } = {};
}
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(){})}={};"
}
default_arguments: {
beautify = {
ecma: 6
}
input: {
function x(a = 6) { }
function x(a = (6 + 5)) { }
function x({ foo } = {}, [ bar ] = [ 1 ]) { }
}
expect_exact: "function x(a=6){}function x(a=6+5){}function x({foo}={},[bar]=[1]){}"
}
default_values_in_destructurings: {
beautify = {
ecma: 6
}
input: {
function x({a=(4), b}) {}
function x([b, c=(12)]) {}
var { x = (6), y } = x;
var [ x, y = (6) ] = x;
}
expect_exact: "function x({a=4,b}){}function x([b,c=12]){}var{x=6,y}=x;var[x,y=6]=x;"
}
accept_duplicated_parameters_in_non_strict_without_spread_or_default_assignment: {
input: {
function a(b, b){}
function b({c: test, c: test}){}
}
expect: {
function a(b, b){}
function b({c: test, c: test}){}
}
}

View File

@@ -148,7 +148,6 @@ mangle_unquoted_properties: {
properties: false
}
mangle_props = {
builtins: true,
keep_quoted: true
}
beautify = {
@@ -239,7 +238,6 @@ mangle_debug_suffix_keep_quoted: {
properties: false
}
mangle_props = {
builtins: true,
keep_quoted: true,
debug: "XYZ",
reserved: []

View File

@@ -2228,10 +2228,11 @@ issue_1814_1: {
options = {
evaluate: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
const a = 42;
var a = 42;
!function() {
var b = a;
!function(a) {
@@ -2240,7 +2241,6 @@ issue_1814_1: {
}();
}
expect: {
const a = 42;
!function() {
!function(a) {
console.log(a++, 42);
@@ -2254,10 +2254,11 @@ issue_1814_2: {
options = {
evaluate: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
const a = "32";
var a = "32";
!function() {
var b = a + 1;
!function(a) {
@@ -2266,7 +2267,6 @@ issue_1814_2: {
}();
}
expect: {
const a = "32";
!function() {
!function(a) {
console.log(a++, "321");
@@ -2576,56 +2576,6 @@ accessor: {
expect_stdout: "1 1"
}
issue_2090_1: {
options = {
evaluate: true,
reduce_vars: true,
}
input: {
console.log(function() {
var x = 1;
[].forEach(() => x = 2);
return x;
}());
}
expect: {
console.log(function() {
var x = 1;
[].forEach(() => x = 2);
return x;
}());
}
expect_stdout: "1"
node_version: ">=4"
}
issue_2090_2: {
options = {
evaluate: true,
reduce_vars: true,
}
input: {
console.log(function() {
var x = 1;
[].forEach(() => {
x = 2;
});
return x;
}());
}
expect: {
console.log(function() {
var x = 1;
[].forEach(() => {
x = 2;
});
return x;
}());
}
expect_stdout: "1"
node_version: ">=4"
}
for_in_prop: {
options = {
reduce_vars: true,

View File

@@ -711,30 +711,6 @@ issue_27: {
}
}
reassign_const: {
options = {
cascade: true,
sequences: true,
side_effects: true,
}
input: {
function f() {
const a = 1;
a++;
return a;
}
console.log(f());
}
expect: {
function f() {
const a = 1;
return a++, a;
}
console.log(f());
}
expect_stdout: true
}
issue_2062: {
options = {
booleans: true,

View File

@@ -1,9 +0,0 @@
super_can_be_parsed: {
input: {
super(1,2);
super.meth();
}
expect_exact: "super(1,2);super.meth();"
}

View File

@@ -1,402 +0,0 @@
template_strings: {
beautify = {
quote_style: 3
}
input: {
``;
`xx\`x`;
`${ foo + 2 }`;
` foo ${ bar + `baz ${ qux }` }`;
}
expect_exact: "``;`xx\\`x`;`${foo+2}`;` foo ${bar+`baz ${qux}`}`;";
}
template_string_prefixes: {
beautify = {
quote_style: 3
}
input: {
String.raw`foo`;
foo `bar`;
}
expect_exact: "String.raw`foo`;foo`bar`;";
}
template_strings_ascii_only: {
beautify = {
ascii_only: true,
quote_style: 3
}
input: {
var foo = `foo
bar
ↂωↂ`;
var bar = `\``;
}
expect_exact: "var foo=`foo\\n bar\\n \\u2182\\u03c9\\u2182`;var bar=`\\``;"
}
template_strings_without_ascii_only: {
beautify = {
quote_style: 3
}
input: {
var foo = `foo
bar
ↂωↂ`
}
expect_exact: "var foo=`foo\\n bar\\n ↂωↂ`;"
}
template_string_with_constant_expression: {
options = {
evaluate: true
}
beautify = {
quote_style: 3
}
input: {
var foo = `${4 + 4} equals 4 + 4`;
}
expect: {
var foo = `8 equals 4 + 4`;
}
}
template_string_with_predefined_constants: {
options = {
evaluate: true
}
beautify = {
quote_style: 3
}
input: {
var foo = `This is ${undefined}`;
var bar = `This is ${NaN}`;
var baz = `This is ${null}`;
var foofoo = `This is ${Infinity}`;
var foobar = "This is ${1/0}";
var foobaz = 'This is ${1/0}';
var barfoo = "This is ${NaN}";
var bazfoo = "This is ${null}";
var bazbaz = `This is ${1/0}`;
var barbar = `This is ${0/0}`;
var barbar = "This is ${0/0}";
var barber = 'This is ${0/0}';
var a = `${4**11}`; // 8 in template vs 7 chars - 4194304
var b = `${4**12}`; // 8 in template vs 8 chars - 16777216
var c = `${4**14}`; // 8 in template vs 9 chars - 268435456
}
expect: {
var foo = `This is undefined`;
var bar = `This is NaN`;
var baz = `This is null`;
var foofoo = `This is ${1/0}`;
var foobar = "This is ${1/0}";
var foobaz = 'This is ${1/0}';
var barfoo = "This is ${NaN}";
var bazfoo = "This is ${null}";
var bazbaz = `This is ${1/0}`;
var barbar = `This is NaN`;
var barbar = "This is ${0/0}";
var barber = 'This is ${0/0}';
var a = `4194304`;
var b = `16777216`; // Potential for further concatentation
var c = `${4**14}`; // Not worth converting
}
}
template_string_evaluate_with_many_segments: {
options = {
evaluate: true
}
beautify = {
quote_style: 3
}
input: {
var foo = `Hello ${guest()}, welcome to ${location()}${"."}`;
var bar = `${1}${2}${3}${4}${5}${6}${7}${8}${9}${0}`;
var baz = `${foobar()}${foobar()}${foobar()}${foobar()}`;
var buzz = `${1}${foobar()}${2}${foobar()}${3}${foobar()}`;
}
expect: {
var foo = `Hello ${guest()}, welcome to ${location()}.`;
var bar = `1234567890`;
var baz = `${foobar()}${foobar()}${foobar()}${foobar()}`;
var buzz = `1${foobar()}2${foobar()}3${foobar()}`;
}
}
template_string_with_many_segments: {
beautify = {
quote_style: 3
}
input: {
var foo = `Hello ${guest()}, welcome to ${location()}${"."}`;
var bar = `${1}${2}${3}${4}${5}${6}${7}${8}${9}${0}`;
var baz = `${foobar()}${foobar()}${foobar()}${foobar()}`;
var buzz = `${1}${foobar()}${2}${foobar()}${3}${foobar()}`;
}
expect: {
var foo = `Hello ${guest()}, welcome to ${location()}${"."}`;
var bar = `${1}${2}${3}${4}${5}${6}${7}${8}${9}${0}`;
var baz = `${foobar()}${foobar()}${foobar()}${foobar()}`;
var buzz = `${1}${foobar()}${2}${foobar()}${3}${foobar()}`;
}
}
template_string_to_normal_string: {
options = {
evaluate: true
}
beautify = {
quote_style: 0
}
input: {
var foo = `This is ${undefined}`;
var bar = "Decimals " + `${1}${2}${3}${4}${5}${6}${7}${8}${9}${0}`;
}
expect: {
var foo = `This is undefined`;
var bar = "Decimals 1234567890";
}
}
template_concattenating_string: {
options = {
evaluate: true
}
beautify = {
quote_style: 3 // Yes, keep quotes
}
input: {
var foo = "Have a nice " + `day. ${`day. ` + `day.`}`;
var bar = "Have a nice " + `${day()}`;
}
expect: {
var foo = "Have a nice day. day. day.";
var bar = "Have a nice " + `${day()}`;
}
}
evaluate_nested_templates: {
options = {
evaluate: true
}
beautify = {
quote_style: 0
}
input: {
var baz = `${`${`${`foo`}`}`}`;
}
expect: {
var baz = `foo`;
}
}
enforce_double_quotes: {
beautify = {
quote_style: 1
}
input: {
var foo = `Hello world`;
var bar = `Hello ${'world'}`;
var baz = `Hello ${world()}`;
}
expect: {
var foo = `Hello world`;
var bar = `Hello ${"world"}`;
var baz = `Hello ${world()}`;
}
}
enforce_single_quotes: {
beautify = {
quote_style: 2
}
input: {
var foo = `Hello world`;
var bar = `Hello ${"world"}`;
var baz = `Hello ${world()}`;
}
expect: {
var foo = `Hello world`;
var bar = `Hello ${'world'}`;
var baz = `Hello ${world()}`;
}
}
enforce_double_quotes_and_evaluate: {
beautify = {
quote_style: 1
}
options = {
evaluate: true
}
input: {
var foo = `Hello world`;
var bar = `Hello ${'world'}`;
var baz = `Hello ${world()}`;
}
expect: {
var foo = `Hello world`;
var bar = `Hello world`;
var baz = `Hello ${world()}`;
}
}
enforce_single_quotes_and_evaluate: {
beautify = {
quote_style: 2
}
options = {
evaluate: true
}
input: {
var foo = `Hello world`;
var bar = `Hello ${"world"}`;
var baz = `Hello ${world()}`;
}
expect: {
var foo = `Hello world`;
var bar = `Hello world`;
var baz = `Hello ${world()}`;
}
}
respect_inline_script: {
beautify = {
inline_script: true,
quote_style: 3
}
input: {
var foo = `</script>${content}`;
var bar = `<!--`;
var baz = `-->`;
}
expect_exact: "var foo=`<\\/script>${content}`;var bar=`\\x3c!--`;var baz=`--\\x3e`;";
}
do_not_optimize_tagged_template_1: {
beautify = {
quote_style: 0
}
options = {
evaluate: true
}
input: {
var foo = tag`Shall not be optimized. ${"But " + "this " + "is " + "fine."}`;
var bar = tag`Don't even mind changing my quotes!`;
}
expect_exact:
'var foo=tag`Shall not be optimized. ${"But this is fine."}`;var bar=tag`Don\'t even mind changing my quotes!`;';
}
do_not_optimize_tagged_template_2: {
options = {
evaluate: true
}
input: {
var foo = tag`test` + " something out";
}
expect_exact: 'var foo=tag`test`+" something out";';
}
keep_raw_content_in_tagged_template: {
options = {
evaluate: true
}
input: {
var foo = tag`\u0020\u{20}\u{00020}\x20\40\040 `;
}
expect_exact: "var foo=tag`\\u0020\\u{20}\\u{00020}\\x20\\40\\040 `;";
}
allow_chained_templates: {
input: {
var foo = tag`a``b``c``d`;
}
expect: {
var foo = tag`a``b``c``d`;
}
}
check_escaped_chars: {
input: {
var foo = `\u0020\u{20}\u{00020}\x20\40\040 `;
}
expect_exact: "var foo=` `;";
}
escape_dollar_curly: {
options = {
evaluate: true
}
input: {
console.log(`\$\{ beep \}`)
console.log(`${1-0}\${2-0}$\{3-0}${4-0}`)
console.log(`$${""}{not an expression}`)
}
expect_exact: "console.log(`\\${ beep }`);console.log(`1\\${2-0}\\${3-0}4`);console.log(`\\${not an expression}`);"
}
template_starting_with_newline: {
options = {
dead_code: true
}
input: {
function foo(e) {
return `
this is a template string!`;
};
}
expect_exact: "function foo(e){return`\\nthis is a template string!`}"
}
template_with_newline: {
options = {
dead_code: true
}
input: {
function foo(e) {
return `yep,
this is a template string!`;
};
}
expect_exact: "function foo(e){return`yep,\\nthis is a template string!`}"
}
template_ending_with_newline: {
options = {
dead_code: true
}
input: {
function foo(e) {
return `this is a template string!
`;
};
}
expect_exact: "function foo(e){return`this is a template string!\\n`}"
}
issue_1856: {
beautify = {
ascii_only: false,
}
input: {
console.log(`\\n\\r\\u2028\\u2029\n\r\u2028\u2029`);
}
expect_exact: "console.log(`\\\\n\\\\r\\\\u2028\\\\u2029\\n\\r\\u2028\\u2029`);"
}
issue_1856_ascii_only: {
beautify = {
ascii_only: true,
}
input: {
console.log(`\\n\\r\\u2028\\u2029\n\r\u2028\u2029`);
}
expect_exact: "console.log(`\\\\n\\\\r\\\\u2028\\\\u2029\\n\\r\\u2028\\u2029`);"
}

View File

@@ -1,12 +0,0 @@
catch_destructuring_with_sequence: {
beautify = {
ecma: 6
}
input: {
try {
throw {};
} catch ({xCover = (0, function() {})} ) {
}
}
expect_exact: "try{throw{}}catch({xCover=(0,function(){})}){}"
}

View File

@@ -15,106 +15,3 @@ unicode_parse_variables: {
var l = 3;
}
}
unicode_escaped_identifier: {
beautify = {ecma: 6}
input: {
var \u{61} = "foo";
var \u{10000} = "bar";
}
expect_exact: 'var a="foo";var \u{10000}="bar";';
}
unicode_identifier_ascii_only: {
beautify = {ascii_only: true, ecma: 6}
input: {
var \u{0061} = "hi";
var bar = "h\u{0065}llo";
var \u{10000} = "testing \u{101111}";
}
expect_exact: 'var a="hi";var bar="hello";var \\u{10000}="testing \\u{101111}";'
}
unicode_string_literals: {
beautify = {ascii_only: true, ecma: 6}
input: {
var a = "6 length unicode character: \u{101111}";
}
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: {
var a = "\x01";
var \ua0081 = "\x10"; // \u0081 only in ID_Continue
var \u0100 = "\u0100";
var \u1000 = "\u1000";
var \u{10000} = "\u{10000}";
var \u{2f800} = "\u{100000}";
}
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: {
var \u{2f800}\u{2f800}\u{2f800}\u{2f800} = "\u{100000}\u{100000}\u{100000}\u{100000}\u{100000}";
}
expect_exact: 'var \\u{2f800}\\u{2f800}\\u{2f800}\\u{2f800}="\\u{100000}\\u{100000}\\u{100000}\\u{100000}\\u{100000}";'
}
escape_non_escaped_identifier: {
beautify = {ascii_only: true, ecma: 6}
input: {
var µþ = "µþ";
}
expect_exact: 'var \\u00b5\\u00fe="\\xb5\\xfe";'
}
non_escape_2_non_escape: {
beautify = {ascii_only: false, ecma: 6}
input: {
var µþ = "µþ";
}
expect_exact: 'var µþ="µþ";'
}
non_escape_2_half_escape1: {
beautify = {ascii_only: false, ascii_identifiers: true, ecma: 6}
input: {
var µþ = "µþ";
}
expect_exact: 'var \\u00b5\\u00fe="µþ";'
}
non_escape_2_half_escape2: {
beautify = {ascii_only: true, ascii_identifiers: false, ecma: 6}
input: {
var µþ = "µþ";
}
expect_exact: 'var µþ="\\xb5\\xfe";'
}

View File

@@ -1,201 +0,0 @@
generators: {
input: {
function* fn() {};
}
expect_exact: "function*fn(){}"
}
generators_yield: {
input: {
function* fn() {
yield remote();
}
}
expect_exact: "function*fn(){yield remote()}"
}
generators_yield_assign: {
input: {
function* fn() {
var x = {};
x.prop = yield 5;
}
}
expect_exact: "function*fn(){var x={};x.prop=yield 5}"
}
generator_yield_undefined: {
input: {
function* fn() {
yield;
}
}
expect_exact: "function*fn(){yield}"
}
yield_optimize_expression: {
options = {
}
input: {
function* f1() { yield; }
function* f2() { yield undefined; }
function* f3() { yield null; }
function* f4() { yield* undefined; }
}
expect: {
function* f1() { yield }
function* f2() { yield; }
function* f3() { yield null; }
function* f4() { yield* void 0; }
}
}
yield_statements: {
input: {
function* fn() {
var a = (yield 1) + (yield 2);
var b = (yield 3) === (yield 4);
var c = (yield 5) << (yield 6);
var d = yield 7;
var e = (yield 8) ? yield 9 : yield 10;
var f = -(yield 11);
}
}
expect_exact: "function*fn(){var a=(yield 1)+(yield 2);var b=(yield 3)===(yield 4);var c=(yield 5)<<(yield 6);var d=yield 7;var e=(yield 8)?yield 9:yield 10;var f=-(yield 11)}"
}
yield_as_identifier_in_function_in_generator: {
input: {
var g = function*() {
function h() {
yield = 1;
}
};
}
expect: {
var g = function*() {
function h() {
yield = 1;
}
};
}
}
yield_before_punctuators: {
input: {
iter = (function*() {
assignmentResult = [ x = yield ] = value;
})();
function* g1() { (yield) }
function* g2() { [yield] }
function* g3() { return {yield} } // Added return to avoid {} drop
function* g4() { yield, yield; }
function* g5() { (yield) ? yield : yield; }
}
expect: {
iter = (function*() {
assignmentResult = [ x = yield ] = value;
})();
function* g1() { (yield) }
function* g2() { [yield] }
function* g3() { return {yield} }
function* g4() { yield, yield; }
function* g5() { (yield) ? yield : yield; }
}
}
yield_as_identifier_outside_strict_mode: {
input: {
import yield from "bar";
yield = 123;
while (true) {
yield:
for(;;) break yield;
foo();
}
while (true)
yield: for(;;) continue yield;
function yield(){}
function foo(...yield){}
try { new Error("") } catch (yield) {}
var yield = "foo";
}
expect: {
import yield from "bar";
yield = 123;
while (true) {
yield:
for(;;) break yield;
foo();
}
while (true)
yield: for(;;) continue yield;
function yield(){}
function foo(...yield){}
try { new Error("") } catch (yield) {}
var yield = "foo";
}
}
empty_generator_as_parameter_with_side_effects: {
options = {
side_effects: true
}
input: {
var GeneratorPrototype = Object.getPrototypeOf(
Object.getPrototypeOf(function*() {}())
);
evaluate(GeneratorPrototype);
}
expect_exact: "var GeneratorPrototype=Object.getPrototypeOf(Object.getPrototypeOf(function*(){}()));evaluate(GeneratorPrototype);"
}
empty_generator_as_parameter_without_side_effects: {
options = {
side_effects: false
}
input: {
var GeneratorPrototype = Object.getPrototypeOf(
Object.getPrototypeOf(function*() {}())
);
evaluate(GeneratorPrototype);
}
expect_exact: "var GeneratorPrototype=Object.getPrototypeOf(Object.getPrototypeOf(function*(){}()));evaluate(GeneratorPrototype);"
}
yield_dot: {
options = {
}
input: {
function* foo(){
yield x.foo;
(yield x).foo;
yield (yield obj.foo()).bar();
}
}
expect_exact: "function*foo(){yield x.foo;(yield x).foo;yield(yield obj.foo()).bar()}"
}
yield_sub: {
options = {
}
input: {
function* foo(){
yield x['foo'];
(yield x)['foo'];
yield (yield obj.foo())['bar']();
}
}
expect_exact: 'function*foo(){yield x["foo"];(yield x)["foo"];yield(yield obj.foo())["bar"]()}'
}
yield_as_ES5_property: {
input: {
"use strict";
console.log({yield: 42}.yield);
}
expect_exact: '"use strict";console.log({yield:42}.yield);'
expect_stdout: "42"
}

View File

@@ -1,8 +0,0 @@
function f() {
const a;
}
function g() {
"use strict";
const a;
}

View File

@@ -1,3 +0,0 @@
{
export var V = 1;
}

View File

@@ -1 +0,0 @@
export class{};

View File

@@ -1 +0,0 @@
export function(){};

View File

@@ -1,3 +0,0 @@
{
import A from "B";
}

View File

@@ -1 +0,0 @@
(a, ...b);

View File

@@ -16,8 +16,8 @@ describe("Accessor tokens", function() {
assert.equal(node.start.pos, 12);
assert.equal(node.end.endpos, 46);
assert(node.key instanceof UglifyJS.AST_SymbolMethod);
assert.equal(node.key.start.pos, 12);
assert(node.key instanceof UglifyJS.AST_SymbolAccessor);
assert.equal(node.key.start.pos, 16);
assert.equal(node.key.end.endpos, 22);
assert(node.value instanceof UglifyJS.AST_Accessor);

View File

@@ -27,253 +27,4 @@ describe("arguments", function() {
assert.strictEqual(ast.body[0].body[0].uses_arguments, true);
assert.strictEqual(ast.body[0].body[0].body[0].uses_arguments, false);
});
it("Should parse a function containing default assignment correctly", function() {
var ast = UglifyJS.parse("function foo(a = 123) {}");
assert(ast.body[0] instanceof UglifyJS.AST_Defun);
assert.strictEqual(ast.body[0].argnames.length, 1);
// First argument
assert(ast.body[0].argnames[0] instanceof UglifyJS.AST_DefaultAssign);
assert(ast.body[0].argnames[0].left instanceof UglifyJS.AST_SymbolFunarg);
assert.strictEqual(ast.body[0].argnames[0].operator, "=");
assert(ast.body[0].argnames[0].right instanceof UglifyJS.AST_Number);
ast = UglifyJS.parse("function foo(a = a) {}");
assert(ast.body[0] instanceof UglifyJS.AST_Defun);
assert.strictEqual(ast.body[0].argnames.length, 1);
// First argument
assert(ast.body[0].argnames[0] instanceof UglifyJS.AST_DefaultAssign);
assert(ast.body[0].argnames[0].left instanceof UglifyJS.AST_SymbolFunarg);
assert.strictEqual(ast.body[0].argnames[0].operator, "=");
assert(ast.body[0].argnames[0].right instanceof UglifyJS.AST_SymbolRef);
});
it("Should parse a function containing default assignments in destructuring correctly", function() {
var ast = UglifyJS.parse("function foo([a = 123]) {}");
assert(ast.body[0] instanceof UglifyJS.AST_Defun);
assert.strictEqual(ast.body[0].argnames.length, 1);
// First argument
assert(ast.body[0].argnames[0] instanceof UglifyJS.AST_Destructuring);
assert.strictEqual(ast.body[0].argnames[0].is_array, true);
assert.strictEqual(ast.body[0].argnames[0].names.length, 1);
assert(ast.body[0].argnames[0].names[0] instanceof UglifyJS.AST_DefaultAssign);
assert(ast.body[0].argnames[0].names[0].left instanceof UglifyJS.AST_SymbolFunarg);
assert.strictEqual(ast.body[0].argnames[0].names[0].operator, "=");
assert(ast.body[0].argnames[0].names[0].right instanceof UglifyJS.AST_Number);
ast = UglifyJS.parse("function foo({a = 123}) {}");
assert(ast.body[0] instanceof UglifyJS.AST_Defun);
assert.strictEqual(ast.body[0].argnames.length, 1);
// First argument
assert(ast.body[0].argnames[0] instanceof UglifyJS.AST_Destructuring);
assert.strictEqual(ast.body[0].argnames[0].is_array, false);
assert.strictEqual(ast.body[0].argnames[0].names.length, 1);
assert(ast.body[0].argnames[0].names[0] instanceof UglifyJS.AST_ObjectKeyVal);
assert.strictEqual(ast.body[0].argnames[0].names[0].key, "a");
// Property a of first argument
assert(ast.body[0].argnames[0].names[0].value instanceof UglifyJS.AST_DefaultAssign);
assert(ast.body[0].argnames[0].names[0].value.left instanceof UglifyJS.AST_SymbolFunarg);
assert.strictEqual(ast.body[0].argnames[0].names[0].value.operator, "=");
assert(ast.body[0].argnames[0].names[0].value.right instanceof UglifyJS.AST_Number);
ast = UglifyJS.parse("function foo({a: a = 123}) {}");
assert(ast.body[0] instanceof UglifyJS.AST_Defun);
assert.strictEqual(ast.body[0].argnames.length, 1);
// First argument
assert(ast.body[0].argnames[0] instanceof UglifyJS.AST_Destructuring);
assert.strictEqual(ast.body[0].argnames[0].is_array, false);
assert.strictEqual(ast.body[0].argnames[0].names.length, 1);
// Content destructuring of first argument
assert(ast.body[0].argnames[0].names[0] instanceof UglifyJS.AST_ObjectKeyVal);
assert.strictEqual(ast.body[0].argnames[0].names[0].key, "a");
assert(ast.body[0].argnames[0].names[0].value instanceof UglifyJS.AST_DefaultAssign);
// Property a of first argument
assert(ast.body[0].argnames[0].names[0].value instanceof UglifyJS.AST_DefaultAssign);
assert(ast.body[0].argnames[0].names[0].value.left instanceof UglifyJS.AST_SymbolFunarg);
assert.strictEqual(ast.body[0].argnames[0].names[0].value.operator, "=");
assert(ast.body[0].argnames[0].names[0].value.right instanceof UglifyJS.AST_Number);
});
it("Should parse a function containing default assignments in complex destructuring correctly", function() {
var ast = UglifyJS.parse("function foo([a, [b = 123]]){}");
assert(ast.body[0] instanceof UglifyJS.AST_Defun);
assert.strictEqual(ast.body[0].argnames.length, 1);
// Check first argument
assert(ast.body[0].argnames[0] instanceof UglifyJS.AST_Destructuring);
assert.strictEqual(ast.body[0].argnames[0].is_array, true);
assert.strictEqual(ast.body[0].argnames[0].names.length, 2);
// Check whole destructuring structure of first argument
assert(ast.body[0].argnames[0].names[0] instanceof UglifyJS.AST_SymbolFunarg);
assert(ast.body[0].argnames[0].names[1] instanceof UglifyJS.AST_Destructuring);
assert.strictEqual(ast.body[0].argnames[0].names[1].is_array, true);
// Check content of second destructuring element (which is the nested destructuring pattern)
assert(ast.body[0].argnames[0].names[1].names[0] instanceof UglifyJS.AST_DefaultAssign);
assert(ast.body[0].argnames[0].names[1].names[0].left instanceof UglifyJS.AST_SymbolFunarg);
assert.strictEqual(ast.body[0].argnames[0].names[1].names[0].operator, "=");
assert(ast.body[0].argnames[0].names[1].names[0].right instanceof UglifyJS.AST_Number);
ast = UglifyJS.parse("function foo([a, {b: c = 123}]){}");
assert(ast.body[0] instanceof UglifyJS.AST_Defun);
assert.strictEqual(ast.body[0].argnames.length, 1);
// Check first argument
assert(ast.body[0].argnames[0] instanceof UglifyJS.AST_Destructuring);
assert.strictEqual(ast.body[0].argnames[0].is_array, true);
assert.strictEqual(ast.body[0].argnames[0].names.length, 2);
// Check whole destructuring structure of first argument
assert(ast.body[0].argnames[0].names[0] instanceof UglifyJS.AST_SymbolFunarg);
assert(ast.body[0].argnames[0].names[1] instanceof UglifyJS.AST_Destructuring);
assert.strictEqual(ast.body[0].argnames[0].names[1].is_array, false);
// Check content of second destructuring element (which is the nested destructuring pattern)
assert(ast.body[0].argnames[0].names[1].names[0] instanceof UglifyJS.AST_ObjectKeyVal);
assert.strictEqual(ast.body[0].argnames[0].names[1].names[0].key, "b");
assert(ast.body[0].argnames[0].names[1].names[0].value instanceof UglifyJS.AST_DefaultAssign);
// Property b of second argument
assert(ast.body[0].argnames[0].names[1].names[0].value instanceof UglifyJS.AST_DefaultAssign);
assert(ast.body[0].argnames[0].names[1].names[0].value.left instanceof UglifyJS.AST_SymbolFunarg);
assert.strictEqual(ast.body[0].argnames[0].names[1].names[0].value.operator, "=");
assert(ast.body[0].argnames[0].names[1].names[0].value.right instanceof UglifyJS.AST_Number);
ast = UglifyJS.parse("function foo({a, b: {b = 123}}){}");
assert(ast.body[0] instanceof UglifyJS.AST_Defun);
assert.strictEqual(ast.body[0].argnames.length, 1);
// Check first argument
assert(ast.body[0].argnames[0] instanceof UglifyJS.AST_Destructuring);
assert.strictEqual(ast.body[0].argnames[0].is_array, false);
assert.strictEqual(ast.body[0].argnames[0].names.length, 2);
// Check whole destructuring structure of first argument
assert(ast.body[0].argnames[0].names[0] instanceof UglifyJS.AST_ObjectKeyVal);
assert.strictEqual(ast.body[0].argnames[0].names[0].key, "a");
assert(ast.body[0].argnames[0].names[0].value instanceof UglifyJS.AST_SymbolFunarg);
assert(ast.body[0].argnames[0].names[1] instanceof UglifyJS.AST_ObjectKeyVal);
assert.strictEqual(ast.body[0].argnames[0].names[1].key, "b");
assert(ast.body[0].argnames[0].names[1].value instanceof UglifyJS.AST_Destructuring);
// Check content of nested destructuring in first parameter
var content = ast.body[0].argnames[0].names[1].value
assert.strictEqual(content.is_array, false);
assert.strictEqual(content.names.length, 1);
assert(content.names[0] instanceof UglifyJS.AST_ObjectKeyVal);
assert.strictEqual(content.names[0].key, "b");
assert(content.names[0].value instanceof UglifyJS.AST_DefaultAssign);
assert(content.names[0].value.left instanceof UglifyJS.AST_SymbolFunarg);
assert.strictEqual(content.names[0].value.operator, "=");
assert(content.names[0].value.right instanceof UglifyJS.AST_Number);
ast = UglifyJS.parse("function foo({a: {b = 123}}){}");
assert(ast.body[0] instanceof UglifyJS.AST_Defun);
assert.strictEqual(ast.body[0].argnames.length, 1);
// Check first argument
assert(ast.body[0].argnames[0] instanceof UglifyJS.AST_Destructuring);
assert.strictEqual(ast.body[0].argnames[0].is_array, false);
assert.strictEqual(ast.body[0].argnames[0].names.length, 1);
// Check whole destructuring structure of first argument
assert(ast.body[0].argnames[0].names[0] instanceof UglifyJS.AST_ObjectKeyVal);
assert.strictEqual(ast.body[0].argnames[0].names[0].key, "a");
assert(ast.body[0].argnames[0].names[0].value instanceof UglifyJS.AST_Destructuring);
// Check content of nested destructuring
content = ast.body[0].argnames[0].names[0].value
assert.strictEqual(content.is_array, false);
assert.strictEqual(content.names.length, 1);
assert(content.names[0] instanceof UglifyJS.AST_ObjectKeyVal);
assert.strictEqual(content.names[0].key, "b");
assert(content.names[0].value instanceof UglifyJS.AST_DefaultAssign);
assert(content.names[0].value.left instanceof UglifyJS.AST_SymbolFunarg);
assert.strictEqual(content.names[0].value.operator, "=");
assert(content.names[0].value.right instanceof UglifyJS.AST_Number);
});
it("Should parse spread correctly", function() {
var ast = UglifyJS.parse("function foo(a, b, ...c){}");
assert(ast.body[0] instanceof UglifyJS.AST_Defun);
assert.strictEqual(ast.body[0].argnames.length, 3);
// Check parameters
assert(ast.body[0].argnames[0] instanceof UglifyJS.AST_SymbolFunarg);
assert(ast.body[0].argnames[1] instanceof UglifyJS.AST_SymbolFunarg);
assert(ast.body[0].argnames[2] instanceof UglifyJS.AST_Expansion);
assert(ast.body[0].argnames[2].expression instanceof UglifyJS.AST_SymbolFunarg);
ast = UglifyJS.parse("function foo([a, b, ...c]){}");
assert(ast.body[0] instanceof UglifyJS.AST_Defun);
assert.strictEqual(ast.body[0].argnames.length, 1);
// Check first parameter
assert(ast.body[0].argnames[0] instanceof UglifyJS.AST_Destructuring);
assert.strictEqual(ast.body[0].argnames[0].is_array, true);
// Check content first parameter
assert(ast.body[0].argnames[0].names[0] instanceof UglifyJS.AST_SymbolFunarg);
assert(ast.body[0].argnames[0].names[1] instanceof UglifyJS.AST_SymbolFunarg);
assert(ast.body[0].argnames[0].names[2] instanceof UglifyJS.AST_Expansion);
assert(ast.body[0].argnames[0].names[2].expression instanceof UglifyJS.AST_SymbolFunarg);
ast = UglifyJS.parse("function foo([a, b, [c, ...d]]){}");
assert(ast.body[0] instanceof UglifyJS.AST_Defun);
assert.strictEqual(ast.body[0].argnames.length, 1);
// Check first parameter
assert(ast.body[0].argnames[0] instanceof UglifyJS.AST_Destructuring);
assert.strictEqual(ast.body[0].argnames[0].is_array, true);
// Check content outer destructuring array
assert(ast.body[0].argnames[0].names[0] instanceof UglifyJS.AST_SymbolFunarg);
assert(ast.body[0].argnames[0].names[1] instanceof UglifyJS.AST_SymbolFunarg);
assert(ast.body[0].argnames[0].names[2] instanceof UglifyJS.AST_Destructuring);
assert.strictEqual(ast.body[0].argnames[0].names[2].is_array, true);
// Check content nested destructuring array
assert.strictEqual(ast.body[0].argnames[0].names[2].names.length, 2);
assert(ast.body[0].argnames[0].names[2].names[0] instanceof UglifyJS.AST_SymbolFunarg);
assert(ast.body[0].argnames[0].names[2].names[1] instanceof UglifyJS.AST_Expansion);
assert(ast.body[0].argnames[0].names[2].names[1].expression instanceof UglifyJS.AST_SymbolFunarg);
ast = UglifyJS.parse("function foo({a: [b, ...c]}){}");
assert(ast.body[0] instanceof UglifyJS.AST_Defun);
assert.strictEqual(ast.body[0].argnames.length, 1);
// Check first parameter
assert(ast.body[0].argnames[0] instanceof UglifyJS.AST_Destructuring);
assert.strictEqual(ast.body[0].argnames[0].is_array, false);
// Check outer destructuring object
assert.strictEqual(ast.body[0].argnames[0].names.length, 1);
assert(ast.body[0].argnames[0].names[0] instanceof UglifyJS.AST_ObjectKeyVal);
assert.strictEqual(ast.body[0].argnames[0].names[0].key, "a");
assert(ast.body[0].argnames[0].names[0].value instanceof UglifyJS.AST_Destructuring);
assert.strictEqual(ast.body[0].argnames[0].names[0].value.is_array, true);
// Check content nested destructuring array
assert.strictEqual(ast.body[0].argnames[0].names[0].value.names.length, 2);
assert(ast.body[0].argnames[0].names[0].value.names[0] instanceof UglifyJS.AST_SymbolFunarg);
assert(ast.body[0].argnames[0].names[0].value.names[1] instanceof UglifyJS.AST_Expansion);
assert(ast.body[0].argnames[0].names[0].value.names[1].expression instanceof UglifyJS.AST_SymbolFunarg);
});
});
});

View File

@@ -1,399 +0,0 @@
var assert = require("assert");
var uglify = require("../node");
describe("Arrow functions", function() {
it("Should not accept spread tokens on non-last parameters or without arguments parentheses", function() {
var tests = [
"var a = ...a => {return a.join()}",
"var b = (a, ...b, c) => { return a + b.join() + c}",
"var c = (...a, b) => a.join()"
];
var test = function(code) {
return function() {
uglify.parse(code);
}
}
var error = function(e) {
return e instanceof uglify.JS_Parse_Error &&
e.message === "Unexpected token: expand (...)";
}
for (var i = 0; i < tests.length; i++) {
assert.throws(test(tests[i]), error);
}
});
it("Should not accept holes in object binding patterns, while still allowing a trailing elision", function() {
var tests = [
"f = ({, , ...x} = [1, 2]) => {};"
];
var test = function(code) {
return function() {
uglify.parse(code);
}
}
var error = function(e) {
return e instanceof uglify.JS_Parse_Error &&
e.message === "Unexpected token: punc (,)";
}
for (var i = 0; i < tests.length; i++) {
assert.throws(test(tests[i]), error);
}
});
it("Should not accept newlines before arrow token", function() {
var tests = [
"f = foo\n=> 'foo';",
"f = (foo, bar)\n=> 'foo';",
"f = ()\n=> 'foo';",
"foo((bar)\n=>'baz';);"
];
var test = function(code) {
return function() {
uglify.parse(code);
}
}
var error = function(e) {
return e instanceof uglify.JS_Parse_Error &&
e.message === "Unexpected newline before arrow (=>)";
}
for (var i = 0; i < tests.length; i++) {
assert.throws(test(tests[i]), error);
}
});
it("Should not accept arrow functions in the middle or end of an expression", function() {
[
"0 + x => 0",
"0 + async x => 0",
"typeof x => 0",
"typeof async x => 0",
"typeof (x) => null",
"typeof async (x) => null",
].forEach(function(code) {
assert.throws(function() {
uglify.parse(code);
}, function(e) {
return e instanceof uglify.JS_Parse_Error && /^Unexpected /.test(e.message);
}, code);
});
});
it("Should parse a function containing default assignment correctly", function() {
var ast = uglify.parse("var a = (a = 123) => {}");
assert(ast.body[0] instanceof uglify.AST_Var);
assert.strictEqual(ast.body[0].definitions.length, 1);
assert(ast.body[0].definitions[0] instanceof uglify.AST_VarDef);
assert(ast.body[0].definitions[0].name instanceof uglify.AST_SymbolVar);
assert(ast.body[0].definitions[0].value instanceof uglify.AST_Arrow);
assert.strictEqual(ast.body[0].definitions[0].value.argnames.length, 1);
// First argument
assert(ast.body[0].definitions[0].value.argnames[0] instanceof uglify.AST_DefaultAssign);
assert(ast.body[0].definitions[0].value.argnames[0].left instanceof uglify.AST_SymbolFunarg);
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].operator, "=");
assert(ast.body[0].definitions[0].value.argnames[0].right instanceof uglify.AST_Number);
ast = uglify.parse("var a = (a = a) => {}");
assert(ast.body[0] instanceof uglify.AST_Var);
assert.strictEqual(ast.body[0].definitions.length, 1);
assert(ast.body[0].definitions[0] instanceof uglify.AST_VarDef);
assert(ast.body[0].definitions[0].name instanceof uglify.AST_SymbolVar);
assert(ast.body[0].definitions[0].value instanceof uglify.AST_Arrow);
assert.strictEqual(ast.body[0].definitions[0].value.argnames.length, 1);
// First argument
assert(ast.body[0].definitions[0].value.argnames[0] instanceof uglify.AST_DefaultAssign);
assert(ast.body[0].definitions[0].value.argnames[0].left instanceof uglify.AST_SymbolFunarg);
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].operator, "=");
assert(ast.body[0].definitions[0].value.argnames[0].right instanceof uglify.AST_SymbolRef);
});
it("Should parse a function containing default assignments in destructuring correctly", function() {
var ast = uglify.parse("var a = ([a = 123]) => {}");
assert(ast.body[0] instanceof uglify.AST_Var);
assert.strictEqual(ast.body[0].definitions.length, 1);
assert(ast.body[0].definitions[0] instanceof uglify.AST_VarDef);
assert(ast.body[0].definitions[0].name instanceof uglify.AST_SymbolVar);
assert(ast.body[0].definitions[0].value instanceof uglify.AST_Arrow);
assert.strictEqual(ast.body[0].definitions[0].value.argnames.length, 1);
// First argument
assert(ast.body[0].definitions[0].value.argnames[0] instanceof uglify.AST_Destructuring);
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].is_array, true);
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].names.length, 1);
assert(ast.body[0].definitions[0].value.argnames[0].names[0] instanceof uglify.AST_DefaultAssign);
assert(ast.body[0].definitions[0].value.argnames[0].names[0].left instanceof uglify.AST_SymbolFunarg);
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].names[0].operator, "=");
assert(ast.body[0].definitions[0].value.argnames[0].names[0].right instanceof uglify.AST_Number);
ast = uglify.parse("var a = ({a = 123}) => {}");
assert(ast.body[0] instanceof uglify.AST_Var);
assert.strictEqual(ast.body[0].definitions.length, 1);
assert(ast.body[0].definitions[0] instanceof uglify.AST_VarDef);
assert(ast.body[0].definitions[0].name instanceof uglify.AST_SymbolVar);
assert(ast.body[0].definitions[0].value instanceof uglify.AST_Arrow);
assert.strictEqual(ast.body[0].definitions[0].value.argnames.length, 1);
// First argument
assert(ast.body[0].definitions[0].value.argnames[0] instanceof uglify.AST_Destructuring);
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].is_array, false);
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].names.length, 1);
assert(ast.body[0].definitions[0].value.argnames[0].names[0] instanceof uglify.AST_ObjectKeyVal);
// First object element in first argument
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].names[0].key, "a");
assert(ast.body[0].definitions[0].value.argnames[0].names[0].value instanceof uglify.AST_DefaultAssign);
assert(ast.body[0].definitions[0].value.argnames[0].names[0].value.left instanceof uglify.AST_SymbolFunarg);
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].names[0].value.operator, "=");
assert(ast.body[0].definitions[0].value.argnames[0].names[0].value.right instanceof uglify.AST_Number);
ast = uglify.parse("var a = ({a: a = 123}) => {}");
assert(ast.body[0] instanceof uglify.AST_Var);
assert.strictEqual(ast.body[0].definitions.length, 1);
assert(ast.body[0].definitions[0] instanceof uglify.AST_VarDef);
assert(ast.body[0].definitions[0].name instanceof uglify.AST_SymbolVar);
assert(ast.body[0].definitions[0].value instanceof uglify.AST_Arrow);
assert.strictEqual(ast.body[0].definitions[0].value.argnames.length, 1);
// First argument
assert(ast.body[0].definitions[0].value.argnames[0] instanceof uglify.AST_Destructuring);
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].is_array, false);
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].names.length, 1);
// Content destructuring of first argument
assert(ast.body[0].definitions[0].value.argnames[0].names[0] instanceof uglify.AST_ObjectProperty);
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].names[0].key, "a");
assert(ast.body[0].definitions[0].value.argnames[0].names[0].value instanceof uglify.AST_DefaultAssign);
assert(ast.body[0].definitions[0].value.argnames[0].names[0].value.left instanceof uglify.AST_SymbolFunarg);
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].names[0].value.operator, "=");
assert(ast.body[0].definitions[0].value.argnames[0].names[0].value.right instanceof uglify.AST_Number);
});
it("Should parse a function containing default assignments in complex destructuring correctly", function() {
var ast = uglify.parse("var a = ([a, [b = 123]]) => {}");
assert(ast.body[0] instanceof uglify.AST_Var);
assert.strictEqual(ast.body[0].definitions.length, 1);
assert(ast.body[0].definitions[0] instanceof uglify.AST_VarDef);
assert(ast.body[0].definitions[0].name instanceof uglify.AST_SymbolVar);
assert(ast.body[0].definitions[0].value instanceof uglify.AST_Arrow);
assert.strictEqual(ast.body[0].definitions[0].value.argnames.length, 1);
// Check first argument
assert(ast.body[0].definitions[0].value.argnames[0] instanceof uglify.AST_Destructuring);
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].is_array, true);
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].names.length, 2);
// Check whole destructuring structure of first argument
assert(ast.body[0].definitions[0].value.argnames[0].names[0] instanceof uglify.AST_SymbolFunarg);
assert(ast.body[0].definitions[0].value.argnames[0].names[1] instanceof uglify.AST_Destructuring);
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].names[1].is_array, true);
// Check content of second destructuring element (which is the nested destructuring pattern)
assert(ast.body[0].definitions[0].value.argnames[0].names[1].names[0] instanceof uglify.AST_DefaultAssign);
assert(ast.body[0].definitions[0].value.argnames[0].names[1].names[0].left instanceof uglify.AST_SymbolFunarg);
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].names[1].names[0].operator, "=");
assert(ast.body[0].definitions[0].value.argnames[0].names[1].names[0].right instanceof uglify.AST_Number);
ast = uglify.parse("var a = ([a, {b: c = 123}]) => {}");
assert(ast.body[0] instanceof uglify.AST_Var);
assert.strictEqual(ast.body[0].definitions.length, 1);
assert(ast.body[0].definitions[0] instanceof uglify.AST_VarDef);
assert(ast.body[0].definitions[0].name instanceof uglify.AST_SymbolVar);
assert(ast.body[0].definitions[0].value instanceof uglify.AST_Arrow);
assert.strictEqual(ast.body[0].definitions[0].value.argnames.length, 1);
// Check first argument
assert(ast.body[0].definitions[0].value.argnames[0] instanceof uglify.AST_Destructuring);
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].is_array, true);
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].names.length, 2);
// Check whole destructuring structure of first argument
assert(ast.body[0].definitions[0].value.argnames[0].names[0] instanceof uglify.AST_SymbolFunarg);
assert(ast.body[0].definitions[0].value.argnames[0].names[1] instanceof uglify.AST_Destructuring);
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].names[1].is_array, false);
// Check content of second destructuring element (which is the nested destructuring pattern)
assert(ast.body[0].definitions[0].value.argnames[0].names[1].names[0] instanceof uglify.AST_ObjectKeyVal);
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].names[1].names[0].key, "b");
assert(ast.body[0].definitions[0].value.argnames[0].names[1].names[0].value instanceof uglify.AST_DefaultAssign);
assert(ast.body[0].definitions[0].value.argnames[0].names[1].names[0].value.left instanceof uglify.AST_SymbolFunarg);
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].names[1].names[0].value.operator, "=");
assert(ast.body[0].definitions[0].value.argnames[0].names[1].names[0].value.right instanceof uglify.AST_Number);
ast = uglify.parse("var a = ({a, b: {b = 123}}) => {}");
assert(ast.body[0] instanceof uglify.AST_Var);
assert.strictEqual(ast.body[0].definitions.length, 1);
assert(ast.body[0].definitions[0] instanceof uglify.AST_VarDef);
assert(ast.body[0].definitions[0].name instanceof uglify.AST_SymbolVar);
assert(ast.body[0].definitions[0].value instanceof uglify.AST_Arrow);
assert.strictEqual(ast.body[0].definitions[0].value.argnames.length, 1);
// Check first argument
assert(ast.body[0].definitions[0].value.argnames[0] instanceof uglify.AST_Destructuring);
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].is_array, false);
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].names.length, 2);
// First argument, property 1
assert(ast.body[0].definitions[0].value.argnames[0].names[0] instanceof uglify.AST_ObjectKeyVal);
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].names[0].key, "a");
assert(ast.body[0].definitions[0].value.argnames[0].names[0].value instanceof uglify.AST_SymbolFunarg);
// First argument, property 2
assert(ast.body[0].definitions[0].value.argnames[0].names[1] instanceof uglify.AST_ObjectKeyVal);
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].names[1].key, "b");
assert(ast.body[0].definitions[0].value.argnames[0].names[1].value instanceof uglify.AST_Destructuring);
// Check content of nested destructuring
var content = ast.body[0].definitions[0].value.argnames[0].names[1].value
assert.strictEqual(content.is_array, false);
assert.strictEqual(content.names.length, 1);
assert(content.names[0] instanceof uglify.AST_ObjectKeyVal);
// Content of first property in nested destructuring
assert.strictEqual(content.names[0].key, "b");
assert(content.names[0].value instanceof uglify.AST_DefaultAssign);
assert(content.names[0].value.left instanceof uglify.AST_SymbolFunarg);
assert.strictEqual(content.names[0].value.operator, "=");
assert(content.names[0].value.right instanceof uglify.AST_Number);
ast = uglify.parse("var a = ({a: {b = 123}}) => {}");
assert(ast.body[0] instanceof uglify.AST_Var);
assert.strictEqual(ast.body[0].definitions.length, 1);
assert(ast.body[0].definitions[0] instanceof uglify.AST_VarDef);
assert(ast.body[0].definitions[0].name instanceof uglify.AST_SymbolVar);
assert(ast.body[0].definitions[0].value instanceof uglify.AST_Arrow);
assert.strictEqual(ast.body[0].definitions[0].value.argnames.length, 1);
// Check first argument
assert(ast.body[0].definitions[0].value.argnames[0] instanceof uglify.AST_Destructuring);
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].is_array, false);
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].names.length, 1);
// Check whole destructuring structure of first argument
assert(ast.body[0].definitions[0].value.argnames[0].names[0] instanceof uglify.AST_ObjectKeyVal);
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].names[0].key, "a");
assert(ast.body[0].definitions[0].value.argnames[0].names[0].value instanceof uglify.AST_Destructuring);
// Check content of nested destructuring
content = ast.body[0].definitions[0].value.argnames[0].names[0].value
assert.strictEqual(content.is_array, false);
assert.strictEqual(content.names.length, 1);
assert(content.names[0] instanceof uglify.AST_ObjectKeyVal);
// Check first property of nested destructuring
assert.strictEqual(content.names[0].key, "b");
assert(content.names[0].value instanceof uglify.AST_DefaultAssign);
assert(content.names[0].value.left instanceof uglify.AST_SymbolFunarg);
assert.strictEqual(content.names[0].value.operator, "=");
assert(content.names[0].value.right instanceof uglify.AST_Number);
});
it("Should parse spread correctly", function() {
var ast = uglify.parse("var a = (a, b, ...c) => {}");
assert(ast.body[0] instanceof uglify.AST_Var);
assert.strictEqual(ast.body[0].definitions.length, 1);
assert(ast.body[0].definitions[0] instanceof uglify.AST_VarDef);
assert(ast.body[0].definitions[0].name instanceof uglify.AST_SymbolVar);
assert(ast.body[0].definitions[0].value instanceof uglify.AST_Arrow);
assert.strictEqual(ast.body[0].definitions[0].value.argnames.length, 3);
// Check parameters
assert(ast.body[0].definitions[0].value.argnames[0] instanceof uglify.AST_SymbolFunarg);
assert(ast.body[0].definitions[0].value.argnames[1] instanceof uglify.AST_SymbolFunarg);
assert(ast.body[0].definitions[0].value.argnames[2] instanceof uglify.AST_Expansion);
assert(ast.body[0].definitions[0].value.argnames[2].expression instanceof uglify.AST_SymbolFunarg);
ast = uglify.parse("var a = ([a, b, ...c]) => {}");
assert(ast.body[0] instanceof uglify.AST_Var);
assert.strictEqual(ast.body[0].definitions.length, 1);
assert(ast.body[0].definitions[0] instanceof uglify.AST_VarDef);
assert(ast.body[0].definitions[0].name instanceof uglify.AST_SymbolVar);
assert(ast.body[0].definitions[0].value instanceof uglify.AST_Arrow);
assert.strictEqual(ast.body[0].definitions[0].value.argnames.length, 1);
// Check first parameter
assert(ast.body[0].definitions[0].value.argnames[0] instanceof uglify.AST_Destructuring);
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].is_array, true);
// Check content first parameter
assert(ast.body[0].definitions[0].value.argnames[0].names[0] instanceof uglify.AST_SymbolFunarg);
assert(ast.body[0].definitions[0].value.argnames[0].names[1] instanceof uglify.AST_SymbolFunarg);
assert(ast.body[0].definitions[0].value.argnames[0].names[2] instanceof uglify.AST_Expansion);
assert(ast.body[0].definitions[0].value.argnames[0].names[2].expression instanceof uglify.AST_SymbolFunarg);
ast = uglify.parse("var a = ([a, b, [c, ...d]]) => {}");
assert(ast.body[0] instanceof uglify.AST_Var);
assert.strictEqual(ast.body[0].definitions.length, 1);
assert(ast.body[0].definitions[0] instanceof uglify.AST_VarDef);
assert(ast.body[0].definitions[0].name instanceof uglify.AST_SymbolVar);
assert(ast.body[0].definitions[0].value instanceof uglify.AST_Arrow);
assert.strictEqual(ast.body[0].definitions[0].value.argnames.length, 1);
// Check first parameter
assert(ast.body[0].definitions[0].value.argnames[0] instanceof uglify.AST_Destructuring);
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].is_array, true);
// Check content outer destructuring array
assert(ast.body[0].definitions[0].value.argnames[0].names[0] instanceof uglify.AST_SymbolFunarg);
assert(ast.body[0].definitions[0].value.argnames[0].names[1] instanceof uglify.AST_SymbolFunarg);
assert(ast.body[0].definitions[0].value.argnames[0].names[2] instanceof uglify.AST_Destructuring);
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].names[2].is_array, true);
// Check content nested destructuring array
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].names[2].names.length, 2);
assert(ast.body[0].definitions[0].value.argnames[0].names[2].names[0] instanceof uglify.AST_SymbolFunarg);
assert(ast.body[0].definitions[0].value.argnames[0].names[2].names[1] instanceof uglify.AST_Expansion);
assert(ast.body[0].definitions[0].value.argnames[0].names[2].names[1].expression instanceof uglify.AST_SymbolFunarg);
ast = uglify.parse("var a = ({a: [b, ...c]}) => {}");
assert(ast.body[0] instanceof uglify.AST_Var);
assert.strictEqual(ast.body[0].definitions.length, 1);
assert(ast.body[0].definitions[0] instanceof uglify.AST_VarDef);
assert(ast.body[0].definitions[0].name instanceof uglify.AST_SymbolVar);
assert(ast.body[0].definitions[0].value instanceof uglify.AST_Arrow);
assert.strictEqual(ast.body[0].definitions[0].value.argnames.length, 1);
// Check first parameter
assert(ast.body[0].definitions[0].value.argnames[0] instanceof uglify.AST_Destructuring);
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].is_array, false);
// Check outer destructuring object
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].names.length, 1);
assert(ast.body[0].definitions[0].value.argnames[0].names[0] instanceof uglify.AST_ObjectKeyVal);
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].names[0].key, "a");
assert(ast.body[0].definitions[0].value.argnames[0].names[0].value instanceof uglify.AST_Destructuring);
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].names[0].value.is_array, true);
// Check content nested destructuring array
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].names[0].value.names.length, 2);
assert(ast.body[0].definitions[0].value.argnames[0].names[0].value.names[0] instanceof uglify.AST_SymbolFunarg);
assert(ast.body[0].definitions[0].value.argnames[0].names[0].value.names[1] instanceof uglify.AST_Expansion);
assert(ast.body[0].definitions[0].value.argnames[0].names[0].value.names[1].expression instanceof uglify.AST_SymbolFunarg);
});
it("Should handle arrow function with bind", function() {
function minify(code) {
return uglify.minify(code, {
mangle: false
}).code;
}
assert.strictEqual(
minify(minify("test(((index) => { console.log(this, index); }).bind(this, 1));")),
"test((index=>{console.log(this,index)}).bind(this,1));"
);
assert.strictEqual(
minify(minify('test(((index) => { console.log(this, index); })["bind"](this, 1));')),
"test((index=>{console.log(this,index)}).bind(this,1));"
);
});
});

View File

@@ -1,34 +0,0 @@
var UglifyJS = require("../../");
var assert = require("assert");
describe("builtins", function() {
it ("Should not mangle builtins", function() {
var test = "function foo(something){\n" +
" return [Object,Array,Function,Number,String,Boolean,Error,Math,Date,RegExp,Symbol,Map,Promise,Proxy,Reflect,Set,WeakMap,WeakSet,Float32Array,something];\n" +
"};";
var result = UglifyJS.minify(test, {parse: {bare_returns: true}}).code;
assert.strictEqual(result.indexOf("something"), -1);
assert.notEqual(result.indexOf("Object"), -1);
assert.notEqual(result.indexOf("Array"), -1);
assert.notEqual(result.indexOf("Function"), -1);
assert.notEqual(result.indexOf("Number"), -1);
assert.notEqual(result.indexOf("String"), -1);
assert.notEqual(result.indexOf("Boolean"), -1);
assert.notEqual(result.indexOf("Error"), -1);
assert.notEqual(result.indexOf("Math"), -1);
assert.notEqual(result.indexOf("Date"), -1);
assert.notEqual(result.indexOf("RegExp"), -1);
assert.notEqual(result.indexOf("Symbol"), -1);
assert.notEqual(result.indexOf("Promise"), -1);
assert.notEqual(result.indexOf("Proxy"), -1);
assert.notEqual(result.indexOf("Reflect"), -1);
assert.notEqual(result.indexOf("Set"), -1);
assert.notEqual(result.indexOf("WeakMap"), -1);
assert.notEqual(result.indexOf("WeakSet"), -1);
assert.notEqual(result.indexOf("Map"), -1);
assert.notEqual(result.indexOf("Float32Array"), -1);
});
});

View File

@@ -1,57 +0,0 @@
var assert = require("assert");
var uglify = require("../node");
describe("Class", function() {
it("Should not accept spread on non-last parameters in methods", function() {
var tests = [
"class foo { bar(...a, b) { return a.join(b) } }",
"class foo { bar(a, b, ...c, d) { return c.join(a + b) + d } }",
"class foo { *bar(...a, b) { return a.join(b) } }",
"class foo { *bar(a, b, ...c, d) { return c.join(a + b) + d } }"
];
var test = function(code) {
return function() {
uglify.parse(code);
}
}
var error = function(e) {
return e instanceof uglify.JS_Parse_Error &&
/^Unexpected token: /.test(e.message);
}
for (var i = 0; i < tests.length; i++) {
assert.throws(test(tests[i]), error);
}
});
it("Should return the correct token for class methods", function() {
var tests = [
{
code: "class foo{static test(){}}",
token_value_start: "static",
token_value_end: "}"
},
{
code: "class bar{*procedural(){}}",
token_value_start: "*",
token_value_end: "}"
},
{
code: "class foobar{aMethod(){}}",
token_value_start: "aMethod",
token_value_end: "}"
},
{
code: "class foobaz{get something(){}}",
token_value_start: "get",
token_value_end: "}"
}
];
for (var i = 0; i < tests.length; i++) {
var ast = uglify.parse(tests[i].code);
assert.strictEqual(ast.body[0].properties[0].start.value, tests[i].token_value_start);
assert.strictEqual(ast.body[0].properties[0].end.value, tests[i].token_value_end);
}
});
});

View File

@@ -1,7 +1,6 @@
var assert = require("assert");
var exec = require("child_process").exec;
var readFileSync = require("fs").readFileSync;
var semver = require("semver");
function read(path) {
return readFileSync(path, "utf8");
@@ -10,11 +9,9 @@ function read(path) {
describe("bin/uglifyjs", function () {
var uglifyjscmd = '"' + process.argv[0] + '" bin/uglifyjs';
it("should produce a functional build when using --self", function (done) {
this.timeout(60000);
this.timeout(30000);
var command = uglifyjscmd + ' --self -mc ecma=';
command += semver.satisfies(process.version, ">=4") ? "6" : "5";
command += ',passes=3,keep_fargs=false,unsafe --wrap WrappedUglifyJS';
var command = uglifyjscmd + ' --self -cm --wrap WrappedUglifyJS';
exec(command, function (err, stdout) {
if (err) throw err;
@@ -401,21 +398,6 @@ describe("bin/uglifyjs", function () {
done();
});
});
it("Should throw syntax error (const a)", function(done) {
var command = uglifyjscmd + ' test/input/invalid/const.js';
exec(command, function (err, stdout, stderr) {
assert.ok(err);
assert.strictEqual(stdout, "");
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
"Parse error at test/input/invalid/const.js:7,11",
" const a;",
" ^",
"ERROR: Missing initializer in const declaration"
].join("\n"));
done();
});
});
it("Should throw syntax error (delete x)", function(done) {
var command = uglifyjscmd + ' test/input/invalid/delete.js';
@@ -486,7 +468,7 @@ describe("bin/uglifyjs", function () {
"Parse error at test/input/invalid/try.js:7,18",
" try {} catch (eval) {}",
" ^",
"ERROR: Unexpected eval identifier as parameter inside strict mode"
"ERROR: Unexpected eval in strict mode"
].join("\n"));
done();
});
@@ -536,81 +518,6 @@ describe("bin/uglifyjs", function () {
done();
});
});
it("Should throw syntax error (block-level export)", function(done) {
var command = uglifyjscmd + ' test/input/invalid/export_1.js -m';
exec(command, function (err, stdout, stderr) {
assert.ok(err);
assert.strictEqual(stdout, "");
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
"Parse error at test/input/invalid/export_1.js:2,4",
" export var V = 1;",
" ^",
"ERROR: Export statement may only appear at top level"
].join("\n"));
done();
});
});
it("Should throw syntax error (block-level import)", function(done) {
var command = uglifyjscmd + ' test/input/invalid/import.js -m';
exec(command, function (err, stdout, stderr) {
assert.ok(err);
assert.strictEqual(stdout, "");
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
"Parse error at test/input/invalid/import.js:2,4",
' import A from "B";',
" ^",
"ERROR: Import statement may only appear at top level"
].join("\n"));
done();
});
});
it("Should throw syntax error (anonymous class)", function(done) {
var command = uglifyjscmd + ' test/input/invalid/export_2.js';
exec(command, function (err, stdout, stderr) {
assert.ok(err);
assert.strictEqual(stdout, "");
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
"Parse error at test/input/invalid/export_2.js:1,12",
"export class{};",
" ^",
"ERROR: Unexpected token: punc ({)"
].join("\n"));
done();
});
});
it("Should throw syntax error (anonymous function)", function(done) {
var command = uglifyjscmd + ' test/input/invalid/export_3.js';
exec(command, function (err, stdout, stderr) {
assert.ok(err);
assert.strictEqual(stdout, "");
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
"Parse error at test/input/invalid/export_3.js:1,15",
"export function(){};",
" ^",
"ERROR: Unexpected token: punc (()"
].join("\n"));
done();
});
});
it("Should throw syntax error (spread in sequence)", function(done) {
var command = uglifyjscmd + ' test/input/invalid/sequence.js';
exec(command, function (err, stdout, stderr) {
assert.ok(err);
assert.strictEqual(stdout, "");
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
"Parse error at test/input/invalid/sequence.js:1,4",
"(a, ...b);",
" ^",
"ERROR: Unexpected token: expand (...)"
].join("\n"));
done();
});
});
it("Should throw syntax error (for-in init)", function(done) {
var command = uglifyjscmd + ' test/input/invalid/for-in_1.js';

View File

@@ -31,8 +31,7 @@ describe("Comment", function() {
"/*Some comment 2\r\n\r\n\r\n*/\r\n>\n\n\n\n\n\n",
"/*Some comment 3\r\r\r*/\r>\n\n\n\n\n\n",
"/*Some comment 4\u2028\u2028\u2028*/\u2028>\n\n\n\n\n\n",
"/*Some comment 5\u2029\u2029\u2029*/\u2029>\n\n\n\n\n\n",
"/*Some comment 6\udbff\udfff\udbff\udfff\n\n\n*/\n>\n\n\n\n\n"
"/*Some comment 5\u2029\u2029\u2029*/\u2029>\n\n\n\n\n\n"
];
var fail = function(e) {

View File

@@ -1,138 +0,0 @@
var assert = require("assert");
var uglify = require("../node");
describe("Destructuring", function() {
it("Should generate similar trees for destructuring in left hand side expressions, definitions, functions and arrow functions", function() {
var patterns = [
"[]",
"{}",
"[a, b, c]",
"{a: b, c: d}",
"{a}",
"{a, b}",
"{a: {}}",
"{a: []}",
"[{}]",
"[[]]",
"{a: {b}}",
// Can't do `a = 123` with lhs expression, so only test in destructuring
"[foo = bar]",
"{a = 123}",
"[{foo: abc = 123}]",
"{foo: [abc = 123]}",
"[...foo]",
"[...{}]",
"[...[]]"
// Can't do `...` because that is an invalid lhs expression, spread in array destructuring should be fine though
];
var types = [
{
name: "lhs",
symbolType: uglify.AST_SymbolRef,
tree: function (ast) {
return ast.body[0].body.left;
},
generate: function (code) {
return "(" + code + " = a)";
}
},
{
name: "var",
symbolType: uglify.AST_SymbolVar,
tree: function (ast) {
return ast.body[0].definitions[0].name;
},
generate: function (code) {
return "var " + code + " = a";
}
},
{
name: "function",
symbolType: uglify.AST_SymbolFunarg,
tree: function (ast) {
return ast.body[0].argnames[0];
},
generate: function (code) {
return "function a(" + code + ") {}";
}
},
{
name: "arrow",
symbolType: uglify.AST_SymbolFunarg,
tree: function (ast) {
return ast.body[0].definitions[0].value.argnames[0];
},
generate: function (code) {
return "var a = (" + code + ") => {}";
}
}
];
var walker = function(type, ref, code, result) {
var w = new uglify.TreeWalker(function(node) {
if (w.parent() instanceof uglify.AST_DefaultAssign &&
w.parent().right === node
) {
return true; // Don't check the content of the default assignment
} else if (node instanceof uglify.AST_Symbol) {
assert(node instanceof type.symbolType,
node.TYPE + " while " + type.symbolType.TYPE + " expected at pos " +
node.start.pos + " in `" + code + "` (" + ref + ")"
);
result.push([
new uglify.AST_Symbol({
start: node.start,
name: node.name,
end: node.end
}),
w.parent()
]);
return;
}
result.push([node, w.parent()]);
});
return w;
};
var getNodeType = function(node) {
return node[0].TYPE + (node[1] ? " " + node[1].TYPE : "");
}
for (var i = 0; i < patterns.length; i++) {
var results = [];
for (var j = 0; j < types.length; j++) {
var code = types[j].generate(patterns[i])
var ast = types[j].tree(
uglify.parse(code)
);
results.push([]);
ast.walk(walker(
types[j],
"`" + patterns[i] + "` on " + types[j].name,
code,
results[j]
));
if (j > 0) {
assert.deepEqual(
results[0].map(getNodeType),
results[j].map(getNodeType),
"AST disagree on " + patterns[i] + " with " + types[j].name
);
}
}
}
});
});

View File

@@ -62,10 +62,10 @@ describe("Directives", function() {
it("Should know which strings are directive and which ones are not", function() {
var test_directive = function(tokenizer, test) {
test.directives.map(function(directive) {
assert.strictEqual(tokenizer.has_directive(directive), true, "Didn't found directive `" + directive + "` at the end of `" + test.input + '`');
assert.strictEqual(tokenizer.has_directive(directive), true, directive + " in " + test.input);
});
test.non_directives.map(function(fake_directive) {
assert.strictEqual(tokenizer.has_directive(fake_directive), false, "Unexpectedly found directive `" + fake_directive + "` at the end of `" + test.input + '`');
assert.strictEqual(tokenizer.has_directive(fake_directive), false, fake_directive + " in " + test.input);
});
}
@@ -156,16 +156,6 @@ describe("Directives", function() {
input: '"use strict";try{"use asm";',
directives: ["use strict"],
non_directives: ["use\nstrict", "use \nstrict", "use asm"]
},
{
input: 'class foo {',
directives: ["use strict"],
non_directives: ["use\nstrict", "use asm"]
},
{
input: 'class foo {}',
directives: [],
non_directives: ["use strict", "use asm", "use\nstrict"]
}
];
@@ -388,44 +378,4 @@ describe("Directives", function() {
);
}
});
it("Should be detect implicit usages of strict mode from tree walker", function() {
var tests = [
{
input: 'class foo {bar(){_check_}}',
directives: ["use strict"],
non_directives: ["use bar"]
},
{
input: 'class foo {bar(){}}_check_',
directives: [],
non_directives: ["use strict", "use bar"]
}
];
var i = 0;
var checked;
var checkWalker = new uglify.TreeWalker(function(node, descend) {
if (node instanceof uglify.AST_Symbol && node.name === "_check_") {
checked = true;
for (var j = 0; j < tests[i].directives.length; j++) {
assert.ok(checkWalker.has_directive(tests[i].directives[j]),
"Did not found directive '" + tests[i].directives[j] + "' in test " + tests[i].input)
}
for (var k = 0; k < tests[i].non_directives.length; k++) {
assert.equal(checkWalker.has_directive(tests[i].non_directives[k]), undefined,
"Found directive '" + tests[i].non_directives[k] + "' in test " + tests[i].input)
}
}
});
for (; i < tests.length; i++) {
// Do tests - iterate the ast in each test - check only when _check_ occurs - fail when no _check_ has been found
checked = false;
var ast = uglify.parse(tests[i].input);
ast.walk(checkWalker);
if (!checked) {
throw "No _check_ symbol found in " + tests[i].input;
}
}
});
});

View File

@@ -1,35 +0,0 @@
var assert = require("assert");
var uglify = require("../node");
describe("EOF", function() {
it("Should test code for at least throwing syntax error when incomplete", function() {
var error = function(e) {
return e instanceof uglify.JS_Parse_Error;
}
var parse = function(test) {
return function() {
uglify.parse(test);
}
}
// Chops off 1 char at a time until limit or start of string is reached
// The passed code must still be valid when unchopped
var test_eol = function(input, chopLimit) {
if (chopLimit === undefined) {
chopLimit = input.length - 1;
}
assert.doesNotThrow(parse(input), "Expected valid code for \n" + input);
for (var i = input.length - 1; chopLimit > 0; chopLimit--, i--) {
var code = input.substr(0, i);
assert.throws(parse(code), error, code);
}
}
test_eol("var \\u1234", 7); // Incomplete identifier
test_eol("'Incomplete string'");
test_eol("/Unterminated regex/");
test_eol("` Unterminated template string`");
test_eol("/* Unfinishing multiline comment */");
});
});

View File

@@ -1,39 +0,0 @@
var assert = require("assert");
var uglify = require("../node");
describe("Export", function() {
it("Should parse export directives", function() {
var inputs = [
['export * from "a.js"', ['*'], "a.js"],
['export {A} from "a.js"', ['A'], "a.js"],
['export {A as X} from "a.js"', ['X'], "a.js"],
['export {A as Foo, B} from "a.js"', ['Foo', 'B'], "a.js"],
['export {A, B} from "a.js"', ['A', 'B'], "a.js"],
];
function test(code) {
return uglify.parse(code);
}
function extractNames(symbols) {
var ret = [];
for (var i = 0; i < symbols.length; i++) {
ret.push(symbols[i].foreign_name.name);
}
return ret;
}
for (var i = 0; i < inputs.length; i++) {
var ast = test(inputs[i][0]);
var names = inputs[i][1];
var filename = inputs[i][2];
assert(ast instanceof uglify.AST_Toplevel);
assert.equal(ast.body.length, 1);
var st = ast.body[0];
assert(st instanceof uglify.AST_Export);
var actualNames = extractNames(st.exported_names);
assert.deepEqual(actualNames, names);
assert.equal(st.module_name.value, filename);
}
});
});

View File

@@ -1,32 +0,0 @@
var assert = require("assert");
var uglify = require("../node");
describe("Expression", function() {
it("Should not allow the first exponentiation operator to be prefixed with an unary operator", function() {
var tests = [
"+5 ** 3",
"-5 ** 3",
"~5 ** 3",
"!5 ** 3",
"void 5 ** 3",
"typeof 5 ** 3",
"delete 5 ** 3",
"var a = -(5) ** 3;"
];
var fail = function(e) {
return e instanceof uglify.JS_Parse_Error &&
/^Unexpected token: operator \((?:[!+~-]|void|typeof|delete)\)/.test(e.message);
}
var exec = function(test) {
return function() {
uglify.parse(test);
}
}
for (var i = 0; i < tests.length; i++) {
assert.throws(exec(tests[i]), fail, tests[i]);
}
});
});

View File

@@ -1,288 +0,0 @@
var assert = require("assert");
var uglify = require("../node");
describe("Function", function() {
it ("Should parse binding patterns correctly", function() {
// Function argument nodes are correct
function get_args(args) {
return args.map(function (arg) {
return [arg.TYPE, arg.name];
});
}
// Destructurings as arguments
var destr_fun1 = uglify.parse('(function ({a, b}) {})').body[0].body;
var destr_fun2 = uglify.parse('(function ([a, [b]]) {})').body[0].body;
var destr_fun3 = uglify.parse('({a, b}) => null').body[0].body;
var destr_fun4 = uglify.parse('([a, [b]]) => null').body[0].body;
assert.equal(destr_fun1.argnames.length, 1);
assert.equal(destr_fun2.argnames.length, 1);
assert.equal(destr_fun3.argnames.length, 1);
assert.equal(destr_fun4.argnames.length, 1);
var destruct1 = destr_fun1.argnames[0];
var destruct2 = destr_fun2.argnames[0];
var destruct3 = destr_fun3.argnames[0];
var destruct4 = destr_fun4.argnames[0];
assert(destruct1 instanceof uglify.AST_Destructuring);
assert(destruct2 instanceof uglify.AST_Destructuring);
assert(destruct3 instanceof uglify.AST_Destructuring);
assert(destruct4 instanceof uglify.AST_Destructuring);
assert(destruct2.names[1] instanceof uglify.AST_Destructuring);
assert(destruct4.names[1] instanceof uglify.AST_Destructuring);
assert.equal(destruct1.start.value, '{');
assert.equal(destruct1.end.value, '}');
assert.equal(destruct2.start.value, '[');
assert.equal(destruct2.end.value, ']');
assert.equal(destruct3.start.value, '{');
assert.equal(destruct3.end.value, '}');
assert.equal(destruct4.start.value, '[');
assert.equal(destruct4.end.value, ']');
assert.equal(destruct1.is_array, false);
assert.equal(destruct2.is_array, true);
assert.equal(destruct3.is_array, false);
assert.equal(destruct4.is_array, true);
// destruct 1
assert.deepEqual(
[
destruct1.names[0].TYPE,
destruct1.names[0].key,
destruct1.names[0].value.name
],
['ObjectKeyVal', 'a', 'a']
);
assert.deepEqual(
[
destruct1.names[1].TYPE,
destruct1.names[1].key,
destruct1.names[1].value.name
],
['ObjectKeyVal', 'b', 'b']
);
// destruct 2
assert.deepEqual(
[
destruct2.names[0].TYPE,
destruct2.names[0].name
],
['SymbolFunarg', 'a']
);
assert.deepEqual(
[
destruct2.names[1].names[0].TYPE,
destruct2.names[1].names[0].name
],
['SymbolFunarg', 'b']
);
// destruct 3
assert.strictEqual(typeof destruct3.names[0].key, "string");
assert.strictEqual(destruct3.names[0].key, "a");
assert.strictEqual(destruct3.names[0].value.TYPE, "SymbolFunarg");
assert.strictEqual(destruct3.names[0].value.name, "a");
assert.strictEqual(typeof destruct3.names[1].key, "string");
assert.strictEqual(destruct3.names[1].key, "b");
assert.strictEqual(destruct3.names[1].value.TYPE, "SymbolFunarg");
assert.strictEqual(destruct3.names[1].value.name, "b");
// destruct 4
assert.deepEqual(
[
destruct4.names[0].TYPE,
destruct4.names[0].name
],
['SymbolFunarg', 'a']
);
assert.strictEqual(destruct4.names[1].TYPE, "Destructuring");
assert.deepEqual(
[
destruct4.names[1].names[0].TYPE,
destruct4.names[1].names[0].name
],
['SymbolFunarg', 'b']
);
assert.deepEqual(
get_args(destr_fun1.args_as_names()),
[['SymbolFunarg', 'a'], ['SymbolFunarg', 'b']]
);
assert.deepEqual(
get_args(destr_fun2.args_as_names()),
[['SymbolFunarg', 'a'], ['SymbolFunarg', 'b']]
);
assert.deepEqual(
get_args(destr_fun3.args_as_names()),
[['SymbolFunarg', 'a'], ['SymbolFunarg', 'b']]
);
assert.deepEqual(
get_args(destr_fun4.args_as_names()),
[['SymbolFunarg', 'a'], ['SymbolFunarg', 'b']]
);
// Making sure we don't accidentally accept things which
// Aren't argument destructurings
assert.throws(function () {
uglify.parse('(function ( { a, [ b ] } ) { })')
});
assert.throws(function () {
uglify.parse('(function (1) { })');
}, /Invalid function parameter/);
assert.throws(function () {
uglify.parse('(function (this) { })');
});
assert.throws(function () {
uglify.parse('(function ([1]) { })');
}, /Invalid function parameter/);
assert.throws(function () {
uglify.parse('(function [a] { })');
});
// generators
var generators_def = uglify.parse('function* fn() {}').body[0];
assert.equal(generators_def.is_generator, true);
assert.throws(function () {
uglify.parse('function* (){ }');
});
var generators_yield_def = uglify.parse('function* fn() {\nyield remote();\}').body[0].body[0];
assert.strictEqual(generators_yield_def.body.is_star, false);
});
it("Should not accept spread on non-last parameters", function() {
var tests = [
"var a = function(...a, b) { return a.join(b) }",
"var b = function(a, b, ...c, d) { return c.join(a + b) + d }",
"function foo(...a, b) { return a.join(b) }",
"function bar(a, b, ...c, d) { return c.join(a + b) + d }",
"var a = function*(...a, b) { return a.join(b) }",
"var b = function*(a, b, ...c, d) { return c.join(a + b) + d }",
"function* foo(...a, b) { return a.join(b) }",
"function* bar(a, b, ...c, d) { return c.join(a + b) + d }"
];
var test = function(code) {
return function() {
uglify.parse(code);
}
}
var error = function(e) {
return e instanceof uglify.JS_Parse_Error &&
/^Unexpected token: /.test(e.message);
}
for (var i = 0; i < tests.length; i++) {
assert.throws(test(tests[i]), error);
}
});
it("Should not accept empty parameters after elision", function() {
var tests = [
"(function(,){})()",
"(function(a,){})()",
];
var test = function(code) {
return function() {
uglify.parse(code, { ecma: 5 });
}
}
var error = function(e) {
return e instanceof uglify.JS_Parse_Error;
}
for (var i = 0; i < tests.length; i++) {
assert.throws(test(tests[i]), error, tests[i]);
}
});
it("Should accept trailing commas only for ES8", function() {
[
"new Foo(a, );",
"async(...[1, 2], );",
"console.log(...[1, 2], );",
"!function(a, b, ){ console.log(a + b); }(3, 4, );",
].forEach(function(code) {
uglify.parse(code, { ecma: 8 });
assert.throws(function() {
uglify.parse(code, { ecma: 6 });
}, function(e) {
return e instanceof uglify.JS_Parse_Error;
}, code);
});
});
it("Should not accept invalid trailing commas", function() {
var tests = [
"f(, );",
"(, ) => {};",
"(...p, ) => {};",
"function f(, ) {}",
"function f(...p, ) {}",
"function foo(a, b, , ) {}",
'console.log("hello", , );',
];
var test = function(code) {
return function() {
uglify.parse(code, { ecma: 8 });
}
}
var error = function(e) {
return e instanceof uglify.JS_Parse_Error;
}
for (var i = 0; i < tests.length; i++) {
assert.throws(test(tests[i]), error, tests[i]);
}
});
it("Should not accept an initializer when parameter is a rest parameter", function() {
var tests = [
"(function(...a = b){})()",
"(function(a, ...b = [c, d]))"
];
var test = function(code) {
return function () {
uglify.parse(code);
}
}
var error = function (e) {
return e instanceof uglify.JS_Parse_Error;
}
for (var i = 0; i < tests.length; i++) {
assert.throws(test(tests[i]), error, tests[i]);
}
});
it("Shoult not accept duplicated identifiers inside parameters in strict mode or when using default assigment or spread", function() {
// From: ES2016 9.2.12 FunctionDeclarationInstantiation (func, argumentsList)
// NOTE Early errors ensure that duplicate parameter names can only occur
// in non-strict functions that do not have parameter default values or
// rest parameters.
var tests = [
"(function(a = 1, a){})()",
"(function(a, [a = 3]){})()",
"(function(a, b, c, d, [{e: [...a]}]){})()",
"'use strict'; (function(a, a){})",
"(function({a, a = b}))",
"(function(a, [...a]){})",
"(function(a, ...a){})",
"(function(a, [a, ...b]){})",
"(function(a, {b: a, c: [...d]}){})",
"(function(a, a, {b: [...c]}){})"
];
var test = function(code) {
return function () {
uglify.parse(code);
}
}
var error = function (e) {
return e instanceof uglify.JS_Parse_Error &&
/^Parameter [a-zA-Z]+ was used already$/.test(e.message);
}
for (var i = 0; i < tests.length; i++) {
assert.throws(test(tests[i]), error, tests[i]);
}
});
});

View File

@@ -71,7 +71,7 @@ describe("Getters and setters", function() {
var fail = function(data) {
return function (e) {
return e instanceof UglifyJS.JS_Parse_Error &&
/^Unexpected token: /.test(e.message);
e.message === "Unexpected token: operator (" + data.operator + ")";
};
};

View File

@@ -26,12 +26,12 @@ describe("bin/uglifyjs with input file globs", function() {
});
});
it("bin/uglifyjs with multiple input file globs.", function(done) {
var command = uglifyjscmd + ' "test/input/issue-1242/???.es5" "test/input/issue-1242/*.js" -mc toplevel';
var command = uglifyjscmd + ' "test/input/issue-1242/???.es5" "test/input/issue-1242/*.js" -mc toplevel,passes=2';
exec(command, function(err, stdout) {
if (err) throw err;
assert.strictEqual(stdout, 'var print=console.log.bind(console);print("qux",9,6),print("Foo:",2*11);\n');
assert.strictEqual(stdout, 'var print=console.log.bind(console);print("qux",9,6),print("Foo:",22);\n');
done();
});
});

View File

@@ -1,265 +0,0 @@
var assert = require("assert");
var uglify = require("../node");
describe("Left-hand side expressions", function () {
it("Should parse destructuring with const/let/var correctly", function () {
var decls = uglify.parse('var {a,b} = foo, { c, d } = bar');
assert.equal(decls.body[0].TYPE, 'Var');
assert.equal(decls.body[0].definitions.length, 2);
// Item 1
assert.equal(decls.body[0].definitions[0].name.TYPE, 'Destructuring');
assert.equal(decls.body[0].definitions[0].value.TYPE, 'SymbolRef');
// Item 2
assert.equal(decls.body[0].definitions[1].name.TYPE, 'Destructuring');
assert.equal(decls.body[0].definitions[1].value.TYPE, 'SymbolRef');
var nested_def = uglify.parse('var [{x}] = foo').body[0].definitions[0];
assert.equal(nested_def.name.names[0].names[0].TYPE, 'ObjectKeyVal');
assert.equal(nested_def.name.names[0].names[0].value.TYPE, 'SymbolVar');
assert.equal(nested_def.name.names[0].names[0].key, 'x');
assert.equal(nested_def.name.names[0].names[0].value.name, 'x');
var holey_def = uglify.parse('const [,,third] = [1,2,3]').body[0].definitions[0];
assert.equal(holey_def.name.names[0].TYPE, 'Hole');
assert.equal(holey_def.name.names[1].TYPE, 'Hole');
assert.equal(holey_def.name.names[2].TYPE, 'SymbolConst');
var expanding_def = uglify.parse('var [first, ...rest] = [1,2,3]').body[0].definitions[0];
assert.equal(expanding_def.name.names[0].TYPE, 'SymbolVar');
assert.equal(expanding_def.name.names[1].TYPE, 'Expansion');
assert.equal(expanding_def.name.names[1].expression.TYPE, 'SymbolVar');
});
it("Parser should use AST_Array for array literals", function() {
var ast = uglify.parse('["foo", "bar"]');
assert(ast.body[0] instanceof uglify.AST_SimpleStatement);
assert(ast.body[0].body instanceof uglify.AST_Array);
ast = uglify.parse('a = ["foo"]');
assert(ast.body[0] instanceof uglify.AST_SimpleStatement);
assert(ast.body[0].body instanceof uglify.AST_Assign);
assert(ast.body[0].body.left instanceof uglify.AST_SymbolRef);
assert.equal(ast.body[0].body.operator, "=");
assert(ast.body[0].body.right instanceof uglify.AST_Array);
});
it("Parser should use AST_Object for object literals", function() {
var ast = uglify.parse('({foo: "bar"})');
assert(ast.body[0] instanceof uglify.AST_SimpleStatement);
assert(ast.body[0].body instanceof uglify.AST_Object);
// This example should be fine though
ast = uglify.parse('a = {foo: "bar"}');
assert(ast.body[0] instanceof uglify.AST_SimpleStatement);
assert(ast.body[0].body instanceof uglify.AST_Assign);
assert(ast.body[0].body.left instanceof uglify.AST_SymbolRef);
assert.equal(ast.body[0].body.operator, "=");
assert(ast.body[0].body.right instanceof uglify.AST_Object);
});
it("Parser should use AST_Destructuring for array assignment patterns", function() {
var ast = uglify.parse('[foo, bar] = [1, 2]');
assert(ast.body[0] instanceof uglify.AST_SimpleStatement);
assert(ast.body[0].body instanceof uglify.AST_Assign);
assert(ast.body[0].body.left instanceof uglify.AST_Destructuring);
assert.strictEqual(ast.body[0].body.left.is_array, true);
assert.equal(ast.body[0].body.operator, "=");
assert(ast.body[0].body.right instanceof uglify.AST_Array);
});
it("Parser should use AST_Destructuring for object assignment patterns", function() {
var ast = uglify.parse('({a: b, b: c} = {b: "c", c: "d"})');
assert(ast.body[0] instanceof uglify.AST_SimpleStatement);
assert(ast.body[0].body instanceof uglify.AST_Assign);
assert(ast.body[0].body.left instanceof uglify.AST_Destructuring);
assert.strictEqual(ast.body[0].body.left.is_array, false);
assert.equal(ast.body[0].body.operator, "=");
assert(ast.body[0].body.right instanceof uglify.AST_Object);
});
it("Parser should be able to handle nested destructuring", function() {
var ast = uglify.parse('[{a,b},[d, e, f, {g, h}]] = [{a: 1, b: 2}, [3, 4, 5, {g: 6, h: 7}]]');
assert(ast.body[0] instanceof uglify.AST_SimpleStatement);
assert(ast.body[0].body instanceof uglify.AST_Assign);
assert(ast.body[0].body.left instanceof uglify.AST_Destructuring);
assert.strictEqual(ast.body[0].body.left.is_array, true);
assert.equal(ast.body[0].body.operator, "=");
assert(ast.body[0].body.right instanceof uglify.AST_Array);
assert(ast.body[0].body.left.names[0] instanceof uglify.AST_Destructuring);
assert.strictEqual(ast.body[0].body.left.names[0].is_array, false);
assert(ast.body[0].body.left.names[1] instanceof uglify.AST_Destructuring);
assert.strictEqual(ast.body[0].body.left.names[1].is_array, true);
assert(ast.body[0].body.left.names[1].names[3] instanceof uglify.AST_Destructuring);
assert.strictEqual(ast.body[0].body.left.names[1].names[3].is_array, false);
});
it("Should handle spread operator in destructuring", function() {
var ast = uglify.parse("[a, b, ...c] = [1, 2, 3, 4, 5]");
assert(ast.body[0] instanceof uglify.AST_SimpleStatement);
assert(ast.body[0].body instanceof uglify.AST_Assign);
assert(ast.body[0].body.left instanceof uglify.AST_Destructuring);
assert.strictEqual(ast.body[0].body.left.is_array, true);
assert.equal(ast.body[0].body.operator, "=");
assert(ast.body[0].body.right instanceof uglify.AST_Array);
assert(ast.body[0].body.left.names[0] instanceof uglify.AST_SymbolRef);
assert(ast.body[0].body.left.names[1] instanceof uglify.AST_SymbolRef);
assert(ast.body[0].body.left.names[2] instanceof uglify.AST_Expansion);
});
it("Should handle default assignments in destructuring", function() {
var ast = uglify.parse("({x: v, z = z + 5} = obj);");
assert(ast.body[0] instanceof uglify.AST_SimpleStatement);
assert(ast.body[0].body instanceof uglify.AST_Assign);
assert(ast.body[0].body.left instanceof uglify.AST_Destructuring);
assert.strictEqual(ast.body[0].body.left.is_array, false);
assert.equal(ast.body[0].body.operator, "=");
assert(ast.body[0].body.right instanceof uglify.AST_SymbolRef);
assert(ast.body[0].body.left.names[0].value instanceof uglify.AST_SymbolRef);
assert.strictEqual(ast.body[0].body.left.names[0].start.value, "x");
assert(ast.body[0].body.left.names[1].value instanceof uglify.AST_DefaultAssign);
assert.strictEqual(ast.body[0].body.left.names[1].start.value, "z");
assert(ast.body[0].body.left.names[1].value.left instanceof uglify.AST_SymbolRef);
assert.strictEqual(ast.body[0].body.left.names[1].value.operator, "=");
assert(ast.body[0].body.left.names[1].value.right instanceof uglify.AST_Binary);
ast = uglify.parse("({x = 123} = obj);");
assert(ast.body[0] instanceof uglify.AST_SimpleStatement);
assert(ast.body[0].body instanceof uglify.AST_Assign);
assert(ast.body[0].body.left instanceof uglify.AST_Destructuring);
assert.strictEqual(ast.body[0].body.left.is_array, false);
assert.equal(ast.body[0].body.operator, "=");
assert(ast.body[0].body.right instanceof uglify.AST_SymbolRef);
assert(ast.body[0].body.left.names[0].value instanceof uglify.AST_DefaultAssign);
assert.strictEqual(ast.body[0].body.left.names[0].value.operator, "=");
assert(ast.body[0].body.left.names[0].value.left instanceof uglify.AST_SymbolRef);
ast = uglify.parse("[x, y = 5] = foo");
assert(ast.body[0] instanceof uglify.AST_SimpleStatement);
assert(ast.body[0].body instanceof uglify.AST_Assign);
assert(ast.body[0].body.left instanceof uglify.AST_Destructuring);
assert.strictEqual(ast.body[0].body.left.is_array, true);
assert.equal(ast.body[0].body.operator, "=");
assert(ast.body[0].body.right instanceof uglify.AST_SymbolRef);
assert(ast.body[0].body.left.names[0] instanceof uglify.AST_SymbolRef);
assert.strictEqual(ast.body[0].body.left.names[0].start.value, "x");
assert(ast.body[0].body.left.names[1] instanceof uglify.AST_DefaultAssign);
assert(ast.body[0].body.left.names[1].left instanceof uglify.AST_SymbolRef);
assert.strictEqual(ast.body[0].body.left.names[1].start.value, "y");
});
it("Should handle default assignments containing assignments in a destructuring", function() {
var ast = uglify.parse("[x, y = z = 2] = a;");
assert(ast.body[0] instanceof uglify.AST_SimpleStatement);
assert(ast.body[0].body instanceof uglify.AST_Assign);
assert(ast.body[0].body.left instanceof uglify.AST_Destructuring);
assert.strictEqual(ast.body[0].body.left.is_array, true);
assert.equal(ast.body[0].body.operator, "=");
assert(ast.body[0].body.right instanceof uglify.AST_SymbolRef);
assert(ast.body[0].body.left.names[0] instanceof uglify.AST_SymbolRef);
assert(ast.body[0].body.left.names[1] instanceof uglify.AST_DefaultAssign);
assert(ast.body[0].body.left.names[1].left instanceof uglify.AST_SymbolRef);
assert.equal(ast.body[0].body.left.names[1].operator, "=");
assert(ast.body[0].body.left.names[1].right instanceof uglify.AST_Assign);
assert(ast.body[0].body.left.names[1].right.left instanceof uglify.AST_SymbolRef);
assert.equal(ast.body[0].body.left.names[1].right.operator, "=");
assert(ast.body[0].body.left.names[1].right.right instanceof uglify.AST_Number);
ast = uglify.parse("({a: a = 123} = obj)");
assert(ast.body[0] instanceof uglify.AST_SimpleStatement);
assert(ast.body[0].body instanceof uglify.AST_Assign);
assert(ast.body[0].body.left instanceof uglify.AST_Destructuring);
assert.strictEqual(ast.body[0].body.left.is_array, false);
assert.equal(ast.body[0].body.operator, "=");
assert(ast.body[0].body.right instanceof uglify.AST_SymbolRef);
assert(ast.body[0].body.left.names[0] instanceof uglify.AST_ObjectProperty);
assert.strictEqual(ast.body[0].body.left.names[0].key, "a");
assert(ast.body[0].body.left.names[0].value instanceof uglify.AST_DefaultAssign);
assert(ast.body[0].body.left.names[0].value.left instanceof uglify.AST_SymbolRef);
assert.strictEqual(ast.body[0].body.left.names[0].value.operator, "=");
assert(ast.body[0].body.left.names[0].value.right instanceof uglify.AST_Number);
});
it("Should allow multiple spread in array literals", function() {
var ast = uglify.parse("var a = [1, 2, 3], b = [4, 5, 6], joined; joined = [...a, ...b]");
assert(ast.body[0] instanceof uglify.AST_Var);
assert(ast.body[1] instanceof uglify.AST_SimpleStatement);
// Check statement containing array with spreads
assert(ast.body[1].body instanceof uglify.AST_Assign);
assert(ast.body[1].body.left instanceof uglify.AST_SymbolRef);
assert.equal(ast.body[1].body.operator, "=");
assert(ast.body[1].body.right instanceof uglify.AST_Array);
// Check array content
assert.strictEqual(ast.body[1].body.right.elements.length, 2);
assert(ast.body[1].body.right.elements[0] instanceof uglify.AST_Expansion);
assert(ast.body[1].body.right.elements[0].expression instanceof uglify.AST_SymbolRef);
assert(ast.body[1].body.right.elements[0].expression.name, "a");
assert(ast.body[1].body.right.elements[1] instanceof uglify.AST_Expansion);
assert(ast.body[1].body.right.elements[1].expression instanceof uglify.AST_SymbolRef);
assert(ast.body[1].body.right.elements[1].expression.name, "b");
});
it("Should not allow spread on invalid locations", function() {
var expect = function(input, expected) {
var execute = function(input) {
return function() {
uglify.parse(input);
}
}
var check = function(e) {
return e instanceof uglify.JS_Parse_Error &&
e.message === expected;
}
assert.throws(execute(input), check);
}
// Spreads are not allowed in destructuring array if it's not the last element
expect("[...a, ...b] = [1, 2, 3, 4]", "Spread must the be last element in destructuring array");
// 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 (...)");
// 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 (...)");
});
});

View File

@@ -1,5 +1,5 @@
var assert = require("assert");
var uglify = require("../node");
var uglify = require("../../");
describe("New", function() {
it("Should add trailing parentheses for new expressions with zero arguments in beautify mode", function() {
@@ -83,11 +83,4 @@ describe("New", function() {
);
}
});
it("Should check target in new.target", function() {
assert.throws(function() {uglify.parse("new.blah")}, function(e) {
return e instanceof uglify.JS_Parse_Error
&& e.message === "Unexpected token name «blah», expected name «target»";
});
});
});

View File

@@ -1,131 +0,0 @@
var Uglify = require("../node");
var assert = require("assert");
describe("Object", function() {
it("Should allow objects to have a methodDefinition as property", function() {
var code = "var a = {test() {return true;}}";
assert.equal(Uglify.minify(code).code, "var a={test(){return!0}};");
});
it("Should not allow objects to use static keywords like in classes", function() {
var code = "{static test() {}}";
var parse = function() {
Uglify.parse(code);
}
var expect = function(e) {
return e instanceof Uglify.JS_Parse_Error;
}
assert.throws(parse, expect);
});
it("Should not allow objects to have static computed properties like in classes", function() {
var code = "var foo = {static [123](){}}";
var parse = function() {
console.log(Uglify.parse(code).body[0].body[0]);
}
var expect = function(e) {
return e instanceof Uglify.JS_Parse_Error;
}
assert.throws(parse, expect);
});
it("Should not accept operator tokens as property/getter/setter name", function() {
var illegalOperators = [
"++",
"--",
"+",
"-",
"!",
"~",
"&",
"|",
"^",
"*",
"/",
"%",
">>",
"<<",
">>>",
"<",
">",
"<=",
">=",
"==",
"===",
"!=",
"!==",
"?",
"=",
"+=",
"-=",
"/=",
"*=",
"%=",
">>=",
"<<=",
">>>=",
"|=",
"^=",
"&=",
"&&",
"||"
];
var generator = function() {
var results = [];
for (var i in illegalOperators) {
results.push({
code: "var obj = { get " + illegalOperators[i] + "() { return test; }};",
operator: illegalOperators[i],
method: "get"
});
results.push({
code: "var obj = { set " + illegalOperators[i] + "(value) { test = value}};",
operator: illegalOperators[i],
method: "set"
});
results.push({
code: "var obj = { " + illegalOperators[i] + ': "123"};',
operator: illegalOperators[i],
method: "key"
});
results.push({
code: "var obj = { " + illegalOperators[i] + "(){ return test; }};",
operator: illegalOperators[i],
method: "method"
});
}
return results;
};
var testCase = function(data) {
return function() {
Uglify.parse(data.code);
};
};
var fail = function(data) {
return function (e) {
return e instanceof Uglify.JS_Parse_Error && (
e.message === "Unexpected token: operator (" + data.operator + ")" ||
(e.message === "Unterminated regular expression" && data.operator[0] === "/") ||
(e.message === "Unexpected token: punc (()" && data.operator === "*")
);
};
};
var errorMessage = function(data) {
return "Expected but didn't get a syntax error while parsing following line:\n" + data.code;
};
var tests = generator();
for (var i = 0; i < tests.length; i++) {
var test = tests[i];
assert.throws(testCase(test), fail(test), errorMessage(test));
}
});
it("Should be able to use shorthand properties", function() {
var ast = Uglify.parse("var foo = 123\nvar obj = {foo: foo}");
assert.strictEqual(ast.print_to_string({ecma: 6}), "var foo=123;var obj={foo};");
})
});

View File

@@ -1,42 +0,0 @@
var assert = require("assert");
var uglify = require("../node");
describe("Template string", function() {
it("Should not accept invalid sequences", function() {
var tests = [
// Stress invalid expression
"var foo = `Hello ${]}`",
"var foo = `Test 123 ${>}`",
"var foo = `Blah ${;}`",
// Stress invalid template_substitution after expression
"var foo = `Blablabla ${123 456}`",
"var foo = `Blub ${123;}`",
"var foo = `Bleh ${a b}`"
];
var exec = function(test) {
return function() {
uglify.parse(test);
}
};
var fail = function(e) {
return e instanceof uglify.JS_Parse_Error
&& /^Unexpected token: /.test(e.message);
};
for (var i = 0; i < tests.length; i++) {
assert.throws(exec(tests[i]), fail, tests[i]);
}
});
it("Should process all line terminators as LF", function() {
[
"`a\rb`",
"`a\nb`",
"`a\r\nb`",
].forEach(function(code) {
assert.strictEqual(uglify.parse(code).print_to_string(), "`a\\nb`;");
});
});
});

View File

@@ -1,22 +0,0 @@
var assert = require("assert");
var uglify = require("../node");
describe("Try", function() {
it("Should not allow catch with an empty parameter", function() {
var tests = [
"try {} catch() {}"
];
var test = function(code) {
return function () {
uglify.parse(code);
}
}
var error = function (e) {
return e instanceof uglify.JS_Parse_Error;
}
for (var i = 0; i < tests.length; i++) {
assert.throws(test(tests[i]), error, tests[i]);
}
});
});

View File

@@ -1,145 +0,0 @@
var assert = require("assert");
var uglify = require("../node");
describe("Unicode", function() {
it("Should not accept invalid code ranges in unicode escape", function() {
var tests = [
"\\u{110000}", // A bit over the unicode range
"\\u{100000061} = 'foo'", // 32-bit overflow resulting in "a"
"\\u{fffffffffff}", // A bit too much over the unicode range
];
var exec = function(test) {
return function() {
uglify.parse(test);
}
}
var fail = function(e) {
return e instanceof uglify.JS_Parse_Error
&& e.message === "Unicode reference out of bounce";
}
for (var i = 0; i < tests.length; i++) {
assert.throws(exec(tests[i]), fail);
}
});
it("Should not accept invalid unicode sequences", function() {
var tests = [
"var foo = '\\u-111'",
"var bar = '\\u{-1}'",
"var baz = '\\ugggg'"
];
var exec = function(test) {
return function() {
uglify.parse(test);
}
}
var fail = function(e) {
return e instanceof uglify.JS_Parse_Error
&& e.message === "Invalid hex-character pattern in string";
}
for (var i = 0; i < tests.length; i++) {
assert.throws(exec(tests[i]), fail);
}
});
it("Should throw error if escaped first identifier char is not part of ID_start", function() {
var tests = [
'var \\u{0} = "foo";',
'var \\u{10ffff} = "bar";',
'var \\u000a = "what\'s up";',
// Valid ID_Start, but using up 2 escaped characters and not fitting in IdentifierStart
'var \\ud800\\udc00 = "Hello";',
'var \\udbff\\udfff = "Unicode";', // Same as previous test
'var \\ud800\udc01 = "Weird unicode";', // Same as above, but mixed escaped with unicode chars
];
var exec = function(test) {
return function() {
uglify.parse(test);
}
}
var fail = function(e) {
return e instanceof uglify.JS_Parse_Error
&& e.message === "First identifier char is an invalid identifier char";
}
for (var i = 0; i < tests.length; i++) {
assert.throws(exec(tests[i]), fail);
}
});
it("Should throw error if escaped non-first identifier char is not part of ID_start", function() {
var tests = [
'var a\\u{0} = "foo";',
'var a\\u{10ffff} = "bar";',
'var z\\u000a = "what\'s up";'
];
var exec = function(test) {
return function() {
uglify.parse(test);
}
}
var fail = function(e) {
return e instanceof uglify.JS_Parse_Error
&& e.message === "Invalid escaped identifier char";
}
for (var i = 0; i < tests.length; i++) {
assert.throws(exec(tests[i]), fail);
}
});
it("Should throw error if identifier is a keyword with a escape sequences", function() {
var tests = [
'var \\u0069\\u006e = "foo"', // in
'var \\u0076\\u0061\\u0072 = "bar"', // var
'var \\u{66}\\u{6f}\\u{72} = "baz"', // for
'var \\u0069\\u{66} = "foobar"', // if
'var \\u{73}uper' // super
];
var exec = function(test) {
return function() {
uglify.parse(test);
}
}
var fail = function(e) {
return e instanceof uglify.JS_Parse_Error
&& e.message === "Escaped characters are not allowed in keywords";
}
for (var i = 0; i < tests.length; i++) {
assert.throws(exec(tests[i]), fail);
}
});
it("Should read strings containing surigates correctly", function() {
var tests = [
['var a = "\ud800\udc00";', 'var a="\\u{10000}";'],
['var b = "\udbff\udfff";', 'var b="\\u{10ffff}";']
];
for (var i = 0; i < tests.length; i++) {
assert.strictEqual(uglify.minify(tests[i][0], {
output: { ascii_only: true, ecma: 6 }
}).code, tests[i][1]);
}
});
it("Should parse raw characters correctly", function() {
var ast = uglify.parse('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");');
});
});

View File

@@ -1,105 +0,0 @@
var UglifyJS = require("../node");
var assert = require("assert");
describe("Yield", function() {
it("Should not delete statements after yield", function() {
var js = 'function *foo(bar) { yield 1; yield 2; return 3; }';
var result = UglifyJS.minify(js);
assert.strictEqual(result.code, 'function*foo(e){return yield 1,yield 2,3}');
});
it("Should not allow yield as labelIdentifier within generators", function() {
var js = "function* g() {yield: 1}"
var test = function() {
UglifyJS.parse(js);
}
var expect = function(e) {
return e instanceof UglifyJS.JS_Parse_Error &&
e.message === "Yield cannot be used as label inside generators";
}
assert.throws(test, expect);
});
it("Should not allow yield* followed by a semicolon in generators", function() {
var js = "function* test() {yield*\n;}";
var test = function() {
UglifyJS.parse(js);
}
var expect = function(e) {
return e instanceof UglifyJS.JS_Parse_Error &&
e.message === "Unexpected token: punc (;)";
}
assert.throws(test, expect);
});
it("Should not allow yield with next token star on next line", function() {
var js = "function* test() {yield\n*123;}";
var test = function() {
UglifyJS.parse(js);
}
var expect = function(e) {
return e instanceof UglifyJS.JS_Parse_Error &&
e.message === "Unexpected token: operator (*)";
}
assert.throws(test, expect);
});
it("Should be able to compress its expression", function() {
assert.strictEqual(
UglifyJS.minify("function *f() { yield 3-4; }", {compress: true}).code,
"function*f(){yield-1}"
);
});
it("Should keep undefined after yield without compression if found in ast", function() {
assert.strictEqual(
UglifyJS.minify("function *f() { yield undefined; yield; yield* undefined; yield void 0}", {compress: false}).code,
"function*f(){yield undefined;yield;yield*undefined;yield void 0}"
);
});
it("Should be able to drop undefined after yield if necessary with compression", function() {
assert.strictEqual(
UglifyJS.minify("function *f() { yield undefined; yield; yield* undefined; yield void 0}", {compress: true}).code,
"function*f(){yield,yield,yield*void 0,yield}"
);
});
it("Should not allow yield to be used as symbol, identifier or shorthand property outside generators in strict mode", function() {
var tests = [
// Fail in as_symbol
'"use strict"; import yield from "bar";',
'"use strict"; yield = 123;',
'"use strict"; yield: "123";',
'"use strict"; for(;;){break yield;}',
'"use strict"; for(;;){continue yield;}',
'"use strict"; function yield(){}',
'"use strict"; function foo(...yield){}',
'"use strict"; try { new Error("")} catch (yield) {}',
'"use strict"; var yield = "foo";',
'"use strict"; class yield {}',
// Fail in maybe_assign
'"use strict"; var foo = yield;',
'"use strict"; var foo = bar = yield',
// Fail in as_property_name
'"use strict"; var foo = {yield};',
];
var fail = function(e) {
return e instanceof UglifyJS.JS_Parse_Error &&
/^Unexpected yield identifier (?:as parameter )?inside strict mode/.test(e.message);
}
var test = function(input) {
return function() {
UglifyJS.parse(input);
}
}
for (var i = 0; i < tests.length; i++) {
assert.throws(test(tests[i]), fail, tests[i]);
}
});
});