mirror of
https://github.com/denoland/rusty_v8.git
synced 2024-11-28 16:21:04 -05:00
Client binding + clean-ups
This commit is contained in:
parent
a291feb5f1
commit
7b8e882546
12 changed files with 307 additions and 191 deletions
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"C_Cpp.clang_format_style": "Chromium",
|
"C_Cpp.clang_format_style": "Chromium",
|
||||||
"files.associations": {
|
"files.associations": {
|
||||||
"memory": "cpp"
|
"memory": "cpp",
|
||||||
|
"vector": "cpp"
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1 +0,0 @@
|
||||||
testing
|
|
|
@ -2,6 +2,8 @@ use std::marker::PhantomData;
|
||||||
use std::mem::size_of;
|
use std::mem::size_of;
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
|
|
||||||
|
pub use std::os::raw::c_int as int;
|
||||||
|
|
||||||
pub type Opaque = [usize; 0];
|
pub type Opaque = [usize; 0];
|
||||||
|
|
||||||
pub trait Delete
|
pub trait Delete
|
||||||
|
|
|
@ -7,9 +7,6 @@
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include "../goog/v8/include/v8-inspector.h"
|
#include "../goog/v8/include/v8-inspector.h"
|
||||||
namespace v8_inspector {
|
|
||||||
using Channel = V8Inspector::Channel;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
using uninit_t = typename std::aligned_storage<sizeof(T), alignof(T)>::type;
|
using uninit_t = typename std::aligned_storage<sizeof(T), alignof(T)>::type;
|
||||||
|
@ -21,4 +18,5 @@ auto launder(T ptr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "v8_inspector/channel.h"
|
#include "v8_inspector/channel.h"
|
||||||
|
#include "v8_inspector/client.h"
|
||||||
#include "v8_inspector/string_buffer.h"
|
#include "v8_inspector/string_buffer.h"
|
||||||
|
|
|
@ -33,7 +33,7 @@ mod example {
|
||||||
message.as_mut().unwrap().string().characters16().unwrap()
|
message.as_mut().unwrap().string().characters16().unwrap()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
fn sendNotification(&mut self, message: UniquePtr<StringBuffer>) {}
|
fn sendNotification(&mut self, _message: UniquePtr<StringBuffer>) {}
|
||||||
fn flushProtocolNotifications(&mut self) {}
|
fn flushProtocolNotifications(&mut self) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
using namespace v8_inspector;
|
using namespace v8_inspector;
|
||||||
|
using Channel = V8Inspector::Channel;
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
void v8_inspector__Channel__EXTENDER__sendResponse(Channel& self,
|
void v8_inspector__Channel__EXTENDER__sendResponse(Channel& self,
|
||||||
int callId,
|
int callId,
|
||||||
StringBuffer* message);
|
StringBuffer* message);
|
||||||
|
@ -33,8 +34,6 @@ struct Channel__EXTENDER : public Channel {
|
||||||
} // namespace v8_inspector
|
} // namespace v8_inspector
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
using namespace v8_inspector;
|
|
||||||
|
|
||||||
void v8_inspector__Channel__EXTENDER__CTOR(uninit_t<Channel__EXTENDER>& buf) {
|
void v8_inspector__Channel__EXTENDER__CTOR(uninit_t<Channel__EXTENDER>& buf) {
|
||||||
new (launder(&buf)) Channel__EXTENDER();
|
new (launder(&buf)) Channel__EXTENDER();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
use std::os::raw::c_int;
|
use crate::cxx_util::int;
|
||||||
|
|
||||||
use crate::cxx_util::CxxVTable;
|
use crate::cxx_util::CxxVTable;
|
||||||
use crate::cxx_util::FieldOffset;
|
use crate::cxx_util::FieldOffset;
|
||||||
use crate::cxx_util::Opaque;
|
use crate::cxx_util::Opaque;
|
||||||
|
@ -25,7 +24,7 @@ extern "C" {
|
||||||
|
|
||||||
fn v8_inspector__Channel__sendResponse(
|
fn v8_inspector__Channel__sendResponse(
|
||||||
this: &mut Channel,
|
this: &mut Channel,
|
||||||
callId: c_int,
|
callId: int,
|
||||||
message: UniquePtr<StringBuffer>,
|
message: UniquePtr<StringBuffer>,
|
||||||
) -> ();
|
) -> ();
|
||||||
fn v8_inspector__Channel__sendNotification(
|
fn v8_inspector__Channel__sendNotification(
|
||||||
|
@ -40,7 +39,7 @@ extern "C" {
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn v8_inspector__Channel__EXTENDER__sendResponse(
|
pub unsafe extern "C" fn v8_inspector__Channel__EXTENDER__sendResponse(
|
||||||
this: &mut Channel,
|
this: &mut Channel,
|
||||||
callId: c_int,
|
callId: int,
|
||||||
message: UniquePtr<StringBuffer>,
|
message: UniquePtr<StringBuffer>,
|
||||||
) -> () {
|
) -> () {
|
||||||
ChannelExtender::dispatch_mut(this).sendResponse(callId, message)
|
ChannelExtender::dispatch_mut(this).sendResponse(callId, message)
|
||||||
|
@ -69,7 +68,7 @@ pub struct Channel {
|
||||||
impl Channel {
|
impl Channel {
|
||||||
pub fn sendResponse(
|
pub fn sendResponse(
|
||||||
&mut self,
|
&mut self,
|
||||||
callId: c_int,
|
callId: int,
|
||||||
message: UniquePtr<StringBuffer>,
|
message: UniquePtr<StringBuffer>,
|
||||||
) -> () {
|
) -> () {
|
||||||
unsafe { v8_inspector__Channel__sendResponse(self, callId, message) }
|
unsafe { v8_inspector__Channel__sendResponse(self, callId, message) }
|
||||||
|
@ -120,7 +119,7 @@ pub trait ChannelOverrides: AsChannel {
|
||||||
|
|
||||||
fn sendResponse(
|
fn sendResponse(
|
||||||
&mut self,
|
&mut self,
|
||||||
callId: i32,
|
callId: int,
|
||||||
message: UniquePtr<StringBuffer>,
|
message: UniquePtr<StringBuffer>,
|
||||||
) -> ();
|
) -> ();
|
||||||
fn sendNotification(&mut self, message: UniquePtr<StringBuffer>) -> ();
|
fn sendNotification(&mut self, message: UniquePtr<StringBuffer>) -> ();
|
||||||
|
|
|
@ -1,176 +0,0 @@
|
||||||
use crate::cxx_util::FieldOffset;
|
|
||||||
use crate::cxx_util::Opaque;
|
|
||||||
use crate::cxx_util::RustVTable;
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
// Call a method/destructor; virtual methods use C++ dynamic dispatch.
|
|
||||||
fn v8_inspector__Channel__DTOR(this: &mut Channel) -> ();
|
|
||||||
fn v8_inspector__Channel__method1(this: &mut Channel, arg: i32) -> ();
|
|
||||||
fn v8_inspector__Channel__method2(this: &Channel) -> i32;
|
|
||||||
|
|
||||||
// Call a method of a specific class implementation, bypassing dynamic
|
|
||||||
// dispatch. C++ equivalent: `my_channel.Channel::a()`.
|
|
||||||
fn v8_inspector__Channel__Channel__method1(
|
|
||||||
this: &mut Channel,
|
|
||||||
arg: i32,
|
|
||||||
) -> ();
|
|
||||||
|
|
||||||
// Constructs a special class derived from Channel that forwards all
|
|
||||||
// virtual method invocations to rust. It is assumed that this subclass
|
|
||||||
// has the same size and memory layout as the class it's deriving from.
|
|
||||||
fn v8_inspector__Channel__EXTENDER__CTOR(
|
|
||||||
buf: &mut std::mem::MaybeUninit<Channel>,
|
|
||||||
) -> ();
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(non_snake_case)]
|
|
||||||
#[no_mangle]
|
|
||||||
pub unsafe extern "C" fn v8_inspector__Channel__EXTENDER__method1(
|
|
||||||
this: &mut Channel,
|
|
||||||
arg: i32,
|
|
||||||
) {
|
|
||||||
ChannelExtender::dispatch_mut(this).method1(arg)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(non_snake_case)]
|
|
||||||
#[no_mangle]
|
|
||||||
pub unsafe extern "C" fn v8_inspector__Channel__EXTENDER__method2(
|
|
||||||
this: &Channel,
|
|
||||||
) -> i32 {
|
|
||||||
ChannelExtender::dispatch(this).method2()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[repr(C)]
|
|
||||||
pub struct Channel {
|
|
||||||
_cxx_vtable: *const Opaque,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Channel {
|
|
||||||
pub fn method1(&mut self, arg: i32) {
|
|
||||||
unsafe { v8_inspector__Channel__method1(self, arg) }
|
|
||||||
}
|
|
||||||
pub fn method2(&self) -> i32 {
|
|
||||||
unsafe { v8_inspector__Channel__method2(self) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Drop for Channel {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
unsafe { v8_inspector__Channel__DTOR(self) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait AsChannel {
|
|
||||||
fn as_channel(&self) -> &Channel;
|
|
||||||
fn as_channel_mut(&mut self) -> &mut Channel;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AsChannel for Channel {
|
|
||||||
fn as_channel(&self) -> &Channel {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
fn as_channel_mut(&mut self) -> &mut Channel {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> AsChannel for T
|
|
||||||
where
|
|
||||||
T: ChannelOverrides,
|
|
||||||
{
|
|
||||||
fn as_channel(&self) -> &Channel {
|
|
||||||
&self.extender().cxx_channel
|
|
||||||
}
|
|
||||||
fn as_channel_mut(&mut self) -> &mut Channel {
|
|
||||||
&mut self.extender_mut().cxx_channel
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct ChannelDefaults;
|
|
||||||
impl ChannelDefaults {
|
|
||||||
pub fn method1(channel: &mut Channel, arg: i32) {
|
|
||||||
unsafe { v8_inspector__Channel__Channel__method1(channel, arg) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait ChannelOverrides: AsChannel {
|
|
||||||
fn extender(&self) -> &ChannelExtender;
|
|
||||||
fn extender_mut(&mut self) -> &mut ChannelExtender;
|
|
||||||
|
|
||||||
fn method1(&mut self, arg: i32) {
|
|
||||||
ChannelDefaults::method1(self.as_channel_mut(), arg)
|
|
||||||
}
|
|
||||||
fn method2(&self) -> i32;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct ChannelExtender {
|
|
||||||
cxx_channel: Channel,
|
|
||||||
extender_offset: FieldOffset<Self>,
|
|
||||||
rust_vtable: RustVTable<&'static dyn ChannelOverrides>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ChannelExtender {
|
|
||||||
fn construct_cxx_channel() -> Channel {
|
|
||||||
unsafe {
|
|
||||||
let mut buf = std::mem::MaybeUninit::<Channel>::uninit();
|
|
||||||
v8_inspector__Channel__EXTENDER__CTOR(&mut buf);
|
|
||||||
buf.assume_init()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_extender_offset<T>() -> FieldOffset<Self>
|
|
||||||
where
|
|
||||||
T: ChannelOverrides,
|
|
||||||
{
|
|
||||||
let buf = std::mem::MaybeUninit::<T>::uninit();
|
|
||||||
let embedder_ptr: *const T = buf.as_ptr();
|
|
||||||
let self_ptr: *const Self = unsafe { (*embedder_ptr).extender() };
|
|
||||||
FieldOffset::from_ptrs(embedder_ptr, self_ptr)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_rust_vtable<T>() -> RustVTable<&'static dyn ChannelOverrides>
|
|
||||||
where
|
|
||||||
T: ChannelOverrides,
|
|
||||||
{
|
|
||||||
let buf = std::mem::MaybeUninit::<T>::uninit();
|
|
||||||
let embedder_ptr = buf.as_ptr();
|
|
||||||
let trait_object: *const dyn ChannelOverrides = embedder_ptr;
|
|
||||||
let (data_ptr, vtable): (*const T, RustVTable<_>) =
|
|
||||||
unsafe { std::mem::transmute(trait_object) };
|
|
||||||
assert_eq!(data_ptr, embedder_ptr);
|
|
||||||
vtable
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new<T>() -> Self
|
|
||||||
where
|
|
||||||
T: ChannelOverrides,
|
|
||||||
{
|
|
||||||
Self {
|
|
||||||
cxx_channel: Self::construct_cxx_channel(),
|
|
||||||
extender_offset: Self::get_extender_offset::<T>(),
|
|
||||||
rust_vtable: Self::get_rust_vtable::<T>(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_channel_offset() -> FieldOffset<Channel> {
|
|
||||||
let buf = std::mem::MaybeUninit::<Self>::uninit();
|
|
||||||
FieldOffset::from_ptrs(buf.as_ptr(), unsafe {
|
|
||||||
&(*buf.as_ptr()).cxx_channel
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub unsafe fn dispatch(channel: &Channel) -> &dyn ChannelOverrides {
|
|
||||||
let this = Self::get_channel_offset().to_embedder::<Self>(channel);
|
|
||||||
let embedder = this.extender_offset.to_embedder::<Opaque>(this);
|
|
||||||
std::mem::transmute((embedder, this.rust_vtable))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub unsafe fn dispatch_mut(
|
|
||||||
channel: &mut Channel,
|
|
||||||
) -> &mut dyn ChannelOverrides {
|
|
||||||
let this = Self::get_channel_offset().to_embedder_mut::<Self>(channel);
|
|
||||||
let vtable = this.rust_vtable;
|
|
||||||
let embedder = this.extender_offset.to_embedder_mut::<Opaque>(this);
|
|
||||||
std::mem::transmute((embedder, vtable))
|
|
||||||
}
|
|
||||||
}
|
|
54
src/v8_inspector/client.h
Normal file
54
src/v8_inspector/client.h
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
#include <memory>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
using namespace v8_inspector;
|
||||||
|
using Client = V8InspectorClient;
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
void v8_inspector__Client__EXTENDER__runMessageLoopOnPause(Client& self,
|
||||||
|
int contextGroupId);
|
||||||
|
void v8_inspector__Client__EXTENDER__quitMessageLoopOnPause(Client& self);
|
||||||
|
void v8_inspector__Client__EXTENDER__runIfWaitingForDebugger(
|
||||||
|
Client& self,
|
||||||
|
int contextGroupId);
|
||||||
|
|
||||||
|
} // extern "C"
|
||||||
|
|
||||||
|
namespace v8_inspector {
|
||||||
|
struct Client__EXTENDER : public Client {
|
||||||
|
using Client::Client;
|
||||||
|
|
||||||
|
void runMessageLoopOnPause(int contextGroupId) override {
|
||||||
|
v8_inspector__Client__EXTENDER__runMessageLoopOnPause(*this,
|
||||||
|
contextGroupId);
|
||||||
|
}
|
||||||
|
void quitMessageLoopOnPause() override {
|
||||||
|
v8_inspector__Client__EXTENDER__quitMessageLoopOnPause(*this);
|
||||||
|
}
|
||||||
|
void runIfWaitingForDebugger(int contextGroupId) override {
|
||||||
|
v8_inspector__Client__EXTENDER__runIfWaitingForDebugger(*this,
|
||||||
|
contextGroupId);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // namespace v8_inspector
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
void v8_inspector__Client__EXTENDER__CTOR(uninit_t<Client__EXTENDER>& buf) {
|
||||||
|
new (launder(&buf)) Client__EXTENDER();
|
||||||
|
}
|
||||||
|
void v8_inspector__Client__DTOR(Client& self) {
|
||||||
|
self.~Client();
|
||||||
|
}
|
||||||
|
|
||||||
|
void v8_inspector__Client__runMessageLoopOnPause(Client& self,
|
||||||
|
int contextGroupId) {
|
||||||
|
self.runMessageLoopOnPause(contextGroupId);
|
||||||
|
}
|
||||||
|
void v8_inspector__Client__quitMessageLoopOnPause(Client& self) {
|
||||||
|
self.quitMessageLoopOnPause();
|
||||||
|
}
|
||||||
|
void v8_inspector__Client__runIfWaitingForDebugger(Client& self,
|
||||||
|
int contextGroupId) {
|
||||||
|
self.runIfWaitingForDebugger(contextGroupId);
|
||||||
|
}
|
||||||
|
} // extern "C"
|
|
@ -0,0 +1,236 @@
|
||||||
|
use crate::cxx_util::int;
|
||||||
|
use crate::cxx_util::CxxVTable;
|
||||||
|
use crate::cxx_util::FieldOffset;
|
||||||
|
use crate::cxx_util::Opaque;
|
||||||
|
use crate::cxx_util::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__Client__EXTENDER__CTOR(
|
||||||
|
buf: &mut std::mem::MaybeUninit<Client>,
|
||||||
|
) -> ();
|
||||||
|
fn v8_inspector__Client__DTOR(this: &mut Client) -> ();
|
||||||
|
|
||||||
|
fn v8_inspector__Client__runMessageLoopOnPause(
|
||||||
|
this: &mut Client,
|
||||||
|
contextGroupId: int,
|
||||||
|
) -> ();
|
||||||
|
fn v8_inspector__Client__quitMessageLoopOnPause(this: &mut Client) -> ();
|
||||||
|
fn v8_inspector__Client__runIfWaitingForDebugger(
|
||||||
|
this: &mut Client,
|
||||||
|
contextGroupId: int,
|
||||||
|
) -> ();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn v8_inspector__Client__EXTENDER__runMessageLoopOnPause(
|
||||||
|
this: &mut Client,
|
||||||
|
contextGroupId: int,
|
||||||
|
) -> () {
|
||||||
|
ClientExtender::dispatch_mut(this).runMessageLoopOnPause(contextGroupId)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn v8_inspector__Client__EXTENDER__quitMessageLoopOnPause(
|
||||||
|
this: &mut Client,
|
||||||
|
) -> () {
|
||||||
|
ClientExtender::dispatch_mut(this).quitMessageLoopOnPause()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn v8_inspector__Client__EXTENDER__runIfWaitingForDebugger(
|
||||||
|
this: &mut Client,
|
||||||
|
contextGroupId: int,
|
||||||
|
) -> () {
|
||||||
|
ClientExtender::dispatch_mut(this).runIfWaitingForDebugger(contextGroupId)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct Client {
|
||||||
|
_cxx_vtable: CxxVTable,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Client {
|
||||||
|
pub fn runMessageLoopOnPause(&mut self, contextGroupId: int) -> () {
|
||||||
|
unsafe { v8_inspector__Client__runMessageLoopOnPause(self, contextGroupId) }
|
||||||
|
}
|
||||||
|
pub fn quitMessageLoopOnPause(&mut self) -> () {
|
||||||
|
unsafe { v8_inspector__Client__quitMessageLoopOnPause(self) }
|
||||||
|
}
|
||||||
|
pub fn runIfWaitingForDebugger(&mut self, contextGroupId: int) -> () {
|
||||||
|
unsafe {
|
||||||
|
v8_inspector__Client__runIfWaitingForDebugger(self, contextGroupId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for Client {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
unsafe { v8_inspector__Client__DTOR(self) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait AsClient {
|
||||||
|
fn as_client(&self) -> &Client;
|
||||||
|
fn as_client_mut(&mut self) -> &mut Client;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsClient for Client {
|
||||||
|
fn as_client(&self) -> &Client {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
fn as_client_mut(&mut self) -> &mut Client {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> AsClient for T
|
||||||
|
where
|
||||||
|
T: ClientOverrides,
|
||||||
|
{
|
||||||
|
fn as_client(&self) -> &Client {
|
||||||
|
&self.extender().cxx_client
|
||||||
|
}
|
||||||
|
fn as_client_mut(&mut self) -> &mut Client {
|
||||||
|
&mut self.extender_mut().cxx_client
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(unused_variables)]
|
||||||
|
pub trait ClientOverrides: AsClient {
|
||||||
|
fn extender(&self) -> &ClientExtender;
|
||||||
|
fn extender_mut(&mut self) -> &mut ClientExtender;
|
||||||
|
|
||||||
|
fn runMessageLoopOnPause(&mut self, contextGroupId: int) -> () {}
|
||||||
|
fn quitMessageLoopOnPause(&mut self) -> () {}
|
||||||
|
fn runIfWaitingForDebugger(&mut self, contextGroupId: int) -> () {}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ClientExtender {
|
||||||
|
cxx_client: Client,
|
||||||
|
extender_offset: FieldOffset<Self>,
|
||||||
|
rust_vtable: RustVTable<&'static dyn ClientOverrides>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ClientExtender {
|
||||||
|
fn construct_cxx_client() -> Client {
|
||||||
|
unsafe {
|
||||||
|
let mut buf = std::mem::MaybeUninit::<Client>::uninit();
|
||||||
|
v8_inspector__Client__EXTENDER__CTOR(&mut buf);
|
||||||
|
buf.assume_init()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_extender_offset<T>() -> FieldOffset<Self>
|
||||||
|
where
|
||||||
|
T: ClientOverrides,
|
||||||
|
{
|
||||||
|
let buf = std::mem::MaybeUninit::<T>::uninit();
|
||||||
|
let embedder_ptr: *const T = buf.as_ptr();
|
||||||
|
let self_ptr: *const Self = unsafe { (*embedder_ptr).extender() };
|
||||||
|
FieldOffset::from_ptrs(embedder_ptr, self_ptr)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_rust_vtable<T>() -> RustVTable<&'static dyn ClientOverrides>
|
||||||
|
where
|
||||||
|
T: ClientOverrides,
|
||||||
|
{
|
||||||
|
let buf = std::mem::MaybeUninit::<T>::uninit();
|
||||||
|
let embedder_ptr = buf.as_ptr();
|
||||||
|
let trait_object: *const dyn ClientOverrides = embedder_ptr;
|
||||||
|
let (data_ptr, vtable): (*const T, RustVTable<_>) =
|
||||||
|
unsafe { std::mem::transmute(trait_object) };
|
||||||
|
assert_eq!(data_ptr, embedder_ptr);
|
||||||
|
vtable
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new<T>() -> Self
|
||||||
|
where
|
||||||
|
T: ClientOverrides,
|
||||||
|
{
|
||||||
|
Self {
|
||||||
|
cxx_client: Self::construct_cxx_client(),
|
||||||
|
extender_offset: Self::get_extender_offset::<T>(),
|
||||||
|
rust_vtable: Self::get_rust_vtable::<T>(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_client_offset() -> FieldOffset<Client> {
|
||||||
|
let buf = std::mem::MaybeUninit::<Self>::uninit();
|
||||||
|
FieldOffset::from_ptrs(buf.as_ptr(), unsafe { &(*buf.as_ptr()).cxx_client })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn dispatch(client: &Client) -> &dyn ClientOverrides {
|
||||||
|
let this = Self::get_client_offset().to_embedder::<Self>(client);
|
||||||
|
let embedder = this.extender_offset.to_embedder::<Opaque>(this);
|
||||||
|
std::mem::transmute((embedder, this.rust_vtable))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn dispatch_mut(client: &mut Client) -> &mut dyn ClientOverrides {
|
||||||
|
let this = Self::get_client_offset().to_embedder_mut::<Self>(client);
|
||||||
|
let vtable = this.rust_vtable;
|
||||||
|
let embedder = this.extender_offset.to_embedder_mut::<Opaque>(this);
|
||||||
|
std::mem::transmute((embedder, vtable))
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,9 @@
|
||||||
pub mod channel;
|
pub mod channel;
|
||||||
|
pub mod client;
|
||||||
pub mod string_buffer;
|
pub mod string_buffer;
|
||||||
pub mod string_view;
|
pub mod string_view;
|
||||||
|
|
||||||
pub use channel::Channel;
|
pub use channel::Channel;
|
||||||
|
pub use client::Client;
|
||||||
pub use string_buffer::StringBuffer;
|
pub use string_buffer::StringBuffer;
|
||||||
pub use string_view::StringView;
|
pub use string_view::StringView;
|
||||||
|
|
|
@ -28,6 +28,8 @@ pub struct StringBuffer {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StringBuffer {
|
impl StringBuffer {
|
||||||
|
// The C++ class definition does not declare `string()` to be a const method,
|
||||||
|
// therefore we declare self as mutable here.
|
||||||
pub fn string(&mut self) -> &StringView {
|
pub fn string(&mut self) -> &StringView {
|
||||||
unsafe { v8_inspector__StringBuffer__string(self) }
|
unsafe { v8_inspector__StringBuffer__string(self) }
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue