From d8bbc7858622b6d9c278469aab701ca0b609cddf Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 15 May 2024 05:35:49 +0200 Subject: Merging upstream version 126.0. Signed-off-by: Daniel Baumann --- js/src/vm/JSONParser.h | 153 ++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 139 insertions(+), 14 deletions(-) (limited to 'js/src/vm/JSONParser.h') diff --git a/js/src/vm/JSONParser.h b/js/src/vm/JSONParser.h index 91e33c02b3..51b90e003c 100644 --- a/js/src/vm/JSONParser.h +++ b/js/src/vm/JSONParser.h @@ -190,10 +190,10 @@ class MOZ_STACK_CLASS JSONFullParseHandlerAnyChar { return *static_cast(vector); } - explicit StackEntry(ElementVector* elements) + explicit StackEntry(JSContext* cx, ElementVector* elements) : state(JSONParserState::FinishArrayElement), vector(elements) {} - explicit StackEntry(PropertyVector* properties) + explicit StackEntry(JSContext* cx, PropertyVector* properties) : state(JSONParserState::FinishObjectMember), vector(properties) {} JSONParserState state; @@ -255,7 +255,7 @@ class MOZ_STACK_CLASS JSONFullParseHandlerAnyChar { PropertyVector** properties); inline bool objectPropertyName(Vector& stack, bool* isProtoInEval); - inline void finishObjectMember(Vector& stack, + inline bool finishObjectMember(Vector& stack, JS::Handle value, PropertyVector** properties); inline bool finishObject(Vector& stack, @@ -303,8 +303,6 @@ class MOZ_STACK_CLASS JSONFullParseHandler bool append(const CharT* begin, const CharT* end); }; - ParseRecordObject parseRecord; - explicit JSONFullParseHandler(JSContext* cx) : Base(cx) {} JSONFullParseHandler(JSONFullParseHandler&& other) noexcept @@ -324,13 +322,101 @@ class MOZ_STACK_CLASS JSONFullParseHandler inline bool setNullValue(mozilla::Span&& source); void reportError(const char* msg, uint32_t line, uint32_t column); +}; + +#ifdef ENABLE_JSON_PARSE_WITH_SOURCE +template +class MOZ_STACK_CLASS JSONReviveHandler : public JSONFullParseHandler { + using CharPtr = mozilla::RangedPtr; + using Base = JSONFullParseHandler; + + public: + using SourceT = mozilla::Span; + using ParseRecordEntry = ParseRecordObject::EntryMap; + + using StringBuilder = typename Base::StringBuilder; + using StackEntry = typename Base::StackEntry; + using PropertyVector = typename Base::PropertyVector; + using ElementVector = typename Base::ElementVector; + + public: + explicit JSONReviveHandler(JSContext* cx) : Base(cx), parseRecordStack(cx) {} + + JSONReviveHandler(JSONReviveHandler&& other) noexcept + : Base(std::move(other)), + parseRecordStack(std::move(other.parseRecordStack)), + parseRecord(std::move(other.parseRecord)) {} + + JSONReviveHandler(const JSONReviveHandler& other) = delete; + void operator=(const JSONReviveHandler& other) = delete; + + JSContext* context() { return this->cx; } + + template + inline bool setStringValue(CharPtr start, size_t length, SourceT&& source) { + if (!Base::template setStringValue(start, length, + std::forward(source))) { + return false; + } + return finishPrimitiveParseRecord(this->v, source); + } + + template + inline bool setStringValue(StringBuilder& builder, SourceT&& source) { + if (!Base::template setStringValue(builder, + std::forward(source))) { + return false; + } + return finishPrimitiveParseRecord(this->v, source); + } + + inline bool setNumberValue(double d, SourceT&& source) { + if (!Base::setNumberValue(d, std::forward(source))) { + return false; + } + return finishPrimitiveParseRecord(this->v, source); + } + + inline bool setBooleanValue(bool value, SourceT&& source) { + return finishPrimitiveParseRecord(JS::BooleanValue(value), source); + } + inline bool setNullValue(SourceT&& source) { + return finishPrimitiveParseRecord(JS::NullValue(), source); + } + + inline bool objectOpen(Vector& stack, + PropertyVector** properties); + inline bool finishObjectMember(Vector& stack, + JS::Handle value, + PropertyVector** properties); + inline bool finishObject(Vector& stack, + JS::MutableHandle vp, + PropertyVector* properties); + + inline bool arrayOpen(Vector& stack, + ElementVector** elements); + inline bool arrayElement(Vector& stack, + JS::Handle value, + ElementVector** elements); + inline bool finishArray(Vector& stack, + JS::MutableHandle vp, + ElementVector* elements); void trace(JSTracer* trc); - protected: - inline bool createJSONParseRecord(const Value& value, - mozilla::Span& source); + private: + inline bool finishMemberParseRecord(JS::PropertyKey& key, + ParseRecordEntry& objectEntry); + inline bool finishCompoundParseRecord(const Value& value, + ParseRecordEntry& objectEntry); + inline bool finishPrimitiveParseRecord(const Value& value, SourceT source); + + Vector parseRecordStack; + + public: + ParseRecordObject parseRecord; }; +#endif // ENABLE_JSON_PARSE_WITH_SOURCE template class MOZ_STACK_CLASS JSONSyntaxParseHandler { @@ -409,9 +495,11 @@ class MOZ_STACK_CLASS JSONSyntaxParseHandler { *isProtoInEval = false; return true; } - inline void finishObjectMember(Vector& stack, + inline bool finishObjectMember(Vector& stack, DummyValue& value, - PropertyVector** properties) {} + PropertyVector** properties) { + return true; + } inline bool finishObject(Vector& stack, DummyValue* vp, PropertyVector* properties); @@ -510,11 +598,52 @@ class MOZ_STACK_CLASS JSONParser * represent |undefined|, so the JSON data couldn't have specified it.) */ bool parse(JS::MutableHandle vp); + + void trace(JSTracer* trc); +}; + +#ifdef ENABLE_JSON_PARSE_WITH_SOURCE +template +class MOZ_STACK_CLASS JSONReviveParser + : JSONPerHandlerParser> { + using Base = JSONPerHandlerParser>; + + public: + using ParseType = JSONFullParseHandlerAnyChar::ParseType; + + /* Public API */ + + /* Create a parser for the provided JSON data. */ + JSONReviveParser(JSContext* cx, mozilla::Range data) + : Base(cx, data) {} + + /* Allow move construction for use with Rooted. */ + JSONReviveParser(JSONReviveParser&& other) noexcept + : Base(std::move(other)) {} + + JSONReviveParser(const JSONReviveParser& other) = delete; + void operator=(const JSONReviveParser& other) = delete; + + /* + * Parse the JSON data specified at construction time. If it parses + * successfully, store the prescribed value in *vp and return true. If an + * internal error (e.g. OOM) occurs during parsing, return false. + * Otherwise, if invalid input was specifed but no internal error occurred, + * behavior depends upon the error handling specified at construction: if + * error handling is RaiseError then throw a SyntaxError and return false, + * otherwise return true and set *vp to |undefined|. (JSON syntax can't + * represent |undefined|, so the JSON data couldn't have specified it.) + * + * If it parses successfully, parse information for calling the reviver + * function is stored in *pro. If this function returns false, *pro will be + * set to |undefined|. + */ bool parse(JS::MutableHandle vp, JS::MutableHandle pro); void trace(JSTracer* trc); }; +#endif // ENABLE_JSON_PARSE_WITH_SOURCE template class MutableWrappedPtrOperations, Wrapper> @@ -523,10 +652,6 @@ class MutableWrappedPtrOperations, Wrapper> bool parse(JS::MutableHandle vp) { return static_cast(this)->get().parse(vp); } - bool parse(JS::MutableHandle vp, - JS::MutableHandle pro) { - return static_cast(this)->get().parse(vp, pro); - } }; template -- cgit v1.2.3