diff options
Diffstat (limited to 'js/src/vm/JSONParser.cpp')
-rw-r--r-- | js/src/vm/JSONParser.cpp | 198 |
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_) { |