Skip to content

Commit

Permalink
Support setting error stack JSValue directly
Browse files Browse the repository at this point in the history
  • Loading branch information
Jarred-Sumner committed Oct 13, 2024
1 parent 01ac6a6 commit 3d38420
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 14 deletions.
44 changes: 35 additions & 9 deletions Source/JavaScriptCore/runtime/ErrorInstance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "JSCInlines.h"
#include "ParseInt.h"
#include "StackFrame.h"
#include "VM.h"
#include <wtf/text/MakeString.h>

namespace JSC {
Expand Down Expand Up @@ -107,6 +108,15 @@ String appendSourceToErrorMessage(CodeBlock* codeBlock, BytecodeIndex bytecodeIn
return appender(message, codeBlock->source().provider()->getRange(start, stop), type, ErrorInstance::FoundApproximateSource);
}

void ErrorInstance::setStackFrames(VM& vm, WTF::Vector<StackFrame>&& stackFrames)
{
std::unique_ptr<Vector<StackFrame>> stackTrace = makeUnique<Vector<StackFrame>>(WTFMove(stackFrames));

Locker locker { cellLock() };
m_stackTrace = WTFMove(stackTrace);
vm.writeBarrier(this);
}

void ErrorInstance::captureStackTrace(VM& vm, JSGlobalObject* globalObject, size_t framesToSkip, bool append)
{
{
Expand All @@ -127,7 +137,7 @@ void ErrorInstance::captureStackTrace(VM& vm, JSGlobalObject* globalObject, size
remaining = std::min(remaining, m_stackTrace->size());
if (remaining > 0) {
ASSERT(m_stackTrace->size() >= remaining);
stackTrace->append(std::span { m_stackTrace->data(), remaining } );
stackTrace->append(std::span { m_stackTrace->data(), remaining });
}
}

Expand Down Expand Up @@ -310,14 +320,8 @@ void ErrorInstance::computeErrorInfo(VM& vm, bool allocationAllowed)

if (m_stackTrace && !m_stackTrace->isEmpty()) {
auto& fn = vm.onComputeErrorInfo();
if (fn && allocationAllowed) {
// This function may call `globalObject` or potentially even execute arbitrary JS code.
// We cannot gurantee the lifetime of this stack trace to continue to be valid.
// We have to move it out of the ErrorInstance.
WTF::Vector<StackFrame> stackTrace = WTFMove(*m_stackTrace.get());
m_stackString = fn(vm, stackTrace, m_lineColumn.line, m_lineColumn.column, m_sourceURL, allocationAllowed ? this : nullptr);
} else if (fn && !allocationAllowed) {
m_stackString = fn(vm, *m_stackTrace.get(), m_lineColumn.line, m_lineColumn.column, m_sourceURL, nullptr);
if (fn) {
m_stackString = fn(vm, *m_stackTrace.get(), m_lineColumn.line, m_lineColumn.column, m_sourceURL);
} else {
getLineColumnAndSource(vm, m_stackTrace.get(), m_lineColumn, m_sourceURL);
m_stackString = Interpreter::stackTraceAsString(vm, *m_stackTrace.get());
Expand All @@ -331,6 +335,28 @@ bool ErrorInstance::materializeErrorInfoIfNeeded(VM& vm)
if (m_errorInfoMaterialized)
return false;

#if USE(BUN_JSC_ADDITIONS)

auto& fn = vm.onComputeErrorInfoJSValue();
if (fn && m_stackTrace && !m_stackTrace->isEmpty()) {
DeferGCForAWhile deferGC(vm);

JSValue stack = fn(vm, *m_stackTrace.get(), m_lineColumn.line, m_lineColumn.column, m_sourceURL, this);
m_stackTrace = nullptr;

auto attributes = static_cast<unsigned>(PropertyAttribute::DontEnum);

putDirect(vm, vm.propertyNames->line, jsNumber(m_lineColumn.line), attributes);
putDirect(vm, vm.propertyNames->column, jsNumber(m_lineColumn.column), attributes);
if (!m_sourceURL.isEmpty())
putDirect(vm, vm.propertyNames->sourceURL, jsString(vm, WTFMove(m_sourceURL)), attributes);

putDirect(vm, vm.propertyNames->stack, stack, attributes);
m_errorInfoMaterialized = true;
return true;
}

#endif
computeErrorInfo(vm, true);

if (!m_stackString.isNull()) {
Expand Down
2 changes: 2 additions & 0 deletions Source/JavaScriptCore/runtime/ErrorInstance.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,8 @@ class ErrorInstance : public JSNonFinalObject {

unsigned column() const { return m_lineColumn.column; }
void setColumn(unsigned column) { m_lineColumn.column = column; }
void setStackFrames(VM& vm, WTF::Vector<JSC::StackFrame>&& stackFrames);

#endif

JS_EXPORT_PRIVATE String sanitizedToString(JSGlobalObject*);
Expand Down
21 changes: 16 additions & 5 deletions Source/JavaScriptCore/runtime/VM.h
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,11 @@ class Waiter;

constexpr bool validateDFGDoesGC = ENABLE_DFG_DOES_GC_VALIDATION;

#if USE(BUN_JSC_ADDITIONS)
using ErrorInfoFunction = WTF::Function<String(VM&, Vector<StackFrame>& stackTrace, unsigned& line, unsigned& column, String& sourceURL)>;
using ErrorInfoFunctionJSValue = WTF::Function<JSValue(VM&, Vector<StackFrame>& stackTrace, unsigned& line, unsigned& column, String& sourceURL, JSC::JSObject*)>;
#endif

#if ENABLE(FTL_JIT)
namespace FTL {
class Thunks;
Expand Down Expand Up @@ -934,10 +939,13 @@ class VM : public ThreadSafeRefCounted<VM>, public DoublyLinkedListNode<VM> {

WTF::Function<void(VM&, SourceProvider*, LineColumn&)>& computeLineColumnWithSourcemap() { return m_computeLineColumnWithSourcemap; }
void setComputeLineColumnWithSourcemap(WTF::Function<void(VM&, SourceProvider*, LineColumn&)>&& func) { m_computeLineColumnWithSourcemap = WTFMove(func); }

WTF::Function<String(VM&, Vector<StackFrame>& stackTrace, unsigned &line, unsigned &column, String& sourceURL, JSC::JSObject*)>& onComputeErrorInfo() { return m_onComputeErrorInfo; }
void setOnComputeErrorInfo(WTF::Function<String(VM&, Vector<StackFrame>& stackTrace, unsigned &line, unsigned &column, String& sourceURL, JSC::JSObject*)>&& func) { m_onComputeErrorInfo = WTFMove(func); }


#if USE(BUN_JSC_ADDITIONS)
const ErrorInfoFunction& onComputeErrorInfo() const { return m_onComputeErrorInfo; }
const ErrorInfoFunctionJSValue& onComputeErrorInfoJSValue() const { return m_onComputeErrorInfoJSValue; }
void setOnComputeErrorInfo(ErrorInfoFunction&& func) { m_onComputeErrorInfo = WTFMove(func); }
void setOnComputeErrorInfoJSValue(ErrorInfoFunctionJSValue&& func) { m_onComputeErrorInfoJSValue = WTFMove(func); }
#endif
void finalizeSynchronousJSExecution()
{
ASSERT(currentThreadIsHoldingAPILock());
Expand Down Expand Up @@ -1135,8 +1143,11 @@ class VM : public ThreadSafeRefCounted<VM>, public DoublyLinkedListNode<VM> {
Vector<Strong<JSPromise>> m_aboutToBeNotifiedRejectedPromises;

WTF::Function<void(VM&)> m_onEachMicrotaskTick;
WTF::Function<String(VM&, Vector<StackFrame>& stackTrace, unsigned &line, unsigned &column, String& sourceURL, JSC::JSObject*)> m_onComputeErrorInfo;
#if USE(BUN_JSC_ADDITIONS)
ErrorInfoFunction m_onComputeErrorInfo;
ErrorInfoFunctionJSValue m_onComputeErrorInfoJSValue;
WTF::Function<void(VM&, SourceProvider*, LineColumn&)> m_computeLineColumnWithSourcemap;
#endif
uintptr_t m_currentWeakRefVersion { 0 };

bool m_hasSideData { false };
Expand Down

0 comments on commit 3d38420

Please sign in to comment.