1 /* 2 * Copyright (c) 2021-2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef ECMASCRIPT_BASE_JSON_PARSE_INL_H 17 #define ECMASCRIPT_BASE_JSON_PARSE_INL_H 18 19 #include <cerrno> 20 21 #include "ecmascript/base/json_helper.h" 22 #include "ecmascript/base/builtins_base.h" 23 #include "ecmascript/base/number_helper.h" 24 #include "ecmascript/base/string_helper.h" 25 #include "ecmascript/ecma_string-inl.h" 26 #include "ecmascript/ecma_string.h" 27 #include "ecmascript/js_array.h" 28 #include "ecmascript/js_function.h" 29 #include "ecmascript/js_handle.h" 30 #include "ecmascript/js_map.h" 31 #include "ecmascript/global_env.h" 32 #include "ecmascript/js_tagged_value.h" 33 #include "ecmascript/message_string.h" 34 #include "ecmascript/object_factory.h" 35 #include "ecmascript/object_fast_operator-inl.h" 36 #include "ecmascript/shared_objects/js_shared_map.h" 37 38 namespace panda::ecmascript::base { 39 constexpr unsigned int UNICODE_DIGIT_LENGTH = 4; 40 constexpr unsigned int NUMBER_TEN = 10; 41 constexpr unsigned int NUMBER_SIXTEEN = 16; 42 constexpr unsigned int INTEGER_MAX_LEN = 9; 43 44 constexpr unsigned char ASCII_END = 0X7F; 45 enum class Tokens : uint8_t { 46 // six structural tokens 47 OBJECT = 0, 48 ARRAY, 49 NUMBER, 50 STRING, 51 LITERAL_TRUE, 52 LITERAL_FALSE, 53 LITERAL_NULL, 54 TOKEN_ILLEGAL, 55 MAP, 56 }; 57 58 struct JsonContinuation { 59 enum class ContinuationType : uint8_t { 60 RETURN = 0, 61 ARRAY, 62 OBJECT, 63 MAP, 64 }; JsonContinuationJsonContinuation65 JsonContinuation(ContinuationType type, size_t index) : type_(type), index_(index) {} 66 67 ContinuationType type_ {ContinuationType::RETURN}; 68 size_t index_ {0}; 69 }; 70 71 template<typename T> 72 class JsonParser { 73 protected: 74 using BigIntMode = base::JsonHelper::BigIntMode; 75 using ParseReturnType = base::JsonHelper::ParseReturnType; 76 using ParseOptions = base::JsonHelper::ParseOptions; 77 using TransformType = base::JsonHelper::TransformType; 78 using Text = const T *; 79 using ContType = JsonContinuation::ContinuationType; 80 // Instantiation of the class is prohibited 81 JsonParser() = default; 82 JsonParser(JSThread *thread, TransformType transformType, 83 ParseOptions options = ParseOptions()) thread_(thread)84 : thread_(thread), transformType_(transformType), parseOptions_(options) 85 { 86 } 87 virtual ~JsonParser() = default; 88 NO_COPY_SEMANTIC(JsonParser); 89 NO_MOVE_SEMANTIC(JsonParser); 90 91 JSHandle<JSTaggedValue> Launch(Text begin, Text end); 92 IsInObjOrArrayOrMap(ContType type)93 inline bool IsInObjOrArrayOrMap(ContType type) 94 { 95 return type == ContType::ARRAY || type == ContType::OBJECT || type == ContType::MAP; 96 } 97 EmptyArrayCheck()98 inline bool EmptyArrayCheck() 99 { 100 GetNextNonSpaceChar(); 101 return *current_ == ']'; 102 } 103 EmptyObjectCheck()104 inline bool EmptyObjectCheck() 105 { 106 GetNextNonSpaceChar(); 107 return *current_ == '}'; 108 } 109 GetSJsonPrototype()110 JSHandle<JSTaggedValue> GetSJsonPrototype() 111 { 112 JSHandle<JSFunction> sObjFunction(thread_->GetEcmaVM()->GetGlobalEnv()->GetSObjectFunction()); 113 JSHandle<JSTaggedValue> jsonPrototype = JSHandle<JSTaggedValue>(thread_, 114 sObjFunction->GetFunctionPrototype(thread_)); 115 return jsonPrototype; 116 } 117 GetSMapPrototype()118 JSHandle<JSTaggedValue> GetSMapPrototype() 119 { 120 auto globalEnv = thread_->GetEcmaVM()->GetGlobalEnv(); 121 JSHandle<JSTaggedValue> proto = globalEnv->GetSharedMapPrototype(); 122 return proto; 123 } 124 125 template<bool isEnableCMCGC> 126 JSTaggedValue ParseJSONText(); 127 128 JSHandle<JSTaggedValue> CreateJsonArray(JsonContinuation continuation, 129 std::vector<JSHandle<JSTaggedValue>> &elementsList); 130 131 JSHandle<JSTaggedValue> CreateSJsonArray([[maybe_unused]] JsonContinuation continuation, 132 [[maybe_unused]] std::vector<JSHandle<JSTaggedValue>> &elementsList); 133 134 template<bool isEnableCMCGC> 135 JSHandle<JSTaggedValue> CreateJsonObject(JsonContinuation continuation, 136 std::vector<JSHandle<JSTaggedValue>> &propertyList); 137 138 template<bool isEnableCMCGC> 139 JSHandle<JSTaggedValue> CreateSJsonObject(JsonContinuation continuation, 140 std::vector<JSHandle<JSTaggedValue>> &propertyList); 141 142 JSHandle<JSSharedMap> CreateSharedMap(); 143 144 JSHandle<JSMap> CreateMap(); 145 146 JSHandle<JSTaggedValue> CreateJsonMap(JsonContinuation continuation, 147 std::vector<JSHandle<JSTaggedValue>> &propertyList); 148 149 JSHandle<JSTaggedValue> CreateSJsonMap(JsonContinuation continuation, 150 std::vector<JSHandle<JSTaggedValue>> &propertyList); 151 152 JSTaggedValue SetPropertyByValue(const JSHandle<JSTaggedValue> &receiver, const JSHandle<JSTaggedValue> &key, 153 const JSHandle<JSTaggedValue> &value); 154 155 JSTaggedValue ParseNumber(bool inObjorArr = false); 156 157 JSTaggedValue ConvertToNumber(const std::string &str, bool negative, bool hasExponent, bool hasDecimal); 158 159 bool ParseStringLength(size_t &length, bool &isAscii, bool inObjorArr); 160 161 bool CheckBackslash(Text &text, Text last, bool &isAscii); 162 163 template<typename Char> 164 void ParseBackslash(Char *&p); 165 166 template<typename Char> 167 void CopyCharWithBackslash(Char *&p); 168 169 JSHandle<JSTaggedValue> ParseStringWithBackslash(bool inObjorArr); 170 virtual void ParticalParseString(std::string& str, Text current, Text nextCurrent) = 0; 171 172 virtual JSHandle<JSTaggedValue> ParseString(bool inObjorArr = false) = 0; 173 174 void SkipEndWhiteSpace(); 175 176 void SkipStartWhiteSpace(); 177 178 void GetNextNonSpaceChar(); 179 180 Tokens ParseToken(); 181 182 JSTaggedValue ParseLiteralTrue(); 183 184 JSTaggedValue ParseLiteralFalse(); 185 186 JSTaggedValue ParseLiteralNull(); 187 188 bool MatchText(const char *str, uint32_t matchLen); 189 190 bool ReadNumberRange(bool &isFast, int32_t &fastInteger); 191 192 Text AdvanceLastNumberCharacter(Text current); 193 194 bool IsNumberCharacter(T ch); 195 196 bool IsNumberSignalCharacter(T ch); 197 198 bool IsExponentNumber(); 199 200 bool IsDecimalsLegal(bool &hasExponent); 201 202 bool IsExponentLegal(bool &hasExponent); 203 204 bool CheckZeroBeginNumber(bool &hasExponent, bool &hasDecimal); 205 206 bool CheckNonZeroBeginNumber(bool &hasExponent, bool &hasDecimal); 207 Advance()208 inline void Advance() 209 { 210 ++current_; 211 } 212 AdvanceMultiStep(int step)213 inline void AdvanceMultiStep(int step) 214 { 215 current_ += step; 216 } 217 218 Text end_ {nullptr}; 219 Text current_ {nullptr}; 220 Text range_ {nullptr}; 221 JSThread *thread_ {nullptr}; 222 ObjectFactory *factory_ {nullptr}; 223 GlobalEnv *env_ {nullptr}; 224 TransformType transformType_ {TransformType::NORMAL}; 225 ParseOptions parseOptions_; 226 JSHandle<JSHClass> initialJSArrayClass_; 227 JSHandle<JSHClass> initialJSObjectClass_; 228 }; 229 230 class PUBLIC_API Utf8JsonParser final : public JsonParser<uint8_t> { 231 public: 232 Utf8JsonParser() = default; 233 Utf8JsonParser(JSThread *thread, TransformType transformType, 234 ParseOptions options = ParseOptions()) JsonParser(thread,transformType,options)235 : JsonParser(thread, transformType, options) {} 236 ~Utf8JsonParser() = default; 237 NO_COPY_SEMANTIC(Utf8JsonParser); 238 NO_MOVE_SEMANTIC(Utf8JsonParser); 239 240 JSHandle<JSTaggedValue> PUBLIC_API Parse(const JSHandle<EcmaString> &strHandle); 241 242 private: 243 void ParticalParseString(std::string& str, Text current, Text nextCurrent) override; 244 245 static void UpdatePointersListener(void *utf8Parser); 246 247 JSHandle<JSTaggedValue> ParseString(bool inObjOrArrOrMap = false) override; 248 249 bool ReadJsonStringRange(bool &isFastString); 250 251 bool IsFastParseJsonString(bool &isFastString); 252 253 const uint8_t *begin_ {nullptr}; 254 JSHandle<EcmaString> sourceString_; 255 }; 256 257 class Utf16JsonParser final : public JsonParser<uint16_t> { 258 public: 259 Utf16JsonParser() = default; 260 Utf16JsonParser(JSThread *thread, TransformType transformType, 261 ParseOptions options = ParseOptions()) JsonParser(thread,transformType,options)262 : JsonParser(thread, transformType, options) {} 263 ~Utf16JsonParser() = default; 264 NO_COPY_SEMANTIC(Utf16JsonParser); 265 NO_MOVE_SEMANTIC(Utf16JsonParser); 266 267 JSHandle<JSTaggedValue> Parse(EcmaString *str); 268 269 private: 270 void ParticalParseString(std::string& str, Text current, Text nextCurrent) override; 271 JSHandle<JSTaggedValue> ParseString(bool inObjOrArrOrMap = false) override; 272 273 bool ReadJsonStringRange(bool &isFastString, bool &isAscii); 274 275 bool IsFastParseJsonString(bool &isFastString, bool &isAscii); 276 277 bool IsLegalAsciiCharacter(uint16_t c, bool &isAscii); 278 }; 279 280 class Internalize { 281 public: 282 using TransformType = base::JsonHelper::TransformType; 283 static JSHandle<JSTaggedValue> InternalizeJsonProperty(JSThread *thread, const JSHandle<JSObject> &holder, 284 const JSHandle<JSTaggedValue> &name, 285 const JSHandle<JSTaggedValue> &receiver, 286 TransformType transformType); 287 private: 288 static bool RecurseAndApply(JSThread *thread, const JSHandle<JSObject> &holder, const JSHandle<JSTaggedValue> &name, 289 const JSHandle<JSTaggedValue> &receiver, TransformType transformType); 290 }; 291 } // namespace panda::ecmascript::base 292 293 #endif // ECMASCRIPT_BASE_JSON_PARSE_INL_H 294