mirror of
https://github.com/oven-sh/bun
synced 2026-02-15 13:22:07 +00:00
Introduce SinkDestructor so that we can tack on an extra finalizer
This commit is contained in:
@@ -1489,6 +1489,40 @@ const AutoFlusher = struct {
|
||||
}
|
||||
};
|
||||
|
||||
pub const SinkDestructor = struct {
|
||||
const Detached = opaque {};
|
||||
const Subprocess = JSC.API.Bun.Subprocess;
|
||||
pub const Ptr = bun.TaggedPointerUnion(.{
|
||||
Detached,
|
||||
Subprocess,
|
||||
});
|
||||
|
||||
pub export fn Bun__onSinkDestroyed(
|
||||
ptr_value: ?*anyopaque,
|
||||
sink_ptr: ?*anyopaque,
|
||||
) callconv(.C) void {
|
||||
_ = sink_ptr; // autofix
|
||||
const ptr = Ptr.from(ptr_value);
|
||||
|
||||
if (ptr.isNull()) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (ptr.tag()) {
|
||||
.Detached => {
|
||||
return;
|
||||
},
|
||||
.Subprocess => {
|
||||
const subprocess = ptr.as(Subprocess);
|
||||
subprocess.onStdinDestroyed();
|
||||
},
|
||||
else => {
|
||||
Output.debugWarn("Unknown sink type", .{});
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
pub fn NewJSSink(comptime SinkType: type, comptime name_: []const u8) type {
|
||||
return struct {
|
||||
sink: SinkType,
|
||||
|
||||
@@ -64,7 +64,7 @@ function header() {
|
||||
class ${className} final : public JSC::JSDestructibleObject {
|
||||
public:
|
||||
using Base = JSC::JSDestructibleObject;
|
||||
static ${className}* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* sinkPtr);
|
||||
static ${className}* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* sinkPtr, uintptr_t destructor = 0);
|
||||
static constexpr SinkID Sink = SinkID::${name};
|
||||
|
||||
DECLARE_EXPORT_INFO;
|
||||
@@ -105,11 +105,14 @@ function header() {
|
||||
|
||||
void* m_sinkPtr;
|
||||
int m_refCount { 1 };
|
||||
|
||||
uintptr_t m_onDestroy { 0 };
|
||||
|
||||
${className}(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr)
|
||||
${className}(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr, uintptr_t onDestroy)
|
||||
: Base(vm, structure)
|
||||
{
|
||||
m_sinkPtr = sinkPtr;
|
||||
m_onDestroy = onDestroy;
|
||||
}
|
||||
|
||||
void finishCreation(JSC::VM&);
|
||||
@@ -120,7 +123,7 @@ function header() {
|
||||
class ${controller} final : public JSC::JSDestructibleObject {
|
||||
public:
|
||||
using Base = JSC::JSDestructibleObject;
|
||||
static ${controller}* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* sinkPtr);
|
||||
static ${controller}* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* sinkPtr, uintptr_t onDestroy);
|
||||
static constexpr SinkID Sink = SinkID::${name};
|
||||
|
||||
DECLARE_EXPORT_INFO;
|
||||
@@ -158,11 +161,14 @@ function header() {
|
||||
mutable WriteBarrier<JSC::Unknown> m_onPull;
|
||||
mutable WriteBarrier<JSC::Unknown> m_onClose;
|
||||
mutable JSC::Weak<JSObject> m_weakReadableStream;
|
||||
|
||||
uintptr_t m_onDestroy { 0 };
|
||||
|
||||
${controller}(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr)
|
||||
${controller}(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr, uintptr_t onDestroy)
|
||||
: Base(vm, structure)
|
||||
{
|
||||
m_sinkPtr = sinkPtr;
|
||||
m_onDestroy = onDestroy;
|
||||
}
|
||||
|
||||
void finishCreation(JSC::VM&);
|
||||
@@ -267,7 +273,7 @@ async function implementation() {
|
||||
#include <JavaScriptCore/Weak.h>
|
||||
#include <JavaScriptCore/WeakInlines.h>
|
||||
|
||||
|
||||
extern "C" void Bun__onSinkDestroyed(uintptr_t destructor, void* sinkPtr);
|
||||
|
||||
namespace WebCore {
|
||||
using namespace JSC;
|
||||
@@ -403,7 +409,6 @@ JSC_DEFINE_CUSTOM_GETTER(function${name}__getter, (JSC::JSGlobalObject * lexical
|
||||
return JSC::JSValue::encode(globalObject->${name}());
|
||||
}
|
||||
|
||||
|
||||
JSC_DECLARE_HOST_FUNCTION(${controller}__close);
|
||||
JSC_DEFINE_HOST_FUNCTION(${controller}__close, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame *callFrame))
|
||||
{
|
||||
@@ -562,6 +567,10 @@ const ClassInfo ${controller}::s_info = { "${controllerName}"_s, &Base::s_info,
|
||||
|
||||
${className}::~${className}()
|
||||
{
|
||||
if (m_onDestroy) {
|
||||
Bun__onSinkDestroyed(m_onDestroy, m_sinkPtr);
|
||||
}
|
||||
|
||||
if (m_sinkPtr) {
|
||||
${name}__finalize(m_sinkPtr);
|
||||
}
|
||||
@@ -570,6 +579,10 @@ ${className}::~${className}()
|
||||
|
||||
${controller}::~${controller}()
|
||||
{
|
||||
if (m_onDestroy) {
|
||||
Bun__onSinkDestroyed(m_onDestroy, m_sinkPtr);
|
||||
}
|
||||
|
||||
if (m_sinkPtr) {
|
||||
${name}__finalize(m_sinkPtr);
|
||||
}
|
||||
@@ -586,6 +599,12 @@ JSObject* JS${controllerName}::createPrototype(VM& vm, JSDOMGlobalObject& global
|
||||
}
|
||||
|
||||
void JS${controllerName}::detach() {
|
||||
if (m_onDestroy) {
|
||||
auto destroy = m_onDestroy;
|
||||
m_onDestroy = 0;
|
||||
Bun__onSinkDestroyed(destroy, m_sinkPtr);
|
||||
}
|
||||
|
||||
m_sinkPtr = nullptr;
|
||||
m_onPull.clear();
|
||||
|
||||
@@ -617,16 +636,16 @@ ${constructor}* ${constructor}::create(JSC::VM& vm, JSC::JSGlobalObject* globalO
|
||||
return ptr;
|
||||
}
|
||||
|
||||
${className}* ${className}::create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* sinkPtr)
|
||||
${className}* ${className}::create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* sinkPtr, uintptr_t onDestroy)
|
||||
{
|
||||
${className}* ptr = new (NotNull, JSC::allocateCell<${className}>(vm)) ${className}(vm, structure, sinkPtr);
|
||||
${className}* ptr = new (NotNull, JSC::allocateCell<${className}>(vm)) ${className}(vm, structure, sinkPtr, onDestroy);
|
||||
ptr->finishCreation(vm);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
${controller}* ${controller}::create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* sinkPtr)
|
||||
${controller}* ${controller}::create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* sinkPtr, uintptr_t onDestroy)
|
||||
{
|
||||
${controller}* ptr = new (NotNull, JSC::allocateCell<${controller}>(vm)) ${controller}(vm, structure, sinkPtr);
|
||||
${controller}* ptr = new (NotNull, JSC::allocateCell<${controller}>(vm)) ${controller}(vm, structure, sinkPtr, onDestroy);
|
||||
ptr->finishCreation(vm);
|
||||
return ptr;
|
||||
}
|
||||
@@ -679,6 +698,15 @@ void ${controller}::finishCreation(VM& vm)
|
||||
ASSERT(inherits(info()));
|
||||
}
|
||||
|
||||
extern "C" void ${name}__setDestroyCallback(EncodedJSValue encodedValue, uintptr_t callback)
|
||||
{
|
||||
JSValue value = JSValue::decode(encodedValue);
|
||||
if (auto* sink = JSC::jsDynamicCast<WebCore::${className}*>(value)) {
|
||||
sink->m_onDestroy = callback;
|
||||
} else if (auto* controller = JSC::jsDynamicCast<WebCore::${controller}*>(value)) {
|
||||
controller->m_onDestroy = callback;
|
||||
}
|
||||
}
|
||||
|
||||
void ${className}::analyzeHeap(JSCell* cell, HeapAnalyzer& analyzer)
|
||||
{
|
||||
@@ -817,12 +845,12 @@ default:
|
||||
const { className, controller, prototypeName, controllerPrototypeName, constructor } = names(name);
|
||||
|
||||
templ += `
|
||||
extern "C" JSC__JSValue ${name}__createObject(JSC__JSGlobalObject* arg0, void* sinkPtr)
|
||||
extern "C" JSC__JSValue ${name}__createObject(JSC__JSGlobalObject* arg0, void* sinkPtr, uintptr_t destructor)
|
||||
{
|
||||
auto& vm = arg0->vm();
|
||||
Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(arg0);
|
||||
JSC::Structure* structure = globalObject->${name}Structure();
|
||||
return JSC::JSValue::encode(WebCore::JS${name}::create(vm, globalObject, structure, sinkPtr));
|
||||
return JSC::JSValue::encode(WebCore::JS${name}::create(vm, globalObject, structure, sinkPtr, destructor));
|
||||
}
|
||||
|
||||
extern "C" void* ${name}__fromJS(JSC__JSGlobalObject* arg0, JSC__JSValue JSValue1)
|
||||
@@ -857,7 +885,7 @@ extern "C" JSC__JSValue ${name}__assignToStream(JSC__JSGlobalObject* arg0, JSC__
|
||||
Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(arg0);
|
||||
|
||||
JSC::Structure* structure = WebCore::getDOMStructure<WebCore::${controller}>(vm, *globalObject);
|
||||
WebCore::${controller} *controller = WebCore::${controller}::create(vm, globalObject, structure, sinkPtr);
|
||||
WebCore::${controller} *controller = WebCore::${controller}::create(vm, globalObject, structure, sinkPtr, 0);
|
||||
*controllerValue = reinterpret_cast<void*>(JSC::JSValue::encode(controller));
|
||||
return globalObject->assignToStream(JSC::JSValue::decode(stream), controller);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user