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:
parent
e511fc59f2
commit
69bac645e0
5 changed files with 157 additions and 0 deletions
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
78
src/microtask.rs
Normal 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) }
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue