tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 4dbbb7733ec95063e8b10d88c56c5eb8e524d2bf
parent 9be06acefa92bccd27d98651d02dfbeb909a5d52
Author: Alexandre Poirot <poirot.alex@gmail.com>
Date:   Mon,  6 Oct 2025 11:50:29 +0000

Bug 1989235 - [devtools] Serialize Errors and Exceptions in the tracer. r=devtools-reviewers,frontend-codestyle-reviewers,mossop,dthayer,nchevobbe

Differential Revision: https://phabricator.services.mozilla.com/D265283

Diffstat:
Mjs/public/Debug.h | 11++++++++++-
Mjs/src/debugger/ExecutionTracer.cpp | 71++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Mjs/src/debugger/ExecutionTracer.h | 4+++-
Mjs/xpconnect/src/ExecutionTracerIntegration.cpp | 71+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Mjs/xpconnect/src/ExecutionTracerIntegration.h | 16++++++++++++++++
Mtools/profiler/tests/browser/browser_test_feature_jstracing_objtestutils.snapshot.mjs | 589++++++++++++++-----------------------------------------------------------------
Mtools/profiler/tests/browser/value_summary_reader.mjs | 45+++++++++++++++++++++++++++++++++++++++++++++
7 files changed, 317 insertions(+), 490 deletions(-)

diff --git a/js/public/Debug.h b/js/public/Debug.h @@ -178,7 +178,7 @@ struct ValueSummary { // This value is written to the start of the value summaries buffer (see // TracedJSContext::valueBuffer), and should be bumped every time the format // is changed. - static const uint32_t VERSION = 1; + static const uint32_t VERSION = 2; // If the type is an int and flags != Flags::NUMBER_IS_OUT_OF_LINE_MAGIC, // the value is MIN_INLINE_INT + flags. @@ -253,6 +253,14 @@ struct ValueSummary { // externalSize field with the amount written. // NOTE: it is the embedders' responsibility to manage the versioning of // their format. +// Kind::Error -> +// shapeSummaryId: uint32_t (summary will only contain class name) +// name: SmallString +// message: SmallString +// stack: SmallString +// filename: SmallString +// lineNumber: uint32_t +// columnNumber uint32_t // // WrappedPrimitiveObjects and GenericObjects make use of a PropertySummary // type, defined here: @@ -279,6 +287,7 @@ struct ObjectSummary { GenericObject, ProxyObject, External, + Error, }; Kind kind; diff --git a/js/src/debugger/ExecutionTracer.cpp b/js/src/debugger/ExecutionTracer.cpp @@ -15,13 +15,15 @@ #include "debugger/Frame.h" // DebuggerFrameType -#include "vm/BooleanObject.h" // BooleanObject +#include "vm/BooleanObject.h" // BooleanObject +#include "vm/ErrorObject.h" #include "vm/NumberObject.h" // NumberObject #include "vm/ObjectOperations.h" // DefineDataElement #include "vm/StringObject.h" // StringObject #include "vm/Time.h" #include "debugger/Debugger-inl.h" +#include "vm/ErrorObject-inl.h" // ErrorObject.fileName,lineNumber,... #include "vm/Stack-inl.h" using namespace js; @@ -739,6 +741,68 @@ bool ValueSummaries::writeShapeSummary(JSContext* cx, return true; } +bool ValueSummaries::writeErrorObjectSummary(JSContext* cx, + JS::Handle<JSObject*> obj, + JS::Handle<ErrorObject*> error, + IsNested nested) { + writeObjectHeader(JS::ObjectSummary::Kind::Error, 0); + + JS::Rooted<Shape*> shape(cx, obj->shape()); + if (!writeMinimalShapeSummary(cx, shape)) { + return false; + } + + JS::Rooted<JS::Value> nameVal(cx); + JS::Rooted<JSString*> name(cx); + if (!GetProperty(cx, obj, obj, cx->names().name, &nameVal) || + !(name = ToString<CanGC>(cx, nameVal))) { + valueData_->writeEmptySmallString(); + } else { + if (!valueData_->writeSmallString(cx, name)) { + return false; + } + } + + JS::Rooted<JSString*> message(cx, error->getMessage()); + if (message) { + if (!valueData_->writeSmallString(cx, message)) { + return false; + } + } else { + valueData_->writeEmptySmallString(); + } + + JS::Rooted<JSObject*> stack(cx, error->stack()); + if (stack) { + JSPrincipals* principals = + JS::GetRealmPrincipals(js::GetNonCCWObjectRealm(stack)); + JS::Rooted<JSString*> formattedStack(cx); + if (!JS::BuildStackString(cx, principals, stack, &formattedStack)) { + return false; + } + if (!valueData_->writeSmallString(cx, formattedStack)) { + return false; + } + } else { + valueData_->writeEmptySmallString(); + } + + JS::Rooted<JSString*> filename(cx, error->fileName(cx)); + if (filename) { + if (!valueData_->writeSmallString(cx, filename)) { + return false; + } + } else { + valueData_->writeEmptySmallString(); + } + + valueData_->write((uint32_t)error->lineNumber()); + + valueData_->write((uint32_t)error->columnNumber().oneOriginValue()); + + return true; +} + bool ValueSummaries::writeMinimalShapeSummary(JSContext* cx, JS::Handle<Shape*> shape) { TracingCaches& caches = cx->caches().tracingCaches; @@ -1109,6 +1173,11 @@ bool ValueSummaries::writeObject(JSContext* cx, JS::Handle<JSObject*> obj, if (!writeMapObjectSummary(cx, typed, nested)) { return false; } + } else if (obj->is<ErrorObject>()) { + JS::Rooted<ErrorObject*> typed(cx, &obj->as<ErrorObject>()); + if (!writeErrorObjectSummary(cx, obj, typed, nested)) { + return false; + } } else if (obj->is<NativeObject>()) { JS::Rooted<NativeObject*> nobj(cx, &obj->as<NativeObject>()); diff --git a/js/src/debugger/ExecutionTracer.h b/js/src/debugger/ExecutionTracer.h @@ -509,8 +509,10 @@ class ValueSummaries { IsNested nested); bool writeSetObjectSummary(JSContext* cx, JS::Handle<SetObject*> set, IsNested nested); - bool writeMapObjectSummary(JSContext* cx, JS::Handle<MapObject*> set, + bool writeMapObjectSummary(JSContext* cx, JS::Handle<MapObject*> map, IsNested nested); + bool writeErrorObjectSummary(JSContext* cx, JS::Handle<JSObject*> obj, + JS::Handle<ErrorObject*> error, IsNested nested); bool writeGenericOrWrappedPrimitiveObjectSummary( JSContext* cx, JS::Handle<NativeObject*> nobj, IsNested nested); bool writeExternalObjectSummary(JSContext* cx, JS::Handle<NativeObject*> nobj, diff --git a/js/xpconnect/src/ExecutionTracerIntegration.cpp b/js/xpconnect/src/ExecutionTracerIntegration.cpp @@ -11,6 +11,8 @@ #include "mozilla/dom/BindingUtils.h" #include "mozilla/dom/Document.h" #include "mozilla/dom/DocumentFragment.h" +#include "mozilla/dom/DOMException.h" +#include "mozilla/dom/DOMExceptionBinding.h" #include "mozilla/dom/Element.h" #include "mozilla/dom/Location.h" #include "nsDOMAttributeMap.h" @@ -125,6 +127,63 @@ bool ExecutionTracerIntegration::WriteNodeSummary( return true; } +bool ExecutionTracerIntegration::WriteExceptionSummary( + JSContext* aCx, JS::Handle<JSObject*> aObj, bool aNested, + JS_TracerSummaryWriter* aWriter) { + RefPtr<DOMException> domException; + RefPtr<Exception> exception; + UNWRAP_OBJECT(DOMException, aObj, domException); + if (domException) { + exception = domException; + } else { + // Not a DOM Exception, try XPC Exception. + UNWRAP_OBJECT(Exception, aObj, exception); + if (!exception) { + return false; + } + } + aWriter->writeUint8(uint8_t(SummaryKind::Exception)); + + nsAutoString name; + exception->GetName(name); + aWriter->writeTwoByteString(name.get()); + + nsAutoString message; + exception->GetMessageMoz(message); + aWriter->writeTwoByteString(message.get()); + + if (domException) { + uint16_t code = domException->Code(); + aWriter->writeUint16(code); + } else { + aWriter->writeUint16(0); + } + + uint32_t result = exception->Result(); + aWriter->writeUint32(result); + + nsAutoCString fileName; + exception->GetFilename(aCx, fileName); + aWriter->writeUTF8String(fileName.get()); + + uint32_t line = exception->LineNumber(aCx); + aWriter->writeUint32(line); + + uint32_t column = exception->ColumnNumber(); + aWriter->writeUint32(column); + + nsCOMPtr<nsIStackFrame> stack = exception->GetLocation(); + nsAutoString stackString; + if (stack) { + stack->GetFormattedStack(aCx, stackString); + aWriter->writeTwoByteString(stackString.get()); + } else { + aWriter->writeTwoByteString(u""); + } + + return true; +} + // static bool ExecutionTracerIntegration::Callback(JSContext* aCx, JS::Handle<JSObject*> aObj, @@ -143,10 +202,18 @@ bool ExecutionTracerIntegration::Callback(JSContext* aCx, if (!WriteNodeSummary(aCx, node, aNested, aWriter)) { return false; } - } else { - aWriter->writeUint8(uint8_t(SummaryKind::Other)); + return true; + } + + if (DOMClassHasInterface<prototypes::id::DOMException>(domClass) || + DOMClassHasInterface<prototypes::id::Exception>(domClass)) { + if (!WriteExceptionSummary(aCx, aObj, aNested, aWriter)) { + return false; + } + return true; } + aWriter->writeUint8(uint8_t(SummaryKind::Other)); return true; } diff --git a/js/xpconnect/src/ExecutionTracerIntegration.h b/js/xpconnect/src/ExecutionTracerIntegration.h @@ -59,6 +59,17 @@ namespace mozilla { // textContent: SmallString // NodeSubkind::Comment -> // textContent: SmallString +// SummaryKind::Exception -> +// name: SmallString +// message: SmallString +// code: uint16_t +// Only defined for DOM Exceptions, otherwise set +// to 0. +// result: uint16_t +// filename: SmallString +// lineNumber: uint32_t +// columnNumber: uint32_t +// stack: SmallString class ExecutionTracerIntegration { public: // This version will be baked into each entry, and should be incremented @@ -70,6 +81,7 @@ class ExecutionTracerIntegration { enum class SummaryKind : uint8_t { Other, Node, + Exception, // TODO: more SummaryKinds will be implemented soon. }; @@ -88,6 +100,10 @@ class ExecutionTracerIntegration { static bool WriteNodeSummary(JSContext* aCx, nsINode* aNode, bool aNested, JS_TracerSummaryWriter* aWriter); + + static bool WriteExceptionSummary(JSContext* aCx, JS::Handle<JSObject*> aObj, + bool aNested, + JS_TracerSummaryWriter* aWriter); }; } // namespace mozilla #endif diff --git a/tools/profiler/tests/browser/browser_test_feature_jstracing_objtestutils.snapshot.mjs b/tools/profiler/tests/browser/browser_test_feature_jstracing_objtestutils.snapshot.mjs @@ -601,39 +601,18 @@ export default [ "type": "object", "class": "Error", "ownPropertyLength": 0, - "isError": false, + "isError": true, "extensible": false, "sealed": false, "frozen": false, "preview": { - "kind": "Object", - "ownProperties": { - "message": { - "configurable": true, - "enumerable": true, - "writable": true, - "value": "foo" - }, - "columnNumber": { - "configurable": true, - "enumerable": true, - "writable": true, - "value": 1 - }, - "lineNumber": { - "configurable": true, - "enumerable": true, - "writable": true, - "value": 1 - }, - "fileName": { - "configurable": true, - "enumerable": true, - "writable": true, - "value": "eval line 7 > eval" - } - }, - "ownPropertiesLength": 4 + "kind": "Error", + "name": "Error", + "message": "foo", + "stack": "@eval line 7 > eval:1:1\n@eval:7:21\n", + "fileName": "eval line 7 > eval", + "lineNumber": 1, + "columnNumber": 1 } }, @@ -642,39 +621,18 @@ export default [ "type": "object", "class": "Error", "ownPropertyLength": 0, - "isError": false, + "isError": true, "extensible": false, "sealed": false, "frozen": false, "preview": { - "kind": "Object", - "ownProperties": { - "message": { - "configurable": true, - "enumerable": true, - "writable": true, - "value": "Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long e" - }, - "columnNumber": { - "configurable": true, - "enumerable": true, - "writable": true, - "value": 7 - }, - "lineNumber": { - "configurable": true, - "enumerable": true, - "writable": true, - "value": 1 - }, - "fileName": { - "configurable": true, - "enumerable": true, - "writable": true, - "value": "eval line 7 > eval" - } - }, - "ownPropertiesLength": 4 + "kind": "Error", + "name": "Error", + "message": "Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long error Long e", + "stack": "@eval line 7 > eval:1:7\n@eval:7:21\n", + "fileName": "eval line 7 > eval", + "lineNumber": 1, + "columnNumber": 7 } }, @@ -687,39 +645,18 @@ export default [ "type": "object", "class": "Error", "ownPropertyLength": 0, - "isError": false, + "isError": true, "extensible": false, "sealed": false, "frozen": false, "preview": { - "kind": "Object", - "ownProperties": { - "message": { - "configurable": true, - "enumerable": true, - "writable": true, - "value": "bar" - }, - "columnNumber": { - "configurable": true, - "enumerable": true, - "writable": true, - "value": 6 - }, - "lineNumber": { - "configurable": true, - "enumerable": true, - "writable": true, - "value": 1 - }, - "fileName": { - "configurable": true, - "enumerable": true, - "writable": true, - "value": "eval line 7 > eval" - } - }, - "ownPropertiesLength": 4 + "kind": "Error", + "name": "Error", + "message": "bar", + "stack": "@eval line 7 > eval:1:6\n@eval:7:21\n", + "fileName": "eval line 7 > eval", + "lineNumber": 1, + "columnNumber": 6 } }, @@ -736,39 +673,18 @@ export default [ "type": "object", "class": "ReferenceError", "ownPropertyLength": 0, - "isError": false, + "isError": true, "extensible": false, "sealed": false, "frozen": false, "preview": { - "kind": "Object", - "ownProperties": { - "message": { - "configurable": true, - "enumerable": true, - "writable": true, - "value": "asdf is not defined" - }, - "columnNumber": { - "configurable": true, - "enumerable": true, - "writable": true, - "value": 9 - }, - "lineNumber": { - "configurable": true, - "enumerable": true, - "writable": true, - "value": 3 - }, - "fileName": { - "configurable": true, - "enumerable": true, - "writable": true, - "value": "eval line 7 > eval" - } - }, - "ownPropertiesLength": 4 + "kind": "Error", + "name": "ReferenceError", + "message": "asdf is not defined", + "stack": "bar@eval line 7 > eval:3:9\nfoo@eval line 7 > eval:6:9\n@eval line 7 > eval:9:7\n@eval:7:21\n", + "fileName": "eval line 7 > eval", + "lineNumber": 3, + "columnNumber": 9 } }, @@ -777,39 +693,18 @@ export default [ "type": "object", "class": "SyntaxError", "ownPropertyLength": 0, - "isError": false, + "isError": true, "extensible": false, "sealed": false, "frozen": false, "preview": { - "kind": "Object", - "ownProperties": { - "message": { - "configurable": true, - "enumerable": true, - "writable": true, - "value": "redeclaration of let a" - }, - "columnNumber": { - "configurable": true, - "enumerable": true, - "writable": true, - "value": 8 - }, - "lineNumber": { - "configurable": true, - "enumerable": true, - "writable": true, - "value": 1 - }, - "fileName": { - "configurable": true, - "enumerable": true, - "writable": true, - "value": "eval line 7 > eval" - } - }, - "ownPropertiesLength": 4 + "kind": "Error", + "name": "SyntaxError", + "message": "redeclaration of let a", + "stack": "@eval line 7 > eval:1:1\n@eval:7:21\n", + "fileName": "eval line 7 > eval", + "lineNumber": 1, + "columnNumber": 8 } }, @@ -865,51 +760,18 @@ export default [ "type": "object", "class": "Error", "ownPropertyLength": 0, - "isError": false, + "isError": true, "extensible": false, "sealed": false, "frozen": false, "preview": { - "kind": "Object", - "ownProperties": { - "flavor": { - "configurable": true, - "enumerable": true, - "writable": true, - "value": "delicious" - }, - "name": { - "configurable": true, - "enumerable": true, - "writable": true, - "value": "JuicyError" - }, - "message": { - "configurable": true, - "enumerable": true, - "writable": true, - "value": "pineapple" - }, - "columnNumber": { - "configurable": true, - "enumerable": true, - "writable": true, - "value": 17 - }, - "lineNumber": { - "configurable": true, - "enumerable": true, - "writable": true, - "value": 2 - }, - "fileName": { - "configurable": true, - "enumerable": true, - "writable": true, - "value": "eval line 7 > eval" - } - }, - "ownPropertiesLength": 6 + "kind": "Error", + "name": "JuicyError", + "message": "pineapple", + "stack": "@eval line 7 > eval:2:17\n@eval:7:21\n", + "fileName": "eval line 7 > eval", + "lineNumber": 2, + "columnNumber": 17 } }, @@ -923,58 +785,18 @@ export default [ "type": "object", "class": "Error", "ownPropertyLength": 0, - "isError": false, + "isError": true, "extensible": false, "sealed": false, "frozen": false, "preview": { - "kind": "Object", - "ownProperties": { - "cause": { - "configurable": true, - "enumerable": true, - "writable": true, - "value": { - "type": "object", - "class": "SyntaxError", - "ownPropertyLength": 0, - "isError": false, - "extensible": false, - "sealed": false, - "frozen": false, - "preview": { - "kind": "Object", - "ownProperties": {}, - "ownPropertiesLength": 4 - } - } - }, - "message": { - "configurable": true, - "enumerable": true, - "writable": true, - "value": "something went wrong" - }, - "columnNumber": { - "configurable": true, - "enumerable": true, - "writable": true, - "value": 17 - }, - "lineNumber": { - "configurable": true, - "enumerable": true, - "writable": true, - "value": 3 - }, - "fileName": { - "configurable": true, - "enumerable": true, - "writable": true, - "value": "eval line 7 > eval" - } - }, - "ownPropertiesLength": 5 + "kind": "Error", + "name": "Error", + "message": "something went wrong", + "stack": "@eval line 7 > eval:3:17\n@eval:7:21\n", + "fileName": "eval line 7 > eval", + "lineNumber": 3, + "columnNumber": 17 } }, @@ -988,58 +810,18 @@ export default [ "type": "object", "class": "Error", "ownPropertyLength": 0, - "isError": false, + "isError": true, "extensible": false, "sealed": false, "frozen": false, "preview": { - "kind": "Object", - "ownProperties": { - "cause": { - "configurable": true, - "enumerable": true, - "writable": true, - "value": { - "type": "object", - "class": "Error", - "ownPropertyLength": 0, - "isError": false, - "extensible": false, - "sealed": false, - "frozen": false, - "preview": { - "kind": "Object", - "ownProperties": {}, - "ownPropertiesLength": 5 - } - } - }, - "message": { - "configurable": true, - "enumerable": true, - "writable": true, - "value": "err-d" - }, - "columnNumber": { - "configurable": true, - "enumerable": true, - "writable": true, - "value": 15 - }, - "lineNumber": { - "configurable": true, - "enumerable": true, - "writable": true, - "value": 5 - }, - "fileName": { - "configurable": true, - "enumerable": true, - "writable": true, - "value": "eval line 7 > eval" - } - }, - "ownPropertiesLength": 5 + "kind": "Error", + "name": "Error", + "message": "err-d", + "stack": "@eval line 7 > eval:5:15\n@eval:7:21\n", + "fileName": "eval line 7 > eval", + "lineNumber": 5, + "columnNumber": 15 } }, @@ -1051,58 +833,18 @@ export default [ "type": "object", "class": "Error", "ownPropertyLength": 0, - "isError": false, + "isError": true, "extensible": false, "sealed": false, "frozen": false, "preview": { - "kind": "Object", - "ownProperties": { - "cause": { - "configurable": true, - "enumerable": true, - "writable": true, - "value": { - "type": "object", - "class": "Error", - "ownPropertyLength": 0, - "isError": false, - "extensible": false, - "sealed": false, - "frozen": false, - "preview": { - "kind": "Object", - "ownProperties": {}, - "ownPropertiesLength": 5 - } - } - }, - "message": { - "configurable": true, - "enumerable": true, - "writable": true, - "value": "err-b" - }, - "columnNumber": { - "configurable": true, - "enumerable": true, - "writable": true, - "value": 15 - }, - "lineNumber": { - "configurable": true, - "enumerable": true, - "writable": true, - "value": 3 - }, - "fileName": { - "configurable": true, - "enumerable": true, - "writable": true, - "value": "eval line 7 > eval" - } - }, - "ownPropertiesLength": 5 + "kind": "Error", + "name": "Error", + "message": "err-b", + "stack": "@eval line 7 > eval:3:15\n@eval:7:21\n", + "fileName": "eval line 7 > eval", + "lineNumber": 3, + "columnNumber": 15 } }, @@ -1111,47 +853,18 @@ export default [ "type": "object", "class": "Error", "ownPropertyLength": 0, - "isError": false, + "isError": true, "extensible": false, "sealed": false, "frozen": false, "preview": { - "kind": "Object", - "ownProperties": { - "cause": { - "configurable": true, - "enumerable": true, - "writable": true, - "value": { - "type": "null" - } - }, - "message": { - "configurable": true, - "enumerable": true, - "writable": true, - "value": "null cause" - }, - "columnNumber": { - "configurable": true, - "enumerable": true, - "writable": true, - "value": 7 - }, - "lineNumber": { - "configurable": true, - "enumerable": true, - "writable": true, - "value": 1 - }, - "fileName": { - "configurable": true, - "enumerable": true, - "writable": true, - "value": "eval line 7 > eval" - } - }, - "ownPropertiesLength": 5 + "kind": "Error", + "name": "Error", + "message": "null cause", + "stack": "@eval line 7 > eval:1:7\n@eval:7:21\n", + "fileName": "eval line 7 > eval", + "lineNumber": 1, + "columnNumber": 7 } }, @@ -1160,45 +873,18 @@ export default [ "type": "object", "class": "Error", "ownPropertyLength": 0, - "isError": false, + "isError": true, "extensible": false, "sealed": false, "frozen": false, "preview": { - "kind": "Object", - "ownProperties": { - "cause": { - "configurable": true, - "enumerable": true, - "writable": true, - "value": 0 - }, - "message": { - "configurable": true, - "enumerable": true, - "writable": true, - "value": "number cause" - }, - "columnNumber": { - "configurable": true, - "enumerable": true, - "writable": true, - "value": 7 - }, - "lineNumber": { - "configurable": true, - "enumerable": true, - "writable": true, - "value": 1 - }, - "fileName": { - "configurable": true, - "enumerable": true, - "writable": true, - "value": "eval line 7 > eval" - } - }, - "ownPropertiesLength": 5 + "kind": "Error", + "name": "Error", + "message": "number cause", + "stack": "@eval line 7 > eval:1:7\n@eval:7:21\n", + "fileName": "eval line 7 > eval", + "lineNumber": 1, + "columnNumber": 7 } }, @@ -1207,45 +893,18 @@ export default [ "type": "object", "class": "Error", "ownPropertyLength": 0, - "isError": false, + "isError": true, "extensible": false, "sealed": false, "frozen": false, "preview": { - "kind": "Object", - "ownProperties": { - "cause": { - "configurable": true, - "enumerable": true, - "writable": true, - "value": "cause message" - }, - "message": { - "configurable": true, - "enumerable": true, - "writable": true, - "value": "string cause" - }, - "columnNumber": { - "configurable": true, - "enumerable": true, - "writable": true, - "value": 7 - }, - "lineNumber": { - "configurable": true, - "enumerable": true, - "writable": true, - "value": 1 - }, - "fileName": { - "configurable": true, - "enumerable": true, - "writable": true, - "value": "eval line 7 > eval" - } - }, - "ownPropertiesLength": 5 + "kind": "Error", + "name": "Error", + "message": "string cause", + "stack": "@eval line 7 > eval:1:7\n@eval:7:21\n", + "fileName": "eval line 7 > eval", + "lineNumber": 1, + "columnNumber": 7 } }, @@ -1257,58 +916,18 @@ export default [ "type": "object", "class": "Error", "ownPropertyLength": 0, - "isError": false, + "isError": true, "extensible": false, "sealed": false, "frozen": false, "preview": { - "kind": "Object", - "ownProperties": { - "cause": { - "configurable": true, - "enumerable": true, - "writable": true, - "value": { - "type": "object", - "class": "Object", - "ownPropertyLength": 0, - "isError": false, - "extensible": false, - "sealed": false, - "frozen": false, - "preview": { - "kind": "Object", - "ownProperties": {}, - "ownPropertiesLength": 2 - } - } - }, - "message": { - "configurable": true, - "enumerable": true, - "writable": true, - "value": "object cause" - }, - "columnNumber": { - "configurable": true, - "enumerable": true, - "writable": true, - "value": 13 - }, - "lineNumber": { - "configurable": true, - "enumerable": true, - "writable": true, - "value": 2 - }, - "fileName": { - "configurable": true, - "enumerable": true, - "writable": true, - "value": "eval line 7 > eval" - } - }, - "ownPropertiesLength": 5 + "kind": "Error", + "name": "Error", + "message": "object cause", + "stack": "@eval line 7 > eval:2:13\n@eval:7:21\n", + "fileName": "eval line 7 > eval", + "lineNumber": 2, + "columnNumber": 13 } }, diff --git a/tools/profiler/tests/browser/value_summary_reader.mjs b/tools/profiler/tests/browser/value_summary_reader.mjs @@ -36,12 +36,14 @@ const OBJECT_KIND_WRAPPED_PRIMITIVE_OBJECT = 4; const OBJECT_KIND_GENERIC_OBJECT = 5; const OBJECT_KIND_PROXY_OBJECT = 6; const OBJECT_KIND_EXTERNAL = 7; +const OBJECT_KIND_ERROR = 8; const MAX_COLLECTION_VALUES = 16; const EXTERNAL_SUMMARY_EXPECTED_VERSION = 1; const EXTERNAL_SUMMARY_KIND_OTHER = 0; const EXTERNAL_SUMMARY_KIND_NODE = 1; +const EXTERNAL_SUMMARY_KIND_EXCEPTION = 2; // const EXTERNAL_NODE_SUBKIND_OTHER = 0; (handled implicitly) const EXTERNAL_NODE_SUBKIND_ELEMENT = 1; @@ -344,6 +346,20 @@ function readNodeSummary(result, reader, depth, shapes) { result.preview = preview; } +function readExceptionSummary(result, reader, _depth, _shapes) { + result.class = "Error"; + const preview = {}; + preview.kind = "DOMException"; + preview.name = reader.readString(); + preview.message = reader.readString(); + preview.code = reader.readUint16(); + preview.result = reader.readUint32(); + preview.lineNumber = reader.readUint32(); + preview.columnNumber = reader.readUint32(); + preview.stack = reader.readString(); + result.preview = preview; +} + function readExternalObjectSummary(result, reader, depth, shapes) { readClassFromShape(result, reader, shapes); @@ -365,6 +381,10 @@ function readExternalObjectSummary(result, reader, depth, shapes) { readNodeSummary(result, reader, depth, shapes); break; } + case EXTERNAL_SUMMARY_KIND_EXCEPTION: { + readExceptionSummary(result, reader, depth, shapes); + break; + } default: } } finally { @@ -372,6 +392,28 @@ function readExternalObjectSummary(result, reader, depth, shapes) { } } +function readErrorObjectSummary(result, reader, depth, shapes) { + const shapeId = reader.readUint32(); + const shape = shapes[shapeId]; + + if (!shape || shape.length <= 0) { + return; + } + + const preview = {}; + result.type = "object"; + result.class = shape[0]; + result.isError = true; + preview.kind = "Error"; + preview.name = reader.readString(); + preview.message = reader.readString(); + preview.stack = reader.readString(); + preview.fileName = reader.readString(); + preview.lineNumber = reader.readUint32(); + preview.columnNumber = reader.readUint32(); + result.preview = preview; +} + function readObjectSummary(reader, flags, depth, shapes) { const result = { type: "object", @@ -400,6 +442,9 @@ function readObjectSummary(reader, flags, depth, shapes) { case OBJECT_KIND_EXTERNAL: readExternalObjectSummary(result, reader, depth, shapes); break; + case OBJECT_KIND_ERROR: + readErrorObjectSummary(result, reader, depth, shapes); + break; case OBJECT_KIND_WRAPPED_PRIMITIVE_OBJECT: { result.wrappedValue = readValueSummary(reader, depth, shapes); readGenericObjectSummary(result, reader, flags, depth, shapes);