mirror of
https://github.com/denoland/rusty_v8.git
synced 2025-03-09 13:38:51 -04:00
parent
e343a387a1
commit
54531519d0
7 changed files with 72 additions and 276 deletions
|
@ -59,7 +59,6 @@ unsafe extern "C" {
|
||||||
deleter: BackingStoreDeleterCallback,
|
deleter: BackingStoreDeleterCallback,
|
||||||
deleter_data: *mut c_void,
|
deleter_data: *mut c_void,
|
||||||
) -> *mut BackingStore;
|
) -> *mut BackingStore;
|
||||||
fn v8__BackingStore__EmptyBackingStore(shared: bool) -> *mut BackingStore;
|
|
||||||
|
|
||||||
fn v8__BackingStore__Data(this: *const BackingStore) -> *mut c_void;
|
fn v8__BackingStore__Data(this: *const BackingStore) -> *mut c_void;
|
||||||
fn v8__BackingStore__ByteLength(this: *const BackingStore) -> usize;
|
fn v8__BackingStore__ByteLength(this: *const BackingStore) -> usize;
|
||||||
|
@ -450,16 +449,6 @@ impl ArrayBuffer {
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new, empty ArrayBuffer.
|
|
||||||
#[inline(always)]
|
|
||||||
pub fn empty<'s>(scope: &mut HandleScope<'s>) -> Local<'s, ArrayBuffer> {
|
|
||||||
// SAFETY: This is a v8-provided empty backing store
|
|
||||||
let backing_store = unsafe {
|
|
||||||
UniqueRef::from_raw(v8__BackingStore__EmptyBackingStore(false))
|
|
||||||
};
|
|
||||||
Self::with_backing_store(scope, &backing_store.make_shared())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Data length in bytes.
|
/// Data length in bytes.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn byte_length(&self) -> usize {
|
pub fn byte_length(&self) -> usize {
|
||||||
|
@ -593,11 +582,6 @@ impl ArrayBuffer {
|
||||||
T: sealed::Rawable,
|
T: sealed::Rawable,
|
||||||
{
|
{
|
||||||
let len = bytes.byte_len();
|
let len = bytes.byte_len();
|
||||||
if len == 0 {
|
|
||||||
return unsafe {
|
|
||||||
UniqueRef::from_raw(v8__BackingStore__EmptyBackingStore(false))
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
let (ptr, slice) = T::into_raw(bytes);
|
let (ptr, slice) = T::into_raw(bytes);
|
||||||
|
|
||||||
|
|
131
src/binding.cc
131
src/binding.cc
|
@ -4,34 +4,24 @@
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <iostream>
|
#include <thread>
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
#include "cppgc/allocation.h"
|
#include "cppgc/allocation.h"
|
||||||
|
#include "cppgc/persistent.h"
|
||||||
#include "cppgc/platform.h"
|
#include "cppgc/platform.h"
|
||||||
|
#include "libplatform/libplatform.h"
|
||||||
#include "support.h"
|
#include "support.h"
|
||||||
#include "unicode/locid.h"
|
#include "unicode/locid.h"
|
||||||
#include "v8-callbacks.h"
|
#include "v8-callbacks.h"
|
||||||
#include "v8/include/cppgc/persistent.h"
|
#include "v8-cppgc.h"
|
||||||
#include "v8/include/libplatform/libplatform.h"
|
#include "v8-fast-api-calls.h"
|
||||||
#include "v8/include/v8-cppgc.h"
|
#include "v8-inspector.h"
|
||||||
#include "v8/include/v8-fast-api-calls.h"
|
#include "v8-internal.h"
|
||||||
#include "v8/include/v8-inspector.h"
|
#include "v8-platform.h"
|
||||||
#include "v8/include/v8-internal.h"
|
#include "v8-profiler.h"
|
||||||
#include "v8/include/v8-platform.h"
|
#include "v8.h"
|
||||||
#include "v8/include/v8-profiler.h"
|
|
||||||
#include "v8/include/v8.h"
|
|
||||||
#include "v8/src/api/api-inl.h"
|
|
||||||
#include "v8/src/api/api.h"
|
|
||||||
#include "v8/src/base/debug/stack_trace.h"
|
|
||||||
#include "v8/src/base/sys-info.h"
|
|
||||||
#include "v8/src/execution/isolate-utils-inl.h"
|
|
||||||
#include "v8/src/execution/isolate-utils.h"
|
|
||||||
#include "v8/src/flags/flags.h"
|
#include "v8/src/flags/flags.h"
|
||||||
#include "v8/src/libplatform/default-platform.h"
|
#include "v8/src/libplatform/default-platform.h"
|
||||||
#include "v8/src/objects/objects-inl.h"
|
|
||||||
#include "v8/src/objects/objects.h"
|
|
||||||
#include "v8/src/objects/smi.h"
|
|
||||||
|
|
||||||
using namespace support;
|
using namespace support;
|
||||||
|
|
||||||
|
@ -125,9 +115,6 @@ static_assert(sizeof(v8::Isolate::DisallowJavascriptExecutionScope) == 12,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
const extern int v8__internal__Internals__kIsolateEmbedderDataOffset =
|
|
||||||
v8::internal::Internals::kIsolateEmbedderDataOffset;
|
|
||||||
|
|
||||||
void v8__V8__SetFlagsFromCommandLine(int* argc, char** argv,
|
void v8__V8__SetFlagsFromCommandLine(int* argc, char** argv,
|
||||||
const char* usage) {
|
const char* usage) {
|
||||||
namespace i = v8::internal;
|
namespace i = v8::internal;
|
||||||
|
@ -204,6 +191,14 @@ uint32_t v8__Isolate__GetNumberOfDataSlots(v8::Isolate* isolate) {
|
||||||
return isolate->GetNumberOfDataSlots();
|
return isolate->GetNumberOfDataSlots();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void* v8__Isolate__GetData(v8::Isolate* isolate, uint32_t slot) {
|
||||||
|
return isolate->GetData(slot);
|
||||||
|
}
|
||||||
|
|
||||||
|
void v8__Isolate__SetData(v8::Isolate* isolate, uint32_t slot, void* data) {
|
||||||
|
isolate->SetData(slot, data);
|
||||||
|
}
|
||||||
|
|
||||||
const v8::Data* v8__Isolate__GetDataFromSnapshotOnce(v8::Isolate* isolate,
|
const v8::Data* v8__Isolate__GetDataFromSnapshotOnce(v8::Isolate* isolate,
|
||||||
size_t index) {
|
size_t index) {
|
||||||
return maybe_local_to_ptr(isolate->GetDataFromSnapshotOnce<v8::Data>(index));
|
return maybe_local_to_ptr(isolate->GetDataFromSnapshotOnce<v8::Data>(index));
|
||||||
|
@ -577,17 +572,17 @@ bool v8__Data__EQ(const v8::Data& self, const v8::Data& other) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool v8__Data__IsBigInt(const v8::Data& self) {
|
bool v8__Data__IsBigInt(const v8::Data& self) {
|
||||||
return IsBigInt(*v8::Utils::OpenHandle(&self));
|
return self.IsValue() && reinterpret_cast<const v8::Value&>(self).IsBigInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool v8__Data__IsBoolean(const v8::Data& self) {
|
bool v8__Data__IsBoolean(const v8::Data& self) {
|
||||||
return IsBoolean(*v8::Utils::OpenHandle(&self));
|
return self.IsValue() && reinterpret_cast<const v8::Value&>(self).IsBoolean();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool v8__Data__IsContext(const v8::Data& self) { return self.IsContext(); }
|
bool v8__Data__IsContext(const v8::Data& self) { return self.IsContext(); }
|
||||||
|
|
||||||
bool v8__Data__IsFixedArray(const v8::Data& self) {
|
bool v8__Data__IsFixedArray(const v8::Data& self) {
|
||||||
return IsFixedArray(*v8::Utils::OpenHandle(&self));
|
return self.IsFixedArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool v8__Data__IsFunctionTemplate(const v8::Data& self) {
|
bool v8__Data__IsFunctionTemplate(const v8::Data& self) {
|
||||||
|
@ -597,15 +592,15 @@ bool v8__Data__IsFunctionTemplate(const v8::Data& self) {
|
||||||
bool v8__Data__IsModule(const v8::Data& self) { return self.IsModule(); }
|
bool v8__Data__IsModule(const v8::Data& self) { return self.IsModule(); }
|
||||||
|
|
||||||
bool v8__Data__IsModuleRequest(const v8::Data& self) {
|
bool v8__Data__IsModuleRequest(const v8::Data& self) {
|
||||||
return IsModuleRequest(*v8::Utils::OpenHandle(&self));
|
return self.IsModuleRequest();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool v8__Data__IsName(const v8::Data& self) {
|
bool v8__Data__IsName(const v8::Data& self) {
|
||||||
return IsName(*v8::Utils::OpenHandle(&self));
|
return self.IsValue() && reinterpret_cast<const v8::Value&>(self).IsName();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool v8__Data__IsNumber(const v8::Data& self) {
|
bool v8__Data__IsNumber(const v8::Data& self) {
|
||||||
return IsNumber(*v8::Utils::OpenHandle(&self));
|
return self.IsValue() && reinterpret_cast<const v8::Value&>(self).IsNumber();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool v8__Data__IsObjectTemplate(const v8::Data& self) {
|
bool v8__Data__IsObjectTemplate(const v8::Data& self) {
|
||||||
|
@ -613,17 +608,18 @@ bool v8__Data__IsObjectTemplate(const v8::Data& self) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool v8__Data__IsPrimitive(const v8::Data& self) {
|
bool v8__Data__IsPrimitive(const v8::Data& self) {
|
||||||
return IsPrimitive(*v8::Utils::OpenHandle(&self)) && !self.IsPrivate();
|
return self.IsValue() &&
|
||||||
|
reinterpret_cast<const v8::Value&>(self).IsPrimitive();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool v8__Data__IsPrivate(const v8::Data& self) { return self.IsPrivate(); }
|
bool v8__Data__IsPrivate(const v8::Data& self) { return self.IsPrivate(); }
|
||||||
|
|
||||||
bool v8__Data__IsString(const v8::Data& self) {
|
bool v8__Data__IsString(const v8::Data& self) {
|
||||||
return IsString(*v8::Utils::OpenHandle(&self));
|
return self.IsValue() && reinterpret_cast<const v8::Value&>(self).IsString();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool v8__Data__IsSymbol(const v8::Data& self) {
|
bool v8__Data__IsSymbol(const v8::Data& self) {
|
||||||
return IsPublicSymbol(*v8::Utils::OpenHandle(&self));
|
return self.IsValue() && reinterpret_cast<const v8::Value&>(self).IsSymbol();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool v8__Data__IsValue(const v8::Data& self) { return self.IsValue(); }
|
bool v8__Data__IsValue(const v8::Data& self) { return self.IsValue(); }
|
||||||
|
@ -896,6 +892,8 @@ const v8::String* v8__Value__TypeOf(v8::Value& self, v8::Isolate* isolate) {
|
||||||
return local_to_ptr(self.TypeOf(isolate));
|
return local_to_ptr(self.TypeOf(isolate));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t v8__Value__GetHash(v8::Value& self) { return self.GetHash(); }
|
||||||
|
|
||||||
const v8::Primitive* v8__Null(v8::Isolate* isolate) {
|
const v8::Primitive* v8__Null(v8::Isolate* isolate) {
|
||||||
return local_to_ptr(v8::Null(isolate));
|
return local_to_ptr(v8::Null(isolate));
|
||||||
}
|
}
|
||||||
|
@ -954,12 +952,6 @@ two_pointers_t v8__ArrayBuffer__GetBackingStore(const v8::ArrayBuffer& self) {
|
||||||
return make_pod<two_pointers_t>(ptr_to_local(&self)->GetBackingStore());
|
return make_pod<two_pointers_t>(ptr_to_local(&self)->GetBackingStore());
|
||||||
}
|
}
|
||||||
|
|
||||||
v8::BackingStore* v8__BackingStore__EmptyBackingStore(bool shared) {
|
|
||||||
std::unique_ptr<i::BackingStoreBase> u = i::BackingStore::EmptyBackingStore(
|
|
||||||
shared ? i::SharedFlag::kShared : i::SharedFlag::kNotShared);
|
|
||||||
return static_cast<v8::BackingStore*>(u.release());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool v8__BackingStore__IsResizableByUserJavaScript(
|
bool v8__BackingStore__IsResizableByUserJavaScript(
|
||||||
const v8::BackingStore& self) {
|
const v8::BackingStore& self) {
|
||||||
return ptr_to_local(&self)->IsResizableByUserJavaScript();
|
return ptr_to_local(&self)->IsResizableByUserJavaScript();
|
||||||
|
@ -2361,10 +2353,10 @@ const v8::Object* v8__PropertyCallbackInfo__Holder(
|
||||||
return local_to_ptr(self.HolderV2());
|
return local_to_ptr(self.HolderV2());
|
||||||
}
|
}
|
||||||
|
|
||||||
v8::internal::Address* v8__PropertyCallbackInfo__GetReturnValue(
|
uintptr_t* v8__PropertyCallbackInfo__GetReturnValue(
|
||||||
const v8::PropertyCallbackInfo<v8::Value>& self) {
|
const v8::PropertyCallbackInfo<v8::Value>& self) {
|
||||||
v8::ReturnValue<v8::Value> rv = self.GetReturnValue();
|
v8::ReturnValue<v8::Value> rv = self.GetReturnValue();
|
||||||
return *reinterpret_cast<v8::internal::Address**>(&rv);
|
return *reinterpret_cast<uintptr_t**>(&rv);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool v8__PropertyCallbackInfo__ShouldThrowOnError(
|
bool v8__PropertyCallbackInfo__ShouldThrowOnError(
|
||||||
|
@ -2877,8 +2869,6 @@ class UnprotectedDefaultPlatform : public v8::platform::DefaultPlatform {
|
||||||
using PriorityMode = v8::platform::PriorityMode;
|
using PriorityMode = v8::platform::PriorityMode;
|
||||||
using TracingController = v8::TracingController;
|
using TracingController = v8::TracingController;
|
||||||
|
|
||||||
static constexpr int kMaxThreadPoolSize = 16;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit UnprotectedDefaultPlatform(
|
explicit UnprotectedDefaultPlatform(
|
||||||
int thread_pool_size, IdleTaskSupport idle_task_support,
|
int thread_pool_size, IdleTaskSupport idle_task_support,
|
||||||
|
@ -2888,28 +2878,8 @@ class UnprotectedDefaultPlatform : public v8::platform::DefaultPlatform {
|
||||||
std::move(tracing_controller),
|
std::move(tracing_controller),
|
||||||
priority_mode) {}
|
priority_mode) {}
|
||||||
|
|
||||||
static std::unique_ptr<v8::Platform> New(
|
|
||||||
int thread_pool_size, IdleTaskSupport idle_task_support,
|
|
||||||
InProcessStackDumping in_process_stack_dumping,
|
|
||||||
std::unique_ptr<TracingController> tracing_controller = {},
|
|
||||||
PriorityMode priority_mode = PriorityMode::kDontApply) {
|
|
||||||
// This implementation is semantically equivalent to the implementation of
|
|
||||||
// `v8::platform::NewDefaultPlatform()`.
|
|
||||||
DCHECK_GE(thread_pool_size, 0);
|
|
||||||
if (thread_pool_size < 1) {
|
|
||||||
thread_pool_size =
|
|
||||||
std::max(v8::base::SysInfo::NumberOfProcessors() - 1, 1);
|
|
||||||
}
|
|
||||||
thread_pool_size = std::min(thread_pool_size, kMaxThreadPoolSize);
|
|
||||||
if (in_process_stack_dumping == InProcessStackDumping::kEnabled) {
|
|
||||||
v8::base::debug::EnableInProcessStackDumping();
|
|
||||||
}
|
|
||||||
return std::make_unique<UnprotectedDefaultPlatform>(
|
|
||||||
thread_pool_size, idle_task_support, std::move(tracing_controller),
|
|
||||||
priority_mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
v8::ThreadIsolatedAllocator* GetThreadIsolatedAllocator() override {
|
v8::ThreadIsolatedAllocator* GetThreadIsolatedAllocator() override {
|
||||||
|
// DefaultThreadIsolatedAllocator is PKU protected
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -2926,11 +2896,14 @@ v8::Platform* v8__Platform__NewDefaultPlatform(int thread_pool_size,
|
||||||
|
|
||||||
v8::Platform* v8__Platform__NewUnprotectedDefaultPlatform(
|
v8::Platform* v8__Platform__NewUnprotectedDefaultPlatform(
|
||||||
int thread_pool_size, bool idle_task_support) {
|
int thread_pool_size, bool idle_task_support) {
|
||||||
return UnprotectedDefaultPlatform::New(
|
if (thread_pool_size < 1) {
|
||||||
thread_pool_size,
|
thread_pool_size = std::thread::hardware_concurrency();
|
||||||
idle_task_support ? v8::platform::IdleTaskSupport::kEnabled
|
}
|
||||||
: v8::platform::IdleTaskSupport::kDisabled,
|
thread_pool_size = std::max(std::min(thread_pool_size, 16), 1);
|
||||||
v8::platform::InProcessStackDumping::kDisabled, nullptr)
|
return std::make_unique<UnprotectedDefaultPlatform>(
|
||||||
|
thread_pool_size, idle_task_support
|
||||||
|
? v8::platform::IdleTaskSupport::kEnabled
|
||||||
|
: v8::platform::IdleTaskSupport::kDisabled)
|
||||||
.release();
|
.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3422,28 +3395,6 @@ void v8__HeapProfiler__TakeHeapSnapshot(v8::Isolate* isolate,
|
||||||
const_cast<v8::HeapSnapshot*>(snapshot)->Delete();
|
const_cast<v8::HeapSnapshot*>(snapshot)->Delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
v8::Isolate* v8__internal__GetIsolateFromHeapObject(const v8::Data& data) {
|
|
||||||
namespace i = v8::internal;
|
|
||||||
i::Tagged<i::Object> object(reinterpret_cast<const i::Address&>(data));
|
|
||||||
i::Isolate* isolate;
|
|
||||||
return IsHeapObject(object) &&
|
|
||||||
i::GetIsolateFromHeapObject(object.GetHeapObject(), &isolate)
|
|
||||||
? reinterpret_cast<v8::Isolate*>(isolate)
|
|
||||||
: nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
int v8__Value__GetHash(const v8::Value& data) {
|
|
||||||
namespace i = v8::internal;
|
|
||||||
i::Tagged<i::Object> object(reinterpret_cast<const i::Address&>(data));
|
|
||||||
i::Isolate* isolate;
|
|
||||||
int hash = IsHeapObject(object) && i::GetIsolateFromHeapObject(
|
|
||||||
object.GetHeapObject(), &isolate)
|
|
||||||
? i::Object::GetOrCreateHash(object, isolate).value()
|
|
||||||
: i::Smi::ToInt(i::Object::GetHash(object));
|
|
||||||
assert(hash != 0);
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
void v8__HeapStatistics__CONSTRUCT(uninit_t<v8::HeapStatistics>* buf) {
|
void v8__HeapStatistics__CONSTRUCT(uninit_t<v8::HeapStatistics>* buf) {
|
||||||
// Should be <= than its counterpart in src/isolate.rs
|
// Should be <= than its counterpart in src/isolate.rs
|
||||||
static_assert(sizeof(v8::HeapStatistics) <= sizeof(uintptr_t[16]),
|
static_assert(sizeof(v8::HeapStatistics) <= sizeof(uintptr_t[16]),
|
||||||
|
|
|
@ -588,11 +588,15 @@ pub type UseCounterCallback =
|
||||||
unsafe extern "C" fn(&mut Isolate, UseCounterFeature);
|
unsafe extern "C" fn(&mut Isolate, UseCounterFeature);
|
||||||
|
|
||||||
unsafe extern "C" {
|
unsafe extern "C" {
|
||||||
static v8__internal__Internals__kIsolateEmbedderDataOffset: int;
|
|
||||||
|
|
||||||
fn v8__Isolate__New(params: *const raw::CreateParams) -> *mut Isolate;
|
fn v8__Isolate__New(params: *const raw::CreateParams) -> *mut Isolate;
|
||||||
fn v8__Isolate__Dispose(this: *mut Isolate);
|
fn v8__Isolate__Dispose(this: *mut Isolate);
|
||||||
fn v8__Isolate__GetNumberOfDataSlots(this: *const Isolate) -> u32;
|
fn v8__Isolate__GetNumberOfDataSlots(this: *const Isolate) -> u32;
|
||||||
|
fn v8__Isolate__GetData(isolate: *const Isolate, slot: u32) -> *mut c_void;
|
||||||
|
fn v8__Isolate__SetData(
|
||||||
|
isolate: *const Isolate,
|
||||||
|
slot: u32,
|
||||||
|
data: *mut c_void,
|
||||||
|
);
|
||||||
fn v8__Isolate__Enter(this: *mut Isolate);
|
fn v8__Isolate__Enter(this: *mut Isolate);
|
||||||
fn v8__Isolate__Exit(this: *mut Isolate);
|
fn v8__Isolate__Exit(this: *mut Isolate);
|
||||||
fn v8__Isolate__GetCurrent() -> *mut Isolate;
|
fn v8__Isolate__GetCurrent() -> *mut Isolate;
|
||||||
|
@ -782,14 +786,6 @@ unsafe extern "C" {
|
||||||
pub struct Isolate(Opaque);
|
pub struct Isolate(Opaque);
|
||||||
|
|
||||||
impl Isolate {
|
impl Isolate {
|
||||||
// Total number of isolate data slots provided by V8.
|
|
||||||
const EMBEDDER_DATA_SLOT_COUNT: u32 = 4;
|
|
||||||
|
|
||||||
// Byte offset inside `Isolate` where the isolate data slots are stored. This
|
|
||||||
// should be the same as the value of `kIsolateEmbedderDataOffset` which is
|
|
||||||
// defined in `v8-internal.h`.
|
|
||||||
const EMBEDDER_DATA_OFFSET: usize = size_of::<[*const (); 73]>();
|
|
||||||
|
|
||||||
// Isolate data slots used internally by rusty_v8.
|
// Isolate data slots used internally by rusty_v8.
|
||||||
const ANNEX_SLOT: u32 = 0;
|
const ANNEX_SLOT: u32 = 0;
|
||||||
const CURRENT_SCOPE_DATA_SLOT: u32 = 1;
|
const CURRENT_SCOPE_DATA_SLOT: u32 = 1;
|
||||||
|
@ -797,14 +793,10 @@ impl Isolate {
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn assert_embedder_data_slot_count_and_offset_correct(&self) {
|
fn assert_embedder_data_slot_count_and_offset_correct(&self) {
|
||||||
assert_eq!(
|
assert!(
|
||||||
unsafe { v8__Isolate__GetNumberOfDataSlots(self) },
|
unsafe { v8__Isolate__GetNumberOfDataSlots(self) }
|
||||||
Self::EMBEDDER_DATA_SLOT_COUNT
|
>= Self::INTERNAL_DATA_SLOT_COUNT
|
||||||
);
|
)
|
||||||
assert_eq!(
|
|
||||||
unsafe { v8__internal__Internals__kIsolateEmbedderDataOffset } as usize,
|
|
||||||
Self::EMBEDDER_DATA_OFFSET
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_impl(params: CreateParams) -> *mut Isolate {
|
fn new_impl(params: CreateParams) -> *mut Isolate {
|
||||||
|
@ -977,29 +969,18 @@ impl Isolate {
|
||||||
/// Returns the maximum number of available embedder data slots. Valid slots
|
/// Returns the maximum number of available embedder data slots. Valid slots
|
||||||
/// are in the range of `0 <= n < Isolate::get_number_of_data_slots()`.
|
/// are in the range of `0 <= n < Isolate::get_number_of_data_slots()`.
|
||||||
pub fn get_number_of_data_slots(&self) -> u32 {
|
pub fn get_number_of_data_slots(&self) -> u32 {
|
||||||
Self::EMBEDDER_DATA_SLOT_COUNT - Self::INTERNAL_DATA_SLOT_COUNT
|
let n = unsafe { v8__Isolate__GetNumberOfDataSlots(self) };
|
||||||
|
n - Self::INTERNAL_DATA_SLOT_COUNT
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn get_data_internal(&self, slot: u32) -> *mut c_void {
|
pub(crate) fn get_data_internal(&self, slot: u32) -> *mut c_void {
|
||||||
let slots = unsafe {
|
unsafe { v8__Isolate__GetData(self, slot) }
|
||||||
let p = self as *const Self as *const u8;
|
|
||||||
let p = p.add(Self::EMBEDDER_DATA_OFFSET);
|
|
||||||
let p = p as *const [*mut c_void; Self::EMBEDDER_DATA_SLOT_COUNT as _];
|
|
||||||
&*p
|
|
||||||
};
|
|
||||||
slots[slot as usize]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn set_data_internal(&mut self, slot: u32, data: *mut c_void) {
|
pub(crate) fn set_data_internal(&mut self, slot: u32, data: *mut c_void) {
|
||||||
let slots = unsafe {
|
unsafe { v8__Isolate__SetData(self, slot, data) }
|
||||||
let p = self as *mut Self as *mut u8;
|
|
||||||
let p = p.add(Self::EMBEDDER_DATA_OFFSET);
|
|
||||||
let p = p as *mut [*mut c_void; Self::EMBEDDER_DATA_SLOT_COUNT as _];
|
|
||||||
&mut *p
|
|
||||||
};
|
|
||||||
slots[slot as usize] = data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn init_scope_root(&mut self) {
|
pub(crate) fn init_scope_root(&mut self) {
|
||||||
|
|
|
@ -35,7 +35,6 @@ unsafe extern "C" {
|
||||||
deleter: BackingStoreDeleterCallback,
|
deleter: BackingStoreDeleterCallback,
|
||||||
deleter_data: *mut c_void,
|
deleter_data: *mut c_void,
|
||||||
) -> *mut BackingStore;
|
) -> *mut BackingStore;
|
||||||
fn v8__BackingStore__EmptyBackingStore(shared: bool) -> *mut BackingStore;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SharedArrayBuffer {
|
impl SharedArrayBuffer {
|
||||||
|
@ -74,17 +73,6 @@ impl SharedArrayBuffer {
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new, empty SharedArrayBuffer.
|
|
||||||
#[inline(always)]
|
|
||||||
pub fn empty<'s>(
|
|
||||||
scope: &mut HandleScope<'s>,
|
|
||||||
) -> Local<'s, SharedArrayBuffer> {
|
|
||||||
// SAFETY: This is a v8-provided empty backing store
|
|
||||||
let backing_store =
|
|
||||||
unsafe { UniqueRef::from_raw(v8__BackingStore__EmptyBackingStore(true)) };
|
|
||||||
Self::with_backing_store(scope, &backing_store.make_shared())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Data length in bytes.
|
/// Data length in bytes.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn byte_length(&self) -> usize {
|
pub fn byte_length(&self) -> usize {
|
||||||
|
@ -173,11 +161,6 @@ impl SharedArrayBuffer {
|
||||||
T: crate::array_buffer::sealed::Rawable,
|
T: crate::array_buffer::sealed::Rawable,
|
||||||
{
|
{
|
||||||
let len = bytes.byte_len();
|
let len = bytes.byte_len();
|
||||||
if len == 0 {
|
|
||||||
return unsafe {
|
|
||||||
UniqueRef::from_raw(v8__BackingStore__EmptyBackingStore(false))
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
let (ptr, slice) = T::into_raw(bytes);
|
let (ptr, slice) = T::into_raw(bytes);
|
||||||
|
|
||||||
|
|
|
@ -9,29 +9,9 @@
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include "v8/include/cppgc/name-provider.h"
|
#include "cppgc/name-provider.h"
|
||||||
#include "v8/include/v8-cppgc.h"
|
#include "v8-cppgc.h"
|
||||||
#include "v8/include/v8.h"
|
#include "v8.h"
|
||||||
|
|
||||||
// Work around a bug in the V8 headers.
|
|
||||||
//
|
|
||||||
// The following template is defined in v8-internal.h. It has a subtle bug that
|
|
||||||
// indirectly makes it impossible to convert `v8::Data` handles to themselves.
|
|
||||||
// Some methods do that impliclity so they don't compile without this hack; one
|
|
||||||
// example is `Local<Data> MaybeLocal::FromMaybe(Local<Data> default_value)`.
|
|
||||||
//
|
|
||||||
// Spot the bug :)
|
|
||||||
//
|
|
||||||
// ```
|
|
||||||
// template <class T>
|
|
||||||
// V8_INLINE void PerformCastCheck(T* data) {
|
|
||||||
// CastCheck<std::is_base_of<Data, T>::value &&
|
|
||||||
// !std::is_same<Data, std::remove_cv<T>>::value>::Perform(data);
|
|
||||||
// }
|
|
||||||
// ```
|
|
||||||
template <>
|
|
||||||
template <>
|
|
||||||
inline void v8::internal::CastCheck<true>::Perform<v8::Data>(v8::Data* data) {}
|
|
||||||
|
|
||||||
// Check assumptions made in binding code.
|
// Check assumptions made in binding code.
|
||||||
static_assert(sizeof(bool) == sizeof(uint8_t), "");
|
static_assert(sizeof(bool) == sizeof(uint8_t), "");
|
||||||
|
|
18
src/value.rs
18
src/value.rs
|
@ -1,5 +1,3 @@
|
||||||
use std::num::NonZeroI32;
|
|
||||||
|
|
||||||
use crate::BigInt;
|
use crate::BigInt;
|
||||||
use crate::Boolean;
|
use crate::Boolean;
|
||||||
use crate::Context;
|
use crate::Context;
|
||||||
|
@ -14,7 +12,6 @@ use crate::String;
|
||||||
use crate::Uint32;
|
use crate::Uint32;
|
||||||
use crate::Value;
|
use crate::Value;
|
||||||
use crate::support::Maybe;
|
use crate::support::Maybe;
|
||||||
use crate::support::int;
|
|
||||||
|
|
||||||
unsafe extern "C" {
|
unsafe extern "C" {
|
||||||
fn v8__Value__IsUndefined(this: *const Value) -> bool;
|
fn v8__Value__IsUndefined(this: *const Value) -> bool;
|
||||||
|
@ -142,7 +139,7 @@ unsafe extern "C" {
|
||||||
);
|
);
|
||||||
fn v8__Value__BooleanValue(this: *const Value, isolate: *mut Isolate)
|
fn v8__Value__BooleanValue(this: *const Value, isolate: *mut Isolate)
|
||||||
-> bool;
|
-> bool;
|
||||||
fn v8__Value__GetHash(this: *const Value) -> int;
|
fn v8__Value__GetHash(this: *const Value) -> u32;
|
||||||
fn v8__Value__TypeOf(
|
fn v8__Value__TypeOf(
|
||||||
this: *const Value,
|
this: *const Value,
|
||||||
isolate: *mut Isolate,
|
isolate: *mut Isolate,
|
||||||
|
@ -704,14 +701,13 @@ impl Value {
|
||||||
unsafe { v8__Value__BooleanValue(self, scope.get_isolate_ptr()) }
|
unsafe { v8__Value__BooleanValue(self, scope.get_isolate_ptr()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the V8 hash value for this value. The current implementation
|
/// Get the hash of this value. The hash is not guaranteed to be
|
||||||
/// uses a hidden property to store the identity hash on some object types.
|
/// unique. For |Object| and |Name| instances the result is equal to
|
||||||
///
|
/// |GetIdentityHash|. Hashes are not guaranteed to be stable across
|
||||||
/// The return value will never be 0. Also, it is not guaranteed to be
|
/// different isolates or processes.
|
||||||
/// unique.
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn get_hash(&self) -> NonZeroI32 {
|
pub fn get_hash(&self) -> u32 {
|
||||||
unsafe { NonZeroI32::new_unchecked(v8__Value__GetHash(self)) }
|
unsafe { v8__Value__GetHash(self) }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
|
|
@ -11,7 +11,7 @@ use std::ffi::c_void;
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
use std::mem::MaybeUninit;
|
use std::mem::MaybeUninit;
|
||||||
use std::os::raw::c_char;
|
use std::os::raw::c_char;
|
||||||
use std::ptr::{NonNull, addr_of, addr_of_mut};
|
use std::ptr::{addr_of, addr_of_mut};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
|
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
|
||||||
|
@ -650,85 +650,6 @@ fn isolate_drop_order() {
|
||||||
drop(isolate2);
|
drop(isolate2);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn get_isolate_from_handle() {
|
|
||||||
unsafe extern "C" {
|
|
||||||
fn v8__internal__GetIsolateFromHeapObject(
|
|
||||||
location: *const v8::Data,
|
|
||||||
) -> *mut v8::Isolate;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn check_handle_helper(
|
|
||||||
isolate: &mut v8::Isolate,
|
|
||||||
expect_some: Option<bool>,
|
|
||||||
local: v8::Local<v8::Data>,
|
|
||||||
) {
|
|
||||||
let isolate_ptr = NonNull::from(isolate);
|
|
||||||
let maybe_ptr = unsafe { v8__internal__GetIsolateFromHeapObject(&*local) };
|
|
||||||
let maybe_ptr = NonNull::new(maybe_ptr);
|
|
||||||
if let Some(ptr) = maybe_ptr {
|
|
||||||
assert_eq!(ptr, isolate_ptr);
|
|
||||||
}
|
|
||||||
if let Some(expected_some) = expect_some {
|
|
||||||
assert_eq!(maybe_ptr.is_some(), expected_some);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn check_handle<'s, F, D>(
|
|
||||||
scope: &mut v8::HandleScope<'s>,
|
|
||||||
expect_some: Option<bool>,
|
|
||||||
f: F,
|
|
||||||
) where
|
|
||||||
F: Fn(&mut v8::HandleScope<'s>) -> D,
|
|
||||||
D: Into<v8::Local<'s, v8::Data>>,
|
|
||||||
{
|
|
||||||
let local = f(scope).into();
|
|
||||||
|
|
||||||
// Check that we can get the isolate from a Local.
|
|
||||||
check_handle_helper(scope, expect_some, local);
|
|
||||||
|
|
||||||
// Check that we can still get it after converting it to a Global.
|
|
||||||
let global = v8::Global::new(scope, local);
|
|
||||||
let local2 = v8::Local::new(scope, &global);
|
|
||||||
check_handle_helper(scope, expect_some, local2);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn check_eval(
|
|
||||||
scope: &mut v8::HandleScope,
|
|
||||||
expect_some: Option<bool>,
|
|
||||||
code: &str,
|
|
||||||
) {
|
|
||||||
check_handle(scope, expect_some, |scope| eval(scope, code).unwrap());
|
|
||||||
}
|
|
||||||
|
|
||||||
let _setup_guard = setup::parallel_test();
|
|
||||||
let isolate = &mut v8::Isolate::new(Default::default());
|
|
||||||
|
|
||||||
let scope = &mut v8::HandleScope::new(isolate);
|
|
||||||
let context = v8::Context::new(scope, Default::default());
|
|
||||||
let scope = &mut v8::ContextScope::new(scope, context);
|
|
||||||
|
|
||||||
check_handle(scope, None, v8::null);
|
|
||||||
check_handle(scope, None, v8::undefined);
|
|
||||||
check_handle(scope, None, |s| v8::Boolean::new(s, true));
|
|
||||||
check_handle(scope, None, |s| v8::Boolean::new(s, false));
|
|
||||||
check_handle(scope, None, |s| v8::String::new(s, "").unwrap());
|
|
||||||
check_eval(scope, None, "''");
|
|
||||||
check_handle(scope, Some(true), |s| v8::String::new(s, "Words").unwrap());
|
|
||||||
check_eval(scope, Some(true), "'Hello'");
|
|
||||||
check_eval(scope, Some(true), "Symbol()");
|
|
||||||
check_handle(scope, Some(true), v8::Object::new);
|
|
||||||
check_eval(scope, Some(true), "this");
|
|
||||||
check_handle(scope, Some(true), |s| s.get_current_context());
|
|
||||||
check_eval(scope, Some(true), "({ foo: 'bar' })");
|
|
||||||
check_eval(scope, Some(true), "() => {}");
|
|
||||||
check_handle(scope, Some(true), |s| v8::Number::new(s, 4.2f64));
|
|
||||||
check_handle(scope, Some(true), |s| v8::Number::new(s, -0f64));
|
|
||||||
check_handle(scope, Some(false), |s| v8::Integer::new(s, 0));
|
|
||||||
check_eval(scope, Some(true), "3.3");
|
|
||||||
check_eval(scope, Some(false), "3.3 / 3.3");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn handles_from_isolate() {
|
fn handles_from_isolate() {
|
||||||
let _setup_guard = setup::parallel_test();
|
let _setup_guard = setup::parallel_test();
|
||||||
|
@ -861,7 +782,7 @@ fn array_buffer() {
|
||||||
assert_eq!(shared_bs_2[9].get(), 9);
|
assert_eq!(shared_bs_2[9].get(), 9);
|
||||||
|
|
||||||
// Empty
|
// Empty
|
||||||
let ab = v8::ArrayBuffer::empty(scope);
|
let ab = v8::ArrayBuffer::new(scope, 0);
|
||||||
assert_eq!(0, ab.byte_length());
|
assert_eq!(0, ab.byte_length());
|
||||||
assert!(!ab.get_backing_store().is_shared());
|
assert!(!ab.get_backing_store().is_shared());
|
||||||
|
|
||||||
|
@ -3009,8 +2930,8 @@ fn object() {
|
||||||
let object_ = v8::Object::new(scope);
|
let object_ = v8::Object::new(scope);
|
||||||
assert!(!object_.is_null_or_undefined());
|
assert!(!object_.is_null_or_undefined());
|
||||||
let id = object_.get_identity_hash();
|
let id = object_.get_identity_hash();
|
||||||
assert_eq!(id, object_.get_hash());
|
assert_eq!(id.get() as u32, object_.get_hash());
|
||||||
assert_ne!(id, v8::Object::new(scope).get_hash());
|
assert_ne!(id.get() as u32, v8::Object::new(scope).get_hash());
|
||||||
|
|
||||||
assert!(object.has(scope, n1.into()).unwrap());
|
assert!(object.has(scope, n1.into()).unwrap());
|
||||||
assert!(object.has_own_property(scope, n1).unwrap());
|
assert!(object.has_own_property(scope, n1).unwrap());
|
||||||
|
@ -5336,7 +5257,7 @@ fn get_hash() {
|
||||||
let hash = pri1.get_hash();
|
let hash = pri1.get_hash();
|
||||||
assert_eq!(hash, pri2.get_hash());
|
assert_eq!(hash, pri2.get_hash());
|
||||||
if let Ok(name) = v8::Local::<v8::Name>::try_from(pri1) {
|
if let Ok(name) = v8::Local::<v8::Name>::try_from(pri1) {
|
||||||
assert_eq!(hash, name.get_identity_hash());
|
assert_eq!(hash, name.get_identity_hash().get() as u32);
|
||||||
name_count += 1;
|
name_count += 1;
|
||||||
}
|
}
|
||||||
if !hashes.insert(hash) {
|
if !hashes.insert(hash) {
|
||||||
|
@ -5381,7 +5302,7 @@ fn get_hash() {
|
||||||
let val = objects.get_index(scope, i).unwrap();
|
let val = objects.get_index(scope, i).unwrap();
|
||||||
let hash = val.get_hash();
|
let hash = val.get_hash();
|
||||||
let obj = v8::Local::<v8::Object>::try_from(val).unwrap();
|
let obj = v8::Local::<v8::Object>::try_from(val).unwrap();
|
||||||
assert_eq!(hash, obj.get_identity_hash());
|
assert_eq!(hash, obj.get_identity_hash().get() as u32);
|
||||||
if !hashes.insert(hash) {
|
if !hashes.insert(hash) {
|
||||||
collision_count += 1;
|
collision_count += 1;
|
||||||
}
|
}
|
||||||
|
@ -6055,7 +5976,7 @@ fn shared_array_buffer() {
|
||||||
assert_eq!(shared_bs_3[9].get(), 9);
|
assert_eq!(shared_bs_3[9].get(), 9);
|
||||||
|
|
||||||
// Empty
|
// Empty
|
||||||
let ab = v8::SharedArrayBuffer::empty(scope);
|
let ab = v8::SharedArrayBuffer::new(scope, 0).unwrap();
|
||||||
assert_eq!(ab.byte_length(), 0);
|
assert_eq!(ab.byte_length(), 0);
|
||||||
assert!(ab.get_backing_store().is_shared());
|
assert!(ab.get_backing_store().is_shared());
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue