Skip to content

Commit 100fa76

Browse files
committed
Return JavaScript objects rather than json
1 parent 3be237b commit 100fa76

File tree

2 files changed

+47
-57
lines changed

2 files changed

+47
-57
lines changed

index.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@ const native = require('./build/release/cross-thread-stack-trace.node');
44
exports.registerThread = function () {
55
native.registerThread(isMainThread ? -1 : threadId );
66
};
7-
exports.captureStackTrace = function (excludeWorkers) {
8-
return JSON.parse(native.captureStackTrace(excludeWorkers));
7+
exports.captureStackTrace = function () {
8+
return native.captureStackTrace();
99
};

module.cc

Lines changed: 45 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
#include <node.h>
22
#include <mutex>
3-
#include <map>
4-
#include <sstream>
53
#include <future>
64

75
using namespace v8;
@@ -14,22 +12,18 @@ static std::unordered_map<v8::Isolate *, int> threads = {};
1412

1513
static void ExecutionInterrupted(Isolate *isolate, void *data)
1614
{
17-
auto promise = static_cast<std::promise<std::string> *>(data);
18-
19-
Local<StackTrace> stack = StackTrace::CurrentStackTrace(isolate, kMaxStackFrames, StackTrace::kDetailed);
15+
auto promise = static_cast<std::promise<Local<Array>> *>(data);
16+
auto stack = StackTrace::CurrentStackTrace(isolate, kMaxStackFrames, StackTrace::kDetailed);
2017

2118
if (stack.IsEmpty())
2219
{
23-
promise->set_value("[]");
20+
promise->set_value(Array::New(isolate, 0));
2421
return;
2522
}
2623

27-
std::ostringstream out;
28-
29-
out << "[";
30-
auto count = stack->GetFrameCount();
24+
auto frames = Array::New(isolate, stack->GetFrameCount());
3125

32-
for (auto i = 0; i < count; i++)
26+
for (int i = 0; i < stack->GetFrameCount(); i++)
3327
{
3428
auto frame = stack->GetFrame(isolate, i);
3529
auto fn_name = frame->GetFunctionName();
@@ -47,30 +41,36 @@ static void ExecutionInterrupted(Isolate *isolate, void *data)
4741
fn_name = String::NewFromUtf8(isolate, "[constructor]", NewStringType::kInternalized).ToLocalChecked();
4842
}
4943

50-
String::Utf8Value function_name(isolate, fn_name);
51-
String::Utf8Value script_name(isolate, frame->GetScriptName());
52-
auto line_number = frame->GetLineNumber();
53-
auto column = frame->GetColumn();
44+
auto frame_obj = Object::New(isolate);
45+
frame_obj->Set(isolate->GetCurrentContext(),
46+
String::NewFromUtf8(isolate, "function", NewStringType::kInternalized).ToLocalChecked(),
47+
fn_name)
48+
.Check();
5449

55-
out << "{\"function\":\"" << *function_name
56-
<< "\",\"filename\":\"" << *script_name
57-
<< "\",\"lineno\":" << line_number
58-
<< ",\"colno\":" << column << "}";
50+
frame_obj->Set(isolate->GetCurrentContext(),
51+
String::NewFromUtf8(isolate, "filename", NewStringType::kInternalized).ToLocalChecked(),
52+
frame->GetScriptName())
53+
.Check();
5954

60-
if (i < count - 1)
61-
{
62-
out << ",";
63-
}
64-
}
55+
frame_obj->Set(isolate->GetCurrentContext(),
56+
String::NewFromUtf8(isolate, "lineno", NewStringType::kInternalized).ToLocalChecked(),
57+
Integer::New(isolate, frame->GetLineNumber()))
58+
.Check();
59+
60+
frame_obj->Set(isolate->GetCurrentContext(),
61+
String::NewFromUtf8(isolate, "colno", NewStringType::kInternalized).ToLocalChecked(),
62+
Integer::New(isolate, frame->GetColumn()))
63+
.Check();
6564

66-
out << "]";
65+
frames->Set(isolate->GetCurrentContext(), i, frame_obj).Check();
66+
}
6767

