--- a/js/src/frontend/BinSource.cpp
+++ b/js/src/frontend/BinSource.cpp
@@ -98,17 +98,17 @@ public:
}
bool parse(char* start, char* stop, GlobalSharedContext* sc, UniquePtr<ParseNode>& out);
private:
bool raiseError();
// --- Parse full nodes.
- bool parseBool(SimpleTokenReader*, Maybe<bool>*);
+ bool parsePattern(SimpleTokenReader* reader, UniquePtr<ParseNode>& out);
bool parseProgram(SimpleTokenReader* reader, UniquePtr<ParseNode>& out);
bool parseStatement(SimpleTokenReader* reader, UniquePtr<ParseNode>& out);
bool parseStatementList(SimpleTokenReader* reader, UniquePtr<ParseNode>& out);
bool parseScope(SimpleTokenReader* reader, ScopeData& out);
bool parseExpression(SimpleTokenReader* reader, UniquePtr<ParseNode>& out);
bool parsePropertyName(SimpleTokenReader* reader, UniquePtr<PropertyName>& out);
bool parseBlockStatement(SimpleTokenReader* reader, UniquePtr<ParseNode>&);
bool parseCatchClause(SimpleTokenReader* reader, UniquePtr<ParseNode>&);
@@ -296,17 +296,17 @@ ASTReader::parseScope(SimpleTokenReader*
}
if (kind != BinKind::binjs_scope) {
return this->raiseError();
}
for (auto field: fields) {
switch (field) {
case BinField::has_direct_eval:
- if (!this->parseBool(reader, &out.hasDirectEval)) {
+ if (!this->readBool(reader, out.hasDirectEval)) {
return false;
}
break;
case BinField::let_decl_names:
if (!this->parseStringList(reader, &out.letNames)) {
return false;
}
break;
@@ -1275,26 +1275,16 @@ ASTReader::parseVariableDeclarationAux(S
result->setKind(kind);
result->setOp(op);
out = Move(result);
return true;
}
-bool
-ASTReader::parseBool(SimpleTokenReader* reader, Maybe<bool>* result) {
- if (result->isSome()) {
- // Already parsed.
- // FIXME: Can replace with an assert once we have
- // implemented headers and header validation.
- return this->raiseError();
- }
- return reader->readBool(result);
-}
bool
ASTReader::parseExpression(SimpleTokenReader* reader, UniquePtr<ParseNode>& out) {
if (out) {
return this->raiseError();
}
SimpleTokenReader::BinFields fields(this->cx);
@@ -1867,17 +1857,17 @@ ASTReader::parseExpression(SimpleTokenRe
}
break;
case BinField::property:
if (!this->parseExpression(&sub, property)) {
return false;
}
break;
case BinField::computed:
- if (!this->parseBool(&sub, &isComputed)) {
+ if (!this->readBool(&sub, isComputed)) {
return false;
}
break;
default:
return this->raiseError();
}
}
@@ -2008,16 +1998,91 @@ ASTReader::parseExpressionStatementAux(S
return this->raiseError();
}
out = Move(result);
return false;
}
bool
+ASTReader::parseVariableDeclarator(SimpleTokenReader* reader, UniquePtr<ParseNode>& out) {
+ if (out) {
+ return this->raiseError();
+ }
+
+ BinKind kind;
+ SimpleTokenReader::BinFields fields(this->cx);
+ SimpleTokenReader sub(this->cx);
+
+ if (!reader->taggedTuple(kind, fields, &sub)) {
+ return false;
+ }
+
+ if (kind != BinKind::variable_declarator) {
+ return this->raiseError();
+ }
+
+ UniquePtr<ParseNode> id;
+ UniquePtr<ParseNode> init; // Optional.
+ for (auto field: fields) {
+ switch (field) {
+ case BinField::id:
+ if (!this->parsePattern(&sub, id)) {
+ return false;
+ }
+ break;
+ case BinField::init:
+ if (!this->parseExpression(&sub, init)) {
+ return false;
+ }
+ break;
+ default:
+ return this->raiseError();
+ }
+ }
+
+ if (!id) {
+ return this->raiseError();
+ }
+
+ UniquePtr<ParseNode> result;
+
+ // FIXME: Documentation in ParseNode is clearly obsolete.
+ if (id->isKind(PNK_NAME)) {
+ // var foo [= bar]
+ RootedAtom atom(cx, id->pn_atom);
+ result = UniquePtr<ParseNode>(new_<NameNode>(PNK_NAME, JSOP_NOP, atom, TokenPos()));
+ if (!result) {
+ return false;
+ }
+
+ if (init) {
+ result->pn_expr = init.release();
+ }
+ } else {
+ // var pattern = bar
+ if (!init) {
+ // Here, `init` is required.
+ return this->raiseError();
+ }
+ result = UniquePtr<ParseNode>(new_<BinaryNode>(PNK_ASSIGN, JSOP_NOP, TokenPos(), nullptr, nullptr));
+ if (!result) {
+ return false;
+ }
+
+ result->pn_left = id.release();
+ result->pn_right = init.release();
+ }
+
+ out = Move(result);
+ return true;
+}
+
+
+bool
ASTReader::readNumber(SimpleTokenReader* reader, Maybe<double>& out) {
if (out) {
return this->raiseError();
}
return reader->readMaybeF64(&out);
}