aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
m---------src/bun.js/WebKit0
-rw-r--r--src/bun.js/bindings/BunClientData.cpp8
-rw-r--r--src/bun.js/bindings/BunClientData.h6
-rw-r--r--src/bun.js/bindings/JSCTaskScheduler.cpp101
-rw-r--r--src/bun.js/bindings/JSCTaskScheduler.h25
-rw-r--r--src/bun.js/bindings/ZigGlobalObject.cpp2
-rw-r--r--src/bun.js/bindings/bindings.cpp6
-rw-r--r--src/bun.js/bindings/bindings.zig10
-rw-r--r--src/bun.js/bindings/headers.h1
-rw-r--r--src/bun.js/bindings/headers.zig1
-rw-r--r--src/bun.js/event_loop.zig52
-rw-r--r--src/bun.js/web_worker.zig4
-rw-r--r--src/bun.js/webcore/response.zig2
-rw-r--r--src/bun.js/webcore/streams.zig2
-rw-r--r--src/cli/test_command.zig1
-rw-r--r--src/deps/uws.zig12
-rw-r--r--src/js/bun/wasi-runner.js15
-rw-r--r--src/js/out/modules/bun/wasi-runner.js11
-rw-r--r--src/napi/napi.zig6
-rw-r--r--src/tagged_pointer.zig4
20 files changed, 227 insertions, 42 deletions
diff --git a/src/bun.js/WebKit b/src/bun.js/WebKit
-Subproject 5e65b9ae7756b6353cfeac5206f7076b00e9ecf
+Subproject ecf1b9c4bc2247020add7b14a732bb0085f25d5
diff --git a/src/bun.js/bindings/BunClientData.cpp b/src/bun.js/bindings/BunClientData.cpp
index 2cdd8b25a..9af17d638 100644
--- a/src/bun.js/bindings/BunClientData.cpp
+++ b/src/bun.js/bindings/BunClientData.cpp
@@ -21,6 +21,7 @@
#include "JavaScriptCore/JSCInlines.h"
#include "JSDOMWrapper.h"
+#include <JavaScriptCore/DeferredWorkTimer.h>
namespace WebCore {
using namespace JSC;
@@ -69,9 +70,14 @@ JSVMClientData::~JSVMClientData()
ASSERT(m_normalWorld->hasOneRef());
m_normalWorld = nullptr;
}
-void JSVMClientData::create(VM* vm)
+void JSVMClientData::create(VM* vm, void* bunVM)
{
JSVMClientData* clientData = new JSVMClientData(*vm);
+ clientData->bunVM = bunVM;
+ vm->deferredWorkTimer->onAddPendingWork = Bun::JSCTaskScheduler::onAddPendingWork;
+ vm->deferredWorkTimer->onScheduleWorkSoon = Bun::JSCTaskScheduler::onScheduleWorkSoon;
+ vm->deferredWorkTimer->onCancelPendingWork = Bun::JSCTaskScheduler::onCancelPendingWork;
+
vm->clientData = clientData; // ~VM deletes this pointer.
clientData->m_normalWorld = DOMWrapperWorld::create(*vm, DOMWrapperWorld::Type::Normal);
diff --git a/src/bun.js/bindings/BunClientData.h b/src/bun.js/bindings/BunClientData.h
index e3c2d3748..0bee575df 100644
--- a/src/bun.js/bindings/BunClientData.h
+++ b/src/bun.js/bindings/BunClientData.h
@@ -24,6 +24,7 @@ class DOMWrapperWorld;
#include "JavaScriptCore/IsoSubspacePerVM.h"
#include "wtf/StdLibExtras.h"
#include "WebCoreJSBuiltins.h"
+#include "JSCTaskScheduler.h"
namespace Zig {
}
@@ -80,7 +81,7 @@ public:
virtual ~JSVMClientData();
- static void create(JSC::VM*);
+ static void create(JSC::VM*, void*);
JSHeapData& heapData() { return *m_heapData; }
BunBuiltinNames& builtinNames() { return m_builtinNames; }
@@ -107,6 +108,9 @@ public:
func(*space);
}
+ void* bunVM;
+ Bun::JSCTaskScheduler deferredWorkTimer;
+
private:
BunBuiltinNames m_builtinNames;
JSBuiltinFunctions m_builtinFunctions;
diff --git a/src/bun.js/bindings/JSCTaskScheduler.cpp b/src/bun.js/bindings/JSCTaskScheduler.cpp
new file mode 100644
index 000000000..436be4c0a
--- /dev/null
+++ b/src/bun.js/bindings/JSCTaskScheduler.cpp
@@ -0,0 +1,101 @@
+#include "config.h"
+#include <JavaScriptCore/VM.h>
+#include "JSCTaskScheduler.h"
+#include "BunClientData.h"
+
+using Ticket = JSC::DeferredWorkTimer::Ticket;
+using Task = JSC::DeferredWorkTimer::Task;
+using TicketData = JSC::DeferredWorkTimer::TicketData;
+
+namespace Bun {
+using namespace JSC;
+
+extern "C" void Bun__queueJSCDeferredWorkTaskConcurrently(void* bunVM, void* task);
+extern "C" void Bun__eventLoop__incrementRefConcurrently(void* bunVM, int delta);
+
+class JSCDeferredWorkTask {
+public:
+ JSCDeferredWorkTask(Ticket ticket, Task&& task)
+ : ticket(ticket)
+ , task(WTFMove(task))
+ {
+ }
+
+ Ticket ticket;
+ Task task;
+
+ WTF_MAKE_FAST_ALLOCATED;
+};
+
+static JSC::VM& getVM(Ticket ticket)
+{
+ return ticket->scriptExecutionOwner.get()->vm();
+}
+
+void JSCTaskScheduler::onAddPendingWork(std::unique_ptr<TicketData> ticket, JSC::DeferredWorkTimer::WorkKind kind)
+{
+ JSC::VM& vm = getVM(ticket.get());
+ auto clientData = WebCore::clientData(vm);
+ auto& scheduler = clientData->deferredWorkTimer;
+ LockHolder holder { scheduler.m_lock };
+ if (kind != DeferredWorkTimer::WorkKind::Other) {
+
+ Bun__eventLoop__incrementRefConcurrently(clientData->bunVM, 1);
+ scheduler.m_pendingTicketsKeepingEventLoopAlive.add(WTFMove(ticket));
+ } else {
+ scheduler.m_pendingTicketsOther.add(WTFMove(ticket));
+ }
+}
+void JSCTaskScheduler::onScheduleWorkSoon(Ticket ticket, Task&& task)
+{
+ auto* job = new JSCDeferredWorkTask(ticket, WTFMove(task));
+ Bun__queueJSCDeferredWorkTaskConcurrently(WebCore::clientData(getVM(ticket))->bunVM, job);
+}
+
+void JSCTaskScheduler::onCancelPendingWork(Ticket ticket)
+{
+ auto& scheduler = WebCore::clientData(getVM(ticket))->deferredWorkTimer;
+
+ LockHolder holder { scheduler.m_lock };
+ bool isKeepingEventLoopAlive = scheduler.m_pendingTicketsKeepingEventLoopAlive.removeIf([ticket](const auto& pendingTicket) {
+ return pendingTicket.get() == ticket;
+ });
+
+ if (isKeepingEventLoopAlive) {
+ holder.unlockEarly();
+ JSC::VM& vm = getVM(ticket);
+ Bun__eventLoop__incrementRefConcurrently(WebCore::clientData(vm)->bunVM, -1);
+ } else {
+ scheduler.m_pendingTicketsOther.removeIf([ticket](const auto& pendingTicket) {
+ return pendingTicket.get() == ticket;
+ });
+ }
+}
+
+static void runPendingWork(void* bunVM, Bun::JSCTaskScheduler& scheduler, JSCDeferredWorkTask* job)
+{
+ LockHolder holder { scheduler.m_lock };
+ auto pendingTicket = scheduler.m_pendingTicketsKeepingEventLoopAlive.take(job->ticket);
+ if (!pendingTicket) {
+ pendingTicket = scheduler.m_pendingTicketsOther.take(job->ticket);
+ } else {
+ Bun__eventLoop__incrementRefConcurrently(bunVM, -1);
+ }
+ holder.unlockEarly();
+
+ if (pendingTicket && !pendingTicket->isCancelled()) {
+ job->task(job->ticket);
+ }
+
+ delete job;
+}
+
+extern "C" void Bun__runDeferredWork(Bun::JSCDeferredWorkTask* job)
+{
+ auto& vm = getVM(job->ticket);
+ auto clientData = WebCore::clientData(vm);
+
+ runPendingWork(clientData->bunVM, clientData->deferredWorkTimer, job);
+}
+
+}
diff --git a/src/bun.js/bindings/JSCTaskScheduler.h b/src/bun.js/bindings/JSCTaskScheduler.h
new file mode 100644
index 000000000..3257eb9c8
--- /dev/null
+++ b/src/bun.js/bindings/JSCTaskScheduler.h
@@ -0,0 +1,25 @@
+#pragma once
+
+#include <JavaScriptCore/DeferredWorkTimer.h>
+
+namespace Bun {
+
+class JSCTaskScheduler {
+public:
+ JSCTaskScheduler()
+ : m_pendingTicketsKeepingEventLoopAlive()
+ , m_pendingTicketsOther()
+ {
+ }
+
+ static void onAddPendingWork(std::unique_ptr<JSC::DeferredWorkTimer::TicketData> ticket, JSC::DeferredWorkTimer::WorkKind kind);
+ static void onScheduleWorkSoon(JSC::DeferredWorkTimer::Ticket ticket, JSC::DeferredWorkTimer::Task&& task);
+ static void onCancelPendingWork(JSC::DeferredWorkTimer::Ticket ticket);
+
+public:
+ Lock m_lock;
+ HashSet<std::unique_ptr<JSC::DeferredWorkTimer::TicketData>> m_pendingTicketsKeepingEventLoopAlive;
+ HashSet<std::unique_ptr<JSC::DeferredWorkTimer::TicketData>> m_pendingTicketsOther;
+};
+
+} \ No newline at end of file
diff --git a/src/bun.js/bindings/ZigGlobalObject.cpp b/src/bun.js/bindings/ZigGlobalObject.cpp
index f267fcbb7..52f633f3d 100644
--- a/src/bun.js/bindings/ZigGlobalObject.cpp
+++ b/src/bun.js/bindings/ZigGlobalObject.cpp
@@ -431,7 +431,7 @@ extern "C" JSC__JSGlobalObject* Zig__GlobalObject__create(JSClassRef* globalObje
// This must happen before JSVMClientData::create
vm.heap.acquireAccess();
- WebCore::JSVMClientData::create(&vm);
+ WebCore::JSVMClientData::create(&vm, Bun__getVM());
JSC::JSLockHolder locker(vm);
Zig::GlobalObject* globalObject;
diff --git a/src/bun.js/bindings/bindings.cpp b/src/bun.js/bindings/bindings.cpp
index 55f718207..9fb0c18d5 100644
--- a/src/bun.js/bindings/bindings.cpp
+++ b/src/bun.js/bindings/bindings.cpp
@@ -9,7 +9,6 @@
#include "JavaScriptCore/BytecodeIndex.h"
#include "JavaScriptCore/CodeBlock.h"
#include "JavaScriptCore/Completion.h"
-#include "JavaScriptCore/DeferredWorkTimer.h"
#include "JavaScriptCore/ErrorInstance.h"
#include "JavaScriptCore/ExceptionHelpers.h"
#include "JavaScriptCore/ExceptionScope.h"
@@ -3893,11 +3892,6 @@ void JSC__VM__deleteAllCode(JSC__VM* arg1, JSC__JSGlobalObject* globalObject)
arg1->heap.reportAbandonedObjectGraph();
}
-void JSC__VM__doWork(JSC__VM* vm)
-{
- vm->deferredWorkTimer->doWork(*vm);
-}
-
void JSC__VM__deinit(JSC__VM* arg1, JSC__JSGlobalObject* globalObject) {}
void JSC__VM__drainMicrotasks(JSC__VM* arg0) { arg0->drainMicrotasks(); }
diff --git a/src/bun.js/bindings/bindings.zig b/src/bun.js/bindings/bindings.zig
index edd1be1a9..924eb27a1 100644
--- a/src/bun.js/bindings/bindings.zig
+++ b/src/bun.js/bindings/bindings.zig
@@ -5083,14 +5083,6 @@ pub const VM = extern struct {
});
}
- pub fn doWork(
- vm: *VM,
- ) void {
- return cppFn("doWork", .{
- vm,
- });
- }
-
pub fn externalMemorySize(vm: *VM) usize {
return cppFn("externalMemorySize", .{vm});
}
@@ -5101,7 +5093,7 @@ pub const VM = extern struct {
return cppFn("blockBytesAllocated", .{vm});
}
- pub const Extern = [_][]const u8{ "collectAsync", "externalMemorySize", "blockBytesAllocated", "heapSize", "releaseWeakRefs", "throwError", "doWork", "deferGC", "holdAPILock", "runGC", "generateHeapSnapshot", "isJITEnabled", "deleteAllCode", "create", "deinit", "setExecutionForbidden", "executionForbidden", "isEntered", "throwError", "drainMicrotasks", "whenIdle", "shrinkFootprint", "setExecutionTimeLimit", "clearExecutionTimeLimit" };
+ pub const Extern = [_][]const u8{ "collectAsync", "externalMemorySize", "blockBytesAllocated", "heapSize", "releaseWeakRefs", "throwError", "deferGC", "holdAPILock", "runGC", "generateHeapSnapshot", "isJITEnabled", "deleteAllCode", "create", "deinit", "setExecutionForbidden", "executionForbidden", "isEntered", "throwError", "drainMicrotasks", "whenIdle", "shrinkFootprint", "setExecutionTimeLimit", "clearExecutionTimeLimit" };
};
pub const ThrowScope = extern struct {
diff --git a/src/bun.js/bindings/headers.h b/src/bun.js/bindings/headers.h
index 8cce986dc..05c708a48 100644
--- a/src/bun.js/bindings/headers.h
+++ b/src/bun.js/bindings/headers.h
@@ -419,7 +419,6 @@ CPP_DECL JSC__VM* JSC__VM__create(unsigned char HeapType0);
CPP_DECL void JSC__VM__deferGC(JSC__VM* arg0, void* arg1, void(* ArgFn2)(void* arg0)) __attribute__((nonnull (2)));
CPP_DECL void JSC__VM__deinit(JSC__VM* arg0, JSC__JSGlobalObject* arg1);
CPP_DECL void JSC__VM__deleteAllCode(JSC__VM* arg0, JSC__JSGlobalObject* arg1);
-CPP_DECL void JSC__VM__doWork(JSC__VM* arg0);
CPP_DECL void JSC__VM__drainMicrotasks(JSC__VM* arg0);
CPP_DECL bool JSC__VM__executionForbidden(JSC__VM* arg0);
CPP_DECL size_t JSC__VM__externalMemorySize(JSC__VM* arg0);
diff --git a/src/bun.js/bindings/headers.zig b/src/bun.js/bindings/headers.zig
index e87e59946..fbca33a30 100644
--- a/src/bun.js/bindings/headers.zig
+++ b/src/bun.js/bindings/headers.zig
@@ -313,7 +313,6 @@ pub extern fn JSC__VM__create(HeapType0: u8) *bindings.VM;
pub extern fn JSC__VM__deferGC(arg0: *bindings.VM, arg1: ?*anyopaque, ArgFn2: ?*const fn (?*anyopaque) callconv(.C) void) void;
pub extern fn JSC__VM__deinit(arg0: *bindings.VM, arg1: *bindings.JSGlobalObject) void;
pub extern fn JSC__VM__deleteAllCode(arg0: *bindings.VM, arg1: *bindings.JSGlobalObject) void;
-pub extern fn JSC__VM__doWork(arg0: *bindings.VM) void;
pub extern fn JSC__VM__drainMicrotasks(arg0: *bindings.VM) void;
pub extern fn JSC__VM__executionForbidden(arg0: *bindings.VM) bool;
pub extern fn JSC__VM__externalMemorySize(arg0: *bindings.VM) usize;
diff --git a/src/bun.js/event_loop.zig b/src/bun.js/event_loop.zig
index 2dbe88d47..6688eaeea 100644
--- a/src/bun.js/event_loop.zig
+++ b/src/bun.js/event_loop.zig
@@ -73,7 +73,7 @@ pub fn ConcurrentPromiseTask(comptime Context: type) type {
}
pub fn onFinish(this: *This) void {
- this.event_loop.enqueueTaskConcurrent(this.concurrent_task.from(this));
+ this.event_loop.enqueueTaskConcurrent(this.concurrent_task.from(this, .manual_deinit));
}
pub fn deinit(this: *This) void {
@@ -136,7 +136,7 @@ pub fn WorkTask(comptime Context: type, comptime async_io: bool) type {
}
pub fn onFinish(this: *This) void {
- this.event_loop.enqueueTaskConcurrent(this.concurrent_task.from(this));
+ this.event_loop.enqueueTaskConcurrent(this.concurrent_task.from(this, .manual_deinit));
}
pub fn deinit(this: *This) void {
@@ -221,6 +221,35 @@ pub const CppTask = opaque {
Bun__performTask(global, this);
}
};
+pub const JSCScheduler = struct {
+ pub const JSCDeferredWorkTask = opaque {
+ extern fn Bun__runDeferredWork(task: *JSCScheduler.JSCDeferredWorkTask) void;
+ pub const run = Bun__runDeferredWork;
+ };
+
+ export fn Bun__eventLoop__incrementRefConcurrently(jsc_vm: *VirtualMachine, delta: c_int) void {
+ JSC.markBinding(@src());
+
+ if (delta > 0) {
+ jsc_vm.uws_event_loop.?.refConcurrently();
+ } else {
+ jsc_vm.uws_event_loop.?.unrefConcurrently();
+ }
+ }
+
+ export fn Bun__queueJSCDeferredWorkTaskConcurrently(jsc_vm: *VirtualMachine, task: *JSCScheduler.JSCDeferredWorkTask) void {
+ JSC.markBinding(@src());
+ var loop = jsc_vm.eventLoop();
+ var concurrent_task = bun.default_allocator.create(ConcurrentTask) catch @panic("out of memory!");
+ loop.enqueueTaskConcurrent(concurrent_task.from(task, .auto_deinit));
+ }
+
+ comptime {
+ _ = Bun__eventLoop__incrementRefConcurrently;
+ _ = Bun__queueJSCDeferredWorkTaskConcurrently;
+ }
+};
+
const ThreadSafeFunction = JSC.napi.ThreadSafeFunction;
const MicrotaskForDefaultGlobalObject = JSC.MicrotaskForDefaultGlobalObject;
const HotReloadTask = JSC.HotReloader.HotReloadTask;
@@ -228,6 +257,7 @@ const FSWatchTask = JSC.Node.FSWatcher.FSWatchTask;
const PollPendingModulesTask = JSC.ModuleLoader.AsyncModule.Queue;
// const PromiseTask = JSInternalPromise.Completion.PromiseTask;
const GetAddrInfoRequestTask = JSC.DNS.GetAddrInfoRequest.Task;
+const JSCDeferredWorkTask = JSCScheduler.JSCDeferredWorkTask;
pub const Task = TaggedPointerUnion(.{
FetchTasklet,
Microtask,
@@ -244,6 +274,8 @@ pub const Task = TaggedPointerUnion(.{
PollPendingModulesTask,
GetAddrInfoRequestTask,
FSWatchTask,
+ JSCDeferredWorkTask,
+
// PromiseTask,
// TimeoutTasklet,
});
@@ -255,10 +287,15 @@ pub const ConcurrentTask = struct {
pub const Queue = UnboundedQueue(ConcurrentTask, .next);
- pub fn from(this: *ConcurrentTask, of: anytype) *ConcurrentTask {
+ pub const AutoDeinit = enum {
+ manual_deinit,
+ auto_deinit,
+ };
+ pub fn from(this: *ConcurrentTask, of: anytype, auto_deinit: AutoDeinit) *ConcurrentTask {
this.* = .{
.task = Task.init(of),
.next = null,
+ .auto_delete = auto_deinit == .auto_deinit,
};
return this;
}
@@ -457,6 +494,11 @@ pub const EventLoop = struct {
transform_task.*.runFromJS();
transform_task.deinit();
},
+ @field(Task.Tag, bun.meta.typeBaseName(@typeName(JSCDeferredWorkTask))) => {
+ var jsc_task: *JSCDeferredWorkTask = task.get(JSCDeferredWorkTask).?;
+ JSC.markBinding(@src());
+ jsc_task.run();
+ },
@field(Task.Tag, @typeName(WriteFileTask)) => {
var transform_task: *WriteFileTask = task.get(WriteFileTask).?;
transform_task.*.runFromJS();
@@ -627,10 +669,6 @@ pub const EventLoop = struct {
break;
}
- // TODO: unify the event loops
- // This needs a hook into JSC to schedule timers
- this.global.vm().doWork();
-
while (this.tickWithCount() > 0) {
this.tickConcurrent();
}
diff --git a/src/bun.js/web_worker.zig b/src/bun.js/web_worker.zig
index 504b0adeb..130e99be1 100644
--- a/src/bun.js/web_worker.zig
+++ b/src/bun.js/web_worker.zig
@@ -141,7 +141,7 @@ pub const WebWorker = struct {
var any_task = bun.default_allocator.create(JSC.AnyTask) catch @panic("OOM");
any_task.* = AnyTask.init(this);
var concurrent_task = bun.default_allocator.create(JSC.ConcurrentTask) catch @panic("OOM");
- this.parent.eventLoop().enqueueTaskConcurrent(concurrent_task.from(any_task));
+ this.parent.eventLoop().enqueueTaskConcurrent(concurrent_task.from(any_task, .auto_deinit));
}
pub fn startWithErrorHandling(
@@ -413,7 +413,7 @@ pub const WebWorker = struct {
var concurrent_task = bun.default_allocator.create(JSC.ConcurrentTask) catch @panic("OOM");
var task = bun.default_allocator.create(JSC.AnyTask) catch @panic("OOM");
task.* = JSC.AnyTask.New(WebWorker, onTerminate).init(this);
- vm.eventLoop().enqueueTaskConcurrent(concurrent_task.from(task));
+ vm.eventLoop().enqueueTaskConcurrent(concurrent_task.from(task, .auto_deinit));
return true;
}
};
diff --git a/src/bun.js/webcore/response.zig b/src/bun.js/webcore/response.zig
index ab2a6010d..a70a4f0ee 100644
--- a/src/bun.js/webcore/response.zig
+++ b/src/bun.js/webcore/response.zig
@@ -979,7 +979,7 @@ pub const Fetch = struct {
pub fn callback(task: *FetchTasklet, result: HTTPClient.HTTPClientResult) void {
task.response_buffer = result.body.?.*;
task.result = result;
- task.javascript_vm.eventLoop().enqueueTaskConcurrent(task.concurrent_task.from(task));
+ task.javascript_vm.eventLoop().enqueueTaskConcurrent(task.concurrent_task.from(task, .manual_deinit));
}
};
diff --git a/src/bun.js/webcore/streams.zig b/src/bun.js/webcore/streams.zig
index 03b1dcdc9..5dc4ea830 100644
--- a/src/bun.js/webcore/streams.zig
+++ b/src/bun.js/webcore/streams.zig
@@ -4168,7 +4168,7 @@ pub const File = struct {
pub fn scheduleMainThreadTask(this: *File) void {
this.concurrent.main_thread_task.ctx = this;
- this.loop.enqueueTaskConcurrent(this.concurrent.concurrent_task.from(&this.concurrent.main_thread_task));
+ this.loop.enqueueTaskConcurrent(this.concurrent.concurrent_task.from(&this.concurrent.main_thread_task, .manual_deinit));
}
fn runAsync(this: *File) void {
diff --git a/src/cli/test_command.zig b/src/cli/test_command.zig
index f53c8121c..14eca012e 100644
--- a/src/cli/test_command.zig
+++ b/src/cli/test_command.zig
@@ -806,7 +806,6 @@ pub const TestCommand = struct {
vm.global.vm().drainMicrotasks();
vm.global.handleRejectedPromises();
}
- vm.global.vm().doWork();
}
const file_end = reporter.jest.files.len;
diff --git a/src/deps/uws.zig b/src/deps/uws.zig
index 6e9d43e5f..15e6eaa68 100644
--- a/src/deps/uws.zig
+++ b/src/deps/uws.zig
@@ -760,6 +760,18 @@ pub const Loop = extern struct {
this.num_polls += 1;
this.active += 1;
}
+ pub fn refConcurrently(this: *Loop) void {
+ log("ref", .{});
+ _ = @atomicRmw(@TypeOf(this.num_polls), &this.num_polls, .Add, 1, .Monotonic);
+ _ = @atomicRmw(@TypeOf(this.active), &this.active, .Add, 1, .Monotonic);
+ }
+
+ pub fn unrefConcurrently(this: *Loop) void {
+ log("unref", .{});
+ _ = @atomicRmw(@TypeOf(this.num_polls), &this.num_polls, .Sub, 1, .Monotonic);
+ _ = @atomicRmw(@TypeOf(this.active), &this.active, .Sub, 1, .Monotonic);
+ }
+
pub fn unref(this: *Loop) void {
log("unref", .{});
this.num_polls -= 1;
diff --git a/src/js/bun/wasi-runner.js b/src/js/bun/wasi-runner.js
index a292c6380..9f7b469e1 100644
--- a/src/js/bun/wasi-runner.js
+++ b/src/js/bun/wasi-runner.js
@@ -11,7 +11,12 @@ if (!filePath) {
// The module specifier is the resolved path to the wasm file
-var { WASM_CWD = process.cwd(), WASM_ROOT_DIR = "/", WASM_ENV_STR = undefined, WASM_USE_ASYNC_INIT = "" } = process.env;
+var {
+ WASM_CWD = process.cwd(),
+ WASM_ROOT_DIR = "/",
+ WASM_ENV_STR = undefined,
+ WASM_USE_ASYNC_INIT = "1",
+} = process.env;
var env = process.env;
if (WASM_ENV_STR?.length) {
@@ -34,10 +39,12 @@ if (!source) {
source = fs.readFileSync(file);
}
-const wasm = new WebAssembly.Module(source);
-const instance = !WASM_USE_ASYNC_INIT
+const wasm = await WebAssembly.compile(source);
+
+const instance = !Number(WASM_USE_ASYNC_INIT)
? new WebAssembly.Instance(wasm, wasi.getImports(wasm))
: await WebAssembly.instantiate(wasm, wasi.getImports(wasm));
+
wasi.start(instance);
-process.exit(0);
+process.reallyExit(0);
diff --git a/src/js/out/modules/bun/wasi-runner.js b/src/js/out/modules/bun/wasi-runner.js
index 9dfd27b23..47c5ade3c 100644
--- a/src/js/out/modules/bun/wasi-runner.js
+++ b/src/js/out/modules/bun/wasi-runner.js
@@ -1,7 +1,12 @@
var filePath = process.argv.at(1);
if (!filePath)
throw err = new Error("To run a wasm file with Bun, the first argument must be a path to a .wasm file"), err.name = "WasmFileNotFound", err;
-var err, { WASM_CWD = process.cwd(), WASM_ROOT_DIR = "/", WASM_ENV_STR = void 0, WASM_USE_ASYNC_INIT = "" } = process.env, env = process.env;
+var err, {
+ WASM_CWD = process.cwd(),
+ WASM_ROOT_DIR = "/",
+ WASM_ENV_STR = void 0,
+ WASM_USE_ASYNC_INIT = "1"
+} = process.env, env = process.env;
if (WASM_ENV_STR?.length)
env = JSON.parse(WASM_ENV_STR);
var wasi = new WASI({
@@ -16,6 +21,6 @@ if (!source) {
const fs = Bun.fs(), file = import.meta.path;
source = fs.readFileSync(file);
}
-var wasm = new WebAssembly.Module(source), instance = !WASM_USE_ASYNC_INIT ? new WebAssembly.Instance(wasm, wasi.getImports(wasm)) : await WebAssembly.instantiate(wasm, wasi.getImports(wasm));
+var wasm = await WebAssembly.compile(source), instance = !Number(WASM_USE_ASYNC_INIT) ? new WebAssembly.Instance(wasm, wasi.getImports(wasm)) : await WebAssembly.instantiate(wasm, wasi.getImports(wasm));
wasi.start(instance);
-process.exit(0);
+process.reallyExit(0);
diff --git a/src/napi/napi.zig b/src/napi/napi.zig
index bb8f19df2..abe8316ad 100644
--- a/src/napi/napi.zig
+++ b/src/napi/napi.zig
@@ -962,7 +962,7 @@ pub const napi_async_work = struct {
this.execute.?(this.global, this.ctx);
this.status.store(@intFromEnum(Status.completed), .SeqCst);
- this.event_loop.enqueueTaskConcurrent(this.concurrent_task.from(this));
+ this.event_loop.enqueueTaskConcurrent(this.concurrent_task.from(this, .manual_deinit));
}
pub fn schedule(this: *napi_async_work) void {
@@ -1338,7 +1338,7 @@ pub const ThreadSafeFunction = struct {
}
}
- this.event_loop.enqueueTaskConcurrent(this.concurrent_task.from(this));
+ this.event_loop.enqueueTaskConcurrent(this.concurrent_task.from(this, .manual_deinit));
}
pub fn finalize(opaq: *anyopaque) void {
@@ -1387,7 +1387,7 @@ pub const ThreadSafeFunction = struct {
if (this.owning_threads.count() == 0) {
this.finalizer_task = JSC.AnyTask{ .ctx = this, .callback = finalize };
- this.event_loop.enqueueTaskConcurrent(this.concurrent_finalizer_task.from(&this.finalizer_task));
+ this.event_loop.enqueueTaskConcurrent(this.concurrent_finalizer_task.from(&this.finalizer_task, .manual_deinit));
return;
}
}
diff --git a/src/tagged_pointer.zig b/src/tagged_pointer.zig
index 6c2462139..b5555a8b4 100644
--- a/src/tagged_pointer.zig
+++ b/src/tagged_pointer.zig
@@ -159,6 +159,10 @@ pub fn TaggedPointerUnion(comptime Types: anytype) type {
pub inline fn init(_ptr: anytype) This {
const Type = std.meta.Child(@TypeOf(_ptr));
+ return initWithType(Type, _ptr);
+ }
+
+ pub inline fn initWithType(comptime Type: type, _ptr: anytype) This {
const name = comptime typeBaseName(@typeName(Type));
// there will be a compiler error if the passed in type doesn't exist in the enum