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