mirror of
https://github.com/denoland/rusty_v8.git
synced 2024-11-22 15:07:00 -05:00
Use bindgen + raw api
This commit is contained in:
parent
b085881ac4
commit
8ea00476b6
6 changed files with 123 additions and 73 deletions
6
build.rs
6
build.rs
|
@ -24,6 +24,8 @@ fn main() {
|
||||||
println!("cargo:rerun-if-changed=.gn");
|
println!("cargo:rerun-if-changed=.gn");
|
||||||
println!("cargo:rerun-if-changed=BUILD.gn");
|
println!("cargo:rerun-if-changed=BUILD.gn");
|
||||||
println!("cargo:rerun-if-changed=src/binding.cc");
|
println!("cargo:rerun-if-changed=src/binding.cc");
|
||||||
|
println!("cargo:rerun-if-changed=src/binding.hpp");
|
||||||
|
println!("cargo:rerun-if-changed=build.rs");
|
||||||
|
|
||||||
// These are all the environment variables that we check. This is
|
// These are all the environment variables that we check. This is
|
||||||
// probably more than what is needed, but missing an important
|
// probably more than what is needed, but missing an important
|
||||||
|
@ -147,7 +149,11 @@ fn build_binding() {
|
||||||
.parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
|
.parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
|
||||||
.clang_args(["-x", "c++", "-std=c++20", "-Iv8/include"])
|
.clang_args(["-x", "c++", "-std=c++20", "-Iv8/include"])
|
||||||
.clang_args(args)
|
.clang_args(args)
|
||||||
|
.respect_cxx_access_specs(true)
|
||||||
.allowlist_item("RUST_.*")
|
.allowlist_item("RUST_.*")
|
||||||
|
.blocklist_item("v8::.*")
|
||||||
|
.blocklist_item("cppgc::.*")
|
||||||
|
.blocklist_item("std::.*")
|
||||||
.generate()
|
.generate()
|
||||||
.expect("Unable to generate bindings");
|
.expect("Unable to generate bindings");
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
// Copyright 2019-2021 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2019-2021 the Deno authors. All rights reserved. MIT license.
|
||||||
|
#include "binding.hpp"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
@ -1071,35 +1073,6 @@ v8__String__GetExternalStringResourceBase(const v8::String& self,
|
||||||
return self.GetExternalStringResourceBase(encoding_out);
|
return self.GetExternalStringResourceBase(encoding_out);
|
||||||
}
|
}
|
||||||
|
|
||||||
class ExternalOneByteString : public v8::String::ExternalOneByteStringResource {
|
|
||||||
public:
|
|
||||||
using RustDestroy = void (*)(char*, size_t);
|
|
||||||
ExternalOneByteString(char* data, int length, RustDestroy rustDestroy,
|
|
||||||
v8::Isolate* isolate)
|
|
||||||
: _data(data),
|
|
||||||
_length(length),
|
|
||||||
_rustDestroy(rustDestroy),
|
|
||||||
_isolate(isolate) {
|
|
||||||
_isolate->AdjustAmountOfExternalAllocatedMemory(
|
|
||||||
static_cast<int64_t>(_length));
|
|
||||||
}
|
|
||||||
~ExternalOneByteString() override {
|
|
||||||
(*_rustDestroy)(_data, _length);
|
|
||||||
_isolate->AdjustAmountOfExternalAllocatedMemory(
|
|
||||||
-static_cast<int64_t>(-_length));
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* data() const override { return _data; }
|
|
||||||
|
|
||||||
size_t length() const override { return _length; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
char* _data;
|
|
||||||
const int _length;
|
|
||||||
RustDestroy _rustDestroy;
|
|
||||||
v8::Isolate* _isolate;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ExternalStaticOneByteStringResource
|
class ExternalStaticOneByteStringResource
|
||||||
: public v8::String::ExternalOneByteStringResource {
|
: public v8::String::ExternalOneByteStringResource {
|
||||||
public:
|
public:
|
||||||
|
@ -1138,7 +1111,7 @@ class ExternalConstOneByteStringResource
|
||||||
const int _length;
|
const int _length;
|
||||||
};
|
};
|
||||||
|
|
||||||
const v8::String* v8__String__NewExternalOneByteConst(
|
const v8::String* v8__String__NewExternalOneByte(
|
||||||
v8::Isolate* isolate, v8::String::ExternalOneByteStringResource* resource) {
|
v8::Isolate* isolate, v8::String::ExternalOneByteStringResource* resource) {
|
||||||
return maybe_local_to_ptr(v8::String::NewExternalOneByte(isolate, resource));
|
return maybe_local_to_ptr(v8::String::NewExternalOneByte(isolate, resource));
|
||||||
}
|
}
|
||||||
|
@ -1150,13 +1123,6 @@ const v8::String* v8__String__NewExternalOneByteStatic(v8::Isolate* isolate,
|
||||||
isolate, new ExternalStaticOneByteStringResource(data, length)));
|
isolate, new ExternalStaticOneByteStringResource(data, length)));
|
||||||
}
|
}
|
||||||
|
|
||||||
const v8::String* v8__String__NewExternalOneByte(
|
|
||||||
v8::Isolate* isolate, char* data, int length,
|
|
||||||
ExternalOneByteString::RustDestroy rustDestroy) {
|
|
||||||
return maybe_local_to_ptr(v8::String::NewExternalOneByte(
|
|
||||||
isolate, new ExternalOneByteString(data, length, rustDestroy, isolate)));
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* v8__ExternalOneByteStringResource__data(
|
const char* v8__ExternalOneByteStringResource__data(
|
||||||
v8::String::ExternalOneByteStringResource* self) {
|
v8::String::ExternalOneByteStringResource* self) {
|
||||||
return self->data();
|
return self->data();
|
||||||
|
@ -3787,31 +3753,23 @@ void v8__PropertyDescriptor__set_configurable(v8::PropertyDescriptor* self,
|
||||||
self->set_configurable(configurable);
|
self->set_configurable(configurable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RUST_ExternalOneByteString::RUST_ExternalOneByteString(
|
||||||
|
char* data, int length,
|
||||||
|
RUST_ExternalOneByteString::RustDestroyFn rustDestroy, v8::Isolate* isolate)
|
||||||
|
: _data(data),
|
||||||
|
_length(length),
|
||||||
|
_rustDestroy(rustDestroy),
|
||||||
|
_isolate(isolate) {
|
||||||
|
_isolate->AdjustAmountOfExternalAllocatedMemory(
|
||||||
|
static_cast<int64_t>(_length));
|
||||||
|
}
|
||||||
|
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
|
|
||||||
// cppgc
|
// cppgc
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
class RustObj;
|
|
||||||
|
|
||||||
using RustTraceFn = void (*)(const RustObj* obj, cppgc::Visitor*);
|
|
||||||
using RustDestroyFn = void (*)(const RustObj* obj);
|
|
||||||
|
|
||||||
class RustObj final : public cppgc::GarbageCollected<RustObj> {
|
|
||||||
public:
|
|
||||||
explicit RustObj(RustTraceFn trace, RustDestroyFn destroy)
|
|
||||||
: trace_(trace), destroy_(destroy) {}
|
|
||||||
|
|
||||||
~RustObj() { destroy_(this); }
|
|
||||||
|
|
||||||
void Trace(cppgc::Visitor* visitor) const { trace_(this, visitor); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
RustTraceFn trace_;
|
|
||||||
RustDestroyFn destroy_;
|
|
||||||
};
|
|
||||||
|
|
||||||
RustObj* v8__Object__Unwrap(v8::Isolate* isolate, const v8::Object& wrapper,
|
RustObj* v8__Object__Unwrap(v8::Isolate* isolate, const v8::Object& wrapper,
|
||||||
v8::CppHeapPointerTag tag) {
|
v8::CppHeapPointerTag tag) {
|
||||||
v8::CppHeapPointerTagRange tag_range(tag, tag);
|
v8::CppHeapPointerTagRange tag_range(tag, tag);
|
||||||
|
@ -3858,8 +3816,8 @@ void cppgc__heap__collect_garbage_for_testing(
|
||||||
}
|
}
|
||||||
|
|
||||||
RustObj* cppgc__make_garbage_collectable(v8::CppHeap* heap, size_t size,
|
RustObj* cppgc__make_garbage_collectable(v8::CppHeap* heap, size_t size,
|
||||||
RustTraceFn trace,
|
RustObj::RustTraceFn trace,
|
||||||
RustDestroyFn destroy) {
|
RustObj::RustDestroyFn destroy) {
|
||||||
return cppgc::MakeGarbageCollected<RustObj>(heap->GetAllocationHandle(),
|
return cppgc::MakeGarbageCollected<RustObj>(heap->GetAllocationHandle(),
|
||||||
cppgc::AdditionalBytes(size),
|
cppgc::AdditionalBytes(size),
|
||||||
trace, destroy);
|
trace, destroy);
|
||||||
|
@ -3948,4 +3906,5 @@ RustObj* cppgc__WeakPersistent__Get(cppgc::WeakPersistent<RustObj>* self) {
|
||||||
return self->Get();
|
return self->Get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include <v8-cppgc.h>
|
#include <v8-cppgc.h>
|
||||||
|
#include <v8-isolate.h>
|
||||||
#include <v8-message.h>
|
#include <v8-message.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -6,12 +7,53 @@
|
||||||
* and made available in `crate::binding` in rust.
|
* and made available in `crate::binding` in rust.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace {
|
extern "C" {
|
||||||
|
class RUST_ExternalOneByteString
|
||||||
class RustObj;
|
: public v8::String::ExternalOneByteStringResource {
|
||||||
|
public:
|
||||||
|
using RustDestroyFn = void (*)(char*, size_t);
|
||||||
|
// bindgen doesn't support generating bindings for inline
|
||||||
|
// constructors/functions
|
||||||
|
RUST_ExternalOneByteString(char* data, int length, RustDestroyFn rustDestroy,
|
||||||
|
v8::Isolate* isolate);
|
||||||
|
|
||||||
|
~RUST_ExternalOneByteString() {
|
||||||
|
(*_rustDestroy)(_data, _length);
|
||||||
|
_isolate->AdjustAmountOfExternalAllocatedMemory(
|
||||||
|
-static_cast<int64_t>(-_length));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char* data() const { return _data; }
|
||||||
|
|
||||||
|
size_t length() const { return static_cast<size_t>(_length); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
char* const _data;
|
||||||
|
const size_t _length;
|
||||||
|
RustDestroyFn _rustDestroy;
|
||||||
|
v8::Isolate* _isolate;
|
||||||
|
};
|
||||||
|
|
||||||
|
class RustObj final : public cppgc::GarbageCollected<RustObj> {
|
||||||
|
public:
|
||||||
|
using RustTraceFn = void (*)(const RustObj* obj, cppgc::Visitor*);
|
||||||
|
using RustDestroyFn = void (*)(const RustObj* obj);
|
||||||
|
explicit RustObj(RustTraceFn trace, RustDestroyFn destroy)
|
||||||
|
: trace_(trace), destroy_(destroy) {}
|
||||||
|
|
||||||
|
~RustObj() { destroy_(this); }
|
||||||
|
|
||||||
|
void Trace(cppgc::Visitor* visitor) const { trace_(this, visitor); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
RustTraceFn trace_;
|
||||||
|
RustDestroyFn destroy_;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate memory using C++'s `new` operator
|
||||||
|
void* RUST_new(size_t size) { return operator new(size); }
|
||||||
|
|
||||||
static size_t RUST_v8__ScriptOrigin_SIZE = sizeof(v8::ScriptOrigin);
|
static size_t RUST_v8__ScriptOrigin_SIZE = sizeof(v8::ScriptOrigin);
|
||||||
|
|
||||||
static size_t RUST_cppgc__Member_SIZE = sizeof(cppgc::Member<RustObj>);
|
static size_t RUST_cppgc__Member_SIZE = sizeof(cppgc::Member<RustObj>);
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
#![allow(non_upper_case_globals)]
|
#![allow(non_upper_case_globals)]
|
||||||
#![allow(non_camel_case_types)]
|
#![allow(non_camel_case_types)]
|
||||||
#![allow(non_snake_case)]
|
#![allow(non_snake_case)]
|
||||||
|
#![allow(dead_code)]
|
||||||
include!(env!("RUSTY_V8_SRC_BINDING_PATH"));
|
include!(env!("RUSTY_V8_SRC_BINDING_PATH"));
|
||||||
|
|
||||||
|
pub use crate::Isolate as v8_Isolate;
|
||||||
|
|
|
@ -79,11 +79,6 @@ extern "C" {
|
||||||
encoding: *mut Encoding,
|
encoding: *mut Encoding,
|
||||||
) -> *mut ExternalStringResourceBase;
|
) -> *mut ExternalStringResourceBase;
|
||||||
|
|
||||||
fn v8__String__NewExternalOneByteConst(
|
|
||||||
isolate: *mut Isolate,
|
|
||||||
onebyte_const: *const OneByteConst,
|
|
||||||
) -> *const String;
|
|
||||||
|
|
||||||
fn v8__String__NewExternalOneByteStatic(
|
fn v8__String__NewExternalOneByteStatic(
|
||||||
isolate: *mut Isolate,
|
isolate: *mut Isolate,
|
||||||
buffer: *const char,
|
buffer: *const char,
|
||||||
|
@ -92,9 +87,7 @@ extern "C" {
|
||||||
|
|
||||||
fn v8__String__NewExternalOneByte(
|
fn v8__String__NewExternalOneByte(
|
||||||
isolate: *mut Isolate,
|
isolate: *mut Isolate,
|
||||||
buffer: *mut char,
|
resource: *mut ExternalOneByteStringResource,
|
||||||
length: int,
|
|
||||||
free: extern "C" fn(*mut char, size_t),
|
|
||||||
) -> *const String;
|
) -> *const String;
|
||||||
|
|
||||||
fn v8__String__NewExternalTwoByteStatic(
|
fn v8__String__NewExternalTwoByteStatic(
|
||||||
|
@ -571,7 +564,11 @@ impl String {
|
||||||
) -> Option<Local<'s, String>> {
|
) -> Option<Local<'s, String>> {
|
||||||
unsafe {
|
unsafe {
|
||||||
scope.cast_local(|sd| {
|
scope.cast_local(|sd| {
|
||||||
v8__String__NewExternalOneByteConst(sd.get_isolate_ptr(), onebyte_const)
|
v8__String__NewExternalOneByte(
|
||||||
|
sd.get_isolate_ptr(),
|
||||||
|
onebyte_const as *const _ as *mut OneByteConst
|
||||||
|
as *mut ExternalOneByteStringResource,
|
||||||
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -606,12 +603,51 @@ impl String {
|
||||||
let buffer_len = buffer.len().try_into().ok()?;
|
let buffer_len = buffer.len().try_into().ok()?;
|
||||||
unsafe {
|
unsafe {
|
||||||
scope.cast_local(|sd| {
|
scope.cast_local(|sd| {
|
||||||
v8__String__NewExternalOneByte(
|
let ptr = crate::support::cpp_new::<
|
||||||
sd.get_isolate_ptr(),
|
crate::binding::RUST_ExternalOneByteString,
|
||||||
|
>();
|
||||||
|
crate::binding::RUST_ExternalOneByteString_RUST_ExternalOneByteString(
|
||||||
|
ptr,
|
||||||
Box::into_raw(buffer).cast::<char>(),
|
Box::into_raw(buffer).cast::<char>(),
|
||||||
buffer_len,
|
buffer_len,
|
||||||
free_rust_external_onebyte,
|
Some(free_rust_external_onebyte),
|
||||||
)
|
sd.get_isolate_ptr().cast(),
|
||||||
|
);
|
||||||
|
|
||||||
|
v8__String__NewExternalOneByte(sd.get_isolate_ptr(), ptr.cast())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a `v8::String` from owned bytes, length, and a custom destructor.
|
||||||
|
/// The bytes must be Latin-1 or ASCII.
|
||||||
|
/// V8 will take ownership of the buffer and free it when the string is garbage collected.
|
||||||
|
///
|
||||||
|
/// SAFETY: `buffer` must be owned (valid for the lifetime of the string), and
|
||||||
|
/// `destructor` must be a valid function pointer that can free the buffer.
|
||||||
|
/// The destructor will be called with the buffer and length when the string is garbage collected.
|
||||||
|
#[inline(always)]
|
||||||
|
pub unsafe fn new_external_onebyte_raw<'s>(
|
||||||
|
scope: &mut HandleScope<'s, ()>,
|
||||||
|
buffer: *mut char,
|
||||||
|
buffer_len: usize,
|
||||||
|
destructor: extern "C" fn(*mut char, usize),
|
||||||
|
) -> Option<Local<'s, String>> {
|
||||||
|
let buffer_len = buffer_len.try_into().ok()?;
|
||||||
|
unsafe {
|
||||||
|
scope.cast_local(|sd| {
|
||||||
|
let ptr = crate::support::cpp_new::<
|
||||||
|
crate::binding::RUST_ExternalOneByteString,
|
||||||
|
>();
|
||||||
|
crate::binding::RUST_ExternalOneByteString_RUST_ExternalOneByteString(
|
||||||
|
ptr,
|
||||||
|
buffer.cast::<char>(),
|
||||||
|
buffer_len,
|
||||||
|
Some(destructor),
|
||||||
|
sd.get_isolate_ptr().cast(),
|
||||||
|
);
|
||||||
|
|
||||||
|
v8__String__NewExternalOneByte(sd.get_isolate_ptr(), ptr.cast())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,10 @@ pub use std::os::raw::c_long as long;
|
||||||
|
|
||||||
pub type Opaque = [u8; 0];
|
pub type Opaque = [u8; 0];
|
||||||
|
|
||||||
|
pub(crate) fn cpp_new<T>() -> *mut T {
|
||||||
|
unsafe { crate::binding::RUST_new(std::mem::size_of::<T>()).cast() }
|
||||||
|
}
|
||||||
|
|
||||||
/// Pointer to object allocated on the C++ heap. The pointer may be null.
|
/// Pointer to object allocated on the C++ heap. The pointer may be null.
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
Loading…
Reference in a new issue