summaryrefslogtreecommitdiffstats
path: root/js/src/vm/JSONParser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/vm/JSONParser.cpp')
-rw-r--r--js/src/vm/JSONParser.cpp198
1 files changed, 158 insertions, 40 deletions
diff --git a/js/src/vm/JSONParser.cpp b/js/src/vm/JSONParser.cpp
index f151f261b5..7a440e3090 100644
--- a/js/src/vm/JSONParser.cpp
+++ b/js/src/vm/JSONParser.cpp
@@ -644,7 +644,7 @@ inline bool JSONFullParseHandlerAnyChar::objectOpen(
return false;
}
}
- if (!stack.append(*properties)) {
+ if (!stack.append(StackEntry(cx, *properties))) {
js_delete(*properties);
return false;
}
@@ -676,11 +676,12 @@ inline bool JSONFullParseHandlerAnyChar::objectPropertyName(
return true;
}
-inline void JSONFullParseHandlerAnyChar::finishObjectMember(
+inline bool JSONFullParseHandlerAnyChar::finishObjectMember(
Vector<StackEntry, 10>& stack, JS::Handle<JS::Value> value,
PropertyVector** properties) {
*properties = &stack.back().properties();
(*properties)->back().value = value;
+ return true;
}
inline bool JSONFullParseHandlerAnyChar::finishObject(
@@ -718,7 +719,7 @@ inline bool JSONFullParseHandlerAnyChar::arrayOpen(
return false;
}
}
- if (!stack.append(*elements)) {
+ if (!stack.append(StackEntry(cx, *elements))) {
js_delete(*elements);
return false;
}
@@ -794,7 +795,7 @@ inline bool JSONFullParseHandler<CharT>::setStringValue(
return false;
}
v = JS::StringValue(str);
- return createJSONParseRecord(v, source);
+ return true;
}
template <typename CharT>
@@ -812,26 +813,26 @@ inline bool JSONFullParseHandler<CharT>::setStringValue(
return false;
}
v = JS::StringValue(str);
- return createJSONParseRecord(v, source);
+ return true;
}
template <typename CharT>
inline bool JSONFullParseHandler<CharT>::setNumberValue(
double d, mozilla::Span<const CharT>&& source) {
v = JS::NumberValue(d);
- return createJSONParseRecord(v, source);
+ return true;
}
template <typename CharT>
inline bool JSONFullParseHandler<CharT>::setBooleanValue(
bool value, mozilla::Span<const CharT>&& source) {
- return createJSONParseRecord(JS::BooleanValue(value), source);
+ return true;
}
template <typename CharT>
inline bool JSONFullParseHandler<CharT>::setNullValue(
mozilla::Span<const CharT>&& source) {
- return createJSONParseRecord(JS::NullValue(), source);
+ return true;
}
template <typename CharT>
@@ -847,29 +848,6 @@ void JSONFullParseHandler<CharT>::reportError(const char* msg, uint32_t line,
msg, lineString, columnString);
}
-template <typename CharT>
-void JSONFullParseHandler<CharT>::trace(JSTracer* trc) {
- Base::trace(trc);
- parseRecord.trace(trc);
-}
-
-template <typename CharT>
-inline bool JSONFullParseHandler<CharT>::createJSONParseRecord(
- const Value& value, mozilla::Span<const CharT>& source) {
-#ifdef ENABLE_JSON_PARSE_WITH_SOURCE
- if (cx->realm()->creationOptions().getJSONParseWithSource()) {
- MOZ_ASSERT(!source.IsEmpty());
- Rooted<JSONParseNode*> parseNode(cx,
- NewStringCopy<CanGC, CharT>(cx, source));
- if (!parseNode) {
- return false;
- }
- parseRecord = ParseRecordObject(parseNode, value);
- }
-#endif
- return true;
-}
-
template <typename CharT, typename HandlerT>
JSONPerHandlerParser<CharT, HandlerT>::~JSONPerHandlerParser() {
for (size_t i = 0; i < stack.length(); i++) {
@@ -889,7 +867,9 @@ bool JSONPerHandlerParser<CharT, HandlerT>::parseImpl(TempValueT& value,
switch (state) {
case JSONParserState::FinishObjectMember: {
typename HandlerT::PropertyVector* properties;
- handler.finishObjectMember(stack, value, &properties);
+ if (!handler.finishObjectMember(stack, value, &properties)) {
+ return false;
+ }
token = tokenizer.advanceAfterProperty();
if (token == JSONToken::ObjectClose) {
@@ -1069,6 +1049,13 @@ template class js::JSONPerHandlerParser<Latin1Char,
template class js::JSONPerHandlerParser<char16_t,
js::JSONFullParseHandler<char16_t>>;
+#ifdef ENABLE_JSON_PARSE_WITH_SOURCE
+template class js::JSONPerHandlerParser<Latin1Char,
+ js::JSONReviveHandler<Latin1Char>>;
+template class js::JSONPerHandlerParser<char16_t,
+ js::JSONReviveHandler<char16_t>>;
+#endif
+
template class js::JSONPerHandlerParser<Latin1Char,
js::JSONSyntaxParseHandler<Latin1Char>>;
template class js::JSONPerHandlerParser<char16_t,
@@ -1085,20 +1072,148 @@ bool JSONParser<CharT>::parse(JS::MutableHandle<JS::Value> vp) {
}
template <typename CharT>
-bool JSONParser<CharT>::parse(JS::MutableHandle<JS::Value> vp,
- JS::MutableHandle<ParseRecordObject> pro) {
+void JSONParser<CharT>::trace(JSTracer* trc) {
+ this->handler.trace(trc);
+
+ for (auto& elem : this->stack) {
+ if (elem.state == JSONParserState::FinishArrayElement) {
+ elem.elements().trace(trc);
+ } else {
+ elem.properties().trace(trc);
+ }
+ }
+}
+
+template class js::JSONParser<Latin1Char>;
+template class js::JSONParser<char16_t>;
+
+#ifdef ENABLE_JSON_PARSE_WITH_SOURCE
+template <typename CharT>
+inline bool JSONReviveHandler<CharT>::objectOpen(Vector<StackEntry, 10>& stack,
+ PropertyVector** properties) {
+ if (!parseRecordStack.append(ParseRecordEntry{context()})) {
+ return false;
+ }
+
+ return Base::objectOpen(stack, properties);
+}
+
+template <typename CharT>
+inline bool JSONReviveHandler<CharT>::finishObjectMember(
+ Vector<StackEntry, 10>& stack, JS::Handle<JS::Value> value,
+ PropertyVector** properties) {
+ if (!Base::finishObjectMember(stack, value, properties)) {
+ return false;
+ }
+ parseRecord.value = value;
+ return finishMemberParseRecord((*properties)->back().id,
+ parseRecordStack.back());
+}
+
+template <typename CharT>
+inline bool JSONReviveHandler<CharT>::finishObject(
+ Vector<StackEntry, 10>& stack, JS::MutableHandle<JS::Value> vp,
+ PropertyVector* properties) {
+ if (!Base::finishObject(stack, vp, properties)) {
+ return false;
+ }
+ if (!finishCompoundParseRecord(vp, parseRecordStack.back())) {
+ return false;
+ }
+ parseRecordStack.popBack();
+
+ return true;
+}
+
+template <typename CharT>
+inline bool JSONReviveHandler<CharT>::arrayOpen(Vector<StackEntry, 10>& stack,
+ ElementVector** elements) {
+ if (!parseRecordStack.append(ParseRecordEntry{context()})) {
+ return false;
+ }
+
+ return Base::arrayOpen(stack, elements);
+}
+
+template <typename CharT>
+inline bool JSONReviveHandler<CharT>::arrayElement(
+ Vector<StackEntry, 10>& stack, JS::Handle<JS::Value> value,
+ ElementVector** elements) {
+ if (!Base::arrayElement(stack, value, elements)) {
+ return false;
+ }
+ size_t index = (*elements)->length() - 1;
+ JS::PropertyKey key = js::PropertyKey::Int(index);
+ return finishMemberParseRecord(key, parseRecordStack.back());
+}
+
+template <typename CharT>
+inline bool JSONReviveHandler<CharT>::finishArray(
+ Vector<StackEntry, 10>& stack, JS::MutableHandle<JS::Value> vp,
+ ElementVector* elements) {
+ if (!Base::finishArray(stack, vp, elements)) {
+ return false;
+ }
+ if (!finishCompoundParseRecord(vp, parseRecordStack.back())) {
+ return false;
+ }
+ parseRecordStack.popBack();
+
+ return true;
+}
+
+template <typename CharT>
+inline bool JSONReviveHandler<CharT>::finishMemberParseRecord(
+ JS::PropertyKey& key, ParseRecordEntry& objectEntry) {
+ parseRecord.key = key;
+ return objectEntry.put(key, std::move(parseRecord));
+}
+
+template <typename CharT>
+inline bool JSONReviveHandler<CharT>::finishCompoundParseRecord(
+ const Value& value, ParseRecordEntry& objectEntry) {
+ Rooted<JSONParseNode*> parseNode(context());
+ parseRecord = ParseRecordObject(parseNode, value);
+ return parseRecord.addEntries(context(), std::move(objectEntry));
+}
+
+template <typename CharT>
+inline bool JSONReviveHandler<CharT>::finishPrimitiveParseRecord(
+ const Value& value, SourceT source) {
+ MOZ_ASSERT(!source.IsEmpty()); // Empty source is for objects and arrays
+ Rooted<JSONParseNode*> parseNode(
+ context(), NewStringCopy<CanGC, CharT>(context(), source));
+ if (!parseNode) {
+ return false;
+ }
+ parseRecord = ParseRecordObject(parseNode, value);
+ return true;
+}
+
+template <typename CharT>
+void JSONReviveHandler<CharT>::trace(JSTracer* trc) {
+ Base::trace(trc);
+ parseRecord.trace(trc);
+ for (auto& entry : this->parseRecordStack) {
+ entry.trace(trc);
+ }
+}
+
+template <typename CharT>
+bool JSONReviveParser<CharT>::parse(JS::MutableHandle<JS::Value> vp,
+ JS::MutableHandle<ParseRecordObject> pro) {
JS::Rooted<JS::Value> tempValue(this->handler.cx);
vp.setUndefined();
bool result = this->parseImpl(
tempValue, [&](JS::Handle<JS::Value> value) { vp.set(value); });
- pro.get() = std::move(this->handler.parseRecord);
+ pro.set(std::move(this->handler.parseRecord));
return result;
}
template <typename CharT>
-void JSONParser<CharT>::trace(JSTracer* trc) {
+void JSONReviveParser<CharT>::trace(JSTracer* trc) {
this->handler.trace(trc);
for (auto& elem : this->stack) {
@@ -1110,8 +1225,9 @@ void JSONParser<CharT>::trace(JSTracer* trc) {
}
}
-template class js::JSONParser<Latin1Char>;
-template class js::JSONParser<char16_t>;
+template class js::JSONReviveParser<Latin1Char>;
+template class js::JSONReviveParser<char16_t>;
+#endif // ENABLE_JSON_PARSE_WITH_SOURCE
template <typename CharT>
inline bool JSONSyntaxParseHandler<CharT>::objectOpen(
@@ -1359,9 +1475,11 @@ class MOZ_STACK_CLASS DelegateHandler {
*isProtoInEval = false;
return true;
}
- inline void finishObjectMember(Vector<StackEntry, 10>& stack,
+ inline bool finishObjectMember(Vector<StackEntry, 10>& stack,
DummyValue& value,
- PropertyVector** properties) {}
+ PropertyVector** properties) {
+ return true;
+ }
inline bool finishObject(Vector<StackEntry, 10>& stack, DummyValue* vp,
PropertyVector* properties) {
if (hadHandlerError_) {