Skip to content

Commit

Permalink
Report uncaught exceptions when the debugger isn't attached
Browse files Browse the repository at this point in the history
  • Loading branch information
Jarred-Sumner committed Nov 17, 2024
1 parent e80d3e1 commit 8f9ae4f
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 9 deletions.
16 changes: 11 additions & 5 deletions Source/JavaScriptCore/inspector/ScriptCallStackFactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
#include "ScriptArguments.h"
#include "ScriptCallFrame.h"
#include "ScriptExecutable.h"
#include <span>
#include <wtf/text/WTFString.h>

namespace Inspector {
Expand Down Expand Up @@ -168,20 +169,19 @@ static bool extractSourceInformationFromException(JSC::JSGlobalObject* globalObj
return result;
}

Ref<ScriptCallStack> createScriptCallStackFromException(JSC::JSGlobalObject* globalObject, JSC::Exception* exception, size_t maxStackSize)
Ref<ScriptCallStack> createScriptCallStackFromStackTrace(JSC::JSGlobalObject* globalObject, std::span<const JSC::StackFrame> stackTrace, JSC::JSValue value, size_t maxStackSize)
{
auto& vm = globalObject->vm();
Vector<ScriptCallFrame> frames;
auto& stackTrace = exception->stack();
VM& vm = globalObject->vm();
for (size_t i = 0; i < stackTrace.size() && i < maxStackSize; i++) {
auto lineColumn = stackTrace[i].computeLineAndColumn();
String functionName = stackTrace[i].functionName(vm);
frames.append(ScriptCallFrame(functionName, stackTrace[i].sourceURL(vm), stackTrace[i].sourceID(), lineColumn));
}

// Fallback to getting at least the line and sourceURL from the exception object if it has values and the exceptionStack doesn't.
if (exception->value().isObject()) {
JSObject* exceptionObject = exception->value().toObject(globalObject);
if (value.isObject()) {
JSObject* exceptionObject = value.toObject(globalObject);
ASSERT(exceptionObject);
LineColumn lineColumn;
String exceptionSourceURL;
Expand Down Expand Up @@ -210,6 +210,12 @@ Ref<ScriptCallStack> createScriptCallStackFromException(JSC::JSGlobalObject* glo
return ScriptCallStack::create(WTFMove(frames), stackTrace.size() > maxStackSize, parentStackTrace);
}

Ref<ScriptCallStack> createScriptCallStackFromException(JSC::JSGlobalObject* globalObject, JSC::Exception* exception, size_t maxStackSize)
{
const auto stackTrace = exception->stack();
return createScriptCallStackFromStackTrace(globalObject, { stackTrace.begin(), stackTrace.end() }, exception->value(), maxStackSize);
}

Ref<ScriptArguments> createScriptArguments(JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame, unsigned skipArgumentCount)
{
VM& vm = globalObject->vm();
Expand Down
1 change: 1 addition & 0 deletions Source/JavaScriptCore/inspector/ScriptCallStackFactory.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ class ScriptArguments;
JS_EXPORT_PRIVATE Ref<ScriptCallStack> createScriptCallStack(JSC::JSGlobalObject*, size_t maxStackSize = ScriptCallStack::maxCallStackSizeToCapture);
JS_EXPORT_PRIVATE Ref<ScriptCallStack> createScriptCallStackForConsole(JSC::JSGlobalObject*, size_t maxStackSize = ScriptCallStack::maxCallStackSizeToCapture);
JS_EXPORT_PRIVATE Ref<ScriptCallStack> createScriptCallStackFromException(JSC::JSGlobalObject*, JSC::Exception*, size_t maxStackSize = ScriptCallStack::maxCallStackSizeToCapture);
JS_EXPORT_PRIVATE Ref<ScriptCallStack> createScriptCallStackFromStackTrace(JSC::JSGlobalObject*, std::span<const JSC::StackFrame>, JSC::JSValue value, size_t maxStackSize = ScriptCallStack::maxCallStackSizeToCapture);
JS_EXPORT_PRIVATE Ref<ScriptArguments> createScriptArguments(JSC::JSGlobalObject*, JSC::CallFrame*, unsigned skipArgumentCount);

} // namespace Inspector
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,13 @@
},
{
"name": "error",
"parameters": [{ "name": "message", "$ref": "Console.ConsoleMessage", "description": "Source of the error" }]
"parameters": [
{ "name": "message", "type": "string", "description": "string associated with the error" },
{ "name": "name", "type": "string", "description": "If an Error instance, the error.name property" },
{ "name": "urls", "type": "array", "description": "Array of URLs associated with the error", "items": { "type": "string" } },
{ "name": "lineColumns", "type": "array", "description": "Line, column pairs associated with the error. Already sourcemapped.", "items": { "type": "integer" } },
{ "name": "sourceLines", "type": "array", "description": "Source code preview associated with the error for up to 5 lines before the error, relative to the first non-internal stack frame.", "items": { "type": "string" } }
]
}
]
}
13 changes: 10 additions & 3 deletions Source/JavaScriptCore/inspector/protocol/TestReporter.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"domain": "TestReporter",
"description": "TestReporter domain allows reporting of lifecycle events.",
"description": "TestReporter domain allows reporting of test-related events.",
"debuggableTypes": ["itml", "javascript"],
"targetTypes": ["itml", "javascript"],
"types": [
Expand Down Expand Up @@ -28,7 +28,14 @@
{
"name": "scriptId",
"$ref": "Debugger.ScriptId",
"description": "Unique identifier of the script that started the test."
"description": "Unique identifier of the script the test is in. Available when the debugger is attached.",
"optional": true
},
{
"name": "url",
"type": "string",
"description": "url of the script the test is in. Available when the debugger is not attached.",
"optional": true
},
{
"name": "line",
Expand All @@ -49,7 +56,7 @@
{ "name": "status", "$ref": "TestStatus", "description": "Status of the test that ended." },
{
"name": "elapsed",
"type": "number",
"type": "integer",
"description": "Elapsed time in milliseconds since the test started."
}
]
Expand Down

0 comments on commit 8f9ae4f

Please sign in to comment.