2626constexpr  int  NODE_REPORT_VERSION = 2 ;
2727constexpr  int  NANOS_PER_SEC = 1000  * 1000  * 1000 ;
2828constexpr  double  SEC_PER_MICROS = 1e-6 ;
29+ constexpr  int  MAX_FRAME_COUNT = 10 ;
2930
3031namespace  node  {
3132namespace  report  {
@@ -43,6 +44,10 @@ using v8::Maybe;
4344using  v8::MaybeLocal;
4445using  v8::Nothing;
4546using  v8::Object;
47+ using  v8::RegisterState;
48+ using  v8::SampleInfo;
49+ using  v8::StackFrame;
50+ using  v8::StackTrace;
4651using  v8::String;
4752using  v8::TryCatch;
4853using  v8::V8;
@@ -62,6 +67,9 @@ static void PrintJavaScriptErrorStack(JSONWriter* writer,
6267                                      Isolate* isolate,
6368                                      Local<Value> error,
6469                                      const  char * trigger);
70+ static  void  PrintJavaScriptStack (JSONWriter* writer,
71+                                  Isolate* isolate,
72+                                  const  char * trigger);
6573static  void  PrintJavaScriptErrorProperties (JSONWriter* writer,
6674                                           Isolate* isolate,
6775                                           Local<Value> error);
@@ -269,8 +277,6 @@ static void WriteNodeReport(Isolate* isolate,
269277    //  Report summary JavaScript error stack backtrace
270278    PrintJavaScriptErrorStack (&writer, isolate, error, trigger);
271279
272-     //  Report summary JavaScript error properties backtrace
273-     PrintJavaScriptErrorProperties (&writer, isolate, error);
274280    writer.json_objectend ();  //  the end of 'javascriptStack'
275281
276282    //  Report V8 Heap and Garbage Collector information
@@ -317,7 +323,7 @@ static void WriteNodeReport(Isolate* isolate,
317323                      env,
318324                      " Worker thread subreport" 
319325                      trigger,
320-                       Local<Object >(),
326+                       Local<Value >(),
321327                      os);
322328
323329        Mutex::ScopedLock lock (workers_mutex);
@@ -534,19 +540,80 @@ static Maybe<std::string> ErrorToString(Isolate* isolate,
534540  return  Just<>(std::string (*sv, sv.length ()));
535541}
536542
543+ static  void  PrintEmptyJavaScriptStack (JSONWriter* writer) {
544+   writer->json_keyvalue (" message" " No stack." 
545+   writer->json_arraystart (" stack" 
546+   writer->json_element (" Unavailable." 
547+   writer->json_arrayend ();
548+ 
549+   writer->json_objectstart (" errorProperties" 
550+   writer->json_objectend ();
551+ }
552+ 
553+ //  Do our best to report the JavaScript stack without calling into JavaScript.
554+ static  void  PrintJavaScriptStack (JSONWriter* writer,
555+                                  Isolate* isolate,
556+                                  const  char * trigger) {
557+   //  Can not capture the stacktrace when the isolate is in a OOM state.
558+   if  (!strcmp (trigger, " OOMError" 
559+     PrintEmptyJavaScriptStack (writer);
560+     return ;
561+   }
562+ 
563+   HandleScope scope (isolate);
564+   RegisterState state;
565+   state.pc  = nullptr ;
566+   state.fp  = &state;
567+   state.sp  = &state;
568+ 
569+   //  in-out params
570+   SampleInfo info;
571+   void * samples[MAX_FRAME_COUNT];
572+   isolate->GetStackSample (state, samples, MAX_FRAME_COUNT, &info);
573+ 
574+   Local<StackTrace> stack = StackTrace::CurrentStackTrace (
575+       isolate, MAX_FRAME_COUNT, StackTrace::kDetailed );
576+ 
577+   if  (stack->GetFrameCount () == 0 ) {
578+     PrintEmptyJavaScriptStack (writer);
579+     return ;
580+   }
581+ 
582+   writer->json_keyvalue (" message" 
583+   writer->json_arraystart (" stack" 
584+   for  (int  i = 0 ; i < stack->GetFrameCount (); i++) {
585+     Local<StackFrame> frame = stack->GetFrame (isolate, i);
586+ 
587+     Utf8Value function_name (isolate, frame->GetFunctionName ());
588+     Utf8Value script_name (isolate, frame->GetScriptName ());
589+     const  int  line_number = frame->GetLineNumber ();
590+     const  int  column = frame->GetColumn ();
591+ 
592+     std::string stack_line = SPrintF (
593+         " at %s (%s:%d:%d)" 
594+     writer->json_element (stack_line);
595+   }
596+   writer->json_arrayend ();
597+   writer->json_objectstart (" errorProperties" 
598+   writer->json_objectend ();
599+ }
600+ 
537601//  Report the JavaScript stack.
538602static  void  PrintJavaScriptErrorStack (JSONWriter* writer,
539603                                      Isolate* isolate,
540604                                      Local<Value> error,
541605                                      const  char * trigger) {
606+   if  (error.IsEmpty ()) {
607+     return  PrintJavaScriptStack (writer, isolate, trigger);
608+   }
609+ 
542610  TryCatch try_catch (isolate);
543611  HandleScope scope (isolate);
544612  Local<Context> context = isolate->GetCurrentContext ();
545613  std::string ss = " " 
546-   if  ((!strcmp (trigger, " FatalError" 
547-       (!strcmp (trigger, " Signal" 
548-       (!ErrorToString (isolate, context, error).To (&ss))) {
549-     ss = " No stack.\n Unavailable.\n " 
614+   if  (!ErrorToString (isolate, context, error).To (&ss)) {
615+     PrintEmptyJavaScriptStack (writer);
616+     return ;
550617  }
551618
552619  int  line = ss.find (' \n ' 
@@ -569,6 +636,9 @@ static void PrintJavaScriptErrorStack(JSONWriter* writer,
569636    }
570637    writer->json_arrayend ();
571638  }
639+ 
640+   //  Report summary JavaScript error properties backtrace
641+   PrintJavaScriptErrorProperties (writer, isolate, error);
572642}
573643
574644//  Report a native stack backtrace
0 commit comments