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:
parent
d43c4a95ac
commit
b3e09e69a0
3 changed files with 72 additions and 0 deletions
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue