diff options
Diffstat (limited to 'src/javascript/jsc/bindings/napi.h')
-rw-r--r-- | src/javascript/jsc/bindings/napi.h | 183 |
1 files changed, 183 insertions, 0 deletions
diff --git a/src/javascript/jsc/bindings/napi.h b/src/javascript/jsc/bindings/napi.h new file mode 100644 index 000000000..e547b22fa --- /dev/null +++ b/src/javascript/jsc/bindings/napi.h @@ -0,0 +1,183 @@ +#pragma once + +namespace Zig { +class GlobalObject; +} + +#include "root.h" +#include "JavaScriptCore/JSFunction.h" +#include "JavaScriptCore/VM.h" + +#include "headers-handwritten.h" +#include "BunClientData.h" +#include "WebCoreJSBuiltinInternals.h" +#include "JavaScriptCore/CallFrame.h" +#include "js_native_api_types.h" +#include "JavaScriptCore/JSWeakValue.h" +#include "JSFFIFunction.h" + +namespace JSC { +class JSGlobalObject; +} + +namespace Zig { + +using namespace JSC; + +static inline JSValue toJS(napi_value val) +{ + return JSC::JSValue::decode(reinterpret_cast<JSC::EncodedJSValue>(val)); +} + +static inline Zig::GlobalObject* toJS(napi_env val) +{ + return reinterpret_cast<Zig::GlobalObject*>(val); +} + +static inline napi_value toNapi(JSC::EncodedJSValue val) +{ + return reinterpret_cast<napi_value>(val); +} + +static inline napi_value toNapi(JSC::JSValue val) +{ + return toNapi(JSC::JSValue::encode(val)); +} + +static inline napi_env toNapi(JSC::JSGlobalObject* val) +{ + return reinterpret_cast<napi_env>(val); +} + +class NapiFinalizer { +public: + void* finalize_hint = nullptr; + napi_finalize finalize_cb; + + void call(JSC::JSGlobalObject* globalObject, void* data); +}; + +class NapiRef : public RefCounted<NapiRef>, public CanMakeWeakPtr<NapiRef> { + WTF_MAKE_FAST_ALLOCATED; + +public: + void ref(); + void unref(); + void clear(); + + NapiRef(JSC::JSGlobalObject* global, uint32_t count) + { + globalObject = JSC::Weak<JSC::JSGlobalObject>(global); + strongRef = {}; + weakValueRef.clear(); + refCount = count; + } + + JSC::JSValue value() const + { + if (refCount == 0) { + if (!weakValueRef.isSet()) { + return JSC::JSValue {}; + } + + if (weakValue.isString()) { + return JSC::JSValue(weakValue.string()); + } + + if (weakValue.isObject()) { + return JSC::JSValue(weakValue.object()); + } + + return weakValue.primitive(); + } + + return strongRef.get(); + } + + ~NapiRef() + { + if (this->refCount > 0) { + this->refCount = 1; + this->unref(); + } + } + + JSC::Weak<JSC::JSGlobalObject> globalObject; + JSC::JSWeakValue weakValueRef; + JSC::Strong<JSC::Unknown> strongRef; + NapiFinalizer finalizer; + uint32_t refCount = 0; +}; + +static inline napi_ref toNapi(NapiRef* val) +{ + return reinterpret_cast<napi_ref>(val); +} + +class NapiClass final : public JSC::JSFunction { +public: + using Base = JSFunction; + + static constexpr unsigned StructureFlags = Base::StructureFlags; + static constexpr bool needsDestruction = false; + static void destroy(JSCell* cell) + { + static_cast<NapiClass*>(cell)->NapiClass::~NapiClass(); + } + + template<typename, SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + if constexpr (mode == JSC::SubspaceAccess::Concurrently) + return nullptr; + return WebCore::subspaceForImpl<NapiClass, WebCore::UseCustomHeapCellType::No>( + vm, + [](auto& spaces) { return spaces.m_clientSubspaceForNapiClass.get(); }, + [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForNapiClass = WTFMove(space); }, + [](auto& spaces) { return spaces.m_subspaceForNapiClass.get(); }, + [](auto& spaces, auto&& space) { spaces.m_subspaceForNapiClass = WTFMove(space); }); + } + + DECLARE_EXPORT_INFO; + + JS_EXPORT_PRIVATE static NapiClass* create(VM&, Zig::GlobalObject*, const char* utf8name, + size_t length, + napi_callback constructor, + void* data, + size_t property_count, + const napi_property_descriptor* properties); + + static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) + { + ASSERT(globalObject); + return Structure::create(vm, globalObject, prototype, TypeInfo(JSFunctionType, StructureFlags), info()); + } + + static CallData getConstructData(JSCell* cell); + + FFIFunction constructor() + { + return m_constructor; + } + + void* dataPtr = nullptr; + FFIFunction m_constructor = nullptr; + +private: + NapiClass(VM& vm, NativeExecutable* executable, JSC::JSGlobalObject* global, Structure* structure) + : Base(vm, executable, global, structure) + { + } + void finishCreation(VM&, NativeExecutable*, unsigned length, const String& name, napi_callback constructor, + void* data, + size_t property_count, + const napi_property_descriptor* properties); + + DECLARE_VISIT_CHILDREN; +}; + +static inline NapiRef* toJS(napi_ref val) +{ + return reinterpret_cast<NapiRef*>(val); +} + +}
\ No newline at end of file |