--- a/js/src/frontend/BinSource.cpp
+++ b/js/src/frontend/BinSource.cpp
@@ -1,17 +1,18 @@
#include <mozilla/ArrayUtils.h>
#include <mozilla/Casting.h>
#include <mozilla/Maybe.h>
#include <mozilla/Move.h>
#include <mozilla/PodOperations.h>
#include <mozilla/Vector.h>
+#include <frontend/Parser.h>
+#include <frontend/ParseNode.h>
#include <frontend/BinTokenReader.h>
-#include <frontend/ParseNode.h>
using namespace mozilla;
using NameBag = GCHashSet<JSString*>;
using Names = GCVector<JSString*, 8>;
namespace js {
namespace frontend {
@@ -37,35 +38,38 @@ const std::string BINJS_VAR_NAME = "BINJ
const std::string BINJS_LET_NAME = "BINJS:LetDeclaredNames";
const std::string BINJS_CONST_NAME = "BINJS:ConstDeclaredNames";
const std::string BINJS_CAPTURED_NAME = "BINJS:CapturedNames";
const std::string BINJS_DIRECT_EVAL = "BINJS:HasDirectEval";
class ASTReader
{
public:
- bool parse(char* start, char* stop, UniquePtr<ParseNode>& out);
+ bool parse(char* start, char* stop, GlobalSharedContext* sc, UniquePtr<ParseNode>& out);
private:
bool raiseError();
// --- Parse full nodes.
- bool parseBool(SimpleTokenReader*, Maybe<bool>*);
- bool parseProgram(SimpleTokenReader* reader, UniquePtr<ParseNode>& out);
- bool parseStatement(SimpleTokenReader* reader, UniquePtr<ParseNode>& out);
- bool parseStatementList(SimpleTokenReader* reader, UniquePtr<ParseNode>& out);
- bool parseStringList(SimpleTokenReader* reader, MutableHandle<Maybe<Names>> out);
- bool parseStringSet(SimpleTokenReader* reader, MutableHandle<Maybe<NameBag>>);
+ bool parseBool(SimpleTokenReader*, ParseContext* pc, Maybe<bool>*);
+ bool parseProgram(SimpleTokenReader* reader, ParseContext* pc, UniquePtr<ParseNode>& out);
+ bool parseStatement(SimpleTokenReader* reader, ParseContext* pc, UniquePtr<ParseNode>& out);
+ bool parseStatementList(SimpleTokenReader* reader, ParseContext* pc, UniquePtr<ParseNode>& out);
+ bool parseStringList(SimpleTokenReader* reader, ParseContext* pc, MutableHandle<Maybe<Names>> out);
+ bool parseStringSet(SimpleTokenReader* reader, ParseContext* pc, MutableHandle<Maybe<NameBag>>);
// --- 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);
+
+ bool parseBlockStatementAux(SimpleTokenReader* reader, ParseContext* pc, const SimpleTokenReader::Fields* fields, UniquePtr<ParseNode>& out);
+ bool parseExpressionStatementAux(SimpleTokenReader* reader, ParseContext* pc, const SimpleTokenReader::Fields* fields, UniquePtr<ParseNode>& out);
// --- Utilities.
- bool readString(SimpleTokenReader* reader, MutableHandleString);
+ bool readString(SimpleTokenReader* reader, ParseContext* pc, MutableHandleString);
+
+ const ReadOnlyCompileOptions& options() const;
ParseNodeAllocator allocator;
ParseNode* allocParseNode(size_t size) {
MOZ_ASSERT(size == sizeof(ParseNode));
return static_cast<ParseNode*>(allocator.allocNode());
}
@@ -79,30 +83,37 @@ private:
JS_DECLARE_NEW_METHODS(new_, allocParseNode, inline)
private:
JSContext* cx;
LifoAlloc& alloc;
};
+
bool
-ASTReader::parse(char* start, char* stop, UniquePtr<ParseNode>& out) {
+ASTReader::parse(char* start, char* stop, GlobalSharedContext* sc, UniquePtr<ParseNode>& out) {
SimpleTokenReader reader(this->cx);
reader.init(start, stop, nullptr);
+ Directives directives(options().strictOption);
+ GlobalSharedContext globalsc(this->cx, ScopeKind::Global,
+ directives, options().extraWarningsOption);
+ ParseContext globalpc(this, &globalsc, /* newDirectives = */ nullptr);
+
+
if (!this->parseProgram(&reader, out) || !reader.uninit()) {
return false;
}
return true;
}
bool
-ASTReader::parseProgram(SimpleTokenReader* reader, UniquePtr<ParseNode>& out) {
+ASTReader::parseProgram(SimpleTokenReader* reader, ParseContext* pc, UniquePtr<ParseNode>& out) {
if (out) {
// Already parsed.
return this->raiseError();
}
SimpleTokenReader::Fields fields(this->cx);
SimpleTokenReader sub(this->cx);
std::string name;
@@ -113,26 +124,28 @@ ASTReader::parseProgram(SimpleTokenReade
if (name != "Program") {
return false;
}
return this->parseBlockStatementAux(&sub, &fields, out);
}
bool
-ASTReader::parseBlockStatementAux(SimpleTokenReader* reader, const SimpleTokenReader::Fields* fields, UniquePtr<ParseNode>& out) {
+ASTReader::parseBlockStatementAux(SimpleTokenReader* reader,
+ ParseContext* pc,
+ const SimpleTokenReader::Fields* fields,
+ UniquePtr<ParseNode>& out)
+{
UniquePtr<ParseNode> body;
Maybe<bool> hasDirectEval;
Rooted<Maybe<Names>> letNames(this->cx);
Rooted<Maybe<Names>> constNames(this->cx);
Rooted<Maybe<Names>> varNames(this->cx);
Rooted<Maybe<NameBag>> capturedNames(this->cx);
- // FIXME: There must be a nicer way to express all of this.
- // FIXME: Could we somehow generate an optimized parser from the header?
for (auto field: *fields) {
// Fields inherited from `BINJS::Scope`.
// FIXME: We could share this code.
if (field == BINJS_DIRECT_EVAL) {
if (!this->parseBool(reader, &hasDirectEval)) {
return false;
}
} else if (field == BINJS_LET_NAME) {
@@ -169,17 +182,16 @@ ASTReader::parseBlockStatementAux(Simple
|| constNames.get().isNothing()
|| varNames.get().isNothing()
|| capturedNames.get().isNothing()) {
// FIXME: Once we have headers + header validation, this error check
// should become an assertion.
return this->raiseError();
}
- // FIXME: For the moment, we are conflating `let` and `const`.
// Probably not a good idea.
UniquePtr<LexicalScope::Data> bindings(
NewEmptyBindingData<LexicalScope>(this->cx, this->alloc, letNames->length() + constNames->length())
);
if (!bindings) {
return this->raiseError();
}
@@ -204,17 +216,17 @@ ASTReader::parseBlockStatementAux(Simple
UniquePtr<ParseNode> result(new_<LexicalScopeNode>(bindings.release(), body.release()));
out = Move(result);
// FIXME: Validate capturedNames, etc.
return true;
}
bool
-ASTReader::parseStringList(SimpleTokenReader* reader, MutableHandle<Maybe<Names>> out) {
+ASTReader::parseStringList(SimpleTokenReader* reader, ParseContext* pc, MutableHandle<Maybe<Names>> out) {
if (out.get()) {
return this->raiseError();
}
uint32_t length;
SimpleTokenReader sub(this->cx);
Names result(this->cx);
@@ -236,17 +248,17 @@ ASTReader::parseStringList(SimpleTokenRe
}
}
out.set(Move(Some(Move(result))));
return true;
}
bool
-ASTReader::parseStatementList(SimpleTokenReader* reader, UniquePtr<ParseNode>& out) {
+ASTReader::parseStatementList(SimpleTokenReader* reader, ParseContext* pc, UniquePtr<ParseNode>& out) {
if (out) {
return this->raiseError();
}
uint32_t length;
SimpleTokenReader sub(this->cx);
UniquePtr<ParseNode> result(new_<ListNode>(PNK_STATEMENTLIST, TokenPos()));
if (!result) {
@@ -266,17 +278,17 @@ ASTReader::parseStatementList(SimpleToke
result->append(statement.release()); // `result` knows how to deallocate `statement`.
}
result.swap(out);
return true;
}
bool
-ASTReader::parseStatement(SimpleTokenReader* reader, UniquePtr<ParseNode>& out) {
+ASTReader::parseStatement(SimpleTokenReader* reader, ParseContext* pc, UniquePtr<ParseNode>& out) {
if (out) {
return this->raiseError();
}
SimpleTokenReader::Fields fields(this->cx);
SimpleTokenReader sub(this->cx);
std::string name;
if (!reader->taggedTuple(&name, &fields, &sub)) {
@@ -344,17 +356,17 @@ ASTReader::parseStatement(SimpleTokenRea
} else {
return this->raiseError();
}
return true;
}
bool
-ASTReader::parseBool(SimpleTokenReader* reader, Maybe<bool>* result) {
+ASTReader::parseBool(SimpleTokenReader* reader, ParseContext* pc, 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);
}