0
0
Fork 0
mirror of https://github.com/denoland/rusty_v8.git synced 2024-11-21 15:04:33 -05:00

Add v8::MicrotaskQueue bindings (#1423)

This commit is contained in:
Divy Srivastava 2024-03-14 08:37:01 -07:00 committed by GitHub
parent e511fc59f2
commit 69bac645e0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 157 additions and 0 deletions

View file

@ -1882,6 +1882,15 @@ bool v8__Context_IsCodeGenerationFromStringsAllowed(v8::Context& self) {
return ptr_to_local(&self)->IsCodeGenerationFromStringsAllowed();
}
v8::MicrotaskQueue* v8__Context__GetMicrotaskQueue(v8::Context& self) {
return ptr_to_local(&self)->GetMicrotaskQueue();
}
void v8__Context__SetMicrotaskQueue(v8::Context& self,
v8::MicrotaskQueue* microtask_queue) {
ptr_to_local(&self)->SetMicrotaskQueue(microtask_queue);
}
const v8::Context* v8__Context__FromSnapshot(v8::Isolate* isolate,
size_t context_snapshot_index) {
v8::MaybeLocal<v8::Context> maybe_local =
@ -1900,6 +1909,25 @@ const v8::Value* v8__Context__GetContinuationPreservedEmbedderData(
return local_to_ptr(value);
}
void v8__MicrotaskQueue__PerformCheckpoint(v8::Isolate* isolate,
v8::MicrotaskQueue* self) {
self->PerformCheckpoint(isolate);
}
bool v8__MicrotaskQueue__IsRunningMicrotasks(v8::MicrotaskQueue* self) {
return self->IsRunningMicrotasks();
}
int v8__MicrotaskQueue__GetMicrotasksScopeDepth(v8::MicrotaskQueue* self) {
return self->GetMicrotasksScopeDepth();
}
void v8__MicrotaskQueue__EnqueueMicrotask(v8::Isolate* isolate,
v8::MicrotaskQueue* self,
v8::Function* callback) {
self->EnqueueMicrotask(isolate, ptr_to_local(callback));
}
const v8::String* v8__Message__Get(const v8::Message& self) {
return local_to_ptr(self.Get());
}

View file

@ -7,6 +7,7 @@ use crate::support::int;
use crate::Context;
use crate::HandleScope;
use crate::Local;
use crate::MicrotaskQueue;
use crate::Object;
use crate::ObjectTemplate;
use crate::Value;
@ -55,6 +56,13 @@ extern "C" {
pub(super) fn v8__Context_IsCodeGenerationFromStringsAllowed(
this: *const Context,
) -> bool;
fn v8__Context__GetMicrotaskQueue(
this: *const Context,
) -> *const MicrotaskQueue;
fn v8__Context__SetMicrotaskQueue(
this: *const Context,
microtask_queue: *const MicrotaskQueue,
);
}
impl Context {
@ -114,6 +122,18 @@ impl Context {
unsafe { scope.cast_local(|_| v8__Context__Global(self)) }.unwrap()
}
#[inline(always)]
pub fn get_microtask_queue(&self) -> &MicrotaskQueue {
unsafe { &*v8__Context__GetMicrotaskQueue(self) }
}
#[inline(always)]
pub fn set_microtask_queue(&self, microtask_queue: &MicrotaskQueue) {
unsafe {
v8__Context__SetMicrotaskQueue(self, microtask_queue);
}
}
#[inline]
fn get_annex_mut<'a>(
&'a self,

View file

@ -46,6 +46,7 @@ mod handle;
pub mod icu;
mod isolate;
mod isolate_create_params;
mod microtask;
mod module;
mod name;
mod number;
@ -117,6 +118,7 @@ pub use isolate::PromiseHookType;
pub use isolate::PromiseRejectCallback;
pub use isolate::WasmAsyncSuccess;
pub use isolate_create_params::CreateParams;
pub use microtask::MicrotaskQueue;
pub use module::*;
pub use object::*;
pub use platform::new_default_platform;

78
src/microtask.rs Normal file
View file

@ -0,0 +1,78 @@
// Copyright 2019-2021 the Deno authors. All rights reserved. MIT license.
use crate::support::int;
use crate::support::Opaque;
use crate::Function;
use crate::Isolate;
use crate::Local;
extern "C" {
fn v8__MicrotaskQueue__PerformCheckpoint(
isolate: *mut Isolate,
queue: *const MicrotaskQueue,
);
fn v8__MicrotaskQueue__IsRunningMicrotasks(
queue: *const MicrotaskQueue,
) -> bool;
fn v8__MicrotaskQueue__GetMicrotasksScopeDepth(
queue: *const MicrotaskQueue,
) -> int;
fn v8__MicrotaskQueue__EnqueueMicrotask(
isolate: *mut Isolate,
queue: *const MicrotaskQueue,
microtask: *const Function,
);
}
/// Represents the microtask queue, where microtasks are stored and processed.
/// https://html.spec.whatwg.org/multipage/webappapis.html#microtask-queue
/// https://html.spec.whatwg.org/multipage/webappapis.html#enqueuejob(queuename,-job,-arguments)
/// https://html.spec.whatwg.org/multipage/webappapis.html#perform-a-microtask-checkpoint
///
/// A MicrotaskQueue instance may be associated to multiple Contexts by passing
/// it to Context::New(), and they can be detached by Context::DetachGlobal().
/// The embedder must keep the MicrotaskQueue instance alive until all associated
/// Contexts are gone or detached.
///
/// Use the same instance of MicrotaskQueue for all Contexts that may access each
/// other synchronously. E.g. for Web embedding, use the same instance for all
/// origins that share the same URL scheme and eTLD+1.
#[repr(C)]
#[derive(Debug)]
pub struct MicrotaskQueue(Opaque);
impl MicrotaskQueue {
pub fn enqueue_microtask(
&self,
isolate: &mut Isolate,
microtask: Local<Function>,
) {
unsafe { v8__MicrotaskQueue__EnqueueMicrotask(isolate, self, &*microtask) }
}
/// Adds a callback to notify the embedder after microtasks were run. The
/// callback is triggered by explicit RunMicrotasks call or automatic
/// microtasks execution (see Isolate::SetMicrotasksPolicy).
///
/// Callback will trigger even if microtasks were attempted to run,
/// but the microtasks queue was empty and no single microtask was actually
/// executed.
///
/// Executing scripts inside the callback will not re-trigger microtasks and
/// the callback.
pub fn perform_checkpoint(&self, isolate: &mut Isolate) {
unsafe {
v8__MicrotaskQueue__PerformCheckpoint(isolate, self);
}
}
/// Removes callback that was installed by AddMicrotasksCompletedCallback.
pub fn is_running_microtasks(&self) -> bool {
unsafe { v8__MicrotaskQueue__IsRunningMicrotasks(self) }
}
/// Returns the current depth of nested MicrotasksScope that has kRunMicrotasks.
pub fn get_microtasks_scope_depth(&self) -> i32 {
unsafe { v8__MicrotaskQueue__GetMicrotasksScopeDepth(self) }
}
}

View file

@ -11324,3 +11324,32 @@ fn allow_scope_in_read_host_object() {
let value = deserializer.read_value(context).unwrap();
assert!(value.is_object());
}
#[test]
fn microtask_queue() {
let _setup_guard = setup::parallel_test();
let mut isolate = v8::Isolate::new(Default::default());
let mut scope = v8::HandleScope::new(&mut isolate);
let context = v8::Context::new(&mut scope);
let queue = context.get_microtask_queue();
let mut scope = v8::ContextScope::new(&mut scope, context);
static CALL_COUNT: AtomicUsize = AtomicUsize::new(0);
let function = v8::Function::new(
&mut scope,
|_: &mut v8::HandleScope,
_: v8::FunctionCallbackArguments,
_: v8::ReturnValue| {
CALL_COUNT.fetch_add(1, Ordering::SeqCst);
},
)
.unwrap();
queue.enqueue_microtask(&mut scope, function);
// Flushes the microtasks queue.
let _ = eval(&mut scope, "").unwrap();
assert_eq!(CALL_COUNT.load(Ordering::SeqCst), 1);
}