1 /* 2 * Copyright (c) 2021 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef ECMASCRIPT_BUILTINS_BUILTINS_GLOBAL_H 17 #define ECMASCRIPT_BUILTINS_BUILTINS_GLOBAL_H 18 19 #include "ecmascript/base/builtins_base.h" 20 #include "ecmascript/js_thread.h" 21 22 #define BUILTIN_GLOBAL_CONSTANTS(V) \ 23 V("Infinity", INFINITY_VALUE) \ 24 V("NaN", NAN_VALUE) \ 25 V("undefined", UNDEFINED_VALUE) 26 27 // List of functions in the global object. 28 // V(name, func, length, stubIndex) 29 // where BuiltinsGlobal::func refers to the native implementation of globalThis[name]. 30 // kungfu::BuiltinsStubCSigns::stubIndex refers to the builtin stub index, or INVALID if no stub available. 31 // The following global object properties are not implemented yet: 32 // - Encode ( string, extraUnescaped ) 33 // - Decode ( string, preserveEscapeSet ) 34 // - ParseHexOctet ( string, position ) 35 // The following global object properties are not listed here: 36 // - parseFloat ( string ), listed in builtins_number.h instead. 37 // - parseInt ( string ), listed in builtins_number.h instead. 38 #define BUILTIN_GLOBAL_FUNCTIONS_COMMON(V) \ 39 /* decodeURI ( encodedURI ) */ \ 40 V("decodeURI", DecodeURI, 1, INVALID) \ 41 /* decodeURIComponent ( encodedURIComponent ) */ \ 42 V("decodeURIComponent", DecodeURIComponent, 1, GlobalDecodeURIComponent) \ 43 /* encodeURI ( uri ) */ \ 44 V("encodeURI", EncodeURI, 1, INVALID) \ 45 /* encodeURIComponent ( uriComponent ) */ \ 46 V("encodeURIComponent", EncodeURIComponent, 1, INVALID) \ 47 /* escape ( string ), defined in B.2.1 */ \ 48 V("escape", Escape, 1, INVALID) \ 49 /* eval ( x ), which is NOT supported in ArkTS engine */ \ 50 V("eval", NotSupportEval, 1, INVALID) \ 51 /* isFinite ( number ) */ \ 52 V("isFinite", IsFinite, 1, GlobalIsFinite) \ 53 /* isNaN ( number ) */ \ 54 V("isNaN", IsNaN, 1, GlobalIsNan) \ 55 /* unescape ( string )*/ \ 56 V("unescape", Unescape, 1, INVALID) \ 57 /* The following are ArkTS extensions */ \ 58 V("markModuleCollectable", MarkModuleCollectable, 0, INVALID) \ 59 V("loadNativeModule", LoadNativeModule, 0, INVALID) \ 60 V("print", PrintEntrypoint, 0, INVALID) \ 61 V("isSendable", IsSendable, 0, INVALID) \ 62 V("__getCurrentModuleName__", GetCurrentModuleName, 0, INVALID) \ 63 V("__getCurrentBundleName__", GetCurrentBundleName, 0, INVALID) 64 #if ECMASCRIPT_ENABLE_RUNTIME_STAT 65 #define BUILTIN_GLOBAL_FUNCTIONS_RUNTIME_STAT(V) \ 66 V("startRuntimeStat", StartRuntimeStat, 0, INVALID) \ 67 V("stopRuntimeStat", StopRuntimeStat, 0, INVALID) 68 #else 69 #define BUILTIN_GLOBAL_FUNCTIONS_RUNTIME_STAT(V) // Nothing 70 #endif 71 72 #if ECMASCRIPT_ENABLE_OPT_CODE_PROFILER 73 #define BUILTIN_GLOBAL_FUNCTIONS_OPT_CODE_PROFILER(V) \ 74 V("printOptStat", PrintOptStat, 0, INVALID) 75 #else 76 #define BUILTIN_GLOBAL_FUNCTIONS_OPT_CODE_PROFILER(V) // Nothing 77 #endif 78 79 #if ECMASCRIPT_ENABLE_FUNCTION_CALL_TIMER 80 #define BUILTIN_GLOBAL_FUNCTIONS_FUNCTION_CALL_TIMER(V) \ 81 V("printFunctionCallStat", PrintFunctionCallStat, 0, INVALID) 82 #else 83 #define BUILTIN_GLOBAL_FUNCTIONS_FUNCTION_CALL_TIMER(V) // Nothing 84 #endif 85 86 #define BUILTIN_GLOBAL_FUNCTIONS(V) \ 87 BUILTIN_GLOBAL_FUNCTIONS_COMMON(V) \ 88 BUILTIN_GLOBAL_FUNCTIONS_RUNTIME_STAT(V) \ 89 BUILTIN_GLOBAL_FUNCTIONS_OPT_CODE_PROFILER(V) \ 90 BUILTIN_GLOBAL_FUNCTIONS_FUNCTION_CALL_TIMER(V) 91 92 namespace panda::ecmascript::builtins { 93 static constexpr uint8_t BIT_MASK = 0x0F; 94 static constexpr uint8_t BIT_MASK_FF = 0xFF; 95 static constexpr uint16_t BIT_MASK_4F = 0xFFFF; 96 static constexpr uint16_t BIT16_MASK = 0x3FF; 97 static constexpr uint8_t BIT_MASK_ONE = 0x80; 98 static constexpr uint8_t BIT_MASK_TWO = 0xC0; 99 static constexpr uint8_t BIT_MASK_THR = 0xE0; 100 static constexpr uint8_t BIT_MASK_FOR = 0xF0; 101 using judgURIFunc = bool (*)(uint16_t); 102 103 enum class Placement { 104 START = 0, 105 END, 106 }; 107 108 class BuiltinsGlobal : public base::BuiltinsBase { 109 public: 110 static const inline JSTaggedValue INFINITY_VALUE = JSTaggedValue(base::POSITIVE_INFINITY); 111 static const inline JSTaggedValue NAN_VALUE = JSTaggedValue(base::NAN_VALUE); 112 static const inline JSTaggedValue UNDEFINED_VALUE = JSTaggedValue::Undefined(); 113 114 // 18.2.1 115 static JSTaggedValue NotSupportEval(EcmaRuntimeCallInfo *msg); 116 // 18.2.2 117 static JSTaggedValue IsFinite(EcmaRuntimeCallInfo *msg); 118 // 18.2.3 119 static JSTaggedValue IsNaN(EcmaRuntimeCallInfo *msg); 120 // 18.2.6 121 static JSTaggedValue DecodeURI(EcmaRuntimeCallInfo *msg); 122 static JSTaggedValue EncodeURI(EcmaRuntimeCallInfo *msg); 123 static JSTaggedValue DecodeURIComponent(EcmaRuntimeCallInfo *msg); 124 static JSTaggedValue EncodeURIComponent(EcmaRuntimeCallInfo *msg); 125 126 static JSTaggedValue PrintEntrypoint(EcmaRuntimeCallInfo *msg); 127 static JSTaggedValue MarkModuleCollectable(EcmaRuntimeCallInfo *msg); 128 static JSTaggedValue LoadNativeModule(EcmaRuntimeCallInfo *msg); 129 static JSTaggedValue CallJsBoundFunction(EcmaRuntimeCallInfo *msg); 130 static JSTaggedValue CallJsProxy(EcmaRuntimeCallInfo *msg); 131 static JSTaggedValue IsSendable(EcmaRuntimeCallInfo *msg); 132 133 static JSTaggedValue GetCurrentModuleName(EcmaRuntimeCallInfo *msg); 134 static JSTaggedValue GetCurrentBundleName(EcmaRuntimeCallInfo *msg); 135 #if ECMASCRIPT_ENABLE_RUNTIME_STAT 136 static JSTaggedValue StartRuntimeStat(EcmaRuntimeCallInfo *msg); 137 static JSTaggedValue StopRuntimeStat(EcmaRuntimeCallInfo *msg); 138 #endif 139 140 #if ECMASCRIPT_ENABLE_OPT_CODE_PROFILER 141 static JSTaggedValue PrintOptStat(EcmaRuntimeCallInfo *msg); 142 #endif 143 144 #if ECMASCRIPT_ENABLE_FUNCTION_CALL_TIMER 145 static JSTaggedValue PrintFunctionCallStat(EcmaRuntimeCallInfo *msg); 146 #endif 147 148 #if ECMASCRIPT_ENABLE_MEGA_PROFILER 149 static JSTaggedValue PrintMegaICStat(EcmaRuntimeCallInfo *msg); 150 #endif 151 152 // B.2.1.1 escape ( string ) 153 static JSTaggedValue Escape(EcmaRuntimeCallInfo *msg); 154 // B.2.1.2 unescape ( string ) 155 static JSTaggedValue Unescape(EcmaRuntimeCallInfo *msg); 156 GetGlobalConstants()157 static Span<const base::BuiltinConstantEntry> GetGlobalConstants() 158 { 159 return Span<const base::BuiltinConstantEntry>(GLOBAL_CONSTANTS); 160 } 161 GetGlobalFunctions()162 static Span<const base::BuiltinFunctionEntry> GetGlobalFunctions() 163 { 164 return Span<const base::BuiltinFunctionEntry>(GLOBAL_FUNCTIONS); 165 } 166 167 private: 168 #define BUILTIN_GLOBAL_CONSTANT_ENTRY(name, var) \ 169 base::BuiltinConstantEntry::Create(name, BuiltinsGlobal::var), 170 #define BUILTIN_GLOBAL_FUNCTION_ENTRY(name, func, length, id) \ 171 base::BuiltinFunctionEntry::Create(name, BuiltinsGlobal::func, length, BUILTINS_STUB_ID(id)), 172 173 static inline std::array GLOBAL_CONSTANTS = { 174 BUILTIN_GLOBAL_CONSTANTS(BUILTIN_GLOBAL_CONSTANT_ENTRY) 175 }; 176 static constexpr std::array GLOBAL_FUNCTIONS = { 177 BUILTIN_GLOBAL_FUNCTIONS(BUILTIN_GLOBAL_FUNCTION_ENTRY) 178 }; 179 #undef BUILTIN_GLOBAL_CONSTANT_ENTRY 180 #undef BUILTIN_GLOBAL_FUNCTION_ENTRY 181 182 static void PrintString(JSThread *thread, EcmaString *string); 183 static void PrintValue(int64_t value, int64_t tag); 184 static JSTaggedValue Encode(JSThread *thread, const JSHandle<EcmaString> &str, judgURIFunc IsInURISet); 185 static JSTaggedValue Decode(JSThread *thread, const JSHandle<EcmaString> &str, judgURIFunc IsInURISet); 186 #if ENABLE_NEXT_OPTIMIZATION 187 template <typename T> 188 static JSTaggedValue DoDecode(JSThread *thread, const JSHandle<EcmaString> &str, judgURIFunc IsInURISet, 189 const T *data); 190 static JSTaggedValue UTF16EncodeCodePoint(JSThread *thread, judgURIFunc IsInURISet, 191 const std::vector<uint8_t> &oct, const JSHandle<EcmaString> &str, 192 uint32_t &start, int32_t &k, std::u16string &resStr); 193 static void HandleSingleByteCharacter(JSThread *thread, uint8_t &bb, 194 const JSHandle<EcmaString> &str, 195 uint32_t &start, int32_t &k, 196 std::u16string &resStr, judgURIFunc IsInURISet); 197 template <typename T> 198 static inline uint16_t GetCodeUnit(Span<T> &sp, int32_t index, int32_t length); 199 template <typename T> 200 static JSTaggedValue DecodePercentEncoding(JSThread *thread, int32_t &n, 201 int32_t &k, const JSHandle<EcmaString> &str, 202 uint8_t &bb, std::vector<uint8_t> &oct, Span<T> &sp, int32_t strLen); 203 template <typename T> 204 static JSTaggedValue DecodePercentEncoding(JSThread *thread, const JSHandle<EcmaString> &str, int32_t &k, 205 judgURIFunc IsInURISet, int32_t strLen, std::u16string &resStr, 206 Span<T> &sp); 207 static inline bool IsUnescapedURI(uint16_t ch); 208 static inline bool IsInUnescapedURISet(uint16_t ch); 209 static inline bool IsInReservedURISet(uint16_t ch); 210 static inline bool IsReservedURI(uint16_t ch); 211 static inline bool IsInMarkURISet(uint16_t ch); 212 static inline void AppendPercentEncodedByte(std::u16string& sStr, uint8_t byte, uint8_t &len); 213 static inline void AppendU32Data(std::u16string &resStr, uint32_t data); 214 #else // ENABLE_NEXT_OPTIMIZATION 215 static JSTaggedValue UTF16EncodeCodePoint(JSThread *thread, judgURIFunc IsInURISet, 216 const std::vector<uint8_t> &oct, const JSHandle<EcmaString> &str, 217 uint32_t &start, int32_t &k, std::u16string &sStr); 218 static void HandleSingleByteCharacter(JSThread *thread, uint8_t &bb, 219 const JSHandle<EcmaString> &str, 220 uint32_t &start, int32_t &k, 221 std::u16string &sStr, judgURIFunc IsInURISet); 222 static JSTaggedValue DecodePercentEncoding(JSThread *thread, int32_t &n, 223 int32_t &k, const JSHandle<EcmaString> &str, 224 uint8_t &bb, std::vector<uint8_t> &oct); 225 static JSTaggedValue DecodePercentEncoding(JSThread *thread, const JSHandle<EcmaString> &str, int32_t &k, 226 judgURIFunc IsInURISet, int32_t strLen, std::u16string &sStr); 227 static bool IsUnescapedURI(uint16_t ch); 228 static bool IsInUnescapedURISet(uint16_t ch); 229 static bool IsInReservedURISet(uint16_t ch); 230 static bool IsReservedURI(uint16_t ch); 231 static bool IsInMarkURISet(uint16_t ch); 232 static bool IsHexDigits(uint16_t ch); 233 static uint8_t GetValueFromTwoHex(uint16_t front, uint16_t behind); 234 #endif // ENABLE_NEXT_OPTIMIZATION 235 static uint16_t GetValueFromHexString(JSThread *thread, const JSHandle<EcmaString> &string); 236 // 22.1.3.17.2 StringPad ( S, maxLength, fillString, placement ) 237 static EcmaString *StringPad(JSThread *thread, 238 const JSHandle<EcmaString> &string, 239 uint32_t maxLength, 240 const JSHandle<EcmaString> &fillString, 241 Placement placement = Placement::START); IsUTF16HighSurrogate(uint16_t ch)242 static bool IsUTF16HighSurrogate(uint16_t ch) 243 { 244 return common::utf_helper::DECODE_LEAD_LOW <= ch && ch <= common::utf_helper::DECODE_LEAD_HIGH; 245 } 246 IsUTF16LowSurrogate(uint16_t ch)247 static bool IsUTF16LowSurrogate(uint16_t ch) 248 { 249 return common::utf_helper::DECODE_TRAIL_LOW <= ch && ch <= common::utf_helper::DECODE_TRAIL_HIGH; 250 } 251 252 // 11.1.3 Static Semantics: UTF16SurrogatePairToCodePoint ( lead, trail ) 253 static uint16_t UTF16SurrogatePairToCodePoint(uint16_t lead, uint16_t trail); 254 // 11.1.5 Static Semantics: StringToCodePoints ( string ) 255 static EcmaString *StringToCodePoints(JSThread *thread, const JSHandle<EcmaString> &string); 256 }; 257 } // namespace panda::ecmascript::builtins 258 259 #endif // ECMASCRIPT_BUILTINS_BUILTINS_ERROR_H 260