mirror of
https://github.com/Samsung/escargot.git
synced 2026-06-22 10:01:50 +00:00
1977 lines
70 KiB
C++
1977 lines
70 KiB
C++
/*
|
|
* Copyright (c) 2017-present Samsung Electronics Co., Ltd
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
|
|
* USA
|
|
*/
|
|
|
|
#ifndef __ESCARGOT_PUBLIC__
|
|
#define __ESCARGOT_PUBLIC__
|
|
|
|
#if !defined(ESCARGOT_EXPORT)
|
|
#if defined(_MSC_VER)
|
|
#define ESCARGOT_EXPORT __declspec(dllexport)
|
|
#else
|
|
#define ESCARGOT_EXPORT __attribute__((visibility("default")))
|
|
#endif
|
|
#endif
|
|
|
|
#include <cstdlib>
|
|
#include <cstddef>
|
|
#include <cstring>
|
|
#include <string>
|
|
#include <vector>
|
|
#include <functional>
|
|
#include <limits>
|
|
#include <tuple>
|
|
#include <type_traits>
|
|
#include <utility>
|
|
#include <sstream>
|
|
|
|
#if !defined(NDEBUG) && defined(__GLIBCXX__) && !defined(_GLIBCXX_DEBUG)
|
|
#pragma message("You should define `_GLIBCXX_DEBUG` in {debug mode + libstdc++} because Escargot uses it")
|
|
#endif
|
|
|
|
#define ESCARGOT_POINTERVALUE_CHILD_REF_LIST(F) \
|
|
F(ArrayBuffer) \
|
|
F(ArrayBufferObject) \
|
|
F(ArrayBufferView) \
|
|
F(ArrayObject) \
|
|
F(BigInt) \
|
|
F(BigIntObject) \
|
|
F(BooleanObject) \
|
|
F(DataViewObject) \
|
|
F(DateObject) \
|
|
F(ErrorObject) \
|
|
F(FinalizationRegistryObject) \
|
|
F(FunctionObject) \
|
|
F(GenericIteratorObject) \
|
|
F(GlobalObject) \
|
|
F(GlobalObjectProxyObject) \
|
|
F(IteratorObject) \
|
|
F(MapObject) \
|
|
F(NumberObject) \
|
|
F(Object) \
|
|
F(PromiseObject) \
|
|
F(ProxyObject) \
|
|
F(RegExpObject) \
|
|
F(SetObject) \
|
|
F(SharedArrayBufferObject) \
|
|
F(String) \
|
|
F(StringObject) \
|
|
F(Symbol) \
|
|
F(SymbolObject) \
|
|
F(WeakMapObject) \
|
|
F(WeakRefObject) \
|
|
F(WeakSetObject)
|
|
|
|
#define ESCARGOT_ERROR_REF_LIST(F) \
|
|
F(AggregateErrorObject) \
|
|
F(EvalErrorObject) \
|
|
F(RangeErrorObject) \
|
|
F(ReferenceErrorObject) \
|
|
F(SyntaxErrorObject) \
|
|
F(TypeErrorObject) \
|
|
F(URIErrorObject)
|
|
|
|
#define ESCARGOT_TYPEDARRAY_REF_LIST(F) \
|
|
F(BigInt64ArrayObject) \
|
|
F(BigUint64ArrayObject) \
|
|
F(Float32ArrayObject) \
|
|
F(Float64ArrayObject) \
|
|
F(Int16ArrayObject) \
|
|
F(Int32ArrayObject) \
|
|
F(Int8ArrayObject) \
|
|
F(Uint16ArrayObject) \
|
|
F(Uint32ArrayObject) \
|
|
F(Uint8ArrayObject) \
|
|
F(Uint8ClampedArrayObject)
|
|
|
|
#define ESCARGOT_REF_LIST(F) \
|
|
F(Context) \
|
|
F(ExecutionState) \
|
|
F(FunctionTemplate) \
|
|
F(ObjectTemplate) \
|
|
F(PointerValue) \
|
|
F(RopeString) \
|
|
F(Script) \
|
|
F(ScriptParser) \
|
|
F(Template) \
|
|
F(VMInstance) \
|
|
F(BackingStore) \
|
|
ESCARGOT_POINTERVALUE_CHILD_REF_LIST(F) \
|
|
ESCARGOT_ERROR_REF_LIST(F) \
|
|
ESCARGOT_TYPEDARRAY_REF_LIST(F)
|
|
|
|
|
|
namespace Escargot {
|
|
|
|
class ValueRef;
|
|
class PlatformRef;
|
|
#define DECLARE_REF_CLASS(Name) class Name##Ref;
|
|
ESCARGOT_REF_LIST(DECLARE_REF_CLASS);
|
|
#undef DECLARE_REF_CLASS
|
|
|
|
class ESCARGOT_EXPORT Globals {
|
|
public:
|
|
// Escargot has thread-independent Globals.
|
|
// Users should call initialize, finalize once in the main program
|
|
static void initialize(PlatformRef* platform);
|
|
static void finalize();
|
|
|
|
// Globals also used for thread initialization
|
|
// Users need to call initializeThread, finalizeThread function for each thread
|
|
static void initializeThread();
|
|
static void finalizeThread();
|
|
|
|
static bool supportsThreading();
|
|
|
|
static const char* version();
|
|
static const char* buildDate();
|
|
};
|
|
|
|
class ESCARGOT_EXPORT Memory {
|
|
public:
|
|
static void* gcMalloc(size_t siz); // allocate memory it can hold gc-allocated pointer
|
|
static void* gcMallocAtomic(size_t siz); // allocate memory it can not hold gc-allocated pointer like string, number
|
|
static void* gcMallocUncollectable(size_t siz); // allocate memory it can hold gc-allocated pointer & it is never collect by gc
|
|
static void* gcMallocAtomicUncollectable(size_t siz); // allocate memory it can not hold gc-allocated pointer & it is never collect by gc
|
|
static void gcFree(void* ptr);
|
|
typedef void (*GCAllocatedMemoryFinalizer)(void* self);
|
|
|
|
// gcRegisterFinalizer
|
|
// 1. if you want to free memory explicitly, you must remove registered finalizer
|
|
// if there was no finalizer, you can just free memory
|
|
// ex) void* gcPointer;
|
|
// gcRegisterFinalizer(gcPointer, ....);
|
|
// ......
|
|
// gcRegisterFinalizer(gcPointer, nullptr); // this removes finalizer
|
|
// Memory::gcFree(gcPointer);
|
|
static void gcRegisterFinalizer(void* ptr, GCAllocatedMemoryFinalizer callback);
|
|
|
|
static void gcRegisterFinalizer(ObjectRef* ptr, GCAllocatedMemoryFinalizer callback);
|
|
static void gcUnregisterFinalizer(ObjectRef* ptr, GCAllocatedMemoryFinalizer callback);
|
|
|
|
static void gc();
|
|
|
|
static size_t heapSize(); // Return the number of bytes in the heap. Excludes bdwgc private data structures. Excludes the unmapped memory
|
|
static size_t totalSize(); // Return the total number of bytes allocated in this process
|
|
|
|
enum GCEventType {
|
|
MARK_START,
|
|
MARK_END,
|
|
RECLAIM_START,
|
|
RECLAIM_END,
|
|
};
|
|
// pointer `data` is not a GC object
|
|
typedef void (*OnGCEventListener)(void* data);
|
|
static void addGCEventListener(GCEventType type, OnGCEventListener l, void* data);
|
|
static bool removeGCEventListener(GCEventType type, OnGCEventListener l, void* data);
|
|
|
|
// NOTE bdwgc(c/c++ gc library escargot use) allocate at least N/GC_free_space_divisor bytes between collections
|
|
// (Allocated memory by GC x 2) / (Frequency parameter value)
|
|
// Increasing this value may use less space but there is more collection event
|
|
static void setGCFrequency(size_t value = 1);
|
|
};
|
|
|
|
// NOTE only {stack, kinds of PersistentHolders} are root set. if you store the data you need on other space, you may lost your data
|
|
template <typename T>
|
|
class ESCARGOT_EXPORT PersistentRefHolder {
|
|
public:
|
|
~PersistentRefHolder()
|
|
{
|
|
destoryHolderSpace();
|
|
}
|
|
|
|
PersistentRefHolder()
|
|
{
|
|
m_holder = nullptr;
|
|
}
|
|
|
|
PersistentRefHolder(T* ptr)
|
|
{
|
|
initHolderSpace(ptr);
|
|
}
|
|
|
|
PersistentRefHolder(PersistentRefHolder<T>&& src)
|
|
{
|
|
m_holder = src.m_holder;
|
|
src.m_holder = nullptr;
|
|
}
|
|
|
|
const PersistentRefHolder<T>& operator=(PersistentRefHolder<T>&& src)
|
|
{
|
|
m_holder = src.m_holder;
|
|
src.m_holder = nullptr;
|
|
|
|
return *this;
|
|
}
|
|
|
|
PersistentRefHolder(const PersistentRefHolder<T>&) = delete;
|
|
const PersistentRefHolder<T>& operator=(const PersistentRefHolder<T>&) = delete;
|
|
|
|
void reset(T* ptr)
|
|
{
|
|
if (!ptr) {
|
|
destoryHolderSpace();
|
|
return;
|
|
}
|
|
if (m_holder == nullptr) {
|
|
initHolderSpace(ptr);
|
|
} else {
|
|
*m_holder = ptr;
|
|
}
|
|
}
|
|
|
|
operator T*()
|
|
{
|
|
return *m_holder;
|
|
}
|
|
|
|
T* get()
|
|
{
|
|
return *m_holder;
|
|
}
|
|
|
|
T* release()
|
|
{
|
|
if (m_holder) {
|
|
T* ptr = *m_holder;
|
|
destoryHolderSpace();
|
|
return ptr;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
T* operator->()
|
|
{
|
|
return *m_holder;
|
|
}
|
|
|
|
bool isInitialized() const
|
|
{
|
|
return m_holder != nullptr;
|
|
}
|
|
|
|
private:
|
|
void initHolderSpace(T* initialValue)
|
|
{
|
|
m_holder = (T**)Memory::gcMallocUncollectable(sizeof(T*));
|
|
*m_holder = initialValue;
|
|
}
|
|
|
|
void destoryHolderSpace()
|
|
{
|
|
if (m_holder) {
|
|
Memory::gcFree(m_holder);
|
|
}
|
|
m_holder = nullptr;
|
|
}
|
|
|
|
T** m_holder;
|
|
};
|
|
|
|
class PersistentValueRefMap {
|
|
public:
|
|
static PersistentRefHolder<PersistentValueRefMap> create();
|
|
|
|
// we can count 0~2^30 range
|
|
// returns how many times rooted
|
|
// if ValueRef has type doesn't require root ex) undefined, number, boolean, small integer value
|
|
// this functions return 0;
|
|
uint32_t add(ValueRef* ptr);
|
|
// return how many times rooted after remove root
|
|
// 0 means the value is not heap-allocated value or is removed from root list
|
|
uint32_t remove(ValueRef* ptr);
|
|
|
|
void clear();
|
|
};
|
|
|
|
template <typename T>
|
|
class ESCARGOT_EXPORT GCManagedVector {
|
|
public:
|
|
GCManagedVector()
|
|
{
|
|
m_buffer = nullptr;
|
|
m_size = 0;
|
|
}
|
|
|
|
explicit GCManagedVector(size_t size)
|
|
{
|
|
if (size) {
|
|
m_buffer = (T*)Memory::gcMalloc(sizeof(T) * size);
|
|
m_size = size;
|
|
for (size_t i = 0; i < size; i++) {
|
|
new (&m_buffer[i]) T();
|
|
}
|
|
} else {
|
|
m_buffer = nullptr;
|
|
m_size = 0;
|
|
}
|
|
}
|
|
|
|
GCManagedVector(GCManagedVector<T>&& other)
|
|
{
|
|
m_size = other.size();
|
|
m_buffer = other.m_buffer;
|
|
other.m_buffer = nullptr;
|
|
other.m_size = 0;
|
|
}
|
|
|
|
GCManagedVector(const GCManagedVector<T>& other)
|
|
{
|
|
m_buffer = nullptr;
|
|
m_size = 0;
|
|
copyFrom(other);
|
|
}
|
|
|
|
const GCManagedVector<T>& operator=(const GCManagedVector<T>& other)
|
|
{
|
|
copyFrom(other);
|
|
return *this;
|
|
}
|
|
|
|
~GCManagedVector()
|
|
{
|
|
if (m_buffer) {
|
|
for (size_t i = 0; i < m_size; i++) {
|
|
m_buffer[i].~T();
|
|
}
|
|
Memory::gcFree(m_buffer);
|
|
}
|
|
}
|
|
|
|
size_t size() const
|
|
{
|
|
return m_size;
|
|
}
|
|
|
|
T& operator[](const size_t idx)
|
|
{
|
|
return m_buffer[idx];
|
|
}
|
|
|
|
const T& operator[](const size_t idx) const
|
|
{
|
|
return m_buffer[idx];
|
|
}
|
|
|
|
void clear()
|
|
{
|
|
if (m_buffer) {
|
|
Memory::gcFree(m_buffer);
|
|
}
|
|
m_size = 0;
|
|
m_buffer = nullptr;
|
|
}
|
|
|
|
void* operator new(size_t size)
|
|
{
|
|
return Memory::gcMalloc(size);
|
|
}
|
|
void* operator new(size_t, void* ptr)
|
|
{
|
|
return ptr;
|
|
}
|
|
void* operator new[](size_t size) = delete;
|
|
|
|
void operator delete(void* ptr)
|
|
{
|
|
Memory::gcFree(ptr);
|
|
}
|
|
void operator delete[](void* obj) = delete;
|
|
|
|
private:
|
|
void copyFrom(const GCManagedVector<T>& other)
|
|
{
|
|
clear();
|
|
m_size = other.size();
|
|
m_buffer = (T*)Memory::gcMalloc(sizeof(T) * m_size);
|
|
for (size_t i = 0; i < m_size; i++) {
|
|
new (&m_buffer[i]) T(other[i]);
|
|
}
|
|
}
|
|
T* m_buffer;
|
|
size_t m_size;
|
|
};
|
|
|
|
template <typename T>
|
|
class ESCARGOT_EXPORT OptionalRef {
|
|
public:
|
|
OptionalRef()
|
|
: m_value(nullptr)
|
|
{
|
|
}
|
|
|
|
OptionalRef(T* value)
|
|
: m_value(value)
|
|
{
|
|
}
|
|
|
|
OptionalRef(std::nullptr_t value)
|
|
: m_value(nullptr)
|
|
{
|
|
}
|
|
|
|
OptionalRef(const OptionalRef<T>& src)
|
|
: m_value(src.m_value)
|
|
{
|
|
}
|
|
|
|
T* value()
|
|
{
|
|
return m_value;
|
|
}
|
|
|
|
const T* value() const
|
|
{
|
|
return m_value;
|
|
}
|
|
|
|
T* get()
|
|
{
|
|
return m_value;
|
|
}
|
|
|
|
const T* get() const
|
|
{
|
|
return m_value;
|
|
}
|
|
|
|
bool hasValue() const
|
|
{
|
|
return !!m_value;
|
|
}
|
|
|
|
operator bool() const
|
|
{
|
|
return hasValue();
|
|
}
|
|
|
|
T* operator->()
|
|
{
|
|
return m_value;
|
|
}
|
|
|
|
const OptionalRef<T>& operator=(const OptionalRef<T>& other)
|
|
{
|
|
m_value = other.m_value;
|
|
return *this;
|
|
}
|
|
|
|
bool operator==(const OptionalRef<T>& other) const
|
|
{
|
|
return m_value == other.m_value;
|
|
}
|
|
|
|
bool operator!=(const OptionalRef<T>& other) const
|
|
{
|
|
return !this->operator==(other);
|
|
}
|
|
|
|
bool operator==(const T*& other) const
|
|
{
|
|
if (hasValue()) {
|
|
return *value() == *other;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool operator!=(const T*& other) const
|
|
{
|
|
return !operator==(other);
|
|
}
|
|
|
|
protected:
|
|
T* m_value;
|
|
};
|
|
|
|
// expand tuple into variadic template function's arguments
|
|
// https://stackoverflow.com/questions/687490/how-do-i-expand-a-tuple-into-variadic-template-functions-arguments
|
|
namespace EvaluatorUtil {
|
|
template <size_t N>
|
|
struct ApplyTupleIntoArgumentsOfVariadicTemplateFunction {
|
|
template <typename F, typename T, typename... A>
|
|
static inline auto apply(F&& f, T&& t, A&&... a)
|
|
-> decltype(ApplyTupleIntoArgumentsOfVariadicTemplateFunction<N - 1>::apply(
|
|
::std::forward<F>(f), ::std::forward<T>(t),
|
|
::std::get<N - 1>(::std::forward<T>(t)), ::std::forward<A>(a)...))
|
|
{
|
|
return ApplyTupleIntoArgumentsOfVariadicTemplateFunction<N - 1>::apply(::std::forward<F>(f), ::std::forward<T>(t),
|
|
::std::get<N - 1>(::std::forward<T>(t)), ::std::forward<A>(a)...);
|
|
}
|
|
};
|
|
|
|
template <>
|
|
struct ApplyTupleIntoArgumentsOfVariadicTemplateFunction<0> {
|
|
template <typename F, typename T, typename... A>
|
|
static inline auto apply(F&& f, T&&, A&&... a)
|
|
-> decltype(::std::forward<F>(f)(::std::forward<A>(a)...))
|
|
{
|
|
return ::std::forward<F>(f)(::std::forward<A>(a)...);
|
|
}
|
|
};
|
|
|
|
template <typename F, typename T>
|
|
inline auto applyTupleIntoArgumentsOfVariadicTemplateFunction(F&& f, T&& t)
|
|
-> decltype(ApplyTupleIntoArgumentsOfVariadicTemplateFunction<::std::tuple_size<
|
|
typename ::std::decay<T>::type>::value>::apply(::std::forward<F>(f), ::std::forward<T>(t)))
|
|
{
|
|
return ApplyTupleIntoArgumentsOfVariadicTemplateFunction<::std::tuple_size<
|
|
typename ::std::decay<T>::type>::value>::apply(::std::forward<F>(f), ::std::forward<T>(t));
|
|
}
|
|
} // namespace EvaluatorUtil
|
|
|
|
class ESCARGOT_EXPORT Evaluator {
|
|
public:
|
|
struct ESCARGOT_EXPORT LOC {
|
|
size_t line;
|
|
size_t column;
|
|
size_t index;
|
|
|
|
LOC(size_t line, size_t column, size_t index)
|
|
: line(line)
|
|
, column(column)
|
|
, index(index)
|
|
{
|
|
}
|
|
};
|
|
|
|
struct ESCARGOT_EXPORT StackTraceData {
|
|
StringRef* src;
|
|
StringRef* sourceCode;
|
|
LOC loc;
|
|
StringRef* functionName;
|
|
bool isFunction;
|
|
bool isConstructor;
|
|
bool isAssociatedWithJavaScriptCode;
|
|
bool isEval;
|
|
StackTraceData();
|
|
};
|
|
|
|
struct ESCARGOT_EXPORT EvaluatorResult {
|
|
EvaluatorResult();
|
|
EvaluatorResult(const EvaluatorResult& src);
|
|
const EvaluatorResult& operator=(EvaluatorResult& src);
|
|
EvaluatorResult(EvaluatorResult&& src);
|
|
|
|
bool isSuccessful() const
|
|
{
|
|
return !error.hasValue();
|
|
}
|
|
|
|
StringRef* resultOrErrorToString(ContextRef* ctx) const;
|
|
|
|
ValueRef* result;
|
|
OptionalRef<ValueRef> error;
|
|
GCManagedVector<StackTraceData> stackTraceData;
|
|
};
|
|
|
|
template <typename... Args, typename F>
|
|
static EvaluatorResult execute(ContextRef* ctx, F&& closure, Args... args)
|
|
{
|
|
typedef ValueRef* (*Closure)(ExecutionStateRef * state, Args...);
|
|
return executeImpl(ctx, Closure(closure), args...);
|
|
}
|
|
|
|
static EvaluatorResult executeFunction(ContextRef* ctx, ValueRef* (*runner)(ExecutionStateRef* state, void* passedData), void* data);
|
|
static EvaluatorResult executeFunction(ContextRef* ctx, ValueRef* (*runner)(ExecutionStateRef* state, void* passedData, void* passedData2), void* data, void* data2);
|
|
|
|
private:
|
|
template <typename... Args>
|
|
static EvaluatorResult executeImpl(ContextRef* ctx, ValueRef* (*fn)(ExecutionStateRef* state, Args...), Args... args)
|
|
{
|
|
typedef ValueRef* (*Closure)(ExecutionStateRef * state, Args...);
|
|
std::tuple<ExecutionStateRef*, Args...> tuple = std::tuple<ExecutionStateRef*, Args...>(nullptr, args...);
|
|
|
|
return executeFunction(ctx, [](ExecutionStateRef* state, void* tuplePtr, void* fnPtr) -> ValueRef* {
|
|
std::tuple<ExecutionStateRef*, Args...>* tuple = (std::tuple<ExecutionStateRef*, Args...>*)tuplePtr;
|
|
Closure fn = (Closure)fnPtr;
|
|
|
|
std::get<0>(*tuple) = state;
|
|
|
|
return EvaluatorUtil::applyTupleIntoArgumentsOfVariadicTemplateFunction(fn, *tuple);
|
|
},
|
|
&tuple, (void*)fn);
|
|
}
|
|
};
|
|
|
|
// Don't save pointer of ExecutionStateRef anywhere yourself
|
|
// If you want to acquire ExecutionStateRef, you can use Evaluator::execute
|
|
class ESCARGOT_EXPORT ExecutionStateRef {
|
|
public:
|
|
OptionalRef<FunctionObjectRef> resolveCallee(); // resolve nearest callee if exists
|
|
GCManagedVector<FunctionObjectRef*> resolveCallstack(); // resolve list of callee
|
|
GlobalObjectRef* resolveCallerLexicalGlobalObject(); // resolve caller's lexical global object
|
|
|
|
bool onTry();
|
|
bool onCatch();
|
|
bool onFinally();
|
|
|
|
void throwException(ValueRef* value);
|
|
|
|
GCManagedVector<Evaluator::StackTraceData> computeStackTraceData();
|
|
|
|
ContextRef* context();
|
|
|
|
OptionalRef<ExecutionStateRef> parent();
|
|
};
|
|
|
|
class ESCARGOT_EXPORT VMInstanceRef {
|
|
public:
|
|
// you can to provide timezone as TZ database name like "US/Pacific".
|
|
// if you don't provide, we try to detect system timezone.
|
|
static PersistentRefHolder<VMInstanceRef> create(const char* locale = nullptr, const char* timezone = nullptr, const char* baseCacheDir = nullptr);
|
|
|
|
typedef void (*OnVMInstanceDelete)(VMInstanceRef* instance);
|
|
void setOnVMInstanceDelete(OnVMInstanceDelete cb);
|
|
|
|
// register ErrorCreationCallback which is triggered when each Error constructor (e.g. new TypeError()) invoked
|
|
// parameter `err` is newly created ErrorObject
|
|
typedef void (*ErrorCreationCallback)(ExecutionStateRef* state, ErrorObjectRef* err);
|
|
void registerErrorCreationCallback(ErrorCreationCallback cb);
|
|
void unregisterErrorCreationCallback();
|
|
|
|
size_t validSourceSize();
|
|
|
|
enum PromiseHookType {
|
|
Init,
|
|
Resolve,
|
|
Before,
|
|
After
|
|
};
|
|
|
|
typedef void (*PromiseHook)(ExecutionStateRef* state, PromiseHookType type, PromiseObjectRef* promise, ValueRef* parent);
|
|
|
|
// Register PromiseHook (PromiseHook is used by third party app)
|
|
void registerPromiseHook(PromiseHook promiseHook);
|
|
void unregisterPromiseHook();
|
|
|
|
// this function enforce do gc,
|
|
// remove every compiled bytecodes,
|
|
// remove regexp cache,
|
|
// and compress every comressible strings if we can
|
|
void enterIdleMode();
|
|
// force clear every caches related with context
|
|
// you can call this function if you don't want to use every alive contexts
|
|
void clearCachesRelatedWithContext();
|
|
|
|
SymbolRef* toStringTagSymbol();
|
|
SymbolRef* iteratorSymbol();
|
|
SymbolRef* unscopablesSymbol();
|
|
SymbolRef* hasInstanceSymbol();
|
|
SymbolRef* isConcatSpreadableSymbol();
|
|
SymbolRef* speciesSymbol();
|
|
SymbolRef* toPrimitiveSymbol();
|
|
SymbolRef* searchSymbol();
|
|
SymbolRef* matchSymbol();
|
|
SymbolRef* matchAllSymbol();
|
|
SymbolRef* replaceSymbol();
|
|
SymbolRef* splitSymbol();
|
|
SymbolRef* asyncIteratorSymbol();
|
|
|
|
bool hasPendingJob();
|
|
Evaluator::EvaluatorResult executePendingJob();
|
|
};
|
|
|
|
class ESCARGOT_EXPORT ContextRef {
|
|
public:
|
|
static PersistentRefHolder<ContextRef> create(VMInstanceRef* vmInstance);
|
|
|
|
void clearRelatedQueuedJobs();
|
|
|
|
VMInstanceRef* vmInstance();
|
|
ScriptParserRef* scriptParser();
|
|
|
|
GlobalObjectRef* globalObject();
|
|
ObjectRef* globalObjectProxy();
|
|
// this setter try to update `globalThis` value on GlobalObject
|
|
void setGlobalObjectProxy(ObjectRef* newGlobalObjectProxy);
|
|
|
|
void throwException(ValueRef* exceptionValue); // if you use this function without Evaluator, your program will crash :(
|
|
|
|
bool initDebugger(const char* options);
|
|
bool isDebuggerRunning();
|
|
void printDebugger(StringRef* output);
|
|
StringRef* getClientSource(StringRef** sourceName);
|
|
|
|
typedef OptionalRef<ValueRef> (*VirtualIdentifierCallback)(ExecutionStateRef* state, ValueRef* name);
|
|
typedef OptionalRef<ValueRef> (*SecurityPolicyCheckCallback)(ExecutionStateRef* state, bool isEval);
|
|
|
|
// this is not compatible with ECMAScript
|
|
// but this callback is needed for browser-implementation
|
|
// if there is a Identifier with that value, callback should return non empty optional value
|
|
void setVirtualIdentifierCallback(VirtualIdentifierCallback cb);
|
|
VirtualIdentifierCallback virtualIdentifierCallback();
|
|
|
|
void setSecurityPolicyCheckCallback(SecurityPolicyCheckCallback cb);
|
|
};
|
|
|
|
// AtomicStringRef is never deleted by gc until VMInstance destroyed
|
|
// client doesn't need to store this ref in Persistent storage
|
|
class ESCARGOT_EXPORT AtomicStringRef {
|
|
public:
|
|
static AtomicStringRef* create(ContextRef* c, const char* src, size_t length); // from ASCII string
|
|
template <size_t N>
|
|
static AtomicStringRef* create(ContextRef* c, const char (&str)[N])
|
|
{
|
|
return create(c, str, N - 1);
|
|
}
|
|
static AtomicStringRef* create(ContextRef* c, StringRef* src);
|
|
static AtomicStringRef* emptyAtomicString();
|
|
StringRef* string();
|
|
|
|
bool equals(AtomicStringRef* ref) const
|
|
{
|
|
return this == ref;
|
|
}
|
|
};
|
|
|
|
// only large integer, double, PointerValueRef are stored in heap
|
|
// other types are represented by pointer, but doesn't use heap
|
|
// client must save heap-allocated values on the space where gc can find from root space(stack, VMInstance, PersistentHolders) if don't want to delete by gc
|
|
class ESCARGOT_EXPORT ValueRef {
|
|
public:
|
|
static ValueRef* create(bool);
|
|
static ValueRef* create(int);
|
|
static ValueRef* create(unsigned);
|
|
static ValueRef* create(float);
|
|
static ValueRef* create(double);
|
|
static ValueRef* create(long);
|
|
static ValueRef* create(unsigned long);
|
|
static ValueRef* create(long long);
|
|
static ValueRef* create(unsigned long long);
|
|
static ValueRef* create(ValueRef* src)
|
|
{
|
|
return src;
|
|
}
|
|
static ValueRef* createNull();
|
|
static ValueRef* createUndefined();
|
|
|
|
bool isStoredInHeap();
|
|
bool isBoolean();
|
|
bool isNumber();
|
|
bool isNull();
|
|
bool isUndefined();
|
|
bool isInt32();
|
|
bool isUInt32();
|
|
bool isDouble();
|
|
bool isTrue();
|
|
bool isFalse();
|
|
bool isCallable(); // can ValueRef::call
|
|
bool isConstructible(); // can ValueRef::construct
|
|
bool isUndefinedOrNull()
|
|
{
|
|
return isUndefined() || isNull();
|
|
}
|
|
bool isPointerValue();
|
|
|
|
bool isArgumentsObject();
|
|
bool isArrayPrototypeObject();
|
|
bool isGeneratorFunctionObject();
|
|
bool isGeneratorObject();
|
|
bool isMapIteratorObject();
|
|
bool isSetIteratorObject();
|
|
bool isTypedArrayObject();
|
|
bool isTypedArrayPrototypeObject();
|
|
bool isModuleNamespaceObject();
|
|
|
|
bool asBoolean();
|
|
double asNumber();
|
|
int32_t asInt32();
|
|
uint32_t asUInt32();
|
|
PointerValueRef* asPointerValue();
|
|
|
|
#define DEFINE_VALUEREF_IS_AS(Name) \
|
|
bool is##Name(); \
|
|
Name##Ref* as##Name();
|
|
|
|
ESCARGOT_POINTERVALUE_CHILD_REF_LIST(DEFINE_VALUEREF_IS_AS);
|
|
ESCARGOT_TYPEDARRAY_REF_LIST(DEFINE_VALUEREF_IS_AS);
|
|
#undef DEFINE_VALUEREF_IS_AS
|
|
|
|
bool toBoolean(ExecutionStateRef* state);
|
|
double toNumber(ExecutionStateRef* state);
|
|
double toInteger(ExecutionStateRef* state);
|
|
double toLength(ExecutionStateRef* state);
|
|
int32_t toInt32(ExecutionStateRef* state);
|
|
uint32_t toUint32(ExecutionStateRef* state);
|
|
StringRef* toString(ExecutionStateRef* state);
|
|
// we never throw exception in this function but returns "Error while converting to string, but do not throw an exception" string
|
|
StringRef* toStringWithoutException(ContextRef* ctx);
|
|
ObjectRef* toObject(ExecutionStateRef* state);
|
|
|
|
enum : uint64_t { InvalidIndexValue = std::numeric_limits<uint64_t>::max() };
|
|
typedef uint64_t ValueIndex;
|
|
ValueIndex toIndex(ExecutionStateRef* state);
|
|
ValueIndex tryToUseAsIndex(ExecutionStateRef* state);
|
|
|
|
enum : uint32_t {
|
|
InvalidIndex32Value = std::numeric_limits<uint32_t>::max(),
|
|
InvalidIndexPropertyValue = InvalidIndex32Value
|
|
};
|
|
uint32_t toIndex32(ExecutionStateRef* state);
|
|
uint32_t tryToUseAsIndex32(ExecutionStateRef* state);
|
|
uint32_t tryToUseAsIndexProperty(ExecutionStateRef* state);
|
|
|
|
bool abstractEqualsTo(ExecutionStateRef* state, const ValueRef* other) const; // ==
|
|
bool equalsTo(ExecutionStateRef* state, const ValueRef* other) const; // ===
|
|
bool instanceOf(ExecutionStateRef* state, const ValueRef* other) const;
|
|
ValueRef* call(ExecutionStateRef* state, ValueRef* receiver, const size_t argc, ValueRef** argv);
|
|
ValueRef* construct(ExecutionStateRef* state, const size_t argc, ValueRef** argv); // same with new expression in js
|
|
};
|
|
|
|
class ESCARGOT_EXPORT ValueVectorRef {
|
|
public:
|
|
static ValueVectorRef* create(size_t size = 0);
|
|
|
|
size_t size();
|
|
void pushBack(ValueRef* val);
|
|
void insert(size_t pos, ValueRef* val);
|
|
void erase(size_t pos);
|
|
void erase(size_t start, size_t end);
|
|
ValueRef* at(const size_t idx);
|
|
void set(const size_t idx, ValueRef* newValue);
|
|
void resize(size_t newSize);
|
|
};
|
|
|
|
// `double` value is not presented in PointerValue, but it is stored in heap
|
|
class ESCARGOT_EXPORT PointerValueRef : public ValueRef {
|
|
public:
|
|
};
|
|
|
|
class ESCARGOT_EXPORT StringRef : public PointerValueRef {
|
|
public:
|
|
template <size_t N>
|
|
static StringRef* createFromASCII(const char (&str)[N])
|
|
{
|
|
return createFromASCII(str, N - 1);
|
|
}
|
|
static StringRef* createFromASCII(const char* s, size_t stringLength);
|
|
template <size_t N>
|
|
static StringRef* createFromUTF8(const char (&str)[N])
|
|
{
|
|
return createFromUTF8(str, N - 1);
|
|
}
|
|
static StringRef* createFromUTF8(const char* s, size_t byteLength, bool maybeASCII = true);
|
|
static StringRef* createFromUTF8(ContextRef* context, const char* s, size_t len, bool maybeASCII);
|
|
|
|
static StringRef* createFromUTF16(const char16_t* s, size_t stringLength);
|
|
static StringRef* createFromLatin1(const unsigned char* s, size_t stringLength);
|
|
static StringRef* createFromLatin1(ContextRef* context, const unsigned char* s, size_t len);
|
|
|
|
static StringRef* createExternalFromASCII(const char* s, size_t stringLength);
|
|
static StringRef* createExternalFromLatin1(const unsigned char* s, size_t stringLength);
|
|
static StringRef* createExternalFromUTF16(const char16_t* s, size_t stringLength);
|
|
|
|
// you can use these functions only if you enabled string compression
|
|
static bool isCompressibleStringEnabled();
|
|
static StringRef* createFromUTF8ToCompressibleString(VMInstanceRef* instance, const char* s, size_t byteLength, bool maybeASCII = true);
|
|
static StringRef* createFromUTF16ToCompressibleString(VMInstanceRef* instance, const char16_t* s, size_t stringLength);
|
|
static StringRef* createFromASCIIToCompressibleString(VMInstanceRef* instance, const char* s, size_t stringLength);
|
|
static StringRef* createFromLatin1ToCompressibleString(VMInstanceRef* instance, const unsigned char* s, size_t stringLength);
|
|
static void* allocateStringDataBufferForCompressibleString(size_t byteLength);
|
|
static void deallocateStringDataBufferForCompressibleString(void* ptr, size_t byteLength);
|
|
static StringRef* createFromAlreadyAllocatedBufferToCompressibleString(VMInstanceRef* instance, void* buffer, size_t stringLen, bool is8Bit /* is ASCII or Latin1 */);
|
|
|
|
// you can use these functions only if you enabled reloadable string
|
|
static bool isReloadableStringEnabled();
|
|
static StringRef* createReloadableString(VMInstanceRef* instance,
|
|
bool is8BitString, size_t stringLength, void* callbackData,
|
|
void* (*loadCallback)(void* callbackData), // you should returns string buffer
|
|
void (*unloadCallback)(void* memoryPtr, void* callbackData)); // you should free memoryPtr
|
|
|
|
static StringRef* emptyString();
|
|
|
|
char16_t charAt(size_t idx);
|
|
size_t length();
|
|
bool has8BitContent();
|
|
|
|
bool hasExternalMemory();
|
|
bool isCompressibleString();
|
|
bool isReloadableString();
|
|
|
|
bool isRopeString();
|
|
RopeStringRef* asRopeString();
|
|
|
|
bool equals(StringRef* src);
|
|
bool equalsWithASCIIString(const char* buf, size_t stringLength);
|
|
|
|
StringRef* substring(size_t from, size_t to);
|
|
|
|
enum WriteOptions {
|
|
NoOptions = 0,
|
|
ReplaceInvalidUtf8 = 1 << 3
|
|
};
|
|
|
|
std::string toStdUTF8String(int options = NoOptions);
|
|
|
|
// don't store this sturct or string buffer
|
|
// this is only for temporary access
|
|
struct ESCARGOT_EXPORT StringBufferAccessDataRef {
|
|
bool has8BitContent;
|
|
size_t length;
|
|
const void* buffer;
|
|
|
|
// A type to hold a single Latin-1 character.
|
|
typedef unsigned char LChar;
|
|
|
|
char16_t uncheckedCharAtFor8Bit(size_t idx) const
|
|
{
|
|
return ((LChar*)buffer)[idx];
|
|
}
|
|
|
|
char16_t uncheckedCharAtFor16Bit(size_t idx) const
|
|
{
|
|
return ((char16_t*)buffer)[idx];
|
|
}
|
|
|
|
char16_t charAt(size_t idx) const
|
|
{
|
|
if (has8BitContent) {
|
|
return ((LChar*)buffer)[idx];
|
|
} else {
|
|
return ((char16_t*)buffer)[idx];
|
|
}
|
|
}
|
|
};
|
|
|
|
StringBufferAccessDataRef stringBufferAccessData();
|
|
};
|
|
|
|
class ESCARGOT_EXPORT RopeStringRef : public StringRef {
|
|
public:
|
|
bool wasFlattened();
|
|
|
|
// you can get left, right value when RopeString is not flattened
|
|
OptionalRef<StringRef> left();
|
|
OptionalRef<StringRef> right();
|
|
};
|
|
|
|
class ESCARGOT_EXPORT SymbolRef : public PointerValueRef {
|
|
public:
|
|
static SymbolRef* create(OptionalRef<StringRef> desc);
|
|
static SymbolRef* fromGlobalSymbolRegistry(VMInstanceRef* context, StringRef* desc); // this is same with Symbol.for
|
|
OptionalRef<StringRef> description();
|
|
StringRef* symbolDescriptiveString();
|
|
};
|
|
|
|
class ESCARGOT_EXPORT BigIntRef : public PointerValueRef {
|
|
public:
|
|
static BigIntRef* create(StringRef* desc);
|
|
static BigIntRef* create(int64_t num);
|
|
static BigIntRef* create(uint64_t num);
|
|
|
|
StringRef* toString(int radix = 10);
|
|
double toNumber();
|
|
int64_t toInt64();
|
|
uint64_t toUint64();
|
|
|
|
bool equals(BigIntRef* b);
|
|
bool equals(StringRef* s);
|
|
bool equals(double b);
|
|
|
|
bool lessThan(BigIntRef* b);
|
|
bool lessThanEqual(BigIntRef* b);
|
|
bool greaterThan(BigIntRef* b);
|
|
bool greaterThanEqual(BigIntRef* b);
|
|
|
|
BigIntRef* addition(ExecutionStateRef* state, BigIntRef* b);
|
|
BigIntRef* subtraction(ExecutionStateRef* state, BigIntRef* b);
|
|
BigIntRef* multiply(ExecutionStateRef* state, BigIntRef* b);
|
|
BigIntRef* division(ExecutionStateRef* state, BigIntRef* b);
|
|
BigIntRef* remainder(ExecutionStateRef* state, BigIntRef* b);
|
|
BigIntRef* pow(ExecutionStateRef* state, BigIntRef* b);
|
|
BigIntRef* bitwiseAnd(ExecutionStateRef* state, BigIntRef* b);
|
|
BigIntRef* bitwiseOr(ExecutionStateRef* state, BigIntRef* b);
|
|
BigIntRef* bitwiseXor(ExecutionStateRef* state, BigIntRef* b);
|
|
BigIntRef* leftShift(ExecutionStateRef* state, BigIntRef* c);
|
|
BigIntRef* rightShift(ExecutionStateRef* state, BigIntRef* c);
|
|
|
|
BigIntRef* increment(ExecutionStateRef* state);
|
|
BigIntRef* decrement(ExecutionStateRef* state);
|
|
BigIntRef* bitwiseNot(ExecutionStateRef* state);
|
|
BigIntRef* negativeValue(ExecutionStateRef* state);
|
|
|
|
bool isZero();
|
|
bool isNaN();
|
|
bool isInfinity();
|
|
bool isNegative();
|
|
};
|
|
|
|
class ESCARGOT_EXPORT ObjectPropertyDescriptorRef {
|
|
public:
|
|
ObjectPropertyDescriptorRef(ValueRef* value);
|
|
ObjectPropertyDescriptorRef(ValueRef* value, bool writable);
|
|
ObjectPropertyDescriptorRef(ValueRef* getter, ValueRef* setter);
|
|
|
|
ObjectPropertyDescriptorRef(const ObjectPropertyDescriptorRef& src);
|
|
const ObjectPropertyDescriptorRef& operator=(const ObjectPropertyDescriptorRef& src);
|
|
~ObjectPropertyDescriptorRef();
|
|
|
|
ValueRef* value() const;
|
|
bool hasValue() const;
|
|
|
|
ValueRef* getter() const;
|
|
bool hasGetter() const;
|
|
ValueRef* setter() const;
|
|
bool hasSetter() const;
|
|
|
|
bool isEnumerable() const;
|
|
void setEnumerable(bool enumerable);
|
|
bool hasEnumerable() const;
|
|
|
|
bool isConfigurable() const;
|
|
void setConfigurable(bool configurable);
|
|
bool hasConfigurable() const;
|
|
|
|
bool isWritable() const;
|
|
bool hasWritable() const;
|
|
|
|
void* operator new(size_t size);
|
|
void* operator new[](size_t size) = delete;
|
|
void operator delete(void* ptr);
|
|
void operator delete[](void* obj) = delete;
|
|
|
|
private:
|
|
friend class ObjectWithPropertyHandler;
|
|
ObjectPropertyDescriptorRef(void* src);
|
|
|
|
void* m_privateData;
|
|
};
|
|
|
|
struct ESCARGOT_EXPORT ExposableObjectGetOwnPropertyCallbackResult {
|
|
ExposableObjectGetOwnPropertyCallbackResult()
|
|
: m_value()
|
|
, m_isWritable(false)
|
|
, m_isEnumerable(false)
|
|
, m_isConfigurable(false)
|
|
{
|
|
}
|
|
|
|
ExposableObjectGetOwnPropertyCallbackResult(ValueRef* value, bool isWritable, bool isEnumerable, bool isConfigurable)
|
|
: m_value(value)
|
|
, m_isWritable(isWritable)
|
|
, m_isEnumerable(isEnumerable)
|
|
, m_isConfigurable(isConfigurable)
|
|
{
|
|
}
|
|
|
|
OptionalRef<ValueRef> m_value;
|
|
bool m_isWritable;
|
|
bool m_isEnumerable;
|
|
bool m_isConfigurable;
|
|
};
|
|
|
|
struct ESCARGOT_EXPORT ExposableObjectEnumerationCallbackResult {
|
|
ExposableObjectEnumerationCallbackResult(ValueRef* name = ValueRef::createUndefined(), bool isWritable = true, bool isEnumerable = true, bool isConfigurable = true)
|
|
: m_name(name)
|
|
, m_isWritable(isWritable)
|
|
, m_isEnumerable(isEnumerable)
|
|
, m_isConfigurable(isConfigurable)
|
|
{
|
|
}
|
|
|
|
ValueRef* m_name;
|
|
bool m_isWritable;
|
|
bool m_isEnumerable;
|
|
bool m_isConfigurable;
|
|
};
|
|
|
|
typedef ExposableObjectGetOwnPropertyCallbackResult (*ExposableObjectGetOwnPropertyCallback)(ExecutionStateRef* state, ObjectRef* self, ValueRef* propertyName);
|
|
typedef bool (*ExposableObjectDefineOwnPropertyCallback)(ExecutionStateRef* state, ObjectRef* self, ValueRef* propertyName, ValueRef* value);
|
|
typedef GCManagedVector<ExposableObjectEnumerationCallbackResult> ExposableObjectEnumerationCallbackResultVector;
|
|
typedef ExposableObjectEnumerationCallbackResultVector (*ExposableObjectEnumerationCallback)(ExecutionStateRef* state, ObjectRef* self);
|
|
typedef bool (*ExposableObjectDeleteOwnPropertyCallback)(ExecutionStateRef* state, ObjectRef* self, ValueRef* propertyName);
|
|
|
|
class ESCARGOT_EXPORT ObjectRef : public PointerValueRef {
|
|
public:
|
|
static ObjectRef* create(ExecutionStateRef* state);
|
|
// can not redefine or delete virtual property
|
|
// virtual property does not follow every rule of ECMAScript
|
|
static ObjectRef* createExposableObject(ExecutionStateRef* state,
|
|
ExposableObjectGetOwnPropertyCallback getOwnPropertyCallback, ExposableObjectDefineOwnPropertyCallback defineOwnPropertyCallback,
|
|
ExposableObjectEnumerationCallback enumerationCallback, ExposableObjectDeleteOwnPropertyCallback deleteOwnPropertyCallback);
|
|
|
|
ValueRef* get(ExecutionStateRef* state, ValueRef* propertyName);
|
|
ValueRef* getOwnProperty(ExecutionStateRef* state, ValueRef* propertyName);
|
|
ValueRef* getOwnPropertyDescriptor(ExecutionStateRef* state, ValueRef* propertyName);
|
|
|
|
bool set(ExecutionStateRef* state, ValueRef* propertyName, ValueRef* value);
|
|
|
|
ValueRef* getIndexedProperty(ExecutionStateRef* state, ValueRef* property);
|
|
bool setIndexedProperty(ExecutionStateRef* state, ValueRef* property, ValueRef* value);
|
|
bool has(ExecutionStateRef* state, ValueRef* propertyName);
|
|
|
|
enum PresentAttribute {
|
|
NotPresent = 0,
|
|
WritablePresent = 1 << 1,
|
|
EnumerablePresent = 1 << 2,
|
|
ConfigurablePresent = 1 << 3,
|
|
NonWritablePresent = 1 << 4,
|
|
NonEnumerablePresent = 1 << 5,
|
|
NonConfigurablePresent = 1 << 6,
|
|
AllPresent = WritablePresent | EnumerablePresent | ConfigurablePresent
|
|
};
|
|
|
|
class DataPropertyDescriptor {
|
|
public:
|
|
DataPropertyDescriptor(ValueRef* value, PresentAttribute attr)
|
|
: m_value(value)
|
|
, m_attribute(attr)
|
|
{
|
|
}
|
|
|
|
ValueRef* m_value;
|
|
PresentAttribute m_attribute;
|
|
};
|
|
|
|
class AccessorPropertyDescriptor {
|
|
public:
|
|
// only undefined, empty optional value, function are allowed to getter, setter parameter
|
|
// empty optional value means unspecified state
|
|
// undefined means truely undefined -> ex) { get: undefined }
|
|
AccessorPropertyDescriptor(ValueRef* getter, OptionalRef<ValueRef> setter, PresentAttribute attr)
|
|
: m_getter(getter)
|
|
, m_setter(setter)
|
|
, m_attribute(attr)
|
|
{
|
|
}
|
|
|
|
ValueRef* m_getter;
|
|
OptionalRef<ValueRef> m_setter;
|
|
PresentAttribute m_attribute;
|
|
};
|
|
|
|
bool defineOwnProperty(ExecutionStateRef* state, ValueRef* propertyName, ValueRef* desc);
|
|
bool defineDataProperty(ExecutionStateRef* state, ValueRef* propertyName, const DataPropertyDescriptor& desc);
|
|
bool defineDataProperty(ExecutionStateRef* state, ValueRef* propertyName, ValueRef* value, bool isWritable, bool isEnumerable, bool isConfigurable);
|
|
bool defineAccessorProperty(ExecutionStateRef* state, ValueRef* propertyName, const AccessorPropertyDescriptor& desc);
|
|
|
|
struct NativeDataAccessorPropertyData;
|
|
typedef ValueRef* (*NativeDataAccessorPropertyGetter)(ExecutionStateRef* state, ObjectRef* self, ValueRef* receiver, NativeDataAccessorPropertyData* data);
|
|
typedef bool (*NativeDataAccessorPropertySetter)(ExecutionStateRef* state, ObjectRef* self, ValueRef* receiver, NativeDataAccessorPropertyData* data, ValueRef* setterInputData);
|
|
// client extend this struct to give data for getter, setter if needs
|
|
// this struct must allocated in gc-heap
|
|
// only setter can be null
|
|
struct ESCARGOT_EXPORT NativeDataAccessorPropertyData {
|
|
bool m_isWritable : 1;
|
|
bool m_isEnumerable : 1;
|
|
bool m_isConfigurable : 1;
|
|
NativeDataAccessorPropertyGetter m_getter;
|
|
NativeDataAccessorPropertySetter m_setter;
|
|
|
|
NativeDataAccessorPropertyData(bool isWritable, bool isEnumerable, bool isConfigurable,
|
|
NativeDataAccessorPropertyGetter getter, NativeDataAccessorPropertySetter setter)
|
|
: m_isWritable(isWritable)
|
|
, m_isEnumerable(isEnumerable)
|
|
, m_isConfigurable(isConfigurable)
|
|
, m_getter(getter)
|
|
, m_setter(setter)
|
|
{
|
|
}
|
|
|
|
void* operator new(size_t size);
|
|
void* operator new[](size_t size) = delete;
|
|
};
|
|
// this function differ with defineDataPropety and defineAccessorPropety.
|
|
// !hasOwnProperty(state, P) is needed for success
|
|
bool defineNativeDataAccessorProperty(ExecutionStateRef* state, ValueRef* P, NativeDataAccessorPropertyData* data, bool actsLikeJSGetterSetter = false);
|
|
|
|
bool deleteOwnProperty(ExecutionStateRef* state, ValueRef* propertyName);
|
|
bool hasOwnProperty(ExecutionStateRef* state, ValueRef* propertyName);
|
|
|
|
bool deleteProperty(ExecutionStateRef* state, ValueRef* propertyName);
|
|
bool hasProperty(ExecutionStateRef* state, ValueRef* propertyName);
|
|
|
|
ValueRef* getPrototype(ExecutionStateRef* state);
|
|
OptionalRef<ObjectRef> getPrototypeObject(ExecutionStateRef* state); // if __proto__ is not object(undefined or null), this function returns nullptr instead of orginal value.
|
|
bool setPrototype(ExecutionStateRef* state, ValueRef* value);
|
|
|
|
OptionalRef<ContextRef> creationContext();
|
|
|
|
ValueVectorRef* ownPropertyKeys(ExecutionStateRef* state);
|
|
|
|
void enumerateObjectOwnProperties(ExecutionStateRef* state, const std::function<bool(ExecutionStateRef* state, ValueRef* propertyName, bool isWritable, bool isEnumerable, bool isConfigurable)>& cb, bool shouldSkipSymbolKey = true);
|
|
|
|
// get `length` property like ToLength(Get(obj, "length"))
|
|
// it returns 0 for exceptional cases (e.g. undefined, nan)
|
|
uint64_t length(ExecutionStateRef* state);
|
|
|
|
bool isExtensible(ExecutionStateRef* state);
|
|
bool preventExtensions(ExecutionStateRef* state);
|
|
bool setIntegrityLevel(ExecutionStateRef* state, bool isSealed);
|
|
|
|
void* extraData();
|
|
void setExtraData(void* e);
|
|
#if defined(ESCARGOT_ENABLE_TEST)
|
|
void setIsHTMLDDA();
|
|
#endif
|
|
|
|
void removeFromHiddenClassChain();
|
|
|
|
// DEPRECATED! this function will be removed
|
|
void removeFromHiddenClassChain(ExecutionStateRef* state);
|
|
};
|
|
|
|
class ESCARGOT_EXPORT GlobalObjectRef : public ObjectRef {
|
|
public:
|
|
FunctionObjectRef* object();
|
|
ObjectRef* objectPrototype();
|
|
FunctionObjectRef* objectPrototypeToString();
|
|
FunctionObjectRef* function();
|
|
FunctionObjectRef* functionPrototype();
|
|
FunctionObjectRef* error();
|
|
ObjectRef* errorPrototype();
|
|
FunctionObjectRef* referenceError();
|
|
ObjectRef* referenceErrorPrototype();
|
|
FunctionObjectRef* typeError();
|
|
ObjectRef* typeErrorPrototype();
|
|
FunctionObjectRef* rangeError();
|
|
ObjectRef* rangeErrorPrototype();
|
|
FunctionObjectRef* syntaxError();
|
|
ObjectRef* syntaxErrorPrototype();
|
|
FunctionObjectRef* uriError();
|
|
ObjectRef* uriErrorPrototype();
|
|
FunctionObjectRef* evalError();
|
|
ObjectRef* evalErrorPrototype();
|
|
FunctionObjectRef* aggregateError();
|
|
ObjectRef* aggregateErrorPrototype();
|
|
FunctionObjectRef* string();
|
|
ObjectRef* stringPrototype();
|
|
FunctionObjectRef* number();
|
|
ObjectRef* numberPrototype();
|
|
FunctionObjectRef* array();
|
|
ObjectRef* arrayPrototype();
|
|
FunctionObjectRef* boolean();
|
|
ObjectRef* booleanPrototype();
|
|
FunctionObjectRef* date();
|
|
ObjectRef* datePrototype();
|
|
ObjectRef* math();
|
|
FunctionObjectRef* regexp();
|
|
ObjectRef* regexpPrototype();
|
|
ObjectRef* json();
|
|
FunctionObjectRef* jsonStringify();
|
|
FunctionObjectRef* jsonParse();
|
|
|
|
FunctionObjectRef* promise();
|
|
ObjectRef* promisePrototype();
|
|
|
|
FunctionObjectRef* arrayBuffer();
|
|
ObjectRef* arrayBufferPrototype();
|
|
FunctionObjectRef* dataView();
|
|
ObjectRef* dataViewPrototype();
|
|
ObjectRef* int8Array();
|
|
ObjectRef* int8ArrayPrototype();
|
|
ObjectRef* uint8Array();
|
|
ObjectRef* uint8ArrayPrototype();
|
|
ObjectRef* int16Array();
|
|
ObjectRef* int16ArrayPrototype();
|
|
ObjectRef* uint16Array();
|
|
ObjectRef* uint16ArrayPrototype();
|
|
ObjectRef* int32Array();
|
|
ObjectRef* int32ArrayPrototype();
|
|
ObjectRef* uint32Array();
|
|
ObjectRef* uint32ArrayPrototype();
|
|
ObjectRef* uint8ClampedArray();
|
|
ObjectRef* uint8ClampedArrayPrototype();
|
|
ObjectRef* float32Array();
|
|
ObjectRef* float32ArrayPrototype();
|
|
ObjectRef* float64Array();
|
|
ObjectRef* float64ArrayPrototype();
|
|
ObjectRef* bigInt64Array();
|
|
ObjectRef* bigInt64ArrayPrototype();
|
|
ObjectRef* bigUint64Array();
|
|
ObjectRef* bigUint64ArrayPrototype();
|
|
};
|
|
|
|
class ESCARGOT_EXPORT GlobalObjectProxyObjectRef : public ObjectRef {
|
|
public:
|
|
// if there is security error, you can throw error in this callback
|
|
enum AccessOperationType {
|
|
Read, // [[Get]], [[GetOwnProperty]]..
|
|
Write // [[Set]], [[DefineOwnProperty]]..
|
|
};
|
|
typedef void (*SecurityCheckCallback)(ExecutionStateRef* state, GlobalObjectProxyObjectRef* proxy, GlobalObjectRef* targetGlobalObject, AccessOperationType operationType, OptionalRef<AtomicStringRef> nonIndexedStringPropertyNameIfExists);
|
|
|
|
static GlobalObjectProxyObjectRef* create(ExecutionStateRef* state, GlobalObjectRef* target, SecurityCheckCallback callback);
|
|
|
|
GlobalObjectRef* target();
|
|
void setTarget(GlobalObjectRef* target);
|
|
};
|
|
|
|
class ESCARGOT_EXPORT FunctionObjectRef : public ObjectRef {
|
|
public:
|
|
// if newTarget is present, that means constructor call
|
|
// in constructor call, function must return newly created object && thisValue is always undefined
|
|
typedef ValueRef* (*NativeFunctionPointer)(ExecutionStateRef* state, ValueRef* thisValue, size_t argc, ValueRef** argv, bool isConstructorCall);
|
|
|
|
enum BuiltinFunctionSlot : size_t {
|
|
PublicFunctionIndex = 0,
|
|
};
|
|
|
|
struct ESCARGOT_EXPORT NativeFunctionInfo {
|
|
bool m_isStrict;
|
|
bool m_isConstructor;
|
|
AtomicStringRef* m_name;
|
|
NativeFunctionPointer m_nativeFunction;
|
|
size_t m_argumentCount;
|
|
|
|
NativeFunctionInfo(AtomicStringRef* name, NativeFunctionPointer fn, size_t argc, bool isStrict = true, bool isConstructor = true)
|
|
: m_isStrict(isStrict)
|
|
, m_isConstructor(isConstructor)
|
|
, m_name(name)
|
|
, m_nativeFunction(fn)
|
|
, m_argumentCount(argc)
|
|
{
|
|
}
|
|
};
|
|
|
|
static FunctionObjectRef* create(ExecutionStateRef* state, NativeFunctionInfo info);
|
|
static FunctionObjectRef* createBuiltinFunction(ExecutionStateRef* state, NativeFunctionInfo info); // protoype of builtin function is non-writable
|
|
static FunctionObjectRef* create(ExecutionStateRef* state, AtomicStringRef* functionName, size_t argumentCount, ValueRef** argumentNameArray, ValueRef* body);
|
|
|
|
// get prototype property of constructible function(not [[prototype]])
|
|
// this property is used for new object construction. see https://www.ecma-international.org/ecma-262/6.0/#sec-ordinarycreatefromconstructor
|
|
ValueRef* getFunctionPrototype(ExecutionStateRef* state);
|
|
|
|
// set prototype property constructible function(not [[prototype]])
|
|
// this property is used for new object construction. see https://www.ecma-international.org/ecma-262/6.0/#sec-ordinarycreatefromconstructor
|
|
bool setFunctionPrototype(ExecutionStateRef* state, ValueRef* v);
|
|
|
|
bool isConstructor();
|
|
void markFunctionNeedsSlowVirtualIdentifierOperation();
|
|
};
|
|
|
|
class ESCARGOT_EXPORT IteratorObjectRef : public ObjectRef {
|
|
public:
|
|
ValueRef* next(ExecutionStateRef* state);
|
|
};
|
|
|
|
class ESCARGOT_EXPORT GenericIteratorObjectRef : public IteratorObjectRef {
|
|
public:
|
|
// returns result and done pair
|
|
typedef std::pair<ValueRef*, bool> (*GenericIteratorObjectRefCallback)(ExecutionStateRef* state, void* data);
|
|
|
|
static GenericIteratorObjectRef* create(ExecutionStateRef* state, GenericIteratorObjectRefCallback callback, void* callbackData);
|
|
};
|
|
|
|
class ESCARGOT_EXPORT ArrayObjectRef : public ObjectRef {
|
|
public:
|
|
static ArrayObjectRef* create(ExecutionStateRef* state);
|
|
static ArrayObjectRef* create(ExecutionStateRef* state, const uint64_t size);
|
|
static ArrayObjectRef* create(ExecutionStateRef* state, ValueVectorRef* source);
|
|
IteratorObjectRef* values(ExecutionStateRef* state);
|
|
IteratorObjectRef* keys(ExecutionStateRef* state);
|
|
IteratorObjectRef* entries(ExecutionStateRef* state);
|
|
};
|
|
|
|
class ESCARGOT_EXPORT ErrorObjectRef : public ObjectRef {
|
|
public:
|
|
enum Code {
|
|
None,
|
|
ReferenceError,
|
|
TypeError,
|
|
SyntaxError,
|
|
RangeError,
|
|
URIError,
|
|
EvalError,
|
|
AggregateError,
|
|
};
|
|
static ErrorObjectRef* create(ExecutionStateRef* state, ErrorObjectRef::Code code, StringRef* errorMessage);
|
|
};
|
|
|
|
class ESCARGOT_EXPORT ReferenceErrorObjectRef : public ErrorObjectRef {
|
|
public:
|
|
static ReferenceErrorObjectRef* create(ExecutionStateRef* state, StringRef* errorMessage);
|
|
};
|
|
|
|
class ESCARGOT_EXPORT TypeErrorObjectRef : public ErrorObjectRef {
|
|
public:
|
|
static TypeErrorObjectRef* create(ExecutionStateRef* state, StringRef* errorMessage);
|
|
};
|
|
|
|
class ESCARGOT_EXPORT SyntaxErrorObjectRef : public ErrorObjectRef {
|
|
public:
|
|
static SyntaxErrorObjectRef* create(ExecutionStateRef* state, StringRef* errorMessage);
|
|
};
|
|
|
|
class ESCARGOT_EXPORT RangeErrorObjectRef : public ErrorObjectRef {
|
|
public:
|
|
static RangeErrorObjectRef* create(ExecutionStateRef* state, StringRef* errorMessage);
|
|
};
|
|
|
|
class ESCARGOT_EXPORT URIErrorObjectRef : public ErrorObjectRef {
|
|
public:
|
|
static URIErrorObjectRef* create(ExecutionStateRef* state, StringRef* errorMessage);
|
|
};
|
|
|
|
class ESCARGOT_EXPORT EvalErrorObjectRef : public ErrorObjectRef {
|
|
public:
|
|
static EvalErrorObjectRef* create(ExecutionStateRef* state, StringRef* errorMessage);
|
|
};
|
|
|
|
class ESCARGOT_EXPORT AggregateErrorObjectRef : public ErrorObjectRef {
|
|
public:
|
|
static AggregateErrorObjectRef* create(ExecutionStateRef* state, StringRef* errorMessage);
|
|
};
|
|
|
|
class ESCARGOT_EXPORT DateObjectRef : public ObjectRef {
|
|
public:
|
|
static DateObjectRef* create(ExecutionStateRef* state);
|
|
static int64_t currentTime();
|
|
void setTimeValue(ExecutionStateRef* state, ValueRef* str);
|
|
void setTimeValue(int64_t value);
|
|
StringRef* toUTCString(ExecutionStateRef* state);
|
|
double primitiveValue();
|
|
};
|
|
|
|
class ESCARGOT_EXPORT StringObjectRef : public ObjectRef {
|
|
public:
|
|
static StringObjectRef* create(ExecutionStateRef* state);
|
|
|
|
void setPrimitiveValue(ExecutionStateRef* state, ValueRef* value);
|
|
StringRef* primitiveValue();
|
|
};
|
|
|
|
class ESCARGOT_EXPORT SymbolObjectRef : public ObjectRef {
|
|
public:
|
|
static SymbolObjectRef* create(ExecutionStateRef* state);
|
|
|
|
void setPrimitiveValue(ExecutionStateRef* state, SymbolRef* value);
|
|
SymbolRef* primitiveValue();
|
|
};
|
|
|
|
class ESCARGOT_EXPORT BigIntObjectRef : public ObjectRef {
|
|
public:
|
|
static BigIntObjectRef* create(ExecutionStateRef* state);
|
|
|
|
void setPrimitiveValue(ExecutionStateRef* state, BigIntRef* value);
|
|
BigIntRef* primitiveValue();
|
|
};
|
|
|
|
class ESCARGOT_EXPORT NumberObjectRef : public ObjectRef {
|
|
public:
|
|
static NumberObjectRef* create(ExecutionStateRef* state);
|
|
|
|
void setPrimitiveValue(ExecutionStateRef* state, ValueRef* value);
|
|
double primitiveValue();
|
|
};
|
|
|
|
class ESCARGOT_EXPORT BooleanObjectRef : public ObjectRef {
|
|
public:
|
|
static BooleanObjectRef* create(ExecutionStateRef* state);
|
|
|
|
void setPrimitiveValue(ExecutionStateRef* state, ValueRef* value);
|
|
bool primitiveValue();
|
|
};
|
|
|
|
class ESCARGOT_EXPORT RegExpObjectRef : public ObjectRef {
|
|
public:
|
|
enum RegExpObjectOption {
|
|
None = 0 << 0,
|
|
Global = 1 << 0,
|
|
IgnoreCase = 1 << 1,
|
|
MultiLine = 1 << 2,
|
|
Sticky = 1 << 3,
|
|
Unicode = 1 << 4,
|
|
DotAll = 1 << 5,
|
|
};
|
|
|
|
struct ESCARGOT_EXPORT RegexMatchResult {
|
|
struct RegexMatchResultPiece {
|
|
unsigned m_start, m_end;
|
|
};
|
|
int m_subPatternNum;
|
|
std::vector<std::vector<RegexMatchResultPiece>> m_matchResults;
|
|
};
|
|
|
|
static RegExpObjectRef* create(ExecutionStateRef* state, ValueRef* source, ValueRef* option);
|
|
static RegExpObjectRef* create(ExecutionStateRef* state, ValueRef* source, RegExpObjectOption option = None);
|
|
|
|
bool match(ExecutionStateRef* state, ValueRef* str, RegexMatchResult& result, bool testOnly = false, size_t startIndex = 0);
|
|
|
|
StringRef* source();
|
|
RegExpObjectOption option();
|
|
};
|
|
|
|
class ESCARGOT_EXPORT BackingStoreRef {
|
|
friend class ArrayBufferObject;
|
|
|
|
public:
|
|
typedef void (*BackingStoreRefDeleterCallback)(void* data, size_t length,
|
|
void* deleterData);
|
|
|
|
// create default NonSharedBackingStore allocated by platform allocator
|
|
static BackingStoreRef* createDefaultNonSharedBackingStore(size_t byteLength);
|
|
// create customized NonSharedBackingStore allocated by other allocator
|
|
static BackingStoreRef* createNonSharedBackingStore(void* data, size_t byteLength, BackingStoreRefDeleterCallback callback, void* callbackData);
|
|
|
|
// Note) SharedBackingStore is allocated for each worker(thread) and its internal data block is actually shared among workers.
|
|
// Also, SharedBackingStore's internal data block is allocated only by platform allocator now.
|
|
// create default SharedBackingStore allocated by platform allocator
|
|
static BackingStoreRef* createDefaultSharedBackingStore(size_t byteLength);
|
|
// create SharedBackingStore by sharing with already created one
|
|
static BackingStoreRef* createSharedBackingStore(BackingStoreRef* backingStore);
|
|
|
|
void* data();
|
|
size_t byteLength();
|
|
// Indicates whether the backing store is SharedDataBlock(for SharedArrayBuffer)
|
|
bool isShared();
|
|
void reallocate(size_t newByteLength);
|
|
};
|
|
|
|
class ESCARGOT_EXPORT ArrayBufferRef : public ObjectRef {
|
|
public:
|
|
OptionalRef<BackingStoreRef> backingStore();
|
|
uint8_t* rawBuffer();
|
|
size_t byteLength();
|
|
};
|
|
|
|
class ESCARGOT_EXPORT ArrayBufferObjectRef : public ArrayBufferRef {
|
|
public:
|
|
static ArrayBufferObjectRef* create(ExecutionStateRef* state);
|
|
void allocateBuffer(ExecutionStateRef* state, size_t bytelength);
|
|
void attachBuffer(BackingStoreRef* backingStore);
|
|
void detachArrayBuffer();
|
|
bool isDetachedBuffer();
|
|
};
|
|
|
|
class ESCARGOT_EXPORT SharedArrayBufferObjectRef : public ArrayBufferRef {
|
|
public:
|
|
static SharedArrayBufferObjectRef* create(ExecutionStateRef* state, size_t bytelength);
|
|
static SharedArrayBufferObjectRef* create(ExecutionStateRef* state, BackingStoreRef* backingStore);
|
|
};
|
|
|
|
class ESCARGOT_EXPORT ArrayBufferViewRef : public ObjectRef {
|
|
public:
|
|
ArrayBufferRef* buffer();
|
|
void setBuffer(ArrayBufferRef* bo, size_t byteOffset, size_t byteLength, size_t arrayLength);
|
|
void setBuffer(ArrayBufferRef* bo, size_t byteOffset, size_t byteLength);
|
|
uint8_t* rawBuffer();
|
|
size_t byteLength();
|
|
size_t byteOffset();
|
|
size_t arrayLength();
|
|
};
|
|
|
|
class ESCARGOT_EXPORT DataViewObjectRef : public ArrayBufferViewRef {
|
|
public:
|
|
static DataViewObjectRef* create(ExecutionStateRef* state);
|
|
};
|
|
|
|
class ESCARGOT_EXPORT Int8ArrayObjectRef : public ArrayBufferViewRef {
|
|
public:
|
|
static Int8ArrayObjectRef* create(ExecutionStateRef* state);
|
|
};
|
|
|
|
class ESCARGOT_EXPORT Uint8ArrayObjectRef : public ArrayBufferViewRef {
|
|
public:
|
|
static Uint8ArrayObjectRef* create(ExecutionStateRef* state);
|
|
};
|
|
|
|
class ESCARGOT_EXPORT Int16ArrayObjectRef : public ArrayBufferViewRef {
|
|
public:
|
|
static Int16ArrayObjectRef* create(ExecutionStateRef* state);
|
|
};
|
|
|
|
class ESCARGOT_EXPORT Uint16ArrayObjectRef : public ArrayBufferViewRef {
|
|
public:
|
|
static Uint16ArrayObjectRef* create(ExecutionStateRef* state);
|
|
};
|
|
|
|
class ESCARGOT_EXPORT Uint32ArrayObjectRef : public ArrayBufferViewRef {
|
|
public:
|
|
static Uint32ArrayObjectRef* create(ExecutionStateRef* state);
|
|
};
|
|
|
|
class ESCARGOT_EXPORT Int32ArrayObjectRef : public ArrayBufferViewRef {
|
|
public:
|
|
static Int32ArrayObjectRef* create(ExecutionStateRef* state);
|
|
};
|
|
|
|
class ESCARGOT_EXPORT Uint8ClampedArrayObjectRef : public ArrayBufferViewRef {
|
|
public:
|
|
static Uint8ClampedArrayObjectRef* create(ExecutionStateRef* state);
|
|
};
|
|
|
|
class ESCARGOT_EXPORT Float32ArrayObjectRef : public ArrayBufferViewRef {
|
|
public:
|
|
static Float32ArrayObjectRef* create(ExecutionStateRef* state);
|
|
};
|
|
|
|
class ESCARGOT_EXPORT Float64ArrayObjectRef : public ArrayBufferViewRef {
|
|
public:
|
|
static Float64ArrayObjectRef* create(ExecutionStateRef* state);
|
|
};
|
|
|
|
class ESCARGOT_EXPORT BigInt64ArrayObjectRef : public ArrayBufferViewRef {
|
|
public:
|
|
static BigInt64ArrayObjectRef* create(ExecutionStateRef* state);
|
|
};
|
|
|
|
class ESCARGOT_EXPORT BigUint64ArrayObjectRef : public ArrayBufferViewRef {
|
|
public:
|
|
static BigUint64ArrayObjectRef* create(ExecutionStateRef* state);
|
|
};
|
|
|
|
class ESCARGOT_EXPORT PromiseObjectRef : public ObjectRef {
|
|
public:
|
|
static PromiseObjectRef* create(ExecutionStateRef* state);
|
|
|
|
enum PromiseState {
|
|
Pending,
|
|
FulFilled,
|
|
Rejected
|
|
};
|
|
PromiseState state();
|
|
ValueRef* promiseResult();
|
|
|
|
ObjectRef* then(ExecutionStateRef* state, ValueRef* handler);
|
|
ObjectRef* catchOperation(ExecutionStateRef* state, ValueRef* handler);
|
|
ObjectRef* then(ExecutionStateRef* state, ValueRef* onFulfilled, ValueRef* onRejected);
|
|
void fulfill(ExecutionStateRef* state, ValueRef* value);
|
|
void reject(ExecutionStateRef* state, ValueRef* reason);
|
|
};
|
|
|
|
class ESCARGOT_EXPORT ProxyObjectRef : public ObjectRef {
|
|
public:
|
|
static ProxyObjectRef* create(ExecutionStateRef* state, ObjectRef* target, ObjectRef* handler);
|
|
ObjectRef* target();
|
|
ObjectRef* handler();
|
|
bool isRevoked();
|
|
void revoke();
|
|
};
|
|
|
|
class ESCARGOT_EXPORT SetObjectRef : public ObjectRef {
|
|
public:
|
|
static SetObjectRef* create(ExecutionStateRef* state);
|
|
void add(ExecutionStateRef* state, ValueRef* key);
|
|
void clear(ExecutionStateRef* state);
|
|
bool deleteOperation(ExecutionStateRef* state, ValueRef* key);
|
|
bool has(ExecutionStateRef* state, ValueRef* key);
|
|
size_t size(ExecutionStateRef* state);
|
|
IteratorObjectRef* values(ExecutionStateRef* state);
|
|
IteratorObjectRef* keys(ExecutionStateRef* state);
|
|
IteratorObjectRef* entries(ExecutionStateRef* state);
|
|
};
|
|
|
|
class ESCARGOT_EXPORT WeakSetObjectRef : public ObjectRef {
|
|
public:
|
|
static WeakSetObjectRef* create(ExecutionStateRef* state);
|
|
void add(ExecutionStateRef* state, ObjectRef* key);
|
|
bool deleteOperation(ExecutionStateRef* state, ObjectRef* key);
|
|
bool has(ExecutionStateRef* state, ObjectRef* key);
|
|
};
|
|
|
|
class ESCARGOT_EXPORT MapObjectRef : public ObjectRef {
|
|
public:
|
|
static MapObjectRef* create(ExecutionStateRef* state);
|
|
void clear(ExecutionStateRef* state);
|
|
bool deleteOperation(ExecutionStateRef* state, ValueRef* key);
|
|
ValueRef* get(ExecutionStateRef* state, ValueRef* key);
|
|
bool has(ExecutionStateRef* state, ValueRef* key);
|
|
void set(ExecutionStateRef* state, ValueRef* key, ValueRef* value);
|
|
size_t size(ExecutionStateRef* state);
|
|
IteratorObjectRef* values(ExecutionStateRef* state);
|
|
IteratorObjectRef* keys(ExecutionStateRef* state);
|
|
IteratorObjectRef* entries(ExecutionStateRef* state);
|
|
};
|
|
|
|
class ESCARGOT_EXPORT WeakMapObjectRef : public ObjectRef {
|
|
public:
|
|
static WeakMapObjectRef* create(ExecutionStateRef* state);
|
|
bool deleteOperation(ExecutionStateRef* state, ObjectRef* key);
|
|
ValueRef* get(ExecutionStateRef* state, ObjectRef* key);
|
|
bool has(ExecutionStateRef* state, ObjectRef* key);
|
|
void set(ExecutionStateRef* state, ObjectRef* key, ValueRef* value);
|
|
};
|
|
|
|
class ESCARGOT_EXPORT WeakRefObjectRef : public ObjectRef {
|
|
public:
|
|
static WeakRefObjectRef* create(ExecutionStateRef* state, ObjectRef* target);
|
|
// returns true if target is alive
|
|
bool deleteOperation(ExecutionStateRef* state);
|
|
OptionalRef<ObjectRef> deref();
|
|
};
|
|
|
|
class ESCARGOT_EXPORT FinalizationRegistryObjectRef : public ObjectRef {
|
|
public:
|
|
static FinalizationRegistryObjectRef* create(ExecutionStateRef* state, ObjectRef* cleanupCallback, ContextRef* realm);
|
|
};
|
|
|
|
// don't modify template after instantiate object
|
|
// it is not intented operation
|
|
// Note) only String or Symbol type is allowed for `propertyName`
|
|
// because TemplateRef is set without ExecutionStateRef, so property name conversion is impossible.
|
|
class ESCARGOT_EXPORT TemplateRef {
|
|
public:
|
|
void set(ValueRef* propertyName, ValueRef* data, bool isWritable, bool isEnumerable, bool isConfigurable);
|
|
void set(ValueRef* propertyName, TemplateRef* data, bool isWritable, bool isEnumerable, bool isConfigurable);
|
|
void setAccessorProperty(ValueRef* propertyName, OptionalRef<FunctionTemplateRef> getter, OptionalRef<FunctionTemplateRef> setter, bool isEnumerable, bool isConfigurable);
|
|
void setNativeDataAccessorProperty(ValueRef* propertyName, ObjectRef::NativeDataAccessorPropertyGetter getter, ObjectRef::NativeDataAccessorPropertySetter setter,
|
|
bool isWritable, bool isEnumerable, bool isConfigurable, bool actsLikeJSGetterSetter = false);
|
|
void setNativeDataAccessorProperty(ValueRef* propertyName, ObjectRef::NativeDataAccessorPropertyData* data, bool actsLikeJSGetterSetter = false);
|
|
|
|
bool has(ValueRef* propertyName);
|
|
// return true if removed
|
|
bool remove(ValueRef* propertyName);
|
|
|
|
ObjectRef* instantiate(ContextRef* ctx);
|
|
bool didInstantiate();
|
|
|
|
bool isObjectTemplate();
|
|
bool isFunctionTemplate();
|
|
|
|
void setInstanceExtraData(void* ptr);
|
|
void* instanceExtraData();
|
|
};
|
|
|
|
typedef OptionalRef<ValueRef> (*PropertyHandlerGetterCallback)(ExecutionStateRef* state, ObjectRef* self, ValueRef* receiver, void* data, ValueRef* propertyName);
|
|
// if intercepted you may returns non-empty value.
|
|
// the returned value will be use futuer operation(you can return true, or false)
|
|
typedef OptionalRef<ValueRef> (*PropertyHandlerSetterCallback)(ExecutionStateRef* state, ObjectRef* self, ValueRef* receiver, void* data, ValueRef* propertyName, ValueRef* value);
|
|
enum class ObjectTemplatePropertyAttribute : uint8_t {
|
|
PropertyAttributeNotExist = 1 << 0,
|
|
PropertyAttributeExist = 1 << 1,
|
|
PropertyAttributeWritable = 1 << 2,
|
|
PropertyAttributeEnumerable = 1 << 3,
|
|
PropertyAttributeConfigurable = 1 << 4,
|
|
};
|
|
inline bool operator&(ObjectTemplatePropertyAttribute a, ObjectTemplatePropertyAttribute b)
|
|
{
|
|
return static_cast<uint8_t>(a) & static_cast<uint8_t>(b);
|
|
}
|
|
inline ObjectTemplatePropertyAttribute operator|(ObjectTemplatePropertyAttribute a, ObjectTemplatePropertyAttribute b)
|
|
{
|
|
return static_cast<ObjectTemplatePropertyAttribute>(static_cast<uint8_t>(a) | static_cast<uint8_t>(b));
|
|
}
|
|
typedef ObjectTemplatePropertyAttribute (*PropertyHandlerQueryCallback)(ExecutionStateRef* state, ObjectRef* self, ValueRef* receiver, void* data, ValueRef* propertyName);
|
|
// if intercepted you may returns non-empty value.
|
|
// the returned value will be use futuer operation(you can return true, or false)
|
|
typedef OptionalRef<ValueRef> (*PropertyHandlerDeleteCallback)(ExecutionStateRef* state, ObjectRef* self, ValueRef* receiver, void* data, ValueRef* propertyName);
|
|
typedef ValueVectorRef* (*PropertyHandlerEnumerationCallback)(ExecutionStateRef* state, ObjectRef* self, ValueRef* receiver, void* data);
|
|
// if intercepted you may returns non-empty value.
|
|
// the returned value will be use futuer operation(you can return true, or false)
|
|
typedef OptionalRef<ValueRef> (*PropertyHandlerDefineOwnPropertyCallback)(ExecutionStateRef* state, ObjectRef* self, ValueRef* receiver, void* data, ValueRef* propertyName, const ObjectPropertyDescriptorRef& desc);
|
|
typedef OptionalRef<ValueRef> (*PropertyHandlerGetPropertyDescriptorCallback)(ExecutionStateRef* state, ObjectRef* self, ValueRef* receiver, void* data, ValueRef* propertyName);
|
|
|
|
struct ESCARGOT_EXPORT ObjectTemplatePropertyHandlerConfiguration {
|
|
PropertyHandlerGetterCallback getter;
|
|
PropertyHandlerSetterCallback setter;
|
|
PropertyHandlerQueryCallback query;
|
|
PropertyHandlerDeleteCallback deleter;
|
|
PropertyHandlerEnumerationCallback enumerator;
|
|
PropertyHandlerDefineOwnPropertyCallback definer;
|
|
PropertyHandlerGetPropertyDescriptorCallback descriptor;
|
|
void* data; // this data member is guaranteed to be kept in GC heap
|
|
|
|
ObjectTemplatePropertyHandlerConfiguration(
|
|
PropertyHandlerGetterCallback getter = nullptr,
|
|
PropertyHandlerSetterCallback setter = nullptr,
|
|
PropertyHandlerQueryCallback query = nullptr,
|
|
PropertyHandlerDeleteCallback deleter = nullptr,
|
|
PropertyHandlerEnumerationCallback enumerator = nullptr,
|
|
PropertyHandlerDefineOwnPropertyCallback definer = nullptr,
|
|
PropertyHandlerGetPropertyDescriptorCallback descriptor = nullptr,
|
|
void* data = nullptr)
|
|
: getter(getter)
|
|
, setter(setter)
|
|
, query(query)
|
|
, deleter(deleter)
|
|
, enumerator(enumerator)
|
|
, definer(definer)
|
|
, descriptor(descriptor)
|
|
, data(data)
|
|
{
|
|
}
|
|
};
|
|
|
|
class ESCARGOT_EXPORT SerializerRef {
|
|
public:
|
|
// returns the serialization was successful
|
|
static bool serializeInto(ValueRef* value, std::ostringstream& output);
|
|
static ValueRef* deserializeFrom(ContextRef* context, std::istringstream& input);
|
|
};
|
|
|
|
class ESCARGOT_EXPORT ObjectTemplateRef : public TemplateRef {
|
|
public:
|
|
static ObjectTemplateRef* create();
|
|
void setNamedPropertyHandler(const ObjectTemplatePropertyHandlerConfiguration& data);
|
|
void setIndexedPropertyHandler(const ObjectTemplatePropertyHandlerConfiguration& data);
|
|
void removeNamedPropertyHandler();
|
|
void removeIndexedPropertyHandler();
|
|
|
|
// returns function template if object template is instance template of function template
|
|
OptionalRef<FunctionTemplateRef> constructor();
|
|
|
|
// returns the installation was successful
|
|
bool installTo(ContextRef* ctx, ObjectRef* target);
|
|
};
|
|
|
|
// FunctionTemplateRef returns the unique function instance in context.
|
|
class ESCARGOT_EXPORT FunctionTemplateRef : public TemplateRef {
|
|
public:
|
|
// in constructor call, thisValue is default consturcted object
|
|
typedef ValueRef* (*NativeFunctionPointer)(ExecutionStateRef* state, ValueRef* thisValue, size_t argc, ValueRef** argv, OptionalRef<ObjectRef> newTarget);
|
|
|
|
static FunctionTemplateRef* create(AtomicStringRef* name, size_t argumentCount, bool isStrict, bool isConstructor,
|
|
FunctionTemplateRef::NativeFunctionPointer fn);
|
|
|
|
// setName and setLength should be called before instantiate
|
|
void setName(AtomicStringRef* name);
|
|
void setLength(size_t length);
|
|
|
|
void updateCallbackFunction(FunctionTemplateRef::NativeFunctionPointer fn);
|
|
|
|
ObjectTemplateRef* prototypeTemplate();
|
|
// ObjectTemplate for new'ed instance of this functionTemplate
|
|
ObjectTemplateRef* instanceTemplate();
|
|
|
|
void inherit(OptionalRef<FunctionTemplateRef> parent);
|
|
OptionalRef<FunctionTemplateRef> parent();
|
|
};
|
|
|
|
class ESCARGOT_EXPORT ScriptParserRef {
|
|
public:
|
|
struct ESCARGOT_EXPORT InitializeScriptResult {
|
|
bool isSuccessful()
|
|
{
|
|
return script.hasValue();
|
|
}
|
|
|
|
OptionalRef<ScriptRef> script;
|
|
StringRef* parseErrorMessage;
|
|
ErrorObjectRef::Code parseErrorCode;
|
|
|
|
InitializeScriptResult();
|
|
ScriptRef* fetchScriptThrowsExceptionIfParseError(ExecutionStateRef* state);
|
|
};
|
|
|
|
InitializeScriptResult initializeScript(StringRef* sourceCode, StringRef* src, bool isModule = false);
|
|
};
|
|
|
|
class ESCARGOT_EXPORT ScriptRef {
|
|
public:
|
|
bool isModule();
|
|
bool isExecuted();
|
|
StringRef* src();
|
|
StringRef* sourceCode();
|
|
ContextRef* context();
|
|
ValueRef* execute(ExecutionStateRef* state);
|
|
|
|
// only module can use these functions
|
|
size_t moduleRequestsLength();
|
|
StringRef* moduleRequest(size_t i);
|
|
ObjectRef* moduleNamespace(ExecutionStateRef* state);
|
|
bool wasThereErrorOnModuleEvaluation();
|
|
ValueRef* moduleEvaluationError();
|
|
};
|
|
|
|
class ESCARGOT_EXPORT PlatformRef {
|
|
public:
|
|
virtual ~PlatformRef() {}
|
|
|
|
// ArrayBuffer
|
|
// client must returns zero-filled memory
|
|
virtual void* onMallocArrayBufferObjectDataBuffer(size_t sizeInByte)
|
|
{
|
|
return calloc(sizeInByte, 1);
|
|
}
|
|
virtual void onFreeArrayBufferObjectDataBuffer(void* buffer, size_t sizeInByte)
|
|
{
|
|
return free(buffer);
|
|
}
|
|
|
|
virtual void* onReallocArrayBufferObjectDataBuffer(void* oldBuffer, size_t oldSizeInByte, size_t newSizeInByte)
|
|
{
|
|
void* ptr = realloc(oldBuffer, newSizeInByte);
|
|
if (oldSizeInByte < newSizeInByte) {
|
|
uint8_t* s = static_cast<uint8_t*>(ptr);
|
|
memset(s + oldSizeInByte, 0, newSizeInByte - oldSizeInByte);
|
|
}
|
|
return ptr;
|
|
}
|
|
|
|
// If you want to add a Job event, you should call VMInstanceRef::executePendingJob after event. see Shell.cpp
|
|
virtual void markJSJobEnqueued(ContextRef* relatedContext) = 0;
|
|
|
|
// Module
|
|
// client needs cache module map<absolute_module_path, ScriptRef*>
|
|
struct ESCARGOT_EXPORT LoadModuleResult {
|
|
LoadModuleResult(ScriptRef* result);
|
|
LoadModuleResult(ErrorObjectRef::Code errorCode, StringRef* errorMessage);
|
|
|
|
OptionalRef<ScriptRef> script;
|
|
StringRef* errorMessage;
|
|
ErrorObjectRef::Code errorCode;
|
|
};
|
|
virtual LoadModuleResult onLoadModule(ContextRef* relatedContext, ScriptRef* whereRequestFrom, StringRef* moduleSrc) = 0;
|
|
virtual void didLoadModule(ContextRef* relatedContext, OptionalRef<ScriptRef> whereRequestFrom, ScriptRef* loadedModule) = 0;
|
|
|
|
// Dynamic Import
|
|
virtual void hostImportModuleDynamically(ContextRef* relatedContext, ScriptRef* referrer, StringRef* src, PromiseObjectRef* promise)
|
|
{
|
|
notifyHostImportModuleDynamicallyResult(relatedContext, referrer, src, promise, onLoadModule(relatedContext, referrer, src));
|
|
}
|
|
void notifyHostImportModuleDynamicallyResult(ContextRef* relatedContext, ScriptRef* referrer, StringRef* src, PromiseObjectRef* promise, LoadModuleResult loadModuleResult);
|
|
|
|
virtual bool canBlockExecution(ContextRef* relatedContext)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
// ThreadLocal custom data
|
|
// PlatformRef should not have any member variables
|
|
// Instead, user could allocate thread-local values through following methods
|
|
virtual void* allocateThreadLocalCustomData()
|
|
{
|
|
// do nothing
|
|
return nullptr;
|
|
}
|
|
|
|
virtual void deallocateThreadLocalCustomData()
|
|
{
|
|
// do nothing
|
|
}
|
|
|
|
#ifdef ESCARGOT_USE_CUSTOM_LOGGING
|
|
// default custom logger
|
|
virtual void customInfoLogger(const char* format, va_list arg)
|
|
{
|
|
vfprintf(stdout, format, arg);
|
|
}
|
|
|
|
virtual void customErrorLogger(const char* format, va_list arg)
|
|
{
|
|
vfprintf(stderr, format, arg);
|
|
}
|
|
#endif
|
|
|
|
void* threadLocalCustomData();
|
|
};
|
|
|
|
#if defined(ENABLE_WASM)
|
|
class ESCARGOT_EXPORT WASMOperationsRef {
|
|
public:
|
|
static ValueRef* copyStableBufferBytes(ExecutionStateRef* state, ValueRef* source);
|
|
static ObjectRef* asyncCompileModule(ExecutionStateRef* state, ValueRef* source);
|
|
static ObjectRef* instantiatePromiseOfModuleWithImportObject(ExecutionStateRef* state, PromiseObjectRef* promiseOfModule, ValueRef* importObj);
|
|
static void collectHeap();
|
|
};
|
|
#endif
|
|
|
|
} // namespace Escargot
|
|
|
|
#endif
|