diff options
author | 2023-06-19 23:28:40 -0700 | |
---|---|---|
committer | 2023-06-19 23:28:40 -0700 | |
commit | bdbb637b3d870f1955cadd342eeae0147f50c3de (patch) | |
tree | 41ef0eaadf53f5fbc9cce96bfec0bada3c53b13d /src/bun.js/bindings/ZigGlobalObject.cpp | |
parent | e9e0e051569d3858cfc18b21a6aa6d1b7184f7e7 (diff) | |
download | bun-bdbb637b3d870f1955cadd342eeae0147f50c3de.tar.gz bun-bdbb637b3d870f1955cadd342eeae0147f50c3de.tar.zst bun-bdbb637b3d870f1955cadd342eeae0147f50c3de.zip |
implement more of V8's stack trace API (#3359)
- fix source map positions for getLineNumber / getColumnNumber
- fix return value getting coerced to a string
- implement CallFrame.p.toString
- add tests for getFunction, getThis, isConstructor, isNative, toString,
getLineNumber, getColumnNumber
still not implemented:
- isPromiseAll/getPromiseIndex
- getEvalOrigin
- getScriptHash
- getPosition
- getEnclosingColumnNumber/getEnclosingLineNumber
- isAsync
- accessing Error.stack should call prepareStackTrace
still broken:
- isEval: often returns false when it should return true
- isToplevel: often returns true when it should return false
Refs: https://v8.dev/docs/stack-trace-api
Refs: v8/src/objects/call-site-info.cc
Fixes: https://github.com/oven-sh/bun/issues/2883
Diffstat (limited to 'src/bun.js/bindings/ZigGlobalObject.cpp')
-rw-r--r-- | src/bun.js/bindings/ZigGlobalObject.cpp | 57 |
1 files changed, 21 insertions, 36 deletions
diff --git a/src/bun.js/bindings/ZigGlobalObject.cpp b/src/bun.js/bindings/ZigGlobalObject.cpp index ec4976bc4..9b3bfd2a2 100644 --- a/src/bun.js/bindings/ZigGlobalObject.cpp +++ b/src/bun.js/bindings/ZigGlobalObject.cpp @@ -2502,7 +2502,7 @@ void GlobalObject::createCallSitesFromFrames(JSC::JSGlobalObject* lexicalGlobalO } } -JSC::JSValue GlobalObject::formatStackTrace(JSC::VM& vm, JSC::JSGlobalObject* lexicalGlobalObject, JSC::JSObject* errorObject, JSC::JSArray* callSites, ZigStackFrame remappedStackFrames[]) +JSC::JSValue GlobalObject::formatStackTrace(JSC::VM& vm, JSC::JSGlobalObject* lexicalGlobalObject, JSC::JSObject* errorObject, JSC::JSArray* callSites) { auto scope = DECLARE_THROW_SCOPE(vm); JSValue errorValue = this->get(this, JSC::Identifier::fromString(vm, "Error"_s)); @@ -2557,39 +2557,8 @@ JSC::JSValue GlobalObject::formatStackTrace(JSC::VM& vm, JSC::JSGlobalObject* le for (size_t i = 0; i < framesCount; i++) { JSC::JSValue callSiteValue = callSites->getIndex(lexicalGlobalObject, i); CallSite* callSite = JSC::jsDynamicCast<CallSite*>(callSiteValue); - - JSString* typeName = jsTypeStringForValue(lexicalGlobalObject, callSite->thisValue()); - JSString* function = callSite->functionName().toString(lexicalGlobalObject); - JSString* functionName = callSite->functionName().toString(lexicalGlobalObject); - JSString* sourceURL = callSite->sourceURL().toString(lexicalGlobalObject); - JSString* columnNumber = remappedStackFrames[i].position.column_start >= 0 ? jsNontrivialString(vm, String::number(remappedStackFrames[i].position.column_start)) : jsEmptyString(vm); - JSString* lineNumber = remappedStackFrames[i].position.line >= 0 ? jsNontrivialString(vm, String::number(remappedStackFrames[i].position.line)) : jsEmptyString(vm); - bool isConstructor = callSite->isConstructor(); - sb.append(" at "_s); - if (functionName->length() > 0) { - if (isConstructor) { - sb.append("new "_s); - } else { - // TODO: print type or class name if available - // sb.append(typeName->getString(lexicalGlobalObject)); - // sb.append(" "_s); - } - sb.append(functionName->getString(lexicalGlobalObject)); - } else { - sb.append("<anonymous>"_s); - } - sb.append(" ("_s); - if (callSite->isNative()) { - sb.append("native"_s); - } else { - sb.append(sourceURL->getString(lexicalGlobalObject)); - sb.append(":"_s); - sb.append(lineNumber->getString(lexicalGlobalObject)); - sb.append(":"_s); - sb.append(columnNumber->getString(lexicalGlobalObject)); - } - sb.append(")"_s); + callSite->formatAsString(vm, lexicalGlobalObject, sb); if (i != framesCount - 1) { sb.append("\n"_s); } @@ -2598,7 +2567,6 @@ JSC::JSValue GlobalObject::formatStackTrace(JSC::VM& vm, JSC::JSGlobalObject* le return JSC::JSValue(jsString(vm, sb.toString())); } -extern "C" void Bun__remapStackFramePositions(JSC::JSGlobalObject*, ZigStackFrame*, size_t); extern "C" EncodedJSValue JSPasswordObject__create(JSC::JSGlobalObject*, bool); JSC_DECLARE_HOST_FUNCTION(errorConstructorFuncCaptureStackTrace); @@ -2662,9 +2630,26 @@ JSC_DEFINE_HOST_FUNCTION(errorConstructorFuncCaptureStackTrace, (JSC::JSGlobalOb } // remap line and column start to original source + // XXX: this function does not fully populate the fields of ZigStackFrame, + // be careful reading the fields below. Bun__remapStackFramePositions(lexicalGlobalObject, remappedFrames, framesCount); - JSC::JSValue formattedStackTrace = globalObject->formatStackTrace(vm, lexicalGlobalObject, errorObject, callSites, remappedFrames); + // write the remapped lines back to the CallSites + for (size_t i = 0; i < framesCount; i++) { + JSC::JSValue callSiteValue = callSites->getIndex(lexicalGlobalObject, i); + CallSite* callSite = JSC::jsDynamicCast<CallSite*>(callSiteValue); + if (remappedFrames[i].remapped) { + int32_t remappedColumnStart = remappedFrames[i].position.column_start; + JSC::JSValue columnNumber = JSC::jsNumber(remappedColumnStart); + callSite->setColumnNumber(columnNumber); + + int32_t remappedLine = remappedFrames[i].position.line; + JSC::JSValue lineNumber = JSC::jsNumber(remappedLine); + callSite->setLineNumber(lineNumber); + } + } + + JSC::JSValue formattedStackTrace = globalObject->formatStackTrace(vm, lexicalGlobalObject, errorObject, callSites); RETURN_IF_EXCEPTION(scope, JSC::JSValue::encode({})); if (errorObject->hasProperty(lexicalGlobalObject, vm.propertyNames->stack)) { @@ -2673,7 +2658,7 @@ JSC_DEFINE_HOST_FUNCTION(errorConstructorFuncCaptureStackTrace, (JSC::JSGlobalOb if (formattedStackTrace.isUndefinedOrNull()) { errorObject->putDirect(vm, vm.propertyNames->stack, jsUndefined(), JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum); } else { - errorObject->putDirect(vm, vm.propertyNames->stack, formattedStackTrace.toString(lexicalGlobalObject), JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum); + errorObject->putDirect(vm, vm.propertyNames->stack, formattedStackTrace, JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum); } RETURN_IF_EXCEPTION(scope, JSC::JSValue::encode(JSValue {})); |