Bug 1823326 - Part 11: Add JSONPerHandlerParser. r=bthrall

To support handler for syntax parser, make the parser templatized for handler.

Differential Revision: https://phabricator.services.mozilla.com/D174569
This commit is contained in:
Tooru Fujisawa 2023-04-20 01:04:48 +00:00
parent eb884636ed
commit 26dd772281
2 changed files with 88 additions and 52 deletions

View File

@ -99,7 +99,7 @@ JSONToken JSONTokenizer<CharT, ParserT, StringBuilderT>::readString() {
* of unescaped characters into a temporary buffer, then an escaped
* character, and repeat until the entire string is consumed.
*/
StringBuilderT builder(parser->handler.cx);
StringBuilderT builder(parser->handler.context());
do {
if (start < current && !builder.append(start.get(), current.get())) {
return token(JSONToken::OOM);
@ -585,9 +585,9 @@ inline void JSONFullParseHandlerAnyChar::freeStackEntry(StackEntry& entry) {
template <typename CharT>
void JSONParser<CharT>::trace(JSTracer* trc) {
handler.trace(trc);
this->handler.trace(trc);
for (auto& elem : stack) {
for (auto& elem : this->stack) {
if (elem.state == JSONParserState::FinishArrayElement) {
elem.elements().trace(trc);
} else {
@ -750,13 +750,13 @@ void JSONFullParseHandler<CharT>::reportError(const char* msg,
msg, lineString, columnString);
}
template <typename CharT>
void JSONParser<CharT>::outOfMemory() {
ReportOutOfMemory(handler.cx);
template <typename CharT, typename HandlerT>
void JSONPerHandlerParser<CharT, HandlerT>::outOfMemory() {
ReportOutOfMemory(handler.context());
}
template <typename CharT>
void JSONParser<CharT>::error(const char* msg) {
template <typename CharT, typename HandlerT>
void JSONPerHandlerParser<CharT, HandlerT>::error(const char* msg) {
if (handler.ignoreError()) {
return;
}
@ -784,26 +784,30 @@ bool JSONFullParseHandler<CharT>::StringBuilder::append(const CharT* begin,
return buffer.append(begin, end);
}
template <typename CharT>
JSONParser<CharT>::~JSONParser() {
template <typename CharT, typename HandlerT>
JSONPerHandlerParser<CharT, HandlerT>::~JSONPerHandlerParser() {
for (size_t i = 0; i < stack.length(); i++) {
handler.freeStackEntry(stack[i]);
}
}
template <typename CharT>
bool JSONParser<CharT>::parse(MutableHandleValue vp) {
RootedValue value(handler.cx);
MOZ_ASSERT(stack.empty());
template class js::JSONPerHandlerParser<Latin1Char,
js::JSONFullParseHandler<Latin1Char>>;
template class js::JSONPerHandlerParser<char16_t,
js::JSONFullParseHandler<char16_t>>;
vp.setUndefined();
template <typename CharT, typename HandlerT>
template <typename TempValueT, typename ResultSetter>
bool JSONPerHandlerParser<CharT, HandlerT>::parseImpl(TempValueT& value,
ResultSetter setResult) {
MOZ_ASSERT(stack.empty());
JSONToken token;
JSONParserState state = JSONParserState::JSONValue;
while (true) {
switch (state) {
case JSONParserState::FinishObjectMember: {
typename Handler::PropertyVector* properties;
typename HandlerT::PropertyVector* properties;
handler.finishObjectMember(stack, value, &properties);
token = tokenizer.advanceAfterProperty();
@ -854,7 +858,7 @@ bool JSONParser<CharT>::parse(MutableHandleValue vp) {
return handler.errorReturn();
case JSONParserState::FinishArrayElement: {
typename Handler::ElementVector* elements;
typename HandlerT::ElementVector* elements;
if (!handler.arrayElement(stack, value, &elements)) {
return false;
}
@ -894,7 +898,7 @@ bool JSONParser<CharT>::parse(MutableHandleValue vp) {
break;
case JSONToken::ArrayOpen: {
typename Handler::ElementVector* elements;
typename HandlerT::ElementVector* elements;
if (!handler.arrayOpen(stack, &elements)) {
return false;
}
@ -910,7 +914,7 @@ bool JSONParser<CharT>::parse(MutableHandleValue vp) {
}
case JSONToken::ObjectOpen: {
typename Handler::PropertyVector* properties;
typename HandlerT::PropertyVector* properties;
if (!handler.objectOpen(stack, &properties)) {
return false;
}
@ -958,9 +962,19 @@ bool JSONParser<CharT>::parse(MutableHandleValue vp) {
MOZ_ASSERT(tokenizer.finished());
MOZ_ASSERT(stack.empty());
vp.set(value);
setResult(value);
return true;
}
template <typename CharT>
bool JSONParser<CharT>::parse(MutableHandleValue vp) {
RootedValue tempValue(this->handler.cx);
vp.setUndefined();
return this->parseImpl(tempValue,
[&](JS::Handle<JS::Value> value) { vp.set(value); });
}
template class js::JSONParser<Latin1Char>;
template class js::JSONParser<char16_t>;

View File

@ -179,8 +179,7 @@ class MOZ_STACK_CLASS JSONFullParseHandlerAnyChar {
Value v;
protected:
const ParseType parseType;
ParseType parseType = ParseType::JSONParse;
private:
// Unused element and property vectors for previous in progress arrays and
@ -190,8 +189,8 @@ class MOZ_STACK_CLASS JSONFullParseHandlerAnyChar {
Vector<PropertyVector*, 5> freeProperties;
public:
JSONFullParseHandlerAnyChar(JSContext* cx, ParseType parseType)
: cx(cx), parseType(parseType), freeElements(cx), freeProperties(cx) {}
explicit JSONFullParseHandlerAnyChar(JSContext* cx)
: cx(cx), freeElements(cx), freeProperties(cx) {}
~JSONFullParseHandlerAnyChar();
// Allow move construction for use with Rooted.
@ -206,6 +205,8 @@ class MOZ_STACK_CLASS JSONFullParseHandlerAnyChar {
delete;
void operator=(const JSONFullParseHandlerAnyChar& other) = delete;
JSContext* context() { return cx; }
Value numberValue() const {
MOZ_ASSERT(v.isNumber());
return v;
@ -266,6 +267,8 @@ class MOZ_STACK_CLASS JSONFullParseHandler
using CharPtr = mozilla::RangedPtr<const CharT>;
public:
using ContextT = JSContext;
class StringBuilder {
public:
JSStringBuilder buffer;
@ -276,8 +279,7 @@ class MOZ_STACK_CLASS JSONFullParseHandler
bool append(const CharT* begin, const CharT* end);
};
JSONFullParseHandler(JSContext* cx, ParseType parseType)
: Base(cx, parseType) {}
explicit JSONFullParseHandler(JSContext* cx) : Base(cx) {}
JSONFullParseHandler(JSONFullParseHandler&& other) noexcept
: Base(std::move(other)) {}
@ -294,23 +296,53 @@ class MOZ_STACK_CLASS JSONFullParseHandler
const char* columnString);
};
template <typename CharT>
class MOZ_STACK_CLASS JSONParser {
using Handler = JSONFullParseHandler<CharT>;
template <typename CharT, typename HandlerT>
class MOZ_STACK_CLASS JSONPerHandlerParser {
using ContextT = typename HandlerT::ContextT;
using Tokenizer = JSONTokenizer<CharT, JSONPerHandlerParser<CharT, HandlerT>,
typename HandlerT::StringBuilder>;
public:
using StringBuilder = typename Handler::StringBuilder;
private:
using Tokenizer = JSONTokenizer<CharT, JSONParser<CharT>, StringBuilder>;
using StringBuilder = typename HandlerT::StringBuilder;
public:
Handler handler;
HandlerT handler;
Tokenizer tokenizer;
// All in progress arrays and objects being parsed, in order from outermost
// to innermost.
Vector<typename Handler::StackEntry, 10> stack;
Vector<typename HandlerT::StackEntry, 10> stack;
public:
JSONPerHandlerParser(ContextT* context, mozilla::Range<const CharT> data)
: handler(context), tokenizer(data, this), stack(context) {}
JSONPerHandlerParser(JSONPerHandlerParser&& other) noexcept
: handler(std::move(other.handler)),
tokenizer(std::move(other.tokenizer)),
stack(handler.context()) {
tokenizer.fixupParser(this);
}
~JSONPerHandlerParser();
JSONPerHandlerParser(const JSONPerHandlerParser<CharT, HandlerT>& other) =
delete;
void operator=(const JSONPerHandlerParser<CharT, HandlerT>& other) = delete;
template <typename TempValueT, typename ResultSetter>
inline bool parseImpl(TempValueT& value, ResultSetter setResult);
void outOfMemory();
void error(const char* msg);
};
template <typename CharT>
class MOZ_STACK_CLASS JSONParser
: JSONPerHandlerParser<CharT, JSONFullParseHandler<CharT>> {
using Base = JSONPerHandlerParser<CharT, JSONFullParseHandler<CharT>>;
public:
using ParseType = JSONFullParseHandlerAnyChar::ParseType;
@ -320,17 +352,15 @@ class MOZ_STACK_CLASS JSONParser {
/* Create a parser for the provided JSON data. */
JSONParser(JSContext* cx, mozilla::Range<const CharT> data,
ParseType parseType)
: handler(cx, parseType), tokenizer(data, this), stack(cx) {}
/* Allow move construction for use with Rooted. */
JSONParser(JSONParser&& other)
: handler(std::move(other.handler)),
tokenizer(std::move(other.tokenizer)),
stack(std::move(other.stack)) {
tokenizer.fixupParser(this);
: Base(cx, data) {
this->handler.parseType = parseType;
}
~JSONParser();
/* Allow move construction for use with Rooted. */
JSONParser(JSONParser&& other) noexcept : Base(std::move(other)) {}
JSONParser(const JSONParser& other) = delete;
void operator=(const JSONParser& other) = delete;
/*
* Parse the JSON data specified at construction time. If it parses
@ -345,14 +375,6 @@ class MOZ_STACK_CLASS JSONParser {
bool parse(MutableHandleValue vp);
void trace(JSTracer* trc);
void outOfMemory();
void error(const char* msg);
private:
JSONParser(const JSONParser& other) = delete;
void operator=(const JSONParser& other) = delete;
};
template <typename CharT, typename Wrapper>