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