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
92namespace panda::ecmascript::builtins {
93static constexpr uint8_t BIT_MASK = 0x0F;
94static constexpr uint8_t BIT_MASK_FF = 0xFF;
95static constexpr uint16_t BIT_MASK_4F = 0xFFFF;
96static constexpr uint16_t BIT16_MASK = 0x3FF;
97static constexpr uint8_t BIT_MASK_ONE = 0x80;
98static constexpr uint8_t BIT_MASK_TWO = 0xC0;
99using judgURIFunc = bool (*)(uint16_t);
100
101enum class Placement {
102    START = 0,
103    END,
104};
105
106class BuiltinsGlobal : public base::BuiltinsBase {
107public:
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
150    static Span<const base::BuiltinConstantEntry> GetGlobalConstants()
151    {
152        return Span<const base::BuiltinConstantEntry>(GLOBAL_CONSTANTS);
153    }
154
155    static Span<const base::BuiltinFunctionEntry> GetGlobalFunctions()
156    {
157        return Span<const base::BuiltinFunctionEntry>(GLOBAL_FUNCTIONS);
158    }
159
160private:
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);
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
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