• 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 #include "ecmascript/builtins/builtins_global.h"
17 #include <random>
18 #include <sstream>
19 #include <string>
20 #include <vector>
21 #include "ecmascript/base/number_helper.h"
22 #include "ecmascript/base/string_helper.h"
23 #include "ecmascript/ecma_macros.h"
24 #include "ecmascript/internal_call_params.h"
25 #include "ecmascript/interpreter/slow_runtime_helper.h"
26 #include "ecmascript/js_invoker.h"
27 #include "ecmascript/mem/c_containers.h"
28 #include "ecmascript/tagged_array-inl.h"
29 
30 namespace panda::ecmascript::builtins {
31 using NumberHelper = base::NumberHelper;
32 using StringHelper = base::StringHelper;
33 
34 // 18.2.1
NotSupportEval(EcmaRuntimeCallInfo * msg)35 JSTaggedValue BuiltinsGlobal::NotSupportEval(EcmaRuntimeCallInfo *msg)
36 {
37     JSThread *thread = msg->GetThread();
38     [[maybe_unused]] EcmaHandleScope handleScope(thread);
39     THROW_TYPE_ERROR_AND_RETURN(thread, "not support eval()", JSTaggedValue::Exception());
40 }
41 
42 // 18.2.2
IsFinite(EcmaRuntimeCallInfo * msg)43 JSTaggedValue BuiltinsGlobal::IsFinite(EcmaRuntimeCallInfo *msg)
44 {
45     ASSERT(msg);
46     JSThread *thread = msg->GetThread();
47     BUILTINS_API_TRACE(thread, Global, IsFinite);
48     [[maybe_unused]] EcmaHandleScope handleScope(thread);
49     JSHandle<JSTaggedValue> numberInput = GetCallArg(msg, 0);
50     // 1. Let num be ToNumber(number).
51     JSTaggedNumber number = JSTaggedValue::ToNumber(thread, numberInput);
52     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
53     // 3. If num is NaN, +Infiniteļ‚„, or -Infinite, return false.
54     // 4. Otherwise, return true.
55     if (std::isfinite(number.GetNumber())) {
56         return GetTaggedBoolean(true);
57     }
58     return GetTaggedBoolean(false);
59 }
60 
61 // 18.2.3
IsNaN(EcmaRuntimeCallInfo * msg)62 JSTaggedValue BuiltinsGlobal::IsNaN(EcmaRuntimeCallInfo *msg)
63 {
64     ASSERT(msg);
65     JSThread *thread = msg->GetThread();
66     BUILTINS_API_TRACE(thread, Global, IsNaN);
67     [[maybe_unused]] EcmaHandleScope handleScope(thread);
68     JSHandle<JSTaggedValue> numberInput = GetCallArg(msg, 0);
69     // 1. Let num be ToNumber(number).
70     JSTaggedNumber number = JSTaggedValue::ToNumber(thread, numberInput);
71     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
72 
73     // 3. If num is NaN, return true.
74     if (std::isnan(number.GetNumber())) {
75         return GetTaggedBoolean(true);
76     }
77     // 4. Otherwise, return false.
78     return GetTaggedBoolean(false);
79 }
80 
IsUnescapedURI(uint16_t ch)81 bool BuiltinsGlobal::IsUnescapedURI(uint16_t ch)
82 {
83     if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9')) {
84         return true;
85     }
86     return IsInMarkURISet(ch);
87 }
88 
IsInUnescapedURISet(uint16_t ch)89 bool BuiltinsGlobal::IsInUnescapedURISet(uint16_t ch)
90 {
91     if (ch == '#') {
92         return true;
93     }
94     return IsUnescapedURI(ch) || IsReservedURI(ch);
95 }
96 
IsInReservedURISet(uint16_t ch)97 bool BuiltinsGlobal::IsInReservedURISet(uint16_t ch)
98 {
99     if (ch == '#') {
100         return true;
101     }
102     return IsReservedURI(ch);
103 }
104 
IsReservedURI(uint16_t ch)105 bool BuiltinsGlobal::IsReservedURI(uint16_t ch)
106 {
107     std::u16string str(u";/?:@&=+$,");
108     std::u16string::size_type index = str.find(ch);
109     return (index != std::u16string::npos);
110 }
111 
IsInMarkURISet(uint16_t ch)112 bool BuiltinsGlobal::IsInMarkURISet(uint16_t ch)
113 {
114     std::u16string str(u"-_.!~*'()");
115     std::u16string::size_type index = str.find(ch);
116     return (index != std::u16string::npos);
117 }
118 
IsHexDigits(uint16_t ch)119 bool BuiltinsGlobal::IsHexDigits(uint16_t ch)
120 {
121     return (ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'F') || (ch >= 'a' && ch <= 'f');
122 }
123 
124 // 18.2.6
DecodeURI(EcmaRuntimeCallInfo * msg)125 JSTaggedValue BuiltinsGlobal::DecodeURI(EcmaRuntimeCallInfo *msg)
126 {
127     ASSERT(msg);
128     JSThread *thread = msg->GetThread();
129     BUILTINS_API_TRACE(thread, Global, DecodeURI);
130     [[maybe_unused]] EcmaHandleScope handleScope(thread);
131     // 1. Let uriString be ToString(encodedURI).
132     // 2. ReturnIfAbrupt(uriString).
133     [[maybe_unused]] JSHandle<EcmaString> uriString = JSTaggedValue::ToString(thread, GetCallArg(msg, 0));
134     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
135 
136     // 3. Let reservedURISet be a String containing one instance of each code unit valid in uriReserved plus "#".
137     // 4. Return Decode(uriString, reservedURISet).
138     return Decode(thread, uriString, IsInReservedURISet);
139 }
140 
EncodeURI(EcmaRuntimeCallInfo * msg)141 JSTaggedValue BuiltinsGlobal::EncodeURI(EcmaRuntimeCallInfo *msg)
142 {
143     ASSERT(msg);
144     JSThread *thread = msg->GetThread();
145     BUILTINS_API_TRACE(thread, Global, EncodeURI);
146     [[maybe_unused]] EcmaHandleScope handleScope(thread);
147     // 1. Let uriString be ToString(uri).
148     // 2. ReturnIfAbrupt(uriString).
149     [[maybe_unused]] JSHandle<EcmaString> uriString = JSTaggedValue::ToString(thread, GetCallArg(msg, 0));
150     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
151 
152     // 3. Let unescapedURISet be a String containing one instance of
153     //    each code unit valid in uriReserved and uriUnescaped plus "#".
154     // 4. Return Encode(uriString, unescapedURISet).
155     return Encode(thread, uriString, IsInUnescapedURISet);
156 }
157 
DecodeURIComponent(EcmaRuntimeCallInfo * msg)158 JSTaggedValue BuiltinsGlobal::DecodeURIComponent(EcmaRuntimeCallInfo *msg)
159 {
160     ASSERT(msg);
161     JSThread *thread = msg->GetThread();
162     BUILTINS_API_TRACE(thread, Global, DecodeURIComponent);
163     [[maybe_unused]] EcmaHandleScope handleScope(thread);
164     // 1. Let componentString be ToString(encodedURIComponent).
165     // 2. ReturnIfAbrupt(componentString).
166     [[maybe_unused]] JSHandle<EcmaString> componentString = JSTaggedValue::ToString(thread, GetCallArg(msg, 0));
167     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
168 
169     // 3. Let reservedURIComponentSet be the empty String.
170     // 4. Return Decode(componentString, reservedURIComponentSet).
171     return Decode(thread, componentString, []([[maybe_unused]] uint16_t unused) { return false; });
172 }
173 
EncodeURIComponent(EcmaRuntimeCallInfo * msg)174 JSTaggedValue BuiltinsGlobal::EncodeURIComponent(EcmaRuntimeCallInfo *msg)
175 {
176     ASSERT(msg);
177     JSThread *thread = msg->GetThread();
178     BUILTINS_API_TRACE(thread, Global, EncodeURIComponent);
179     [[maybe_unused]] EcmaHandleScope handleScope(thread);
180     // 1. Let componentString be ToString(uriComponent).
181     // 2. ReturnIfAbrupt(componentString).
182     [[maybe_unused]] JSHandle<EcmaString> componentString = JSTaggedValue::ToString(thread, GetCallArg(msg, 0));
183     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
184 
185     // 3. Let unescapedURIComponentSet be a String containing one instance of each code unit valid in uriUnescaped.
186     // 4. Return Encode(componentString, unescapedURIComponentSet).
187     return Encode(thread, componentString, IsUnescapedURI);
188 }
189 
190 // Runtime Semantics
Encode(JSThread * thread,const JSHandle<EcmaString> & str,judgURIFunc IsInURISet)191 JSTaggedValue BuiltinsGlobal::Encode(JSThread *thread, const JSHandle<EcmaString> &str, judgURIFunc IsInURISet)
192 {
193     // 1. Let strLen be the number of code units in string.
194     uint32_t strLen = str->GetLength();
195     // 2. Let R be the empty String.
196     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
197     std::u16string resStr;
198 
199     // 3. Let k be 0.
200     // 4. Repeat
201     uint32_t k = 0;
202     while (true) {
203         // a. If k equals strLen, return R.
204         if (k == strLen) {
205             auto *uint16tData = reinterpret_cast<uint16_t *>(resStr.data());
206             int32_t resSize = resStr.size();
207             return factory->NewFromUtf16Literal(uint16tData, resSize).GetTaggedValue();
208         }
209 
210         // b. Let C be the code unit at index k within string.
211         // c. If C is in unescapedSet, then
212         //   i. Let S be a String containing only the code unit C.
213         //   ii. Let R be a new String value computed by concatenating the previous value of R and S.
214         // d. Else C is not in unescapedSet,
215         uint16_t cc = str->At(k);
216         if (IsInURISet(cc)) {
217             std::u16string sStr = StringHelper::Utf16ToU16String(&cc, 1);
218             resStr.append(sStr);
219         } else {
220             // i. If the code unit value of C is not less than 0xDC00 and not greater than 0xDFFF,
221             //    throw a URIError exception.
222             if (cc >= base::utf_helper::DECODE_TRAIL_LOW && cc <= base::utf_helper::DECODE_TRAIL_HIGH) {
223                 THROW_URI_ERROR_AND_RETURN(thread, "EncodeURI: The format of the URI to be parsed is incorrect",
224                                            JSTaggedValue::Exception());
225             }
226 
227             // ii. If the code unit value of C is less than 0xD800 or greater than 0xDBFF, then
228             //    1. Let V be the code unit value of C.
229             // iii. Else,
230             //    1. Increase k by 1.
231             //    2. If k equals strLen, throw a URIError exception.
232             //    3. Let kChar be the code unit value of the code unit at index k within string.
233             //    4. If kChar is less than 0xDC00 or greater than 0xDFFF, throw a URIError exception.
234             //    5. Let V be UTF16Decode(C, kChar).
235             uint32_t vv;
236             if (cc < base::utf_helper::DECODE_LEAD_LOW || cc > base::utf_helper::DECODE_LEAD_HIGH) {
237                 vv = cc;
238             } else {
239                 k++;
240                 if (k == strLen) {
241                     THROW_URI_ERROR_AND_RETURN(thread, "k is invalid", JSTaggedValue::Exception());
242                 }
243                 uint16_t kc = str->At(k);
244                 if (kc < base::utf_helper::DECODE_TRAIL_LOW || kc > base::utf_helper::DECODE_TRAIL_HIGH) {
245                     THROW_URI_ERROR_AND_RETURN(thread, "EncodeURI: The format of the URI to be parsed is incorrect",
246                                                JSTaggedValue::Exception());
247                 }
248                 vv = base::utf_helper::UTF16Decode(cc, kc);
249             }
250 
251             // iv. Let Octets be the array of octets resulting by applying the UTF-8 transformation to V,
252             //     and let L be the array size.
253             // v. Let j be 0.
254             // vi. Repeat, while j < L
255             //    1. Let jOctet be the value at index j within Octets.
256             //    2. Let S be a String containing three code units "%XY" where XY are two uppercase hexadecimal
257             //       digits encoding the value of jOctet.
258             //    3. Let R be a new String value computed by concatenating the previous value of R and S.
259             //    4. Increase j by 1.
260             std::string oct = StringHelper::Utf32ToString(vv);
261             std::string hexStr("0123456789ABCDEF");
262 
263             uint32_t length = oct.length();
264             std::stringstream tmpStr;
265             for (uint32_t j = 0; j < length; j++) {
266                 uint8_t joct = oct.at(j);
267                 tmpStr << '%' << hexStr.at((joct >> 4U) & BIT_MASK)  // NOLINT
268                        << hexStr.at(joct & BIT_MASK);                // 4: means shift right by 4 digits
269             }
270             resStr.append(StringHelper::StringToU16string(tmpStr.str()));
271         }
272 
273         // e. Increase k by 1.
274         k++;
275     }
276 }
277 
GetValueFromTwoHex(uint16_t front,uint16_t behind)278 uint8_t BuiltinsGlobal::GetValueFromTwoHex(uint16_t front, uint16_t behind)
279 {
280     ASSERT(IsHexDigits(front) && IsHexDigits(behind));
281     std::u16string hexString(u"0123456789ABCDEF");
282 
283     size_t idxf = StringHelper::FindFromU16ToUpper(hexString, &front);
284     size_t idxb = StringHelper::FindFromU16ToUpper(hexString, &behind);
285     uint8_t res = ((idxf << 4U) | idxb) & BIT_MASK_FF;  // NOLINT 4: means shift left by 4 digits
286     return res;
287 }
288 
289 // Runtime Semantics
Decode(JSThread * thread,const JSHandle<EcmaString> & str,judgURIFunc IsInURISet)290 JSTaggedValue BuiltinsGlobal::Decode(JSThread *thread, const JSHandle<EcmaString> &str, judgURIFunc IsInURISet)
291 {
292     // 1. Let strLen be the number of code units in string.
293     [[maybe_unused]] uint32_t strLen = str->GetLength();
294     // 2. Let R be the empty String.
295     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
296     std::u16string resStr;
297 
298     // 3. Let k be 0.
299     // 4. Repeat
300     uint32_t k = 0;
301     while (true) {
302         // a. If k equals strLen, return R.
303         if (k == strLen) {
304             auto *uint16tData = reinterpret_cast<uint16_t *>(resStr.data());
305             int32_t resSize = resStr.size();
306             return factory->NewFromUtf16Literal(uint16tData, resSize).GetTaggedValue();
307         }
308 
309         // b. Let C be the code unit at index k within string.
310         // c. If C is not "%", then
311         //    i. Let S be the String containing only the code unit C.
312         // d. Else C is "%",
313         //   i. Let start be k.
314         //   iv. Let B be the 8-bit value represented by the two hexadecimal digits at index (k + 1) and (k + 2).
315         //   v. Increment k by 2.
316         //   vi. If the most significant bit in B is 0, then
317         //      1. Let C be the code unit with code unit value B.
318         //      2. If C is not in reservedSet, then
319         //         a. Let S be the String containing only the code unit C.
320         //      3. Else C is in reservedSet,
321         //         a. Let S be the substring of string from index start to index k inclusive.
322         uint16_t cc = str->At(k);
323         std::u16string sStr;
324         if (cc != '%') {
325             if (cc == 0 && strLen == 1) {
326                 JSHandle<EcmaString> tmpEcmaString = factory->NewFromUtf16Literal(&cc, 1);
327                 return tmpEcmaString.GetTaggedValue();
328             }
329             sStr = StringHelper::Utf16ToU16String(&cc, 1);
330         } else {
331             [[maybe_unused]] uint32_t start = k;
332 
333             // ii. If k + 2 is greater than or equal to strLen, throw a URIError exception.
334             // iii. If the code units at index (k+1) and (k + 2) within string do not represent hexadecimal digits,
335             //      throw a URIError exception.
336             if ((k + 2) >= strLen) {  // 2: means plus 2
337                 THROW_URI_ERROR_AND_RETURN(thread, "DecodeURI: The format of the URI to be parsed is incorrect",
338                                            JSTaggedValue::Exception());
339             }
340             if (!(IsHexDigits(str->At(k + 1)) && IsHexDigits(str->At(k + 2)))) {  // 2: means plus 2
341                 THROW_URI_ERROR_AND_RETURN(thread, "DecodeURI: The format of the URI to be parsed is incorrect",
342                                            JSTaggedValue::Exception());
343             }
344 
345             uint16_t frontChar = str->At(k + 1);
346             uint16_t behindChar = str->At(k + 2);  // 2: means plus 2
347             uint8_t bb = GetValueFromTwoHex(frontChar, behindChar);
348             k += 2;  // 2: means plus 2
349             if ((bb & BIT_MASK_ONE) == 0) {
350                 if (!IsInURISet(bb)) {
351                     sStr = StringHelper::Utf8ToU16String(&bb, 1);
352                     if (bb == 0) {
353                         return factory->NewFromUtf16Literal(reinterpret_cast<uint16_t *>(sStr.data()), 1)
354                             .GetTaggedValue();
355                     }
356                 } else {
357                     sStr = StringHelper::StringToU16string(StringHelper::SubString(thread, str, start, k - start + 1));
358                 }
359             } else {
360                 // vii. Else the most significant bit in B is 1,
361                 //   1. Let n be the smallest nonnegative integer such that (B << n) & 0x80 is equal to 0.
362                 //   3. Let Octets be an array of 8-bit integers of size n.
363                 //   4. Put B into Octets at index 0.
364                 //   6. Let j be 1.
365                 //   7. Repeat, while j < n
366                 //     a. Increment k by 1.
367                 //     d. Let B be the 8-bit value represented by the two hexadecimal digits at
368                 //        index (k + 1) and (k + 2).
369                 //     f. Increment k by 2.
370                 //     g. Put B into Octets at index j.
371                 //     h. Increment j by 1.
372                 //   9. If V < 0x10000, then
373                 //     a. Let C be the code unit V.
374                 //     b. If C is not in reservedSet, then
375                 //        i. Let S be the String containing only the code unit C.
376                 //     c. Else C is in reservedSet,
377                 //        i. Let S be the substring of string from index start to index k inclusive.
378                 //   10. Else V ≄ 0x10000,
379                 //     a. Let L be (((V – 0x10000) & 0x3FF) + 0xDC00).
380                 //     b. Let H be ((((V – 0x10000) >> 10) & 0x3FF) + 0xD800).
381                 //     c. Let S be the String containing the two code units H and L.
382                 uint32_t n = 0;
383                 while ((((bb << n) & BIT_MASK_ONE) != 0)) {
384                     n++;
385                     if (n > 4) // 4 : 4 means less than 4
386                         break;
387                 }
388                 // 2. If n equals 1 or n is greater than 4, throw a URIError exception.
389                 if ((n == 1) || (n > 4)) {  // 4: means greater than 4
390                     THROW_URI_ERROR_AND_RETURN(thread, "DecodeURI: The format of the URI to be parsed is incorrect",
391                                                JSTaggedValue::Exception());
392                 }
393 
394                 std::vector<uint8_t> oct = {bb};
395 
396                 // 5. If k + (3 Ɨ (n – 1)) is greater than or equal to strLen, throw a URIError exception.
397                 if (k + (3 * (n - 1)) >= strLen) {  // 3: means multiply by 3
398                     THROW_URI_ERROR_AND_RETURN(thread, "DecodeURI: The format of the URI to be parsed is incorrect",
399                                                JSTaggedValue::Exception());
400                 }
401                 uint32_t j = 1;
402                 while (j < n) {
403                     k++;
404                     uint16_t codeUnit = str->At(k);
405                     // b. If the code unit at index k within string is not "%", throw a URIError exception.
406                     // c. If the code units at index (k +1) and (k + 2) within string do not represent hexadecimal
407                     //    digits, throw a URIError exception.
408                     if (!(codeUnit == '%')) {
409                         THROW_URI_ERROR_AND_RETURN(thread, "DecodeURI: The format of the URI to be parsed is incorrect",
410                                                    JSTaggedValue::Exception());
411                     }
412                     if (!(IsHexDigits(str->At(k + 1)) && IsHexDigits(str->At(k + 2)))) {  // 2: means plus 2
413                         THROW_URI_ERROR_AND_RETURN(thread, "DecodeURI: The format of the URI to be parsed is incorrect",
414                                                    JSTaggedValue::Exception());
415                     }
416 
417                     uint16_t frontChart = str->At(k + 1);
418                     uint16_t behindChart = str->At(k + 2);  // 2: means plus 2
419                     bb = GetValueFromTwoHex(frontChart, behindChart);
420                     // e. If the two most significant bits in B are not 10, throw a URIError exception.
421                     if (!((bb & BIT_MASK_TWO) == BIT_MASK_ONE)) {
422                         THROW_URI_ERROR_AND_RETURN(thread, "DecodeURI: The format of the URI to be parsed is incorrect",
423                                                    JSTaggedValue::Exception());
424                     }
425 
426                     k += 2;  // 2: means plus 2
427                     oct.push_back(bb);
428                     j++;
429                 }
430 
431                 // 8. Let V be the value obtained by applying the UTF-8 transformation to Octets, that is,
432                 //     from an array of octets into a 21-bit value. If Octets does not contain a valid UTF-8 encoding of
433                 //     a Unicode code point throw a URIError exception.
434                 if (!base::utf_helper::IsValidUTF8(oct)) {
435                     THROW_URI_ERROR_AND_RETURN(thread, "DecodeURI: The format of the URI to be parsed is incorrect",
436                                                JSTaggedValue::Exception());
437                 }
438                 uint32_t vv = StringHelper::Utf8ToU32String(oct);
439                 if (vv < base::utf_helper::DECODE_SECOND_FACTOR) {
440                     if (!IsInURISet(vv)) {
441                         sStr = StringHelper::Utf16ToU16String(reinterpret_cast<uint16_t *>(&vv), 1);
442                     } else {
443                         sStr =
444                             StringHelper::StringToU16string(StringHelper::SubString(thread, str, start, k - start + 1));
445                     }
446                 } else {
447                     uint16_t lv = (((vv - base::utf_helper::DECODE_SECOND_FACTOR) & BIT16_MASK) +
448                         base::utf_helper::DECODE_TRAIL_LOW);
449                     uint16_t hv = ((((vv - base::utf_helper::DECODE_SECOND_FACTOR) >> 10U) & BIT16_MASK) +  // NOLINT
450                         base::utf_helper::DECODE_LEAD_LOW);  // 10: means shift left by 10 digits
451                     sStr = StringHelper::Append(StringHelper::Utf16ToU16String(&hv, 1),
452                                                 StringHelper::Utf16ToU16String(&lv, 1));
453                 }
454             }
455         }
456         // e. Let R be a new String value computed by concatenating the previous value of R and S.
457         // f. Increase k by 1.
458         resStr.append(sStr);
459         k++;
460     }
461 }
462 
PrintString(JSThread * thread,EcmaString * string)463 void BuiltinsGlobal::PrintString([[maybe_unused]] JSThread *thread, EcmaString *string)
464 {
465     if (string == nullptr) {
466         return;
467     }
468 
469     CString buffer = ConvertToString(string);
470     std::cout << buffer;
471 }
472 
PrintEntrypoint(EcmaRuntimeCallInfo * msg)473 JSTaggedValue BuiltinsGlobal::PrintEntrypoint(EcmaRuntimeCallInfo *msg)
474 {
475     if (msg == nullptr) {
476         return JSTaggedValue::Undefined();
477     }
478     JSThread *thread = msg->GetThread();
479     [[maybe_unused]] EcmaHandleScope handleScope(thread);
480     BUILTINS_API_TRACE(thread, Global, PrintEntryPoint);
481 
482     uint32_t numArgs = msg->GetArgsNumber();
483     for (uint32_t i = 0; i < numArgs; i++) {
484         JSHandle<EcmaString> stringContent = JSTaggedValue::ToString(thread, GetCallArg(msg, i));
485         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
486         PrintString(thread, *stringContent);
487 
488         if (i != numArgs - 1) {
489             std::cout << " ";
490         }
491     }
492     std::cout << std::endl;
493     return JSTaggedValue::Undefined();
494 }
495 
CallJsBoundFunction(EcmaRuntimeCallInfo * msg)496 JSTaggedValue BuiltinsGlobal::CallJsBoundFunction(EcmaRuntimeCallInfo *msg)
497 {
498     JSThread *thread = msg->GetThread();
499     BUILTINS_API_TRACE(thread, Global, CallJsBoundFunction);
500     [[maybe_unused]] EcmaHandleScope handleScope(thread);
501     // msg contains jsfunc, this, arg1,...
502 
503     JSHandle<JSBoundFunction> boundFunc(GetConstructor(msg));
504     JSHandle<JSTaggedValue> thisObj(thread, boundFunc->GetBoundThis());
505 
506     InternalCallParams *arguments = thread->GetInternalCallParams();
507     arguments->MakeArgv(msg, 0);
508     return SlowRuntimeHelper::CallBoundFunction(thread, boundFunc, thisObj);
509 }
510 
CallJsProxy(EcmaRuntimeCallInfo * msg)511 JSTaggedValue BuiltinsGlobal::CallJsProxy(EcmaRuntimeCallInfo *msg)
512 {
513     JSThread *thread = msg->GetThread();
514     BUILTINS_API_TRACE(thread, Global, CallJsProxy);
515     [[maybe_unused]] EcmaHandleScope handleScope(thread);
516     // msg contains js_proxy, this, arg1,...
517     JSHandle<JSProxy> proxy(GetConstructor(msg));
518     if (!proxy->IsCallable()) {
519         THROW_TYPE_ERROR_AND_RETURN(thread, "Proxy target is not callable", JSTaggedValue::Undefined());
520     }
521 
522     // Calling proxy directly should transfer 'undefined' as this
523     JSHandle<JSTaggedValue> thisObj(GetThis(msg));
524 
525     JSHandle<TaggedArray> argsList = GetArgsArray(msg);
526     InternalCallParams *arguments = thread->GetInternalCallParams();
527     arguments->MakeArgList(*argsList);
528     return JSProxy::CallInternal(thread, proxy, thisObj, argsList->GetLength(), arguments->GetArgv());
529 }
530 
531 #if ECMASCRIPT_ENABLE_RUNTIME_STAT
StartRuntimeStat(EcmaRuntimeCallInfo * msg)532 JSTaggedValue BuiltinsGlobal::StartRuntimeStat(EcmaRuntimeCallInfo *msg)
533 {
534     JSThread *thread = msg->GetThread();
535     [[maybe_unused]] EcmaHandleScope handleScope(thread);
536     // start vm runtime stat statistic
537     thread->GetEcmaVM()->SetRuntimeStatEnable(true);
538     return JSTaggedValue::Undefined();
539 }
540 
StopRuntimeStat(EcmaRuntimeCallInfo * msg)541 JSTaggedValue BuiltinsGlobal::StopRuntimeStat(EcmaRuntimeCallInfo *msg)
542 {
543     JSThread *thread = msg->GetThread();
544     [[maybe_unused]] EcmaHandleScope handleScope(thread);
545     // start vm runtime stat statistic
546     thread->GetEcmaVM()->SetRuntimeStatEnable(false);
547     return JSTaggedValue::Undefined();
548 }
549 #endif
550 }  // namespace panda::ecmascript::builtins
551