Starting destructuring.
This commit is contained in:
committed by
Richard van Velzen
parent
252fc65558
commit
32f76f7ff8
90
lib/ast.js
90
lib/ast.js
@@ -359,13 +359,73 @@ var AST_Toplevel = DEFNODE("Toplevel", "globals", {
|
|||||||
}
|
}
|
||||||
}, AST_Scope);
|
}, AST_Scope);
|
||||||
|
|
||||||
|
var AST_ArrowParametersOrSeq = DEFNODE("ArrowParametersOrSeq", "expressions", {
|
||||||
|
$documentation: "A set of arrow function parameters or a sequence expression. This is used because when the parser sees a \"(\" it could be the start of a seq, or the start of a parameter list of an arrow function.",
|
||||||
|
$propdoc: {
|
||||||
|
expressions: "[AST_Expression|AST_Destructuring*] array of expressions or argument names or destructurings."
|
||||||
|
},
|
||||||
|
as_params: function (croak) {
|
||||||
|
// We don't want anything which doesn't belong in a destructuring
|
||||||
|
var root = this;
|
||||||
|
return this.expressions.map(function to_fun_args(ex) {
|
||||||
|
if (ex instanceof AST_Object) {
|
||||||
|
if (ex.properties.length == 0)
|
||||||
|
croak("Invalid destructuring function parameter", ex.start.line, ex.start.col);
|
||||||
|
return new AST_Destructuring({
|
||||||
|
start: ex.start,
|
||||||
|
end: ex.end,
|
||||||
|
is_array: false,
|
||||||
|
names: ex.properties.map(to_fun_args)
|
||||||
|
});
|
||||||
|
} else if (ex instanceof AST_ObjectSymbol) {
|
||||||
|
return new AST_SymbolFunarg({
|
||||||
|
name: ex.symbol.name,
|
||||||
|
start: ex.start,
|
||||||
|
end: ex.end
|
||||||
|
});
|
||||||
|
} else if (ex instanceof AST_SymbolRef) {
|
||||||
|
return new AST_SymbolFunarg({
|
||||||
|
name: ex.name,
|
||||||
|
start: ex.start,
|
||||||
|
end: ex.end
|
||||||
|
});
|
||||||
|
} else if (ex instanceof AST_Array) {
|
||||||
|
if (ex.elements.length === 0)
|
||||||
|
croak("Invalid destructuring function parameter", ex.start.line, ex.start.col);
|
||||||
|
return new AST_Destructuring({
|
||||||
|
start: ex.start,
|
||||||
|
end: ex.end,
|
||||||
|
is_array: true,
|
||||||
|
names: ex.elements.map(to_fun_args)
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.log(ex.__proto__.TYPE)
|
||||||
|
croak("Invalid function parameter", ex.start.line, ex.start.col);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
as_expr: function (croak) {
|
||||||
|
return AST_Seq.from_array(this.expressions);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
var AST_Lambda = DEFNODE("Lambda", "name argnames uses_arguments", {
|
var AST_Lambda = DEFNODE("Lambda", "name argnames uses_arguments", {
|
||||||
$documentation: "Base class for functions",
|
$documentation: "Base class for functions",
|
||||||
$propdoc: {
|
$propdoc: {
|
||||||
name: "[AST_SymbolDeclaration?] the name of this function",
|
name: "[AST_SymbolDeclaration?] the name of this function",
|
||||||
argnames: "[AST_SymbolFunarg*] array of function arguments",
|
argnames: "[AST_SymbolFunarg|AST_Destructuring*] array of function arguments or destructurings",
|
||||||
uses_arguments: "[boolean/S] tells whether this function accesses the arguments array"
|
uses_arguments: "[boolean/S] tells whether this function accesses the arguments array"
|
||||||
},
|
},
|
||||||
|
args_as_names: function () {
|
||||||
|
var out = [];
|
||||||
|
this.walk(new TreeWalker(function (parm) {
|
||||||
|
var that = this;
|
||||||
|
if (parm instanceof AST_SymbolFunarg) {
|
||||||
|
out.push(parm);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
return out;
|
||||||
|
},
|
||||||
_walk: function(visitor) {
|
_walk: function(visitor) {
|
||||||
return visitor._visit(this, function(){
|
return visitor._visit(this, function(){
|
||||||
if (this.name) this.name._walk(visitor);
|
if (this.name) this.name._walk(visitor);
|
||||||
@@ -385,10 +445,26 @@ var AST_Function = DEFNODE("Function", null, {
|
|||||||
$documentation: "A function expression"
|
$documentation: "A function expression"
|
||||||
}, AST_Lambda);
|
}, AST_Lambda);
|
||||||
|
|
||||||
|
var AST_Arrow = DEFNODE("Arrow", null, {
|
||||||
|
$documentation: "An ES6 Arrow function ((a) => b)"
|
||||||
|
}, AST_Lambda);
|
||||||
|
|
||||||
var AST_Defun = DEFNODE("Defun", null, {
|
var AST_Defun = DEFNODE("Defun", null, {
|
||||||
$documentation: "A function definition"
|
$documentation: "A function definition"
|
||||||
}, AST_Lambda);
|
}, 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",
|
||||||
|
_walk: function(visitor) {
|
||||||
|
return visitor._visit(this, function(){
|
||||||
|
this.names.forEach(function(name){
|
||||||
|
name._walk(visitor);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
/* -----[ JUMPS ]----- */
|
/* -----[ JUMPS ]----- */
|
||||||
|
|
||||||
var AST_Jump = DEFNODE("Jump", null, {
|
var AST_Jump = DEFNODE("Jump", null, {
|
||||||
@@ -774,6 +850,18 @@ var AST_ObjectKeyVal = DEFNODE("ObjectKeyVal", "quote", {
|
|||||||
}
|
}
|
||||||
}, AST_ObjectProperty);
|
}, AST_ObjectProperty);
|
||||||
|
|
||||||
|
var AST_ObjectSymbol = DEFNODE("ObjectSymbol", "symbol", {
|
||||||
|
$propdoc: {
|
||||||
|
symbol: "[AST_SymbolRef] what symbol it is"
|
||||||
|
},
|
||||||
|
$documentation: "A symbol in an object",
|
||||||
|
_walk: function (visitor) {
|
||||||
|
return visitor._visit(this, function(){
|
||||||
|
this.symbol._walk(visitor);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, AST_ObjectProperty);
|
||||||
|
|
||||||
var AST_ObjectSetter = DEFNODE("ObjectSetter", null, {
|
var AST_ObjectSetter = DEFNODE("ObjectSetter", null, {
|
||||||
$documentation: "An object setter property",
|
$documentation: "An object setter property",
|
||||||
}, AST_ObjectProperty);
|
}, AST_ObjectProperty);
|
||||||
|
|||||||
@@ -231,6 +231,7 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
function make_arguments_names_list(func) {
|
function make_arguments_names_list(func) {
|
||||||
return func.argnames.map(function(sym){
|
return func.argnames.map(function(sym){
|
||||||
|
// TODO not sure what to do here with destructuring
|
||||||
return make_node(AST_String, sym, { value: sym.name });
|
return make_node(AST_String, sym, { value: sym.name });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -1089,17 +1090,26 @@ merge(Compressor.prototype, {
|
|||||||
if (node instanceof AST_Lambda && !(node instanceof AST_Accessor)) {
|
if (node instanceof AST_Lambda && !(node instanceof AST_Accessor)) {
|
||||||
if (compressor.option("unsafe") && !compressor.option("keep_fargs")) {
|
if (compressor.option("unsafe") && !compressor.option("keep_fargs")) {
|
||||||
for (var a = node.argnames, i = a.length; --i >= 0;) {
|
for (var a = node.argnames, i = a.length; --i >= 0;) {
|
||||||
var sym = a[i];
|
if (a[i] instanceof AST_Destructuring) {
|
||||||
if (sym.unreferenced()) {
|
// Do not drop destructuring arguments.
|
||||||
a.pop();
|
// They constitute a type assertion, so dropping
|
||||||
compressor.warn("Dropping unused function argument {name} [{file}:{line},{col}]", {
|
// them would stop that TypeError which would happen
|
||||||
name : sym.name,
|
// if someone called it with an incorrectly formatted
|
||||||
file : sym.start.file,
|
// parameter.
|
||||||
line : sym.start.line,
|
break;
|
||||||
col : sym.start.col
|
} else {
|
||||||
});
|
var sym = a[i];
|
||||||
|
if (sym.unreferenced()) {
|
||||||
|
a.pop();
|
||||||
|
compressor.warn("Dropping unused function argument {name} [{file}:{line},{col}]", {
|
||||||
|
name : sym.name,
|
||||||
|
file : sym.start.file,
|
||||||
|
line : sym.start.line,
|
||||||
|
col : sym.start.col
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else break;
|
||||||
}
|
}
|
||||||
else break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1263,9 +1273,10 @@ merge(Compressor.prototype, {
|
|||||||
// collect only vars which don't show up in self's arguments list
|
// collect only vars which don't show up in self's arguments list
|
||||||
var defs = [];
|
var defs = [];
|
||||||
vars.each(function(def, name){
|
vars.each(function(def, name){
|
||||||
|
// TODO test this too
|
||||||
if (self instanceof AST_Lambda
|
if (self instanceof AST_Lambda
|
||||||
&& find_if(function(x){ return x.name == def.name.name },
|
&& find_if(function(x){ return x.name == def.name.name },
|
||||||
self.argnames)) {
|
self.args_as_names())) {
|
||||||
vars.del(name);
|
vars.del(name);
|
||||||
} else {
|
} else {
|
||||||
def = def.clone();
|
def = def.clone();
|
||||||
@@ -1785,6 +1796,7 @@ merge(Compressor.prototype, {
|
|||||||
if (ex !== ast) throw ex;
|
if (ex !== ast) throw ex;
|
||||||
};
|
};
|
||||||
if (!fun) return self;
|
if (!fun) return self;
|
||||||
|
// TODO does this work with destructuring? Test it.
|
||||||
var args = fun.argnames.map(function(arg, i){
|
var args = fun.argnames.map(function(arg, i){
|
||||||
return make_node(AST_String, self.args[i], {
|
return make_node(AST_String, self.args[i], {
|
||||||
value: arg.print_to_string()
|
value: arg.print_to_string()
|
||||||
|
|||||||
@@ -598,6 +598,17 @@ function OutputStream(options) {
|
|||||||
output.print_string(self.value, self.quote);
|
output.print_string(self.value, self.quote);
|
||||||
output.semicolon();
|
output.semicolon();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
DEFPRINT(AST_Destructuring, function (self, output) {
|
||||||
|
output.print(self.is_array ? "[" : "{");
|
||||||
|
var first = true;
|
||||||
|
self.names.forEach(function (name) {
|
||||||
|
if (first) first = false; else { output.comma(); output.space(); }
|
||||||
|
name.print(output);
|
||||||
|
})
|
||||||
|
output.print(self.is_array ? "]" : "}");
|
||||||
|
})
|
||||||
|
|
||||||
DEFPRINT(AST_Debugger, function(self, output){
|
DEFPRINT(AST_Debugger, function(self, output){
|
||||||
output.print("debugger");
|
output.print("debugger");
|
||||||
output.semicolon();
|
output.semicolon();
|
||||||
|
|||||||
102
lib/parse.js
102
lib/parse.js
@@ -644,6 +644,7 @@ function parse($TEXT, options) {
|
|||||||
prev : null,
|
prev : null,
|
||||||
peeked : null,
|
peeked : null,
|
||||||
in_function : 0,
|
in_function : 0,
|
||||||
|
in_parameters : false,
|
||||||
in_directives : true,
|
in_directives : true,
|
||||||
in_loop : 0,
|
in_loop : 0,
|
||||||
labels : []
|
labels : []
|
||||||
@@ -957,35 +958,58 @@ function parse($TEXT, options) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
var function_ = function(ctor) {
|
var function_ = function(ctor) {
|
||||||
|
var start = S.token
|
||||||
|
|
||||||
var in_statement = ctor === AST_Defun;
|
var in_statement = ctor === AST_Defun;
|
||||||
var name = is("name") ? as_symbol(in_statement ? AST_SymbolDefun : AST_SymbolLambda) : null;
|
var name = is("name") ? as_symbol(in_statement ? AST_SymbolDefun : AST_SymbolLambda) : null;
|
||||||
if (in_statement && !name)
|
if (in_statement && !name)
|
||||||
unexpected();
|
unexpected();
|
||||||
expect("(");
|
|
||||||
|
var args = params_or_seq_().as_params(croak);
|
||||||
|
var body = _function_body();
|
||||||
return new ctor({
|
return new ctor({
|
||||||
name: name,
|
start : args.start,
|
||||||
argnames: (function(first, a){
|
end : body.end,
|
||||||
while (!is("punc", ")")) {
|
name : name,
|
||||||
if (first) first = false; else expect(",");
|
argnames: args,
|
||||||
a.push(as_symbol(AST_SymbolFunarg));
|
body : body
|
||||||
}
|
|
||||||
next();
|
|
||||||
return a;
|
|
||||||
})(true, []),
|
|
||||||
body: (function(loop, labels){
|
|
||||||
++S.in_function;
|
|
||||||
S.in_directives = true;
|
|
||||||
S.in_loop = 0;
|
|
||||||
S.labels = [];
|
|
||||||
var a = block_();
|
|
||||||
--S.in_function;
|
|
||||||
S.in_loop = loop;
|
|
||||||
S.labels = labels;
|
|
||||||
return a;
|
|
||||||
})(S.in_loop, S.labels)
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function params_or_seq_() {
|
||||||
|
var start = S.token
|
||||||
|
expect("(");
|
||||||
|
var first = true;
|
||||||
|
var a = [];
|
||||||
|
S.in_parameters = true;
|
||||||
|
while (!is("punc", ")")) {
|
||||||
|
if (first) first = false; else expect(",");
|
||||||
|
a.push(expression(false));
|
||||||
|
}
|
||||||
|
S.in_parameters = false;
|
||||||
|
var end = S.token
|
||||||
|
next();
|
||||||
|
return new AST_ArrowParametersOrSeq({
|
||||||
|
start: start,
|
||||||
|
end: end,
|
||||||
|
expressions: a
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function _function_body() {
|
||||||
|
var loop = S.in_loop;
|
||||||
|
var labels = S.labels;
|
||||||
|
++S.in_function;
|
||||||
|
S.in_directives = true;
|
||||||
|
S.in_loop = 0;
|
||||||
|
S.labels = [];
|
||||||
|
var a = block_();
|
||||||
|
--S.in_function;
|
||||||
|
S.in_loop = loop;
|
||||||
|
S.labels = labels;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
function if_() {
|
function if_() {
|
||||||
var cond = parenthesised(), body = statement(), belse = null;
|
var cond = parenthesised(), body = statement(), belse = null;
|
||||||
if (is("keyword", "else")) {
|
if (is("keyword", "else")) {
|
||||||
@@ -1224,6 +1248,7 @@ function parse($TEXT, options) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
var object_ = embed_tokens(function() {
|
var object_ = embed_tokens(function() {
|
||||||
|
var start = S.token;
|
||||||
expect("{");
|
expect("{");
|
||||||
var first = true, a = [];
|
var first = true, a = [];
|
||||||
while (!is("punc", "}")) {
|
while (!is("punc", "}")) {
|
||||||
@@ -1254,14 +1279,33 @@ function parse($TEXT, options) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
expect(":");
|
|
||||||
a.push(new AST_ObjectKeyVal({
|
if (!is("punc", ":")) {
|
||||||
start : start,
|
// It's one of those object destructurings, the value is its own name
|
||||||
quote : start.quote,
|
if (!S.in_parameters) {
|
||||||
key : name,
|
croak("Invalid syntax", S.token.line, S.token.col);
|
||||||
value : expression(false),
|
}
|
||||||
end : prev()
|
a.push(new AST_ObjectSymbol({
|
||||||
}));
|
start: start,
|
||||||
|
end: start,
|
||||||
|
symbol: new AST_SymbolRef({
|
||||||
|
start: start,
|
||||||
|
end: start,
|
||||||
|
name: name
|
||||||
|
})
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
if (S.in_parameters) {
|
||||||
|
croak("Cannot destructure", S.token.line, S.token.col);
|
||||||
|
}
|
||||||
|
expect(":");
|
||||||
|
a.push(new AST_ObjectKeyVal({
|
||||||
|
start : start,
|
||||||
|
key : name,
|
||||||
|
value : expression(false),
|
||||||
|
end : prev()
|
||||||
|
}));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
next();
|
next();
|
||||||
return new AST_Object({ properties: a });
|
return new AST_Object({ properties: a });
|
||||||
|
|||||||
14
lib/scope.js
14
lib/scope.js
@@ -50,6 +50,7 @@ function SymbolDef(scope, index, orig) {
|
|||||||
this.references = [];
|
this.references = [];
|
||||||
this.global = false;
|
this.global = false;
|
||||||
this.mangled_name = null;
|
this.mangled_name = null;
|
||||||
|
this.object_destructuring_arg = false;
|
||||||
this.undeclared = false;
|
this.undeclared = false;
|
||||||
this.constant = false;
|
this.constant = false;
|
||||||
this.index = index;
|
this.index = index;
|
||||||
@@ -60,6 +61,7 @@ SymbolDef.prototype = {
|
|||||||
if (!options) options = {};
|
if (!options) options = {};
|
||||||
|
|
||||||
return (this.global && !options.toplevel)
|
return (this.global && !options.toplevel)
|
||||||
|
|| this.object_destructuring_arg
|
||||||
|| this.undeclared
|
|| this.undeclared
|
||||||
|| (!options.eval && (this.scope.uses_eval || this.scope.uses_with))
|
|| (!options.eval && (this.scope.uses_eval || this.scope.uses_with))
|
||||||
|| (options.keep_fnames
|
|| (options.keep_fnames
|
||||||
@@ -94,6 +96,7 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
|
|||||||
var scope = self.parent_scope = null;
|
var scope = self.parent_scope = null;
|
||||||
var defun = null;
|
var defun = null;
|
||||||
var nesting = 0;
|
var nesting = 0;
|
||||||
|
var object_destructuring_arg = false;
|
||||||
var tw = new TreeWalker(function(node, descend){
|
var tw = new TreeWalker(function(node, descend){
|
||||||
if (options.screw_ie8 && node instanceof AST_Catch) {
|
if (options.screw_ie8 && node instanceof AST_Catch) {
|
||||||
var save_scope = scope;
|
var save_scope = scope;
|
||||||
@@ -104,6 +107,12 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
|
|||||||
scope = save_scope;
|
scope = save_scope;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (node instanceof AST_Destructuring && node.is_array === false) {
|
||||||
|
object_destructuring_arg = true; // These don't nest
|
||||||
|
descend();
|
||||||
|
object_destructuring_arg = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
if (node instanceof AST_Scope) {
|
if (node instanceof AST_Scope) {
|
||||||
node.init_scope_vars(nesting);
|
node.init_scope_vars(nesting);
|
||||||
var save_scope = node.parent_scope = scope;
|
var save_scope = node.parent_scope = scope;
|
||||||
@@ -127,6 +136,10 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
|
|||||||
if (node instanceof AST_Symbol) {
|
if (node instanceof AST_Symbol) {
|
||||||
node.scope = scope;
|
node.scope = scope;
|
||||||
}
|
}
|
||||||
|
if (node instanceof AST_SymbolFunarg) {
|
||||||
|
node.object_destructuring_arg = object_destructuring_arg;
|
||||||
|
defun.def_variable(node);
|
||||||
|
}
|
||||||
if (node instanceof AST_SymbolLambda) {
|
if (node instanceof AST_SymbolLambda) {
|
||||||
defun.def_function(node);
|
defun.def_function(node);
|
||||||
}
|
}
|
||||||
@@ -250,6 +263,7 @@ AST_Scope.DEFMETHOD("def_variable", function(symbol){
|
|||||||
if (!this.variables.has(symbol.name)) {
|
if (!this.variables.has(symbol.name)) {
|
||||||
def = new SymbolDef(this, this.variables.size(), symbol);
|
def = new SymbolDef(this, this.variables.size(), symbol);
|
||||||
this.variables.set(symbol.name, def);
|
this.variables.set(symbol.name, def);
|
||||||
|
def.object_destructuring_arg = symbol.object_destructuring_arg;
|
||||||
def.global = !this.parent_scope;
|
def.global = !this.parent_scope;
|
||||||
} else {
|
} else {
|
||||||
def = this.variables.get(symbol.name);
|
def = this.variables.get(symbol.name);
|
||||||
|
|||||||
103
test/parser.js
Normal file
103
test/parser.js
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
|
||||||
|
var UglifyJS = require("..");
|
||||||
|
var ok = require('assert');
|
||||||
|
|
||||||
|
module.exports = function () {
|
||||||
|
console.log("--- Parser tests");
|
||||||
|
|
||||||
|
// Destructuring arguments
|
||||||
|
|
||||||
|
// 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 = UglifyJS.parse('(function ({a, b}) {})').body[0].body;
|
||||||
|
var destr_fun2 = UglifyJS.parse('(function ([a, [b]]) {})').body[0].body;
|
||||||
|
|
||||||
|
ok.equal(destr_fun1.argnames.length, 1);
|
||||||
|
ok.equal(destr_fun2.argnames.length, 1);
|
||||||
|
|
||||||
|
var destruct1 = destr_fun1.argnames[0];
|
||||||
|
var destruct2 = destr_fun2.argnames[0];
|
||||||
|
|
||||||
|
ok(destruct1 instanceof UglifyJS.AST_Destructuring);
|
||||||
|
ok(destruct2 instanceof UglifyJS.AST_Destructuring);
|
||||||
|
ok(destruct2.names[1] instanceof UglifyJS.AST_Destructuring);
|
||||||
|
|
||||||
|
ok.equal(destruct1.start.value, '{');
|
||||||
|
ok.equal(destruct1.end.value, '}');
|
||||||
|
ok.equal(destruct2.start.value, '[');
|
||||||
|
ok.equal(destruct2.end.value, ']');
|
||||||
|
|
||||||
|
ok.equal(destruct1.is_array, false);
|
||||||
|
ok.equal(destruct2.is_array, true);
|
||||||
|
|
||||||
|
var aAndB = [
|
||||||
|
['SymbolFunarg', 'a'],
|
||||||
|
['SymbolFunarg', 'b']
|
||||||
|
];
|
||||||
|
|
||||||
|
ok.deepEqual(
|
||||||
|
[
|
||||||
|
destruct1.names[0].TYPE,
|
||||||
|
destruct1.names[0].name],
|
||||||
|
aAndB[0]);
|
||||||
|
|
||||||
|
ok.deepEqual(
|
||||||
|
[
|
||||||
|
destruct2.names[1].names[0].TYPE,
|
||||||
|
destruct2.names[1].names[0].name
|
||||||
|
],
|
||||||
|
aAndB[1]);
|
||||||
|
|
||||||
|
ok.deepEqual(
|
||||||
|
get_args(destr_fun1.args_as_names()),
|
||||||
|
aAndB)
|
||||||
|
ok.deepEqual(
|
||||||
|
get_args(destr_fun2.args_as_names()),
|
||||||
|
aAndB)
|
||||||
|
|
||||||
|
// Making sure we don't accidentally accept things which
|
||||||
|
// Aren't argument destructurings
|
||||||
|
|
||||||
|
ok.throws(function () {
|
||||||
|
UglifyJS.parse('(function ([]) {})');
|
||||||
|
}, /Invalid destructuring function parameter/);
|
||||||
|
|
||||||
|
ok.throws(function () {
|
||||||
|
UglifyJS.parse('(function ( { a, [ b ] } ) { })')
|
||||||
|
});
|
||||||
|
|
||||||
|
ok.throws(function () {
|
||||||
|
UglifyJS.parse('(function (1) { })');
|
||||||
|
}, /Invalid function parameter/);
|
||||||
|
|
||||||
|
ok.throws(function () {
|
||||||
|
UglifyJS.parse('(function (this) { })');
|
||||||
|
});
|
||||||
|
|
||||||
|
ok.throws(function () {
|
||||||
|
UglifyJS.parse('(function ([1]) { })');
|
||||||
|
}, /Invalid function parameter/);
|
||||||
|
|
||||||
|
ok.throws(function () {
|
||||||
|
UglifyJS.parse('(function [a] { })');
|
||||||
|
});
|
||||||
|
|
||||||
|
ok.throws(function () {
|
||||||
|
// Note: this *is* a valid destructuring, but before we implement
|
||||||
|
// destructuring (right now it's only destructuring *arguments*),
|
||||||
|
// this won't do.
|
||||||
|
UglifyJS.parse('[{a}]');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run standalone
|
||||||
|
if (module.parent === null) {
|
||||||
|
module.exports();
|
||||||
|
}
|
||||||
|
|
||||||
@@ -23,6 +23,10 @@ run_ast_conversion_tests({
|
|||||||
iterations: 1000
|
iterations: 1000
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var run_parser_tests = require('./parser.js');
|
||||||
|
|
||||||
|
run_parser_tests();
|
||||||
|
|
||||||
/* -----[ utils ]----- */
|
/* -----[ utils ]----- */
|
||||||
|
|
||||||
function tmpl() {
|
function tmpl() {
|
||||||
|
|||||||
Reference in New Issue
Block a user