• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 "ecmascript/base/json_parser.h"
20 #include "ecmascript/base/builtins_base.h"
21 #include "ecmascript/base/number_helper.h"
22 #include "ecmascript/base/string_helper.h"
23 #include "ecmascript/base/utf_helper.h"
24 #include "ecmascript/ecma_string-inl.h"
25 #include "ecmascript/ecma_string.h"
26 #include "ecmascript/internal_call_params.h"
27 #include "ecmascript/interpreter/fast_runtime_stub-inl.h"
28 #include "ecmascript/js_array.h"
29 #include "ecmascript/js_function.h"
30 #include "ecmascript/js_handle.h"
31 #include "ecmascript/js_tagged_value.h"
32 #include "ecmascript/object_factory.h"
33 
34 namespace panda::ecmascript::base {
35 constexpr unsigned int UNICODE_DIGIT_LENGTH = 4;
36 constexpr unsigned int NUMBER_TEN = 10;
37 constexpr unsigned int NUMBER_SIXTEEN = 16;
38 
39 constexpr unsigned char CODE_SPACE = 0x20;
40 constexpr unsigned char ASCII_END = 0X7F;
41 enum class Tokens : uint8_t {
42         // six structural tokens
43         OBJECT = 0,
44         ARRAY,
45         NUMBER,
46         STRING,
47         LITERAL_TRUE,
48         LITERAL_FALSE,
49         LITERAL_NULL,
50         TOKEN_ILLEGAL,
51     };
52 
53 template<typename T>
54 class JsonParser {
55 public:
56     using Text = const T *;
57     explicit JsonParser() = default;
JsonParser(JSThread * thread)58     explicit JsonParser(JSThread *thread) : thread_(thread) {}
59     ~JsonParser() = default;
60     NO_COPY_SEMANTIC(JsonParser);
61     NO_MOVE_SEMANTIC(JsonParser);
Parse(Text begin,Text end)62     JSHandle<JSTaggedValue> Parse(Text begin, Text end)
63     {
64         end_ = end - 1;
65         current_ = begin;
66 
67         auto vm = thread_->GetEcmaVM();
68         factory_ = vm->GetFactory();
69         env_ = *vm->GetGlobalEnv();
70 
71         SkipEndWhiteSpace();
72         range_ = end_;
73         JSTaggedValue result = ParseJSONText<false>();
74         return JSHandle<JSTaggedValue>(thread_, result);
75     }
76 
ParseUtf8(EcmaString * str)77     JSHandle<JSTaggedValue> ParseUtf8(EcmaString *str)
78     {
79         ASSERT(str != nullptr);
80         isAsciiString_ = true;
81         uint32_t len = str->GetUtf8Length();
82         CVector<T> buf(len);
83         str->CopyDataUtf8(buf.data(), len);
84         Text begin = buf.data();
85         return Parse(begin, begin + str->GetLength());
86     }
87 
ParseUtf16(EcmaString * str)88     JSHandle<JSTaggedValue> ParseUtf16(EcmaString *str)
89     {
90         ASSERT(str != nullptr);
91         uint32_t len = str->GetLength();
92         CVector<T> buf(len);
93         str->CopyDataUtf16(buf.data(), len);
94         Text begin = buf.data();
95         return Parse(begin, begin + len);
96     }
97 
98 private:
99     template<bool inObjorArr = false>
ParseJSONText()100     JSTaggedValue ParseJSONText()
101     {
102         SkipStartWhiteSpace();
103         Tokens token = ParseToken();
104         switch (token) {
105             case Tokens::OBJECT:
106                 return ParseObject<inObjorArr>();
107             case Tokens::ARRAY:
108                 return ParseArray<inObjorArr>();
109             case Tokens::LITERAL_TRUE:
110                 return ParseLiteral("true", Tokens::LITERAL_TRUE);
111             case Tokens::LITERAL_FALSE:
112                 return ParseLiteral("false", Tokens::LITERAL_FALSE);
113             case Tokens::LITERAL_NULL:
114                 return ParseLiteral("null", Tokens::LITERAL_NULL);
115             case Tokens::NUMBER:
116                 return ParseNumber<inObjorArr>();
117             case Tokens::STRING:
118                 return ParseString<inObjorArr>();
119             default:
120                 THROW_SYNTAX_ERROR_AND_RETURN(thread_, "Unexpected Text in JSON", JSTaggedValue::Exception());
121         }
122     }
123 
124     template<bool inObjOrArr = false>
ParseNumber()125     JSTaggedValue ParseNumber()
126     {
127         if (inObjOrArr) {
128             bool isFast = true;
129             bool isNumber = ReadNumberRange(isFast);
130             if (!isNumber) {
131                 THROW_SYNTAX_ERROR_AND_RETURN(thread_, "Unexpected Number in JSON", JSTaggedValue::Exception());
132             }
133             if (isFast) {
134                 std::string strNum(current_, end_ + 1);
135                 current_ = end_;
136                 return JSTaggedValue(std::stod(strNum));
137             }
138         }
139 
140         Text current = current_;
141         bool hasExponent = false;
142         if (*current_ == '-') {
143             if (UNLIKELY(current_++ == end_)) {
144                 THROW_SYNTAX_ERROR_AND_RETURN(thread_, "Unexpected Number in JSON", JSTaggedValue::Exception());
145             }
146         }
147         if (*current_ == '0') {
148             if (!CheckZeroBeginNumber(hasExponent)) {
149                 THROW_SYNTAX_ERROR_AND_RETURN(thread_, "Unexpected Number in JSON", JSTaggedValue::Exception());
150             }
151         } else if (*current_ >= '1' && *current_ <= '9') {
152             if (!CheckNonZeroBeginNumber(hasExponent)) {
153                 THROW_SYNTAX_ERROR_AND_RETURN(thread_, "Unexpected Number in JSON", JSTaggedValue::Exception());
154             }
155         } else {
156             THROW_SYNTAX_ERROR_AND_RETURN(thread_, "Unexpected Number in JSON", JSTaggedValue::Exception());
157         }
158 
159         std::string strNum(current, end_ + 1);
160         current_ = end_;
161         return JSTaggedValue(std::stod(strNum));
162     }
163 
ReadJsonStringRange(bool & isFastString,bool & isAscii)164     bool ReadJsonStringRange(bool &isFastString, bool &isAscii)
165     {
166         current_++;
167         if (isAsciiString_) {
168             return ReadAsciiStringRange(isFastString);
169         }
170         return ReadStringRange(isFastString, isAscii);
171     }
172 
IsFastParseJsonString(bool & isFastString,bool & isAscii)173     bool IsFastParseJsonString(bool &isFastString, bool &isAscii)
174     {
175         current_++;
176         if (isAsciiString_) {
177             return IsFastParseAsciiString(isFastString);
178         }
179         return IsFastParseString(isFastString, isAscii);
180     }
181 
ParseBackslash(CString & res)182     bool ParseBackslash(CString &res)
183     {
184         if (current_ == end_) {
185             return false;
186         }
187         current_++;
188         switch (*current_) {
189             case '\"':
190                 res += "\"";
191                 break;
192             case '\\':
193                 res += "\\";
194                 break;
195             case '/':
196                 res += "/";
197                 break;
198             case 'b':
199                 res += "\b";
200                 break;
201             case 'f':
202                 res += "\f";
203                 break;
204             case 'n':
205                 res += "\n";
206                 break;
207             case 'r':
208                 res += "\r";
209                 break;
210             case 't':
211                 res += "\t";
212                 break;
213             case 'u': {
214                 CVector<uint16_t> vec;
215                 if (UNLIKELY(!ConvertStringUnicode(vec))) {
216                     return false;
217                 }
218                 std::u16string u16Str;
219                 u16Str.assign(vec.begin(), vec.end());
220                 res += base::StringHelper::U16stringToString(u16Str);
221                 break;
222             }
223             default:
224                 return false;
225         }
226         return true;
227     }
228 
SlowParseString()229     JSTaggedValue SlowParseString()
230     {
231         end_--;
232         CString res;
233         while (current_ <= end_) {
234             if (*current_ == '\\') {
235                 bool isLegalChar = ParseBackslash(res);
236                 if (!isLegalChar) {
237                     THROW_SYNTAX_ERROR_AND_RETURN(thread_, "Unexpected string in JSON", JSTaggedValue::Exception());
238                 }
239                 current_++;
240             } else if (UNLIKELY(*current_ > ASCII_END)) {
241                 if (UNLIKELY(*current_ > utf_helper::DECODE_LEAD_LOW && *current_ < utf_helper::DECODE_LEAD_HIGH &&
242                              *(current_ + 1) > utf_helper::DECODE_TRAIL_LOW &&
243                              *(current_ + 1) < utf_helper::DECODE_TRAIL_HIGH)) {
244                     std::u16string str(current_, current_ + 2);  // 2 means twice as many bytes as normal u16string
245                     res += ConvertToString(StringHelper::U16stringToString(str));
246                     current_ += 2;  // 2 means twice as many bytes as normal u16string
247                 } else {
248                     std::u16string str(current_, current_ + 1);
249                     res += ConvertToString(StringHelper::U16stringToString(str));
250                     current_++;
251                 }
252             } else {
253                 res += *current_;
254                 current_++;
255             }
256         }
257         return factory_->NewFromUtf8Literal(reinterpret_cast<const uint8_t *>(res.c_str()), res.length())
258             .GetTaggedValue();
259     }
260 
261     template<bool inObjorArr = false>
ParseString()262     JSTaggedValue ParseString()
263     {
264         bool isFastString = true;
265         bool isAscii = true;
266         bool isLegal = true;
267         if (inObjorArr) {
268             isLegal = ReadJsonStringRange(isFastString, isAscii);
269             if (!isLegal) {
270                 THROW_SYNTAX_ERROR_AND_RETURN(thread_, "Unexpected end Text in JSON", JSTaggedValue::Exception());
271             }
272             if (isFastString) {
273                 if (isAscii) {
274                     CString value(current_, end_);
275                     current_ = end_;
276                     return factory_->NewFromUtf8Literal(
277                         reinterpret_cast<const uint8_t *>(value.c_str()), value.length()).GetTaggedValue();
278                 }
279                 std::u16string value(current_, end_);
280                 current_ = end_;
281                 return factory_->NewFromUtf16Literal(
282                     reinterpret_cast<const uint16_t *>(value.c_str()), value.length()).GetTaggedValue();
283             }
284         } else {
285             if (*end_ != '"' || current_ == end_) {
286                 THROW_SYNTAX_ERROR_AND_RETURN(thread_, "Unexpected end Text in JSON", JSTaggedValue::Exception());
287             }
288             isLegal = IsFastParseJsonString(isFastString, isAscii);
289             if (!isLegal) {
290                 THROW_SYNTAX_ERROR_AND_RETURN(thread_, "Unexpected end Text in JSON", JSTaggedValue::Exception());
291             }
292             if (LIKELY(isFastString)) {
293                 if (isAscii) {
294                     CString value(current_, end_);
295                     return factory_->NewFromUtf8Literal(
296                         reinterpret_cast<const uint8_t *>(value.c_str()), value.length()).GetTaggedValue();
297                 }
298                 std::u16string value(current_, end_);
299                 return factory_->NewFromUtf16Literal(
300                     reinterpret_cast<const uint16_t *>(value.c_str()), value.length()).GetTaggedValue();
301             }
302         }
303         return SlowParseString();
304     }
305 
306     template<bool inObjorArr = false>
ParseArray()307     JSTaggedValue ParseArray()
308     {
309         if (UNLIKELY(*range_ != ']' && !inObjorArr)) {
310             THROW_SYNTAX_ERROR_AND_RETURN(thread_, "Unexpected Array in JSON", JSTaggedValue::Exception());
311         }
312 
313         current_++;
314         JSHandle<JSArray> arr = factory_->NewJSArray();
315         if (*current_ == ']') {
316             return arr.GetTaggedValue();
317         }
318 
319         JSTaggedValue value;
320         uint32_t index = 0;
321         while (current_ <= range_) {
322             value = ParseJSONText<true>();
323             RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread_);
324             FastRuntimeStub::SetPropertyByIndex<true>(thread_, arr.GetTaggedValue(), index++, value);
325             GetNextNonSpaceChar();
326             if (*current_ == ',') {
327                 current_++;
328             } else if (*current_ == ']') {
329                 if (inObjorArr || current_ == range_) {
330                     return arr.GetTaggedValue();
331                 } else {
332                     THROW_SYNTAX_ERROR_AND_RETURN(thread_, "Unexpected Array in JSON", JSTaggedValue::Exception());
333                 }
334             }
335         }
336         THROW_SYNTAX_ERROR_AND_RETURN(thread_, "Unexpected Array in JSON", JSTaggedValue::Exception());
337     }
338 
339     template<bool inObjorArr = false>
ParseObject()340     JSTaggedValue ParseObject()
341     {
342         if (UNLIKELY(*range_ != '}' && !inObjorArr)) {
343             THROW_SYNTAX_ERROR_AND_RETURN(thread_, "Unexpected Object in JSON", JSTaggedValue::Exception());
344         }
345 
346         JSHandle<JSTaggedValue> proto = env_->GetObjectFunction();
347         JSHandle<JSObject> result = factory_->NewJSObjectByConstructor(JSHandle<JSFunction>(proto), proto);
348         current_++;
349         if (*current_ == '}') {
350             return result.GetTaggedValue();
351         }
352 
353         JSMutableHandle<JSTaggedValue> keyHandle(thread_, JSTaggedValue::Undefined());
354         JSTaggedValue value;
355         while (current_ <= range_) {
356             SkipStartWhiteSpace();
357             if (*current_ == '"') {
358                 keyHandle.Update(ParseString<true>());
359             } else {
360                 if (*current_ == '}' && (inObjorArr || current_ == range_)) {
361                     return result.GetTaggedValue();
362                 }
363                 THROW_SYNTAX_ERROR_AND_RETURN(thread_, "Unexpected Object in JSON", JSTaggedValue::Exception());
364             }
365             GetNextNonSpaceChar();
366             if (*current_ == ':') {
367                 current_++;
368             } else {
369                 THROW_SYNTAX_ERROR_AND_RETURN(thread_, "Unexpected Object in JSON", JSTaggedValue::Exception());
370             }
371             value = ParseJSONText<true>();
372             FastRuntimeStub::SetPropertyByValue<true>(
373                 thread_, result.GetTaggedValue(), keyHandle.GetTaggedValue(), value);
374             GetNextNonSpaceChar();
375             if (*current_ == ',') {
376                 current_++;
377             } else if (*current_ == '}') {
378                 if (inObjorArr || current_ == range_) {
379                     return result.GetTaggedValue();
380                 } else {
381                     THROW_SYNTAX_ERROR_AND_RETURN(thread_, "Unexpected Object in JSON", JSTaggedValue::Exception());
382                 }
383             }
384         }
385         THROW_SYNTAX_ERROR_AND_RETURN(thread_, "Unexpected Object in JSON", JSTaggedValue::Exception());
386     }
387 
SkipEndWhiteSpace()388     void SkipEndWhiteSpace()
389     {
390         while (current_ != end_) {
391             if (*end_ == ' ' || *end_ == '\r' || *end_ == '\n' || *end_ == '\t') {
392                 end_--;
393             } else {
394                 break;
395             }
396         }
397     }
398 
SkipStartWhiteSpace()399     void SkipStartWhiteSpace()
400     {
401         while (current_ != end_) {
402             if (*current_ == ' ' || *current_ == '\r' || *current_ == '\n' || *current_ == '\t') {
403                 current_++;
404             } else {
405                 break;
406             }
407         }
408     }
409 
GetNextNonSpaceChar()410     void GetNextNonSpaceChar()
411     {
412         current_++;
413         SkipStartWhiteSpace();
414     }
415 
ParseToken()416     Tokens ParseToken()
417     {
418         switch (*current_) {
419             case '{':
420                 return Tokens::OBJECT;
421             case '[':
422                 return Tokens::ARRAY;
423             case '"':
424                 return Tokens::STRING;
425             case '0':
426             case '1':
427             case '2':
428             case '3':
429             case '4':
430             case '5':
431             case '6':
432             case '7':
433             case '8':
434             case '9':
435             case '-':
436                 return Tokens::NUMBER;
437             case 't':
438                 return Tokens::LITERAL_TRUE;
439             case 'f':
440                 return Tokens::LITERAL_FALSE;
441             case 'n':
442                 return Tokens::LITERAL_NULL;
443             default:
444                 return Tokens::TOKEN_ILLEGAL;
445         }
446     }
447 
ParseLiteral(CString str,Tokens literalToken)448     JSTaggedValue ParseLiteral(CString str, Tokens literalToken)
449     {
450         uint32_t strLen = str.size() - 1;
451         uint32_t remainingLength = range_ - current_;
452         if (UNLIKELY(remainingLength < strLen)) {
453             THROW_SYNTAX_ERROR_AND_RETURN(thread_, "Unexpected Text in JSON", JSTaggedValue::Exception());
454         }
455 
456         bool isMatch = MatchText(str, strLen);
457         if (LIKELY(isMatch)) {
458             switch (literalToken) {
459                 case Tokens::LITERAL_TRUE:
460                     return JSTaggedValue::True();
461                 case Tokens::LITERAL_FALSE:
462                     return JSTaggedValue::False();
463                 case Tokens::LITERAL_NULL:
464                     return JSTaggedValue::Null();
465                 default:
466                     UNREACHABLE();
467             }
468         }
469         THROW_SYNTAX_ERROR_AND_RETURN(thread_, "Unexpected Text in JSON", JSTaggedValue::Exception());
470     }
471 
MatchText(CString str,uint32_t matchLen)472     bool MatchText(CString str, uint32_t matchLen)
473     {
474         const char *text = str.c_str();
475         uint32_t pos = 1;
476         while (pos <= matchLen) {
477             if (current_[pos] != text[pos]) {
478                 return false;
479             }
480             pos++;
481         }
482         current_ += matchLen;
483         return true;
484     }
485 
ReadNumberRange(bool & isFast)486     bool ReadNumberRange(bool &isFast)
487     {
488         Text current = current_;
489         if (*current == '0') {
490             isFast = false;
491             current++;
492         } else if (*current == '-') {
493             current++;
494             if (*current == '0') {
495                 isFast = false;
496                 current++;
497             }
498         }
499 
500         while (current != range_) {
501             if (IsNumberCharacter(*current)) {
502                 current++;
503                 continue;
504             } else if (IsNumberSignalCharacter(*current)) {
505                 isFast = false;
506                 current++;
507                 continue;
508             }
509             Text end = current;
510             while (current != range_) {
511                 if (*current == ' ' || *current == '\r' || *current == '\n' || *current == '\t') {
512                     current++;
513                 } else if (*current == ',' || *current == ']' || *current == '}') {
514                     end_ = end - 1;
515                     return true;
516                 } else {
517                     return false;
518                 }
519             }
520             if (*current == ']' || *current == '}') {
521                 end_ = end - 1;
522                 return true;
523             }
524             return false;
525         }
526         end_ = range_ - 1;
527         return true;
528     }
529 
IsNumberCharacter(T ch)530     bool IsNumberCharacter(T ch)
531     {
532         if (ch >= '0' && ch <= '9') {
533             return true;
534         }
535         return false;
536     }
537 
IsNumberSignalCharacter(T ch)538     bool IsNumberSignalCharacter(T ch)
539     {
540         return ch == '.' || ch == 'e' || ch == 'E' || ch == '+' || ch == '-';
541     }
542 
IsExponentNumber()543     bool IsExponentNumber()
544     {
545         if (IsNumberCharacter(*current_)) {
546             return true;
547         } else if (*current_ == '-' || *current_ == '+') {
548             if (current_ == end_) {
549                 return false;
550             }
551             current_++;
552             if (IsNumberCharacter(*current_)) {
553                 return true;
554             }
555         }
556         return false;
557     }
558 
IsDecimalsLegal(bool & hasExponent)559     bool IsDecimalsLegal(bool &hasExponent)
560     {
561         if (current_ == end_ && !IsNumberCharacter(*++current_)) {
562             return false;
563         }
564 
565         while (current_ != end_) {
566             current_++;
567             if (IsNumberCharacter(*current_)) {
568                 continue;
569             } else if (*current_ == 'e' || *current_ == 'E') {
570                 if (hasExponent || current_ == end_) {
571                     return false;
572                 }
573                 current_++;
574                 if (!IsExponentNumber()) {
575                     return false;
576                 }
577                 hasExponent = true;
578             } else {
579                 return false;
580             }
581         }
582         return true;
583     }
584 
IsExponentLegal(bool & hasExponent)585     bool IsExponentLegal(bool &hasExponent)
586     {
587         if (hasExponent || current_ == end_) {
588             return false;
589         }
590         current_++;
591         if (!IsExponentNumber()) {
592             return false;
593         }
594         while (current_ != end_) {
595             if (!IsNumberCharacter(*current_)) {
596                 return false;
597             }
598             current_++;
599         }
600         return true;
601     }
602 
ReadStringRange(bool & isFast,bool & isAscii)603     bool ReadStringRange(bool &isFast, bool &isAscii)
604     {
605         T c = 0;
606         Text current = current_;
607 
608         while (current != range_) {
609             c = *current;
610             if (c == '"') {
611                 end_ = current;
612                 return true;
613             } else if (UNLIKELY(c == '\\')) {
614                 current++;
615                 isFast = false;
616             }
617             if (!IsLegalAsciiCharacter(c, isAscii)) {
618                 return false;
619             }
620             current++;
621         }
622         return false;
623     }
624 
ReadAsciiStringRange(bool & isFast)625     bool ReadAsciiStringRange(bool &isFast)
626     {
627         T c = 0;
628         Text current = current_;
629 
630         while (current != range_) {
631             c = *current;
632             if (c == '"') {
633                 end_ = current;
634                 return true;
635             } else if (UNLIKELY(c == '\\')) {
636                 current++;
637                 isFast = false;
638             } else if (UNLIKELY(c < CODE_SPACE)) {
639                 return false;
640             }
641             current++;
642         }
643         return false;
644     }
645 
IsFastParseString(bool & isFast,bool & isAscii)646     bool IsFastParseString(bool &isFast, bool &isAscii)
647     {
648         Text current = current_;
649         while (current != end_) {
650             if (!IsLegalAsciiCharacter(*current, isAscii)) {
651                 return false;
652             }
653             if (*current == '\\') {
654                 isFast = false;
655             }
656             current++;
657         }
658         return true;
659     }
660 
IsFastParseAsciiString(bool & isFast)661     bool IsFastParseAsciiString(bool &isFast)
662     {
663         Text current = current_;
664         while (current != end_) {
665             if (*current < CODE_SPACE) {
666                 return false;
667             } else if (*current == '\\') {
668                 isFast = false;
669             }
670             current++;
671         }
672         return true;
673     }
674 
ConvertStringUnicode(CVector<uint16_t> & vec)675     bool ConvertStringUnicode(CVector<uint16_t> &vec)
676     {
677         uint32_t remainingLength = end_ - current_;
678         if (remainingLength < UNICODE_DIGIT_LENGTH) {
679             return false;
680         }
681         uint16_t res = 0;
682         uint32_t exponent = UNICODE_DIGIT_LENGTH;
683         for (uint32_t pos = 0; pos < UNICODE_DIGIT_LENGTH; pos++) {
684             current_++;
685             exponent--;
686             if (*current_ >= '0' && *current_ <= '9') {
687                 res += (*current_ - '0') * pow(NUMBER_SIXTEEN, exponent);
688             } else if (*current_ >= 'a' && *current_ <= 'f') {
689                 res += (*current_ - 'a' + NUMBER_TEN) * pow(NUMBER_SIXTEEN, exponent);
690             } else if (*current_ >= 'A' && *current_ <= 'F') {
691                 res += (*current_ - 'A' + NUMBER_TEN) * pow(NUMBER_SIXTEEN, exponent);
692             } else {
693                 return false;
694             }
695         }
696 
697         vec.emplace_back(res);
698 
699         if (*(current_ + 1) == '\\' && *(current_ + 2) == 'u') {  // 2: next two chars
700             current_ += 2;                                        // 2: point moves backwards by two digits
701             return ConvertStringUnicode(vec);
702         }
703         return true;
704     }
705 
CheckZeroBeginNumber(bool & hasExponent)706     bool CheckZeroBeginNumber(bool &hasExponent)
707     {
708         if (current_++ != end_) {
709             if (*current_ == '.') {
710                 if (!IsDecimalsLegal(hasExponent)) {
711                     return false;
712                 }
713             } else if (*current_ == 'e' || *current_ == 'E') {
714                 if (!IsExponentLegal(hasExponent)) {
715                     return false;
716                 }
717             } else {
718                 return false;
719             }
720         }
721         return true;
722     }
723 
CheckNonZeroBeginNumber(bool & hasExponent)724     bool CheckNonZeroBeginNumber(bool &hasExponent)
725     {
726         while (current_ != end_) {
727             current_++;
728             if (IsNumberCharacter(*current_)) {
729                 continue;
730             } else if (*current_ == '.') {
731                 if (!IsDecimalsLegal(hasExponent)) {
732                     return false;
733                 }
734             } else if (*current_ == 'e' || *current_ == 'E') {
735                 if (!IsExponentLegal(hasExponent)) {
736                     return false;
737                 }
738             } else {
739                 return false;
740             }
741         }
742         return true;
743     }
744 
IsLegalAsciiCharacter(T c,bool & isAscii)745     bool IsLegalAsciiCharacter(T c, bool &isAscii)
746     {
747         if (c <= ASCII_END) {
748             if (c >= CODE_SPACE) {
749                 return true;
750             }
751             return false;
752         }
753         isAscii = false;
754         return true;
755     }
756 
757     bool isAsciiString_{false};
758     Text end_{nullptr};
759     Text current_{nullptr};
760     Text range_{nullptr};
761     JSThread *thread_{nullptr};
762     ObjectFactory *factory_{nullptr};
763     GlobalEnv *env_{nullptr};
764 };
765 
766 class Internalize {
767 public:
768     static JSHandle<JSTaggedValue> InternalizeJsonProperty(JSThread *thread, const JSHandle<JSObject> &holder,
769                                                            const JSHandle<JSTaggedValue> &name,
770                                                            const JSHandle<JSTaggedValue> &receiver);
771 private:
772     static bool RecurseAndApply(JSThread *thread, const JSHandle<JSObject> &holder, const JSHandle<JSTaggedValue> &name,
773                                 const JSHandle<JSTaggedValue> &receiver);
774 };
775 }  // namespace panda::ecmascript::base
776 
777 #endif  // ECMASCRIPT_BASE_JSON_PARSE_INL_H
778