* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ECMASCRIPT_BUILTINS_BUILTINS_GLOBAL_H
#define ECMASCRIPT_BUILTINS_BUILTINS_GLOBAL_H
#include "ecmascript/base/builtins_base.h"
#include "ecmascript/js_thread.h"
#define BUILTIN_GLOBAL_CONSTANTS(V) \
V("Infinity", INFINITY_VALUE) \
V("NaN", NAN_VALUE) \
V("undefined", UNDEFINED_VALUE)
#define BUILTIN_GLOBAL_FUNCTIONS_COMMON(V) \
\
V("decodeURI", DecodeURI, 1, INVALID) \
\
V("decodeURIComponent", DecodeURIComponent, 1, GlobalDecodeURIComponent) \
\
V("encodeURI", EncodeURI, 1, INVALID) \
\
V("encodeURIComponent", EncodeURIComponent, 1, INVALID) \
\
V("escape", Escape, 1, INVALID) \
\
V("eval", NotSupportEval, 1, INVALID) \
\
V("isFinite", IsFinite, 1, GlobalIsFinite) \
\
V("isNaN", IsNaN, 1, GlobalIsNan) \
\
V("unescape", Unescape, 1, INVALID) \
\
V("markModuleCollectable", MarkModuleCollectable, 0, INVALID) \
V("loadNativeModule", LoadNativeModule, 0, INVALID) \
V("print", PrintEntrypoint, 0, INVALID) \
V("isSendable", IsSendable, 0, INVALID) \
V("__getCurrentModuleName__", GetCurrentModuleName, 0, INVALID) \
V("__getCurrentBundleName__", GetCurrentBundleName, 0, INVALID)
#if ECMASCRIPT_ENABLE_RUNTIME_STAT
#define BUILTIN_GLOBAL_FUNCTIONS_RUNTIME_STAT(V) \
V("startRuntimeStat", StartRuntimeStat, 0, INVALID) \
V("stopRuntimeStat", StopRuntimeStat, 0, INVALID)
#else
#define BUILTIN_GLOBAL_FUNCTIONS_RUNTIME_STAT(V)
#endif
#if ECMASCRIPT_ENABLE_OPT_CODE_PROFILER
#define BUILTIN_GLOBAL_FUNCTIONS_OPT_CODE_PROFILER(V) \
V("printOptStat", PrintOptStat, 0, INVALID)
#else
#define BUILTIN_GLOBAL_FUNCTIONS_OPT_CODE_PROFILER(V)
#endif
#if ECMASCRIPT_ENABLE_FUNCTION_CALL_TIMER
#define BUILTIN_GLOBAL_FUNCTIONS_FUNCTION_CALL_TIMER(V) \
V("printFunctionCallStat", PrintFunctionCallStat, 0, INVALID)
#else
#define BUILTIN_GLOBAL_FUNCTIONS_FUNCTION_CALL_TIMER(V)
#endif
#define BUILTIN_GLOBAL_FUNCTIONS(V) \
BUILTIN_GLOBAL_FUNCTIONS_COMMON(V) \
BUILTIN_GLOBAL_FUNCTIONS_RUNTIME_STAT(V) \
BUILTIN_GLOBAL_FUNCTIONS_OPT_CODE_PROFILER(V) \
BUILTIN_GLOBAL_FUNCTIONS_FUNCTION_CALL_TIMER(V)
namespace panda::ecmascript::builtins {
static constexpr uint8_t BIT_MASK = 0x0F;
static constexpr uint8_t BIT_MASK_FF = 0xFF;
static constexpr uint16_t BIT_MASK_4F = 0xFFFF;
static constexpr uint16_t BIT16_MASK = 0x3FF;
static constexpr uint8_t BIT_MASK_ONE = 0x80;
static constexpr uint8_t BIT_MASK_TWO = 0xC0;
static constexpr uint8_t BIT_MASK_THR = 0xE0;
static constexpr uint8_t BIT_MASK_FOR = 0xF0;
using judgURIFunc = bool (*)(uint16_t);
enum class Placement {
START = 0,
END,
};
class BuiltinsGlobal : public base::BuiltinsBase {
public:
static const inline JSTaggedValue INFINITY_VALUE = JSTaggedValue(base::POSITIVE_INFINITY);
static const inline JSTaggedValue NAN_VALUE = JSTaggedValue(base::NAN_VALUE);
static const inline JSTaggedValue UNDEFINED_VALUE = JSTaggedValue::Undefined();
static JSTaggedValue NotSupportEval(EcmaRuntimeCallInfo *msg);
static JSTaggedValue IsFinite(EcmaRuntimeCallInfo *msg);
static JSTaggedValue IsNaN(EcmaRuntimeCallInfo *msg);
static JSTaggedValue DecodeURI(EcmaRuntimeCallInfo *msg);
static JSTaggedValue EncodeURI(EcmaRuntimeCallInfo *msg);
static JSTaggedValue DecodeURIComponent(EcmaRuntimeCallInfo *msg);
static JSTaggedValue EncodeURIComponent(EcmaRuntimeCallInfo *msg);
static JSTaggedValue PrintEntrypoint(EcmaRuntimeCallInfo *msg);
static JSTaggedValue MarkModuleCollectable(EcmaRuntimeCallInfo *msg);
static JSTaggedValue LoadNativeModule(EcmaRuntimeCallInfo *msg);
static JSTaggedValue CallJsBoundFunction(EcmaRuntimeCallInfo *msg);
static JSTaggedValue CallJsProxy(EcmaRuntimeCallInfo *msg);
static JSTaggedValue IsSendable(EcmaRuntimeCallInfo *msg);
static JSTaggedValue GetCurrentModuleName(EcmaRuntimeCallInfo *msg);
static JSTaggedValue GetCurrentBundleName(EcmaRuntimeCallInfo *msg);
#if ECMASCRIPT_ENABLE_RUNTIME_STAT
static JSTaggedValue StartRuntimeStat(EcmaRuntimeCallInfo *msg);
static JSTaggedValue StopRuntimeStat(EcmaRuntimeCallInfo *msg);
#endif
#if ECMASCRIPT_ENABLE_OPT_CODE_PROFILER
static JSTaggedValue PrintOptStat(EcmaRuntimeCallInfo *msg);
#endif
#if ECMASCRIPT_ENABLE_FUNCTION_CALL_TIMER
static JSTaggedValue PrintFunctionCallStat(EcmaRuntimeCallInfo *msg);
#endif
#if ECMASCRIPT_ENABLE_MEGA_PROFILER
static JSTaggedValue PrintMegaICStat(EcmaRuntimeCallInfo *msg);
#endif
static JSTaggedValue Escape(EcmaRuntimeCallInfo *msg);
static JSTaggedValue Unescape(EcmaRuntimeCallInfo *msg);
static Span<const base::BuiltinConstantEntry> GetGlobalConstants()
{
return Span<const base::BuiltinConstantEntry>(GLOBAL_CONSTANTS);
}
static Span<const base::BuiltinFunctionEntry> GetGlobalFunctions()
{
return Span<const base::BuiltinFunctionEntry>(GLOBAL_FUNCTIONS);
}
private:
#define BUILTIN_GLOBAL_CONSTANT_ENTRY(name, var) \
base::BuiltinConstantEntry::Create(name, BuiltinsGlobal::var),
#define BUILTIN_GLOBAL_FUNCTION_ENTRY(name, func, length, id) \
base::BuiltinFunctionEntry::Create(name, BuiltinsGlobal::func, length, BUILTINS_STUB_ID(id)),
static inline std::array GLOBAL_CONSTANTS = {
BUILTIN_GLOBAL_CONSTANTS(BUILTIN_GLOBAL_CONSTANT_ENTRY)
};
static constexpr std::array GLOBAL_FUNCTIONS = {
BUILTIN_GLOBAL_FUNCTIONS(BUILTIN_GLOBAL_FUNCTION_ENTRY)
};
#undef BUILTIN_GLOBAL_CONSTANT_ENTRY
#undef BUILTIN_GLOBAL_FUNCTION_ENTRY
static void PrintString(JSThread *thread, EcmaString *string);
static void PrintValue(int64_t value, int64_t tag);
static JSTaggedValue Encode(JSThread *thread, const JSHandle<EcmaString> &str, judgURIFunc IsInURISet);
static JSTaggedValue Decode(JSThread *thread, const JSHandle<EcmaString> &str, judgURIFunc IsInURISet);
template <typename T>
static JSTaggedValue DoDecode(JSThread *thread, const JSHandle<EcmaString> &str, judgURIFunc IsInURISet,
const T *data);
static JSTaggedValue UTF16EncodeCodePoint(JSThread *thread, judgURIFunc IsInURISet,
const std::vector<uint8_t> &oct, const JSHandle<EcmaString> &str,
uint32_t &start, int32_t &k, std::u16string &resStr);
static void HandleSingleByteCharacter(JSThread *thread, uint8_t &bb,
const JSHandle<EcmaString> &str,
uint32_t &start, int32_t &k,
std::u16string &resStr, judgURIFunc IsInURISet);
template <typename T>
static inline uint16_t GetCodeUnit(Span<T> &sp, int32_t index, int32_t length);
template <typename T>
static JSTaggedValue DecodePercentEncoding(JSThread *thread, int32_t &n,
int32_t &k, const JSHandle<EcmaString> &str,
uint8_t &bb, std::vector<uint8_t> &oct, Span<T> &sp, int32_t strLen);
template <typename T>
static JSTaggedValue DecodePercentEncoding(JSThread *thread, const JSHandle<EcmaString> &str, int32_t &k,
judgURIFunc IsInURISet, int32_t strLen, std::u16string &resStr,
Span<T> &sp);
static inline bool IsUnescapedURI(uint16_t ch);
static inline bool IsInUnescapedURISet(uint16_t ch);
static inline bool IsInReservedURISet(uint16_t ch);
static inline bool IsReservedURI(uint16_t ch);
static inline bool IsInMarkURISet(uint16_t ch);
static inline void AppendPercentEncodedByte(std::u16string& sStr, uint8_t byte, uint8_t &len);
static inline void AppendU32Data(std::u16string &resStr, uint32_t data);
static uint16_t GetValueFromHexString(JSThread *thread, const JSHandle<EcmaString> &string);
static EcmaString *StringPad(JSThread *thread,
const JSHandle<EcmaString> &string,
uint32_t maxLength,
const JSHandle<EcmaString> &fillString,
Placement placement = Placement::START);
static bool IsUTF16HighSurrogate(uint16_t ch)
{
return common::utf_helper::DECODE_LEAD_LOW <= ch && ch <= common::utf_helper::DECODE_LEAD_HIGH;
}
static bool IsUTF16LowSurrogate(uint16_t ch)
{
return common::utf_helper::DECODE_TRAIL_LOW <= ch && ch <= common::utf_helper::DECODE_TRAIL_HIGH;
}
static uint16_t UTF16SurrogatePairToCodePoint(uint16_t lead, uint16_t trail);
static EcmaString *StringToCodePoints(JSThread *thread, const JSHandle<EcmaString> &string);
};
}
#endif