Skip to content

Commit

Permalink
Implement napi_create_external and napi_get_value_external
Browse files Browse the repository at this point in the history
  • Loading branch information
Jarred-Sumner committed Nov 10, 2022
1 parent 7ce8328 commit dddbce8
Show file tree
Hide file tree
Showing 14 changed files with 342 additions and 86 deletions.
47 changes: 47 additions & 0 deletions src/bun.js/bindings/napi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
#include "../modules/ObjectModule.h"

#include "JavaScriptCore/JSSourceCode.h"
#include "napi_external.h"

// #include <iostream>
using namespace JSC;
Expand Down Expand Up @@ -1433,3 +1434,49 @@ extern "C" napi_status napi_get_property_names(napi_env env, napi_value object,

return napi_ok;
}

extern "C" napi_status napi_create_external(napi_env env, void* data,
napi_finalize finalize_cb,
void* finalize_hint,
napi_value* result)
{
if (UNLIKELY(result == nullptr)) {
return napi_invalid_arg;
}

Zig::GlobalObject* globalObject = toJS(env);
JSC::VM& vm = globalObject->vm();

auto* structure = Bun::NapiExternal::createStructure(vm, globalObject, globalObject->objectPrototype());
JSValue value = JSValue(Bun::NapiExternal::create(vm, structure, data, finalize_hint, finalize_cb));
JSC::EnsureStillAliveScope ensureStillAlive(value);
*result = toNapi(value);
return napi_ok;
}

extern "C" napi_status napi_get_value_external(napi_env env, napi_value value,
void** result)
{
if (UNLIKELY(result == nullptr)) {
return napi_invalid_arg;
}

Zig::GlobalObject* globalObject = toJS(env);
JSC::VM& vm = globalObject->vm();

auto scope = DECLARE_CATCH_SCOPE(vm);
JSC::JSValue jsValue = JSC::JSValue::decode(reinterpret_cast<JSC::EncodedJSValue>(value));
JSC::EnsureStillAliveScope ensureStillAlive(jsValue);

if (!jsValue || !jsValue.isObject()) {
return napi_invalid_arg;
}

JSC::JSObject* object = jsValue.getObject();
if (!object->inherits<Bun::NapiExternal>()) {
return napi_invalid_arg;
}

*result = jsCast<Bun::NapiExternal*>(object)->value();
return napi_ok;
}
60 changes: 15 additions & 45 deletions src/bun.js/bindings/napi_external.cpp
Original file line number Diff line number Diff line change
@@ -1,50 +1,20 @@
#include "napi_external.h"
#include "napi.h"

namespace Bun {

// #pragma once
NapiExternal::~NapiExternal()
{
if (finalizer) {
finalizer(toNapi(globalObject()), m_value, m_finalizerHint);
}
}

// #include "root.h"
void NapiExternal::destroy(JSC::JSCell* cell)
{
jsCast<NapiExternal*>(cell)->~NapiExternal();
}

// #include "BunBuiltinNames.h"
// #include "BunClientData.h"
const ClassInfo NapiExternal::s_info = { "External"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(NapiExternal) };

// namespace Zig {

// using namespace JSC;

// class NapiExternal : public JSC::JSNonFinalObject {
// using Base = JSC::JSNonFinalObject;

// public:
// NapiExternal(JSC::VM& vm, JSC::Structure* structure)
// : Base(vm, structure)
// {
// }

// DECLARE_INFO;

// static constexpr unsigned StructureFlags = Base::StructureFlags;

// template<typename CellType, SubspaceAccess> static GCClient::IsoSubspace* subspaceFor(VM& vm)
// {
// return &vm.plainObjectSpace();
// }

// static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject,
// JSC::JSValue prototype)
// {
// return JSC::Structure::create(vm, globalObject, prototype,
// JSC::TypeInfo(JSC::ObjectType, StructureFlags), info());
// }

// static NapiExternal* create(JSC::VM& vm, JSC::Structure* structure)
// {
// NapiExternal* accessor = new (NotNull, JSC::allocateCell<NapiExternal>(vm)) NapiExternal(vm, structure);
// accessor->finishCreation(vm);
// return accessor;
// }

// void finishCreation(JSC::VM& vm);
// void* m_value;
// };

// } // namespace Zig
}
93 changes: 52 additions & 41 deletions src/bun.js/bindings/napi_external.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,59 +6,70 @@

#include "BunBuiltinNames.h"
#include "BunClientData.h"
#include "node_api.h"

