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 using judgURIFunc = bool (*)(uint16_t); 100 101 enum class Placement { 102 START = 0, 103 END, 104 }; 105 106 class BuiltinsGlobal : public base::BuiltinsBase { 107 public: 108 static const inline JSTaggedValue INFINITY_VALUE = JSTaggedValue(base::POSITIVE_INFINITY); 109 static const inline JSTaggedValue NAN_VALUE = JSTaggedValue(base::NAN_VALUE); 110 static const inline JSTaggedValue UNDEFINED_VALUE = JSTaggedValue::Undefined(); 111 112 // 18.2.1 113 static JSTaggedValue NotSupportEval(EcmaRuntimeCallInfo *msg); 114 // 18.2.2 115 static JSTaggedValue IsFinite(EcmaRuntimeCallInfo *msg); 116 // 18.2.3 117 static JSTaggedValue IsNaN(EcmaRuntimeCallInfo *msg); 118 // 18.2.6 119 static JSTaggedValue DecodeURI(EcmaRuntimeCallInfo *msg); 120 static JSTaggedValue EncodeURI(EcmaRuntimeCallInfo *msg); 121 static JSTaggedValue DecodeURIComponent(EcmaRuntimeCallInfo *msg); 122 static JSTaggedValue EncodeURIComponent(EcmaRuntimeCallInfo *msg); 123 124 static JSTaggedValue PrintEntrypoint(EcmaRuntimeCallInfo *msg); 125 static JSTaggedValue MarkModuleCollectable(EcmaRuntimeCallInfo *msg); 126 static JSTaggedValue LoadNativeModule(EcmaRuntimeCallInfo *msg); 127 static JSTaggedValue CallJsBoundFunction(EcmaRuntimeCallInfo *msg); 128 static JSTaggedValue CallJsProxy(EcmaRuntimeCallInfo *msg); 129 static JSTaggedValue IsSendable(EcmaRuntimeCallInfo *msg); 130 131 static JSTaggedValue GetCurrentModuleName(EcmaRuntimeCallInfo *msg); 132 static JSTaggedValue GetCurrentBundleName(EcmaRuntimeCallInfo *msg); 133 #if ECMASCRIPT_ENABLE_RUNTIME_STAT 134 static JSTaggedValue StartRuntimeStat(EcmaRuntimeCallInfo *msg); 135 static JSTaggedValue StopRuntimeStat(EcmaRuntimeCallInfo *msg); 136 #endif 137 138 #if ECMASCRIPT_ENABLE_OPT_CODE_PROFILER 139 static JSTaggedValue PrintOptStat(EcmaRuntimeCallInfo *msg); 140 #endif 141 142 #if ECMASCRIPT_ENABLE_FUNCTION_CALL_TIMER 143 static JSTaggedValue PrintFunctionCallStat(EcmaRuntimeCallInfo *msg); 144 #endif 145 // B.2.1.1 escape ( string ) 146 static JSTaggedValue Escape(EcmaRuntimeCallInfo *msg); 147 // B.2.1.2 unescape ( string ) 148 static JSTaggedValue Unescape(EcmaRuntimeCallInfo *msg); 149 GetGlobalConstants()150 static Span<const base::BuiltinConstantEntry> GetGlobalConstants() 151 { 152 return Span<const base::BuiltinConstantEntry>(GLOBAL_CONSTANTS); 153 } 154 GetGlobalFunctions()155 static Span<const base::BuiltinFunctionEntry> GetGlobalFunctions() 156 { 157 return Span<const base::BuiltinFunctionEntry>(GLOBAL_FUNCTIONS); 158 } 159 160 private: 161 #define BUILTIN_GLOBAL_CONSTANT_ENTRY(name, var) \ 162 base::BuiltinConstantEntry::Create(name, BuiltinsGlobal::var), 163 #define BUILTIN_GLOBAL_FUNCTION_ENTRY(name, func, length, id) \ 164 base::BuiltinFunctionEntry::Create(name, BuiltinsGlobal::func, length, kungfu::BuiltinsStubCSigns::id), 165 166 static inline std::array GLOBAL_CONSTANTS = { 167 BUILTIN_GLOBAL_CONSTANTS(BUILTIN_GLOBAL_CONSTANT_ENTRY) 168 }; 169 static constexpr std::array GLOBAL_FUNCTIONS = { 170 BUILTIN_GLOBAL_FUNCTIONS(BUILTIN_GLOBAL_FUNCTION_ENTRY) 171 }; 172 #undef BUILTIN_GLOBAL_CONSTANT_ENTRY 173 #undef BUILTIN_GLOBAL_FUNCTION_ENTRY 174 175 static void PrintString(JSThread *thread, EcmaString *string); 176 static void PrintValue(int64_t value, int64_t tag); 177 static JSTaggedValue Encode(JSThread *thread, const JSHandle<EcmaString> &str, judgURIFunc IsInURISet); 178 static JSTaggedValue Decode(JSThread *thread, const JSHandle<EcmaString> &str, judgURIFunc IsInURISet); 179 static JSTaggedValue UTF16EncodeCodePoint(JSThread *thread, judgURIFunc IsInURISet, 180 const std::vector<uint8_t> &oct, const JSHandle<EcmaString> &str, 181 uint32_t &start, int32_t &k, std::u16string &sStr); 182 static void HandleSingleByteCharacter(JSThread *thread, uint8_t &bb, 183 const JSHandle<EcmaString> &str, 184 uint32_t &start, int32_t &k, 185 std::u16string &sStr, judgURIFunc IsInURISet); 186 static JSTaggedValue DecodePercentEncoding(JSThread *thread, int32_t &n, 187 int32_t &k, const JSHandle<EcmaString> &str, 188 uint8_t &bb, std::vector<uint8_t> &oct); 189 static JSTaggedValue DecodePercentEncoding(JSThread *thread, const JSHandle<EcmaString> &str, int32_t &k, 190 judgURIFunc IsInURISet, int32_t strLen, std::u16string &sStr); 191 static bool IsUnescapedURI(uint16_t ch); 192 static bool IsInUnescapedURISet(uint16_t ch); 193 static bool IsInReservedURISet(uint16_t ch); 194 static bool IsReservedURI(uint16_t ch); 195 static bool IsInMarkURISet(uint16_t ch); 196 static bool IsHexDigits(uint16_t ch); 197 static uint8_t GetValueFromTwoHex(uint16_t front, uint16_t behind); 198 static uint16_t GetValueFromHexString(const JSHandle<EcmaString> &string); 199 // 22.1.3.17.2 StringPad ( S, maxLength, fillString, placement ) 200 static EcmaString *StringPad(JSThread *thread, 201 const JSHandle<EcmaString> &string, 202 uint32_t maxLength, 203 const JSHandle<EcmaString> &fillString, 204 Placement placement = Placement::START); IsUTF16HighSurrogate(uint16_t ch)205 static bool IsUTF16HighSurrogate(uint16_t ch) 206 { 207 return base::utf_helper::DECODE_LEAD_LOW <= ch && ch <= base::utf_helper::DECODE_LEAD_HIGH; 208 } 209 IsUTF16LowSurrogate(uint16_t ch)210 static bool IsUTF16LowSurrogate(uint16_t ch) 211 { 212 return base::utf_helper::DECODE_TRAIL_LOW <= ch && ch <= base::utf_helper::DECODE_TRAIL_HIGH; 213 } 214 215 // 11.1.3 Static Semantics: UTF16SurrogatePairToCodePoint ( lead, trail ) 216 static uint16_t UTF16SurrogatePairToCodePoint(uint16_t lead, uint16_t trail); 217 // 11.1.5 Static Semantics: StringToCodePoints ( string ) 218 static EcmaString *StringToCodePoints(JSThread *thread, const JSHandle<EcmaString> &string); 219 }; 220 } // namespace panda::ecmascript::builtins 221 222 #endif // ECMASCRIPT_BUILTINS_BUILTINS_ERROR_H 223