Always ensure proper isolate lock management and thread-safe access patterns when working with JavaScript contexts and cross-thread operations. Accessing JSG objects, IoContext, or V8 handles without holding the isolate lock leads to undefined behavior and crashes.
Always ensure proper isolate lock management and thread-safe access patterns when working with JavaScript contexts and cross-thread operations. Accessing JSG objects, IoContext, or V8 handles without holding the isolate lock leads to undefined behavior and crashes.
Key requirements:
[&]
- reference capture is only safe for synchronous executionctx.run()
for isolate entry - manually acquiring locks misses critical setup like setting current IoContext and honoring input locksIoContext::current().getWeakRef()
and check validity before accessing.wait()
or threadsownContentIsRpcResponse
to indicate thread affinity requirementsExample of unsafe vs safe patterns:
// UNSAFE: Reference capture in async lambda
return context.awaitIo(js, kj::mv(promise), [&](jsg::Lock& js, kj::String text) mutable {
// [&] is unsafe when lambda executes asynchronously
});
// SAFE: Explicit capture list
return context.awaitIo(js, kj::mv(promise), [context = &context](jsg::Lock& js, kj::String text) mutable {
// Explicit capture is safe
});
// UNSAFE: Manual isolate lock without proper context
auto lock = co_await ctx.getWorker()->takeAsyncLockWithoutRequest(nullptr);
// SAFE: Use ctx.run() for proper isolate entry
co_await ctx.run([](Worker::Lock& lock) {
// Proper context setup with IoContext, input locks, etc.
});
This prevents data races, use-after-free bugs, and ensures proper resource lifecycle management across thread boundaries.
Enter the URL of a public GitHub repository