diff --git a/src/bun.js/bindings/InspectorTestReporterAgent.cpp b/src/bun.js/bindings/InspectorTestReporterAgent.cpp index 84369818eb9dfd..d788e490d7fe6e 100644 --- a/src/bun.js/bindings/InspectorTestReporterAgent.cpp +++ b/src/bun.js/bindings/InspectorTestReporterAgent.cpp @@ -169,7 +169,7 @@ void InspectorTestReporterAgent::reportTestFound(JSC::CallFrame* callFrame, int remappedFrame.position.column_zero_based = originalColumn.zeroBasedInt(); remappedFrame.source_url = Bun::toStringRef(sourceURL); - Bun__remapStackFramePositions(globalObject, &remappedFrame, 1); + Bun__remapStackFramePositions(Bun::vm(globalObject), &remappedFrame, 1); sourceURL = remappedFrame.source_url.toWTFString(); lineColumn.line = OrdinalNumber::fromZeroBasedInt(remappedFrame.position.line_zero_based).oneBasedInt(); diff --git a/src/bun.js/bindings/ZigGlobalObject.cpp b/src/bun.js/bindings/ZigGlobalObject.cpp index c0d2156bed36c7..30bad901240bd6 100644 --- a/src/bun.js/bindings/ZigGlobalObject.cpp +++ b/src/bun.js/bindings/ZigGlobalObject.cpp @@ -449,6 +449,13 @@ WTF::String Bun::formatStackTrace( size_t framesCount = stackTrace.size(); bool hasSet = false; + void* bunVM = nullptr; + const auto getBunVM = [&]() -> void* { + if (!bunVM) { + bunVM = clientData(vm)->bunVM; + } + return bunVM; + }; if (errorInstance) { if (JSC::ErrorInstance* err = jsDynamicCast(errorInstance)) { @@ -472,9 +479,8 @@ WTF::String Bun::formatStackTrace( // https://github.com/oven-sh/bun/issues/3595 if (!sourceURLForFrame.isEmpty()) { remappedFrame.source_url = Bun::toStringRef(sourceURLForFrame); - // This ensures the lifetime of the sourceURL is accounted for correctly - Bun__remapStackFramePositions(globalObject, &remappedFrame, 1); + Bun__remapStackFramePositions(getBunVM(), &remappedFrame, 1); sourceURLForFrame = remappedFrame.source_url.toWTFString(); } @@ -558,7 +564,7 @@ WTF::String Bun::formatStackTrace( remappedFrame.source_url = Bun::toStringRef(sourceURLForFrame); // This ensures the lifetime of the sourceURL is accounted for correctly - Bun__remapStackFramePositions(globalObject, &remappedFrame, 1); + Bun__remapStackFramePositions(getBunVM(), &remappedFrame, 1); sourceURLForFrame = remappedFrame.source_url.toWTFString(); } @@ -707,7 +713,7 @@ static JSValue computeErrorInfoWithPrepareStackTrace(JSC::VM& vm, Zig::GlobalObj frame.source_url = Bun::toStringRef(sourceURLForFrame); // This ensures the lifetime of the sourceURL is accounted for correctly - Bun__remapStackFramePositions(globalObject, &frame, 1); + Bun__remapStackFramePositions(globalObject->bunVM(), &frame, 1); sourceURLForFrame = frame.source_url.toWTFString(); } diff --git a/src/bun.js/bindings/bindings.cpp b/src/bun.js/bindings/bindings.cpp index 929e5666835950..d90c1d62138707 100644 --- a/src/bun.js/bindings/bindings.cpp +++ b/src/bun.js/bindings/bindings.cpp @@ -6443,7 +6443,7 @@ CPP_DECL void Bun__CallFrame__getCallerSrcLoc(JSC::CallFrame* callFrame, JSC::JS remappedFrame.position.column_zero_based = originalColumn.zeroBasedInt(); remappedFrame.source_url = Bun::toStringRef(sourceURL); - Bun__remapStackFramePositions(globalObject, &remappedFrame, 1); + Bun__remapStackFramePositions(Bun::vm(globalObject), &remappedFrame, 1); sourceURL = remappedFrame.source_url.toWTFString(); lineColumn.line = OrdinalNumber::fromZeroBasedInt(remappedFrame.position.line_zero_based).oneBasedInt(); diff --git a/src/bun.js/bindings/headers-handwritten.h b/src/bun.js/bindings/headers-handwritten.h index e6bb4e2de7bfc0..00176b94c627b7 100644 --- a/src/bun.js/bindings/headers-handwritten.h +++ b/src/bun.js/bindings/headers-handwritten.h @@ -433,7 +433,7 @@ bool Bun__deepMatch( bool replacePropsWithAsymmetricMatchers, bool isMatchingObjectContaining); -extern "C" void Bun__remapStackFramePositions(JSC::JSGlobalObject*, ZigStackFrame*, size_t); +extern "C" void Bun__remapStackFramePositions(void*, ZigStackFrame*, size_t); namespace Inspector { class ScriptArguments; diff --git a/src/bun.js/javascript.zig b/src/bun.js/javascript.zig index a5c975c2e9f40d..bf847630fb55f4 100644 --- a/src/bun.js/javascript.zig +++ b/src/bun.js/javascript.zig @@ -835,6 +835,8 @@ pub const VirtualMachine = struct { after_event_loop_callback_ctx: ?*anyopaque = null, after_event_loop_callback: ?OpaqueCallback = null, + remap_stack_frames_mutex: bun.Mutex = .{}, + /// The arguments used to launch the process _after_ the script name and bun and any flags applied to Bun /// "bun run foo --bar" /// ["--bar"] @@ -3551,8 +3553,10 @@ pub const VirtualMachine = struct { } } - pub export fn Bun__remapStackFramePositions(globalObject: *JSGlobalObject, frames: [*]JSC.ZigStackFrame, frames_count: usize) void { - globalObject.bunVM().remapStackFramePositions(frames, frames_count); + pub export fn Bun__remapStackFramePositions(vm: *JSC.VirtualMachine, frames: [*]JSC.ZigStackFrame, frames_count: usize) void { + // **Warning** this method can be called in the heap collector thread!! + // https://github.com/oven-sh/bun/issues/17087 + vm.remapStackFramePositions(frames, frames_count); } pub fn remapStackFramePositions(this: *VirtualMachine, frames: [*]JSC.ZigStackFrame, frames_count: usize) void { @@ -3561,6 +3565,11 @@ pub const VirtualMachine = struct { var sourceURL = frame.source_url.toUTF8(bun.default_allocator); defer sourceURL.deinit(); + // **Warning** this method can be called in the heap collector thread!! + // https://github.com/oven-sh/bun/issues/17087 + this.remap_stack_frames_mutex.lock(); + defer this.remap_stack_frames_mutex.unlock(); + if (this.resolveSourceMapping( sourceURL.slice(), @max(frame.position.line.zeroBased(), 0),