@@ -22,6 +22,7 @@ using v8::Integer;
22
22
using v8::Isolate;
23
23
using v8::KeyCollectionMode;
24
24
using v8::Local;
25
+ using v8::LocalVector;
25
26
using v8::Object;
26
27
using v8::ObjectTemplate;
27
28
using v8::ONLY_CONFIGURABLE;
@@ -254,12 +255,60 @@ static void ParseEnv(const FunctionCallbackInfo<Value>& args) {
254
255
args.GetReturnValue ().Set (dotenv.ToObject (env));
255
256
}
256
257
258
+ static void GetCallSite (const FunctionCallbackInfo<Value>& args) {
259
+ Environment* env = Environment::GetCurrent (args);
260
+ Isolate* isolate = env->isolate ();
261
+
262
+ CHECK_EQ (args.Length (), 1 );
263
+ CHECK (args[0 ]->IsNumber ());
264
+ const uint32_t frames = args[0 ].As <Uint32>()->Value ();
265
+ DCHECK (frames >= 1 && frames <= 200 );
266
+
267
+ // +1 for disregarding node:util
268
+ Local<StackTrace> stack = StackTrace::CurrentStackTrace (isolate, frames + 1 );
269
+ const int frame_count = stack->GetFrameCount ();
270
+ LocalVector<Value> callsite_objects (isolate);
271
+
272
+ // Frame 0 is node:util. It should be skipped.
273
+ for (int i = 1 ; i < frame_count; ++i) {
274
+ Local<Object> obj = Object::New (isolate);
275
+ Local<StackFrame> stack_frame = stack->GetFrame (isolate, i);
276
+
277
+ Utf8Value function_name (isolate, stack_frame->GetFunctionName ());
278
+ Utf8Value script_name (isolate, stack_frame->GetScriptName ());
279
+
280
+ obj->Set (env->context (),
281
+ env->function_name_string (),
282
+ String::NewFromUtf8 (isolate, *function_name).ToLocalChecked ())
283
+ .Check ();
284
+ obj->Set (env->context (),
285
+ env->script_name_string (),
286
+ String::NewFromUtf8 (isolate, *script_name).ToLocalChecked ())
287
+ .Check ();
288
+ obj->Set (env->context (),
289
+ env->line_number_string (),
290
+ Integer::NewFromUnsigned (isolate, stack_frame->GetLineNumber ()))
291
+ .Check ();
292
+ obj->Set (env->context (),
293
+ env->column_string (),
294
+ Integer::NewFromUnsigned (isolate, stack_frame->GetColumn ()))
295
+ .Check ();
296
+
297
+ callsite_objects.push_back (obj);
298
+ }
299
+
300
+ Local<Array> callsites =
301
+ Array::New (isolate, callsite_objects.data (), callsite_objects.size ());
302
+ args.GetReturnValue ().Set (callsites);
303
+ }
304
+
257
305
void RegisterExternalReferences (ExternalReferenceRegistry* registry) {
258
306
registry->Register (GetPromiseDetails);
259
307
registry->Register (GetProxyDetails);
260
308
registry->Register (GetCallerLocation);
261
309
registry->Register (IsArrayBufferDetached);
262
310
registry->Register (PreviewEntries);
311
+ registry->Register (GetCallSite);
263
312
registry->Register (GetOwnNonIndexProperties);
264
313
registry->Register (GetConstructorName);
265
314
registry->Register (GetExternalValue);
@@ -365,6 +414,7 @@ void Initialize(Local<Object> target,
365
414
SetMethodNoSideEffect (
366
415
context, target, " getConstructorName" , GetConstructorName);
367
416
SetMethodNoSideEffect (context, target, " getExternalValue" , GetExternalValue);
417
+ SetMethodNoSideEffect (context, target, " getCallSite" , GetCallSite);
368
418
SetMethod (context, target, " sleep" , Sleep);
369
419
SetMethod (context, target, " parseEnv" , ParseEnv);
370
420
0 commit comments