aboutsummaryrefslogtreecommitdiff
path: root/src/bun.js/bindings/napi.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/bun.js/bindings/napi.h')
-rw-r--r--src/bun.js/bindings/napi.h242
1 files changed, 242 insertions, 0 deletions
diff --git a/src/bun.js/bindings/napi.h b/src/bun.js/bindings/napi.h
new file mode 100644
index 000000000..754c34ec4
--- /dev/null
+++ b/src/bun.js/bindings/napi.h
@@ -0,0 +1,242 @@
+#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 "JavaScriptCore/CallFrame.h"
+#include "js_native_api_types.h"
+#include "JavaScriptCore/JSWeakValue.h"
+#include "JSFFIFunction.h"
+
+namespace JSC {
+class JSGlobalObject;
+class JSSourceCode;
+}
+
+namespace Napi {
+JSC::SourceCode generateSourceCode(WTF::String keyString, JSC::VM& vm, JSC::JSObject* object, JSC::JSGlobalObject* globalObject);
+}
+
+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 (weakValueRef.isString()) {
+ return JSC::JSValue(weakValueRef.string());
+ }
+
+ if (weakValueRef.isObject()) {
+ return JSC::JSValue(weakValueRef.object());
+ }
+
+ return weakValueRef.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;
+ void* data = nullptr;
+ 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;
+};
+
+class NapiPrototype : public JSC::JSDestructibleObject {
+public:
+ using Base = JSC::JSDestructibleObject;
+
+ static constexpr unsigned StructureFlags = Base::StructureFlags;
+ static constexpr bool needsDestruction = true;
+
+ template<typename CellType, SubspaceAccess>
+ static CompleteSubspace* subspaceFor(VM& vm)
+ {
+ return &vm.destructibleObjectSpace();
+ }
+
+ DECLARE_INFO;
+
+ static NapiPrototype* create(VM& vm, JSGlobalObject* globalObject, Structure* structure)
+ {
+ NapiPrototype* footprint = new (NotNull, allocateCell<NapiPrototype>(vm)) NapiPrototype(vm, structure);
+ footprint->finishCreation(vm);
+ return footprint;
+ }
+
+ static NapiPrototype* create(VM& vm, JSGlobalObject* globalObject)
+ {
+ Structure* structure = createStructure(vm, globalObject, globalObject->objectPrototype());
+ return create(vm, globalObject, structure);
+ }
+
+ static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
+ {
+ ASSERT(globalObject);
+ return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
+ }
+
+ NapiPrototype* subclass(JSC::JSObject* newTarget)
+ {
+ auto& vm = this->vm();
+ auto* structure = InternalFunction::createSubclassStructure(globalObject(),
+ newTarget,
+ this->structure());
+ NapiPrototype* footprint = new (NotNull, allocateCell<NapiPrototype>(vm)) NapiPrototype(vm, structure);
+ footprint->finishCreation(vm);
+ return footprint;
+ }
+
+ NapiRef* napiRef = nullptr;
+
+private:
+ NapiPrototype(VM& vm, Structure* structure)
+ : Base(vm, structure)
+ {
+ }
+};
+
+static inline NapiRef* toJS(napi_ref val)
+{
+ return reinterpret_cast<NapiRef*>(val);
+}
+
+} \ No newline at end of file