/* * 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_NAPI_INCLUDE_JSNAPI_H #define ECMASCRIPT_NAPI_INCLUDE_JSNAPI_H #include #include #include #include #include "ecmascript/common.h" #include "libpandabase/macros.h" namespace panda { class JSNApiHelper; class EscapeLocalScope; class PromiseRejectInfo; template class Global; class JSNApi; class PrimitiveRef; class ArrayRef; class StringRef; class ObjectRef; class FunctionRef; class NumberRef; class BooleanRef; class NativePointerRef; namespace test { class JSNApiTests; } // namespace test namespace ecmascript { class EcmaVM; class JSRuntimeOptions; } // namespace ecmascript using Deleter = void (*)(void *nativePointer, void *data); using EcmaVM = ecmascript::EcmaVM; using JSTaggedType = uint64_t; static constexpr uint32_t DEFAULT_GC_POOL_SIZE = 256 * 1024 * 1024; // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) #define ECMA_DISALLOW_COPY(className) \ className(const className &) = delete; \ className &operator=(const className &) = delete // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) #define ECMA_DISALLOW_MOVE(className) \ className(className &&) = delete; \ className &operator=(className &&) = delete template class PUBLIC_API Local { // NOLINT(cppcoreguidelines-special-member-functions, hicpp-special-member-functions) public: inline Local() = default; template inline Local(const Local ¤t) : address_(reinterpret_cast(*current)) { // Check } Local(const EcmaVM *vm, const Global ¤t); ~Local() = default; inline T *operator*() const { return GetAddress(); } inline T *operator->() const { return GetAddress(); } inline bool IsEmpty() const { return GetAddress() == nullptr; } inline bool CheckException() const { return IsEmpty() || GetAddress()->IsException(); } inline bool IsException() const { return !IsEmpty() && GetAddress()->IsException(); } inline bool IsNull() const { return IsEmpty() || GetAddress()->IsHole(); } private: explicit inline Local(uintptr_t addr) : address_(addr) {} inline T *GetAddress() const { return reinterpret_cast(address_); }; uintptr_t address_ = 0U; friend JSNApiHelper; friend EscapeLocalScope; }; template class PUBLIC_API Global { // NOLINTNEXTLINE(cppcoreguidelines-special-member-functions public: inline Global() = default; inline Global(const Global &that) { Update(that); } inline Global &operator=(const Global &that) { Update(that); return *this; } inline Global(Global &&that) { Update(that); } inline Global &operator=(Global &&that) { Update(that); return *this; } // Non-empty initial value. explicit Global(const EcmaVM *vm); template Global(const EcmaVM *vm, const Local ¤t); template Global(const EcmaVM *vm, const Global ¤t); ~Global() = default; Local ToLocal(const EcmaVM *vm) const { return Local(vm, *this); } void Empty() { address_ = 0; } // This method must be called before Global is released. void FreeGlobalHandleAddr(); inline T *operator*() const { return GetAddress(); } inline T *operator->() const { return GetAddress(); } inline bool IsEmpty() const { return GetAddress() == nullptr; } inline bool CheckException() const { return IsEmpty() || GetAddress()->IsException(); } void SetWeak(); void ClearWeak(); bool IsWeak() const; private: inline T *GetAddress() const { return reinterpret_cast(address_); }; inline void Update(const Global &that); uintptr_t address_ = 0U; const EcmaVM *vm_ {nullptr}; }; // NOLINTNEXTLINE(cppcoreguidelines-special-member-functions, hicpp-special-member-functions) class PUBLIC_API LocalScope { public: explicit LocalScope(const EcmaVM *vm); virtual ~LocalScope(); protected: inline LocalScope(const EcmaVM *vm, JSTaggedType value); private: void *prevNext_ = nullptr; void *prevEnd_ = nullptr; int prevHandleStorageIndex_ {-1}; void *thread_ = nullptr; }; class PUBLIC_API EscapeLocalScope final : public LocalScope { public: explicit EscapeLocalScope(const EcmaVM *vm); ~EscapeLocalScope() override = default; ECMA_DISALLOW_COPY(EscapeLocalScope); ECMA_DISALLOW_MOVE(EscapeLocalScope); template inline Local Escape(Local current) { ASSERT(!alreadyEscape_); alreadyEscape_ = true; *(reinterpret_cast(escapeHandle_)) = **current; return Local(escapeHandle_); } private: bool alreadyEscape_ = false; uintptr_t escapeHandle_ = 0U; }; class PUBLIC_API JSExecutionScope { public: explicit JSExecutionScope(const EcmaVM *vm); ~JSExecutionScope(); ECMA_DISALLOW_COPY(JSExecutionScope); ECMA_DISALLOW_MOVE(JSExecutionScope); private: void *last_current_thread_ = nullptr; bool is_revert_ = false; }; class PUBLIC_API JSValueRef { public: static Local Undefined(const EcmaVM *vm); static Local Null(const EcmaVM *vm); static Local True(const EcmaVM *vm); static Local False(const EcmaVM *vm); static Local Exception(const EcmaVM *vm); bool BooleaValue(); int64_t IntegerValue(const EcmaVM *vm); uint32_t Uint32Value(const EcmaVM *vm); int32_t Int32Value(const EcmaVM *vm); Local ToNumber(const EcmaVM *vm); Local ToBoolean(const EcmaVM *vm); Local ToString(const EcmaVM *vm); Local ToObject(const EcmaVM *vm); Local ToNativePointer(const EcmaVM *vm); bool IsUndefined(); bool IsNull(); bool IsHole(); bool IsTrue(); bool IsFalse(); bool IsNumber(); bool IsBigInt(); bool IsInt(); bool WithinInt32(); bool IsBoolean(); bool IsString(); bool IsSymbol(); bool IsObject(); bool IsArray(const EcmaVM *vm); bool IsConstructor(); bool IsFunction(); bool IsProxy(); bool IsException(); bool IsPromise(); bool IsDataView(); bool IsTypedArray(); bool IsNativePointer(); bool IsDate(); bool IsError(); bool IsMap(); bool IsSet(); bool IsWeakMap(); bool IsWeakSet(); bool IsRegExp(); bool IsArrayIterator(); bool IsStringIterator(); bool IsSetIterator(); bool IsMapIterator(); bool IsArrayBuffer(); bool IsUint8Array(); bool IsInt8Array(); bool IsUint8ClampedArray(); bool IsInt16Array(); bool IsUint16Array(); bool IsInt32Array(); bool IsUint32Array(); bool IsFloat32Array(); bool IsFloat64Array(); bool IsJSPrimitiveRef(); bool IsJSPrimitiveNumber(); bool IsJSPrimitiveInt(); bool IsJSPrimitiveBoolean(); bool IsJSPrimitiveString(); bool IsGeneratorObject(); bool IsJSPrimitiveSymbol(); bool IsArgumentsObject(); bool IsGeneratorFunction(); bool IsAsyncFunction(); bool IsStrictEquals(const EcmaVM *vm, Local value); Local Typeof(const EcmaVM *vm); bool InstanceOf(const EcmaVM *vm, Local value); private: JSTaggedType value_; friend JSNApi; template friend class Global; template friend class Local; }; class PUBLIC_API PrimitiveRef : public JSValueRef { }; class PUBLIC_API IntegerRef : public PrimitiveRef { public: static Local New(const EcmaVM *vm, int input); static Local NewFromUnsigned(const EcmaVM *vm, unsigned int input); int Value(); }; class PUBLIC_API NumberRef : public PrimitiveRef { public: static Local New(const EcmaVM *vm, double input); static Local New(const EcmaVM *vm, int32_t input); static Local New(const EcmaVM *vm, uint32_t input); static Local New(const EcmaVM *vm, int64_t input); double Value(); }; class PUBLIC_API BigIntRef : public PrimitiveRef { public: static Local New(const EcmaVM *vm, uint64_t input); static Local New(const EcmaVM *vm, int64_t input); static Local CreateBigWords(const EcmaVM *vm, bool sign, uint32_t size, const uint64_t* words); void BigIntToInt64(const EcmaVM *vm, int64_t *cValue, bool *lossless); void BigIntToUint64(const EcmaVM *vm, uint64_t *cValue, bool *lossless); void GetWordsArray(bool* signBit, size_t wordCount, uint64_t* words); uint32_t GetWordsArraySize(); }; class PUBLIC_API BooleanRef : public PrimitiveRef { public: static Local New(const EcmaVM *vm, bool input); bool Value(); }; class PUBLIC_API StringRef : public PrimitiveRef { public: static inline StringRef *Cast(JSValueRef *value) { // check return static_cast(value); } static Local NewFromUtf8(const EcmaVM *vm, const char *utf8, int length = -1); std::string ToString(); int32_t Length(); int32_t Utf8Length(); int WriteUtf8(char *buffer, int length); }; class PUBLIC_API SymbolRef : public PrimitiveRef { public: static Local New(const EcmaVM *vm, Local description); Local GetDescription(const EcmaVM *vm); }; using NativePointerCallback = void (*)(void* value, void* hint); class PUBLIC_API NativePointerRef : public JSValueRef { public: static Local New(const EcmaVM *vm, void *nativePointer); static Local New(const EcmaVM *vm, void *nativePointer, NativePointerCallback callBack, void *data); void *Value(); }; // NOLINTNEXTLINE(cppcoreguidelines-special-member-functions, hicpp-special-member-functions) class PUBLIC_API PropertyAttribute { public: static PropertyAttribute Default() { return PropertyAttribute(); } PropertyAttribute() = default; PropertyAttribute(Local value, bool w, bool e, bool c) : value_(value), writable_(w), enumerable_(e), configurable_(c), hasWritable_(true), hasEnumerable_(true), hasConfigurable_(true) {} ~PropertyAttribute() = default; bool IsWritable() const { return writable_; } void SetWritable(bool flag) { writable_ = flag; hasWritable_ = true; } bool IsEnumerable() const { return enumerable_; } void SetEnumerable(bool flag) { enumerable_ = flag; hasEnumerable_ = true; } bool IsConfigurable() const { return configurable_; } void SetConfigurable(bool flag) { configurable_ = flag; hasConfigurable_ = true; } bool HasWritable() const { return hasWritable_; } bool HasConfigurable() const { return hasConfigurable_; } bool HasEnumerable() const { return hasEnumerable_; } Local GetValue(const EcmaVM *vm) const { if (value_.IsEmpty()) { return JSValueRef::Undefined(vm); } return value_; } void SetValue(Local value) { value_ = value; } inline bool HasValue() const { return !value_.IsEmpty(); } Local GetGetter(const EcmaVM *vm) const { if (getter_.IsEmpty()) { return JSValueRef::Undefined(vm); } return getter_; } void SetGetter(Local value) { getter_ = value; } bool HasGetter() const { return !getter_.IsEmpty(); } Local GetSetter(const EcmaVM *vm) const { if (setter_.IsEmpty()) { return JSValueRef::Undefined(vm); } return setter_; } void SetSetter(Local value) { setter_ = value; } bool HasSetter() const { return !setter_.IsEmpty(); } private: Local value_; Local getter_; Local setter_; bool writable_ = false; bool enumerable_ = false; bool configurable_ = false; bool hasWritable_ = false; bool hasEnumerable_ = false; bool hasConfigurable_ = false; }; class PUBLIC_API ObjectRef : public JSValueRef { public: static inline ObjectRef *Cast(JSValueRef *value) { // check return static_cast(value); } static Local New(const EcmaVM *vm); bool Set(const EcmaVM *vm, Local key, Local value); bool Set(const EcmaVM *vm, uint32_t key, Local value); bool SetAccessorProperty(const EcmaVM *vm, Local key, Local getter, Local setter, PropertyAttribute attribute = PropertyAttribute::Default()); Local Get(const EcmaVM *vm, Local key); Local Get(const EcmaVM *vm, int32_t key); bool GetOwnProperty(const EcmaVM *vm, Local key, PropertyAttribute &property); Local GetOwnPropertyNames(const EcmaVM *vm); Local GetOwnEnumerablePropertyNames(const EcmaVM *vm); Local GetPrototype(const EcmaVM *vm); bool DefineProperty(const EcmaVM *vm, Local key, PropertyAttribute attribute); bool Has(const EcmaVM *vm, Local key); bool Has(const EcmaVM *vm, uint32_t key); bool Delete(const EcmaVM *vm, Local key); bool Delete(const EcmaVM *vm, uint32_t key); void SetNativePointerFieldCount(int32_t count); int32_t GetNativePointerFieldCount(); void *GetNativePointerField(int32_t index); void SetNativePointerField(int32_t index, void *nativePointer = nullptr, NativePointerCallback callBack = nullptr, void *data = nullptr); }; using FunctionCallback = Local (*)(EcmaVM *, Local, const Local[], // NOLINTNEXTLINE(modernize-avoid-c-arrays) int32_t, void *); using FunctionCallbackWithNewTarget = Local (*)(EcmaVM *, Local, Local, const Local[], int32_t, void *); class PUBLIC_API FunctionRef : public ObjectRef { public: static Local New(EcmaVM *vm, FunctionCallback nativeFunc, void *data); static Local New(EcmaVM *vm, FunctionCallback nativeFunc, Deleter deleter, void *data); static Local NewWithProperty(EcmaVM *vm, FunctionCallback nativeFunc, void *data); static Local NewClassFunction(EcmaVM *vm, FunctionCallbackWithNewTarget nativeFunc, Deleter deleter, void *data); Local Call(const EcmaVM *vm, Local thisObj, const Local argv[], int32_t length); Local Constructor(const EcmaVM *vm, const Local argv[], int32_t length); Local GetFunctionPrototype(const EcmaVM *vm); // Inherit Prototype from parent function // set this.Prototype.__proto__ to parent.Prototype, set this.__proto__ to parent function bool Inherit(const EcmaVM *vm, Local parent); void SetName(const EcmaVM *vm, Local name); Local GetName(const EcmaVM *vm); bool IsNative(const EcmaVM *vm); }; class PUBLIC_API ArrayRef : public ObjectRef { public: static Local New(const EcmaVM *vm, int32_t length = 0); int32_t Length(const EcmaVM *vm); static bool SetValueAt(const EcmaVM *vm, Local obj, uint32_t index, Local value); static Local GetValueAt(const EcmaVM *vm, Local obj, uint32_t index); }; class PUBLIC_API PromiseRef : public ObjectRef { public: Local Catch(const EcmaVM *vm, Local handler); Local Then(const EcmaVM *vm, Local handler); Local Then(const EcmaVM *vm, Local onFulfilled, Local onRejected); }; class PUBLIC_API PromiseCapabilityRef : public ObjectRef { public: static Local New(const EcmaVM *vm); bool Resolve(const EcmaVM *vm, Local value); bool Reject(const EcmaVM *vm, Local reason); Local GetPromise(const EcmaVM *vm); }; class PUBLIC_API ArrayBufferRef : public ObjectRef { public: static Local New(const EcmaVM *vm, int32_t length); static Local New(const EcmaVM *vm, void *buffer, int32_t length, const Deleter &deleter, void *data); int32_t ByteLength(const EcmaVM *vm); void *GetBuffer(); }; class PUBLIC_API DataViewRef : public ObjectRef { public: static Local New(const EcmaVM *vm, Local arrayBuffer, uint32_t byteOffset, uint32_t byteLength); uint32_t ByteLength(); uint32_t ByteOffset(); Local GetArrayBuffer(const EcmaVM *vm); }; class PUBLIC_API TypedArrayRef : public ObjectRef { public: int32_t ByteLength(const EcmaVM *vm); int32_t ByteOffset(const EcmaVM *vm); int32_t ArrayLength(const EcmaVM *vm); Local GetArrayBuffer(const EcmaVM *vm); }; class PUBLIC_API Int8ArrayRef : public TypedArrayRef { public: static Local New(const EcmaVM *vm, Local buffer, int32_t byteOffset, int32_t length); }; class PUBLIC_API Uint8ArrayRef : public TypedArrayRef { public: static Local New(const EcmaVM *vm, Local buffer, int32_t byteOffset, int32_t length); }; class PUBLIC_API Uint8ClampedArrayRef : public TypedArrayRef { public: static Local New(const EcmaVM *vm, Local buffer, int32_t byteOffset, int32_t length); }; class PUBLIC_API Int16ArrayRef : public TypedArrayRef { public: static Local New(const EcmaVM *vm, Local buffer, int32_t byteOffset, int32_t length); }; class PUBLIC_API Uint16ArrayRef : public TypedArrayRef { public: static Local New(const EcmaVM *vm, Local buffer, int32_t byteOffset, int32_t length); }; class PUBLIC_API Int32ArrayRef : public TypedArrayRef { public: static Local New(const EcmaVM *vm, Local buffer, int32_t byteOffset, int32_t length); }; class PUBLIC_API Uint32ArrayRef : public TypedArrayRef { public: static Local New(const EcmaVM *vm, Local buffer, int32_t byteOffset, int32_t length); }; class PUBLIC_API Float32ArrayRef : public TypedArrayRef { public: static Local New(const EcmaVM *vm, Local buffer, int32_t byteOffset, int32_t length); }; class PUBLIC_API Float64ArrayRef : public TypedArrayRef { public: static Local New(const EcmaVM *vm, Local buffer, int32_t byteOffset, int32_t length); }; class PUBLIC_API RegExpRef : public ObjectRef { public: Local GetOriginalSource(const EcmaVM *vm); }; class PUBLIC_API DateRef : public ObjectRef { public: static Local New(const EcmaVM *vm, double time); Local ToString(const EcmaVM *vm); double GetTime(); }; class PUBLIC_API MapRef : public ObjectRef { public: int32_t GetSize(); }; class PUBLIC_API SetRef : public ObjectRef { public: int32_t GetSize(); }; class PUBLIC_API JSON { public: static Local Parse(const EcmaVM *vm, Local string); static Local Stringify(const EcmaVM *vm, Local json); }; class PUBLIC_API Exception { public: static Local Error(const EcmaVM *vm, Local message); static Local RangeError(const EcmaVM *vm, Local message); static Local ReferenceError(const EcmaVM *vm, Local message); static Local SyntaxError(const EcmaVM *vm, Local message); static Local TypeError(const EcmaVM *vm, Local message); static Local EvalError(const EcmaVM *vm, Local message); }; using LOG_PRINT = int (*)(int id, int level, const char *tag, const char *fmt, const char *message); class PUBLIC_API RuntimeOption { public: enum class PUBLIC_API GC_TYPE : uint8_t { EPSILON, GEN_GC, STW }; enum class PUBLIC_API LOG_LEVEL : uint8_t { DEBUG = 3, INFO = 4, WARN = 5, ERROR = 6, FATAL = 7, }; void SetGcType(GC_TYPE type) { gcType_ = type; } void SetGcPoolSize(uint32_t size) { gcPoolSize_ = size; } void SetLogLevel(LOG_LEVEL logLevel) { logLevel_ = logLevel; } void SetLogBufPrint(LOG_PRINT out) { logBufPrint_ = out; } void SetDebuggerLibraryPath(const std::string &path) { debuggerLibraryPath_ = path; } void SetEnableArkTools(bool value) { enableArkTools_ = value; } void SetEnableCpuprofiler(bool value) { enableCpuprofiler_ = value; } void SetArkProperties(int prop) { arkProperties_ = prop; } private: std::string GetGcType() const { std::string gcType; switch (gcType_) { case GC_TYPE::GEN_GC: gcType = "gen-gc"; break; case GC_TYPE::STW: gcType = "stw"; break; case GC_TYPE::EPSILON: gcType = "epsilon"; break; default: UNREACHABLE(); } return gcType; } std::string GetLogLevel() const { std::string logLevel; switch (logLevel_) { case LOG_LEVEL::INFO: case LOG_LEVEL::WARN: logLevel = "info"; break; case LOG_LEVEL::ERROR: logLevel = "error"; break; case LOG_LEVEL::FATAL: logLevel = "fatal"; break; case LOG_LEVEL::DEBUG: default: logLevel = "debug"; break; } return logLevel; } uint32_t GetGcPoolSize() const { return gcPoolSize_; } LOG_PRINT GetLogBufPrint() const { return logBufPrint_; } std::string GetDebuggerLibraryPath() const { return debuggerLibraryPath_; } bool GetEnableArkTools() const { return enableArkTools_; } bool GetEnableCpuprofiler() const { return enableCpuprofiler_; } int GetArkProperties() const { return arkProperties_; } GC_TYPE gcType_ = GC_TYPE::EPSILON; LOG_LEVEL logLevel_ = LOG_LEVEL::DEBUG; uint32_t gcPoolSize_ = DEFAULT_GC_POOL_SIZE; LOG_PRINT logBufPrint_ {nullptr}; std::string debuggerLibraryPath_ {}; bool enableArkTools_ {false}; bool enableCpuprofiler_ {false}; int arkProperties_ {-1}; friend JSNApi; }; class PUBLIC_API PromiseRejectInfo { public: enum class PUBLIC_API PROMISE_REJECTION_EVENT : uint32_t { REJECT = 0, HANDLE }; PromiseRejectInfo(Local promise, Local reason, PromiseRejectInfo::PROMISE_REJECTION_EVENT operation, void* data); ~PromiseRejectInfo() {} Local GetPromise() const; Local GetReason() const; PromiseRejectInfo::PROMISE_REJECTION_EVENT GetOperation() const; void* GetData() const; private: Local promise_ {}; Local reason_ {}; PROMISE_REJECTION_EVENT operation_ = PROMISE_REJECTION_EVENT::REJECT; void* data_ {nullptr}; }; class PUBLIC_API JSNApi { public: using DebuggerPostTask = std::function&&)>; // JSVM enum class PUBLIC_API TRIGGER_GC_TYPE : uint8_t { SEMI_GC, OLD_GC, FULL_GC }; static EcmaVM *CreateJSVM(const RuntimeOption &option); static void DestroyJSVM(EcmaVM *ecmaVm); // JS code static bool Execute(EcmaVM *vm, const std::string &fileName, const std::string &entry); static bool Execute(EcmaVM *vm, const uint8_t *data, int32_t size, const std::string &entry, const std::string &filename = ""); static bool ExecuteModuleFromBuffer(EcmaVM *vm, const void *data, int32_t size, const std::string &file); static Local GetExportObject(EcmaVM *vm, const std::string &file, const std::string &itemName); // ObjectRef Operation static Local GetGlobalObject(const EcmaVM *vm); static void ExecutePendingJob(const EcmaVM *vm); // Memory static void TriggerGC(const EcmaVM *vm, TRIGGER_GC_TYPE gcType = TRIGGER_GC_TYPE::SEMI_GC); // Exception static void ThrowException(const EcmaVM *vm, Local error); static Local GetAndClearUncaughtException(const EcmaVM *vm); static Local GetUncaughtException(const EcmaVM *vm); static void EnableUserUncaughtErrorHandler(EcmaVM *vm); static bool StartDebugger(const char *libraryPath, EcmaVM *vm, bool isDebugMode, int32_t instanceId = 0, const DebuggerPostTask &debuggerPostTask = {}); static bool StopDebugger(EcmaVM *vm); // Serialize & Deserialize. static void* SerializeValue(const EcmaVM *vm, Local data, Local transfer); static Local DeserializeValue(const EcmaVM *vm, void* recoder); static void DeleteSerializationData(void *data); static void SetOptions(const ecmascript::JSRuntimeOptions &options); static void SetHostPromiseRejectionTracker(EcmaVM *vm, void *cb, void* data); static void SetHostEnqueueJob(const EcmaVM* vm, Local cb); // profile generator static void StartCpuProfiler(const EcmaVM *vm, const std::string &fileName); static void StopCpuProfiler(); static void ResumeVM(const EcmaVM *vm); static bool SuspendVM(const EcmaVM *vm); static bool IsSuspended(const EcmaVM *vm); static bool CheckSafepoint(const EcmaVM *vm); private: static int vmCount; static bool CreateRuntime(const RuntimeOption &option); static bool DestroyRuntime(); static uintptr_t GetHandleAddr(const EcmaVM *vm, uintptr_t localAddress); static uintptr_t GetGlobalHandleAddr(const EcmaVM *vm, uintptr_t localAddress); static uintptr_t SetWeak(const EcmaVM *vm, uintptr_t localAddress); static uintptr_t ClearWeak(const EcmaVM *vm, uintptr_t localAddress); static bool IsWeak(const EcmaVM *vm, uintptr_t localAddress); static void DisposeGlobalHandleAddr(const EcmaVM *vm, uintptr_t addr); template friend class Global; template friend class Local; friend class test::JSNApiTests; }; template template Global::Global(const EcmaVM *vm, const Local ¤t) : vm_(vm) { if (!current.IsEmpty()) { address_ = JSNApi::GetGlobalHandleAddr(vm_, reinterpret_cast(*current)); } } template template Global::Global(const EcmaVM *vm, const Global ¤t) : vm_(vm) { if (!current.IsEmpty()) { address_ = JSNApi::GetGlobalHandleAddr(vm_, reinterpret_cast(*current)); } } template void Global::Update(const Global &that) { if (address_ != 0) { JSNApi::DisposeGlobalHandleAddr(vm_, address_); } address_ = that.address_; vm_ = that.vm_; } template void Global::FreeGlobalHandleAddr() { if (address_ == 0) { return; } JSNApi::DisposeGlobalHandleAddr(vm_, address_); address_ = 0; } template void Global::SetWeak() { address_ = JSNApi::SetWeak(vm_, address_); } template void Global::ClearWeak() { address_ = JSNApi::ClearWeak(vm_, address_); } template bool Global::IsWeak() const { return JSNApi::IsWeak(vm_, address_); } // ---------------------------------- Local -------------------------------------------- template Local::Local(const EcmaVM *vm, const Global ¤t) { address_ = JSNApi::GetHandleAddr(vm, reinterpret_cast(*current)); } } // namespace panda #endif // ECMASCRIPT_NAPI_INCLUDE_JSNAPI_H