aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/bun.js/bindings/ScriptExecutionContext.cpp3
-rw-r--r--src/bun.js/bindings/webcore/JSWorker.cpp8
-rw-r--r--src/bun.js/bindings/webcore/Worker.cpp14
-rw-r--r--src/bun.js/bindings/webcore/Worker.h1
-rw-r--r--src/bun.js/module_loader.zig6
-rw-r--r--src/bun.js/web_worker.zig46
6 files changed, 57 insertions, 21 deletions
diff --git a/src/bun.js/bindings/ScriptExecutionContext.cpp b/src/bun.js/bindings/ScriptExecutionContext.cpp
index f878fd9fb..d93478ed8 100644
--- a/src/bun.js/bindings/ScriptExecutionContext.cpp
+++ b/src/bun.js/bindings/ScriptExecutionContext.cpp
@@ -120,8 +120,7 @@ void ScriptExecutionContext::regenerateIdentifier()
m_identifier = ++lastUniqueIdentifier;
- Locker locker { allScriptExecutionContextsMapLock };
- allScriptExecutionContextsMap().add(m_identifier, this);
+ addToContextsMap();
}
void ScriptExecutionContext::addToContextsMap()
diff --git a/src/bun.js/bindings/webcore/JSWorker.cpp b/src/bun.js/bindings/webcore/JSWorker.cpp
index 68e06a2a0..bcf670d63 100644
--- a/src/bun.js/bindings/webcore/JSWorker.cpp
+++ b/src/bun.js/bindings/webcore/JSWorker.cpp
@@ -162,8 +162,16 @@ template<> EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSWorkerDOMConstructor::const
auto jsValue = toJSNewlyCreated<IDLInterface<Worker>>(*lexicalGlobalObject, *castedThis->globalObject(), throwScope, WTFMove(object));
if constexpr (IsExceptionOr<decltype(object)>)
RETURN_IF_EXCEPTION(throwScope, {});
+
+ auto& impl = jsCast<JSWorker*>(jsValue)->wrapped();
+ if (!impl.updatePtr()) {
+ throwVMError(lexicalGlobalObject, throwScope, "Failed to start Worker thread"_s);
+ return encodedJSValue();
+ }
+
setSubclassStructureIfNeeded<Worker>(lexicalGlobalObject, callFrame, asObject(jsValue));
RETURN_IF_EXCEPTION(throwScope, {});
+
return JSValue::encode(jsValue);
}
JSC_ANNOTATE_HOST_FUNCTION(JSWorkerDOMConstructorConstruct, JSWorkerDOMConstructor::construct);
diff --git a/src/bun.js/bindings/webcore/Worker.cpp b/src/bun.js/bindings/webcore/Worker.cpp
index d92b6e2e5..dfbc0e007 100644
--- a/src/bun.js/bindings/webcore/Worker.cpp
+++ b/src/bun.js/bindings/webcore/Worker.cpp
@@ -105,7 +105,7 @@ Worker::Worker(ScriptExecutionContext& context, WorkerOptions&& options)
auto addResult = allWorkers().add(m_clientIdentifier, this);
ASSERT_UNUSED(addResult, addResult.isNewEntry);
}
-
+extern "C" bool WebWorker__updatePtr(void* worker, Worker* ptr);
extern "C" void* WebWorker__create(
Worker* worker,
void* parent,
@@ -125,6 +125,18 @@ void Worker::setKeepAlive(bool keepAlive)
WebWorker__setRef(impl_, keepAlive);
}
+bool Worker::updatePtr()
+{
+ if (!WebWorker__updatePtr(impl_, this)) {
+ m_wasTerminated = true;
+ m_isClosing = true;
+ m_isOnline = false;
+ return false;
+ }
+
+ return true;
+}
+
ExceptionOr<Ref<Worker>> Worker::create(ScriptExecutionContext& context, const String& urlInit, WorkerOptions&& options)
{
auto worker = adoptRef(*new Worker(context, WTFMove(options)));
diff --git a/src/bun.js/bindings/webcore/Worker.h b/src/bun.js/bindings/webcore/Worker.h
index 99a54e37f..b0b8e0a2b 100644
--- a/src/bun.js/bindings/webcore/Worker.h
+++ b/src/bun.js/bindings/webcore/Worker.h
@@ -70,6 +70,7 @@ public:
void terminate();
bool wasTerminated() const { return m_wasTerminated; }
bool hasPendingActivity() const;
+ bool updatePtr();
String identifier() const { return m_identifier; }
const String& name() const { return m_options.name; }
diff --git a/src/bun.js/module_loader.zig b/src/bun.js/module_loader.zig
index 483ff94cb..6a04540b1 100644
--- a/src/bun.js/module_loader.zig
+++ b/src/bun.js/module_loader.zig
@@ -1697,6 +1697,12 @@ pub const ModuleLoader = struct {
// so it consistently handles bundled imports
// we can't take the shortcut of just directly importing the file, sadly.
.@"bun:main" => {
+ defer {
+ if (jsc_vm.worker) |worker| {
+ worker.queueInitialTask();
+ }
+ }
+
if (comptime disable_transpilying) {
return ResolvedSource{
.allocator = null,
diff --git a/src/bun.js/web_worker.zig b/src/bun.js/web_worker.zig
index df2e63c3a..39ab2c8f1 100644
--- a/src/bun.js/web_worker.zig
+++ b/src/bun.js/web_worker.zig
@@ -19,20 +19,39 @@ pub const WebWorker = struct {
store_fd: bool = false,
arena: bun.MimallocArena = undefined,
name: [:0]const u8 = "Worker",
- cpp_worker: *void,
+ cpp_worker: *anyopaque,
allowed_to_exit: bool = false,
mini: bool = false,
parent_poll_ref: JSC.PollRef = .{},
initial_poll_ref: JSC.PollRef = .{},
+ did_send_initial_task: bool = false,
- extern fn WebWorker__dispatchExit(?*JSC.JSGlobalObject, *void, i32) void;
- extern fn WebWorker__dispatchOnline(this: *void, *JSC.JSGlobalObject) void;
- extern fn WebWorker__dispatchError(*JSC.JSGlobalObject, *void, bun.String, JSValue) void;
+ extern fn WebWorker__dispatchExit(?*JSC.JSGlobalObject, *anyopaque, i32) void;
+ extern fn WebWorker__dispatchOnline(this: *anyopaque, *JSC.JSGlobalObject) void;
+ extern fn WebWorker__dispatchError(*JSC.JSGlobalObject, *anyopaque, bun.String, JSValue) void;
export fn WebWorker__getParentWorker(vm: *JSC.VirtualMachine) ?*anyopaque {
var worker = vm.worker orelse return null;
return worker.cpp_worker;
}
+ export fn WebWorker__updatePtr(worker: *WebWorker, ptr: *anyopaque) bool {
+ worker.cpp_worker = ptr;
+
+ var thread = std.Thread.spawn(
+ .{ .stack_size = 2 * 1024 * 1024 },
+ startWithErrorHandling,
+ .{worker},
+ ) catch {
+ worker.deinit();
+ worker.parent_poll_ref.unref(worker.parent);
+ worker.initial_poll_ref.unref(worker.parent);
+ bun.default_allocator.destroy(worker);
+ return false;
+ };
+ thread.detach();
+ return true;
+ }
+
pub fn hasPendingActivity(this: *WebWorker) callconv(.C) bool {
JSC.markBinding(@src());
@@ -105,23 +124,13 @@ pub const WebWorker = struct {
worker.parent_poll_ref.ref(parent);
}
- var thread = std.Thread.spawn(
- .{ .stack_size = 2 * 1024 * 1024 },
- startWithErrorHandling,
- .{worker},
- ) catch {
- worker.deinit();
- worker.requested_terminate = true;
- worker.parent_poll_ref.unref(worker.parent);
- worker.initial_poll_ref.unref(worker.parent);
- return null;
- };
- thread.detach();
-
return worker;
}
- fn queueInitialTask(this: *WebWorker) void {
+ pub fn queueInitialTask(this: *WebWorker) void {
+ if (this.did_send_initial_task) return;
+ this.did_send_initial_task = true;
+
const Unref = struct {
pub fn unref(worker: *WebWorker) void {
worker.initial_poll_ref.unref(worker.parent);
@@ -364,6 +373,7 @@ pub const WebWorker = struct {
@export(create, .{ .name = "WebWorker__create" });
@export(terminate, .{ .name = "WebWorker__terminate" });
@export(setRef, .{ .name = "WebWorker__setRef" });
+ _ = WebWorker__updatePtr;
}
}