--- a/js/src/frontend/BinSource.cpp
+++ b/js/src/frontend/BinSource.cpp
@@ -96,16 +96,17 @@ private:
bool parseExpression(SimpleTokenReader* reader, UniquePtr<ParseNode>& out);
bool parsePropertyName(SimpleTokenReader* reader, UniquePtr<PropertyName>& out);
bool parseSwitchCaseList(SimpleTokenReader* reader, UniquePtr<ParseNode>& out);
bool parseBlockStatement(SimpleTokenReader* reader, UniquePtr<ParseNode>&);
bool parseCatchClause(SimpleTokenReader* reader, UniquePtr<ParseNode>&);
// --- Parse the contents of a node whose kind has already been determined.
+ bool parsePatternAux(SimpleTokenReader* reader, const std::string& name, const SimpleTokenReader::Fields* fields, UniquePtr<ParseNode>& out);
bool parseBlockStatementAux(SimpleTokenReader* reader, const std::string& name, const SimpleTokenReader::Fields* fields, UniquePtr<ParseNode>& out);
bool parseExpressionStatementAux(SimpleTokenReader* reader, const std::string& name, const SimpleTokenReader::Fields* fields, UniquePtr<ParseNode>& out);
bool parseExpressionAux(SimpleTokenReader* reader, const std::string& name, const SimpleTokenReader::Fields* fields, UniquePtr<ParseNode>& out);
bool parseVariableDeclarationAux(SimpleTokenReader* reader, const std::string& name, const SimpleTokenReader::Fields* fields, UniquePtr<ParseNode>& out);
// --- Utilities.
bool readString(SimpleTokenReader* reader, MutableHandleString);
@@ -805,17 +806,85 @@ ASTReader::parseStatement(SimpleTokenRea
}
Unused << forHead.release();
Unused << body.release();
out = Move(result);
} else if (name == "ForInStatement") {
- // FIXME: Implement
+
+ UniquePtr<ParseNode> left;
+ UniquePtr<ParseNode> right;
+ UniquePtr<ParseNode> body;
+ ScopeData scope(this->cx); // Optional
+
+ for (auto field: fields) {
+ if (field == "left") {
+
+ // This can be either a VarDecl or a Pattern.
+ SimpleTokenReader::Fields subFields(this->cx);
+ SimpleTokenReader subSub(this->cx);
+ std::string subName;
+
+ if (!sub.taggedTuple(&subName, &subFields, &subSub)) {
+ return false;
+ }
+
+
+ if (subName == "VariableDeclaration") {
+ if (!this->parseVariableDeclarationAux(&subSub, subName, &subFields, left)) {
+ return false;
+ }
+ } else /* Parse as pattern */ {
+ if (!this->parsePatternAux(&subSub, subName, &subFields, left)) {
+ return false;
+ }
+ }
+
+ } else if (field == "right") {
+ if (!this->parseExpression(&sub, right)) {
+ return false;
+ }
+ } else if (field == "body") {
+ if (!this->parseExpression(&sub, body)) {
+ return false;
+ }
+ } else if (field == BINJS_SCOPE) {
+ if (!this->parseScope(&sub, scope)) {
+ return false;
+ }
+ } else {
+ return this->raiseError();
+ }
+ }
+
+ if (!left || !right || !body) {
+ return this->raiseError();
+ }
+
+ UniquePtr<ParseNode> forHead(new_<TernaryNode>(PNK_FORIN, JSOP_NOP, left.get(), nullptr, right.get(), TokenPos()));
+ if (!forHead) {
+ return false;
+ }
+
+ Unused << left.release();
+ Unused << right.release();
+
+ UniquePtr<ParseNode> result(new_<BinaryNode>(PNK_FOR, JSOP_ITER, TokenPos(),
+ forHead.get(), body.get()));
+ if (!result) {
+ return false;
+ }
+
+ Unused << forHead.release();
+ Unused << body.release();
+
+ out = Move(result);
+
} else if (name == "FunctionDeclaration") {
// FIXME: Implement
} else if (name == "VariableDeclaration") {
// FIXME: Implement
} else if (name == "SwitchStatement") {
// FIXME: Implement
} else {
return this->raiseError();