namespace Zig {
namespace Bun {

using namespace JSC;
using namespace WebCore;

class NapiExternal : public JSC::JSNonFinalObject {
using Base = JSC::JSNonFinalObject;
class NapiExternal : public JSC::JSDestructibleObject {
using Base = JSC::JSDestructibleObject;

public:
NapiExternal(JSC::VM& vm, JSC::Structure* structure)
: Base(vm, structure)
{
}

DECLARE_INFO;
DECLARE_EXPORT_INFO;

~NapiExternal()
static constexpr unsigned StructureFlags = Base::StructureFlags;

template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm)
{
if constexpr (mode == JSC::SubspaceAccess::Concurrently)
return nullptr;

return WebCore::subspaceForImpl<NapiExternal, UseCustomHeapCellType::No>(
vm,
[](auto& spaces) { return spaces.m_clientSubspaceForNapiExternal.get(); },
[](auto& spaces, auto&& space) { spaces.m_clientSubspaceForNapiExternal = WTFMove(space); },
[](auto& spaces) { return spaces.m_subspaceForNapiExternal.get(); },
[](auto& spaces, auto&& space) { spaces.m_subspaceForNapiExternal = WTFMove(space); });
}

~NapiExternal();

static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject,
JSC::JSValue prototype)
{
return JSC::Structure::create(vm, globalObject, prototype,
JSC::TypeInfo(JSC::ObjectType, StructureFlags), info());
}

static NapiExternal* create(JSC::VM& vm, JSC::Structure* structure, void* value, void* finalizer_hint, napi_finalize finalizer)
{
if (m_value) {
delete m_value;
}

static constexpr unsigned StructureFlags = Base::StructureFlags;

template<typename, SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM & vm)
{
if constexpr (mode == JSC::SubspaceAccess::Concurrently)
return nullptr;
return WebCore::subspaceForImpl<JSNapiExternal, WebCore::UseCustomHeapCellType::No>(
vm,
[](auto& spaces) { return spaces.m_clientSubspaceForNapiExternal.get(); },
[](auto& spaces, auto&& space) { spaces.m_clientSubspaceForNapiExternal = WTFMove(space); },
[](auto& spaces) { return spaces.m_subspaceForNapiExternal.get(); },
[](auto& spaces, auto&& space) { spaces.m_subspaceForNapiExternal = WTFMove(space); });
}

static JSC::Structure* createStructure(JSC::VM & vm, JSC::JSGlobalObject * globalObject,
JSC::JSValue prototype)
{
return JSC::Structure::create(vm, globalObject, prototype,
JSC::TypeInfo(JSC::ObjectType, StructureFlags), info());
}

static NapiExternal* create(JSC::VM & vm, JSC::Structure * structure)
{
NapiExternal* accessor = new (NotNull, JSC::allocateCell<NapiExternal>(vm)) NapiExternal(vm, structure);
accessor->finishCreation(vm);
return accessor;
}

void finishCreation(JSC::VM & vm);
void* m_value;
void* finalizer_context;
};
NapiExternal* accessor = new (NotNull, JSC::allocateCell<NapiExternal>(vm)) NapiExternal(vm, structure);
accessor->finishCreation(vm, value, finalizer_hint, finalizer);
return accessor;
}

void finishCreation(JSC::VM& vm, void* value, void* finalizer_hint, napi_finalize finalizer)
{
Base::finishCreation(vm);
m_value = value;
m_finalizerHint = finalizer_hint;
this->finalizer = finalizer;
}

static void destroy(JSC::JSCell* cell);

void* value() const { return m_value; }

void* m_value;
void* m_finalizerHint;
napi_finalize finalizer;
};

} // namespace Zig
1 change: 1 addition & 0 deletions src/bun.js/bindings/webcore/DOMClientIsoSubspaces.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ class DOMClientIsoSubspaces {
std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForPendingVirtualModuleResult;
std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForOnigurumaRegExp;
std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForCallSite;
std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForNapiExternal;
#include "ZigGeneratedClasses+DOMClientIsoSubspaces.h"
/* --- bun --- */

Expand Down
1 change: 1 addition & 0 deletions src/bun.js/bindings/webcore/DOMIsoSubspaces.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ class DOMIsoSubspaces {
std::unique_ptr<IsoSubspace> m_subspaceForPendingVirtualModuleResult;
std::unique_ptr<IsoSubspace> m_subspaceForOnigurumaRegExp;
std::unique_ptr<IsoSubspace> m_subspaceForCallSite;
std::unique_ptr<IsoSubspace> m_subspaceForNapiExternal;
#include "ZigGeneratedClasses+DOMIsoSubspaces.h"
/*-- BUN --*/

Expand Down
4 changes: 4 additions & 0 deletions src/napi/napi.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1506,6 +1506,8 @@ pub fn fixDeadCodeElimination() void {
std.mem.doNotOptimizeAway(&napi_add_async_cleanup_hook);
std.mem.doNotOptimizeAway(&napi_remove_async_cleanup_hook);
std.mem.doNotOptimizeAway(&napi_add_finalizer);
std.mem.doNotOptimizeAway(&napi_create_external);
std.mem.doNotOptimizeAway(&napi_get_value_external);

std.mem.doNotOptimizeAway(&@import("../bun.js/node/buffer.zig").BufferVectorized.fill);
}
Expand Down Expand Up @@ -1600,5 +1602,7 @@ comptime {
_ = napi_remove_async_cleanup_hook;
_ = @import("../bun.js/node/buffer.zig").BufferVectorized.fill;
_ = napi_add_finalizer;
_ = napi_create_external;
_ = napi_get_value_external;
}
}
4 changes: 4 additions & 0 deletions src/options.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1402,6 +1402,10 @@ pub const BundleOptions = struct {
// If we're not doing SSR, we want all the import paths to be absolute
opts.import_path_format = if (opts.import_path_format == .absolute_url) .absolute_url else .absolute_path;
opts.env.behavior = .load_all;
if (transform.extension_order.len == 0) {
// we must also support require'ing .node files
opts.extension_order = Defaults.ExtensionOrder ++ &[_][]const u8{".node"};
}
},
else => {},
}
Expand Down
2 changes: 2 additions & 0 deletions src/symbols.dyn
Original file line number Diff line number Diff line change
Expand Up @@ -126,4 +126,6 @@
_napi_unwrap;
_napi_wrap;
_napi_remove_wrap;
_napi_create_external;
_napi_get_value_external;
};
2 changes: 2 additions & 0 deletions src/symbols.txt
Original file line number Diff line number Diff line change
Expand Up @@ -125,3 +125,5 @@ _napi_unref_threadsafe_function
_napi_unwrap
_napi_wrap
_napi_remove_wrap
_napi_create_external
_napi_get_value_external
3 changes: 3 additions & 0 deletions test/bun.js/napi-test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#include "../../src/napi/node_api.h"

void
Empty file added test/bun.js/napi.test.ts
Empty file.
Binary file not shown.
Loading

0 comments on commit dddbce8

Please sign in to comment.