2020-01-02 13:57:00 -05:00
|
|
|
// Copyright 2019-2020 the Deno authors. All rights reserved. MIT license.
|
2020-04-20 21:18:03 +02:00
|
|
|
use crate::isolate_create_params::raw;
|
|
|
|
use crate::isolate_create_params::CreateParams;
|
2019-12-19 14:13:33 +01:00
|
|
|
use crate::promise::PromiseRejectMessage;
|
2019-11-15 16:21:34 -08:00
|
|
|
use crate::support::Opaque;
|
2019-12-24 16:40:41 -05:00
|
|
|
use crate::Context;
|
2020-01-02 10:15:31 -05:00
|
|
|
use crate::Function;
|
2020-02-11 17:01:27 -05:00
|
|
|
use crate::InIsolate;
|
2019-12-19 21:34:07 -05:00
|
|
|
use crate::Local;
|
2019-12-20 08:47:20 -05:00
|
|
|
use crate::Message;
|
2019-12-24 16:40:41 -05:00
|
|
|
use crate::Module;
|
|
|
|
use crate::Object;
|
2019-12-26 10:45:55 -05:00
|
|
|
use crate::Promise;
|
|
|
|
use crate::ScriptOrModule;
|
|
|
|
use crate::String;
|
2019-12-19 21:34:07 -05:00
|
|
|
use crate::Value;
|
2020-02-12 11:33:58 -05:00
|
|
|
|
2020-04-20 21:18:03 +02:00
|
|
|
use std::any::Any;
|
2020-04-23 09:34:28 +02:00
|
|
|
use std::any::TypeId;
|
|
|
|
use std::cell::{Ref, RefCell, RefMut};
|
|
|
|
use std::collections::HashMap;
|
2019-12-25 10:56:27 -05:00
|
|
|
use std::ffi::c_void;
|
2019-12-20 08:47:20 -05:00
|
|
|
use std::ops::Deref;
|
|
|
|
use std::ops::DerefMut;
|
2020-02-12 11:33:58 -05:00
|
|
|
use std::ptr::null_mut;
|
2019-12-20 08:47:20 -05:00
|
|
|
use std::ptr::NonNull;
|
2020-02-12 11:33:58 -05:00
|
|
|
use std::sync::Arc;
|
|
|
|
use std::sync::Mutex;
|
2019-12-19 21:34:07 -05:00
|
|
|
|
2019-12-26 10:45:55 -05:00
|
|
|
pub type MessageCallback = extern "C" fn(Local<Message>, Local<Value>);
|
2019-11-15 16:21:34 -08:00
|
|
|
|
2019-12-26 10:45:55 -05:00
|
|
|
pub type PromiseRejectCallback = extern "C" fn(PromiseRejectMessage);
|
2019-12-19 14:13:33 +01:00
|
|
|
|
2019-12-26 10:45:55 -05:00
|
|
|
/// HostInitializeImportMetaObjectCallback is called the first time import.meta
|
|
|
|
/// is accessed for a module. Subsequent access will reuse the same value.
|
|
|
|
///
|
|
|
|
/// The method combines two implementation-defined abstract operations into one:
|
|
|
|
/// HostGetImportMetaProperties and HostFinalizeImportMeta.
|
|
|
|
///
|
|
|
|
/// The embedder should use v8::Object::CreateDataProperty to add properties on
|
|
|
|
/// the meta object.
|
|
|
|
pub type HostInitializeImportMetaObjectCallback =
|
2019-12-24 16:40:41 -05:00
|
|
|
extern "C" fn(Local<Context>, Local<Module>, Local<Object>);
|
|
|
|
|
2019-12-26 10:45:55 -05:00
|
|
|
/// HostImportModuleDynamicallyCallback is called when we require the
|
|
|
|
/// embedder to load a module. This is used as part of the dynamic
|
|
|
|
/// import syntax.
|
|
|
|
///
|
|
|
|
/// The referrer contains metadata about the script/module that calls
|
|
|
|
/// import.
|
|
|
|
///
|
|
|
|
/// The specifier is the name of the module that should be imported.
|
|
|
|
///
|
|
|
|
/// The embedder must compile, instantiate, evaluate the Module, and
|
|
|
|
/// obtain it's namespace object.
|
|
|
|
///
|
|
|
|
/// The Promise returned from this function is forwarded to userland
|
|
|
|
/// JavaScript. The embedder must resolve this promise with the module
|
|
|
|
/// namespace object. In case of an exception, the embedder must reject
|
|
|
|
/// this promise with the exception. If the promise creation itself
|
|
|
|
/// fails (e.g. due to stack overflow), the embedder must propagate
|
|
|
|
/// that exception by returning an empty MaybeLocal.
|
|
|
|
pub type HostImportModuleDynamicallyCallback = extern "C" fn(
|
|
|
|
Local<Context>,
|
|
|
|
Local<ScriptOrModule>,
|
|
|
|
Local<String>,
|
|
|
|
) -> *mut Promise;
|
|
|
|
|
2020-01-15 15:33:47 -05:00
|
|
|
pub type InterruptCallback =
|
|
|
|
extern "C" fn(isolate: &mut Isolate, data: *mut c_void);
|
|
|
|
|
2019-11-15 16:21:34 -08:00
|
|
|
extern "C" {
|
2020-04-20 21:18:03 +02:00
|
|
|
fn v8__Isolate__New(params: *const raw::CreateParams) -> *mut Isolate;
|
2019-12-19 19:15:52 -05:00
|
|
|
fn v8__Isolate__Dispose(this: *mut Isolate);
|
2019-12-25 10:56:27 -05:00
|
|
|
fn v8__Isolate__SetData(this: *mut Isolate, slot: u32, data: *mut c_void);
|
|
|
|
fn v8__Isolate__GetData(this: *const Isolate, slot: u32) -> *mut c_void;
|
|
|
|
fn v8__Isolate__GetNumberOfDataSlots(this: *const Isolate) -> u32;
|
2019-12-19 19:15:52 -05:00
|
|
|
fn v8__Isolate__Enter(this: *mut Isolate);
|
|
|
|
fn v8__Isolate__Exit(this: *mut Isolate);
|
2019-12-18 17:17:38 -05:00
|
|
|
fn v8__Isolate__SetCaptureStackTraceForUncaughtExceptions(
|
2019-12-19 19:15:52 -05:00
|
|
|
this: *mut Isolate,
|
2019-12-18 17:17:38 -05:00
|
|
|
caputre: bool,
|
|
|
|
frame_limit: i32,
|
|
|
|
);
|
2019-12-19 21:34:07 -05:00
|
|
|
fn v8__Isolate__AddMessageListener(
|
2020-04-13 14:43:56 +02:00
|
|
|
isolate: *mut Isolate,
|
2019-12-19 21:34:07 -05:00
|
|
|
callback: MessageCallback,
|
|
|
|
) -> bool;
|
2019-12-19 14:13:33 +01:00
|
|
|
fn v8__Isolate__SetPromiseRejectCallback(
|
2019-12-19 19:15:52 -05:00
|
|
|
isolate: *mut Isolate,
|
2019-12-19 14:13:33 +01:00
|
|
|
callback: PromiseRejectCallback,
|
2019-12-19 19:15:52 -05:00
|
|
|
);
|
2019-12-24 16:40:41 -05:00
|
|
|
fn v8__Isolate__SetHostInitializeImportMetaObjectCallback(
|
|
|
|
isolate: *mut Isolate,
|
|
|
|
callback: HostInitializeImportMetaObjectCallback,
|
|
|
|
);
|
2019-12-26 10:45:55 -05:00
|
|
|
fn v8__Isolate__SetHostImportModuleDynamicallyCallback(
|
|
|
|
isolate: *mut Isolate,
|
|
|
|
callback: HostImportModuleDynamicallyCallback,
|
|
|
|
);
|
2020-01-15 15:33:47 -05:00
|
|
|
fn v8__Isolate__RequestInterrupt(
|
|
|
|
isolate: *const Isolate,
|
|
|
|
callback: InterruptCallback,
|
|
|
|
data: *mut c_void,
|
|
|
|
);
|
2019-12-23 08:16:01 -05:00
|
|
|
fn v8__Isolate__ThrowException(
|
2020-01-17 15:17:48 +01:00
|
|
|
isolate: *mut Isolate,
|
2020-04-13 14:43:56 +02:00
|
|
|
exception: *const Value,
|
|
|
|
) -> *const Value;
|
2020-01-17 15:17:48 +01:00
|
|
|
fn v8__Isolate__TerminateExecution(isolate: *const Isolate);
|
|
|
|
fn v8__Isolate__IsExecutionTerminating(isolate: *const Isolate) -> bool;
|
|
|
|
fn v8__Isolate__CancelTerminateExecution(isolate: *const Isolate);
|
|
|
|
fn v8__Isolate__RunMicrotasks(isolate: *mut Isolate);
|
|
|
|
fn v8__Isolate__EnqueueMicrotask(
|
|
|
|
isolate: *mut Isolate,
|
2020-04-13 14:43:56 +02:00
|
|
|
function: *const Function,
|
2020-01-17 15:17:48 +01:00
|
|
|
);
|
2019-11-20 13:34:32 -08:00
|
|
|
|
2020-03-09 18:30:25 +01:00
|
|
|
fn v8__HeapProfiler__TakeHeapSnapshot(
|
|
|
|
isolate: *mut Isolate,
|
|
|
|
callback: extern "C" fn(*mut c_void, *const u8, usize) -> bool,
|
|
|
|
arg: *mut c_void,
|
|
|
|
);
|
2019-11-15 16:21:34 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
#[repr(C)]
|
2019-12-20 08:47:20 -05:00
|
|
|
/// Isolate represents an isolated instance of the V8 engine. V8 isolates have
|
|
|
|
/// completely separate states. Objects from one isolate must not be used in
|
|
|
|
/// other isolates. The embedder can create multiple isolates and use them in
|
|
|
|
/// parallel in multiple threads. An isolate can be entered by at most one
|
|
|
|
/// thread at any given time. The Locker/Unlocker API must be used to
|
|
|
|
/// synchronize.
|
2019-12-19 19:15:52 -05:00
|
|
|
pub struct Isolate(Opaque);
|
2019-11-27 07:14:39 -08:00
|
|
|
|
2019-11-15 16:21:34 -08:00
|
|
|
impl Isolate {
|
2019-12-04 00:57:06 -05:00
|
|
|
/// Creates a new isolate. Does not change the currently entered
|
|
|
|
/// isolate.
|
|
|
|
///
|
|
|
|
/// When an isolate is no longer used its resources should be freed
|
|
|
|
/// by calling V8::dispose(). Using the delete operator is not allowed.
|
|
|
|
///
|
|
|
|
/// V8::initialize() must have run prior to this.
|
2019-12-19 19:15:52 -05:00
|
|
|
#[allow(clippy::new_ret_no_self)]
|
2020-04-20 21:18:03 +02:00
|
|
|
pub fn new(params: CreateParams) -> OwnedIsolate {
|
2019-11-30 09:16:25 -08:00
|
|
|
crate::V8::assert_initialized();
|
2020-04-20 21:18:03 +02:00
|
|
|
let (raw_create_params, create_param_allocations) = params.finalize();
|
|
|
|
let cxx_isolate = unsafe { v8__Isolate__New(&raw_create_params) };
|
2020-04-23 09:34:28 +02:00
|
|
|
let mut owned_isolate =
|
|
|
|
OwnedIsolate::new(cxx_isolate, create_param_allocations);
|
|
|
|
owned_isolate.create_annex();
|
|
|
|
owned_isolate
|
2019-11-15 16:21:34 -08:00
|
|
|
}
|
2019-12-04 00:57:06 -05:00
|
|
|
|
|
|
|
/// Initial configuration parameters for a new Isolate.
|
2020-04-20 21:18:03 +02:00
|
|
|
pub fn create_params() -> CreateParams {
|
|
|
|
CreateParams::default()
|
2019-12-04 00:57:06 -05:00
|
|
|
}
|
2019-12-09 02:26:58 +01:00
|
|
|
|
2020-02-12 11:33:58 -05:00
|
|
|
pub fn thread_safe_handle(&mut self) -> IsolateHandle {
|
|
|
|
IsolateHandle::new(self)
|
|
|
|
}
|
|
|
|
|
2020-04-23 09:34:28 +02:00
|
|
|
fn create_annex(&mut self) {
|
|
|
|
let annex_arc = Arc::new(IsolateAnnex::new(self));
|
|
|
|
let annex_ptr = Arc::into_raw(annex_arc);
|
|
|
|
unsafe { v8__Isolate__SetData(self, 0, annex_ptr as *mut c_void) }
|
2020-02-13 15:03:25 -05:00
|
|
|
}
|
|
|
|
|
2020-04-23 09:34:28 +02:00
|
|
|
fn get_annex(&self) -> &IsolateAnnex {
|
|
|
|
unsafe {
|
|
|
|
&*(v8__Isolate__GetData(self, 0) as *const _ as *const IsolateAnnex)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn get_annex_mut(&mut self) -> &mut IsolateAnnex {
|
|
|
|
unsafe { &mut *(v8__Isolate__GetData(self, 0) as *mut IsolateAnnex) }
|
|
|
|
}
|
|
|
|
|
|
|
|
fn get_annex_arc(&self) -> Arc<IsolateAnnex> {
|
|
|
|
let annex_ptr = self.get_annex();
|
|
|
|
let annex_arc = unsafe { Arc::from_raw(annex_ptr) };
|
|
|
|
Arc::into_raw(annex_arc.clone());
|
|
|
|
annex_arc
|
2020-02-13 15:03:25 -05:00
|
|
|
}
|
|
|
|
|
2019-12-25 10:56:27 -05:00
|
|
|
/// Associate embedder-specific data with the isolate. |slot| has to be
|
|
|
|
/// between 0 and GetNumberOfDataSlots() - 1.
|
|
|
|
pub unsafe fn set_data(&mut self, slot: u32, ptr: *mut c_void) {
|
2020-02-25 16:22:32 -08:00
|
|
|
v8__Isolate__SetData(self, slot + 1, ptr)
|
2019-12-25 10:56:27 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Retrieve embedder-specific data from the isolate.
|
|
|
|
/// Returns NULL if SetData has never been called for the given |slot|.
|
|
|
|
pub fn get_data(&self, slot: u32) -> *mut c_void {
|
2020-02-25 16:22:32 -08:00
|
|
|
unsafe { v8__Isolate__GetData(self, slot + 1) }
|
2019-12-25 10:56:27 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the maximum number of available embedder data slots. Valid slots
|
|
|
|
/// are in the range of 0 - GetNumberOfDataSlots() - 1.
|
|
|
|
pub fn get_number_of_data_slots(&self) -> u32 {
|
2020-02-25 16:22:32 -08:00
|
|
|
unsafe { v8__Isolate__GetNumberOfDataSlots(self) - 1 }
|
2019-12-25 10:56:27 -05:00
|
|
|
}
|
|
|
|
|
2020-04-23 09:34:28 +02:00
|
|
|
/// Safe alternative to Isolate::get_data
|
|
|
|
///
|
|
|
|
/// Warning: will be renamed to get_data_mut() after original unsafe version
|
|
|
|
/// is removed.
|
|
|
|
pub fn get_slot_mut<T: 'static>(&self) -> Option<RefMut<T>> {
|
|
|
|
let cell = self.get_annex().slots.get(&TypeId::of::<T>())?;
|
|
|
|
let ref_mut = cell.try_borrow_mut().ok()?;
|
|
|
|
let ref_mut = RefMut::map(ref_mut, |box_any| {
|
|
|
|
let mut_any = &mut **box_any;
|
|
|
|
Any::downcast_mut::<T>(mut_any).unwrap()
|
|
|
|
});
|
|
|
|
Some(ref_mut)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Safe alternative to Isolate::get_data
|
|
|
|
///
|
|
|
|
/// Warning: will be renamed to get_data() after original unsafe version is
|
|
|
|
/// removed.
|
|
|
|
pub fn get_slot<T: 'static>(&self) -> Option<Ref<T>> {
|
|
|
|
let cell = self.get_annex().slots.get(&TypeId::of::<T>())?;
|
|
|
|
let r = cell.try_borrow().ok()?;
|
|
|
|
Some(Ref::map(r, |box_any| {
|
|
|
|
let a = &**box_any;
|
|
|
|
Any::downcast_ref::<T>(a).unwrap()
|
|
|
|
}))
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Safe alternative to Isolate::set_data
|
|
|
|
///
|
|
|
|
/// Use with Isolate::get_slot and Isolate::get_slot_mut to associate state
|
|
|
|
/// with an Isolate.
|
|
|
|
///
|
|
|
|
/// This method gives ownership of value to the Isolate. Exactly one object of
|
|
|
|
/// each type can be associated with an Isolate. If called more than once with
|
|
|
|
/// an object of the same type, the earlier version will be dropped and
|
|
|
|
/// replaced.
|
|
|
|
///
|
|
|
|
/// Returns true if value was set without replacing an existing value.
|
|
|
|
///
|
|
|
|
/// The value will be dropped when the isolate is dropped.
|
|
|
|
///
|
|
|
|
/// Warning: will be renamed to set_data() after original unsafe version is
|
|
|
|
/// removed.
|
|
|
|
pub fn set_slot<T: 'static>(&mut self, value: T) -> bool {
|
|
|
|
self
|
|
|
|
.get_annex_mut()
|
|
|
|
.slots
|
|
|
|
.insert(Any::type_id(&value), RefCell::new(Box::new(value)))
|
|
|
|
.is_none()
|
|
|
|
}
|
|
|
|
|
2019-12-09 02:26:58 +01:00
|
|
|
/// Sets this isolate as the entered one for the current thread.
|
|
|
|
/// Saves the previously entered one (if any), so that it can be
|
|
|
|
/// restored when exiting. Re-entering an isolate is allowed.
|
2020-01-17 08:57:27 +01:00
|
|
|
pub(crate) fn enter(&mut self) {
|
2019-12-19 19:15:52 -05:00
|
|
|
unsafe { v8__Isolate__Enter(self) }
|
2019-12-09 02:26:58 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Exits this isolate by restoring the previously entered one in the
|
|
|
|
/// current thread. The isolate may still stay the same, if it was
|
|
|
|
/// entered more than once.
|
|
|
|
///
|
|
|
|
/// Requires: self == Isolate::GetCurrent().
|
2020-01-17 08:57:27 +01:00
|
|
|
pub(crate) fn exit(&mut self) {
|
2019-12-19 19:15:52 -05:00
|
|
|
unsafe { v8__Isolate__Exit(self) }
|
2019-12-09 02:26:58 +01:00
|
|
|
}
|
2019-12-18 17:17:38 -05:00
|
|
|
|
|
|
|
/// Tells V8 to capture current stack trace when uncaught exception occurs
|
|
|
|
/// and report it to the message listeners. The option is off by default.
|
|
|
|
pub fn set_capture_stack_trace_for_uncaught_exceptions(
|
|
|
|
&mut self,
|
|
|
|
capture: bool,
|
|
|
|
frame_limit: i32,
|
|
|
|
) {
|
|
|
|
unsafe {
|
|
|
|
v8__Isolate__SetCaptureStackTraceForUncaughtExceptions(
|
2019-12-19 19:15:52 -05:00
|
|
|
self,
|
2019-12-18 17:17:38 -05:00
|
|
|
capture,
|
|
|
|
frame_limit,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
2019-12-19 14:13:33 +01:00
|
|
|
|
2019-12-19 21:34:07 -05:00
|
|
|
/// Adds a message listener (errors only).
|
|
|
|
///
|
|
|
|
/// The same message listener can be added more than once and in that
|
|
|
|
/// case it will be called more than once for each message.
|
|
|
|
///
|
|
|
|
/// The exception object will be passed to the callback.
|
|
|
|
pub fn add_message_listener(&mut self, callback: MessageCallback) -> bool {
|
|
|
|
unsafe { v8__Isolate__AddMessageListener(self, callback) }
|
|
|
|
}
|
|
|
|
|
2019-12-19 14:13:33 +01:00
|
|
|
/// Set callback to notify about promise reject with no handler, or
|
|
|
|
/// revocation of such a previous notification once the handler is added.
|
|
|
|
pub fn set_promise_reject_callback(
|
|
|
|
&mut self,
|
|
|
|
callback: PromiseRejectCallback,
|
|
|
|
) {
|
2019-12-19 19:15:52 -05:00
|
|
|
unsafe { v8__Isolate__SetPromiseRejectCallback(self, callback) }
|
|
|
|
}
|
2019-12-24 16:40:41 -05:00
|
|
|
/// This specifies the callback called by the upcoming importa.meta
|
|
|
|
/// language feature to retrieve host-defined meta data for a module.
|
|
|
|
pub fn set_host_initialize_import_meta_object_callback(
|
|
|
|
&mut self,
|
|
|
|
callback: HostInitializeImportMetaObjectCallback,
|
|
|
|
) {
|
|
|
|
unsafe {
|
|
|
|
v8__Isolate__SetHostInitializeImportMetaObjectCallback(self, callback)
|
|
|
|
}
|
|
|
|
}
|
2019-12-19 19:15:52 -05:00
|
|
|
|
2019-12-26 10:45:55 -05:00
|
|
|
/// This specifies the callback called by the upcoming dynamic
|
|
|
|
/// import() language feature to load modules.
|
|
|
|
pub fn set_host_import_module_dynamically_callback(
|
|
|
|
&mut self,
|
|
|
|
callback: HostImportModuleDynamicallyCallback,
|
|
|
|
) {
|
|
|
|
unsafe {
|
|
|
|
v8__Isolate__SetHostImportModuleDynamicallyCallback(self, callback)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-23 08:16:01 -05:00
|
|
|
/// Schedules an exception to be thrown when returning to JavaScript. When an
|
|
|
|
/// exception has been scheduled it is illegal to invoke any JavaScript
|
|
|
|
/// operation; the caller must return immediately and only after the exception
|
|
|
|
/// has been handled does it become legal to invoke JavaScript operations.
|
|
|
|
pub fn throw_exception<'sc>(
|
2020-01-17 15:17:48 +01:00
|
|
|
&mut self,
|
|
|
|
exception: Local<Value>,
|
2019-12-23 08:16:01 -05:00
|
|
|
) -> Local<'sc, Value> {
|
|
|
|
unsafe {
|
2020-04-13 14:43:56 +02:00
|
|
|
let ptr = v8__Isolate__ThrowException(self, &*exception);
|
2019-12-25 12:39:42 +01:00
|
|
|
Local::from_raw(ptr).unwrap()
|
2019-12-23 08:16:01 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-12 11:33:58 -05:00
|
|
|
/// Runs the default MicrotaskQueue until it gets empty.
|
|
|
|
/// Any exceptions thrown by microtask callbacks are swallowed.
|
|
|
|
pub fn run_microtasks(&mut self) {
|
|
|
|
unsafe { v8__Isolate__RunMicrotasks(self) }
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Enqueues the callback to the default MicrotaskQueue
|
|
|
|
pub fn enqueue_microtask(&mut self, microtask: Local<Function>) {
|
2020-04-13 14:43:56 +02:00
|
|
|
unsafe { v8__Isolate__EnqueueMicrotask(self, &*microtask) }
|
2020-02-12 11:33:58 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Disposes the isolate. The isolate must not be entered by any
|
|
|
|
/// thread to be disposable.
|
|
|
|
unsafe fn dispose(&mut self) {
|
2020-04-23 19:48:07 +02:00
|
|
|
let annex = self.get_annex_mut();
|
|
|
|
|
|
|
|
// Set the `isolate` pointer inside the annex struct to null, so any
|
|
|
|
// IsolateHandle that outlives the isolate will know that it can't call
|
|
|
|
// methods on the isolate.
|
|
|
|
{
|
|
|
|
let _lock = annex.isolate_mutex.lock().unwrap();
|
|
|
|
annex.isolate = null_mut();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Clear slots.
|
|
|
|
annex.slots.clear();
|
|
|
|
|
|
|
|
// Subtract one from the Arc<IsolateAnnex> reference count.
|
|
|
|
Arc::from_raw(annex);
|
|
|
|
self.set_data(0, null_mut());
|
2020-02-19 22:55:44 -05:00
|
|
|
|
|
|
|
// No test case in rusty_v8 show this, but there have been situations in
|
|
|
|
// deno where dropping Annex before the states causes a segfault.
|
2020-02-12 11:33:58 -05:00
|
|
|
v8__Isolate__Dispose(self)
|
|
|
|
}
|
2020-03-09 18:30:25 +01:00
|
|
|
|
|
|
|
/// Take a heap snapshot. The callback is invoked one or more times
|
|
|
|
/// with byte slices containing the snapshot serialized as JSON.
|
|
|
|
/// It's the callback's responsibility to reassemble them into
|
|
|
|
/// a single document, e.g., by writing them to a file.
|
|
|
|
/// Note that Chrome DevTools refuses to load snapshots without
|
|
|
|
/// a .heapsnapshot suffix.
|
|
|
|
pub fn take_heap_snapshot<F>(&mut self, mut callback: F)
|
|
|
|
where
|
|
|
|
F: FnMut(&[u8]) -> bool,
|
|
|
|
{
|
|
|
|
extern "C" fn trampoline<F>(
|
|
|
|
arg: *mut c_void,
|
|
|
|
data: *const u8,
|
|
|
|
size: usize,
|
|
|
|
) -> bool
|
|
|
|
where
|
|
|
|
F: FnMut(&[u8]) -> bool,
|
|
|
|
{
|
|
|
|
let p = arg as *mut F;
|
|
|
|
let callback = unsafe { &mut *p };
|
|
|
|
let slice = unsafe { std::slice::from_raw_parts(data, size) };
|
|
|
|
callback(slice)
|
|
|
|
}
|
|
|
|
|
|
|
|
let arg = &mut callback as *mut F as *mut c_void;
|
|
|
|
unsafe { v8__HeapProfiler__TakeHeapSnapshot(self, trampoline::<F>, arg) }
|
|
|
|
}
|
2020-02-12 11:33:58 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) struct IsolateAnnex {
|
2020-04-23 09:34:28 +02:00
|
|
|
slots: HashMap<TypeId, RefCell<Box<dyn Any>>>,
|
2020-04-23 19:18:06 +02:00
|
|
|
// The `isolate` and `isolate_mutex` fields are there so an `IsolateHandle`
|
|
|
|
// (which may outlive the isolate itself) can determine whether the isolate is
|
|
|
|
// still alive, and if so, get a reference to it. Safety rules:
|
|
|
|
// - The 'main thread' must lock the mutex and reset `isolate` to null just
|
|
|
|
// before the isolate is disposed.
|
|
|
|
// - Any other thread must lock the mutex while it's reading/using the
|
|
|
|
// `isolate` pointer.
|
|
|
|
isolate: *mut Isolate,
|
|
|
|
isolate_mutex: Mutex<()>,
|
2020-02-12 11:33:58 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
impl IsolateAnnex {
|
|
|
|
fn new(isolate: &mut Isolate) -> Self {
|
|
|
|
Self {
|
2020-04-23 09:34:28 +02:00
|
|
|
slots: HashMap::new(),
|
2020-04-23 19:18:06 +02:00
|
|
|
isolate,
|
|
|
|
isolate_mutex: Mutex::new(()),
|
2020-02-12 11:33:58 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone)]
|
|
|
|
pub struct IsolateHandle(Arc<IsolateAnnex>);
|
|
|
|
|
|
|
|
unsafe impl Send for IsolateHandle {}
|
|
|
|
unsafe impl Sync for IsolateHandle {}
|
|
|
|
|
|
|
|
impl IsolateHandle {
|
|
|
|
// This function is marked unsafe because it must be called only with either
|
|
|
|
// IsolateAnnex::mutex locked, or from the main thread associated with the V8
|
|
|
|
// isolate.
|
|
|
|
pub(crate) unsafe fn get_isolate_ptr(&self) -> *mut Isolate {
|
|
|
|
self.0.isolate
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn new(isolate: &mut Isolate) -> Self {
|
2020-04-23 09:34:28 +02:00
|
|
|
Self(isolate.get_annex_arc())
|
2020-02-12 11:33:58 -05:00
|
|
|
}
|
|
|
|
|
2019-12-31 03:11:43 -08:00
|
|
|
/// Forcefully terminate the current thread of JavaScript execution
|
|
|
|
/// in the given isolate.
|
|
|
|
///
|
|
|
|
/// This method can be used by any thread even if that thread has not
|
|
|
|
/// acquired the V8 lock with a Locker object.
|
|
|
|
///
|
2020-02-12 11:33:58 -05:00
|
|
|
/// Returns false if Isolate was already destroyed.
|
|
|
|
pub fn terminate_execution(&self) -> bool {
|
2020-04-23 19:18:06 +02:00
|
|
|
let _lock = self.0.isolate_mutex.lock().unwrap();
|
2020-02-12 11:33:58 -05:00
|
|
|
if self.0.isolate.is_null() {
|
|
|
|
false
|
|
|
|
} else {
|
|
|
|
unsafe { v8__Isolate__TerminateExecution(self.0.isolate) };
|
|
|
|
true
|
|
|
|
}
|
2019-12-31 03:11:43 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Resume execution capability in the given isolate, whose execution
|
|
|
|
/// was previously forcefully terminated using TerminateExecution().
|
|
|
|
///
|
|
|
|
/// When execution is forcefully terminated using TerminateExecution(),
|
|
|
|
/// the isolate can not resume execution until all JavaScript frames
|
|
|
|
/// have propagated the uncatchable exception which is generated. This
|
|
|
|
/// method allows the program embedding the engine to handle the
|
|
|
|
/// termination event and resume execution capability, even if
|
|
|
|
/// JavaScript frames remain on the stack.
|
|
|
|
///
|
|
|
|
/// This method can be used by any thread even if that thread has not
|
|
|
|
/// acquired the V8 lock with a Locker object.
|
2020-02-12 11:33:58 -05:00
|
|
|
///
|
|
|
|
/// Returns false if Isolate was already destroyed.
|
|
|
|
pub fn cancel_terminate_execution(&self) -> bool {
|
2020-04-23 19:18:06 +02:00
|
|
|
let _lock = self.0.isolate_mutex.lock().unwrap();
|
2020-02-12 11:33:58 -05:00
|
|
|
if self.0.isolate.is_null() {
|
|
|
|
false
|
|
|
|
} else {
|
|
|
|
unsafe { v8__Isolate__CancelTerminateExecution(self.0.isolate) };
|
|
|
|
true
|
|
|
|
}
|
2020-01-02 10:15:31 -05:00
|
|
|
}
|
|
|
|
|
2020-02-12 11:33:58 -05:00
|
|
|
/// Is V8 terminating JavaScript execution.
|
|
|
|
///
|
|
|
|
/// Returns true if JavaScript execution is currently terminating
|
|
|
|
/// because of a call to TerminateExecution. In that case there are
|
|
|
|
/// still JavaScript frames on the stack and the termination
|
|
|
|
/// exception is still active.
|
|
|
|
///
|
|
|
|
/// Returns false if Isolate was already destroyed.
|
|
|
|
pub fn is_execution_terminating(&self) -> bool {
|
2020-04-23 19:18:06 +02:00
|
|
|
let _lock = self.0.isolate_mutex.lock().unwrap();
|
2020-02-12 11:33:58 -05:00
|
|
|
if self.0.isolate.is_null() {
|
|
|
|
false
|
|
|
|
} else {
|
|
|
|
unsafe { v8__Isolate__IsExecutionTerminating(self.0.isolate) }
|
|
|
|
}
|
2020-01-02 10:15:31 -05:00
|
|
|
}
|
|
|
|
|
2020-01-15 15:33:47 -05:00
|
|
|
/// Request V8 to interrupt long running JavaScript code and invoke
|
|
|
|
/// the given |callback| passing the given |data| to it. After |callback|
|
|
|
|
/// returns control will be returned to the JavaScript code.
|
|
|
|
/// There may be a number of interrupt requests in flight.
|
|
|
|
/// Can be called from another thread without acquiring a |Locker|.
|
|
|
|
/// Registered |callback| must not reenter interrupted Isolate.
|
2020-02-12 11:33:58 -05:00
|
|
|
///
|
|
|
|
/// Returns false if Isolate was already destroyed.
|
2020-01-15 15:33:47 -05:00
|
|
|
// Clippy warns that this method is dereferencing a raw pointer, but it is
|
|
|
|
// not: https://github.com/rust-lang/rust-clippy/issues/3045
|
|
|
|
#[allow(clippy::not_unsafe_ptr_arg_deref)]
|
|
|
|
pub fn request_interrupt(
|
|
|
|
&self,
|
|
|
|
callback: InterruptCallback,
|
|
|
|
data: *mut c_void,
|
2020-02-12 11:33:58 -05:00
|
|
|
) -> bool {
|
2020-04-23 19:18:06 +02:00
|
|
|
let _lock = self.0.isolate_mutex.lock().unwrap();
|
2020-02-12 11:33:58 -05:00
|
|
|
if self.0.isolate.is_null() {
|
|
|
|
false
|
|
|
|
} else {
|
|
|
|
unsafe { v8__Isolate__RequestInterrupt(self.0.isolate, callback, data) };
|
|
|
|
true
|
|
|
|
}
|
2019-12-19 14:13:33 +01:00
|
|
|
}
|
2019-11-15 16:21:34 -08:00
|
|
|
}
|
|
|
|
|
2019-12-19 19:15:52 -05:00
|
|
|
/// Same as Isolate but gets disposed when it goes out of scope.
|
2020-04-20 21:18:03 +02:00
|
|
|
pub struct OwnedIsolate {
|
|
|
|
cxx_isolate: NonNull<Isolate>,
|
|
|
|
create_param_allocations: Box<dyn Any>,
|
|
|
|
}
|
2019-12-19 19:15:52 -05:00
|
|
|
|
2020-04-20 21:18:03 +02:00
|
|
|
impl OwnedIsolate {
|
|
|
|
pub(crate) fn new(
|
|
|
|
cxx_isolate: *mut Isolate,
|
|
|
|
create_param_allocations: Box<dyn Any>,
|
|
|
|
) -> Self {
|
|
|
|
let cxx_isolate = NonNull::new(cxx_isolate).unwrap();
|
|
|
|
Self {
|
|
|
|
cxx_isolate,
|
|
|
|
create_param_allocations,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-02-19 22:55:44 -05:00
|
|
|
|
2020-02-11 17:01:27 -05:00
|
|
|
impl InIsolate for OwnedIsolate {
|
|
|
|
fn isolate(&mut self) -> &mut Isolate {
|
|
|
|
self.deref_mut()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-19 19:15:52 -05:00
|
|
|
impl Drop for OwnedIsolate {
|
2019-11-15 16:21:34 -08:00
|
|
|
fn drop(&mut self) {
|
2020-04-20 21:18:03 +02:00
|
|
|
unsafe { self.cxx_isolate.as_mut().dispose() }
|
2019-11-15 16:21:34 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-19 19:15:52 -05:00
|
|
|
impl Deref for OwnedIsolate {
|
|
|
|
type Target = Isolate;
|
2019-11-30 16:31:51 +01:00
|
|
|
fn deref(&self) -> &Self::Target {
|
2020-04-20 21:18:03 +02:00
|
|
|
unsafe { self.cxx_isolate.as_ref() }
|
2019-11-15 16:21:34 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-19 19:15:52 -05:00
|
|
|
impl DerefMut for OwnedIsolate {
|
2019-11-30 16:31:51 +01:00
|
|
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
2020-04-20 21:18:03 +02:00
|
|
|
unsafe { self.cxx_isolate.as_mut() }
|
2019-11-20 13:34:32 -08:00
|
|
|
}
|
|
|
|
}
|