@@ -827,6 +827,11 @@ std::string HeapObject::Inspect(InspectOptions* options, Error& err) {
827827 return pre + m.Inspect (options, err);
828828 }
829829
830+ if (IsJSErrorType (err)) {
831+ JSError error (this );
832+ return pre + error.Inspect (options, err);
833+ }
834+
830835 if (JSObject::IsObjectType (v8 (), type)) {
831836 JSObject o (this );
832837 return pre + o.Inspect (options, err);
@@ -1495,22 +1500,31 @@ std::string JSObject::Inspect(InspectOptions* options, Error& err) {
14951500 int64_t constructor_type = constructor_obj.GetType (err);
14961501 if (err.Fail ()) return std::string ();
14971502
1503+ std::stringstream output;
14981504 if (constructor_type != v8 ()->types ()->kJSFunctionType ) {
1499- std::stringstream ss;
1500- ss << rang::fg::yellow << " <Object: no constructor >" << rang::fg::reset;
1501- return ss .str (). c_str ();
1505+ output << rang::fg::yellow << " <Object: " << rang::fg::gray
1506+ << " no constructor " << rang::fg::yellow << " >" << rang::fg::reset;
1507+ return output .str ();
15021508 }
15031509
15041510 JSFunction constructor (constructor_obj);
15051511
1506- std::string res = " <Object: " + constructor.Name (err);
1512+ output << rang::fg::yellow << " <Object: " << constructor.Name (err);
15071513 if (err.Fail ()) return std::string ();
15081514
1515+ output << InspectAllProperties (options, err) << rang::fg::yellow << " >"
1516+ << rang::fg::reset;
1517+ return output.str ();
1518+ }
1519+
1520+ std::string JSObject::InspectAllProperties (InspectOptions* options,
1521+ Error& err) {
1522+ std::string res = std::string ();
15091523 // Print properties in detailed mode
15101524 if (options->detailed ) {
15111525 std::stringstream ss;
15121526 ss << rang::fg::magenta << res << rang::fg::reset;
1513- res = ss.str (). c_str () ;
1527+ res = ss.str ();
15141528
15151529 res += " " + InspectProperties (err);
15161530 if (err.Fail ()) return std::string ();
@@ -1523,15 +1537,101 @@ std::string JSObject::Inspect(InspectOptions* options, Error& err) {
15231537 ss << rang::fg::magenta << " \n internal fields" << rang::fg::reset
15241538 << " {" << std::endl
15251539 << fields << " }" ;
1526- res += ss.str (). c_str () ;
1540+ res += ss.str ();
15271541 }
1528- return res + " > " ;
1542+ return res;
15291543 } else {
15301544 std::stringstream ss;
1531- ss << rang::fg::yellow << res << " > " << rang::fg::reset;
1532- res = ss.str (). c_str () ;
1545+ ss << rang::fg::yellow << res << rang::fg::reset;
1546+ res = ss.str ();
15331547 return res;
15341548 }
1549+
1550+ return res;
1551+ }
1552+
1553+ std::string JSError::InspectAllProperties (InspectOptions* options, Error& err) {
1554+ std::string res = JSObject::InspectAllProperties (options, err);
1555+ if (options->detailed ) {
1556+ InspectOptions simple;
1557+
1558+ // TODO (mmarchini): once we have Symbol support we'll need to search for
1559+ // <unnamed symbol>, since the stack symbol doesn't have an external name.
1560+ // In the future we can add postmortem metadata on V8 regarding existing
1561+ // symbols, but for now we'll use an heuristic to find the stack in the
1562+ // error object.
1563+ Value maybe_stack = GetProperty (" <non-string>" , err);
1564+
1565+ if (err.Fail ()) {
1566+ Error::PrintInDebugMode (
1567+ " Couldn't find a symbol property in the Error object." );
1568+ return res;
1569+ }
1570+
1571+ int64_t type = HeapObject (maybe_stack).GetType (err);
1572+
1573+ if (err.Fail ()) {
1574+ Error::PrintInDebugMode (" Symbol property references an invalid object." );
1575+ return res;
1576+ }
1577+
1578+ // NOTE (mmarchini): The stack is stored as a JSArray
1579+ if (type != v8 ()->types ()->kJSArrayType ) {
1580+ Error::PrintInDebugMode (" Symbol property doesn't have the right type." );
1581+ return res;
1582+ }
1583+
1584+ JSArray arr (maybe_stack);
1585+
1586+ Value maybe_stack_len = arr.GetArrayElement (0 , err);
1587+
1588+ if (err.Fail ()) {
1589+ Error::PrintInDebugMode (
1590+ " Couldn't get the first element from the stack array" );
1591+ return res;
1592+ }
1593+
1594+ int64_t stack_len = Smi (maybe_stack_len).GetValue ();
1595+
1596+ int multiplier = 5 ;
1597+ // On Node.js v8.x, the first array element is the stack size, and each
1598+ // stack frame use 5 elements.
1599+ if ((stack_len * multiplier + 1 ) != arr.GetArrayLength (err)) {
1600+ // On Node.js v6.x, the first array element is zero, and each stack frame
1601+ // use 4 element.
1602+ multiplier = 4 ;
1603+ if ((stack_len != 0 ) ||
1604+ ((arr.GetArrayLength (err) - 1 ) % multiplier != 0 )) {
1605+ Error::PrintInDebugMode (
1606+ " JSArray doesn't look like a Stack Frames array. stack_len: %lld "
1607+ " array_len: %lld" ,
1608+ stack_len, arr.GetArrayLength (err));
1609+ return res;
1610+ }
1611+ stack_len = (arr.GetArrayLength (err) - 1 ) / multiplier;
1612+ }
1613+
1614+ std::stringstream error_stack;
1615+ error_stack << std::endl
1616+ << rang::fg::red << " error stack" << rang::fg::reset << " {"
1617+ << std::endl;
1618+
1619+ // TODO (mmarchini): Refactor: create an StackIterator which returns
1620+ // StackFrame objects
1621+ for (int64_t i = 0 ; i < stack_len; i++) {
1622+ Value maybe_fn = arr.GetArrayElement (2 + (i * multiplier), err);
1623+ if (err.Fail ()) {
1624+ error_stack << rang::fg::gray << " <unknown>" << std::endl;
1625+ continue ;
1626+ }
1627+
1628+ error_stack << " " << HeapObject (maybe_fn).Inspect (&simple, err)
1629+ << std::endl;
1630+ }
1631+ error_stack << " }" ;
1632+ res += error_stack.str ();
1633+ }
1634+ return res;
15351635}
15361636
15371637
0 commit comments