mirror of
https://github.com/denoland/rusty_v8.git
synced 2024-12-27 01:29:19 -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=BUILD.gn");
|
||||
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
|
||||
// probably more than what is needed, but missing an important
|
||||
|
@ -147,7 +149,11 @@ fn build_binding() {
|
|||
.parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
|
||||
.clang_args(["-x", "c++", "-std=c++20", "-Iv8/include"])
|
||||
.clang_args(args)
|
||||
.respect_cxx_access_specs(true)
|
||||
.allowlist_item("RUST_.*")
|
||||
.blocklist_item("v8::.*")
|
||||
.blocklist_item("cppgc::.*")
|
||||
.blocklist_item("std::.*")
|
||||
.generate()
|
||||
.expect("Unable to generate bindings");
|
||||
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
// Copyright 2019-2021 the Deno authors. All rights reserved. MIT license.
|
||||
#include "binding.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
|
@ -1071,35 +1073,6 @@ v8__String__GetExternalStringResourceBase(const v8::String& self,
|
|||
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
|
||||
: public v8::String::ExternalOneByteStringResource {
|
||||
public:
|
||||
|
@ -1138,7 +1111,7 @@ class ExternalConstOneByteStringResource
|
|||
const int _length;
|
||||
};
|
||||
|
||||
const v8::String* v8__String__NewExternalOneByteConst(
|
||||
const v8::String* v8__String__NewExternalOneByte(
|
||||
v8::Isolate* isolate, v8::String::ExternalOneByteStringResource* 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)));
|
||||
}
|
||||
|
||||
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(
|
||||
v8::String::ExternalOneByteStringResource* self) {
|
||||
return self->data();
|
||||
|
@ -3787,31 +3753,23 @@ void v8__PropertyDescriptor__set_configurable(v8::PropertyDescriptor* self,
|
|||
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"
|
||||
|
||||
// cppgc
|
||||
|
||||
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,
|
||||
v8::CppHeapPointerTag 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,
|
||||
RustTraceFn trace,
|
||||
RustDestroyFn destroy) {
|
||||
RustObj::RustTraceFn trace,
|
||||
RustObj::RustDestroyFn destroy) {
|
||||
return cppgc::MakeGarbageCollected<RustObj>(heap->GetAllocationHandle(),
|
||||
cppgc::AdditionalBytes(size),
|
||||
trace, destroy);
|
||||
|
@ -3948,4 +3906,5 @@ RustObj* cppgc__WeakPersistent__Get(cppgc::WeakPersistent<RustObj>* self) {
|
|||
return self->Get();
|
||||
}
|
||||
|
||||
//
|
||||
} // extern "C"
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include <v8-cppgc.h>
|
||||
#include <v8-isolate.h>
|
||||
#include <v8-message.h>
|
||||
|
||||
/**
|
||||
|
@ -6,12 +7,53 @@
|
|||
* and made available in `crate::binding` in rust.
|
||||
*/
|
||||
|
||||
namespace {
|
||||
extern "C" {
|
||||
class RUST_ExternalOneByteString
|
||||
: 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);
|
||||
|
||||
class RustObj;
|
||||
~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_cppgc__Member_SIZE = sizeof(cppgc::Member<RustObj>);
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
#![allow(non_upper_case_globals)]
|
||||
#![allow(non_camel_case_types)]
|
||||
#![allow(non_snake_case)]
|
||||
#![allow(dead_code)]
|
||||
include!(env!("RUSTY_V8_SRC_BINDING_PATH"));
|
||||
|
||||
pub use crate::Isolate as v8_Isolate;
|
||||
|
|
|
@ -79,11 +79,6 @@ extern "C" {
|
|||
encoding: *mut Encoding,
|
||||
) -> *mut ExternalStringResourceBase;
|
||||
|
||||
fn v8__String__NewExternalOneByteConst(
|
||||
isolate: *mut Isolate,
|
||||
onebyte_const: *const OneByteConst,
|
||||
) -> *const String;
|
||||
|
||||
fn v8__String__NewExternalOneByteStatic(
|
||||
isolate: *mut Isolate,
|
||||
buffer: *const char,
|
||||
|
@ -92,9 +87,7 @@ extern "C" {
|
|||
|
||||
fn v8__String__NewExternalOneByte(
|
||||
isolate: *mut Isolate,
|
||||
buffer: *mut char,
|
||||
length: int,
|
||||
free: extern "C" fn(*mut char, size_t),
|
||||
resource: *mut ExternalOneByteStringResource,
|
||||
) -> *const String;
|
||||
|
||||
fn v8__String__NewExternalTwoByteStatic(
|
||||
|
@ -571,7 +564,11 @@ impl String {
|
|||
) -> Option<Local<'s, String>> {
|
||||
unsafe {
|
||||
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()?;
|
||||
unsafe {
|
||||
scope.cast_local(|sd| {
|
||||
v8__String__NewExternalOneByte(
|
||||
sd.get_isolate_ptr(),
|
||||
let ptr = crate::support::cpp_new::<
|
||||
crate::binding::RUST_ExternalOneByteString,
|
||||
>();
|
||||
crate::binding::RUST_ExternalOneByteString_RUST_ExternalOneByteString(
|
||||
ptr,
|
||||
Box::into_raw(buffer).cast::<char>(),
|
||||
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(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.
|
||||
#[repr(transparent)]
|
||||
#[derive(Debug)]
|
||||
|
|
Loading…
Reference in a new issue