tor-browser

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

commit 62ab9e5d620a2ecb6f83fda060198916817bf6ce
parent cc700d53c9a093f41795cdde8018846133291f4f
Author: Alexandre Poirot <poirot.alex@gmail.com>
Date:   Tue,  7 Oct 2025 20:50:05 +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 | 15++++++++++++++-
Mjs/src/debugger/ExecutionTracer.cpp | 71++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Mjs/src/debugger/ExecutionTracer.h | 5++++-
Mjs/src/jit-test/tests/debug/ExecutionTracer-traced-values.js | 3++-
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+++++++++++++++++++++++++++++++++++++++++++++
8 files changed, 324 insertions(+), 491 deletions(-)

diff --git a/js/public/Debug.h b/js/public/Debug.h @@ -178,7 +178,11 @@ 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; + // + // Keep in mind to update + // js/src/jit-test/tests/debug/ExecutionTracer-traced-values.js + // VALUE_SUMMARY_VERSION value. + 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 +257,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 +291,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 @@ -24,6 +24,7 @@ #include "js/RootingAPI.h" // JS::Rooted #include "js/Utility.h" // js_malloc, js_free #include "js/Value.h" // JS::Value +#include "vm/ErrorObject.h" // ErrorObject #include "vm/JSContext.h" // JSContext #include "vm/Stack.h" // js::AbstractFramePtr @@ -509,8 +510,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/src/jit-test/tests/debug/ExecutionTracer-traced-values.js b/js/src/jit-test/tests/debug/ExecutionTracer-traced-values.js @@ -1,6 +1,7 @@ if (typeof enableExecutionTracing == "undefined") { quit(); } +const VALUE_SUMMARY_VERSION = 2; const JSVAL_TYPE_DOUBLE = 0x00; const JSVAL_TYPE_INT32 = 0x01; @@ -167,7 +168,7 @@ g.disableExecutionTracing(); assertEq(trace.length, 1); let versionReader = new BufferReader(trace[0].valueBuffer, 0); -assertEq(versionReader.readUint32(), 1); +assertEq(versionReader.readUint32(), VALUE_SUMMARY_VERSION); function testSingleArgument(event, cb) { assertEq(typeof event.values, "number"); 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);