mirror of
https://github.com/lexmount/moli.git
synced 2026-10-04 16:00:47 +00:00
vendor(v8): add browsing context lifecycle bridges
This commit is contained in:
Vendored
+8
@@ -28,6 +28,7 @@ unsafe extern "C" {
|
||||
) -> *const Context;
|
||||
fn v8__Isolate__GetCurrent() -> *mut RealIsolate;
|
||||
fn v8__Context__Global(this: *const Context) -> *const Object;
|
||||
fn v8__Context__DetachGlobal(this: *const Context);
|
||||
fn v8__Context__GetExtrasBindingObject(this: *const Context)
|
||||
-> *const Object;
|
||||
fn v8__Context__GetNumberOfEmbedderDataFields(this: *const Context) -> u32;
|
||||
@@ -143,6 +144,13 @@ impl Context {
|
||||
unsafe { scope.cast_local(|_| v8__Context__Global(self)) }.unwrap()
|
||||
}
|
||||
|
||||
/// Detaches this context's global proxy so its identity can be reused by a
|
||||
/// subsequently created context.
|
||||
#[inline(always)]
|
||||
pub fn detach_global(&self) {
|
||||
unsafe { v8__Context__DetachGlobal(self) }
|
||||
}
|
||||
|
||||
/// Returns the microtask queue associated with this context.
|
||||
///
|
||||
/// Returns `None` if the context has no microtask queue, which is the case
|
||||
|
||||
Vendored
+40
@@ -0,0 +1,40 @@
|
||||
// Copyright 2026 the Moli authors. MIT license.
|
||||
|
||||
#include "support.h"
|
||||
#include "v8-context.h"
|
||||
#include "v8-isolate.h"
|
||||
|
||||
using namespace support;
|
||||
|
||||
static_assert(sizeof(v8::Context::BackupIncumbentScope) ==
|
||||
sizeof(size_t) * 3,
|
||||
"BackupIncumbentScope size mismatch");
|
||||
|
||||
extern "C" {
|
||||
|
||||
void v8__Context__BackupIncumbentScope__CONSTRUCT(
|
||||
uninit_t<v8::Context::BackupIncumbentScope>* buf,
|
||||
const v8::Context& context) {
|
||||
construct_in_place<v8::Context::BackupIncumbentScope>(buf,
|
||||
ptr_to_local(&context));
|
||||
}
|
||||
|
||||
void v8__Context__BackupIncumbentScope__DESTRUCT(
|
||||
v8::Context::BackupIncumbentScope* self) {
|
||||
self->~BackupIncumbentScope();
|
||||
}
|
||||
|
||||
void v8__Context__DetachGlobal(const v8::Context& self) {
|
||||
ptr_to_local(&self)->DetachGlobal();
|
||||
}
|
||||
|
||||
const v8::Context* v8__Isolate__GetIncumbentContext(v8::Isolate* isolate) {
|
||||
return local_to_ptr(isolate->GetIncumbentContext());
|
||||
}
|
||||
|
||||
void v8__Isolate__SetFailedAccessCheckCallbackFunction(
|
||||
v8::Isolate* isolate, v8::FailedAccessCheckCallback callback) {
|
||||
isolate->SetFailedAccessCheckCallbackFunction(callback);
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
Vendored
+33
-1
@@ -82,10 +82,23 @@ use std::sync::atomic::AtomicUsize;
|
||||
#[repr(C)]
|
||||
pub enum MicrotasksPolicy {
|
||||
Explicit = 0,
|
||||
// Scoped = 1 (RAII) is omitted for now, doesn't quite map to idiomatic Rust.
|
||||
Scoped = 1,
|
||||
Auto = 2,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
#[repr(C)]
|
||||
pub enum AccessType {
|
||||
Get,
|
||||
Set,
|
||||
Has,
|
||||
Delete,
|
||||
Keys,
|
||||
}
|
||||
|
||||
pub type FailedAccessCheckCallback =
|
||||
unsafe extern "C" fn(Local<Object>, AccessType, Local<Value>);
|
||||
|
||||
/// Memory pressure level for the MemoryPressureNotification.
|
||||
/// None hints V8 that there is no memory pressure.
|
||||
/// Moderate hints V8 to speed up incremental garbage collection at the cost
|
||||
@@ -819,6 +832,10 @@ unsafe extern "C" {
|
||||
isolate: *mut RealIsolate,
|
||||
callback: RawModifyCodeGenerationFromStringsCallback,
|
||||
);
|
||||
fn v8__Isolate__SetFailedAccessCheckCallbackFunction(
|
||||
isolate: *mut RealIsolate,
|
||||
callback: FailedAccessCheckCallback,
|
||||
);
|
||||
fn v8__Isolate__RequestInterrupt(
|
||||
isolate: *const RealIsolate,
|
||||
callback: InterruptCallback,
|
||||
@@ -905,6 +922,21 @@ impl UnsafeRawIsolatePtr {
|
||||
pub struct RealIsolate(Opaque);
|
||||
|
||||
impl Isolate {
|
||||
/// Installs the callback invoked when an object access check fails and no
|
||||
/// failed-access interceptor handles the operation.
|
||||
#[inline(always)]
|
||||
pub fn set_failed_access_check_callback_function(
|
||||
&mut self,
|
||||
callback: FailedAccessCheckCallback,
|
||||
) {
|
||||
unsafe {
|
||||
v8__Isolate__SetFailedAccessCheckCallbackFunction(
|
||||
self.as_real_ptr(),
|
||||
callback,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn as_real_ptr(&self) -> *mut RealIsolate {
|
||||
self.0.as_ptr()
|
||||
}
|
||||
|
||||
Vendored
+3
@@ -109,6 +109,8 @@ pub use handle::SealedLocal;
|
||||
pub use handle::TracedReference;
|
||||
pub use handle::Weak;
|
||||
pub use isolate::GarbageCollectionType;
|
||||
pub use isolate::AccessType;
|
||||
pub use isolate::FailedAccessCheckCallback;
|
||||
pub use isolate::HeapCodeStatistics;
|
||||
pub use isolate::HeapSpaceStatistics;
|
||||
pub use isolate::HeapStatistics;
|
||||
@@ -162,6 +164,7 @@ pub use property_filter::*;
|
||||
pub use property_handler_flags::*;
|
||||
pub use regexp::RegExpCreationFlags;
|
||||
pub use scope::AllowJavascriptExecutionScope;
|
||||
pub use scope::BackupIncumbentScope;
|
||||
// pub use scope::CallbackScope;
|
||||
pub use scope::CallbackScope;
|
||||
pub use scope::ContextScope;
|
||||
|
||||
Vendored
+51
@@ -340,6 +340,12 @@ mod get_isolate_impls {
|
||||
}
|
||||
}
|
||||
|
||||
impl GetIsolate for Local<'_, Object> {
|
||||
fn get_isolate_ptr(&self) -> *mut RealIsolate {
|
||||
unsafe { raw::v8__Isolate__GetCurrent() }
|
||||
}
|
||||
}
|
||||
|
||||
impl GetIsolate for Local<'_, Message> {
|
||||
fn get_isolate_ptr(&self) -> *mut RealIsolate {
|
||||
unsafe { raw::v8__Isolate__GetCurrent() }
|
||||
@@ -563,6 +569,15 @@ impl<'s> PinnedRef<'s, HandleScope<'_>> {
|
||||
unsafe { Local::from_raw_unchecked(context_ptr) }
|
||||
}
|
||||
|
||||
/// Returns the context corresponding to the incumbent Realm in the HTML
|
||||
/// specification.
|
||||
pub fn get_incumbent_context(&self) -> Option<Local<'s, Context>> {
|
||||
let context_ptr = unsafe {
|
||||
raw::v8__Isolate__GetIncumbentContext(self.0.isolate.as_ptr())
|
||||
};
|
||||
unsafe { Local::from_raw(context_ptr) }
|
||||
}
|
||||
|
||||
/// Return data that was previously attached to the isolate snapshot via
|
||||
/// SnapshotCreator, and removes the reference to it. If called again with
|
||||
/// same `index` argument, this function returns `DataError::NoData`.
|
||||
@@ -789,6 +804,42 @@ impl<P: ClearCachedContext> DerefMut for ContextScope<'_, '_, P> {
|
||||
impl<P: ClearCachedContext> sealed::Sealed for ContextScope<'_, '_, P> {}
|
||||
impl<P: ClearCachedContext> Scope for ContextScope<'_, '_, P> {}
|
||||
|
||||
/// Pushes a context onto V8's backup incumbent settings object stack.
|
||||
///
|
||||
/// V8 links this object into an isolate-owned stack by its address. Pin the
|
||||
/// returned `ScopeStorage` before calling `init()` and keep it alive until the
|
||||
/// callback invocation completes.
|
||||
pub struct BackupIncumbentScope<'s> {
|
||||
raw: raw::BackupIncumbentScope,
|
||||
context: Local<'s, Context>,
|
||||
_pinned: PhantomPinned,
|
||||
}
|
||||
|
||||
impl<'s> BackupIncumbentScope<'s> {
|
||||
pub fn new(context: Local<'s, Context>) -> ScopeStorage<Self> {
|
||||
ScopeStorage::new(Self {
|
||||
raw: unsafe { raw::BackupIncumbentScope::uninit() },
|
||||
context,
|
||||
_pinned: PhantomPinned,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl ScopeInit for BackupIncumbentScope<'_> {
|
||||
fn init_stack(storage: Pin<&mut ScopeStorage<Self>>) -> Pin<&mut Self> {
|
||||
let storage_mut = unsafe { storage.get_unchecked_mut() };
|
||||
let context = storage_mut.scope.context;
|
||||
unsafe {
|
||||
storage_mut.scope.raw.init(context);
|
||||
Pin::new_unchecked(&mut storage_mut.scope)
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn deinit(me: &mut Self) {
|
||||
unsafe { me.raw.deinit() };
|
||||
}
|
||||
}
|
||||
|
||||
mod new_context_scope {
|
||||
|
||||
use super::{GetIsolate, Scope};
|
||||
|
||||
Vendored
+40
@@ -36,6 +36,36 @@ impl Drop for ContextScope {
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
pub(super) struct BackupIncumbentScope([MaybeUninit<usize>; 3]);
|
||||
|
||||
impl BackupIncumbentScope {
|
||||
/// Creates uninitialized storage for V8's stack-address-sensitive scope.
|
||||
///
|
||||
/// The returned value must be pinned before `init()` constructs the C++
|
||||
/// object in place.
|
||||
pub unsafe fn uninit() -> Self {
|
||||
Self(unsafe { MaybeUninit::uninit().assume_init() })
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// `self` must be pinned at its final address and initialized exactly once.
|
||||
pub unsafe fn init(&mut self, context: Local<Context>) {
|
||||
unsafe {
|
||||
v8__Context__BackupIncumbentScope__CONSTRUCT(self, &*context);
|
||||
}
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// `self` must have been initialized by `init()` and must not have moved.
|
||||
pub unsafe fn deinit(&mut self) {
|
||||
unsafe { v8__Context__BackupIncumbentScope__DESTRUCT(self) };
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "v8_enable_v8_checks")]
|
||||
pub const HANDLE_SCOPE_SIZE: usize = 4;
|
||||
#[cfg(not(feature = "v8_enable_v8_checks"))]
|
||||
@@ -227,6 +257,9 @@ unsafe extern "C" {
|
||||
pub(super) fn v8__Isolate__GetEnteredOrMicrotaskContext(
|
||||
isolate: *mut RealIsolate,
|
||||
) -> *const Context;
|
||||
pub(super) fn v8__Isolate__GetIncumbentContext(
|
||||
isolate: *mut RealIsolate,
|
||||
) -> *const Context;
|
||||
pub(super) fn v8__Isolate__ThrowException(
|
||||
isolate: *mut RealIsolate,
|
||||
exception: *const Value,
|
||||
@@ -241,6 +274,13 @@ unsafe extern "C" {
|
||||
|
||||
pub(super) fn v8__Context__Enter(this: *const Context);
|
||||
pub(super) fn v8__Context__Exit(this: *const Context);
|
||||
pub(super) fn v8__Context__BackupIncumbentScope__CONSTRUCT(
|
||||
buf: *mut BackupIncumbentScope,
|
||||
context: *const Context,
|
||||
);
|
||||
pub(super) fn v8__Context__BackupIncumbentScope__DESTRUCT(
|
||||
this: *mut BackupIncumbentScope,
|
||||
);
|
||||
pub(super) fn v8__Context__GetDataFromSnapshotOnce(
|
||||
this: *const Context,
|
||||
index: usize,
|
||||
|
||||
Reference in New Issue
Block a user