@@ -23,76 +23,62 @@ static std::unordered_map<v8::Isolate *, ThreadInfo> threads = {};
2323
2424// Function to be called when an isolate's execution is interrupted
2525static void ExecutionInterrupted (Isolate *isolate, void *data) {
26- auto promise = static_cast <std::promise<Local<Array> > *>(data);
26+ auto promise = static_cast <std::promise<std::string > *>(data);
2727 auto stack = StackTrace::CurrentStackTrace (isolate, kMaxStackFrames ,
2828 StackTrace::kDetailed );
2929
3030 if (stack.IsEmpty ()) {
31- promise->set_value (Array::New (isolate, 0 ) );
31+ promise->set_value (" " );
3232 return ;
3333 }
3434
35- auto frames = Array::New (isolate, stack-> GetFrameCount ()) ;
35+ std::string stack_string ;
3636
3737 for (int i = 0 ; i < stack->GetFrameCount (); i++) {
3838 auto frame = stack->GetFrame (isolate, i);
3939 auto fn_name = frame->GetFunctionName ();
4040
41+ std::string function_name;
4142 if (frame->IsEval ()) {
42- fn_name =
43- String::NewFromUtf8 (isolate, " [eval]" , NewStringType::kInternalized )
44- .ToLocalChecked ();
43+ function_name = " [eval]" ;
4544 } else if (fn_name.IsEmpty () || fn_name->Length () == 0 ) {
46- fn_name = String::NewFromUtf8 (isolate, " ?" , NewStringType::kInternalized )
47- .ToLocalChecked ();
45+ function_name = " ?" ;
4846 } else if (frame->IsConstructor ()) {
49- fn_name = String::NewFromUtf8 (isolate, " [constructor]" ,
50- NewStringType::kInternalized )
51- .ToLocalChecked ();
47+ function_name = " [constructor]" ;
48+ } else {
49+ v8::String::Utf8Value utf8_fn (isolate, fn_name);
50+ function_name = *utf8_fn ? *utf8_fn : " ?" ;
5251 }
5352
54- auto frame_obj = Object::New (isolate);
55- frame_obj
56- ->Set (isolate->GetCurrentContext (),
57- String::NewFromUtf8 (isolate, " function" ,
58- NewStringType::kInternalized )
59- .ToLocalChecked (),
60- fn_name)
61- .Check ();
62-
63- frame_obj
64- ->Set (isolate->GetCurrentContext (),
65- String::NewFromUtf8 (isolate, " filename" ,
66- NewStringType::kInternalized )
67- .ToLocalChecked (),
68- frame->GetScriptName ())
69- .Check ();
70-
71- frame_obj
72- ->Set (
73- isolate->GetCurrentContext (),
74- String::NewFromUtf8 (isolate, " lineno" , NewStringType::kInternalized )
75- .ToLocalChecked (),
76- Integer::New (isolate, frame->GetLineNumber ()))
77- .Check ();
53+ std::string filename;
54+ auto script_name = frame->GetScriptName ();
55+ if (!script_name.IsEmpty ()) {
56+ v8::String::Utf8Value utf8_filename (isolate, script_name);
57+ filename = *utf8_filename ? *utf8_filename : " <unknown>" ;
58+ } else {
59+ filename = " <unknown>" ;
60+ }
7861
79- frame_obj
80- ->Set (
81- isolate->GetCurrentContext (),
82- String::NewFromUtf8 (isolate, " colno" , NewStringType::kInternalized )
83- .ToLocalChecked (),
84- Integer::New (isolate, frame->GetColumn ()))
85- .Check ();
62+ int line_number = frame->GetLineNumber ();
63+ int column_number = frame->GetColumn ();
64+
65+ // Build stack trace line in JavaScript format: " at functionName
66+ // (filename:line:column)"
67+ stack_string += " at " + function_name + " (" + filename + " :" +
68+ std::to_string (line_number) + " :" +
69+ std::to_string (column_number) + " )" ;
8670
87- frames->Set (isolate->GetCurrentContext (), i, frame_obj).Check ();
71+ if (i < stack->GetFrameCount () - 1 ) {
72+ stack_string += " \n " ;
73+ }
8874 }
8975
90- promise->set_value (frames );
76+ promise->set_value (stack_string );
9177}
9278
9379// Function to capture the stack trace of a single isolate
94- Local<Array> CaptureStackTrace (Isolate *isolate) {
95- std::promise<Local<Array> > promise;
80+ std::string CaptureStackTrace (Isolate *isolate) {
81+ std::promise<std::string > promise;
9682 auto future = promise.get_future ();
9783
9884 // The v8 isolate must be interrupted to capture the stack trace
@@ -105,7 +91,7 @@ Local<Array> CaptureStackTrace(Isolate *isolate) {
10591void CaptureStackTraces (const FunctionCallbackInfo<Value> &args) {
10692 auto capture_from_isolate = args.GetIsolate ();
10793
108- using ThreadResult = std::tuple<std::string, Local<Array> >;
94+ using ThreadResult = std::tuple<std::string, std::string >;
10995 std::vector<std::future<ThreadResult>> futures;
11096
11197 // We collect the futures into a vec so they can be processed in parallel
@@ -128,13 +114,17 @@ void CaptureStackTraces(const FunctionCallbackInfo<Value> &args) {
128114 // JavaScript object
129115 Local<Object> result = Object::New (capture_from_isolate);
130116 for (auto &future : futures) {
131- auto [thread_name, frames ] = future.get ();
117+ auto [thread_name, stack_string ] = future.get ();
132118
133119 auto key = String::NewFromUtf8 (capture_from_isolate, thread_name.c_str (),
134120 NewStringType::kNormal )
135121 .ToLocalChecked ();
136122
137- result->Set (capture_from_isolate->GetCurrentContext (), key, frames).Check ();
123+ auto value = String::NewFromUtf8 (capture_from_isolate, stack_string.c_str (),
124+ NewStringType::kNormal )
125+ .ToLocalChecked ();
126+
127+ result->Set (capture_from_isolate->GetCurrentContext (), key, value).Check ();
138128 }
139129
140130 args.GetReturnValue ().Set (result);
0 commit comments