68-
promise->set_value(out.str());
68+
promise->set_value(frames);
6969
}
7070

71-
std::string CaptureStackTrace(Isolate *isolate)
71+
Local<Array> CaptureStackTrace(Isolate *isolate)
7272
{
73-
std::promise<std::string> promise;
73+
std::promise<Local<Array>> promise;
7474
auto future = promise.get_future();
7575

7676
isolate->RequestInterrupt(ExecutionInterrupted, &promise);
@@ -81,37 +81,28 @@ void CaptureStackTraces(const FunctionCallbackInfo<Value> &args)
8181
{
8282
auto capture_from_isolate = args.GetIsolate();
8383

84-
std::vector<std::future<std::string>> futures;
84+
using ThreadResult = std::tuple<std::string, Local<Array>>;
85+
std::vector<std::future<ThreadResult>> futures;
8586

8687
std::lock_guard<std::mutex> lock(threads_mutex);
87-
for (auto &thread : threads)
88+
for (auto [thread_isolate, thread_id] : threads)
8889
{
89-
auto thread_isolate = thread.first;
90-
if (thread_isolate != capture_from_isolate)
91-
{
92-
int thread_id = thread.second;
93-
auto thread_name = thread_id == -1 ? "main" : "worker-" + std::to_string(thread_id);
94-
95-
futures.emplace_back(std::async(std::launch::async, [thread_name](Isolate *isolate)
96-
{ return "\"" + thread_name + "\":" + CaptureStackTrace(isolate); }, thread_isolate));
97-
}
90+
if (thread_isolate == capture_from_isolate)
91+
continue;
92+
auto thread_name = thread_id == -1 ? "main" : "worker-" + std::to_string(thread_id);
93+
futures.emplace_back(std::async(std::launch::async, [thread_name](Isolate *isolate) -> ThreadResult
94+
{ return std::make_tuple(thread_name, CaptureStackTrace(isolate)); }, thread_isolate));
9895
}
9996

100-
std::ostringstream out;
101-
102-
auto count = futures.size();
103-
out << "{";
97+
Local<Object> result = Object::New(capture_from_isolate);
10498
for (auto &future : futures)
10599
{
106-
out << future.get();
107-
if (--count > 0)
108-
{
109-
out << ",";
110-
}
100+
auto [thread_name, frames] = future.get();
101+
auto key = String::NewFromUtf8(capture_from_isolate, thread_name.c_str(), NewStringType::kNormal).ToLocalChecked();
102+
result->Set(capture_from_isolate->GetCurrentContext(), key, frames).Check();
111103
}
112-
out << "}";
113104

114-
args.GetReturnValue().Set(String::NewFromUtf8(capture_from_isolate, out.str().c_str(), NewStringType::kNormal).ToLocalChecked());
105+
args.GetReturnValue().Set(result);
115106
}
116107

117108
void Cleanup(void *arg)
@@ -131,7 +122,7 @@ void RegisterThread(const FunctionCallbackInfo<Value> &args)
131122
return;
132123
}
133124

134-
int thread_id = args[0].As<Number>()->Value();
125+
auto thread_id = args[0].As<Number>()->Value();
135126

136127
{
137128
std::lock_guard<std::mutex> lock(threads_mutex);
@@ -140,10 +131,9 @@ void RegisterThread(const FunctionCallbackInfo<Value> &args)
140131
node::AddEnvironmentCleanupHook(isolate, Cleanup, isolate);
141132
}
142133

143-
extern "C" NODE_MODULE_EXPORT void
144-
NODE_MODULE_INITIALIZER(Local<Object> exports,
145-
Local<Value> module,
146-
Local<Context> context)
134+
extern "C" NODE_MODULE_EXPORT void NODE_MODULE_INITIALIZER(Local<Object> exports,
135+
Local<Value> module,
136+
Local<Context> context)
147137
{
148138
auto isolate = context->GetIsolate();
149139

0 commit comments

Comments
 (0)