summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--js/src/builtin/ReflectParse.cpp12
-rw-r--r--js/src/frontend/BytecodeEmitter.cpp12
-rw-r--r--js/src/frontend/FullParseHandler.h12
-rw-r--r--js/src/frontend/Parser.cpp42
-rw-r--r--js/src/frontend/SyntaxParseHandler.h1
5 files changed, 73 insertions, 6 deletions
diff --git a/js/src/builtin/ReflectParse.cpp b/js/src/builtin/ReflectParse.cpp
index 3495ede2f..8e8bb2417 100644
--- a/js/src/builtin/ReflectParse.cpp
+++ b/js/src/builtin/ReflectParse.cpp
@@ -3222,6 +3222,8 @@ ASTSerializer::property(ParseNode* pn, MutableHandleValue dst)
return expression(pn->pn_kid, &val) &&
builder.prototypeMutation(val, &pn->pn_pos, dst);
}
+ if (pn->isKind(PNK_SPREAD))
+ return expression(pn, dst);
PropKind kind;
switch (pn->getOp()) {
@@ -3342,6 +3344,16 @@ ASTSerializer::objectPattern(ParseNode* pn, MutableHandleValue dst)
return false;
for (ParseNode* propdef = pn->pn_head; propdef; propdef = propdef->pn_next) {
+ if (propdef->isKind(PNK_SPREAD)) {
+ RootedValue target(cx);
+ RootedValue spread(cx);
+ if (!pattern(propdef->pn_kid, &target))
+ return false;
+ if(!builder.spreadExpression(target, &propdef->pn_pos, &spread))
+ return false;
+ elts.infallibleAppend(spread);
+ continue;
+ }
LOCAL_ASSERT(propdef->isKind(PNK_MUTATEPROTO) != propdef->isOp(JSOP_INITPROP));
RootedValue key(cx);
diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp
index c2eae4344..f9a1f8675 100644
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -5815,6 +5815,11 @@ BytecodeEmitter::emitDestructuringOpsObject(ParseNode* pattern, DestructuringFla
return false;
for (ParseNode* member = pattern->pn_head; member; member = member->pn_next) {
+ if (member->isKind(PNK_SPREAD)) {
+ // FIXME: Implement
+ continue;
+ }
+
ParseNode* subpattern;
if (member->isKind(PNK_MUTATEPROTO))
subpattern = member->pn_kid;
@@ -9449,6 +9454,13 @@ BytecodeEmitter::emitPropertyList(ParseNode* pn, MutableHandlePlainObject objp,
continue;
}
+ if (propdef->isKind(PNK_SPREAD)) {
+ MOZ_ASSERT(type == ObjectLiteral);
+ objp.set(nullptr);
+ // FIXME: implement
+ continue;
+ }
+
bool extraPop = false;
if (type == ClassBody && propdef->as<ClassMethod>().isStatic()) {
extraPop = true;
diff --git a/js/src/frontend/FullParseHandler.h b/js/src/frontend/FullParseHandler.h
index d34cdf43d..2d7f57e1e 100644
--- a/js/src/frontend/FullParseHandler.h
+++ b/js/src/frontend/FullParseHandler.h
@@ -395,6 +395,18 @@ class FullParseHandler
return true;
}
+ MOZ_MUST_USE bool addSpreadProperty(ParseNode* literal, uint32_t begin, ParseNode* inner) {
+ MOZ_ASSERT(literal->isKind(PNK_OBJECT));
+ MOZ_ASSERT(literal->isArity(PN_LIST));
+
+ setListFlag(literal, PNX_NONCONST);
+ ParseNode* spread = newSpread(begin, inner);
+ if (!spread)
+ return false;
+ literal->append(spread);
+ return true;
+ }
+
MOZ_MUST_USE bool addObjectMethodDefinition(ParseNode* literal, ParseNode* key, ParseNode* fn,
JSOp op)
{
diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp
index 585eef59d..47e0f943d 100644
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -4367,9 +4367,20 @@ Parser<ParseHandler>::objectBindingPattern(DeclarationKind kind, YieldHandling y
break;
if (tt == TOK_TRIPLEDOT) {
- // TODO: rest-binding property
- error(JSMSG_UNEXPECTED_TOKEN, "property name", TokenKindToDesc(tt));
- return null();
+ // rest-binding property
+ tokenStream.consumeKnownToken(TOK_TRIPLEDOT);
+ uint32_t begin = pos().begin;
+
+ TokenKind tt;
+ if (!tokenStream.getToken(&tt))
+ return null();
+
+ Node inner = bindingIdentifierOrPattern(kind, yieldHandling, tt);
+ if (!inner)
+ return null();
+
+ if (!handler.addSpreadProperty(literal, begin, inner))
+ return null();
} else {
TokenPos namePos = tokenStream.nextToken().pos;
@@ -4439,6 +4450,10 @@ Parser<ParseHandler>::objectBindingPattern(DeclarationKind kind, YieldHandling y
return null();
if (!matched)
break;
+ if (tt == TOK_TRIPLEDOT) {
+ error(JSMSG_REST_WITH_COMMA);
+ return null();
+ }
}
MUST_MATCH_TOKEN_MOD_WITH_REPORT(TOK_RC, TokenStream::None,
@@ -9693,9 +9708,22 @@ Parser<ParseHandler>::objectLiteral(YieldHandling yieldHandling, PossibleError*
break;
if (tt == TOK_TRIPLEDOT) {
- // TODO: object spread
- error(JSMSG_UNEXPECTED_TOKEN, "property name", TokenKindToDesc(tt));
- return null();
+ // object spread
+ tokenStream.consumeKnownToken(TOK_TRIPLEDOT);
+ uint32_t begin = pos().begin;
+
+ TokenPos innerPos;
+ if (!tokenStream.peekTokenPos(&innerPos, TokenStream::Operand))
+ return null();
+
+ Node inner = assignExpr(InAllowed, yieldHandling, TripledotProhibited,
+ possibleError);
+ if (!inner)
+ return null();
+ if (possibleError)
+ checkDestructuringAssignmentTarget(inner, innerPos, possibleError);
+ if (!handler.addSpreadProperty(literal, begin, inner))
+ return null();
} else {
TokenPos namePos = tokenStream.nextToken().pos;
@@ -9860,6 +9888,8 @@ Parser<ParseHandler>::objectLiteral(YieldHandling yieldHandling, PossibleError*
return null();
if (!matched)
break;
+ if (tt == TOK_TRIPLEDOT && possibleError)
+ possibleError->setPendingDestructuringErrorAt(pos(), JSMSG_REST_WITH_COMMA);
}
MUST_MATCH_TOKEN_MOD_WITH_REPORT(TOK_RC, TokenStream::None,
diff --git a/js/src/frontend/SyntaxParseHandler.h b/js/src/frontend/SyntaxParseHandler.h
index 7de6a242e..a604b599f 100644
--- a/js/src/frontend/SyntaxParseHandler.h
+++ b/js/src/frontend/SyntaxParseHandler.h
@@ -298,6 +298,7 @@ class SyntaxParseHandler
MOZ_MUST_USE bool addPrototypeMutation(Node literal, uint32_t begin, Node expr) { return true; }
MOZ_MUST_USE bool addPropertyDefinition(Node literal, Node name, Node expr) { return true; }
MOZ_MUST_USE bool addShorthand(Node literal, Node name, Node expr) { return true; }
+ MOZ_MUST_USE bool addSpreadProperty(Node literal, uint32_t begin, Node inner) { return true; }
MOZ_MUST_USE bool addObjectMethodDefinition(Node literal, Node name, Node fn, JSOp op) { return true; }
MOZ_MUST_USE bool addClassMethodDefinition(Node literal, Node name, Node fn, JSOp op, bool isStatic) { return true; }
Node newYieldExpression(uint32_t begin, Node value, Node gen) { return NodeGeneric; }