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