0
0
Fork 0
mirror of https://github.com/denoland/rusty_v8.git synced 2024-11-25 15:29:43 -05:00

stub out inspector APIs (#206)

This commit is contained in:
Bartek Iwańczuk 2020-01-17 00:12:25 +01:00 committed by Ry Dahl
parent 22bf9c6a39
commit f650abe44e
9 changed files with 360 additions and 104 deletions

View file

@ -1224,6 +1224,50 @@ void v8_inspector__V8Inspector__Channel__BASE__sendNotification(
v8_inspector::StringBuffer* message);
void v8_inspector__V8Inspector__Channel__BASE__flushProtocolNotifications(
v8_inspector::V8Inspector::Channel& self);
void v8_inspector__V8Inspector__DELETE(v8_inspector::V8Inspector& self) {
delete &self;
}
v8_inspector::V8Inspector* v8_inspector__V8Inspector__create(
v8::Isolate* isolate, v8_inspector::V8InspectorClient* client) {
std::unique_ptr<v8_inspector::V8Inspector> u =
v8_inspector::V8Inspector::create(isolate, client);
return u.release();
}
v8_inspector::V8InspectorSession* v8_inspector__V8Inspector__connect(
v8_inspector::V8Inspector& self, int context_group_id,
v8_inspector::V8Inspector::Channel* channel,
v8_inspector::StringView& state) {
std::unique_ptr<v8_inspector::V8InspectorSession> u =
self.connect(context_group_id, channel, state);
return u.release();
}
void v8_inspector__V8Inspector__contextCreated(
v8_inspector::V8Inspector& self, v8::Context* context, int contextGroupId,
v8_inspector::StringView& humanReadableName) {
self.contextCreated(v8_inspector::V8ContextInfo(
ptr_to_local(context), contextGroupId, humanReadableName));
}
void v8_inspector__V8InspectorSession__DELETE(
v8_inspector::V8InspectorSession& self) {
delete &self;
}
void v8_inspector__V8InspectorSession__dispatchProtocolMessage(
v8_inspector::V8InspectorSession& self,
v8_inspector::StringView& message) {
self.dispatchProtocolMessage(message);
}
void v8_inspector__V8InspectorSession__schedulePauseOnNextStatement(
v8_inspector::V8InspectorSession& self, v8_inspector::StringBuffer& reason,
v8_inspector::StringBuffer& detail) {
self.schedulePauseOnNextStatement(reason.string(), detail.string());
}
} // extern "C"
struct v8_inspector__V8Inspector__Channel__BASE

View file

