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