aboutsummaryrefslogtreecommitdiff
path: root/lib/ast.js
diff options
context:
space:
mode:
authorAlex Lam S.L <alexlamsl@gmail.com>2020-12-05 21:19:31 +0000
committerGitHub <noreply@github.com>2020-12-06 05:19:31 +0800
commit1e4985ed9e0822118ad01313af09008af1e9f036 (patch)
treea30030887031071c32dce0a37841732fe8c66cf5 /lib/ast.js
parentd2d56e301ecd8f6af056ccd355f940e11c851bd5 (diff)
downloadtracifyjs-1e4985ed9e0822118ad01313af09008af1e9f036.tar.gz
tracifyjs-1e4985ed9e0822118ad01313af09008af1e9f036.zip
support spread syntax (#4328)
Diffstat (limited to 'lib/ast.js')
-rw-r--r--lib/ast.js32
1 files changed, 27 insertions, 5 deletions
diff --git a/lib/ast.js b/lib/ast.js
index 2a4631f7..792264ff 100644
--- a/lib/ast.js
+++ b/lib/ast.js
@@ -209,6 +209,8 @@ var AST_EmptyStatement = DEFNODE("EmptyStatement", null, {
function must_be_expression(node, prop) {
if (!(node[prop] instanceof AST_Node)) throw new Error(prop + " must be AST_Node");
+ if (node[prop] instanceof AST_Hole) throw new Error(prop + " cannot be AST_Hole");
+ if (node[prop] instanceof AST_Spread) throw new Error(prop + " cannot be AST_Spread");
if (node[prop] instanceof AST_Statement && !(node[prop] instanceof AST_Function)) {
throw new Error(prop + " cannot be AST_Statement");
}
@@ -817,9 +819,11 @@ var AST_VarDef = DEFNODE("VarDef", "name value", {
/* -----[ OTHER ]----- */
-function must_be_expressions(node, prop) {
+function must_be_expressions(node, prop, allow_spread, allow_hole) {
node[prop].forEach(function(node) {
if (!(node instanceof AST_Node)) throw new Error(prop + " must be AST_Node[]");
+ if (!allow_hole && node instanceof AST_Hole) throw new Error(prop + " cannot be AST_Hole");
+ if (!allow_spread && node instanceof AST_Spread) throw new Error(prop + " cannot be AST_Spread");
if (node instanceof AST_Statement && !(node instanceof AST_Function)) {
throw new Error(prop + " cannot contain AST_Statement");
}
@@ -843,7 +847,7 @@ var AST_Call = DEFNODE("Call", "expression args pure", {
},
_validate: function() {
must_be_expression(this, "expression");
- must_be_expressions(this, "args");
+ must_be_expressions(this, "args", true);
},
});
@@ -920,6 +924,22 @@ var AST_Sub = DEFNODE("Sub", null, {
},
}, AST_PropAccess);
+var AST_Spread = DEFNODE("Spread", "expression", {
+ $documentation: "Spread expression in array/object literals or function calls",
+ $propdoc: {
+ expression: "[AST_Node] expression to be expanded",
+ },
+ walk: function(visitor) {
+ var node = this;
+ visitor.visit(node, function() {
+ node.expression.walk(visitor);
+ });
+ },
+ _validate: function() {
+ must_be_expression(this, "expression");
+ },
+});
+
var AST_Unary = DEFNODE("Unary", "operator expression", {
$documentation: "Base class for unary expressions",
$propdoc: {
@@ -1020,7 +1040,7 @@ var AST_Array = DEFNODE("Array", "elements", {
});
},
_validate: function() {
- must_be_expressions(this, "elements");
+ must_be_expressions(this, "elements", true, true);
},
});
@@ -1098,7 +1118,7 @@ var AST_DestructuredObject = DEFNODE("DestructuredObject", "properties", {
var AST_Object = DEFNODE("Object", "properties", {
$documentation: "An object literal",
$propdoc: {
- properties: "[AST_ObjectProperty*] array of properties"
+ properties: "[(AST_ObjectProperty|AST_Spread)*] array of properties"
},
walk: function(visitor) {
var node = this;
@@ -1110,7 +1130,9 @@ var AST_Object = DEFNODE("Object", "properties", {
},
_validate: function() {
this.properties.forEach(function(node) {
- if (!(node instanceof AST_ObjectProperty)) throw new Error("properties must be AST_ObjectProperty[]");
+ if (!(node instanceof AST_ObjectProperty || node instanceof AST_Spread)) {
+ throw new Error("properties must contain AST_ObjectProperty and/or AST_Spread only");
+ }
});
},
});