0
0
Fork 0
mirror of https://github.com/denoland/rusty_v8.git synced 2024-11-21 15:04:33 -05:00

feat: v8::StackTrace::CurrentStackTrace() bindings (#800)

This commit is contained in:
Aaron O'Mullan 2021-12-28 16:52:12 +01:00 committed by GitHub
parent d43c4a95ac
commit b3e09e69a0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 72 additions and 0 deletions

View file

@ -1658,6 +1658,12 @@ const v8::Value* v8__ReturnValue__Get(const v8::ReturnValue<v8::Value>& self) {
return local_to_ptr(self.Get());
}
// Note: StackTraceOptions is deprecated, kDetailed is always used
const v8::StackTrace* v8__StackTrace__CurrentStackTrace(v8::Isolate* isolate,
int frame_limit) {
return local_to_ptr(v8::StackTrace::CurrentStackTrace(isolate, frame_limit));
}
int v8__StackTrace__GetFrameCount(const v8::StackTrace& self) {
return self.GetFrameCount();
}

View file

@ -1,5 +1,7 @@
#![allow(non_snake_case)]
use std::convert::TryInto;
use crate::isolate::Isolate;
use crate::support::int;
use crate::Context;
@ -32,6 +34,10 @@ extern "C" {
fn v8__Message__IsOpaque(this: *const Message) -> bool;
fn v8__Message__GetStackTrace(this: *const Message) -> *const StackTrace;
fn v8__StackTrace__CurrentStackTrace(
isolate: *mut Isolate,
frame_limit: int,
) -> *const StackTrace;
fn v8__StackTrace__GetFrameCount(this: *const StackTrace) -> int;
fn v8__StackTrace__GetFrame(
this: *const StackTrace,
@ -67,6 +73,19 @@ extern "C" {
}
impl StackTrace {
/// Grab a snapshot of the current JavaScript execution stack.
pub fn current_stack_trace<'s>(
scope: &mut HandleScope<'s>,
frame_limit: usize,
) -> Option<Local<'s, StackTrace>> {
let frame_limit = frame_limit.try_into().ok()?;
unsafe {
scope.cast_local(|sd| {
v8__StackTrace__CurrentStackTrace(sd.get_isolate_ptr(), frame_limit)
})
}
}
/// Returns the number of StackFrames.
pub fn get_frame_count(&self) -> usize {
unsafe { v8__StackTrace__GetFrameCount(self) as usize }

View file

@ -5675,3 +5675,50 @@ fn backing_store_from_empty_boxed_slice() {
.make_shared();
let _ = v8::ArrayBuffer::with_backing_store(&mut scope, &store);
}
#[test]
fn current_stack_trace() {
// Setup isolate
let isolate = &mut v8::Isolate::new(Default::default());
let scope = &mut v8::HandleScope::new(isolate);
let context = v8::Context::new(scope);
let scope = &mut v8::ContextScope::new(scope, context);
// A simple JS-facing function that returns its call depth, max of 5
fn call_depth(
scope: &mut v8::HandleScope,
_args: v8::FunctionCallbackArguments,
mut rv: v8::ReturnValue,
) {
let stack = v8::StackTrace::current_stack_trace(scope, 5).unwrap();
let count = stack.get_frame_count();
rv.set(v8::Integer::new(scope, count as i32).into())
}
let key = v8::String::new(scope, "callDepth").unwrap();
let tmpl = v8::FunctionTemplate::new(scope, call_depth);
let func = tmpl.get_function(scope).unwrap();
let global = context.global(scope);
global.set(scope, key.into(), func.into());
let top_level = eval(scope, "callDepth()")
.unwrap()
.uint32_value(scope)
.unwrap();
assert_eq!(top_level, 1);
let nested = eval(scope, "(_ => (_ => callDepth())())()")
.unwrap()
.uint32_value(scope)
.unwrap();
assert_eq!(nested, 3);
let too_deep = eval(
scope,
"(_ => (_ => (_ => (_ => (_ => (_ => (_ => callDepth())())())())())())())()",
)
.unwrap()
.uint32_value(scope)
.unwrap();
assert_eq!(too_deep, 5);
}