14514f5e3Sopenharmony_ci/*
24514f5e3Sopenharmony_ci * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License.
54514f5e3Sopenharmony_ci * You may obtain a copy of the License at
64514f5e3Sopenharmony_ci *
74514f5e3Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
84514f5e3Sopenharmony_ci *
94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and
134514f5e3Sopenharmony_ci * limitations under the License.
144514f5e3Sopenharmony_ci */
154514f5e3Sopenharmony_ci
164514f5e3Sopenharmony_ci#include "ecmascript/builtins/builtins_global.h"
174514f5e3Sopenharmony_ci
184514f5e3Sopenharmony_ci#include <random>
194514f5e3Sopenharmony_ci#include <sstream>
204514f5e3Sopenharmony_ci#include <string>
214514f5e3Sopenharmony_ci#include <vector>
224514f5e3Sopenharmony_ci
234514f5e3Sopenharmony_ci#include "ecmascript/interpreter/interpreter.h"
244514f5e3Sopenharmony_ci#include "ecmascript/js_object-inl.h"
254514f5e3Sopenharmony_ci#include "ecmascript/module/js_module_deregister.h"
264514f5e3Sopenharmony_ci#include "ecmascript/module/module_path_helper.h"
274514f5e3Sopenharmony_ci#include "ecmascript/stubs/runtime_stubs.h"
284514f5e3Sopenharmony_ci#include "ecmascript/containers/containers_errors.h"
294514f5e3Sopenharmony_ci#include "ecmascript/jspandafile/js_pandafile_manager.h"
304514f5e3Sopenharmony_ci#include "ecmascript/module/js_module_manager.h"
314514f5e3Sopenharmony_ci
324514f5e3Sopenharmony_cinamespace panda::ecmascript::builtins {
334514f5e3Sopenharmony_ciusing NumberHelper = base::NumberHelper;
344514f5e3Sopenharmony_ciusing StringHelper = base::StringHelper;
354514f5e3Sopenharmony_ciusing GlobalError = containers::ContainerError;
364514f5e3Sopenharmony_ci// bitmap for "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_" + "@*+-./"
374514f5e3Sopenharmony_ciconstexpr std::uint8_t ESCAPE_BIT_MAP[128] = {
384514f5e3Sopenharmony_ci    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
394514f5e3Sopenharmony_ci    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
404514f5e3Sopenharmony_ci    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1,
414514f5e3Sopenharmony_ci    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
424514f5e3Sopenharmony_ci    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
434514f5e3Sopenharmony_ci    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,
444514f5e3Sopenharmony_ci    0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
454514f5e3Sopenharmony_ci    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0};
464514f5e3Sopenharmony_ciconstexpr std::uint8_t ESCAPE_HEX_TO_CHAR[16] = {
474514f5e3Sopenharmony_ci    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
484514f5e3Sopenharmony_ci};
494514f5e3Sopenharmony_ciconstexpr std::uint8_t ESCAPE_CHAR_TO_HEX[128] = {
504514f5e3Sopenharmony_ci    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
514514f5e3Sopenharmony_ci    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
524514f5e3Sopenharmony_ci    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
534514f5e3Sopenharmony_ci    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0,
544514f5e3Sopenharmony_ci    0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0,
554514f5e3Sopenharmony_ci    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
564514f5e3Sopenharmony_ci    0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0,
574514f5e3Sopenharmony_ci    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
584514f5e3Sopenharmony_ci};
594514f5e3Sopenharmony_ciconstexpr std::uint8_t ESCAPE_HEX_MASK = 0xf;
604514f5e3Sopenharmony_ciconstexpr std::uint8_t ESCAPE_HEX_BIT4 = 4;
614514f5e3Sopenharmony_ciconstexpr std::uint8_t ESCAPE_HEX_BIT8 = 8;
624514f5e3Sopenharmony_ciconstexpr std::uint8_t ESCAPE_HEX_BIT12 = 12;
634514f5e3Sopenharmony_ciconstexpr std::uint8_t ESCAPE_CHAR_OFFSET2 = 2;
644514f5e3Sopenharmony_ciconstexpr std::uint8_t ESCAPE_CHAR_OFFSET3 = 3;
654514f5e3Sopenharmony_ciconstexpr std::uint8_t ESCAPE_CHAR_OFFSET4 = 4;
664514f5e3Sopenharmony_ciconstexpr std::uint8_t ESCAPE_CHAR_OFFSET5 = 5;
674514f5e3Sopenharmony_ciconstexpr std::uint16_t CHAR16_LETTER_NULL = u'\0';
684514f5e3Sopenharmony_ci
694514f5e3Sopenharmony_ci// 18.2.1
704514f5e3Sopenharmony_ciJSTaggedValue BuiltinsGlobal::NotSupportEval(EcmaRuntimeCallInfo *msg)
714514f5e3Sopenharmony_ci{
724514f5e3Sopenharmony_ci    JSThread *thread = msg->GetThread();
734514f5e3Sopenharmony_ci    BUILTINS_API_TRACE(thread, Global, NotSupportEval);
744514f5e3Sopenharmony_ci    [[maybe_unused]] EcmaHandleScope handleScope(thread);
754514f5e3Sopenharmony_ci    THROW_TYPE_ERROR_AND_RETURN(thread, "not support eval()", JSTaggedValue::Exception());
764514f5e3Sopenharmony_ci}
774514f5e3Sopenharmony_ci
784514f5e3Sopenharmony_ci// 18.2.2
794514f5e3Sopenharmony_ciJSTaggedValue BuiltinsGlobal::IsFinite(EcmaRuntimeCallInfo *msg)
804514f5e3Sopenharmony_ci{
814514f5e3Sopenharmony_ci    ASSERT(msg);
824514f5e3Sopenharmony_ci    JSThread *thread = msg->GetThread();
834514f5e3Sopenharmony_ci    BUILTINS_API_TRACE(thread, Global, IsFinite);
844514f5e3Sopenharmony_ci    [[maybe_unused]] EcmaHandleScope handleScope(thread);
854514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> numberInput = GetCallArg(msg, 0);
864514f5e3Sopenharmony_ci    // 1. Let num be ToNumber(number).
874514f5e3Sopenharmony_ci    JSTaggedNumber number = JSTaggedValue::ToNumber(thread, numberInput);
884514f5e3Sopenharmony_ci    RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
894514f5e3Sopenharmony_ci    // 3. If num is NaN, +Infinite, or -Infinite, return false.
904514f5e3Sopenharmony_ci    // 4. Otherwise, return true.
914514f5e3Sopenharmony_ci    if (std::isfinite(number.GetNumber())) {
924514f5e3Sopenharmony_ci        return GetTaggedBoolean(true);
934514f5e3Sopenharmony_ci    }
944514f5e3Sopenharmony_ci    return GetTaggedBoolean(false);
954514f5e3Sopenharmony_ci}
964514f5e3Sopenharmony_ci
974514f5e3Sopenharmony_ci// 18.2.3
984514f5e3Sopenharmony_ciJSTaggedValue BuiltinsGlobal::IsNaN(EcmaRuntimeCallInfo *msg)
994514f5e3Sopenharmony_ci{
1004514f5e3Sopenharmony_ci    ASSERT(msg);
1014514f5e3Sopenharmony_ci    JSThread *thread = msg->GetThread();
1024514f5e3Sopenharmony_ci    BUILTINS_API_TRACE(thread, Global, IsNaN);
1034514f5e3Sopenharmony_ci    [[maybe_unused]] EcmaHandleScope handleScope(thread);
1044514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> numberInput = GetCallArg(msg, 0);
1054514f5e3Sopenharmony_ci    // 1. Let num be ToNumber(number).
1064514f5e3Sopenharmony_ci    JSTaggedNumber number = JSTaggedValue::ToNumber(thread, numberInput);
1074514f5e3Sopenharmony_ci    RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1084514f5e3Sopenharmony_ci
1094514f5e3Sopenharmony_ci    // 3. If num is NaN, return true.
1104514f5e3Sopenharmony_ci    if (std::isnan(number.GetNumber())) {
1114514f5e3Sopenharmony_ci        return GetTaggedBoolean(true);
1124514f5e3Sopenharmony_ci    }
1134514f5e3Sopenharmony_ci    // 4. Otherwise, return false.
1144514f5e3Sopenharmony_ci    return GetTaggedBoolean(false);
1154514f5e3Sopenharmony_ci}
1164514f5e3Sopenharmony_ci
1174514f5e3Sopenharmony_cibool BuiltinsGlobal::IsUnescapedURI(uint16_t ch)
1184514f5e3Sopenharmony_ci{
1194514f5e3Sopenharmony_ci    if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9')) {
1204514f5e3Sopenharmony_ci        return true;
1214514f5e3Sopenharmony_ci    }
1224514f5e3Sopenharmony_ci    return IsInMarkURISet(ch);
1234514f5e3Sopenharmony_ci}
1244514f5e3Sopenharmony_ci
1254514f5e3Sopenharmony_cibool BuiltinsGlobal::IsInUnescapedURISet(uint16_t ch)
1264514f5e3Sopenharmony_ci{
1274514f5e3Sopenharmony_ci    if (ch == '#') {
1284514f5e3Sopenharmony_ci        return true;
1294514f5e3Sopenharmony_ci    }
1304514f5e3Sopenharmony_ci    return IsUnescapedURI(ch) || IsReservedURI(ch);
1314514f5e3Sopenharmony_ci}
1324514f5e3Sopenharmony_ci
1334514f5e3Sopenharmony_cibool BuiltinsGlobal::IsInReservedURISet(uint16_t ch)
1344514f5e3Sopenharmony_ci{
1354514f5e3Sopenharmony_ci    if (ch == '#') {
1364514f5e3Sopenharmony_ci        return true;
1374514f5e3Sopenharmony_ci    }
1384514f5e3Sopenharmony_ci    return IsReservedURI(ch);
1394514f5e3Sopenharmony_ci}
1404514f5e3Sopenharmony_ci
1414514f5e3Sopenharmony_cibool BuiltinsGlobal::IsReservedURI(uint16_t ch)
1424514f5e3Sopenharmony_ci{
1434514f5e3Sopenharmony_ci    std::u16string str(u";/?:@&=+$,");
1444514f5e3Sopenharmony_ci    std::u16string::size_type index = str.find(ch);
1454514f5e3Sopenharmony_ci    return (index != std::u16string::npos);
1464514f5e3Sopenharmony_ci}
1474514f5e3Sopenharmony_ci
1484514f5e3Sopenharmony_cibool BuiltinsGlobal::IsInMarkURISet(uint16_t ch)
1494514f5e3Sopenharmony_ci{
1504514f5e3Sopenharmony_ci    std::u16string str(u"-_.!~*'()");
1514514f5e3Sopenharmony_ci    std::u16string::size_type index = str.find(ch);
1524514f5e3Sopenharmony_ci    return (index != std::u16string::npos);
1534514f5e3Sopenharmony_ci}
1544514f5e3Sopenharmony_ci
1554514f5e3Sopenharmony_cibool BuiltinsGlobal::IsHexDigits(uint16_t ch)
1564514f5e3Sopenharmony_ci{
1574514f5e3Sopenharmony_ci    return (ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'F') || (ch >= 'a' && ch <= 'f');
1584514f5e3Sopenharmony_ci}
1594514f5e3Sopenharmony_ci
1604514f5e3Sopenharmony_ci// 18.2.6
1614514f5e3Sopenharmony_ciJSTaggedValue BuiltinsGlobal::DecodeURI(EcmaRuntimeCallInfo *msg)
1624514f5e3Sopenharmony_ci{
1634514f5e3Sopenharmony_ci    ASSERT(msg);
1644514f5e3Sopenharmony_ci    JSThread *thread = msg->GetThread();
1654514f5e3Sopenharmony_ci    BUILTINS_API_TRACE(thread, Global, DecodeURI);
1664514f5e3Sopenharmony_ci    [[maybe_unused]] EcmaHandleScope handleScope(thread);
1674514f5e3Sopenharmony_ci    // 1. Let uriString be ToString(encodedURI).
1684514f5e3Sopenharmony_ci    // 2. ReturnIfAbrupt(uriString).
1694514f5e3Sopenharmony_ci    JSHandle<EcmaString> uriString = JSTaggedValue::ToString(thread, GetCallArg(msg, 0));
1704514f5e3Sopenharmony_ci    RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1714514f5e3Sopenharmony_ci
1724514f5e3Sopenharmony_ci    // 3. Let reservedURISet be a String containing one instance of each code unit valid in uriReserved plus "#".
1734514f5e3Sopenharmony_ci    // 4. Return Decode(uriString, reservedURISet).
1744514f5e3Sopenharmony_ci    return Decode(thread, uriString, IsInReservedURISet);
1754514f5e3Sopenharmony_ci}
1764514f5e3Sopenharmony_ci
1774514f5e3Sopenharmony_ciJSTaggedValue BuiltinsGlobal::EncodeURI(EcmaRuntimeCallInfo *msg)
1784514f5e3Sopenharmony_ci{
1794514f5e3Sopenharmony_ci    ASSERT(msg);
1804514f5e3Sopenharmony_ci    JSThread *thread = msg->GetThread();
1814514f5e3Sopenharmony_ci    BUILTINS_API_TRACE(thread, Global, EncodeURI);
1824514f5e3Sopenharmony_ci    [[maybe_unused]] EcmaHandleScope handleScope(thread);
1834514f5e3Sopenharmony_ci    // 1. Let uriString be ToString(uri).
1844514f5e3Sopenharmony_ci    // 2. ReturnIfAbrupt(uriString).
1854514f5e3Sopenharmony_ci    JSHandle<EcmaString> uriString = JSTaggedValue::ToString(thread, GetCallArg(msg, 0));
1864514f5e3Sopenharmony_ci    RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1874514f5e3Sopenharmony_ci
1884514f5e3Sopenharmony_ci    // 3. Let unescapedURISet be a String containing one instance of
1894514f5e3Sopenharmony_ci    //    each code unit valid in uriReserved and uriUnescaped plus "#".
1904514f5e3Sopenharmony_ci    // 4. Return Encode(uriString, unescapedURISet).
1914514f5e3Sopenharmony_ci    return Encode(thread, uriString, IsInUnescapedURISet);
1924514f5e3Sopenharmony_ci}
1934514f5e3Sopenharmony_ci
1944514f5e3Sopenharmony_ciJSTaggedValue BuiltinsGlobal::DecodeURIComponent(EcmaRuntimeCallInfo *msg)
1954514f5e3Sopenharmony_ci{
1964514f5e3Sopenharmony_ci    ASSERT(msg);
1974514f5e3Sopenharmony_ci    JSThread *thread = msg->GetThread();
1984514f5e3Sopenharmony_ci    BUILTINS_API_TRACE(thread, Global, DecodeURIComponent);
1994514f5e3Sopenharmony_ci    [[maybe_unused]] EcmaHandleScope handleScope(thread);
2004514f5e3Sopenharmony_ci    // 1. Let componentString be ToString(encodedURIComponent).
2014514f5e3Sopenharmony_ci    // 2. ReturnIfAbrupt(componentString).
2024514f5e3Sopenharmony_ci    JSHandle<EcmaString> componentString = JSTaggedValue::ToString(thread, GetCallArg(msg, 0));
2034514f5e3Sopenharmony_ci    RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2044514f5e3Sopenharmony_ci
2054514f5e3Sopenharmony_ci    // 3. Let reservedURIComponentSet be the empty String.
2064514f5e3Sopenharmony_ci    // 4. Return Decode(componentString, reservedURIComponentSet).
2074514f5e3Sopenharmony_ci    return Decode(thread, componentString, []([[maybe_unused]] uint16_t unused) { return false; });
2084514f5e3Sopenharmony_ci}
2094514f5e3Sopenharmony_ci
2104514f5e3Sopenharmony_ciJSTaggedValue BuiltinsGlobal::EncodeURIComponent(EcmaRuntimeCallInfo *msg)
2114514f5e3Sopenharmony_ci{
2124514f5e3Sopenharmony_ci    ASSERT(msg);
2134514f5e3Sopenharmony_ci    JSThread *thread = msg->GetThread();
2144514f5e3Sopenharmony_ci    BUILTINS_API_TRACE(thread, Global, EncodeURIComponent);
2154514f5e3Sopenharmony_ci    [[maybe_unused]] EcmaHandleScope handleScope(thread);
2164514f5e3Sopenharmony_ci    // 1. Let componentString be ToString(uriComponent).
2174514f5e3Sopenharmony_ci    // 2. ReturnIfAbrupt(componentString).
2184514f5e3Sopenharmony_ci    JSHandle<EcmaString> componentString = JSTaggedValue::ToString(thread, GetCallArg(msg, 0));
2194514f5e3Sopenharmony_ci    RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2204514f5e3Sopenharmony_ci
2214514f5e3Sopenharmony_ci    // 3. Let unescapedURIComponentSet be a String containing one instance of each code unit valid in uriUnescaped.
2224514f5e3Sopenharmony_ci    // 4. Return Encode(componentString, unescapedURIComponentSet).
2234514f5e3Sopenharmony_ci    return Encode(thread, componentString, IsUnescapedURI);
2244514f5e3Sopenharmony_ci}
2254514f5e3Sopenharmony_ci
2264514f5e3Sopenharmony_ci// Runtime Semantics
2274514f5e3Sopenharmony_ciJSTaggedValue BuiltinsGlobal::Encode(JSThread *thread, const JSHandle<EcmaString> &str, judgURIFunc IsInURISet)
2284514f5e3Sopenharmony_ci{
2294514f5e3Sopenharmony_ci    BUILTINS_API_TRACE(thread, Global, Encode);
2304514f5e3Sopenharmony_ci    // 1. Let strLen be the number of code units in string.
2314514f5e3Sopenharmony_ci    CString errorMsg;
2324514f5e3Sopenharmony_ci    uint32_t strLen = EcmaStringAccessor(str).GetLength();
2334514f5e3Sopenharmony_ci    // 2. Let R be the empty String.
2344514f5e3Sopenharmony_ci    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
2354514f5e3Sopenharmony_ci    std::u16string resStr;
2364514f5e3Sopenharmony_ci    JSHandle<EcmaString> string = str;
2374514f5e3Sopenharmony_ci    if (EcmaStringAccessor(str).IsTreeString()) {
2384514f5e3Sopenharmony_ci        string = JSHandle<EcmaString>(thread, EcmaStringAccessor::Flatten(thread->GetEcmaVM(), str));
2394514f5e3Sopenharmony_ci    }
2404514f5e3Sopenharmony_ci    // 3. Let k be 0.
2414514f5e3Sopenharmony_ci    // 4. Repeat
2424514f5e3Sopenharmony_ci    uint32_t k = 0;
2434514f5e3Sopenharmony_ci    while (true) {
2444514f5e3Sopenharmony_ci        // a. If k equals strLen, return R.
2454514f5e3Sopenharmony_ci        if (k == strLen) {
2464514f5e3Sopenharmony_ci            auto *uint16tData = reinterpret_cast<uint16_t *>(resStr.data());
2474514f5e3Sopenharmony_ci            uint32_t resSize = resStr.size();
2484514f5e3Sopenharmony_ci            return factory->NewFromUtf16Literal(uint16tData, resSize).GetTaggedValue();
2494514f5e3Sopenharmony_ci        }
2504514f5e3Sopenharmony_ci
2514514f5e3Sopenharmony_ci        // b. Let C be the code unit at index k within string.
2524514f5e3Sopenharmony_ci        // c. If C is in unescapedSet, then
2534514f5e3Sopenharmony_ci        //   i. Let S be a String containing only the code unit C.
2544514f5e3Sopenharmony_ci        //   ii. Let R be a new String value computed by concatenating the previous value of R and S.
2554514f5e3Sopenharmony_ci        // d. Else C is not in unescapedSet,
2564514f5e3Sopenharmony_ci        uint16_t cc = EcmaStringAccessor(string).Get(k);
2574514f5e3Sopenharmony_ci        if (IsInURISet(cc)) {
2584514f5e3Sopenharmony_ci            std::u16string sStr = StringHelper::Utf16ToU16String(&cc, 1);
2594514f5e3Sopenharmony_ci            resStr.append(sStr);
2604514f5e3Sopenharmony_ci        } else {
2614514f5e3Sopenharmony_ci            // i. If the code unit value of C is not less than 0xDC00 and not greater than 0xDFFF,
2624514f5e3Sopenharmony_ci            //    throw a URIError exception.
2634514f5e3Sopenharmony_ci            if (cc >= base::utf_helper::DECODE_TRAIL_LOW && cc <= base::utf_helper::DECODE_TRAIL_HIGH) {
2644514f5e3Sopenharmony_ci                errorMsg = "DecodeURI: invalid character: " + ConvertToString(string.GetTaggedValue());
2654514f5e3Sopenharmony_ci                THROW_URI_ERROR_AND_RETURN(thread, errorMsg.c_str(), JSTaggedValue::Exception());
2664514f5e3Sopenharmony_ci            }
2674514f5e3Sopenharmony_ci
2684514f5e3Sopenharmony_ci            // ii. If the code unit value of C is less than 0xD800 or greater than 0xDBFF, then
2694514f5e3Sopenharmony_ci            //    1. Let V be the code unit value of C.
2704514f5e3Sopenharmony_ci            // iii. Else,
2714514f5e3Sopenharmony_ci            //    1. Increase k by 1.
2724514f5e3Sopenharmony_ci            //    2. If k equals strLen, throw a URIError exception.
2734514f5e3Sopenharmony_ci            //    3. Let kChar be the code unit value of the code unit at index k within string.
2744514f5e3Sopenharmony_ci            //    4. If kChar is less than 0xDC00 or greater than 0xDFFF, throw a URIError exception.
2754514f5e3Sopenharmony_ci            //    5. Let V be UTF16Decode(C, kChar).
2764514f5e3Sopenharmony_ci            uint32_t vv;
2774514f5e3Sopenharmony_ci            if (cc < base::utf_helper::DECODE_LEAD_LOW || cc > base::utf_helper::DECODE_LEAD_HIGH) {
2784514f5e3Sopenharmony_ci                vv = cc;
2794514f5e3Sopenharmony_ci            } else {
2804514f5e3Sopenharmony_ci                k++;
2814514f5e3Sopenharmony_ci                if (k == strLen) {
2824514f5e3Sopenharmony_ci                    errorMsg = "DecodeURI: invalid character: " + ConvertToString(string.GetTaggedValue());
2834514f5e3Sopenharmony_ci                    THROW_URI_ERROR_AND_RETURN(thread, errorMsg.c_str(), JSTaggedValue::Exception());
2844514f5e3Sopenharmony_ci                }
2854514f5e3Sopenharmony_ci                uint16_t kc = EcmaStringAccessor(string).Get(k);
2864514f5e3Sopenharmony_ci                if (kc < base::utf_helper::DECODE_TRAIL_LOW || kc > base::utf_helper::DECODE_TRAIL_HIGH) {
2874514f5e3Sopenharmony_ci                    errorMsg = "DecodeURI: invalid character: " + ConvertToString(string.GetTaggedValue());
2884514f5e3Sopenharmony_ci                    THROW_URI_ERROR_AND_RETURN(thread, errorMsg.c_str(), JSTaggedValue::Exception());
2894514f5e3Sopenharmony_ci                }
2904514f5e3Sopenharmony_ci                vv = base::utf_helper::UTF16Decode(cc, kc);
2914514f5e3Sopenharmony_ci            }
2924514f5e3Sopenharmony_ci
2934514f5e3Sopenharmony_ci            // iv. Let Octets be the array of octets resulting by applying the UTF-8 transformation to V,
2944514f5e3Sopenharmony_ci            //     and let L be the array size.
2954514f5e3Sopenharmony_ci            // v. Let j be 0.
2964514f5e3Sopenharmony_ci            // vi. Repeat, while j < L
2974514f5e3Sopenharmony_ci            //    1. Let jOctet be the value at index j within Octets.
2984514f5e3Sopenharmony_ci            //    2. Let S be a String containing three code units "%XY" where XY are two uppercase hexadecimal
2994514f5e3Sopenharmony_ci            //       digits encoding the value of jOctet.
3004514f5e3Sopenharmony_ci            //    3. Let R be a new String value computed by concatenating the previous value of R and S.
3014514f5e3Sopenharmony_ci            //    4. Increase j by 1.
3024514f5e3Sopenharmony_ci            std::string oct = StringHelper::Utf32ToString(vv);
3034514f5e3Sopenharmony_ci            std::string hexStr("0123456789ABCDEF");
3044514f5e3Sopenharmony_ci
3054514f5e3Sopenharmony_ci            uint32_t length = oct.length();
3064514f5e3Sopenharmony_ci            std::stringstream tmpStr;
3074514f5e3Sopenharmony_ci            for (uint32_t j = 0; j < length; j++) {
3084514f5e3Sopenharmony_ci                uint8_t joct = static_cast<uint8_t>(oct.at(j));
3094514f5e3Sopenharmony_ci                tmpStr << '%' << hexStr.at((joct >> 4U) & BIT_MASK)  // NOLINT
3104514f5e3Sopenharmony_ci                       << hexStr.at(joct & BIT_MASK);                // 4: means shift right by 4 digits
3114514f5e3Sopenharmony_ci            }
3124514f5e3Sopenharmony_ci            resStr.append(StringHelper::StringToU16string(tmpStr.str()));
3134514f5e3Sopenharmony_ci        }
3144514f5e3Sopenharmony_ci
3154514f5e3Sopenharmony_ci        // e. Increase k by 1.
3164514f5e3Sopenharmony_ci        k++;
3174514f5e3Sopenharmony_ci    }
3184514f5e3Sopenharmony_ci}
3194514f5e3Sopenharmony_ci
3204514f5e3Sopenharmony_ciuint8_t BuiltinsGlobal::GetValueFromTwoHex(uint16_t front, uint16_t behind)
3214514f5e3Sopenharmony_ci{
3224514f5e3Sopenharmony_ci    ASSERT(IsHexDigits(front) && IsHexDigits(behind));
3234514f5e3Sopenharmony_ci    std::u16string hexString(u"0123456789ABCDEF");
3244514f5e3Sopenharmony_ci
3254514f5e3Sopenharmony_ci    size_t idxf = StringHelper::FindFromU16ToUpper(hexString, &front);
3264514f5e3Sopenharmony_ci    size_t idxb = StringHelper::FindFromU16ToUpper(hexString, &behind);
3274514f5e3Sopenharmony_ci    uint8_t res = ((idxf << 4U) | idxb) & BIT_MASK_FF;  // NOLINT 4: means shift left by 4 digits
3284514f5e3Sopenharmony_ci    return res;
3294514f5e3Sopenharmony_ci}
3304514f5e3Sopenharmony_ci
3314514f5e3Sopenharmony_ciuint16_t BuiltinsGlobal::GetValueFromHexString(const JSHandle<EcmaString> &string)
3324514f5e3Sopenharmony_ci{
3334514f5e3Sopenharmony_ci    uint32_t size = EcmaStringAccessor(string).GetLength();
3344514f5e3Sopenharmony_ci    ASSERT(size > 0 && size <= 4); // NOLINT 4: means 4 hex digits
3354514f5e3Sopenharmony_ci    std::u16string hexString(u"0123456789ABCDEF");
3364514f5e3Sopenharmony_ci
3374514f5e3Sopenharmony_ci    uint16_t ret = 0;
3384514f5e3Sopenharmony_ci    for (uint32_t i = 0; i < size; ++i) {
3394514f5e3Sopenharmony_ci        uint16_t ch = EcmaStringAccessor(string).Get(i);
3404514f5e3Sopenharmony_ci        size_t idx = StringHelper::FindFromU16ToUpper(hexString, &ch);
3414514f5e3Sopenharmony_ci        ret = ((ret << 4U) | idx) & BIT_MASK_4F; // NOLINT 4: means shift left by 4
3424514f5e3Sopenharmony_ci    }
3434514f5e3Sopenharmony_ci    return ret;
3444514f5e3Sopenharmony_ci}
3454514f5e3Sopenharmony_ci
3464514f5e3Sopenharmony_ci// 22.1.3.17.2 StringPad ( S, maxLength, fillString, placement )
3474514f5e3Sopenharmony_ciEcmaString *BuiltinsGlobal::StringPad(JSThread *thread, const JSHandle<EcmaString> &source,
3484514f5e3Sopenharmony_ci                                      uint32_t maxLength, const JSHandle<EcmaString> &fillString,
3494514f5e3Sopenharmony_ci                                      Placement placement)
3504514f5e3Sopenharmony_ci{
3514514f5e3Sopenharmony_ci    // 1. Let stringLength be the length of S.
3524514f5e3Sopenharmony_ci    uint32_t stringLength = EcmaStringAccessor(source).GetLength();
3534514f5e3Sopenharmony_ci    // 2. If maxLength ≤ stringLength, return S.
3544514f5e3Sopenharmony_ci    if (maxLength <= stringLength) {
3554514f5e3Sopenharmony_ci        return *source;
3564514f5e3Sopenharmony_ci    }
3574514f5e3Sopenharmony_ci    // 3. If fillString is the empty String, return S.
3584514f5e3Sopenharmony_ci    uint32_t targetStrLen = EcmaStringAccessor(fillString).GetLength();
3594514f5e3Sopenharmony_ci    if (targetStrLen == 0) {
3604514f5e3Sopenharmony_ci        return *source;
3614514f5e3Sopenharmony_ci    }
3624514f5e3Sopenharmony_ci    // 4. Let fillLen be maxLength - stringLength.
3634514f5e3Sopenharmony_ci    uint32_t fillLen = maxLength - stringLength;
3644514f5e3Sopenharmony_ci    EcmaVM *vm = thread->GetEcmaVM();
3654514f5e3Sopenharmony_ci    //5. Let truncatedStringFiller be the String value consisting of repeated concatenations
3664514f5e3Sopenharmony_ci    // of fillString truncated to length fillLen.
3674514f5e3Sopenharmony_ci    uint32_t repeatTimes = std::ceil(fillLen / targetStrLen);
3684514f5e3Sopenharmony_ci    EcmaString *p = nullptr;
3694514f5e3Sopenharmony_ci    JSHandle<EcmaString> stringFiller = vm->GetFactory()->NewFromStdString(std::string("\0"));
3704514f5e3Sopenharmony_ci    for (uint32_t k = 0; k < repeatTimes; ++k) {
3714514f5e3Sopenharmony_ci        p = EcmaStringAccessor::Concat(vm, stringFiller, fillString);
3724514f5e3Sopenharmony_ci        stringFiller = JSHandle<EcmaString>(thread, p);
3734514f5e3Sopenharmony_ci    }
3744514f5e3Sopenharmony_ci    JSHandle<EcmaString> truncatedStringFiller(thread,
3754514f5e3Sopenharmony_ci        EcmaStringAccessor::FastSubString(vm, stringFiller, 0, fillLen));
3764514f5e3Sopenharmony_ci    // 6. If placement is start, return the string-concatenation of truncatedStringFiller and S.
3774514f5e3Sopenharmony_ci    // 7. Else, return the string-concatenation of S and truncatedStringFiller.
3784514f5e3Sopenharmony_ci    if (placement == Placement::START) {
3794514f5e3Sopenharmony_ci        return EcmaStringAccessor::Concat(vm, truncatedStringFiller, source);
3804514f5e3Sopenharmony_ci    } else {
3814514f5e3Sopenharmony_ci        return EcmaStringAccessor::Concat(vm, source, truncatedStringFiller);
3824514f5e3Sopenharmony_ci    }
3834514f5e3Sopenharmony_ci}
3844514f5e3Sopenharmony_ci
3854514f5e3Sopenharmony_ci// Static Semantics: UTF16SurrogatePairToCodePoint ( lead, trail )
3864514f5e3Sopenharmony_ciuint16_t BuiltinsGlobal::UTF16SurrogatePairToCodePoint(uint16_t lead, uint16_t trail)
3874514f5e3Sopenharmony_ci{
3884514f5e3Sopenharmony_ci    // 1. Assert: lead is a leading surrogate and trail is a trailing surrogate.
3894514f5e3Sopenharmony_ci    ASSERT(IsUTF16HighSurrogate(lead) && IsUTF16LowSurrogate(trail));
3904514f5e3Sopenharmony_ci    // 2. Let cp be (lead - 0xD800) × 0x400 + (trail - 0xDC00) + 0x10000.
3914514f5e3Sopenharmony_ci    uint16_t cp = ((lead - 0xD800) << 10UL) + (trail - 0xDC00) + 0x10000;
3924514f5e3Sopenharmony_ci    // 3. Return the code point cp.
3934514f5e3Sopenharmony_ci    return cp;
3944514f5e3Sopenharmony_ci}
3954514f5e3Sopenharmony_ci
3964514f5e3Sopenharmony_ci// 11.1.5 Static Semantics: StringToCodePoints ( string )
3974514f5e3Sopenharmony_ciEcmaString *BuiltinsGlobal::StringToCodePoints(JSThread *thread, const JSHandle<EcmaString> &string)
3984514f5e3Sopenharmony_ci{
3994514f5e3Sopenharmony_ci    // 1. Let codePoints be a new empty List.
4004514f5e3Sopenharmony_ci    std::u16string codePoints;
4014514f5e3Sopenharmony_ci    // 2. Let size be the length of string.
4024514f5e3Sopenharmony_ci    uint32_t size = EcmaStringAccessor(string).GetLength();
4034514f5e3Sopenharmony_ci    // 3. Let position be 0.
4044514f5e3Sopenharmony_ci    uint32_t position = 0;
4054514f5e3Sopenharmony_ci    // 4. Repeat, while position < size,
4064514f5e3Sopenharmony_ci    //    a. Let cp be CodePointAt(string, position).
4074514f5e3Sopenharmony_ci    //    b. Append cp.[[CodePoint]] to codePoints.
4084514f5e3Sopenharmony_ci    //    c. Set position to position + cp.[[CodeUnitCount]].
4094514f5e3Sopenharmony_ci    while (position < size) {
4104514f5e3Sopenharmony_ci        // i.Let first be the code unit at index position within string.
4114514f5e3Sopenharmony_ci        uint16_t first = EcmaStringAccessor(string).Get(position);
4124514f5e3Sopenharmony_ci        uint16_t cp = first - CHAR16_LETTER_NULL;
4134514f5e3Sopenharmony_ci        uint8_t codeUnitCount = 0;
4144514f5e3Sopenharmony_ci        bool isUnpairedSurrogate = false;
4154514f5e3Sopenharmony_ci        // ii. If first is neither a leading surrogate nor a trailing surrogate, then
4164514f5e3Sopenharmony_ci        //   a. Return the Record { [[CodePoint]]: cp, [[CodeUnitCount]]: 1, [[IsUnpairedSurrogate]]: false }.
4174514f5e3Sopenharmony_ci        if (!IsUTF16HighSurrogate(first) && !IsUTF16LowSurrogate(first)) {
4184514f5e3Sopenharmony_ci            codeUnitCount = 1; // 1 means: code unit count
4194514f5e3Sopenharmony_ci            isUnpairedSurrogate = false;
4204514f5e3Sopenharmony_ci        } else if (IsUTF16HighSurrogate(first) || position + 1 == size) {
4214514f5e3Sopenharmony_ci            // iii. If first is a trailing surrogate or position + 1 = size, then
4224514f5e3Sopenharmony_ci            //   a. Return the Record { [[CodePoint]]: cp, [[CodeUnitCount]]: 1, [[IsUnpairedSurrogate]]: true }.
4234514f5e3Sopenharmony_ci            codeUnitCount = 1;
4244514f5e3Sopenharmony_ci            isUnpairedSurrogate = true;
4254514f5e3Sopenharmony_ci        } else {
4264514f5e3Sopenharmony_ci            // iv. Let second be the code unit at index position + 1 within string.
4274514f5e3Sopenharmony_ci            uint16_t second = EcmaStringAccessor(string).Get(position + 1);
4284514f5e3Sopenharmony_ci            // v. If second is not a trailing surrogate, then
4294514f5e3Sopenharmony_ci            //   a. Return the Record { [[CodePoint]]: cp, [[CodeUnitCount]]: 1, [[IsUnpairedSurrogate]]: true }.
4304514f5e3Sopenharmony_ci            if (!IsUTF16LowSurrogate(second)) {
4314514f5e3Sopenharmony_ci                codeUnitCount = 1; // 1 means: code unit count
4324514f5e3Sopenharmony_ci                isUnpairedSurrogate = true;
4334514f5e3Sopenharmony_ci            } else {
4344514f5e3Sopenharmony_ci            // vi. Set cp to UTF16SurrogatePairToCodePoint(first, second).
4354514f5e3Sopenharmony_ci            // vii. Return the Record { [[CodePoint]]: cp, [[CodeUnitCount]]: 2, [[IsUnpairedSurrogate]]: false }.
4364514f5e3Sopenharmony_ci                cp = UTF16SurrogatePairToCodePoint(first, second);
4374514f5e3Sopenharmony_ci                codeUnitCount = 2; // 2 means: code unit count
4384514f5e3Sopenharmony_ci                isUnpairedSurrogate = false;
4394514f5e3Sopenharmony_ci            }
4404514f5e3Sopenharmony_ci        }
4414514f5e3Sopenharmony_ci        codePoints.push_back(cp);
4424514f5e3Sopenharmony_ci        position = position + codeUnitCount;
4434514f5e3Sopenharmony_ci    }
4444514f5e3Sopenharmony_ci    // 5. Return codePoints.
4454514f5e3Sopenharmony_ci    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
4464514f5e3Sopenharmony_ci    uint16_t *ptr = reinterpret_cast<uint16_t *>(codePoints.data());
4474514f5e3Sopenharmony_ci    JSHandle<EcmaString> codePointsString = factory->NewFromUtf16Literal(ptr, codePoints.size());
4484514f5e3Sopenharmony_ci    return *codePointsString;
4494514f5e3Sopenharmony_ci}
4504514f5e3Sopenharmony_ci
4514514f5e3Sopenharmony_ci// Runtime Semantics
4524514f5e3Sopenharmony_ciJSTaggedValue BuiltinsGlobal::Decode(JSThread *thread, const JSHandle<EcmaString> &str, judgURIFunc IsInURISet)
4534514f5e3Sopenharmony_ci{
4544514f5e3Sopenharmony_ci    BUILTINS_API_TRACE(thread, Global, Decode);
4554514f5e3Sopenharmony_ci    // 1. Let strLen be the number of code units in string.
4564514f5e3Sopenharmony_ci    int32_t strLen = static_cast<int32_t>(EcmaStringAccessor(str).GetLength());
4574514f5e3Sopenharmony_ci    // 2. Let R be the empty String.
4584514f5e3Sopenharmony_ci    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
4594514f5e3Sopenharmony_ci    std::u16string resStr;
4604514f5e3Sopenharmony_ci    JSHandle<EcmaString> string = str;
4614514f5e3Sopenharmony_ci    if (EcmaStringAccessor(str).IsTreeString()) {
4624514f5e3Sopenharmony_ci        string = JSHandle<EcmaString>(thread, EcmaStringAccessor::Flatten(thread->GetEcmaVM(), str));
4634514f5e3Sopenharmony_ci    }
4644514f5e3Sopenharmony_ci
4654514f5e3Sopenharmony_ci    // 3. Let k be 0.
4664514f5e3Sopenharmony_ci    // 4. Repeat
4674514f5e3Sopenharmony_ci    int32_t k = 0;
4684514f5e3Sopenharmony_ci    while (true) {
4694514f5e3Sopenharmony_ci        if (k == strLen) {
4704514f5e3Sopenharmony_ci            // a. If k equals strLen, return R.
4714514f5e3Sopenharmony_ci            auto *uint16tData = reinterpret_cast<uint16_t *>(resStr.data());
4724514f5e3Sopenharmony_ci            uint32_t resSize = resStr.size();
4734514f5e3Sopenharmony_ci            return factory->NewFromUtf16Literal(uint16tData, resSize).GetTaggedValue();
4744514f5e3Sopenharmony_ci        }
4754514f5e3Sopenharmony_ci
4764514f5e3Sopenharmony_ci        // b. Let C be the code unit at index k within string.
4774514f5e3Sopenharmony_ci        // c. If C is not "%", then
4784514f5e3Sopenharmony_ci        //    i. Let S be the String containing only the code unit C.
4794514f5e3Sopenharmony_ci        // d. Else C is "%",
4804514f5e3Sopenharmony_ci        //   i. Let start be k.
4814514f5e3Sopenharmony_ci        //   iv. Let B be the 8-bit value represented by the two hexadecimal digits at index (k + 1) and (k + 2).
4824514f5e3Sopenharmony_ci        //   v. Increase k by 2.
4834514f5e3Sopenharmony_ci        //   vi. If the most significant bit in B is 0, then
4844514f5e3Sopenharmony_ci        //      1. Let C be the code unit with code unit value B.
4854514f5e3Sopenharmony_ci        //      2. If C is not in reservedSet, then
4864514f5e3Sopenharmony_ci        //         a. Let S be the String containing only the code unit C.
4874514f5e3Sopenharmony_ci        //      3. Else C is in reservedSet,
4884514f5e3Sopenharmony_ci        //         a. Let S be the substring of string from index start to index k inclusive.
4894514f5e3Sopenharmony_ci        uint16_t cc = EcmaStringAccessor(string).Get(k);
4904514f5e3Sopenharmony_ci        std::u16string sStr;
4914514f5e3Sopenharmony_ci        if (cc != '%') {
4924514f5e3Sopenharmony_ci            if (cc == 0 && strLen == 1) {
4934514f5e3Sopenharmony_ci                JSHandle<EcmaString> tmpEcmaString = factory->NewFromUtf16Literal(&cc, 1);
4944514f5e3Sopenharmony_ci                return tmpEcmaString.GetTaggedValue();
4954514f5e3Sopenharmony_ci            }
4964514f5e3Sopenharmony_ci            sStr = StringHelper::Utf16ToU16String(&cc, 1);
4974514f5e3Sopenharmony_ci        } else {
4984514f5e3Sopenharmony_ci            DecodePercentEncoding(thread, string, k, IsInURISet, strLen, sStr);
4994514f5e3Sopenharmony_ci            RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
5004514f5e3Sopenharmony_ci        }
5014514f5e3Sopenharmony_ci        resStr.append(sStr);
5024514f5e3Sopenharmony_ci        k++;
5034514f5e3Sopenharmony_ci    }
5044514f5e3Sopenharmony_ci}
5054514f5e3Sopenharmony_ci
5064514f5e3Sopenharmony_civoid BuiltinsGlobal::HandleSingleByteCharacter(JSThread *thread, uint8_t &bb,
5074514f5e3Sopenharmony_ci                                               const JSHandle<EcmaString> &str,
5084514f5e3Sopenharmony_ci                                               uint32_t &start, int32_t &k,
5094514f5e3Sopenharmony_ci                                               std::u16string &sStr, judgURIFunc IsInURISet)
5104514f5e3Sopenharmony_ci{
5114514f5e3Sopenharmony_ci    if (!IsInURISet(bb)) {
5124514f5e3Sopenharmony_ci        sStr = StringHelper::Utf8ToU16String(&bb, 1);
5134514f5e3Sopenharmony_ci    } else {
5144514f5e3Sopenharmony_ci        auto substr = EcmaStringAccessor::FastSubString(
5154514f5e3Sopenharmony_ci            thread->GetEcmaVM(), str, start, k - start + 1U);
5164514f5e3Sopenharmony_ci        sStr = StringHelper::StringToU16string(
5174514f5e3Sopenharmony_ci            EcmaStringAccessor(substr).ToStdString(StringConvertedUsage::LOGICOPERATION));
5184514f5e3Sopenharmony_ci    }
5194514f5e3Sopenharmony_ci}
5204514f5e3Sopenharmony_ci
5214514f5e3Sopenharmony_ci
5224514f5e3Sopenharmony_ciJSTaggedValue BuiltinsGlobal::DecodePercentEncoding(JSThread *thread, const JSHandle<EcmaString> &str, int32_t &k,
5234514f5e3Sopenharmony_ci                                                    judgURIFunc IsInURISet, int32_t strLen, std::u16string &sStr)
5244514f5e3Sopenharmony_ci{
5254514f5e3Sopenharmony_ci    [[maybe_unused]] uint32_t start = static_cast<uint32_t>(k);
5264514f5e3Sopenharmony_ci    CString errorMsg;
5274514f5e3Sopenharmony_ci    // ii. If k + 2 is greater than or equal to strLen, throw a URIError exception.
5284514f5e3Sopenharmony_ci    // iii. If the code units at index (k+1) and (k + 2) within string do not represent hexadecimal digits,
5294514f5e3Sopenharmony_ci    //      throw a URIError exception.
5304514f5e3Sopenharmony_ci    if ((k + 2) >= strLen) {  // 2: means plus 2
5314514f5e3Sopenharmony_ci        errorMsg = "DecodeURI: invalid character: " + ConvertToString(str.GetTaggedValue());
5324514f5e3Sopenharmony_ci        THROW_URI_ERROR_AND_RETURN(thread, errorMsg.c_str(), JSTaggedValue::Exception());
5334514f5e3Sopenharmony_ci    }
5344514f5e3Sopenharmony_ci    uint16_t frontChar = EcmaStringAccessor(str).Get(k + 1);
5354514f5e3Sopenharmony_ci    uint16_t behindChar = EcmaStringAccessor(str).Get(k + 2);  // 2: means plus 2
5364514f5e3Sopenharmony_ci    if (!(IsHexDigits(frontChar) && IsHexDigits(behindChar))) {
5374514f5e3Sopenharmony_ci        errorMsg = "DecodeURI: invalid character: " + ConvertToString(str.GetTaggedValue());
5384514f5e3Sopenharmony_ci        THROW_URI_ERROR_AND_RETURN(thread, errorMsg.c_str(), JSTaggedValue::Exception());
5394514f5e3Sopenharmony_ci    }
5404514f5e3Sopenharmony_ci    uint8_t bb = GetValueFromTwoHex(frontChar, behindChar);
5414514f5e3Sopenharmony_ci    k += 2;  // 2: means plus 2
5424514f5e3Sopenharmony_ci    if ((bb & BIT_MASK_ONE) == 0) {
5434514f5e3Sopenharmony_ci        HandleSingleByteCharacter(thread, bb, str, start, k, sStr, IsInURISet);
5444514f5e3Sopenharmony_ci    } else {
5454514f5e3Sopenharmony_ci        // vii. Else the most significant bit in B is 1,
5464514f5e3Sopenharmony_ci        //   1. Let n be the smallest nonnegative integer such that (B << n) & 0x80 is equal to 0.
5474514f5e3Sopenharmony_ci        //   3. Let Octets be an array of 8-bit integers of size n.
5484514f5e3Sopenharmony_ci        //   4. Put B into Octets at index 0.
5494514f5e3Sopenharmony_ci        //   6. Let j be 1.
5504514f5e3Sopenharmony_ci        //   7. Repeat, while j < n
5514514f5e3Sopenharmony_ci        //     a. Increase k by 1.
5524514f5e3Sopenharmony_ci        //     d. Let B be the 8-bit value represented by the two hexadecimal digits at
5534514f5e3Sopenharmony_ci        //        index (k + 1) and (k + 2).
5544514f5e3Sopenharmony_ci        //     f. Increase k by 2.
5554514f5e3Sopenharmony_ci        //     g. Put B into Octets at index j.
5564514f5e3Sopenharmony_ci        //     h. Increase j by 1.
5574514f5e3Sopenharmony_ci        //   9. If V < 0x10000, then
5584514f5e3Sopenharmony_ci        //     a. Let C be the code unit V.
5594514f5e3Sopenharmony_ci        //     b. If C is not in reservedSet, then
5604514f5e3Sopenharmony_ci        //        i. Let S be the String containing only the code unit C.
5614514f5e3Sopenharmony_ci        //     c. Else C is in reservedSet,
5624514f5e3Sopenharmony_ci        //        i. Let S be the substring of string from index start to index k inclusive.
5634514f5e3Sopenharmony_ci        //   10. Else V ≥ 0x10000,
5644514f5e3Sopenharmony_ci        //     a. Let L be (((V – 0x10000) & 0x3FF) + 0xDC00).
5654514f5e3Sopenharmony_ci        //     b. Let H be ((((V – 0x10000) >> 10) & 0x3FF) + 0xD800).
5664514f5e3Sopenharmony_ci        //     c. Let S be the String containing the two code units H and L.
5674514f5e3Sopenharmony_ci        int32_t n = 0;
5684514f5e3Sopenharmony_ci        while ((((static_cast<uint32_t>(bb) << static_cast<uint32_t>(n)) & BIT_MASK_ONE) != 0)) {
5694514f5e3Sopenharmony_ci            n++;
5704514f5e3Sopenharmony_ci            if (n > 4) { // 4 : 4 means less than 4
5714514f5e3Sopenharmony_ci                break;
5724514f5e3Sopenharmony_ci            }
5734514f5e3Sopenharmony_ci        }
5744514f5e3Sopenharmony_ci        // 2. If n equals 1 or n is greater than 4, throw a URIError exception.
5754514f5e3Sopenharmony_ci        if ((n == 1) || (n > 4)) {
5764514f5e3Sopenharmony_ci            errorMsg = "DecodeURI: invalid character: " + ConvertToString(str.GetTaggedValue());
5774514f5e3Sopenharmony_ci            THROW_URI_ERROR_AND_RETURN(thread, errorMsg.c_str(), JSTaggedValue::Exception());
5784514f5e3Sopenharmony_ci        }
5794514f5e3Sopenharmony_ci
5804514f5e3Sopenharmony_ci        std::vector<uint8_t> oct = {bb};
5814514f5e3Sopenharmony_ci
5824514f5e3Sopenharmony_ci        // 5. If k + (3 × (n – 1)) is greater than or equal to strLen, throw a URIError exception.
5834514f5e3Sopenharmony_ci        if (k + (3 * (n - 1)) >= strLen) {  // 3: means multiply by 3
5844514f5e3Sopenharmony_ci            errorMsg = "DecodeURI: invalid character: " + ConvertToString(str.GetTaggedValue());
5854514f5e3Sopenharmony_ci            THROW_URI_ERROR_AND_RETURN(thread, errorMsg.c_str(), JSTaggedValue::Exception());
5864514f5e3Sopenharmony_ci        }
5874514f5e3Sopenharmony_ci        DecodePercentEncoding(thread, n, k, str, bb, oct);
5884514f5e3Sopenharmony_ci        RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
5894514f5e3Sopenharmony_ci        UTF16EncodeCodePoint(thread, IsInURISet, oct, str, start, k, sStr);
5904514f5e3Sopenharmony_ci        RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
5914514f5e3Sopenharmony_ci    }
5924514f5e3Sopenharmony_ci    return JSTaggedValue::True();
5934514f5e3Sopenharmony_ci}
5944514f5e3Sopenharmony_ci
5954514f5e3Sopenharmony_ciJSTaggedValue BuiltinsGlobal::DecodePercentEncoding(JSThread *thread, int32_t &n,
5964514f5e3Sopenharmony_ci                                                    int32_t &k, const JSHandle<EcmaString> &str,
5974514f5e3Sopenharmony_ci                                                    uint8_t &bb, std::vector<uint8_t> &oct)
5984514f5e3Sopenharmony_ci{
5994514f5e3Sopenharmony_ci    CString errorMsg;
6004514f5e3Sopenharmony_ci    int32_t j = 1;
6014514f5e3Sopenharmony_ci    while (j < n) {
6024514f5e3Sopenharmony_ci        k++;
6034514f5e3Sopenharmony_ci        uint16_t codeUnit = EcmaStringAccessor(str).Get(k);
6044514f5e3Sopenharmony_ci        // b. If the code unit at index k within string is not "%", throw a URIError exception.
6054514f5e3Sopenharmony_ci        // c. If the code units at index (k +1) and (k + 2) within string do not represent hexadecimal
6064514f5e3Sopenharmony_ci        //    digits, throw a URIError exception.
6074514f5e3Sopenharmony_ci        if (!(codeUnit == '%')) {
6084514f5e3Sopenharmony_ci            errorMsg = "DecodeURI: invalid character: " + ConvertToString(str.GetTaggedValue());
6094514f5e3Sopenharmony_ci            THROW_URI_ERROR_AND_RETURN(thread, errorMsg.c_str(), JSTaggedValue::Exception());
6104514f5e3Sopenharmony_ci        }
6114514f5e3Sopenharmony_ci        if (!(IsHexDigits(EcmaStringAccessor(str).Get(k + 1)) &&
6124514f5e3Sopenharmony_ci                IsHexDigits(EcmaStringAccessor(str).Get(k + 2)))) {  // 2: means plus 2
6134514f5e3Sopenharmony_ci            errorMsg = "DecodeURI: invalid character: " + ConvertToString(str.GetTaggedValue());
6144514f5e3Sopenharmony_ci            THROW_URI_ERROR_AND_RETURN(thread, errorMsg.c_str(), JSTaggedValue::Exception());
6154514f5e3Sopenharmony_ci        }
6164514f5e3Sopenharmony_ci        uint16_t frontChart = EcmaStringAccessor(str).Get(k + 1);
6174514f5e3Sopenharmony_ci        uint16_t behindChart = EcmaStringAccessor(str).Get(k + 2);  // 2: means plus 2
6184514f5e3Sopenharmony_ci        bb = GetValueFromTwoHex(frontChart, behindChart);
6194514f5e3Sopenharmony_ci        // e. If the two most significant bits in B are not 10, throw a URIError exception.
6204514f5e3Sopenharmony_ci        if (!((bb & BIT_MASK_TWO) == BIT_MASK_ONE)) {
6214514f5e3Sopenharmony_ci            errorMsg = "DecodeURI: invalid character: " + ConvertToString(str.GetTaggedValue());
6224514f5e3Sopenharmony_ci            THROW_URI_ERROR_AND_RETURN(thread, errorMsg.c_str(), JSTaggedValue::Exception());
6234514f5e3Sopenharmony_ci        }
6244514f5e3Sopenharmony_ci        k += 2;  // 2: means plus 2
6254514f5e3Sopenharmony_ci        oct.push_back(bb);
6264514f5e3Sopenharmony_ci        j++;
6274514f5e3Sopenharmony_ci    }
6284514f5e3Sopenharmony_ci    return JSTaggedValue::True();
6294514f5e3Sopenharmony_ci}
6304514f5e3Sopenharmony_ci
6314514f5e3Sopenharmony_ciJSTaggedValue BuiltinsGlobal::UTF16EncodeCodePoint(JSThread *thread, judgURIFunc IsInURISet,
6324514f5e3Sopenharmony_ci                                                   const std::vector<uint8_t> &oct, const JSHandle<EcmaString> &str,
6334514f5e3Sopenharmony_ci                                                   uint32_t &start, int32_t &k, std::u16string &sStr)
6344514f5e3Sopenharmony_ci{
6354514f5e3Sopenharmony_ci    if (!base::utf_helper::IsValidUTF8(oct)) {
6364514f5e3Sopenharmony_ci        CString errorMsg = "DecodeURI: invalid character: " + ConvertToString(str.GetTaggedValue());
6374514f5e3Sopenharmony_ci        THROW_URI_ERROR_AND_RETURN(thread, errorMsg.c_str(), JSTaggedValue::Exception());
6384514f5e3Sopenharmony_ci    }
6394514f5e3Sopenharmony_ci    uint32_t vv = StringHelper::Utf8ToU32String(oct);
6404514f5e3Sopenharmony_ci    if (vv < base::utf_helper::DECODE_SECOND_FACTOR) {
6414514f5e3Sopenharmony_ci        if (!IsInURISet(vv)) {
6424514f5e3Sopenharmony_ci            sStr = StringHelper::Utf16ToU16String(reinterpret_cast<uint16_t *>(&vv), 1);
6434514f5e3Sopenharmony_ci        } else {
6444514f5e3Sopenharmony_ci            auto substr = EcmaStringAccessor::FastSubString(
6454514f5e3Sopenharmony_ci                thread->GetEcmaVM(), str, start, static_cast<uint32_t>(k) - start + 1U);
6464514f5e3Sopenharmony_ci            sStr = StringHelper::StringToU16string(
6474514f5e3Sopenharmony_ci                EcmaStringAccessor(substr).ToStdString(StringConvertedUsage::LOGICOPERATION));
6484514f5e3Sopenharmony_ci        }
6494514f5e3Sopenharmony_ci    } else {
6504514f5e3Sopenharmony_ci        uint16_t lv = (((vv - base::utf_helper::DECODE_SECOND_FACTOR) & BIT16_MASK) +
6514514f5e3Sopenharmony_ci            base::utf_helper::DECODE_TRAIL_LOW);
6524514f5e3Sopenharmony_ci        uint16_t hv = ((((vv - base::utf_helper::DECODE_SECOND_FACTOR) >> 10U) & BIT16_MASK) +  // NOLINT
6534514f5e3Sopenharmony_ci            base::utf_helper::DECODE_LEAD_LOW);  // 10: means shift left by 10 digits
6544514f5e3Sopenharmony_ci        sStr = StringHelper::Append(StringHelper::Utf16ToU16String(&hv, 1),
6554514f5e3Sopenharmony_ci                                    StringHelper::Utf16ToU16String(&lv, 1));
6564514f5e3Sopenharmony_ci    }
6574514f5e3Sopenharmony_ci    return JSTaggedValue::True();
6584514f5e3Sopenharmony_ci}
6594514f5e3Sopenharmony_ci
6604514f5e3Sopenharmony_civoid BuiltinsGlobal::PrintString([[maybe_unused]] JSThread *thread, EcmaString *string)
6614514f5e3Sopenharmony_ci{
6624514f5e3Sopenharmony_ci    if (string == nullptr) {
6634514f5e3Sopenharmony_ci        return;
6644514f5e3Sopenharmony_ci    }
6654514f5e3Sopenharmony_ci    BUILTINS_API_TRACE(thread, Global, PrintString);
6664514f5e3Sopenharmony_ci    CString buffer = ConvertToString(string);
6674514f5e3Sopenharmony_ci    std::cout << buffer;
6684514f5e3Sopenharmony_ci}
6694514f5e3Sopenharmony_ci
6704514f5e3Sopenharmony_ciJSTaggedValue BuiltinsGlobal::PrintEntrypoint(EcmaRuntimeCallInfo *msg)
6714514f5e3Sopenharmony_ci{
6724514f5e3Sopenharmony_ci    if (msg == nullptr) {
6734514f5e3Sopenharmony_ci        return JSTaggedValue::Undefined();
6744514f5e3Sopenharmony_ci    }
6754514f5e3Sopenharmony_ci    JSThread *thread = msg->GetThread();
6764514f5e3Sopenharmony_ci    [[maybe_unused]] EcmaHandleScope handleScope(thread);
6774514f5e3Sopenharmony_ci    BUILTINS_API_TRACE(thread, Global, PrintEntryPoint);
6784514f5e3Sopenharmony_ci
6794514f5e3Sopenharmony_ci    uint32_t numArgs = msg->GetArgsNumber();
6804514f5e3Sopenharmony_ci    for (uint32_t i = 0; i < numArgs; i++) {
6814514f5e3Sopenharmony_ci        JSHandle<EcmaString> stringContent = JSTaggedValue::ToString(thread, GetCallArg(msg, i));
6824514f5e3Sopenharmony_ci        RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
6834514f5e3Sopenharmony_ci        PrintString(thread, *stringContent);
6844514f5e3Sopenharmony_ci
6854514f5e3Sopenharmony_ci        if (i != numArgs - 1) {
6864514f5e3Sopenharmony_ci            std::cout << " ";
6874514f5e3Sopenharmony_ci        }
6884514f5e3Sopenharmony_ci    }
6894514f5e3Sopenharmony_ci    std::cout << std::endl;
6904514f5e3Sopenharmony_ci    return JSTaggedValue::Undefined();
6914514f5e3Sopenharmony_ci}
6924514f5e3Sopenharmony_ci
6934514f5e3Sopenharmony_ciJSTaggedValue BuiltinsGlobal::MarkModuleCollectable(EcmaRuntimeCallInfo *msg)
6944514f5e3Sopenharmony_ci{
6954514f5e3Sopenharmony_ci    ASSERT(msg);
6964514f5e3Sopenharmony_ci    JSThread *thread = msg->GetThread();
6974514f5e3Sopenharmony_ci    [[maybe_unused]] EcmaHandleScope handleScope(thread);
6984514f5e3Sopenharmony_ci
6994514f5e3Sopenharmony_ci    uint32_t numArgs = msg->GetArgsNumber();
7004514f5e3Sopenharmony_ci    if (numArgs != 1) {
7014514f5e3Sopenharmony_ci        LOG_FULL(ERROR) << "The number of parameters received by markModuleCollectable is incorrect.";
7024514f5e3Sopenharmony_ci        return JSTaggedValue::False();
7034514f5e3Sopenharmony_ci    }
7044514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> module = GetCallArg(msg, 0);
7054514f5e3Sopenharmony_ci    if (!module->IsModuleNamespace()) {
7064514f5e3Sopenharmony_ci        return JSTaggedValue::False();
7074514f5e3Sopenharmony_ci    }
7084514f5e3Sopenharmony_ci
7094514f5e3Sopenharmony_ci    ModuleDeregister::ProcessModuleReference(thread, module);
7104514f5e3Sopenharmony_ci    return JSTaggedValue::True();
7114514f5e3Sopenharmony_ci}
7124514f5e3Sopenharmony_ci
7134514f5e3Sopenharmony_ciJSTaggedValue BuiltinsGlobal::LoadNativeModule(EcmaRuntimeCallInfo *msg)
7144514f5e3Sopenharmony_ci{
7154514f5e3Sopenharmony_ci    ASSERT(msg);
7164514f5e3Sopenharmony_ci    JSThread *thread = msg->GetThread();
7174514f5e3Sopenharmony_ci    [[maybe_unused]] EcmaHandleScope handleScope(thread);
7184514f5e3Sopenharmony_ci    CString errorMsg;
7194514f5e3Sopenharmony_ci    uint32_t numArgs = msg->GetArgsNumber();
7204514f5e3Sopenharmony_ci    if (numArgs != 1) {
7214514f5e3Sopenharmony_ci        errorMsg = "The number of parameters received by loadNativeModule is incorrect.";
7224514f5e3Sopenharmony_ci        auto error = GlobalError::ParamError(thread, errorMsg.c_str());
7234514f5e3Sopenharmony_ci        THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
7244514f5e3Sopenharmony_ci    }
7254514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> input = GetCallArg(msg, 0);
7264514f5e3Sopenharmony_ci    if (!input->IsString()) {
7274514f5e3Sopenharmony_ci        errorMsg = "The number of parameters received by loadNativeModule is incorrect.";
7284514f5e3Sopenharmony_ci        auto error = GlobalError::ParamError(thread, errorMsg.c_str());
7294514f5e3Sopenharmony_ci        THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
7304514f5e3Sopenharmony_ci    }
7314514f5e3Sopenharmony_ci
7324514f5e3Sopenharmony_ci    EcmaVM *vm  = thread->GetEcmaVM();
7334514f5e3Sopenharmony_ci    auto [moduleName, fileName] = vm->GetCurrentModuleInfo(false);
7344514f5e3Sopenharmony_ci    std::shared_ptr<JSPandaFile> curJsPandaFile;
7354514f5e3Sopenharmony_ci    CString requestPath = ModulePathHelper::Utf8ConvertToString(input.GetTaggedValue());
7364514f5e3Sopenharmony_ci    CString abcFilePath = fileName.c_str();
7374514f5e3Sopenharmony_ci    if (moduleName.size() != 0) {
7384514f5e3Sopenharmony_ci        curJsPandaFile = JSPandaFileManager::GetInstance()->LoadJSPandaFile(thread, abcFilePath, requestPath);
7394514f5e3Sopenharmony_ci        if (curJsPandaFile == nullptr) {
7404514f5e3Sopenharmony_ci            errorMsg = "Load native module failed, filename '" + abcFilePath +
7414514f5e3Sopenharmony_ci                ", module name '" + requestPath;
7424514f5e3Sopenharmony_ci            auto error = GlobalError::ReferenceError(thread, errorMsg.c_str());
7434514f5e3Sopenharmony_ci            THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
7444514f5e3Sopenharmony_ci        }
7454514f5e3Sopenharmony_ci        if (vm->IsNormalizedOhmUrlPack()) {
7464514f5e3Sopenharmony_ci            ModulePathHelper::TranslateExpressionToNormalized(thread, curJsPandaFile.get(), abcFilePath, "",
7474514f5e3Sopenharmony_ci                requestPath);
7484514f5e3Sopenharmony_ci        } else if (ModulePathHelper::NeedTranstale(requestPath)) {
7494514f5e3Sopenharmony_ci            ModulePathHelper::TranstaleExpressionInput(curJsPandaFile.get(), requestPath);
7504514f5e3Sopenharmony_ci        }
7514514f5e3Sopenharmony_ci
7524514f5e3Sopenharmony_ci        size_t pos = requestPath.find(PathHelper::COLON_TAG);
7534514f5e3Sopenharmony_ci        if (pos == CString::npos) {
7544514f5e3Sopenharmony_ci            errorMsg = "The module name '"+ requestPath +
7554514f5e3Sopenharmony_ci                "' of parameters received by loadNativeModule is incorrect.";
7564514f5e3Sopenharmony_ci            auto error = GlobalError::ParamError(thread, errorMsg.c_str());
7574514f5e3Sopenharmony_ci            THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
7584514f5e3Sopenharmony_ci        }
7594514f5e3Sopenharmony_ci    }
7604514f5e3Sopenharmony_ci
7614514f5e3Sopenharmony_ci    ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager();
7624514f5e3Sopenharmony_ci    auto exportObject = moduleManager->ExecuteNativeModuleMayThrowError(thread, requestPath);
7634514f5e3Sopenharmony_ci    return exportObject.GetTaggedValue();
7644514f5e3Sopenharmony_ci}
7654514f5e3Sopenharmony_ci
7664514f5e3Sopenharmony_ciJSTaggedValue BuiltinsGlobal::CallJsBoundFunction(EcmaRuntimeCallInfo *msg)
7674514f5e3Sopenharmony_ci{
7684514f5e3Sopenharmony_ci    JSThread *thread = msg->GetThread();
7694514f5e3Sopenharmony_ci    BUILTINS_API_TRACE(thread, Global, CallJsBoundFunction);
7704514f5e3Sopenharmony_ci    [[maybe_unused]] EcmaHandleScope handleScope(thread);
7714514f5e3Sopenharmony_ci    // msg contains jsfunc, this, arg1,...
7724514f5e3Sopenharmony_ci
7734514f5e3Sopenharmony_ci    JSHandle<JSBoundFunction> boundFunc(GetConstructor(msg));
7744514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> thisObj(thread, boundFunc->GetBoundThis());
7754514f5e3Sopenharmony_ci    msg->SetThis(thisObj.GetTaggedValue());
7764514f5e3Sopenharmony_ci    return RuntimeStubs::CallBoundFunction(msg);
7774514f5e3Sopenharmony_ci}
7784514f5e3Sopenharmony_ci
7794514f5e3Sopenharmony_ciJSTaggedValue BuiltinsGlobal::CallJsProxy(EcmaRuntimeCallInfo *msg)
7804514f5e3Sopenharmony_ci{
7814514f5e3Sopenharmony_ci    JSThread *thread = msg->GetThread();
7824514f5e3Sopenharmony_ci    BUILTINS_API_TRACE(thread, Global, CallJsProxy);
7834514f5e3Sopenharmony_ci    [[maybe_unused]] EcmaHandleScope handleScope(thread);
7844514f5e3Sopenharmony_ci    // msg contains js_proxy, this, arg1,...
7854514f5e3Sopenharmony_ci    JSHandle<JSProxy> proxy(GetConstructor(msg));
7864514f5e3Sopenharmony_ci    if (!proxy->IsCallable()) {
7874514f5e3Sopenharmony_ci        THROW_TYPE_ERROR_AND_RETURN(thread, "Proxy target is not callable", JSTaggedValue::Undefined());
7884514f5e3Sopenharmony_ci    }
7894514f5e3Sopenharmony_ci
7904514f5e3Sopenharmony_ci    // Calling proxy directly should transfer 'undefined' as this
7914514f5e3Sopenharmony_ci    return JSProxy::CallInternal(msg);
7924514f5e3Sopenharmony_ci}
7934514f5e3Sopenharmony_ci
7944514f5e3Sopenharmony_ci#if ECMASCRIPT_ENABLE_RUNTIME_STAT
7954514f5e3Sopenharmony_ciJSTaggedValue BuiltinsGlobal::StartRuntimeStat(EcmaRuntimeCallInfo *msg)
7964514f5e3Sopenharmony_ci{
7974514f5e3Sopenharmony_ci    JSThread *thread = msg->GetThread();
7984514f5e3Sopenharmony_ci    BUILTINS_API_TRACE(thread, Global, StartRuntimeStat);
7994514f5e3Sopenharmony_ci    [[maybe_unused]] EcmaHandleScope handleScope(thread);
8004514f5e3Sopenharmony_ci    // start vm runtime stat statistic
8014514f5e3Sopenharmony_ci    thread->GetCurrentEcmaContext()->SetRuntimeStatEnable(true);
8024514f5e3Sopenharmony_ci    return JSTaggedValue::Undefined();
8034514f5e3Sopenharmony_ci}
8044514f5e3Sopenharmony_ci
8054514f5e3Sopenharmony_ciJSTaggedValue BuiltinsGlobal::StopRuntimeStat(EcmaRuntimeCallInfo *msg)
8064514f5e3Sopenharmony_ci{
8074514f5e3Sopenharmony_ci    JSThread *thread = msg->GetThread();
8084514f5e3Sopenharmony_ci    BUILTINS_API_TRACE(thread, Global, StopRuntimeStat);
8094514f5e3Sopenharmony_ci    [[maybe_unused]] EcmaHandleScope handleScope(thread);
8104514f5e3Sopenharmony_ci    // start vm runtime stat statistic
8114514f5e3Sopenharmony_ci    thread->GetCurrentEcmaContext()->SetRuntimeStatEnable(false);
8124514f5e3Sopenharmony_ci    return JSTaggedValue::Undefined();
8134514f5e3Sopenharmony_ci}
8144514f5e3Sopenharmony_ci#endif
8154514f5e3Sopenharmony_ci
8164514f5e3Sopenharmony_ci#if ECMASCRIPT_ENABLE_OPT_CODE_PROFILER
8174514f5e3Sopenharmony_ciJSTaggedValue BuiltinsGlobal::PrintOptStat(EcmaRuntimeCallInfo *msg)
8184514f5e3Sopenharmony_ci{
8194514f5e3Sopenharmony_ci    JSThread *thread = msg->GetThread();
8204514f5e3Sopenharmony_ci    BUILTINS_API_TRACE(thread, Global, PrintOptStat);
8214514f5e3Sopenharmony_ci    [[maybe_unused]] EcmaHandleScope handleScope(thread);
8224514f5e3Sopenharmony_ci    // start vm runtime stat statistic
8234514f5e3Sopenharmony_ci    thread->GetCurrentEcmaContext()->PrintOptStat();
8244514f5e3Sopenharmony_ci    return JSTaggedValue::Undefined();
8254514f5e3Sopenharmony_ci}
8264514f5e3Sopenharmony_ci#endif
8274514f5e3Sopenharmony_ci
8284514f5e3Sopenharmony_ci#if ECMASCRIPT_ENABLE_FUNCTION_CALL_TIMER
8294514f5e3Sopenharmony_ciJSTaggedValue BuiltinsGlobal::PrintFunctionCallStat(EcmaRuntimeCallInfo *msg)
8304514f5e3Sopenharmony_ci{
8314514f5e3Sopenharmony_ci    JSThread *thread = msg->GetThread();
8324514f5e3Sopenharmony_ci    BUILTINS_API_TRACE(thread, Global, PrintFunctionCallStat);
8334514f5e3Sopenharmony_ci    [[maybe_unused]] EcmaHandleScope handleScope(thread);
8344514f5e3Sopenharmony_ci    // start vm runtime stat statistic
8354514f5e3Sopenharmony_ci    thread->GetEcmaVM()->DumpCallTimeInfo();
8364514f5e3Sopenharmony_ci    return JSTaggedValue::Undefined();
8374514f5e3Sopenharmony_ci}
8384514f5e3Sopenharmony_ci#endif
8394514f5e3Sopenharmony_ci
8404514f5e3Sopenharmony_ci// B.2.1.1 escape ( string )
8414514f5e3Sopenharmony_ciJSTaggedValue BuiltinsGlobal::Escape(EcmaRuntimeCallInfo *msg)
8424514f5e3Sopenharmony_ci{
8434514f5e3Sopenharmony_ci    ASSERT(msg);
8444514f5e3Sopenharmony_ci    JSThread *thread = msg->GetThread();
8454514f5e3Sopenharmony_ci    BUILTINS_API_TRACE(thread, Global, Escape);
8464514f5e3Sopenharmony_ci    [[maybe_unused]] EcmaHandleScope handleScope(thread);
8474514f5e3Sopenharmony_ci    // 1. Set string to ? ToString(string).
8484514f5e3Sopenharmony_ci    JSHandle<EcmaString> string = JSTaggedValue::ToString(thread, GetCallArg(msg, 0));
8494514f5e3Sopenharmony_ci    RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
8504514f5e3Sopenharmony_ci    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
8514514f5e3Sopenharmony_ci    // 2. Let len be the length of string.
8524514f5e3Sopenharmony_ci    uint32_t len = EcmaStringAccessor(string).GetLength();
8534514f5e3Sopenharmony_ci    // 3. Let R be the empty String.
8544514f5e3Sopenharmony_ci    std::u16string r;
8554514f5e3Sopenharmony_ci    // 4. Let unescapedSet be the string-concatenation of the ASCII word characters and "@*+-./".
8564514f5e3Sopenharmony_ci    // 5. Let k be 0.
8574514f5e3Sopenharmony_ci    uint32_t k = 0;
8584514f5e3Sopenharmony_ci    // 6. Repeat, while k < len,
8594514f5e3Sopenharmony_ci    //   a. Let C be the code unit at index k within string.
8604514f5e3Sopenharmony_ci    //   b. If unescapedSet contains C, then
8614514f5e3Sopenharmony_ci    //        i. Let S be C.
8624514f5e3Sopenharmony_ci    //   c. Else,
8634514f5e3Sopenharmony_ci    //        i. Let n be the numeric value of C.
8644514f5e3Sopenharmony_ci    //        ii. If n < 256, then
8654514f5e3Sopenharmony_ci    //          1. Let hex be the String representation of n, formatted as an uppercase hexadecimal number.
8664514f5e3Sopenharmony_ci    //          2. Let S be the string-concatenation of "%" and StringPad(hex, 2, "0", start).
8674514f5e3Sopenharmony_ci    //        iii. Else,
8684514f5e3Sopenharmony_ci    //          1. Let hex be the String representation of n, formatted as an uppercase hexadecimal number.
8694514f5e3Sopenharmony_ci    //          2. Let S be the string-concatenation of "%u" and StringPad(hex, 4, "0", start).
8704514f5e3Sopenharmony_ci    //    d. Set R to the string-concatenation of R and S.
8714514f5e3Sopenharmony_ci    //    e. Set k to k + 1.
8724514f5e3Sopenharmony_ci    while (k < len) {
8734514f5e3Sopenharmony_ci        uint16_t c = EcmaStringAccessor(string).Get(k);
8744514f5e3Sopenharmony_ci        if (c < std::numeric_limits<int8_t>::max() && ESCAPE_BIT_MAP[c] == 1) {
8754514f5e3Sopenharmony_ci            r.push_back(c);
8764514f5e3Sopenharmony_ci        } else {
8774514f5e3Sopenharmony_ci            r.push_back('%');
8784514f5e3Sopenharmony_ci            if (c <= std::numeric_limits<uint8_t>::max()) {
8794514f5e3Sopenharmony_ci                r.push_back(ESCAPE_HEX_TO_CHAR[(c >> ESCAPE_HEX_BIT4) & ESCAPE_HEX_MASK]);
8804514f5e3Sopenharmony_ci                r.push_back(ESCAPE_HEX_TO_CHAR[c & ESCAPE_HEX_MASK]);
8814514f5e3Sopenharmony_ci            } else {
8824514f5e3Sopenharmony_ci                r.push_back('u');
8834514f5e3Sopenharmony_ci                r.push_back(ESCAPE_HEX_TO_CHAR[(c >> ESCAPE_HEX_BIT12) & ESCAPE_HEX_MASK]);
8844514f5e3Sopenharmony_ci                r.push_back(ESCAPE_HEX_TO_CHAR[(c >> ESCAPE_HEX_BIT8) & ESCAPE_HEX_MASK]);
8854514f5e3Sopenharmony_ci                r.push_back(ESCAPE_HEX_TO_CHAR[(c >> ESCAPE_HEX_BIT4) & ESCAPE_HEX_MASK]);
8864514f5e3Sopenharmony_ci                r.push_back(ESCAPE_HEX_TO_CHAR[c & ESCAPE_HEX_MASK]);
8874514f5e3Sopenharmony_ci            }
8884514f5e3Sopenharmony_ci        }
8894514f5e3Sopenharmony_ci        ++k;
8904514f5e3Sopenharmony_ci    }
8914514f5e3Sopenharmony_ci    // 7. Return R.
8924514f5e3Sopenharmony_ci    auto *returnData = reinterpret_cast<uint16_t *>(r.data());
8934514f5e3Sopenharmony_ci    uint32_t retSize = r.size();
8944514f5e3Sopenharmony_ci    return factory->NewFromUtf16Literal(returnData, retSize).GetTaggedValue();
8954514f5e3Sopenharmony_ci}
8964514f5e3Sopenharmony_ci
8974514f5e3Sopenharmony_ci// B.2.1.2 unescape ( string )
8984514f5e3Sopenharmony_ciJSTaggedValue BuiltinsGlobal::Unescape(EcmaRuntimeCallInfo *msg)
8994514f5e3Sopenharmony_ci{
9004514f5e3Sopenharmony_ci    ASSERT(msg);
9014514f5e3Sopenharmony_ci    JSThread *thread = msg->GetThread();
9024514f5e3Sopenharmony_ci    BUILTINS_API_TRACE(thread, Global, Unescape);
9034514f5e3Sopenharmony_ci    [[maybe_unused]] EcmaHandleScope handleScope(thread);
9044514f5e3Sopenharmony_ci    // 1. Set string to ? ToString(string).
9054514f5e3Sopenharmony_ci    JSHandle<EcmaString> string = JSTaggedValue::ToString(thread, GetCallArg(msg, 0));
9064514f5e3Sopenharmony_ci    RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
9074514f5e3Sopenharmony_ci    // 2. Let len be the length of string.
9084514f5e3Sopenharmony_ci    uint32_t len = EcmaStringAccessor(string).GetLength();
9094514f5e3Sopenharmony_ci    // 3. Let R be the empty String.
9104514f5e3Sopenharmony_ci    EcmaVM *vm = thread->GetEcmaVM();
9114514f5e3Sopenharmony_ci    ObjectFactory *factory = vm->GetFactory();
9124514f5e3Sopenharmony_ci    std::u16string r;
9134514f5e3Sopenharmony_ci    // 4. Let k be 0.
9144514f5e3Sopenharmony_ci    uint32_t k = 0;
9154514f5e3Sopenharmony_ci    // 5. Repeat, while k < len,
9164514f5e3Sopenharmony_ci    //   a. Let C be the code unit at index k within string.
9174514f5e3Sopenharmony_ci    //   b. If C is the code unit 0x0025 (PERCENT SIGN), then
9184514f5e3Sopenharmony_ci    //     i. Let hexDigits be the empty String.
9194514f5e3Sopenharmony_ci    //     ii. Let optionalAdvance be 0.
9204514f5e3Sopenharmony_ci    //     iii. If k + 5 < len and the code unit at index k + 1 within string is the code unit
9214514f5e3Sopenharmony_ci    //          0x0075 (LATIN SMALL LETTER U), then
9224514f5e3Sopenharmony_ci    //       1. Set hexDigits to the substring of string from k + 2 to k + 6.
9234514f5e3Sopenharmony_ci    //       2. Set optionalAdvance to 5.
9244514f5e3Sopenharmony_ci    //     iv. Else if k + 3 ≤ len, then
9254514f5e3Sopenharmony_ci    //       1. Set hexDigits to the substring of string from k + 1 to k + 3.
9264514f5e3Sopenharmony_ci    //       2. Set optionalAdvance to 2.
9274514f5e3Sopenharmony_ci    //     v. Let parseResult be ParseText(StringToCodePoints(hexDigits), HexDigits[~Sep]).
9284514f5e3Sopenharmony_ci    //     vi. If parseResult is a Parse Node, then
9294514f5e3Sopenharmony_ci    //       1. Let n be the MV of parseResult.
9304514f5e3Sopenharmony_ci    //       2. Set C to the code unit whose numeric value is n.
9314514f5e3Sopenharmony_ci    //       3. Set k to k + optionalAdvance.
9324514f5e3Sopenharmony_ci    //   c. Set R to the string-concatenation of R and C.
9334514f5e3Sopenharmony_ci    //   d. Set k to k + 1.
9344514f5e3Sopenharmony_ci    while (k < len) {
9354514f5e3Sopenharmony_ci        uint16_t c = EcmaStringAccessor(string).Get(k);
9364514f5e3Sopenharmony_ci        if (c == '%') {
9374514f5e3Sopenharmony_ci            uint16_t c1 = EcmaStringAccessor(string).Get(k + 1);
9384514f5e3Sopenharmony_ci            if (k + ESCAPE_CHAR_OFFSET5 < len && c1 == 'u') {
9394514f5e3Sopenharmony_ci                uint16_t c2 = EcmaStringAccessor(string).Get(k + ESCAPE_CHAR_OFFSET2);
9404514f5e3Sopenharmony_ci                uint16_t c3 = EcmaStringAccessor(string).Get(k + ESCAPE_CHAR_OFFSET3);
9414514f5e3Sopenharmony_ci                uint16_t c4 = EcmaStringAccessor(string).Get(k + ESCAPE_CHAR_OFFSET4);
9424514f5e3Sopenharmony_ci                uint16_t c5 = EcmaStringAccessor(string).Get(k + ESCAPE_CHAR_OFFSET5);
9434514f5e3Sopenharmony_ci                bool c2IsHexDigits = IsHexDigits(c2);
9444514f5e3Sopenharmony_ci                bool c3IsHexDigits = IsHexDigits(c3);
9454514f5e3Sopenharmony_ci                bool c4IsHexDigits = IsHexDigits(c4);
9464514f5e3Sopenharmony_ci                bool c5IsHexDigits = IsHexDigits(c5);
9474514f5e3Sopenharmony_ci                bool isHexDigits = c2IsHexDigits && c3IsHexDigits && c4IsHexDigits && c5IsHexDigits;
9484514f5e3Sopenharmony_ci                if (isHexDigits) {
9494514f5e3Sopenharmony_ci                    c = ESCAPE_CHAR_TO_HEX[c2];
9504514f5e3Sopenharmony_ci                    c = (c << ESCAPE_HEX_BIT4) | ESCAPE_CHAR_TO_HEX[c3];
9514514f5e3Sopenharmony_ci                    c = (c << ESCAPE_HEX_BIT4) | ESCAPE_CHAR_TO_HEX[c4];
9524514f5e3Sopenharmony_ci                    c = (c << ESCAPE_HEX_BIT4) | ESCAPE_CHAR_TO_HEX[c5];
9534514f5e3Sopenharmony_ci                    k = k + ESCAPE_CHAR_OFFSET5;
9544514f5e3Sopenharmony_ci                }
9554514f5e3Sopenharmony_ci            } else if (k + ESCAPE_CHAR_OFFSET3 <= len) {
9564514f5e3Sopenharmony_ci                uint16_t c2 = EcmaStringAccessor(string).Get(k + ESCAPE_CHAR_OFFSET2);
9574514f5e3Sopenharmony_ci                bool c1IsHexDigits = IsHexDigits(c1);
9584514f5e3Sopenharmony_ci                bool c2IsHexDigits = IsHexDigits(c2);
9594514f5e3Sopenharmony_ci                bool isHexDigits = c1IsHexDigits && c2IsHexDigits;
9604514f5e3Sopenharmony_ci                if (isHexDigits) {
9614514f5e3Sopenharmony_ci                    c = ESCAPE_CHAR_TO_HEX[c1];
9624514f5e3Sopenharmony_ci                    c = (c << ESCAPE_HEX_BIT4) | ESCAPE_CHAR_TO_HEX[c2];
9634514f5e3Sopenharmony_ci                    k = k + ESCAPE_CHAR_OFFSET2;
9644514f5e3Sopenharmony_ci                }
9654514f5e3Sopenharmony_ci            }
9664514f5e3Sopenharmony_ci        }
9674514f5e3Sopenharmony_ci        r.push_back(c);
9684514f5e3Sopenharmony_ci        ++k;
9694514f5e3Sopenharmony_ci    }
9704514f5e3Sopenharmony_ci    // 7. Return R.
9714514f5e3Sopenharmony_ci    auto *returnData = reinterpret_cast<uint16_t *>(r.data());
9724514f5e3Sopenharmony_ci    uint32_t retSize = r.size();
9734514f5e3Sopenharmony_ci    return factory->NewFromUtf16Literal(returnData, retSize).GetTaggedValue();
9744514f5e3Sopenharmony_ci}
9754514f5e3Sopenharmony_ci
9764514f5e3Sopenharmony_ciJSTaggedValue BuiltinsGlobal::GetCurrentModuleName(EcmaRuntimeCallInfo *msg)
9774514f5e3Sopenharmony_ci{
9784514f5e3Sopenharmony_ci    ASSERT(msg);
9794514f5e3Sopenharmony_ci    JSThread *thread = msg->GetThread();
9804514f5e3Sopenharmony_ci    BUILTINS_API_TRACE(thread, Global, GetCurrentModuleName);
9814514f5e3Sopenharmony_ci    [[maybe_unused]] EcmaHandleScope handleScope(thread);
9824514f5e3Sopenharmony_ci    std::pair<CString, CString> moduleInfo = EcmaInterpreter::GetCurrentEntryPoint(thread);
9834514f5e3Sopenharmony_ci    RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
9844514f5e3Sopenharmony_ci    CString fileName = moduleInfo.second;
9854514f5e3Sopenharmony_ci    CString moduleName = ModulePathHelper::GetModuleNameWithBaseFile(fileName);
9864514f5e3Sopenharmony_ci    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
9874514f5e3Sopenharmony_ci    JSHandle<EcmaString> result = factory->NewFromUtf8(moduleName.c_str());
9884514f5e3Sopenharmony_ci    return result.GetTaggedValue();
9894514f5e3Sopenharmony_ci}
9904514f5e3Sopenharmony_ci
9914514f5e3Sopenharmony_ciJSTaggedValue BuiltinsGlobal::GetCurrentBundleName(EcmaRuntimeCallInfo *msg)
9924514f5e3Sopenharmony_ci{
9934514f5e3Sopenharmony_ci    ASSERT(msg);
9944514f5e3Sopenharmony_ci    JSThread *thread = msg->GetThread();
9954514f5e3Sopenharmony_ci    BUILTINS_API_TRACE(thread, Global, GetCurrentBundleName);
9964514f5e3Sopenharmony_ci    [[maybe_unused]] EcmaHandleScope handleScope(thread);
9974514f5e3Sopenharmony_ci    std::pair<CString, CString> moduleInfo = EcmaInterpreter::GetCurrentEntryPoint(thread);
9984514f5e3Sopenharmony_ci    RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
9994514f5e3Sopenharmony_ci    EcmaVM *vm = thread->GetEcmaVM();
10004514f5e3Sopenharmony_ci    CString recordName = moduleInfo.first;
10014514f5e3Sopenharmony_ci    CString bundleName = ModulePathHelper::GetBundleNameWithRecordName(vm, recordName);
10024514f5e3Sopenharmony_ci    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
10034514f5e3Sopenharmony_ci    JSHandle<EcmaString> result = factory->NewFromUtf8(bundleName.c_str());
10044514f5e3Sopenharmony_ci    return result.GetTaggedValue();
10054514f5e3Sopenharmony_ci}
10064514f5e3Sopenharmony_ci
10074514f5e3Sopenharmony_ciJSTaggedValue BuiltinsGlobal::IsSendable(EcmaRuntimeCallInfo *msg)
10084514f5e3Sopenharmony_ci{
10094514f5e3Sopenharmony_ci    ASSERT(msg);
10104514f5e3Sopenharmony_ci    JSThread *thread = msg->GetThread();
10114514f5e3Sopenharmony_ci    [[maybe_unused]] EcmaHandleScope handleScope(thread);
10124514f5e3Sopenharmony_ci
10134514f5e3Sopenharmony_ci    uint32_t numArgs = msg->GetArgsNumber();
10144514f5e3Sopenharmony_ci    if (numArgs != 1) {
10154514f5e3Sopenharmony_ci        LOG_FULL(ERROR) << "The number of parameters received by IsSendable is incorrect.";
10164514f5e3Sopenharmony_ci        return JSTaggedValue::False();
10174514f5e3Sopenharmony_ci    }
10184514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> obj = GetCallArg(msg, 0);
10194514f5e3Sopenharmony_ci    if ((obj->IsECMAObject() && obj->IsJSShared()) ||
10204514f5e3Sopenharmony_ci        obj->IsString() || obj->IsNumber() || obj->IsBoolean() ||
10214514f5e3Sopenharmony_ci        obj->IsUndefined() || obj->IsNull() || obj->IsBigInt()) {
10224514f5e3Sopenharmony_ci        return JSTaggedValue::True();
10234514f5e3Sopenharmony_ci    }
10244514f5e3Sopenharmony_ci
10254514f5e3Sopenharmony_ci    return JSTaggedValue::False();
10264514f5e3Sopenharmony_ci}
10274514f5e3Sopenharmony_ci}  // namespace panda::ecmascript::builtins
1028