--- a/js/src/frontend/BinSource.cpp
+++ b/js/src/frontend/BinSource.cpp
@@ -85,16 +85,17 @@ private:
bool parseStatement(SimpleTokenReader* reader, UniquePtr<ParseNode>& out);
bool parseStatementList(SimpleTokenReader* reader, UniquePtr<ParseNode>& out);
bool parseStringList(SimpleTokenReader* reader, MutableHandle<Maybe<Names>> out);
bool parseStringList(SimpleTokenReader* reader, MutableHandle<Names> out);
bool parseStringSet(SimpleTokenReader* reader, MutableHandle<Maybe<NameBag>>);
bool parseStringSet(SimpleTokenReader* reader, MutableHandle<NameBag>);
bool parseScope(SimpleTokenReader* reader, ScopeData& out);
bool parseExpression(SimpleTokenReader* reader, UniquePtr<ParseNode>& out);
+ bool parsePropertyName(SimpleTokenReader* reader, UniquePtr<PropertyName>& out);
// --- Parse the contents of a node whose kind has already been determined.
bool parseBlockStatementAux(SimpleTokenReader* reader, const SimpleTokenReader::Fields* fields, UniquePtr<ParseNode>& out);
bool parseExpressionStatementAux(SimpleTokenReader* reader, const SimpleTokenReader::Fields* fields, UniquePtr<ParseNode>& out);
// --- Utilities.
bool readString(SimpleTokenReader* reader, MutableHandleString);
@@ -284,16 +285,18 @@ ASTReader::parseBlockStatementAux(Simple
BindingName binding(atom, isCaptured);
PodCopy(cursor, &binding, 1); // FIXME: Why does this work?
cursor++;
bindings->length++;
}
bindings->constStart = scope.letNames->length();
UniquePtr<ParseNode> result(new_<LexicalScopeNode>(bindings.release(), body.release()));
+ // FIXME: Handle case in which `new_` fails. This complicates `release()`.
+ // FIXME: Also for other nodes.
out = Move(result);
// FIXME: Validate capturedNames, etc.
return true;
}
bool
ASTReader::parseStringList(SimpleTokenReader* reader, MutableHandle<Maybe<Names>> out) {
if (out.get()) {
@@ -414,36 +417,67 @@ ASTReader::parseStatement(SimpleTokenRea
}
UniquePtr<ParseNode> result(new_<BinaryNode>(PNK_WITH, JSOP_NOP, TokenPos(),
expr.release(), body.release()));
if (!result) {
return false;
}
out = Move(result);
+
} else if (name == "ReturnStatement") {
UniquePtr<ParseNode> arg;
for (auto field: fields) {
if (field == "argument") {
if (!this->parseExpression(&sub, arg)) { // FIXME: Make sure that it works with no expression.
return false;
}
} else {
return this->raiseError();
}
}
+
+ // `arg` is optional, so we don't check whether it's `nullptr`.
UniquePtr<ParseNode> result(new_<UnaryNode>(PNK_RETURN, JSOP_RETURN, TokenPos(), arg.release()));
if (!result) {
return false;
}
out = Move(result);
} else if (name == "LabeledStatement") {
- // FIXME: Implement
+
+ UniquePtr<PropertyName> label;
+ UniquePtr<ParseNode> body;
+
+ for (auto field: fields) {
+ if (field == "label") {
+ if (!this->parsePropertyName(&sub, label)) {
+ return false;
+ }
+ } else if (field == "body") {
+ if (!this->parseStatement(&sub, body)) {
+ return false;
+ }
+ } else {
+ return this->raiseError();
+ }
+ }
+
+ if (!label || !body) {
+ return false;
+ }
+
+ UniquePtr<ParseNode> result(new_<LabeledStatement>(label.release(), body.release(), 0));
+ if (!result) {
+ return false;
+ }
+
+ out = Move(result);
+
} else if (name == "BreakStatement") {
// FIXME: Implement
} else if (name == "ContinueStatement") {
// FIXME: Implement
} else if (name == "IfStatement") {
// FIXME: Implement
} else if (name == "SwitchStatement") {
// FIXME: Implement