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