support rest parameters (#4515)
This commit is contained in:
109
lib/parse.js
109
lib/parse.js
@@ -1039,11 +1039,18 @@ function parse($TEXT, options) {
|
||||
}
|
||||
|
||||
function to_funarg(node) {
|
||||
if (node instanceof AST_Array) return new AST_DestructuredArray({
|
||||
start: node.start,
|
||||
elements: node.elements.map(to_funarg),
|
||||
end: node.end,
|
||||
});
|
||||
if (node instanceof AST_Array) {
|
||||
var rest = null;
|
||||
if (node.elements[node.elements.length - 1] instanceof AST_Spread) {
|
||||
rest = to_funarg(node.elements.pop().expression);
|
||||
}
|
||||
return new AST_DestructuredArray({
|
||||
start: node.start,
|
||||
elements: node.elements.map(to_funarg),
|
||||
rest: rest,
|
||||
end: node.end,
|
||||
});
|
||||
}
|
||||
if (node instanceof AST_Assign) return new AST_DefaultValue({
|
||||
start: node.start,
|
||||
name: to_funarg(node.left),
|
||||
@@ -1056,28 +1063,37 @@ function parse($TEXT, options) {
|
||||
}
|
||||
if (node instanceof AST_DestructuredArray) {
|
||||
node.elements = node.elements.map(to_funarg);
|
||||
if (node.rest) node.rest = to_funarg(node.rest);
|
||||
return node;
|
||||
}
|
||||
if (node instanceof AST_DestructuredObject) {
|
||||
node.properties.forEach(function(prop) {
|
||||
prop.value = to_funarg(prop.value);
|
||||
});
|
||||
if (node.rest) node.rest = to_funarg(node.rest);
|
||||
return node;
|
||||
}
|
||||
if (node instanceof AST_Hole) return node;
|
||||
if (node instanceof AST_Object) return new AST_DestructuredObject({
|
||||
start: node.start,
|
||||
properties: node.properties.map(function(prop) {
|
||||
if (!(prop instanceof AST_ObjectKeyVal)) token_error(prop.start, "Invalid destructuring assignment");
|
||||
return new AST_DestructuredKeyVal({
|
||||
start: prop.start,
|
||||
key: prop.key,
|
||||
value: to_funarg(prop.value),
|
||||
end: prop.end,
|
||||
});
|
||||
}),
|
||||
end: node.end,
|
||||
});
|
||||
if (node instanceof AST_Object) {
|
||||
var rest = null;
|
||||
if (node.properties[node.properties.length - 1] instanceof AST_Spread) {
|
||||
rest = to_funarg(node.properties.pop().expression);
|
||||
}
|
||||
return new AST_DestructuredObject({
|
||||
start: node.start,
|
||||
properties: node.properties.map(function(prop) {
|
||||
if (!(prop instanceof AST_ObjectKeyVal)) token_error(prop.start, "Invalid destructuring assignment");
|
||||
return new AST_DestructuredKeyVal({
|
||||
start: prop.start,
|
||||
key: prop.key,
|
||||
value: to_funarg(prop.value),
|
||||
end: prop.end,
|
||||
});
|
||||
}),
|
||||
rest: rest,
|
||||
end: node.end,
|
||||
});
|
||||
}
|
||||
if (node instanceof AST_SymbolRef) return new AST_SymbolFunarg(node);
|
||||
token_error(node.start, "Invalid arrow parameter");
|
||||
}
|
||||
@@ -1116,6 +1132,7 @@ function parse($TEXT, options) {
|
||||
return new AST_Arrow({
|
||||
start: start,
|
||||
argnames: argnames,
|
||||
rest: exprs.rest || null,
|
||||
body: body,
|
||||
value: value,
|
||||
end: prev(),
|
||||
@@ -1155,6 +1172,7 @@ function parse($TEXT, options) {
|
||||
if (S.input.has_directive("use strict")) {
|
||||
if (name) strict_verify_symbol(name);
|
||||
argnames.forEach(strict_verify_symbol);
|
||||
if (argnames.rest) strict_verify_symbol(argnames.rest);
|
||||
}
|
||||
S.input.pop_directives_stack();
|
||||
--S.in_function;
|
||||
@@ -1164,6 +1182,7 @@ function parse($TEXT, options) {
|
||||
return new ctor({
|
||||
name: name,
|
||||
argnames: argnames,
|
||||
rest: argnames.rest || null,
|
||||
body: body
|
||||
});
|
||||
};
|
||||
@@ -1445,17 +1464,22 @@ function parse($TEXT, options) {
|
||||
if (allow_trailing_comma && is("punc", closing)) break;
|
||||
if (allow_empty && is("punc", ",")) {
|
||||
a.push(new AST_Hole({ start: S.token, end: S.token }));
|
||||
} else if (parser === maybe_assign && is("operator", "...")) {
|
||||
} else if (!is("operator", "...")) {
|
||||
a.push(parser());
|
||||
} else if (parser === maybe_assign) {
|
||||
a.push(new AST_Spread({
|
||||
start: S.token,
|
||||
expression: (next(), parser()),
|
||||
end: prev(),
|
||||
}));
|
||||
} else {
|
||||
a.push(parser());
|
||||
next();
|
||||
a.rest = parser();
|
||||
if (a.rest instanceof AST_DefaultValue) token_error(a.rest.start, "Invalid rest parameter");
|
||||
break;
|
||||
}
|
||||
}
|
||||
next();
|
||||
expect(closing);
|
||||
return a;
|
||||
}
|
||||
|
||||
@@ -1634,17 +1658,19 @@ function parse($TEXT, options) {
|
||||
var start = S.token;
|
||||
if (is("punc", "[")) {
|
||||
next();
|
||||
var elements = expr_list("]", !options.strict, true, function() {
|
||||
return maybe_default(type);
|
||||
});
|
||||
return new AST_DestructuredArray({
|
||||
start: start,
|
||||
elements: expr_list("]", !options.strict, true, function() {
|
||||
return maybe_default(type);
|
||||
}),
|
||||
elements: elements,
|
||||
rest: elements.rest || null,
|
||||
end: prev(),
|
||||
});
|
||||
}
|
||||
if (is("punc", "{")) {
|
||||
next();
|
||||
var first = true, a = [];
|
||||
var first = true, a = [], rest = null;
|
||||
while (!is("punc", "}")) {
|
||||
if (first) first = false; else expect(",");
|
||||
// allow trailing comma
|
||||
@@ -1661,6 +1687,11 @@ function parse($TEXT, options) {
|
||||
}));
|
||||
continue;
|
||||
}
|
||||
if (is("operator", "...")) {
|
||||
next();
|
||||
rest = maybe_destructured(type);
|
||||
break;
|
||||
}
|
||||
var name = as_symbol(type);
|
||||
if (is("operator", "=")) {
|
||||
next();
|
||||
@@ -1678,10 +1709,11 @@ function parse($TEXT, options) {
|
||||
end: prev(),
|
||||
}));
|
||||
}
|
||||
next();
|
||||
expect("}");
|
||||
return new AST_DestructuredObject({
|
||||
start: start,
|
||||
properties: a,
|
||||
rest: rest,
|
||||
end: prev(),
|
||||
});
|
||||
}
|
||||
@@ -1845,6 +1877,11 @@ function parse($TEXT, options) {
|
||||
|
||||
function to_destructured(node) {
|
||||
if (node instanceof AST_Array) {
|
||||
var rest = null;
|
||||
if (node.elements[node.elements.length - 1] instanceof AST_Spread) {
|
||||
rest = to_destructured(node.elements.pop().expression);
|
||||
if (!(rest instanceof AST_Destructured || is_assignable(rest))) return node;
|
||||
}
|
||||
var elements = node.elements.map(to_destructured);
|
||||
return all(elements, function(node) {
|
||||
return node instanceof AST_DefaultValue
|
||||
@@ -1854,6 +1891,7 @@ function parse($TEXT, options) {
|
||||
}) ? new AST_DestructuredArray({
|
||||
start: node.start,
|
||||
elements: elements,
|
||||
rest: rest,
|
||||
end: node.end,
|
||||
}) : node;
|
||||
}
|
||||
@@ -1867,6 +1905,11 @@ function parse($TEXT, options) {
|
||||
}) : node;
|
||||
}
|
||||
if (!(node instanceof AST_Object)) return node;
|
||||
var rest = null;
|
||||
if (node.properties[node.properties.length - 1] instanceof AST_Spread) {
|
||||
rest = to_destructured(node.properties.pop().expression);
|
||||
if (!(rest instanceof AST_Destructured || is_assignable(rest))) return node;
|
||||
}
|
||||
var props = [];
|
||||
for (var i = 0; i < node.properties.length; i++) {
|
||||
var prop = node.properties[i];
|
||||
@@ -1885,6 +1928,7 @@ function parse($TEXT, options) {
|
||||
return new AST_DestructuredObject({
|
||||
start: node.start,
|
||||
properties: props,
|
||||
rest: rest,
|
||||
end: node.end,
|
||||
});
|
||||
}
|
||||
@@ -1912,15 +1956,20 @@ function parse($TEXT, options) {
|
||||
var start = S.token;
|
||||
var exprs = [];
|
||||
while (true) {
|
||||
if (maybe_arrow && is("operator", "...")) {
|
||||
next();
|
||||
exprs.rest = maybe_destructured(AST_SymbolFunarg);
|
||||
break;
|
||||
}
|
||||
exprs.push(maybe_assign(no_in));
|
||||
if (!is("punc", ",")) break;
|
||||
next();
|
||||
if (maybe_arrow && is("punc", ")") && is_token(peek(), "punc", "=>")) break;
|
||||
}
|
||||
return exprs.length == 1 ? exprs[0] : new AST_Sequence({
|
||||
start : start,
|
||||
expressions : exprs,
|
||||
end : prev()
|
||||
return exprs.length == 1 && !exprs.rest ? exprs[0] : new AST_Sequence({
|
||||
start: start,
|
||||
expressions: exprs,
|
||||
end: prev(),
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user