mirror of
https://github.com/denoland/rusty_v8.git
synced 2025-01-11 08:34:01 -05:00
Add Task
This commit is contained in:
parent
c3f0fbbeb4
commit
9a6e90be38
11 changed files with 283 additions and 75 deletions
1
build.rs
1
build.rs
|
@ -7,6 +7,7 @@ fn main() {
|
|||
.debug(true)
|
||||
.file("src/v8/inspector/channel.cpp")
|
||||
.file("src/v8/inspector/client.cpp")
|
||||
.file("src/v8/platform/task.cpp")
|
||||
.file("src/v8/string_buffer.cpp")
|
||||
.compile("v8-bindings");
|
||||
|
||||
|
|
54
src/main.rs
54
src/main.rs
|
@ -7,15 +7,16 @@ mod v8;
|
|||
mod example {
|
||||
use crate::support::UniquePtr;
|
||||
use crate::v8::inspector::channel::*;
|
||||
use crate::v8::platform::task::*;
|
||||
use crate::v8::*;
|
||||
|
||||
pub struct Example {
|
||||
pub struct TestChannel {
|
||||
a: i32,
|
||||
channel_base: ChannelBase,
|
||||
b: i32,
|
||||
}
|
||||
|
||||
impl ChannelImpl for Example {
|
||||
impl ChannelImpl for TestChannel {
|
||||
fn base(&self) -> &ChannelBase {
|
||||
&self.channel_base
|
||||
}
|
||||
|
@ -37,7 +38,7 @@ mod example {
|
|||
fn flushProtocolNotifications(&mut self) {}
|
||||
}
|
||||
|
||||
impl Example {
|
||||
impl TestChannel {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
channel_base: ChannelBase::new::<Self>(),
|
||||
|
@ -46,16 +47,59 @@ mod example {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TestTask {
|
||||
a: i32,
|
||||
base: TaskBase,
|
||||
b: i32,
|
||||
}
|
||||
|
||||
impl TaskImpl for TestTask {
|
||||
fn base(&self) -> &TaskBase {
|
||||
&self.base
|
||||
}
|
||||
fn base_mut(&mut self) -> &mut TaskBase {
|
||||
&mut self.base
|
||||
}
|
||||
fn Run(&mut self) -> () {
|
||||
println!("TestTask::Run {} {}", self.a, self.b);
|
||||
}
|
||||
}
|
||||
|
||||
impl TestTask {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
base: TaskBase::new::<Self>(),
|
||||
a: 2,
|
||||
b: 3,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for TestTask {
|
||||
fn drop(&mut self) {
|
||||
println!("TestTask::drop()");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
fn main1() {
|
||||
use crate::v8::inspector::channel::*;
|
||||
use crate::v8::*;
|
||||
use example::*;
|
||||
let mut ex = Example::new();
|
||||
let mut ex = TestChannel::new();
|
||||
let chan = ex.as_channel_mut();
|
||||
let message = b"hello";
|
||||
let message = StringView::from(&message[..]);
|
||||
let message = StringBuffer::create(&message);
|
||||
chan.sendResponse(3, message);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
use crate::v8::platform::task::*;
|
||||
use example::*;
|
||||
let mut v = TestTask::new();
|
||||
v.Run();
|
||||
let b = Box::new(v);
|
||||
b.into_unique_ptr();
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
use std::marker::PhantomData;
|
||||
use std::mem::size_of;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::mem::transmute;
|
||||
use std::ops::Deref;
|
||||
use std::ops::DerefMut;
|
||||
|
||||
pub use std::os::raw::c_int as int;
|
||||
|
||||
|
@ -20,6 +22,23 @@ pub struct UniquePtr<T>(Option<&'static mut T>)
|
|||
where
|
||||
T: Delete;
|
||||
|
||||
impl<T> UniquePtr<T>
|
||||
where
|
||||
T: Delete,
|
||||
{
|
||||
pub fn null() -> Self {
|
||||
Self(None)
|
||||
}
|
||||
|
||||
pub fn new(r: &'static mut T) -> Self {
|
||||
Self(Some(r))
|
||||
}
|
||||
|
||||
pub unsafe fn from_raw(p: *mut T) -> Self {
|
||||
transmute(p)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Deref for UniquePtr<T>
|
||||
where
|
||||
T: Delete,
|
||||
|
@ -48,42 +67,6 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
/// Reference to object allocated on the C++ heap, similar to UniquePtr<T>,
|
||||
/// but guaranteed to never contain a nullptr.
|
||||
#[repr(transparent)]
|
||||
pub struct UniqueRef<T>(&'static mut T)
|
||||
where
|
||||
T: Delete;
|
||||
|
||||
impl<T> Deref for UniqueRef<T>
|
||||
where
|
||||
T: Delete,
|
||||
{
|
||||
type Target = T;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> DerefMut for UniqueRef<T>
|
||||
where
|
||||
T: Delete,
|
||||
{
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Drop for UniqueRef<T>
|
||||
where
|
||||
T: Delete,
|
||||
{
|
||||
fn drop(&mut self) {
|
||||
let ptr: &'static mut T = unsafe { std::mem::transmute_copy(self.0) };
|
||||
ptr.delete();
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[repr(transparent)]
|
||||
pub struct CxxVTable(pub *const Opaque);
|
||||
|
|
|
@ -19,28 +19,25 @@ void v8_inspector__V8Inspector__Channel__BASE__flushProtocolNotifications(
|
|||
struct v8_inspector__V8Inspector__Channel__BASE : public V8Inspector::Channel {
|
||||
using V8Inspector::Channel::Channel;
|
||||
|
||||
inline void sendResponse(int callId,
|
||||
void sendResponse(int callId,
|
||||
std::unique_ptr<StringBuffer> message) override {
|
||||
v8_inspector__V8Inspector__Channel__BASE__sendResponse(*this, callId,
|
||||
message.release());
|
||||
}
|
||||
inline void sendNotification(std::unique_ptr<StringBuffer> message) override {
|
||||
void sendNotification(std::unique_ptr<StringBuffer> message) override {
|
||||
v8_inspector__V8Inspector__Channel__BASE__sendNotification(
|
||||
*this, message.release());
|
||||
}
|
||||
inline void flushProtocolNotifications() override {
|
||||
void flushProtocolNotifications() override {
|
||||
v8_inspector__V8Inspector__Channel__BASE__flushProtocolNotifications(*this);
|
||||
}
|
||||
};
|
||||
|
||||
extern "C" {
|
||||
void v8_inspector__V8Inspector__Channel__BASE__CTOR(
|
||||
void v8_inspector__V8Inspector__Channel__BASE__CONSTRUCT(
|
||||
uninit_t<v8_inspector__V8Inspector__Channel__BASE>& buf) {
|
||||
construct_in_place<v8_inspector__V8Inspector__Channel__BASE>(buf);
|
||||
}
|
||||
void v8_inspector__V8Inspector__Channel__DTOR(V8Inspector::Channel& self) {
|
||||
self.~Channel();
|
||||
}
|
||||
|
||||
void v8_inspector__V8Inspector__Channel__sendResponse(
|
||||
V8Inspector::Channel& self,
|
||||
|
|
|
@ -16,10 +16,9 @@ use crate::v8::StringBuffer;
|
|||
// };
|
||||
|
||||
extern "C" {
|
||||
fn v8_inspector__V8Inspector__Channel__BASE__CTOR(
|
||||
fn v8_inspector__V8Inspector__Channel__BASE__CONSTRUCT(
|
||||
buf: &mut std::mem::MaybeUninit<Channel>,
|
||||
) -> ();
|
||||
fn v8_inspector__V8Inspector__Channel__DTOR(this: &mut Channel) -> ();
|
||||
|
||||
fn v8_inspector__V8Inspector__Channel__sendResponse(
|
||||
this: &mut Channel,
|
||||
|
@ -86,12 +85,6 @@ impl Channel {
|
|||
}
|
||||
}
|
||||
|
||||
impl Drop for Channel {
|
||||
fn drop(&mut self) {
|
||||
unsafe { v8_inspector__V8Inspector__Channel__DTOR(self) }
|
||||
}
|
||||
}
|
||||
|
||||
pub trait AsChannel {
|
||||
fn as_channel(&self) -> &Channel;
|
||||
fn as_channel_mut(&mut self) -> &mut Channel;
|
||||
|
@ -141,7 +134,7 @@ impl ChannelBase {
|
|||
fn construct_cxx_base() -> Channel {
|
||||
unsafe {
|
||||
let mut buf = std::mem::MaybeUninit::<Channel>::uninit();
|
||||
v8_inspector__V8Inspector__Channel__BASE__CTOR(&mut buf);
|
||||
v8_inspector__V8Inspector__Channel__BASE__CONSTRUCT(&mut buf);
|
||||
buf.assume_init()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,27 +18,24 @@ void v8_inspector__V8InspectorClient__BASE__runIfWaitingForDebugger(
|
|||
struct v8_inspector__V8InspectorClient__BASE : public V8InspectorClient {
|
||||
using V8InspectorClient::V8InspectorClient;
|
||||
|
||||
inline void runMessageLoopOnPause(int contextGroupId) override {
|
||||
void runMessageLoopOnPause(int contextGroupId) override {
|
||||
v8_inspector__V8InspectorClient__BASE__runMessageLoopOnPause(
|
||||
*this, contextGroupId);
|
||||
}
|
||||
inline void quitMessageLoopOnPause() override {
|
||||
void quitMessageLoopOnPause() override {
|
||||
v8_inspector__V8InspectorClient__BASE__quitMessageLoopOnPause(*this);
|
||||
}
|
||||
inline void runIfWaitingForDebugger(int contextGroupId) override {
|
||||
void runIfWaitingForDebugger(int contextGroupId) override {
|
||||
v8_inspector__V8InspectorClient__BASE__runIfWaitingForDebugger(
|
||||
*this, contextGroupId);
|
||||
}
|
||||
};
|
||||
|
||||
extern "C" {
|
||||
void v8_inspector__V8InspectorClient__BASE__CTOR(
|
||||
void v8_inspector__V8InspectorClient__BASE__CONSTRUCT(
|
||||
uninit_t<v8_inspector__V8InspectorClient__BASE>& buf) {
|
||||
construct_in_place<v8_inspector__V8InspectorClient__BASE>(buf);
|
||||
}
|
||||
void v8_inspector__V8InspectorClient__DTOR(V8InspectorClient& self) {
|
||||
self.~V8InspectorClient();
|
||||
}
|
||||
|
||||
void v8_inspector__V8InspectorClient__runMessageLoopOnPause(
|
||||
V8InspectorClient& self,
|
||||
|
|
|
@ -67,10 +67,9 @@ use crate::support::RustVTable;
|
|||
// };
|
||||
|
||||
extern "C" {
|
||||
fn v8_inspector__V8InspectorClient__BASE__CTOR(
|
||||
fn v8_inspector__V8InspectorClient__BASE__CONSTRUCT(
|
||||
buf: &mut std::mem::MaybeUninit<Client>,
|
||||
) -> ();
|
||||
fn v8_inspector__V8InspectorClient__DTOR(this: &mut Client) -> ();
|
||||
|
||||
fn v8_inspector__V8InspectorClient__runMessageLoopOnPause(
|
||||
this: &mut Client,
|
||||
|
@ -135,12 +134,6 @@ impl Client {
|
|||
}
|
||||
}
|
||||
|
||||
impl Drop for Client {
|
||||
fn drop(&mut self) {
|
||||
unsafe { v8_inspector__V8InspectorClient__DTOR(self) }
|
||||
}
|
||||
}
|
||||
|
||||
pub trait AsClient {
|
||||
fn as_client(&self) -> &Client;
|
||||
fn as_client_mut(&mut self) -> &mut Client;
|
||||
|
@ -187,7 +180,7 @@ impl ClientBase {
|
|||
fn construct_cxx_base() -> Client {
|
||||
unsafe {
|
||||
let mut buf = std::mem::MaybeUninit::<Client>::uninit();
|
||||
v8_inspector__V8InspectorClient__BASE__CTOR(&mut buf);
|
||||
v8_inspector__V8InspectorClient__BASE__CONSTRUCT(&mut buf);
|
||||
buf.assume_init()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
pub mod inspector;
|
||||
pub mod platform;
|
||||
pub mod string_buffer;
|
||||
pub mod string_view;
|
||||
|
||||
|
|
3
src/v8/platform/mod.rs
Normal file
3
src/v8/platform/mod.rs
Normal file
|
@ -0,0 +1,3 @@
|
|||
pub mod task;
|
||||
|
||||
pub use task::Task;
|
32
src/v8/platform/task.cpp
Normal file
32
src/v8/platform/task.cpp
Normal file
|
@ -0,0 +1,32 @@
|
|||
#include "../../../v8/include/v8-platform.h"
|
||||
#include "../../support.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using namespace v8;
|
||||
using namespace support;
|
||||
|
||||
extern "C" {
|
||||
void v8__Task__BASE__DELETE(Task& self);
|
||||
void v8__Task__BASE__Run(Task& self);
|
||||
} // extern "C"
|
||||
|
||||
struct v8__Task__BASE : public Task {
|
||||
using Task::Task;
|
||||
void operator delete(void* ptr) noexcept {
|
||||
v8__Task__BASE__DELETE(*reinterpret_cast<Task*>(ptr));
|
||||
}
|
||||
void Run() override { v8__Task__BASE__Run(*this); }
|
||||
};
|
||||
|
||||
extern "C" {
|
||||
void v8__Task__BASE__CONSTRUCT(uninit_t<v8__Task__BASE>& buf) {
|
||||
construct_in_place<v8__Task__BASE>(buf);
|
||||
}
|
||||
void v8__Task__DELETE(Task& self) {
|
||||
delete &self;
|
||||
}
|
||||
void v8__Task__Run(Task& self) {
|
||||
self.Run();
|
||||
}
|
||||
} // extern "C"
|
164
src/v8/platform/task.rs
Normal file
164
src/v8/platform/task.rs
Normal file
|
@ -0,0 +1,164 @@
|
|||
use std::mem::drop;
|
||||
use std::mem::forget;
|
||||
|
||||
use crate::support::CxxVTable;
|
||||
use crate::support::Delete;
|
||||
use crate::support::FieldOffset;
|
||||
use crate::support::Opaque;
|
||||
use crate::support::RustVTable;
|
||||
use crate::support::UniquePtr;
|
||||
|
||||
// class Task {
|
||||
// public:
|
||||
// virtual ~Task() = default;
|
||||
// virtual void Run() = 0;
|
||||
// };
|
||||
|
||||
extern "C" {
|
||||
fn v8__Task__BASE__CONSTRUCT(buf: &mut std::mem::MaybeUninit<Task>) -> ();
|
||||
fn v8__Task__DELETE(this: &'static mut Task) -> ();
|
||||
fn v8__Task__Run(this: &mut Task) -> ();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn v8__Task__BASE__DELETE(this: &mut Task) -> () {
|
||||
println!("v8__Task__BASE__DELETE");
|
||||
drop(TaskBase::dispatch_box(this))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn v8__Task__BASE__Run(this: &mut Task) -> () {
|
||||
TaskBase::dispatch_mut(this).Run()
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct Task {
|
||||
_cxx_vtable: CxxVTable,
|
||||
}
|
||||
|
||||
impl Task {
|
||||
pub fn Run(&mut self) -> () {
|
||||
unsafe { v8__Task__Run(self) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Delete for Task {
|
||||
fn delete(&'static mut self) {
|
||||
println!("Task::delete()");
|
||||
unsafe { v8__Task__DELETE(self) }
|
||||
}
|
||||
}
|
||||
|
||||
pub trait AsTask {
|
||||
fn as_task(&self) -> &Task;
|
||||
fn as_task_mut(&mut self) -> &mut Task;
|
||||
|
||||
// TODO: this should be a trait in itself.
|
||||
fn into_unique_ptr(mut self: Box<Self>) -> UniquePtr<Task>
|
||||
where
|
||||
Self: 'static,
|
||||
{
|
||||
let task = self.as_task_mut() as *mut Task;
|
||||
forget(self);
|
||||
unsafe { UniquePtr::from_raw(task) }
|
||||
}
|
||||
}
|
||||
|
||||
impl AsTask for Task {
|
||||
fn as_task(&self) -> &Task {
|
||||
self
|
||||
}
|
||||
fn as_task_mut(&mut self) -> &mut Task {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> AsTask for T
|
||||
where
|
||||
T: TaskImpl,
|
||||
{
|
||||
fn as_task(&self) -> &Task {
|
||||
&self.base().cxx_base
|
||||
}
|
||||
fn as_task_mut(&mut self) -> &mut Task {
|
||||
&mut self.base_mut().cxx_base
|
||||
}
|
||||
}
|
||||
|
||||
pub trait TaskImpl: AsTask {
|
||||
fn base(&self) -> &TaskBase;
|
||||
fn base_mut(&mut self) -> &mut TaskBase;
|
||||
fn Run(&mut self) -> ();
|
||||
}
|
||||
|
||||
pub struct TaskBase {
|
||||
cxx_base: Task,
|
||||
offset_within_embedder: FieldOffset<Self>,
|
||||
rust_vtable: RustVTable<&'static dyn TaskImpl>,
|
||||
}
|
||||
|
||||
impl TaskBase {
|
||||
fn construct_cxx_base() -> Task {
|
||||
unsafe {
|
||||
let mut buf = std::mem::MaybeUninit::<Task>::uninit();
|
||||
v8__Task__BASE__CONSTRUCT(&mut buf);
|
||||
buf.assume_init()
|
||||
}
|
||||
}
|
||||
|
||||
fn get_cxx_base_offset() -> FieldOffset<Task> {
|
||||
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: TaskImpl,
|
||||
{
|
||||
let buf = std::mem::MaybeUninit::<T>::uninit();
|
||||
let embedder_ptr: *const T = buf.as_ptr();
|
||||
let self_ptr: *const Self = unsafe { (*embedder_ptr).base() };
|
||||
FieldOffset::from_ptrs(embedder_ptr, self_ptr)
|
||||
}
|
||||
|
||||
fn get_rust_vtable<T>() -> RustVTable<&'static dyn TaskImpl>
|
||||
where
|
||||
T: TaskImpl,
|
||||
{
|
||||
let buf = std::mem::MaybeUninit::<T>::uninit();
|
||||
let embedder_ptr = buf.as_ptr();
|
||||
let trait_object: *const dyn TaskImpl = 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: TaskImpl,
|
||||
{
|
||||
Self {
|
||||
cxx_base: Self::construct_cxx_base(),
|
||||
offset_within_embedder: Self::get_offset_within_embedder::<T>(),
|
||||
rust_vtable: Self::get_rust_vtable::<T>(),
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn dispatch(task: &Task) -> &dyn TaskImpl {
|
||||
let this = Self::get_cxx_base_offset().to_embedder::<Self>(task);
|
||||
let embedder = this.offset_within_embedder.to_embedder::<Opaque>(this);
|
||||
std::mem::transmute((embedder, this.rust_vtable))
|
||||
}
|
||||
|
||||
pub unsafe fn dispatch_mut(task: &mut Task) -> &mut dyn TaskImpl {
|
||||
let this = Self::get_cxx_base_offset().to_embedder_mut::<Self>(task);
|
||||
let vtable = this.rust_vtable;
|
||||
let embedder = this.offset_within_embedder.to_embedder_mut::<Opaque>(this);
|
||||
std::mem::transmute((embedder, vtable))
|
||||
}
|
||||
|
||||
pub unsafe fn dispatch_box(task: &mut Task) -> Box<dyn TaskImpl> {
|
||||
std::mem::transmute(Self::dispatch_mut(task))
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue