=> with destructuring arguments. Requires a lot of parser changes
This commit is contained in:
@@ -387,6 +387,11 @@ var AST_ArrowParametersOrSeq = DEFNODE("ArrowParametersOrSeq", "expressions", {
|
||||
start: ex.start,
|
||||
end: ex.end
|
||||
});
|
||||
} else if (ex instanceof AST_Destructuring) {
|
||||
if (ex.names.length == 0)
|
||||
croak("Invalid destructuring function parameter", ex.start.line, ex.start.col);
|
||||
ex.names = ex.names.map(to_fun_args);
|
||||
return ex;
|
||||
} else if (ex instanceof AST_SymbolRef) {
|
||||
return new AST_SymbolFunarg({
|
||||
name: ex.name,
|
||||
|
||||
110
lib/parse.js
110
lib/parse.js
@@ -989,35 +989,17 @@ function parse($TEXT, options) {
|
||||
var arrow_function = function(args) {
|
||||
expect_token("arrow", "=>");
|
||||
|
||||
if (args instanceof AST_SymbolRef) {
|
||||
args = [args];
|
||||
} else if (args instanceof AST_Seq) {
|
||||
args = args.to_array();
|
||||
} else if (args instanceof AST_Node) {
|
||||
croak("Invalid syntax", args.start.line, args.start.col);
|
||||
}
|
||||
var argnames = args.as_params(croak);
|
||||
|
||||
for (var i = 0; i < args.length; i++) {
|
||||
if (!(args[i] instanceof AST_SymbolRef)) {
|
||||
croak("Invalid parameter for an arrow function", args[i].start.line, args[i].start.col);
|
||||
}
|
||||
|
||||
args[i] = new AST_SymbolFunarg({
|
||||
name: args[i].name,
|
||||
start: args[i].start,
|
||||
end: args[i].end
|
||||
})
|
||||
}
|
||||
var body = is("punc", "{") ?
|
||||
_function_body(true) :
|
||||
_function_body(false);
|
||||
|
||||
return new AST_Arrow({
|
||||
argnames: args,
|
||||
body: (function(){
|
||||
if (is("punc", "{")) {
|
||||
return _function_body();
|
||||
} else {
|
||||
return expression(true);
|
||||
}
|
||||
})()
|
||||
start : args.start,
|
||||
end : body.end,
|
||||
argnames : argnames,
|
||||
body : body
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1030,7 +1012,7 @@ function parse($TEXT, options) {
|
||||
unexpected();
|
||||
|
||||
var args = params_or_seq_().as_params(croak);
|
||||
var body = _function_body();
|
||||
var body = _function_body(true);
|
||||
return new ctor({
|
||||
start : args.start,
|
||||
end : body.end,
|
||||
@@ -1060,14 +1042,18 @@ function parse($TEXT, options) {
|
||||
});
|
||||
}
|
||||
|
||||
function _function_body() {
|
||||
function _function_body(block) {
|
||||
var loop = S.in_loop;
|
||||
var labels = S.labels;
|
||||
++S.in_function;
|
||||
if (block)
|
||||
S.in_directives = true;
|
||||
S.in_loop = 0;
|
||||
S.labels = [];
|
||||
if (block)
|
||||
var a = block_();
|
||||
else
|
||||
var a = expression(false);
|
||||
--S.in_function;
|
||||
S.in_loop = loop;
|
||||
S.labels = labels;
|
||||
@@ -1263,16 +1249,17 @@ function parse($TEXT, options) {
|
||||
if (is("punc")) {
|
||||
switch (start.value) {
|
||||
case "(":
|
||||
next();
|
||||
var ex = expression(true);
|
||||
var ex = params_or_seq_();
|
||||
ex.start = start;
|
||||
ex.end = S.token;
|
||||
expect(")");
|
||||
return subscripts(ex, allow_calls);
|
||||
if (is("arrow", "=>")) {
|
||||
return arrow_function(ex);
|
||||
}
|
||||
return subscripts(ex.as_expr(croak), allow_calls);
|
||||
case "[":
|
||||
return subscripts(array_(), allow_calls);
|
||||
case "{":
|
||||
return subscripts(object_(), allow_calls);
|
||||
return subscripts(object_or_object_destructuring_(), allow_calls);
|
||||
}
|
||||
unexpected();
|
||||
}
|
||||
@@ -1311,9 +1298,10 @@ function parse($TEXT, options) {
|
||||
});
|
||||
});
|
||||
|
||||
var object_ = embed_tokens(function() {
|
||||
var object_or_object_destructuring_ = embed_tokens(function() {
|
||||
var start = S.token;
|
||||
expect("{");
|
||||
function try_an_object() {
|
||||
var first = true, a = [];
|
||||
while (!is("punc", "}")) {
|
||||
if (first) first = false; else expect(",");
|
||||
@@ -1372,7 +1360,39 @@ function parse($TEXT, options) {
|
||||
}
|
||||
}
|
||||
next();
|
||||
return new AST_Object({ properties: a });
|
||||
return new AST_Object({ properties: a })
|
||||
}
|
||||
|
||||
var obj = try_an_object();
|
||||
if (obj instanceof AST_Object) { return obj; }
|
||||
|
||||
if (!S.in_parameters) {
|
||||
croak("Cannot destructure", S.token.line, S.token.col);
|
||||
}
|
||||
|
||||
var firstName = obj;
|
||||
|
||||
var namesInDestructuring = [];
|
||||
|
||||
namesInDestructuring.push( new AST_SymbolRef({
|
||||
start : prev(),
|
||||
end : prev(),
|
||||
name : firstName
|
||||
}));
|
||||
|
||||
while (!is("punc", "}")) {
|
||||
expect(",");
|
||||
namesInDestructuring.push(as_symbol(AST_SymbolRef))
|
||||
}
|
||||
|
||||
expect('}');
|
||||
|
||||
return new AST_Destructuring({
|
||||
start : start,
|
||||
end : S.token,
|
||||
names : namesInDestructuring,
|
||||
is_array : false
|
||||
})
|
||||
});
|
||||
|
||||
function as_property_name() {
|
||||
@@ -1530,16 +1550,13 @@ function parse($TEXT, options) {
|
||||
return (expr instanceof AST_PropAccess || expr instanceof AST_Symbol);
|
||||
};
|
||||
|
||||
// In ES6, AssignmentExpression can also be an ArrowFunction
|
||||
var maybe_assign = function(no_in) {
|
||||
var start = S.token;
|
||||
|
||||
if (start.value == "(" && peek().value == ")") {
|
||||
next(); // (
|
||||
next(); // )
|
||||
return arrow_function([]);
|
||||
}
|
||||
var left = maybe_conditional(no_in);
|
||||
var val = S.token.value;
|
||||
|
||||
var left = maybe_conditional(no_in), val = S.token.value;
|
||||
if (is("operator") && ASSIGNMENT(val)) {
|
||||
if (is_assignable(left)) {
|
||||
next();
|
||||
@@ -1553,15 +1570,20 @@ function parse($TEXT, options) {
|
||||
}
|
||||
croak("Invalid assignment");
|
||||
}
|
||||
if (is("arrow")) {
|
||||
return arrow_function(left)
|
||||
}
|
||||
return left;
|
||||
};
|
||||
|
||||
var expression = function(commas, no_in) {
|
||||
var start = S.token;
|
||||
var expr = maybe_assign(no_in);
|
||||
if (expr instanceof AST_SymbolRef && is("arrow", "=>")) {
|
||||
expr = new AST_ArrowParametersOrSeq({
|
||||
start: expr.start,
|
||||
end: expr.end,
|
||||
expressions: [expr]
|
||||
});
|
||||
return arrow_function(expr);
|
||||
}
|
||||
if (commas && is("punc", ",")) {
|
||||
next();
|
||||
return new AST_Seq({
|
||||
|
||||
@@ -35,3 +35,65 @@ regression_arrow_functions_and_hoist: {
|
||||
}
|
||||
expect_exact: "a=>b;"
|
||||
}
|
||||
|
||||
destructuring_arguments: {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,12 @@ module.exports = function () {
|
||||
ok.equal(destr_fun1.argnames.length, 1);
|
||||
ok.equal(destr_fun2.argnames.length, 1);
|
||||
|
||||
var destr_fun1 = UglifyJS.parse('({a, b}) => null').body[0].body;
|
||||
var destr_fun2 = UglifyJS.parse('([a, [b]]) => null').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];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user