From baa89345459006a96bd597a5ed229b45b7369055 Mon Sep 17 00:00:00 2001 From: Dylan Conway Date: Wed, 20 Sep 2023 00:25:59 -0700 Subject: some of it --- src/bun.js/bindings/CallSite.cpp | 40 +++++++++++++++++++++++++ src/bun.js/bindings/CallSite.h | 9 ++++++ src/bun.js/bindings/ZigGlobalObject.cpp | 53 +++++++++++++++++++++++++++++++-- src/bun.js/bindings/ZigGlobalObject.h | 1 - 4 files changed, 100 insertions(+), 3 deletions(-) diff --git a/src/bun.js/bindings/CallSite.cpp b/src/bun.js/bindings/CallSite.cpp index 48fe82275..1b42b826f 100644 --- a/src/bun.js/bindings/CallSite.cpp +++ b/src/bun.js/bindings/CallSite.cpp @@ -75,6 +75,46 @@ void CallSite::finishCreation(VM& vm, JSC::JSGlobalObject* globalObject, JSCStac } } +void CallSite::finishCreationWithFrame(VM& vm, JSC::JSGlobalObject* globalObject, JSC::StackFrame& stackFrame, bool encounteredStrictFrame) +{ + Base::finishCreation(vm); + + bool isStrictFrame = encounteredStrictFrame; + if (!isStrictFrame) { + JSC::CodeBlock* codeBlock = stackFrame.codeBlock(); + if (codeBlock) { + isStrictFrame = codeBlock->ownerExecutable()->isInStrictContext(); + } + } + + JSObject* calleeObject = jsCast(stackFrame.callee()); + + m_thisValue.set(vm, this, JSC::jsUndefined()); + if (isStrictFrame) { + m_function.set(vm, this, JSC::jsUndefined()); + m_flags |= static_cast(Flags::IsStrict); + } else { + m_function.set(vm, this, stackFrame.callee()); + } + + // m_functionName.set(vm, this, stackFrame.functionName(vm)); + // m_sourceURL.set(vm, this, stackFrame.sourceURL(vm)); + + unsigned int line = 0; + unsigned int column = 0; + stackFrame.computeLineAndColumn(line, column); + m_lineNumber = jsNumber(line + 1); + m_columnNumber = jsNumber(column + 1); + + if (!stackFrame.codeBlock()) { + m_flags |= static_cast(Flags::IsNative); + } else { + if (stackFrame.codeBlock()->codeType() == EvalCode) { + m_flags |= static_cast(Flags::IsEval); + } + } +} + template void CallSite::visitChildrenImpl(JSCell* cell, Visitor& visitor) { diff --git a/src/bun.js/bindings/CallSite.h b/src/bun.js/bindings/CallSite.h index 93ce9a46b..8a5380c90 100644 --- a/src/bun.js/bindings/CallSite.h +++ b/src/bun.js/bindings/CallSite.h @@ -38,6 +38,14 @@ private: public: using Base = JSC::JSNonFinalObject; + static CallSite* createWithFrame(JSC::JSGlobalObject* globalObject, JSC::Structure* structure, JSC::StackFrame& stackFrame, bool encounteredStrictFrame) + { + JSC::VM& vm = globalObject->vm(); + CallSite* callSite = new (NotNull, JSC::allocateCell(vm)) CallSite(vm, structure); + callSite->finishCreationWithFrame(vm, globalObject, stackFrame, encounteredStrictFrame); + return callSite; + } + static CallSite* create(JSC::JSGlobalObject* globalObject, JSC::Structure* structure, JSCStackFrame& stackFrame, bool encounteredStrictFrame) { JSC::VM& vm = globalObject->vm(); @@ -92,6 +100,7 @@ private: } void finishCreation(VM& vm, JSC::JSGlobalObject* globalObject, JSCStackFrame& stackFrame, bool encounteredStrictFrame); + void finishCreationWithFrame(VM& vm, JSC::JSGlobalObject* globalObject, JSC::StackFrame& stackFrame, bool encounteredStrictFrame); DECLARE_VISIT_CHILDREN; }; diff --git a/src/bun.js/bindings/ZigGlobalObject.cpp b/src/bun.js/bindings/ZigGlobalObject.cpp index 9b36157fe..aca1663b5 100644 --- a/src/bun.js/bindings/ZigGlobalObject.cpp +++ b/src/bun.js/bindings/ZigGlobalObject.cpp @@ -438,8 +438,57 @@ static String computeErrorInfoWithoutPrepareStackTrace(JSC::VM& vm, Vector& stackTrace, JSArray* callSites) +{ + bool encounteredStrictFrame = false; + GlobalObject* globalObject = reinterpret_cast(lexicalGlobalObject); + + JSC::Structure* callSiteStructure = globalObject->callSiteStructure(); + size_t framesCount = stackTrace.size(); + for (size_t i = 0; i < framesCount; i++) { + CallSite* callSite = CallSite::createWithFrame(lexicalGlobalObject, callSiteStructure, stackTrace.at(i), encounteredStrictFrame); + callSites->putDirectIndex(lexicalGlobalObject, i, callSite); + + if (!encounteredStrictFrame) { + encounteredStrictFrame = callSite->isStrict(); + } + } +} + static String computeErrorInfo(JSC::VM& vm, Vector& stackTrace, unsigned& line, unsigned& column, String& sourceURL, JSObject* errorInstance) { + Zig::GlobalObject* globalObject = jsDynamicCast(errorInstance->globalObject()); + JSGlobalObject* lexicalGlobalObject = jsDynamicCast(globalObject); + auto errorConstructor = globalObject->errorConstructor(); + auto scope = DECLARE_THROW_SCOPE(vm); + + JSValue prepareStackTrace = errorConstructor->getIfPropertyExists(globalObject, Identifier::fromString(vm, "prepareStackTrace"_s)); + if (prepareStackTrace && prepareStackTrace.isCallable()) { + CallData prepareStackTraceCallData = JSC::getCallData(prepareStackTrace); + if (prepareStackTraceCallData.type != CallData::Type::None) { + // create the call site from the Vector + JSArray* callSites = JSArray::create(vm, globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous), stackTrace.size()); + + createCallSitesFromFrames(lexicalGlobalObject, stackTrace, callSites); + + MarkedArgumentBuffer args; + args.append(errorInstance); + args.append(callSites); + ASSERT(!args.hasOverflowed()); + + JSValue result = profiledCall( + lexicalGlobalObject, + ProfilingReason::Other, + prepareStackTrace, + prepareStackTraceCallData, + errorConstructor, + args); + RETURN_IF_EXCEPTION(scope, String()); + + errorInstance->putDirect(vm, vm.propertyNames->stack, result, 0); + return String(); + } + } return computeErrorInfoWithoutPrepareStackTrace(vm, stackTrace, line, column, sourceURL, errorInstance); } @@ -2441,7 +2490,7 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionPerformMicrotaskVariadic, (JSGlobalObject * g return JSValue::encode(jsUndefined()); } -void GlobalObject::createCallSitesFromFrames(JSC::JSGlobalObject* lexicalGlobalObject, JSCStackTrace& stackTrace, JSC::JSArray* callSites) +void createCallSitesFromStackTrace(JSC::JSGlobalObject* lexicalGlobalObject, JSCStackTrace& stackTrace, JSC::JSArray* callSites) { /* From v8's "Stack Trace API" (https://github.com/v8/v8/wiki/Stack-Trace-API): * "To maintain restrictions imposed on strict mode functions, frames that have a @@ -2581,7 +2630,7 @@ JSC_DEFINE_HOST_FUNCTION(errorConstructorFuncCaptureStackTrace, (JSC::JSGlobalOb stackTrace.size()); // Create the call sites (one per frame) - GlobalObject::createCallSitesFromFrames(lexicalGlobalObject, stackTrace, callSites); + createCallSitesFromStackTrace(lexicalGlobalObject, stackTrace, callSites); /* Format the stack trace. * Note that v8 won't actually format the stack trace here, but will create a "stack" accessor diff --git a/src/bun.js/bindings/ZigGlobalObject.h b/src/bun.js/bindings/ZigGlobalObject.h index ad5138527..90e9bd11d 100644 --- a/src/bun.js/bindings/ZigGlobalObject.h +++ b/src/bun.js/bindings/ZigGlobalObject.h @@ -152,7 +152,6 @@ public: void clearDOMGuardedObjects(); - static void createCallSitesFromFrames(JSC::JSGlobalObject* lexicalGlobalObject, JSCStackTrace& stackTrace, JSC::JSArray* callSites); JSC::JSValue formatStackTrace(JSC::VM& vm, JSC::JSGlobalObject* lexicalGlobalObject, JSC::JSObject* errorObject, JSC::JSArray* callSites); static void reportUncaughtExceptionAtEventLoop(JSGlobalObject*, JSC::Exception*); -- cgit v1.2.3