@ -4,115 +4,55 @@ use crate::support::FieldOffset;
use crate::support::Opaque;
use crate::support::RustVTable;
// class V8InspectorClient {
// public:
// virtual ~V8InspectorClient() = default;
//
// virtual void runMessageLoopOnPause(int contextGroupId) {}
// virtual void quitMessageLoopOnPause() {}
// virtual void runIfWaitingForDebugger(int contextGroupId) {}
//
// virtual void muteMetrics(int contextGroupId) {}
// virtual void unmuteMetrics(int contextGroupId) {}
//
// virtual void beginUserGesture() {}
// virtual void endUserGesture() {}
//
// virtual std::unique_ptr<StringBuffer> valueSubtype(v8::Local<v8::Value>) {
// return nullptr;
// }
// virtual bool formatAccessorsAsProperties(v8::Local<v8::Value>) {
// return false;
// }
// virtual bool isInspectableHeapObject(v8::Local<v8::Object>) {
// return true;
// }
//
// virtual v8::Local<v8::Context> ensureDefaultContextInGroup(
// int contextGroupId) {
// return v8::Local<v8::Context>();
// }
// virtual void beginEnsureAllContextsInGroup(int contextGroupId) {}
// virtual void endEnsureAllContextsInGroup(int contextGroupId) {}
//
// virtual void installAdditionalCommandLineAPI(v8::Local<v8::Context>,
// v8::Local<v8::Object>) {}
// virtual void consoleAPIMessage(int contextGroupId,
// v8::Isolate::MessageErrorLevel level,
// const StringView& message,
// const StringView& url, unsigned lineNumber,
// unsigned columnNumber, V8StackTrace*) {}
// virtual v8::MaybeLocal<v8::Value> memoryInfo(v8::Isolate*,
// v8::Local<v8::Context>) {
// return v8::MaybeLocal<v8::Value>();
// }
//
// virtual void consoleTime(const StringView& title) {}
// virtual void consoleTimeEnd(const StringView& title) {}
// virtual void consoleTimeStamp(const StringView& title) {}
// virtual void consoleClear(int contextGroupId) {}
// virtual double currentTimeMS() { return 0; }
// typedef void (*TimerCallback)(void*);
// virtual void startRepeatingTimer(double, TimerCallback, void* data) {}
// virtual void cancelTimer(void* data) {}
//
// virtual bool canExecuteScripts(int contextGroupId) { return true; }
//
// virtual void maxAsyncCallStackDepthChanged(int depth) {}
//
// virtual std::unique_ptr<StringBuffer> resourceNameToUrl(
// const StringView& resourceName) {
// return nullptr;
// }
// };
extern "C" {
fn v8_inspector__V8InspectorClient__BASE__CONSTRUCT(
buf: &mut std::mem::MaybeUninit<Client>,
buf: &mut std::mem::MaybeUninit<V8InspectorClient>,
) -> ();
fn v8_inspector__V8InspectorClient__runMessageLoopOnPause(
this: &mut Client,
this: &mut V8InspectorClient,
context_group_id: int,
) -> ();
fn v8_inspector__V8InspectorClient__quitMessageLoopOnPause(
this: &mut Client,
this: &mut V8InspectorClient,
) -> ();
fn v8_inspector__V8InspectorClient__runIfWaitingForDebugger(
this: &mut Client,
this: &mut V8InspectorClient,
context_group_id: int,
) -> ();
}
#[no_mangle]
pub unsafe extern "C" fn v8_inspector__V8InspectorClient__BASE__runMessageLoopOnPause(
this: &mut Client,
this: &mut V8InspectorClient,
context_group_id: int,
) {
ClientBase::dispatch_mut(this).run_message_loop_on_pause(context_group_id)
V8InspectorClientBase::dispatch_mut(this)
.run_message_loop_on_pause(context_group_id)
}
#[no_mangle]
pub unsafe extern "C" fn v8_inspector__V8InspectorClient__BASE__quitMessageLoopOnPause(
this: &mut Client,
this: &mut V8InspectorClient,
) {
ClientBase::dispatch_mut(this).quit_message_loop_on_pause()
V8InspectorClientBase::dispatch_mut(this).quit_message_loop_on_pause()
}
#[no_mangle]
pub unsafe extern "C" fn v8_inspector__V8InspectorClient__BASE__runIfWaitingForDebugger(
this: &mut Client,
this: &mut V8InspectorClient,
context_group_id: int,
) {
ClientBase::dispatch_mut(this).run_if_waiting_for_debugger(context_group_id)
V8InspectorClientBase::dispatch_mut(this)
.run_if_waiting_for_debugger(context_group_id)
}
#[repr(C)]
pub struct Client {
pub struct V8InspectorClient {
_cxx_vtable: CxxVTable,
}
impl Client {
impl V8InspectorClient {
pub fn run_message_loop_on_pause(&mut self, context_group_id: int) {
unsafe {
v8_inspector__V8InspectorClient__runMessageLoopOnPause(
@ -134,65 +74,65 @@ impl Client {
}
}
pub trait AsClient {
fn as_client(&self) -> &Client;
fn as_client_mut(&mut self) -> &mut Client;
pub trait AsV8InspectorClient {
fn as_client(&self) -> &V8InspectorClient;
fn as_client_mut(&mut self) -> &mut V8InspectorClient;
}
impl AsClient for Client {
fn as_client(&self) -> &Client {
impl AsV8InspectorClient for V8InspectorClient {
fn as_client(&self) -> &V8InspectorClient {
self
}
fn as_client_mut(&mut self) -> &mut Client {
fn as_client_mut(&mut self) -> &mut V8InspectorClient {
self
}
}
impl<T> AsClient for T
impl<T> AsV8InspectorClient for T
where
T: ClientImpl,
T: V8InspectorClientImpl,
{
fn as_client(&self) -> &Client {
fn as_client(&self) -> &V8InspectorClient {
&self.base().cxx_base
}
fn as_client_mut(&mut self) -> &mut Client {
fn as_client_mut(&mut self) -> &mut V8InspectorClient {
&mut self.base_mut().cxx_base
}
}
#[allow(unused_variables)]
pub trait ClientImpl: AsClient {
fn base(&self) -> &ClientBase;
fn base_mut(&mut self) -> &mut ClientBase;
pub trait V8InspectorClientImpl: AsV8InspectorClient {
fn base(&self) -> &V8InspectorClientBase;
fn base_mut(&mut self) -> &mut V8InspectorClientBase;
fn run_message_loop_on_pause(&mut self, context_group_id: int) {}
fn quit_message_loop_on_pause(&mut self) {}
fn run_if_waiting_for_debugger(&mut self, context_group_id: int) {}
}
pub struct ClientBase {
cxx_base: Client,
pub struct V8InspectorClientBase {
cxx_base: V8InspectorClient,
offset_within_embedder: FieldOffset<Self>,
rust_vtable: RustVTable<&'static dyn ClientImpl>,
rust_vtable: RustVTable<&'static dyn V8InspectorClientImpl>,
}
impl ClientBase {
fn construct_cxx_base() -> Client {
impl V8InspectorClientBase {
fn construct_cxx_base() -> V8InspectorClient {
unsafe {
let mut buf = std::mem::MaybeUninit::<Client>::uninit();
let mut buf = std::mem::MaybeUninit::<V8InspectorClient>::uninit();
v8_inspector__V8InspectorClient__BASE__CONSTRUCT(&mut buf);
buf.assume_init()
}
}
fn get_cxx_base_offset() -> FieldOffset<Client> {
fn get_cxx_base_offset() -> FieldOffset<V8InspectorClient> {
let buf = std::mem::MaybeUninit::<Self>::uninit();
FieldOffset::from_ptrs(buf.as_ptr(), unsafe { &(*buf.as_ptr()).cxx_base })
}
fn get_offset_within_embedder<T>() -> FieldOffset<Self>
where
T: ClientImpl,
T: V8InspectorClientImpl,
{
let buf = std::mem::MaybeUninit::<T>::uninit();
let embedder_ptr: *const T = buf.as_ptr();
@ -200,13 +140,13 @@ impl ClientBase {
FieldOffset::from_ptrs(embedder_ptr, self_ptr)
}
fn get_rust_vtable<T>() -> RustVTable<&'static dyn ClientImpl>
fn get_rust_vtable<T>() -> RustVTable<&'static dyn V8InspectorClientImpl>
where
T: ClientImpl,
T: V8InspectorClientImpl,
{
let buf = std::mem::MaybeUninit::<T>::uninit();
let embedder_ptr = buf.as_ptr();
let trait_object: *const dyn ClientImpl = embedder_ptr;
let trait_object: *const dyn V8InspectorClientImpl = embedder_ptr;
let (data_ptr, vtable): (*const T, RustVTable<_>) =
unsafe { std::mem::transmute(trait_object) };
assert_eq!(data_ptr, embedder_ptr);
@ -215,7 +155,7 @@ impl ClientBase {
pub fn new<T>() -> Self
where
T: ClientImpl,
T: V8InspectorClientImpl,
{
Self {
cxx_base: Self::construct_cxx_base(),
@ -224,13 +164,17 @@ impl ClientBase {
}
}
pub unsafe fn dispatch(client: &Client) -> &dyn ClientImpl {
pub unsafe fn dispatch(
client: &V8InspectorClient,
) -> &dyn V8InspectorClientImpl {
let this = Self::get_cxx_base_offset().to_embedder::<Self>(client);
let embedder = this.offset_within_embedder.to_embedder::<Opaque>(this);
std::mem::transmute((embedder, this.rust_vtable))
}
pub unsafe fn dispatch_mut(client: &mut Client) -> &mut dyn ClientImpl {
pub unsafe fn dispatch_mut(
client: &mut V8InspectorClient,
) -> &mut dyn V8InspectorClientImpl {
let this = Self::get_cxx_base_offset().to_embedder_mut::<Self>(client);
let vtable = this.rust_vtable;
let embedder = this.offset_within_embedder.to_embedder_mut::<Opaque>(this);

View file

@ -1,9 +1,16 @@
mod channel;
mod client;
mod session;
mod string_buffer;
mod string_view;
mod v8_inspector;
pub use channel::Channel;
pub use client::Client;
pub use channel::{AsChannel, Channel, ChannelBase, ChannelImpl};
pub use client::AsV8InspectorClient;
pub use client::V8InspectorClient;
pub use client::V8InspectorClientBase;
pub use client::V8InspectorClientImpl;
pub use session::V8InspectorSession;
pub use string_buffer::StringBuffer;
pub use string_view::StringView;
pub use v8_inspector::V8Inspector;

50
src/inspector/session.rs Normal file
View file

@ -0,0 +1,50 @@
use super::StringBuffer;
use super::StringView;
use crate::support::Delete;
use crate::support::Opaque;
extern "C" {
fn v8_inspector__V8InspectorSession__DELETE(
this: &'static mut V8InspectorSession,
);
fn v8_inspector__V8InspectorSession__dispatchProtocolMessage(
session: *mut V8InspectorSession,
message: &StringView,
);
fn v8_inspector__V8InspectorSession__schedulePauseOnNextStatement(
session: *mut V8InspectorSession,
break_reason: *mut StringBuffer,
break_details: *mut StringBuffer,
);
}
#[repr(C)]
pub struct V8InspectorSession(Opaque);
impl V8InspectorSession {
pub fn dispatch_protocol_message(&mut self, message: &StringView) {
unsafe {
v8_inspector__V8InspectorSession__dispatchProtocolMessage(self, message)
}
}
pub fn schedule_pause_on_next_statement(
&mut self,
reason: &mut StringBuffer,
detail: &mut StringBuffer,
) {
unsafe {
v8_inspector__V8InspectorSession__schedulePauseOnNextStatement(
self,
&mut *reason,
&mut *detail,
)
}
}
}
impl Delete for V8InspectorSession {
fn delete(&'static mut self) {
unsafe { v8_inspector__V8InspectorSession__DELETE(self) };
}
}

View file

@ -52,3 +52,5 @@ impl Delete for StringBuffer {
unsafe { v8_inspector__StringBuffer__DELETE(self) }
}
}
unsafe impl Send for StringBuffer {}

View file

@ -0,0 +1,96 @@
use super::channel::AsChannel;
use super::client::AsV8InspectorClient;
use super::session::V8InspectorSession;
use super::Channel;
use super::StringView;
use super::V8InspectorClient;
use crate::support::int;
use crate::support::Delete;
use crate::support::Opaque;
use crate::support::UniqueRef;
use crate::Context;
use crate::Isolate;
use crate::Local;
extern "C" {
fn v8_inspector__V8Inspector__DELETE(this: &'static mut V8Inspector);
fn v8_inspector__V8Inspector__create(
isolate: *mut Isolate,
client: *mut V8InspectorClient,
) -> *mut V8Inspector;
fn v8_inspector__V8Inspector__connect(
inspector: *mut V8Inspector,
context_group_id: int,
channel: *mut Channel,
state: *const StringView,
) -> *mut V8InspectorSession;
fn v8_inspector__V8Inspector__contextCreated(
inspector: *mut V8Inspector,
context: *mut Context,
context_group_id: int,
human_readable_name: *const StringView,
);
}
#[repr(C)]
pub struct V8Inspector(Opaque);
impl V8Inspector {
pub fn create<T>(
isolate: &mut Isolate,
client: &mut T,
) -> UniqueRef<V8Inspector>
where
T: AsV8InspectorClient,
{
unsafe {
UniqueRef::from_raw(v8_inspector__V8Inspector__create(
isolate,
client.as_client_mut(),
))
}
}
pub fn connect<T>(
&mut self,
context_group_id: int,
channel: &mut T,
state: &StringView,
) -> UniqueRef<V8InspectorSession>
where
T: AsChannel,
{
unsafe {
UniqueRef::from_raw(v8_inspector__V8Inspector__connect(
self,
context_group_id,
channel.as_channel_mut(),
state,
))
}
}
/// Note: this method deviates from the C++ API here because it's a lot of
/// work to bind the V8ContextInfo, which is not used elsewhere.
pub fn context_created(
&mut self,
mut context: Local<Context>,
context_group_id: int,
human_readable_name: &StringView,
) {
unsafe {
v8_inspector__V8Inspector__contextCreated(
self,
&mut *context,
context_group_id,
human_readable_name,
)
}
}
}
impl Delete for V8Inspector {
fn delete(&'static mut self) {
unsafe { v8_inspector__V8Inspector__DELETE(self) };
}
}

View file

@ -115,8 +115,10 @@ pub use snapshot::OwnedStartupData;
pub use snapshot::SnapshotCreator;
pub use snapshot::StartupData;
pub use string::NewStringType;
pub use support::int;
pub use support::MaybeBool;
pub use support::SharedRef;
pub use support::UniquePtr;
pub use support::UniqueRef;
pub use try_catch::{TryCatch, TryCatchScope};

View file

@ -1,10 +1,11 @@
pub mod task;
pub use task::Task;
pub use task::{Task, TaskBase, TaskImpl};
use crate::support::Delete;
use crate::support::Opaque;
use crate::support::UniquePtr;
use crate::Isolate;
extern "C" {
// TODO: move this to libplatform.rs?
@ -26,3 +27,15 @@ impl Delete for Platform {
unsafe { v8__Platform__DELETE(self) }
}
}
impl Platform {
/// Pumps the message loop for the given isolate.
///
/// The caller has to make sure that this is called from the right thread.
/// Returns true if a task was executed, and false otherwise. Unless requested
/// through the |behavior| parameter, this call does not block if no task is
/// pending. The |platform| has to be created using |NewDefaultPlatform|.
pub fn pump_message_loop(_platform: &Self, _isolate: &Isolate) -> bool {
todo!()
}
}

View file

@ -2127,3 +2127,101 @@ fn try_from_local() {
context.exit();
}
}
#[test]
fn inspector_dispatch_protocol_message() {
let _g = setup();
let mut params = v8::Isolate::create_params();
params.set_array_buffer_allocator(v8::new_default_allocator());
let mut isolate = v8::Isolate::new(params);
let mut locker = v8::Locker::new(&isolate);
use v8::inspector::*;
struct Client {
base: V8InspectorClientBase,
}
impl Client {
fn new() -> Self {
Self {
base: V8InspectorClientBase::new::<Self>(),
}
}
}
impl V8InspectorClientImpl for Client {
fn base(&self) -> &V8InspectorClientBase {
&self.base
}
fn base_mut(&mut self) -> &mut V8InspectorClientBase {
&mut self.base
}
}
struct TestChannel {
base: ChannelBase,
send_response_count: usize,
send_notification_count: usize,
flush_protocol_notifications_count: usize,
}
impl TestChannel {
pub fn new() -> Self {
Self {
base: ChannelBase::new::<Self>(),
send_response_count: 0,
send_notification_count: 0,
flush_protocol_notifications_count: 0,
}
}
}
impl ChannelImpl for TestChannel {
fn base(&self) -> &ChannelBase {
&self.base
}
fn base_mut(&mut self) -> &mut ChannelBase {
&mut self.base
}
fn send_response(
&mut self,
_call_id: i32,
_message: v8::UniquePtr<StringBuffer>,
) {
self.send_response_count += 1;
}
fn send_notification(&mut self, _message: v8::UniquePtr<StringBuffer>) {
self.send_notification_count += 1;
}
fn flush_protocol_notifications(&mut self) {
self.flush_protocol_notifications_count += 1;
}
}
let mut hs = v8::HandleScope::new(&mut locker);
let scope = hs.enter();
let mut context = v8::Context::new(scope);
context.enter();
let mut default_client = Client::new();
let mut inspector = V8Inspector::create(&mut isolate, &mut default_client);
let name = b"";
let name_view = StringView::from(&name[..]);
inspector.context_created(context, 1, &name_view);
let mut channel = TestChannel::new();
let state = b"{}";
let state_view = StringView::from(&state[..]);
let mut session = inspector.connect(1, &mut channel, &state_view);
let message = String::from(
r#"{"id":1,"method":"Network.enable","params":{"maxPostDataSize":65536}}"#,
);
let message = &message.into_bytes()[..];
let string_view = StringView::from(message);
session.dispatch_protocol_message(&string_view);
assert_eq!(channel.send_response_count, 1);
assert_eq!(channel.send_notification_count, 0);
assert_eq!(channel.flush_protocol_notifications_count, 0);
context.exit();
}