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