• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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