perf: stack allocated v8 scopes (#30827)
Some checks are pending
ci / test release macos-x86_64 (push) Blocked by required conditions
ci / test debug windows-x86_64 (push) Blocked by required conditions
ci / test release windows-x86_64 (push) Blocked by required conditions
ci / build libs (push) Blocked by required conditions
ci / pre-build (push) Waiting to run
ci / test debug linux-aarch64 (push) Blocked by required conditions
ci / test release linux-aarch64 (push) Blocked by required conditions
ci / test debug macos-aarch64 (push) Blocked by required conditions
ci / test release macos-aarch64 (push) Blocked by required conditions
ci / bench release linux-x86_64 (push) Blocked by required conditions
ci / lint debug linux-x86_64 (push) Blocked by required conditions
ci / lint debug macos-x86_64 (push) Blocked by required conditions
ci / lint debug windows-x86_64 (push) Blocked by required conditions
ci / test debug linux-x86_64 (push) Blocked by required conditions
ci / test release linux-x86_64 (push) Blocked by required conditions
ci / test debug macos-x86_64 (push) Blocked by required conditions
ci / publish canary (push) Blocked by required conditions

This commit is contained in:
Nathan Whitaker 2025-09-23 17:54:14 -07:00 committed by GitHub
parent e7e1f1c13a
commit d82f509c41
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
59 changed files with 679 additions and 1313 deletions

16
Cargo.lock generated
View file

@ -1930,9 +1930,9 @@ dependencies = [
[[package]]
name = "deno_core"
version = "0.360.0"
version = "0.362.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bdc3775fb87e9af0e84bf09b2aa5180721e3ae84660e77a64318d94e3398ce6e"
checksum = "be08f717b55b73bbb9a96e8c6854f8693d34f5c4dd41c7284c338d923709473c"
dependencies = [
"anyhow",
"az",
@ -2649,9 +2649,9 @@ dependencies = [
[[package]]
name = "deno_ops"
version = "0.236.0"
version = "0.238.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ae5392198a37964acd20b1e3ff2f20f0bf591a3267878eb05784ae1a86fb8ba"
checksum = "18cde9a34023084eec749c6264bb5be7f3c8e843dbc8b75874c6da3b8b200f02"
dependencies = [
"indexmap 2.9.0",
"proc-macro-rules",
@ -8255,9 +8255,9 @@ dependencies = [
[[package]]
name = "serde_v8"
version = "0.269.0"
version = "0.271.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8bc2310cc16892a3204ebfe47568e295cdf4952bfb3610ad66ef933fc9241139"
checksum = "4046e43ba5435ecd4412ded9c0e44845f2e7bdd6a89d9e0fcd2b862edeb0324d"
dependencies = [
"deno_error",
"num-bigint",
@ -10090,9 +10090,9 @@ dependencies = [
[[package]]
name = "v8"
version = "140.1.1"
version = "140.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee1055021c5cd98e825e997e898bb700968f52cfa80f16ea81c02fcb9eb9cdf7"
checksum = "8827809a2884fb68530d678a8ef15b1ed1344bbf844879194d68c140c6f844f9"
dependencies = [
"bindgen 0.72.1",
"bitflags 2.9.3",

View file

@ -62,7 +62,7 @@ repository = "https://github.com/denoland/deno"
[workspace.dependencies]
deno_ast = { version = "=0.50.0", features = ["transpiling"] }
deno_core = { version = "0.360.0" }
deno_core = { version = "0.362.0" }
deno_cache_dir = "=0.25.0"
deno_doc = "=0.183.0"

View file

@ -52,7 +52,7 @@ pub fn bench_js_sync_with(
opts: BenchOptions,
) {
let mut runtime = create_js_runtime(setup);
let scope = &mut runtime.handle_scope();
deno_core::scope!(scope, runtime);
// Increase JS iterations if profiling for nicer flamegraphs
let inner_iters = if is_profiling() {

View file

@ -280,7 +280,7 @@ impl<'a> ToV8<'a> for ChangeKind {
type Error = Infallible;
fn to_v8(
self,
scope: &mut v8::HandleScope<'a>,
scope: &mut v8::PinScope<'a, '_>,
) -> Result<v8::Local<'a, v8::Value>, Self::Error> {
Smi(self as u8).to_v8(scope)
}
@ -309,7 +309,7 @@ impl<'a> ToV8<'a> for PendingChange {
type Error = Infallible;
fn to_v8(
self,
scope: &mut v8::HandleScope<'a>,
scope: &mut v8::PinScope<'a, '_>,
) -> Result<v8::Local<'a, v8::Value>, Self::Error> {
let modified_scripts = {
let mut modified_scripts_v8 =
@ -4719,7 +4719,7 @@ struct LoadResponse {
#[op2]
fn op_load<'s>(
scope: &'s mut v8::HandleScope,
scope: &'s mut v8::PinScope<'_, '_>,
state: &mut OpState,
#[string] specifier: &str,
) -> Result<v8::Local<'s, v8::Value>, LoadError> {
@ -4811,7 +4811,7 @@ impl<'a> ToV8<'a> for TscRequestArray {
fn to_v8(
self,
scope: &mut v8::HandleScope<'a>,
scope: &mut v8::PinScope<'a, '_>,
) -> Result<v8::Local<'a, v8::Value>, Self::Error> {
let id = self.id.to_v8(scope).unwrap_infallible();
@ -5276,7 +5276,7 @@ impl TscRuntime {
fn new(mut js_runtime: JsRuntime) -> Self {
let server_main_loop_fn_global = {
let context = js_runtime.main_context();
let scope = &mut js_runtime.handle_scope();
deno_core::scope!(scope, &mut js_runtime);
let context_local = v8::Local::new(scope, context);
let global_obj = context_local.global(scope);
let server_main_loop_fn_str =
@ -5361,7 +5361,7 @@ fn run_tsc_thread(
let mut runtime = tsc_runtime.lock().await;
let main_loop = runtime.server_main_loop_fn_global.clone();
let args = {
let scope = &mut runtime.js_runtime.handle_scope();
deno_core::scope!(scope, &mut runtime.js_runtime);
let enable_debug_local =
v8::Local::<v8::Value>::from(v8::Boolean::new(scope, enable_debug));
[v8::Global::new(scope, enable_debug_local)]
@ -5882,7 +5882,7 @@ impl TscRequest {
/// function
fn to_server_request<'s>(
&self,
scope: &mut v8::HandleScope<'s>,
scope: &mut v8::PinScope<'s, '_>,
) -> Result<(&'static str, Option<v8::Local<'s, v8::Value>>), serde_v8::Error>
{
let args = match self {

View file

@ -991,7 +991,7 @@ impl<TGraphContainer: ModuleGraphContainer> ModuleLoader
fn get_host_defined_options<'s>(
&self,
scope: &mut deno_core::v8::HandleScope<'s>,
scope: &mut deno_core::v8::PinScope<'s, '_>,
name: &str,
) -> Option<deno_core::v8::Local<'s, deno_core::v8::Data>> {
let name = deno_core::ModuleSpecifier::parse(name).ok()?;

View file

@ -361,7 +361,7 @@ impl ModuleLoader for EmbeddedModuleLoader {
fn get_host_defined_options<'s>(
&self,
scope: &mut deno_core::v8::HandleScope<'s>,
scope: &mut deno_core::v8::PinScope<'s, '_>,
name: &str,
) -> Option<deno_core::v8::Local<'s, deno_core::v8::Data>> {
let name = Url::parse(name).ok()?;

View file

@ -261,7 +261,7 @@ async fn bench_specifier_inner(
.js_runtime
.with_event_loop_promise(call, PollEventLoopOptions::default())
.await?;
let scope = &mut worker.js_runtime.handle_scope();
deno_core::scope!(scope, &mut worker.js_runtime);
let result = v8::Local::new(scope, result);
let result = serde_v8::from_v8::<BenchResult>(scope, result)
.map_err(JsErrorBox::from_err)

View file

@ -171,7 +171,7 @@ async fn create_plugin_runner_inner(
log::debug!("Lint plugins loaded, capturing default exports");
let (install_plugins_fn, run_plugins_for_file_fn) = {
let scope = &mut runtime.handle_scope();
deno_core::scope!(scope, runtime);
let module_exports: v8::Local<v8::Object> =
v8::Local::new(scope, obj).try_into().unwrap();
@ -326,7 +326,7 @@ impl PluginHost {
);
}
let scope = &mut self.worker.js_runtime.handle_scope();
deno_core::scope!(scope, &mut self.worker.js_runtime);
let file_name_v8: v8::Local<v8::Value> =
v8::String::new(scope, &file_path.display().to_string())
.unwrap()
@ -343,18 +343,20 @@ impl PluginHost {
v8::Local::new(scope, &*self.run_plugins_for_file_fn);
let undefined = v8::undefined(scope);
let mut tc_scope = v8::TryCatch::new(scope);
let _run_plugins_result = run_plugins_for_file.call(
&mut tc_scope,
undefined.into(),
&[file_name_v8, ast_bin_v8],
);
let _run_plugins_result = {
v8::tc_scope!(tc_scope, scope);
let _run_plugins_result = run_plugins_for_file.call(
tc_scope,
undefined.into(),
&[file_name_v8, ast_bin_v8],
);
if let Some(exception) = tc_scope.exception() {
let error = JsError::from_v8_exception(&mut tc_scope, exception);
return Err(error.into());
}
drop(tc_scope);
if let Some(exception) = tc_scope.exception() {
let error = JsError::from_v8_exception(tc_scope, exception);
return Err(error.into());
}
_run_plugins_result
};
Ok(())
}
@ -386,7 +388,7 @@ impl PluginHost {
for (fut, mod_id) in load_futures {
fut.await?;
let module = self.worker.js_runtime.get_module_namespace(mod_id).unwrap();
let scope = &mut self.worker.js_runtime.handle_scope();
deno_core::scope!(scope, &mut self.worker.js_runtime);
let module_local = v8::Local::new(scope, module);
let default_export_str = DEFAULT.v8_string(scope).unwrap();
let default_export =
@ -395,7 +397,7 @@ impl PluginHost {
plugin_handles.push(default_export_global);
}
let scope = &mut self.worker.js_runtime.handle_scope();
deno_core::scope!(scope, &mut self.worker.js_runtime);
let install_plugins_local =
v8::Local::new(scope, &*self.install_plugins_fn.clone());
let exclude_v8: v8::Local<v8::Value> =
@ -424,14 +426,16 @@ impl PluginHost {
log::debug!("Installing lint plugins...");
let mut tc_scope = v8::TryCatch::new(scope);
let plugins_info_result =
install_plugins_local.call(&mut tc_scope, undefined.into(), args);
if let Some(exception) = tc_scope.exception() {
let error = JsError::from_v8_exception(&mut tc_scope, exception);
return Err(error.into());
}
drop(tc_scope);
let plugins_info_result = {
v8::tc_scope!(tc_scope, scope);
let plugins_info_result =
install_plugins_local.call(tc_scope, undefined.into(), args);
if let Some(exception) = tc_scope.exception() {
let error = JsError::from_v8_exception(tc_scope, exception);
return Err(error.into());
}
plugins_info_result
};
let plugins_info = plugins_info_result.unwrap();
let infos: Vec<PluginInfo> =
deno_core::serde_v8::from_v8(scope, plugins_info)?;

View file

@ -1075,7 +1075,7 @@ async fn run_tests_for_worker_inner(
};
// Check the result before we check for leaks
let scope = &mut worker.js_runtime.handle_scope();
deno_core::scope!(scope, &mut worker.js_runtime);
let result = v8::Local::new(scope, result);
serde_v8::from_v8::<TestResult>(scope, result)?
} else {

View file

@ -29,7 +29,7 @@ where
fn to_v8(
self,
scope: &mut v8::HandleScope<'a>,
scope: &mut v8::PinScope<'a, '_>,
) -> Result<v8::Local<'a, v8::Value>, Self::Error> {
match self.0 {
Some(value) => value.to_v8(scope),
@ -45,7 +45,7 @@ where
type Error = T::Error;
fn from_v8(
scope: &mut v8::HandleScope<'a>,
scope: &mut v8::PinScope<'a, '_>,
value: v8::Local<'a, v8::Value>,
) -> Result<Self, Self::Error> {
if value.is_null() {

View file

@ -10,7 +10,7 @@ deno_core::extension!(
#[op2]
pub fn op_preview_entries<'s>(
scope: &mut v8::HandleScope<'s>,
scope: &mut v8::PinScope<'s, '_>,
object: &v8::Object,
slow_path: bool,
) -> v8::Local<'s, v8::Value> {

View file

@ -67,7 +67,7 @@ unsafe fn ffi_call_rtype_struct(
// A one-off synchronous FFI call.
pub(crate) fn ffi_call_sync<'scope>(
scope: &mut v8::HandleScope<'scope>,
scope: &mut v8::PinScope<'scope, '_>,
args: v8::FunctionCallbackArguments,
symbol: &Symbol,
out_buffer: Option<OutBuffer>,
@ -301,7 +301,7 @@ fn ffi_call(
#[op2(async, stack_trace)]
#[serde]
pub fn op_ffi_call_ptr_nonblocking<FP>(
scope: &mut v8::HandleScope,
scope: &mut v8::PinScope<'_, '_>,
state: Rc<RefCell<OpState>>,
pointer: *mut c_void,
#[serde] def: ForeignFunction,
@ -349,7 +349,7 @@ where
#[op2(async)]
#[serde]
pub fn op_ffi_call_nonblocking(
scope: &mut v8::HandleScope,
scope: &mut v8::PinScope<'_, '_>,
state: Rc<RefCell<OpState>>,
#[smi] rid: ResourceId,
#[string] symbol: String,
@ -400,7 +400,7 @@ pub fn op_ffi_call_nonblocking(
#[op2(reentrant, stack_trace)]
#[serde]
pub fn op_ffi_call_ptr<FP>(
scope: &mut v8::HandleScope,
scope: &mut v8::PinScope<'_, '_>,
state: Rc<RefCell<OpState>>,
pointer: *mut c_void,
#[serde] def: ForeignFunction,

View file

@ -21,7 +21,6 @@ use deno_core::ResourceId;
use deno_core::V8CrossThreadTaskSpawner;
use deno_core::op2;
use deno_core::v8;
use deno_core::v8::TryCatch;
use libffi::middle::Cif;
use serde::Deserialize;
@ -130,7 +129,7 @@ struct TaskArgs {
unsafe impl Send for TaskArgs {}
impl TaskArgs {
fn run(&mut self, scope: &mut v8::HandleScope) {
fn run(&mut self, scope: &mut v8::PinScope<'_, '_>) {
// SAFETY: making a call using Send-safe pointers turned back into references. We know the
// lifetime of these will last because we block on the result of the spawn call.
unsafe {
@ -170,8 +169,8 @@ unsafe extern "C" fn deno_ffi_callback(
NonNull<v8::Context>,
v8::Local<v8::Context>,
>(context);
let mut cb_scope = v8::CallbackScope::new(context);
let scope = &mut v8::HandleScope::new(&mut cb_scope);
v8::callback_scope!(unsafe cb_scope, context);
v8::scope!(scope, cb_scope);
do_ffi_callback(scope, cif, info, result, args);
} else {
@ -186,7 +185,7 @@ unsafe extern "C" fn deno_ffi_callback(
async_work_sender.spawn_blocking(move |scope| {
// We don't have a lot of choice here, so just print an unhandled exception message
let tc_scope = &mut TryCatch::new(scope);
v8::tc_scope!(tc_scope, scope);
args.run(tc_scope);
if tc_scope.exception().is_some() {
log::error!("Illegal unhandled exception in nonblocking callback");
@ -198,7 +197,7 @@ unsafe extern "C" fn deno_ffi_callback(
}
unsafe fn do_ffi_callback(
scope: &mut v8::HandleScope,
scope: &mut v8::PinScope<'_, '_>,
cif: &libffi::low::ffi_cif,
info: &CallbackInfo,
result: &mut c_void,
@ -578,7 +577,7 @@ pub struct RegisterCallbackArgs {
#[op2(stack_trace)]
pub fn op_ffi_unsafe_callback_create<FP, 'scope>(
state: &mut OpState,
scope: &mut v8::HandleScope<'scope>,
scope: &mut v8::PinScope<'scope, '_>,
#[serde] args: RegisterCallbackArgs,
cb: v8::Local<v8::Function>,
) -> Result<v8::Local<'scope, v8::Value>, CallbackError>
@ -651,7 +650,7 @@ where
#[op2(fast)]
pub fn op_ffi_unsafe_callback_close(
state: &mut OpState,
scope: &mut v8::HandleScope,
scope: &mut v8::PinScope<'_, '_>,
#[smi] rid: ResourceId,
) -> Result<(), CallbackError> {
// SAFETY: This drops the closure and the callback info associated with it.

View file

@ -144,7 +144,7 @@ impl<'de> Deserialize<'de> for ForeignSymbol {
#[op2(stack_trace)]
pub fn op_ffi_load<'scope, FP>(
scope: &mut v8::HandleScope<'scope>,
scope: &mut v8::PinScope<'scope, '_>,
state: Rc<RefCell<OpState>>,
#[string] path: &str,
#[serde] symbols: HashMap<String, ForeignSymbol>,
@ -270,7 +270,7 @@ unsafe impl GarbageCollected for FunctionData {
// Create a JavaScript function for synchronous FFI call to
// the given symbol.
fn make_sync_fn<'s>(
scope: &mut v8::HandleScope<'s>,
scope: &mut v8::PinScope<'s, '_>,
symbol: Box<Symbol>,
) -> v8::Local<'s, v8::Function> {
let turbocall = if turbocall::is_compatible(&symbol) {
@ -309,7 +309,7 @@ fn make_sync_fn<'s>(
}
fn sync_fn_impl<'s>(
scope: &mut v8::HandleScope<'s>,
scope: &mut v8::PinScope<'s, '_>,
args: v8::FunctionCallbackArguments<'s>,
mut rv: v8::ReturnValue,
) {

View file

@ -62,7 +62,7 @@ unsafe impl Send for OutBuffer {}
unsafe impl Sync for OutBuffer {}
pub fn out_buffer_as_ptr(
scope: &mut v8::HandleScope,
scope: &mut v8::PinScope<'_, '_>,
out_buffer: Option<v8::Local<v8::TypedArray>>,
) -> Option<OutBuffer> {
match out_buffer {
@ -127,7 +127,7 @@ impl NativeValue {
#[inline]
pub unsafe fn to_v8<'scope>(
&self,
scope: &mut v8::HandleScope<'scope>,
scope: &mut v8::PinScope<'scope, '_>,
native_type: NativeType,
) -> v8::Local<'scope, v8::Value> {
#[allow(clippy::undocumented_unsafe_blocks)]
@ -252,7 +252,7 @@ pub fn ffi_parse_i32_arg(
#[inline]
pub fn ffi_parse_u64_arg(
scope: &mut v8::HandleScope,
scope: &mut v8::PinScope<'_, '_>,
arg: v8::Local<v8::Value>,
) -> Result<NativeValue, IRError> {
// Order of checking:
@ -271,7 +271,7 @@ pub fn ffi_parse_u64_arg(
#[inline]
pub fn ffi_parse_i64_arg(
scope: &mut v8::HandleScope,
scope: &mut v8::PinScope<'_, '_>,
arg: v8::Local<v8::Value>,
) -> Result<NativeValue, IRError> {
// Order of checking:
@ -290,7 +290,7 @@ pub fn ffi_parse_i64_arg(
#[inline]
pub fn ffi_parse_usize_arg(
scope: &mut v8::HandleScope,
scope: &mut v8::PinScope<'_, '_>,
arg: v8::Local<v8::Value>,
) -> Result<NativeValue, IRError> {
// Order of checking:
@ -309,7 +309,7 @@ pub fn ffi_parse_usize_arg(
#[inline]
pub fn ffi_parse_isize_arg(
scope: &mut v8::HandleScope,
scope: &mut v8::PinScope<'_, '_>,
arg: v8::Local<v8::Value>,
) -> Result<NativeValue, IRError> {
// Order of checking:
@ -348,7 +348,7 @@ pub fn ffi_parse_f64_arg(
#[inline]
pub fn ffi_parse_pointer_arg(
_scope: &mut v8::HandleScope,
_scope: &mut v8::PinScope<'_, '_>,
arg: v8::Local<v8::Value>,
) -> Result<NativeValue, IRError> {
let pointer = if let Ok(value) = v8::Local::<v8::External>::try_from(arg) {
@ -408,7 +408,7 @@ pub fn ffi_parse_buffer_arg(
#[inline]
pub fn ffi_parse_struct_arg(
scope: &mut v8::HandleScope,
scope: &mut v8::PinScope<'_, '_>,
arg: v8::Local<v8::Value>,
) -> Result<NativeValue, IRError> {
// Order of checking:
@ -442,7 +442,7 @@ pub fn ffi_parse_struct_arg(
#[inline]
pub fn ffi_parse_function_arg(
_scope: &mut v8::HandleScope,
_scope: &mut v8::PinScope<'_, '_>,
arg: v8::Local<v8::Value>,
) -> Result<NativeValue, IRError> {
let pointer = if let Ok(value) = v8::Local::<v8::External>::try_from(arg) {
@ -456,7 +456,7 @@ pub fn ffi_parse_function_arg(
}
pub fn ffi_parse_args<'scope>(
scope: &mut v8::HandleScope<'scope>,
scope: &mut v8::PinScope<'scope, '_>,
args: v8::Local<v8::Array>,
parameter_types: &[NativeType],
) -> Result<Vec<NativeValue>, IRError>

View file

@ -163,7 +163,7 @@ where
#[op2(stack_trace)]
pub fn op_ffi_get_buf<FP, 'scope>(
scope: &mut v8::HandleScope<'scope>,
scope: &mut v8::PinScope<'scope, '_>,
state: &mut OpState,
ptr: *mut c_void,
#[number] offset: isize,
@ -225,7 +225,7 @@ where
#[op2(stack_trace)]
pub fn op_ffi_cstr_read<FP, 'scope>(
scope: &mut v8::HandleScope<'scope>,
scope: &mut v8::PinScope<'scope, '_>,
state: &mut OpState,
ptr: *mut c_void,
#[number] offset: isize,

View file

@ -28,7 +28,7 @@ pub enum StaticError {
#[op2]
pub fn op_ffi_get_static<'scope>(
scope: &mut v8::HandleScope<'scope>,
scope: &mut v8::PinScope<'scope, '_>,
state: &mut OpState,
#[smi] rid: ResourceId,
#[string] name: String,

View file

@ -5,6 +5,7 @@ use std::sync::LazyLock;
use deno_core::OpState;
use deno_core::op2;
use deno_core::v8;
use deno_core::v8::fast_api;
use crate::NativeType;
@ -411,11 +412,9 @@ unsafe extern "C" fn turbocall_raise(
options: *const deno_core::v8::fast_api::FastApiCallbackOptions,
) {
// SAFETY: This is called with valid FastApiCallbackOptions from within fast callback.
let mut scope = unsafe { deno_core::v8::CallbackScope::new(&*options) };
let exception = deno_core::error::to_v8_error(
&mut scope,
&crate::IRError::InvalidBufferType,
);
v8::callback_scope!(unsafe scope, unsafe { &*options });
let exception =
deno_core::error::to_v8_error(scope, &crate::IRError::InvalidBufferType);
scope.throw_exception(exception);
}
@ -425,14 +424,14 @@ unsafe extern "C" fn turbocall_trace(
options: *const deno_core::v8::fast_api::FastApiCallbackOptions,
) {
// SAFETY: This is called with valid FastApiCallbackOptions from within fast callback.
let mut scope = unsafe { deno_core::v8::CallbackScope::new(&*options) };
v8::callback_scope!(unsafe let scope, unsafe { &*options });
let func_data = deno_core::cppgc::try_unwrap_cppgc_object::<FunctionData>(
&mut scope,
scope,
// SAFETY: This is valid if the options are valid.
unsafe { (&*options).data },
)
.unwrap();
deno_core::JsRuntime::op_state_from(&scope)
deno_core::JsRuntime::op_state_from(scope)
.borrow_mut()
.put(TurbocallTarget(func_data.symbol.name.clone()));
}

View file

@ -261,7 +261,7 @@ fn set_promise_complete(http: Rc<HttpRecord>, status: u16) {
#[op2]
pub fn op_http_get_request_method_and_url<'scope, HTTP>(
scope: &mut v8::HandleScope<'scope>,
scope: &mut v8::PinScope<'scope, '_>,
external: *const c_void,
) -> v8::Local<'scope, v8::Array>
where
@ -381,7 +381,7 @@ pub fn op_http_get_request_header(
#[op2]
pub fn op_http_get_request_headers<'scope>(
scope: &mut v8::HandleScope<'scope>,
scope: &mut v8::PinScope<'scope, '_>,
external: *const c_void,
) -> v8::Local<'scope, v8::Array> {
let http =
@ -497,7 +497,7 @@ pub fn op_http_set_response_header(
#[op2(fast)]
pub fn op_http_set_response_headers(
scope: &mut v8::HandleScope,
scope: &mut v8::PinScope<'_, '_>,
external: *const c_void,
headers: v8::Local<v8::Array>,
) {

View file

@ -44,7 +44,7 @@ extern "C" fn call_fn(info: *const v8::FunctionCallbackInfo) {
// SAFETY: calling user provided function pointer.
let value = unsafe { (info.cb)(info.env as napi_env, info_ptr as *mut _) };
if let Some(exc) = unsafe { &mut *info.env }.last_exception.take() {
let scope = unsafe { &mut v8::CallbackScope::new(callback_info) };
v8::callback_scope!(unsafe scope, callback_info);
let exc = v8::Local::new(scope, exc);
scope.throw_exception(exc);
}
@ -54,7 +54,7 @@ extern "C" fn call_fn(info: *const v8::FunctionCallbackInfo) {
}
pub fn create_function<'s>(
scope: &mut v8::HandleScope<'s>,
scope: &mut v8::PinScope<'s, '_>,
env: *mut Env,
name: Option<v8::Local<v8::String>>,
cb: napi_callback,
@ -75,7 +75,7 @@ pub fn create_function<'s>(
}
pub fn create_function_template<'s>(
scope: &mut v8::HandleScope<'s>,
scope: &mut v8::PinScope<'s, '_>,
env: *mut Env,
name: Option<v8::Local<v8::String>>,
cb: napi_callback,

File diff suppressed because it is too large Load diff

View file

@ -23,6 +23,7 @@ pub mod uv;
use core::ptr::NonNull;
use std::borrow::Cow;
use std::cell::Cell;
use std::cell::RefCell;
use std::collections::HashMap;
pub use std::ffi::CStr;
@ -287,7 +288,7 @@ pub struct napi_extended_error_info {
pub error_message: *const c_char,
pub engine_reserved: *mut c_void,
pub engine_error_code: i32,
pub error_code: napi_status,
pub error_code: Cell<napi_status>,
}
#[repr(C)]
@ -381,7 +382,7 @@ impl EnvShared {
#[repr(C)]
pub struct Env {
context: NonNull<v8::Context>,
pub isolate_ptr: *mut v8::Isolate,
pub isolate_ptr: v8::UnsafeRawIsolatePtr,
pub open_handle_scopes: usize,
pub shared: *mut EnvShared,
pub async_work_sender: V8CrossThreadTaskSpawner,
@ -400,7 +401,7 @@ unsafe impl Sync for Env {}
impl Env {
#[allow(clippy::too_many_arguments)]
pub fn new(
isolate_ptr: *mut v8::Isolate,
isolate_ptr: v8::UnsafeRawIsolatePtr,
context: v8::Global<v8::Context>,
global: v8::Global<v8::Object>,
buffer_constructor: v8::Global<v8::Function>,
@ -424,7 +425,7 @@ impl Env {
error_message: std::ptr::null(),
engine_reserved: std::ptr::null_mut(),
engine_error_code: 0,
error_code: napi_ok,
error_code: Cell::new(napi_ok),
},
last_exception: None,
}
@ -447,22 +448,19 @@ impl Env {
#[inline]
pub fn isolate(&mut self) -> &mut v8::Isolate {
// SAFETY: Lifetime of `Isolate` is longer than `Env`.
unsafe { &mut *self.isolate_ptr }
unsafe {
v8::Isolate::ref_from_raw_isolate_ptr_mut_unchecked(&mut self.isolate_ptr)
}
}
#[inline]
pub fn scope(&self) -> v8::CallbackScope<'_> {
// SAFETY: `v8::Local` is always non-null pointer; the `HandleScope` is
pub fn context<'s>(&'s self) -> v8::Local<'s, v8::Context> {
// SAFETY: `v8::Local` is always non-null pointer; the `PinScope<'_, '_>` is
// already on the stack, but we don't have access to it.
let context = unsafe {
unsafe {
std::mem::transmute::<NonNull<v8::Context>, v8::Local<v8::Context>>(
self.context,
)
};
// SAFETY: there must be a `HandleScope` on the stack, this is ensured because
// we are in a V8 callback or the module has already opened a `HandleScope`
// using `napi_open_handle_scope`.
unsafe { v8::CallbackScope::new(context) }
}
}
pub fn threadsafe_function_ref(&mut self) {
@ -556,8 +554,8 @@ static NAPI_LOADED_MODULES: std::sync::LazyLock<
#[op2(reentrant, stack_trace)]
fn op_napi_open<NP, 'scope>(
scope: &mut v8::HandleScope<'scope>,
isolate: *mut v8::Isolate,
scope: &mut v8::PinScope<'scope, '_>,
isolate: &mut v8::Isolate,
op_state: Rc<RefCell<OpState>>,
#[string] path: &str,
global: v8::Local<'scope, v8::Object>,
@ -604,7 +602,7 @@ where
let ctx = scope.get_current_context();
let mut env = Env::new(
isolate,
unsafe { isolate.as_raw_isolate_ptr() },
v8::Global::new(scope, ctx),
v8::Global::new(scope, global),
v8::Global::new(scope, buffer_constructor),

View file

@ -128,11 +128,13 @@ fn napi_remove_async_cleanup_hook(
fn napi_fatal_exception(env: &mut Env, err: napi_value) -> napi_status {
check_arg!(env, err);
let report_error = v8::Local::new(&mut env.scope(), &env.report_error);
v8::callback_scope!(unsafe scope, env.context());
let this = v8::undefined(&mut env.scope());
let report_error = v8::Local::new(scope, &env.report_error);
let this = v8::undefined(scope);
if report_error
.call(&mut env.scope(), this.into(), &[err.unwrap()])
.call(scope, this.into(), &[err.unwrap()])
.is_none()
{
return napi_generic_failure;
@ -251,7 +253,9 @@ fn napi_make_callback<'s>(
check_arg!(env, argv);
}
let Some(recv) = recv.and_then(|v| v.to_object(&mut env.scope())) else {
v8::callback_scope!(unsafe scope, env.context());
let Some(recv) = recv.and_then(|v| v.to_object(scope)) else {
return napi_object_expected;
};
@ -271,7 +275,7 @@ fn napi_make_callback<'s>(
// TODO: async_context
let Some(v) = func.call(&mut env.scope(), recv.into(), args) else {
let Some(v) = func.call(scope, recv.into(), args) else {
return napi_generic_failure;
};
@ -291,12 +295,12 @@ fn napi_create_buffer<'s>(
) -> napi_status {
check_arg!(env, result);
let ab = v8::ArrayBuffer::new(&mut env.scope(), length);
v8::callback_scope!(unsafe scope, env.context());
let buffer_constructor =
v8::Local::new(&mut env.scope(), &env.buffer_constructor);
let Some(buffer) =
buffer_constructor.new_instance(&mut env.scope(), &[ab.into()])
let ab = v8::ArrayBuffer::new(scope, length);
let buffer_constructor = v8::Local::new(scope, &env.buffer_constructor);
let Some(buffer) = buffer_constructor.new_instance(scope, &[ab.into()])
else {
return napi_generic_failure;
};
@ -334,13 +338,11 @@ fn napi_create_external_buffer<'s>(
finalize_hint,
);
let ab =
v8::ArrayBuffer::with_backing_store(&mut env.scope(), &store.make_shared());
v8::callback_scope!(unsafe scope, env.context());
let ab = v8::ArrayBuffer::with_backing_store(scope, &store.make_shared());
let buffer_constructor =
v8::Local::new(&mut env.scope(), &env.buffer_constructor);
let Some(buffer) =
buffer_constructor.new_instance(&mut env.scope(), &[ab.into()])
let buffer_constructor = v8::Local::new(scope, &env.buffer_constructor);
let Some(buffer) = buffer_constructor.new_instance(scope, &[ab.into()])
else {
return napi_generic_failure;
};
@ -362,12 +364,12 @@ fn napi_create_buffer_copy<'s>(
) -> napi_status {
check_arg!(env, result);
let ab = v8::ArrayBuffer::new(&mut env.scope(), length);
v8::callback_scope!(unsafe scope, env.context());
let buffer_constructor =
v8::Local::new(&mut env.scope(), &env.buffer_constructor);
let Some(buffer) =
buffer_constructor.new_instance(&mut env.scope(), &[ab.into()])
let ab = v8::ArrayBuffer::new(scope, length);
let buffer_constructor = v8::Local::new(scope, &env.buffer_constructor);
let Some(buffer) = buffer_constructor.new_instance(scope, &[ab.into()])
else {
return napi_generic_failure;
};
@ -493,33 +495,37 @@ pub(crate) fn napi_create_async_work(
check_arg!(env, execute);
check_arg!(env, result);
let resource = if let Some(v) = *async_resource {
let Some(resource) = v.to_object(&mut env.scope()) else {
return napi_set_last_error(env, napi_object_expected);
let work = {
v8::callback_scope!(unsafe scope, env.context());
let resource = if let Some(v) = *async_resource {
let Some(resource) = v.to_object(scope) else {
return napi_set_last_error(env, napi_object_expected);
};
resource
} else {
v8::Object::new(scope)
};
resource
} else {
v8::Object::new(&mut env.scope())
let Some(resource_name) =
async_resource_name.and_then(|v| v.to_string(scope))
else {
return napi_set_last_error(env, napi_string_expected);
};
let resource_name = resource_name.to_rust_string_lossy(scope);
Box::new(AsyncWork {
state: AtomicU8::new(AsyncWork::IDLE),
env: env_ptr,
_async_resource: v8::Global::new(scope, resource),
_async_resource_name: resource_name,
execute: execute.unwrap(),
complete,
data,
})
};
let Some(resource_name) =
async_resource_name.and_then(|v| v.to_string(&mut env.scope()))
else {
return napi_set_last_error(env, napi_string_expected);
};
let resource_name = resource_name.to_rust_string_lossy(&mut env.scope());
let work = Box::new(AsyncWork {
state: AtomicU8::new(AsyncWork::IDLE),
env: env_ptr,
_async_resource: v8::Global::new(&mut env.scope(), resource),
_async_resource_name: resource_name,
execute: execute.unwrap(),
complete,
data,
});
unsafe {
*result = Box::into_raw(work) as _;
}
@ -653,7 +659,7 @@ extern "C" fn default_call_js_cb(
&& let Ok(js_callback) = v8::Local::<v8::Function>::try_from(js_callback)
{
let env = unsafe { &mut *(env as *mut Env) };
let scope = &mut env.scope();
v8::callback_scope!(unsafe scope, env.context());
let recv = v8::undefined(scope);
js_callback.call(scope, recv.into(), &[]);
}
@ -799,7 +805,7 @@ impl TsFn {
let context = SendPtr(self.context);
let call_js_cb = self.call_js_cb;
self.sender.spawn(move |scope: &mut v8::HandleScope| {
self.sender.spawn(move |scope: &mut v8::PinScope<'_, '_>| {
let data = data.take();
// if is_closed then tsfn is freed, don't read from it.
@ -865,32 +871,36 @@ fn napi_create_threadsafe_function(
}
check_arg!(env, result);
let func = if let Some(value) = *func {
let Ok(func) = v8::Local::<v8::Function>::try_from(value) else {
return napi_set_last_error(env, napi_function_expected);
let (func, resource, resource_name) = {
v8::callback_scope!(unsafe scope, env.context());
let func = if let Some(value) = *func {
let Ok(func) = v8::Local::<v8::Function>::try_from(value) else {
return napi_set_last_error(env, napi_function_expected);
};
Some(v8::Global::new(scope, func))
} else {
check_arg!(env, call_js_cb);
None
};
Some(v8::Global::new(&mut env.scope(), func))
} else {
check_arg!(env, call_js_cb);
None
};
let resource = if let Some(v) = *async_resource {
let Some(resource) = v.to_object(&mut env.scope()) else {
return napi_set_last_error(env, napi_object_expected);
let resource = if let Some(v) = *async_resource {
let Some(resource) = v.to_object(scope) else {
return napi_set_last_error(env, napi_object_expected);
};
resource
} else {
v8::Object::new(scope)
};
resource
} else {
v8::Object::new(&mut env.scope())
};
let resource = v8::Global::new(&mut env.scope(), resource);
let resource = v8::Global::new(scope, resource);
let Some(resource_name) =
async_resource_name.and_then(|v| v.to_string(&mut env.scope()))
else {
return napi_set_last_error(env, napi_string_expected);
let Some(resource_name) =
async_resource_name.and_then(|v| v.to_string(scope))
else {
return napi_set_last_error(env, napi_string_expected);
};
let resource_name = resource_name.to_rust_string_lossy(scope);
(func, resource, resource_name)
};
let resource_name = resource_name.to_rust_string_lossy(&mut env.scope());
let tsfn = Box::new(TsFn {
env,

View file

@ -126,11 +126,8 @@ pub(crate) unsafe fn check_new_from_utf8_len<'s>(
};
let result = {
let env = unsafe { &mut *(env as *mut Env) };
v8::String::new_from_utf8(
&mut env.scope(),
string,
v8::NewStringType::Internalized,
)
v8::callback_scope!(unsafe scope, env.context());
v8::String::new_from_utf8(scope, string, v8::NewStringType::Internalized)
};
return_error_status_if_false!(env, result.is_some(), napi_generic_failure);
Ok(result.unwrap())
@ -163,7 +160,7 @@ pub(crate) unsafe fn v8_name_from_property_descriptor<'s>(
pub(crate) fn napi_clear_last_error(env: *mut Env) -> napi_status {
let env = unsafe { &mut *env };
env.last_error.error_code = napi_ok;
env.last_error.error_code.set(napi_ok);
env.last_error.engine_error_code = 0;
env.last_error.engine_reserved = std::ptr::null_mut();
env.last_error.error_message = std::ptr::null_mut();
@ -171,11 +168,11 @@ pub(crate) fn napi_clear_last_error(env: *mut Env) -> napi_status {
}
pub(crate) fn napi_set_last_error(
env: *mut Env,
env: *const Env,
error_code: napi_status,
) -> napi_status {
let env = unsafe { &mut *env };
env.last_error.error_code = error_code;
let env = unsafe { &*env };
env.last_error.error_code.set(error_code);
error_code
}
@ -243,8 +240,8 @@ macro_rules! napi_wrap {
$crate::util::napi_clear_last_error(env);
let scope_env = unsafe { &mut *env_ptr };
let scope = &mut scope_env.scope();
let try_catch = &mut v8::TryCatch::new(scope);
deno_core::v8::callback_scope!(unsafe scope, scope_env.context());
deno_core::v8::tc_scope!(try_catch, scope);
#[inline(always)]
fn inner $( < $( $x ),* > )? ( $env: & $( $lt )? mut Env , $( $ident : $ty ),* ) -> napi_status $body

View file

@ -269,7 +269,7 @@ pub fn op_tls_key_static(
#[op2]
pub fn op_tls_cert_resolver_create<'s>(
scope: &mut v8::HandleScope<'s>,
scope: &mut v8::PinScope<'s, '_>,
) -> v8::Local<'s, v8::Array> {
let (resolver, lookup) = new_resolver();
let resolver = deno_core::cppgc::make_cppgc_object(

View file

@ -111,7 +111,7 @@ impl GlobalsStorage {
}
pub fn global_template_middleware<'s>(
_scope: &mut v8::HandleScope<'s, ()>,
_scope: &mut v8::PinScope<'s, '_, ()>,
template: v8::Local<'s, v8::ObjectTemplate>,
) -> v8::Local<'s, v8::ObjectTemplate> {
let mut config = v8::NamedPropertyHandlerConfiguration::new().flags(
@ -135,7 +135,7 @@ pub fn global_template_middleware<'s>(
}
pub fn global_object_middleware<'s>(
scope: &mut v8::HandleScope<'s>,
scope: &mut v8::PinScope<'s, '_>,
global: v8::Local<'s, v8::Object>,
) {
// ensure the global object is not Object.prototype
@ -218,7 +218,7 @@ pub fn global_object_middleware<'s>(
}
fn is_managed_key(
scope: &mut v8::HandleScope,
scope: &mut v8::PinScope<'_, '_>,
key: v8::Local<v8::Name>,
) -> bool {
let Ok(str): Result<v8::Local<v8::String>, _> = key.try_into() else {
@ -235,7 +235,7 @@ fn is_managed_key(
MANAGED_GLOBALS.binary_search(&&buf[..len]).is_ok()
}
fn current_mode(scope: &mut v8::HandleScope) -> Mode {
fn current_mode(scope: &mut v8::PinScope<'_, '_>) -> Mode {
let Some(host_defined_options) = scope.get_current_host_defined_options()
else {
return Mode::Deno;
@ -252,7 +252,7 @@ fn current_mode(scope: &mut v8::HandleScope) -> Mode {
}
pub fn getter<'s>(
scope: &mut v8::HandleScope<'s>,
scope: &mut v8::PinScope<'s, '_>,
key: v8::Local<'s, v8::Name>,
args: v8::PropertyCallbackArguments<'s>,
mut rv: v8::ReturnValue,
@ -286,7 +286,7 @@ pub fn getter<'s>(
}
pub fn setter<'s>(
scope: &mut v8::HandleScope<'s>,
scope: &mut v8::PinScope<'s, '_>,
key: v8::Local<'s, v8::Name>,
value: v8::Local<'s, v8::Value>,
args: v8::PropertyCallbackArguments<'s>,
@ -318,7 +318,7 @@ pub fn setter<'s>(
}
pub fn query<'s>(
scope: &mut v8::HandleScope<'s>,
scope: &mut v8::PinScope<'s, '_>,
key: v8::Local<'s, v8::Name>,
_args: v8::PropertyCallbackArguments<'s>,
mut rv: v8::ReturnValue<v8::Integer>,
@ -351,7 +351,7 @@ pub fn query<'s>(
}
pub fn deleter<'s>(
scope: &mut v8::HandleScope<'s>,
scope: &mut v8::PinScope<'s, '_>,
key: v8::Local<'s, v8::Name>,
args: v8::PropertyCallbackArguments<'s>,
mut rv: v8::ReturnValue<v8::Boolean>,
@ -387,7 +387,7 @@ pub fn deleter<'s>(
}
pub fn enumerator<'s>(
scope: &mut v8::HandleScope<'s>,
scope: &mut v8::PinScope<'s, '_>,
_args: v8::PropertyCallbackArguments<'s>,
mut rv: v8::ReturnValue<v8::Array>,
) {
@ -417,7 +417,7 @@ pub fn enumerator<'s>(
}
pub fn definer<'s>(
scope: &mut v8::HandleScope<'s>,
scope: &mut v8::PinScope<'s, '_>,
key: v8::Local<'s, v8::Name>,
descriptor: &v8::PropertyDescriptor,
args: v8::PropertyCallbackArguments<'s>,
@ -452,7 +452,7 @@ pub fn definer<'s>(
}
pub fn descriptor<'s>(
scope: &mut v8::HandleScope<'s>,
scope: &mut v8::PinScope<'s, '_>,
key: v8::Local<'s, v8::Name>,
_args: v8::PropertyCallbackArguments<'s>,
mut rv: v8::ReturnValue,
@ -463,7 +463,7 @@ pub fn descriptor<'s>(
let mode = current_mode(scope);
let scope = &mut v8::TryCatch::new(scope);
v8::tc_scope!(scope, scope);
let context = scope.get_current_context();
let inner = {

View file

@ -904,7 +904,7 @@ pub type NodeResolverRc<TInNpmPackageChecker, TNpmPackageFolderResolver, TSys> =
#[allow(clippy::disallowed_types)]
pub fn create_host_defined_options<'s>(
scope: &mut v8::HandleScope<'s>,
scope: &mut v8::PinScope<'s, '_>,
) -> v8::Local<'s, v8::Data> {
let host_defined_options = v8::PrimitiveArray::new(scope, 1);
let value = v8::Boolean::new(scope, true);

View file

@ -123,7 +123,7 @@ fn utf8_to_ascii(source: &[u8]) -> Vec<u8> {
#[op2]
pub fn op_node_decode_utf8<'a>(
scope: &mut v8::HandleScope<'a>,
scope: &mut v8::PinScope<'a, '_>,
buf: v8::Local<v8::ArrayBufferView>,
start: v8::Local<v8::Value>,
end: v8::Local<v8::Value>,
@ -174,7 +174,7 @@ enum BufferError {
#[inline(always)]
fn parse_array_index(
scope: &mut v8::HandleScope,
scope: &mut v8::PinScope<'_, '_>,
arg: v8::Local<v8::Value>,
default: usize,
) -> Result<usize, BufferError> {

View file

@ -139,7 +139,7 @@ impl HandleWrap {
&self,
op_state: Rc<RefCell<OpState>>,
#[this] this: v8::Global<v8::Object>,
scope: &mut v8::HandleScope,
scope: &mut v8::PinScope<'_, '_>,
#[global] cb: Option<v8::Global<v8::Function>>,
) -> Result<(), ResourceError> {
if self.state.get() != State::Initialized {
@ -150,7 +150,7 @@ impl HandleWrap {
// This effectively mimicks Node's OnClose callback.
//
// https://github.com/nodejs/node/blob/038d82980ab26cd79abe4409adc2fecad94d7c93/src/handle_wrap.cc#L135-L157
let on_close = move |scope: &mut v8::HandleScope| {
let on_close = move |scope: &mut v8::PinScope<'_, '_>| {
assert!(state.get() == State::Closing);
state.set(State::Closed);
@ -211,12 +211,12 @@ impl HandleWrap {
}
fn uv_close<F>(
scope: &mut v8::HandleScope,
scope: &mut v8::PinScope<'_, '_>,
op_state: Rc<RefCell<OpState>>,
this: v8::Global<v8::Object>,
on_close: F,
) where
F: FnOnce(&mut v8::HandleScope) + 'static,
F: FnOnce(&mut v8::PinScope<'_, '_>) + 'static,
{
// Call _onClose() on the JS handles. Not needed for Rust handles.
let this = v8::Local::new(scope, this);

View file

@ -108,8 +108,8 @@ pub enum InspectorConnectError {
#[op2(stack_trace)]
#[cppgc]
pub fn op_inspector_connect<'s, P>(
isolate: *mut v8::Isolate,
scope: &mut v8::HandleScope<'s>,
isolate: &v8::Isolate,
scope: &mut v8::PinScope<'s, '_>,
state: &mut OpState,
connect_to_main_thread: bool,
callback: v8::Local<'s, v8::Function>,
@ -131,6 +131,9 @@ where
let inspector = state.borrow::<Rc<JsRuntimeInspector>>().clone();
// SAFETY: just grabbing the raw pointer
let isolate = unsafe { isolate.as_raw_isolate_ptr() };
// The inspector connection does not keep the event loop alive but
// when the inspector sends a message to the frontend, the JS that
// that runs may keep the event loop alive so we have to call back
@ -140,10 +143,11 @@ where
// SAFETY: This function is called directly by the inspector, so
// 1) The isolate is still valid
// 2) We are on the same thread as the Isolate
let scope = unsafe { &mut v8::CallbackScope::new(&mut *isolate) };
let mut isolate = unsafe { v8::Isolate::from_raw_isolate_ptr(isolate) };
v8::callback_scope!(unsafe let scope, &mut isolate);
let context = v8::Local::new(scope, context.clone());
let scope = &mut v8::ContextScope::new(scope, context);
let scope = &mut v8::TryCatch::new(scope);
v8::tc_scope!(let scope, scope);
let recv = v8::undefined(scope);
if let Some(message) = v8::String::new(scope, &message.content) {
let callback = v8::Local::new(scope, callback.clone());

View file

@ -28,12 +28,12 @@ mod impl_ {
use serde::Serialize;
/// Wrapper around v8 value that implements Serialize.
struct SerializeWrapper<'a, 'b>(
RefCell<&'b mut v8::HandleScope<'a>>,
struct SerializeWrapper<'a, 'b, 'c>(
RefCell<&'b mut v8::PinScope<'a, 'c>>,
v8::Local<'a, v8::Value>,
);
impl Serialize for SerializeWrapper<'_, '_> {
impl Serialize for SerializeWrapper<'_, '_, '_> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
@ -46,7 +46,7 @@ mod impl_ {
/// This allows us to go from v8 values to JSON without having to
/// deserialize into a `serde_json::Value` and then reserialize to JSON
fn serialize_v8_value<'a, S: Serializer>(
scope: &mut v8::HandleScope<'a>,
scope: &mut v8::PinScope<'a, '_>,
value: v8::Local<'a, v8::Value>,
ser: S,
) -> Result<S::Ok, S::Error> {
@ -182,7 +182,7 @@ mod impl_ {
#[op2(async)]
pub fn op_node_ipc_write<'a>(
scope: &mut v8::HandleScope<'a>,
scope: &mut v8::PinScope<'a, '_>,
state: Rc<RefCell<OpState>>,
#[smi] rid: ResourceId,
value: v8::Local<'a, v8::Value>,
@ -287,7 +287,7 @@ mod impl_ {
fn serialize_js_to_json(runtime: &mut JsRuntime, js: String) -> String {
let val = runtime.execute_script("", js).unwrap();
let scope = &mut runtime.handle_scope();
deno_core::scope!(scope, runtime);
let val = v8::Local::new(scope, val);
let mut buf = Vec::new();
let mut ser = deno_core::serde_json::Serializer::new(&mut buf);

View file

@ -702,10 +702,10 @@ pub fn op_require_break_on_next_statement(state: Rc<RefCell<OpState>>) {
#[op2(fast)]
pub fn op_require_can_parse_as_esm(
scope: &mut v8::HandleScope,
scope: &mut v8::PinScope<'_, '_>,
#[string] source: &str,
) -> bool {
let scope = &mut v8::TryCatch::new(scope);
v8::tc_scope!(scope, scope);
let Some(source) = v8::String::new(scope, source) else {
return false;
};

View file

@ -48,7 +48,7 @@ impl<'a> FromV8<'a> for DatabaseSyncOptions {
type Error = validators::Error;
fn from_v8(
scope: &mut v8::HandleScope<'a>,
scope: &mut v8::PinScope<'a, '_>,
value: v8::Local<'a, v8::Value>,
) -> Result<Self, Self::Error> {
use validators::Error;
@ -175,7 +175,7 @@ struct ApplyChangesetOptions<'a> {
// Local references.
impl<'a> ApplyChangesetOptions<'a> {
fn from_value(
scope: &mut v8::HandleScope<'a>,
scope: &mut v8::PinScope<'a, '_>,
value: v8::Local<'a, v8::Value>,
) -> Result<Option<Self>, validators::Error> {
use validators::Error;
@ -351,7 +351,7 @@ fn open_db(
}
fn database_constructor(
_: &mut v8::HandleScope,
_: &mut v8::PinScope<'_, '_>,
args: &v8::FunctionCallbackArguments,
) -> Result<(), validators::Error> {
// TODO(littledivy): use `IsConstructCall()`
@ -363,7 +363,7 @@ fn database_constructor(
}
fn is_open(
scope: &mut v8::HandleScope,
scope: &mut v8::PinScope<'_, '_>,
args: &v8::FunctionCallbackArguments,
) -> Result<(), SqliteError> {
let this_ = args.this();
@ -570,7 +570,7 @@ impl DatabaseSync {
#[reentrant]
fn apply_changeset<'a>(
&self,
scope: &mut v8::HandleScope<'a>,
scope: &mut v8::PinScope<'a, '_>,
#[validate(validators::changeset_buffer)]
#[buffer]
changeset: &[u8],
@ -578,8 +578,8 @@ impl DatabaseSync {
) -> Result<bool, SqliteError> {
let options = ApplyChangesetOptions::from_value(scope, options)?;
struct HandlerCtx<'a, 'b> {
scope: &'a mut v8::HandleScope<'b>,
struct HandlerCtx<'a, 'b, 'c> {
scope: &'a mut v8::PinScope<'b, 'c>,
confict: Option<v8::Local<'b, v8::Function>>,
filter: Option<v8::Local<'b, v8::Function>>,
}
@ -598,7 +598,7 @@ impl DatabaseSync {
let recv = v8::undefined(ctx.scope).into();
let args = [v8::Integer::new(ctx.scope, e_conflict).into()];
let tc_scope = &mut v8::TryCatch::new(ctx.scope);
v8::tc_scope!(tc_scope, ctx.scope);
let ret = conflict
.call(tc_scope, recv, &args)

View file

@ -25,7 +25,7 @@ impl FromV8<'_> for SessionOptions {
type Error = validators::Error;
fn from_v8(
scope: &mut v8::HandleScope,
scope: &mut v8::PinScope<'_, '_>,
value: v8::Local<v8::Value>,
) -> Result<Self, validators::Error> {
use validators::Error;

View file

@ -30,7 +30,7 @@ impl<'a> ToV8<'a> for RunStatementResult {
fn to_v8(
self,
scope: &mut v8::HandleScope<'a>,
scope: &mut v8::PinScope<'a, '_>,
) -> Result<v8::Local<'a, v8::Value>, SqliteError> {
v8_static_strings! {
LAST_INSERT_ROW_ID = "lastInsertRowid",
@ -226,7 +226,7 @@ impl StatementSync {
fn column_value<'a>(
&self,
index: i32,
scope: &mut v8::HandleScope<'a>,
scope: &mut v8::PinScope<'a, '_>,
) -> Result<v8::Local<'a, v8::Value>, SqliteError> {
// SAFETY: `self.inner` is a valid pointer to a sqlite3_stmt
// as it lives as long as the StatementSync instance.
@ -281,7 +281,7 @@ impl StatementSync {
// Read the current row of the prepared statement.
fn read_row<'a>(
&self,
scope: &mut v8::HandleScope<'a>,
scope: &mut v8::PinScope<'a, '_>,
) -> Result<Option<v8::Local<'a, v8::Object>>, SqliteError> {
if self.step()? {
return Ok(None);
@ -314,7 +314,7 @@ impl StatementSync {
fn bind_value(
&self,
scope: &mut v8::HandleScope,
scope: &mut v8::PinScope<'_, '_>,
value: v8::Local<v8::Value>,
index: i32,
) -> Result<(), SqliteError> {
@ -409,7 +409,7 @@ impl StatementSync {
// Bind the parameters to the prepared statement.
fn bind_params(
&self,
scope: &mut v8::HandleScope,
scope: &mut v8::PinScope<'_, '_>,
params: Option<&v8::FunctionCallbackArguments>,
) -> Result<(), SqliteError> {
let raw = self.inner;
@ -547,7 +547,7 @@ impl StatementSync {
// Optionally, parameters can be bound to the prepared statement.
fn get<'a>(
&self,
scope: &mut v8::HandleScope<'a>,
scope: &mut v8::PinScope<'a, '_>,
#[varargs] params: Option<&v8::FunctionCallbackArguments>,
) -> Result<v8::Local<'a, v8::Value>, SqliteError> {
self.reset()?;
@ -571,7 +571,7 @@ impl StatementSync {
#[to_v8]
fn run(
&self,
scope: &mut v8::HandleScope,
scope: &mut v8::PinScope<'_, '_>,
#[varargs] params: Option<&v8::FunctionCallbackArguments>,
) -> Result<RunStatementResult, SqliteError> {
let db_rc = self.db.upgrade().ok_or(SqliteError::InUse)?;
@ -599,7 +599,7 @@ impl StatementSync {
// Optionally, parameters can be bound to the prepared statement.
fn all<'a>(
&self,
scope: &mut v8::HandleScope<'a>,
scope: &mut v8::PinScope<'a, '_>,
#[varargs] params: Option<&v8::FunctionCallbackArguments>,
) -> Result<v8::Local<'a, v8::Array>, SqliteError> {
let mut arr = vec![];
@ -617,7 +617,7 @@ impl StatementSync {
fn iterate<'a>(
&self,
scope: &mut v8::HandleScope<'a>,
scope: &mut v8::PinScope<'a, '_>,
#[varargs] params: Option<&v8::FunctionCallbackArguments>,
) -> Result<v8::Local<'a, v8::Object>, SqliteError> {
macro_rules! v8_static_strings {
@ -641,7 +641,7 @@ impl StatementSync {
self.bind_params(scope, params)?;
let iterate_next = |scope: &mut v8::HandleScope,
let iterate_next = |scope: &mut v8::PinScope<'_, '_>,
args: v8::FunctionCallbackArguments,
mut rv: v8::ReturnValue| {
let context = v8::Local::<v8::External>::try_from(args.data())
@ -688,7 +688,7 @@ impl StatementSync {
rv.set(result.into());
};
let iterate_return = |scope: &mut v8::HandleScope,
let iterate_return = |scope: &mut v8::PinScope<'_, '_>,
args: v8::FunctionCallbackArguments,
mut rv: v8::ReturnValue| {
let context = v8::Local::<v8::External>::try_from(args.data())

View file

@ -50,7 +50,7 @@ impl From<ErrorCode> for deno_error::PropertyValue {
}
pub(super) fn sql_str(
_: &mut v8::HandleScope,
_: &mut v8::PinScope<'_, '_>,
value: v8::Local<v8::Value>,
) -> Result<(), Error> {
if value.is_string() {
@ -63,7 +63,7 @@ pub(super) fn sql_str(
}
pub(super) fn changeset_buffer(
_: &mut v8::HandleScope,
_: &mut v8::PinScope<'_, '_>,
value: v8::Local<v8::Value>,
) -> Result<(), Error> {
if value.is_uint8_array() {
@ -76,7 +76,7 @@ pub(super) fn changeset_buffer(
}
pub(super) fn path_str(
_: &mut v8::HandleScope,
_: &mut v8::PinScope<'_, '_>,
value: v8::Local<v8::Value>,
) -> Result<(), Error> {
if value.is_string() {
@ -89,7 +89,7 @@ pub(super) fn path_str(
}
pub(super) fn allow_bare_named_params_bool(
_: &mut v8::HandleScope,
_: &mut v8::PinScope<'_, '_>,
value: v8::Local<v8::Value>,
) -> Result<(), Error> {
if value.is_boolean() {
@ -102,7 +102,7 @@ pub(super) fn allow_bare_named_params_bool(
}
pub(super) fn read_big_ints_bool(
_: &mut v8::HandleScope,
_: &mut v8::PinScope<'_, '_>,
value: v8::Local<v8::Value>,
) -> Result<(), Error> {
if value.is_boolean() {

View file

@ -102,7 +102,7 @@ pub fn op_node_call_is_from_dependency<
TSys: ExtNodeSys + 'static,
>(
state: &mut OpState,
scope: &mut v8::HandleScope,
scope: &mut v8::PinScope<'_, '_>,
) -> bool {
// non internal call site should appear in < 20 frames
let Some(stack_trace) = v8::StackTrace::current_stack_trace(scope, 20) else {

View file

@ -18,7 +18,7 @@ pub fn op_v8_cached_data_version_tag() -> u32 {
#[op2(fast)]
pub fn op_v8_get_heap_statistics(
scope: &mut v8::HandleScope,
scope: &mut v8::PinScope<'_, '_>,
#[buffer] buffer: &mut [f64],
) {
let stats = scope.get_heap_statistics();
@ -59,7 +59,7 @@ unsafe impl v8::cppgc::GarbageCollected for Serializer<'_> {
impl SerializerDelegate {
fn obj<'s>(
&self,
scope: &mut v8::HandleScope<'s>,
scope: &mut v8::PinScope<'s, '_>,
) -> v8::Local<'s, v8::Object> {
v8::Local::new(scope, &self.obj)
}
@ -68,7 +68,7 @@ impl SerializerDelegate {
impl v8::ValueSerializerImpl for SerializerDelegate {
fn get_shared_array_buffer_id<'s>(
&self,
scope: &mut v8::HandleScope<'s>,
scope: &mut v8::PinScope<'s, '_>,
shared_array_buffer: v8::Local<'s, v8::SharedArrayBuffer>,
) -> Option<u32> {
let obj = self.obj(scope);
@ -85,12 +85,12 @@ impl v8::ValueSerializerImpl for SerializerDelegate {
}
None
}
fn has_custom_host_object(&self, _isolate: &mut v8::Isolate) -> bool {
fn has_custom_host_object(&self, _isolate: &v8::Isolate) -> bool {
false
}
fn throw_data_clone_error<'s>(
&self,
scope: &mut v8::HandleScope<'s>,
scope: &mut v8::PinScope<'s, '_>,
message: v8::Local<'s, v8::String>,
) {
let obj = self.obj(scope);
@ -113,7 +113,7 @@ impl v8::ValueSerializerImpl for SerializerDelegate {
fn write_host_object<'s>(
&self,
scope: &mut v8::HandleScope<'s>,
scope: &mut v8::PinScope<'s, '_>,
object: v8::Local<'s, v8::Object>,
_value_serializer: &dyn ValueSerializerHelper,
) -> Option<bool> {
@ -134,7 +134,7 @@ impl v8::ValueSerializerImpl for SerializerDelegate {
fn is_host_object<'s>(
&self,
_scope: &mut v8::HandleScope<'s>,
_scope: &mut v8::PinScope<'s, '_>,
_object: v8::Local<'s, v8::Object>,
) -> Option<bool> {
// should never be called because has_custom_host_object returns false
@ -145,7 +145,7 @@ impl v8::ValueSerializerImpl for SerializerDelegate {
#[op2]
#[cppgc]
pub fn op_v8_new_serializer(
scope: &mut v8::HandleScope,
scope: &mut v8::PinScope<'_, '_>,
obj: v8::Local<v8::Object>,
) -> Serializer<'static> {
let obj = v8::Global::new(scope, obj);
@ -210,7 +210,7 @@ pub fn op_v8_write_uint64(#[cppgc] ser: &Serializer, hi: u32, lo: u32) {
#[op2(nofast, reentrant)]
pub fn op_v8_write_value(
scope: &mut v8::HandleScope,
scope: &mut v8::PinScope<'_, '_>,
#[cppgc] ser: &Serializer,
value: v8::Local<v8::Value>,
) {
@ -257,7 +257,7 @@ unsafe impl GarbageCollected for DeserializerDelegate {
impl v8::ValueDeserializerImpl for DeserializerDelegate {
fn read_host_object<'s>(
&self,
scope: &mut v8::HandleScope<'s>,
scope: &mut v8::PinScope<'s, '_>,
_value_deserializer: &dyn v8::ValueDeserializerHelper,
) -> Option<v8::Local<'s, v8::Object>> {
let obj = self.obj.get(scope).unwrap();
@ -265,7 +265,8 @@ impl v8::ValueDeserializerImpl for DeserializerDelegate {
.v8_string(scope)
.unwrap()
.into();
let scope = &mut v8::AllowJavascriptExecutionScope::new(scope);
let scope = std::pin::pin!(v8::AllowJavascriptExecutionScope::new(scope));
let scope = &mut scope.init();
if let Some(v) = obj.get(scope, key)
&& let Ok(v) = v.try_cast::<v8::Function>()
{
@ -290,7 +291,7 @@ impl v8::ValueDeserializerImpl for DeserializerDelegate {
#[op2]
#[cppgc]
pub fn op_v8_new_deserializer(
scope: &mut v8::HandleScope,
scope: &mut v8::PinScope<'_, '_>,
obj: v8::Local<v8::Object>,
buffer: v8::Local<v8::ArrayBufferView>,
) -> Result<Deserializer<'static>, JsErrorBox> {
@ -349,7 +350,7 @@ pub fn op_v8_read_double(
#[op2(nofast)]
pub fn op_v8_read_header(
scope: &mut v8::HandleScope,
scope: &mut v8::PinScope<'_, '_>,
#[cppgc] deser: &Deserializer,
) -> bool {
let context = scope.get_current_context();
@ -406,7 +407,7 @@ pub fn op_v8_get_wire_format_version(#[cppgc] deser: &Deserializer) -> u32 {
#[op2(reentrant)]
pub fn op_v8_read_value<'s>(
scope: &mut v8::HandleScope<'s>,
scope: &mut v8::PinScope<'s, '_>,
#[cppgc] deser: &Deserializer,
) -> v8::Local<'s, v8::Value> {
let context = scope.get_current_context();

View file

@ -35,7 +35,7 @@ unsafe impl v8::cppgc::GarbageCollected for ContextifyScript {
impl ContextifyScript {
#[allow(clippy::too_many_arguments)]
fn create<'s>(
scope: &mut v8::HandleScope<'s>,
scope: &mut v8::PinScope<'s, '_>,
source: v8::Local<'s, v8::String>,
filename: v8::Local<'s, v8::Value>,
line_offset: i32,
@ -95,7 +95,7 @@ impl ContextifyScript {
v8::script_compiler::CompileOptions::NoCompileOptions
};
let scope = &mut v8::TryCatch::new(scope);
v8::tc_scope!(scope, scope);
let Some(unbound_script) = v8::script_compiler::compile_unbound_script(
scope,
@ -138,7 +138,7 @@ impl ContextifyScript {
fn run_in_context<'s>(
&self,
scope: &mut v8::HandleScope<'s>,
scope: &mut v8::PinScope<'s, '_>,
sandbox: Option<v8::Local<'s, v8::Object>>,
timeout: i64,
display_errors: bool,
@ -171,18 +171,20 @@ impl ContextifyScript {
)
}
pub fn eval_machine<'s>(
pub fn eval_machine<'s, 'i>(
&self,
scope: &mut v8::HandleScope<'s>,
context: v8::Local<v8::Context>,
scope: &mut v8::PinScope<'s, 'i>,
context: v8::Local<'s, v8::Context>,
timeout: i64,
_display_errors: bool,
_break_on_sigint: bool,
microtask_queue: Option<&v8::MicrotaskQueue>,
) -> Option<v8::Local<'s, v8::Value>> {
let context_scope = &mut v8::ContextScope::new(scope, context);
let scope = &mut v8::EscapableHandleScope::new(context_scope);
let scope = &mut v8::TryCatch::new(scope);
let scope_storage =
std::pin::pin!(v8::EscapableHandleScope::new(context_scope));
let scope = &mut scope_storage.init();
v8::tc_scope!(scope, scope);
let unbound_script = self.script.get(scope).unwrap();
let script = unbound_script.bind_to_current_context(scope);
@ -299,7 +301,7 @@ extern "C" fn allow_wasm_code_gen(
impl ContextifyContext {
pub fn attach(
scope: &mut v8::HandleScope,
scope: &mut v8::PinScope<'_, '_>,
sandbox_obj: v8::Local<v8::Object>,
_name: String,
_origin: String,
@ -380,7 +382,7 @@ impl ContextifyContext {
}
pub fn from_sandbox_obj<'a>(
scope: &mut v8::HandleScope<'a>,
scope: &mut v8::PinScope<'a, '_>,
sandbox_obj: v8::Local<v8::Object>,
) -> Option<&'a Self> {
let private_str =
@ -399,7 +401,7 @@ impl ContextifyContext {
}
pub fn is_contextify_context(
scope: &mut v8::HandleScope,
scope: &mut v8::PinScope<'_, '_>,
object: v8::Local<v8::Object>,
) -> bool {
Self::from_sandbox_obj(scope, object).is_some()
@ -407,14 +409,14 @@ impl ContextifyContext {
pub fn context<'a>(
&self,
scope: &mut v8::HandleScope<'a>,
scope: &mut v8::PinScope<'a, '_>,
) -> v8::Local<'a, v8::Context> {
self.context.get(scope).unwrap()
}
fn global_proxy<'s>(
&self,
scope: &mut v8::HandleScope<'s>,
scope: &mut v8::PinScope<'s, '_>,
) -> v8::Local<'s, v8::Object> {
let ctx = self.context(scope);
ctx.global(scope)
@ -422,7 +424,7 @@ impl ContextifyContext {
fn sandbox<'a>(
&self,
scope: &mut v8::HandleScope<'a>,
scope: &mut v8::PinScope<'a, '_>,
) -> Option<v8::Local<'a, v8::Object>> {
self.sandbox.get(scope)
}
@ -437,7 +439,7 @@ impl ContextifyContext {
}
fn get<'a, 'c>(
scope: &mut v8::HandleScope<'a>,
scope: &mut v8::PinScope<'a, '_>,
object: v8::Local<'a, v8::Object>,
) -> Option<&'c ContextifyContext> {
let context = object.get_creation_context(scope)?;
@ -461,12 +463,13 @@ pub enum ContextInitMode {
}
pub fn create_v8_context<'a>(
scope: &mut v8::HandleScope<'a, ()>,
scope: &mut v8::PinScope<'a, '_, ()>,
object_template: v8::Local<v8::ObjectTemplate>,
mode: ContextInitMode,
microtask_queue: *mut v8::MicrotaskQueue,
) -> v8::Local<'a, v8::Context> {
let scope = &mut v8::EscapableHandleScope::new(scope);
let scope = std::pin::pin!(v8::EscapableHandleScope::new(scope));
let scope = &mut scope.init();
let context = if mode == ContextInitMode::UseSnapshot {
v8::Context::from_snapshot(
@ -505,7 +508,7 @@ struct SlotContextifyGlobalTemplate(v8::Global<v8::ObjectTemplate>);
#[allow(clippy::unnecessary_unwrap)]
pub fn init_global_template<'a>(
scope: &mut v8::HandleScope<'a, ()>,
scope: &mut v8::PinScope<'a, '_, ()>,
mode: ContextInitMode,
) -> v8::Local<'a, v8::ObjectTemplate> {
let maybe_object_template_slot =
@ -552,9 +555,12 @@ thread_local! {
pub static INDEXED_QUERY_MAP_FN: v8::IndexedPropertyQueryCallback = indexed_property_query.map_fn_to();
}
pub fn init_global_template_inner<'a>(
scope: &mut v8::HandleScope<'a, ()>,
pub fn init_global_template_inner<'a, 'b, 'i>(
scope: &'b mut v8::PinScope<'a, 'i, ()>,
) -> v8::Local<'a, v8::ObjectTemplate> {
let scope = std::pin::pin!(v8::EscapableHandleScope::new(scope));
let scope = &mut scope.init();
let global_object_template = v8::ObjectTemplate::new(scope);
global_object_template.set_internal_field_count(3);
@ -599,11 +605,11 @@ pub fn init_global_template_inner<'a>(
global_object_template
.set_indexed_property_handler(indexed_property_handler_config);
global_object_template
scope.escape(global_object_template)
}
fn property_query<'s>(
scope: &mut v8::HandleScope<'s>,
scope: &mut v8::PinScope<'s, '_>,
property: v8::Local<'s, v8::Name>,
args: v8::PropertyCallbackArguments<'s>,
mut rv: v8::ReturnValue<v8::Integer>,
@ -652,7 +658,7 @@ fn property_query<'s>(
}
fn property_getter<'s>(
scope: &mut v8::HandleScope<'s>,
scope: &mut v8::PinScope<'s, '_>,
key: v8::Local<'s, v8::Name>,
args: v8::PropertyCallbackArguments<'s>,
mut ret: v8::ReturnValue,
@ -665,7 +671,7 @@ fn property_getter<'s>(
return v8::Intercepted::No;
};
let tc_scope = &mut v8::TryCatch::new(scope);
v8::tc_scope!(tc_scope, scope);
let maybe_rv = sandbox.get_real_named_property(tc_scope, key).or_else(|| {
ctx
.global_proxy(tc_scope)
@ -689,7 +695,7 @@ fn property_getter<'s>(
}
fn property_setter<'s>(
scope: &mut v8::HandleScope<'s>,
scope: &mut v8::PinScope<'s, '_>,
key: v8::Local<'s, v8::Name>,
value: v8::Local<'s, v8::Value>,
args: v8::PropertyCallbackArguments<'s>,
@ -779,7 +785,7 @@ fn property_setter<'s>(
}
fn property_descriptor<'s>(
scope: &mut v8::HandleScope<'s>,
scope: &mut v8::PinScope<'s, '_>,
key: v8::Local<'s, v8::Name>,
args: v8::PropertyCallbackArguments<'s>,
mut rv: v8::ReturnValue,
@ -805,7 +811,7 @@ fn property_descriptor<'s>(
}
fn property_definer<'s>(
scope: &mut v8::HandleScope<'s>,
scope: &mut v8::PinScope<'s, '_>,
key: v8::Local<'s, v8::Name>,
desc: &v8::PropertyDescriptor,
args: v8::PropertyCallbackArguments<'s>,
@ -840,7 +846,7 @@ fn property_definer<'s>(
};
let define_prop_on_sandbox =
|scope: &mut v8::HandleScope,
|scope: &mut v8::PinScope<'_, '_>,
desc_for_sandbox: &mut v8::PropertyDescriptor| {
if desc.has_enumerable() {
desc_for_sandbox.set_enumerable(desc.enumerable());
@ -889,7 +895,7 @@ fn property_definer<'s>(
}
fn property_deleter<'s>(
scope: &mut v8::HandleScope<'s>,
scope: &mut v8::PinScope<'s, '_>,
key: v8::Local<'s, v8::Name>,
args: v8::PropertyCallbackArguments<'s>,
mut rv: v8::ReturnValue<v8::Boolean>,
@ -913,7 +919,7 @@ fn property_deleter<'s>(
}
fn property_enumerator<'s>(
scope: &mut v8::HandleScope<'s>,
scope: &mut v8::PinScope<'s, '_>,
args: v8::PropertyCallbackArguments<'s>,
mut rv: v8::ReturnValue<v8::Array>,
) {
@ -937,7 +943,7 @@ fn property_enumerator<'s>(
}
fn indexed_property_enumerator<'s>(
scope: &mut v8::HandleScope<'s>,
scope: &mut v8::PinScope<'s, '_>,
args: v8::PropertyCallbackArguments<'s>,
mut rv: v8::ReturnValue<v8::Array>,
) {
@ -975,7 +981,7 @@ fn indexed_property_enumerator<'s>(
}
fn uint32_to_name<'s>(
scope: &mut v8::HandleScope<'s>,
scope: &mut v8::PinScope<'s, '_>,
index: u32,
) -> v8::Local<'s, v8::Name> {
let int = v8::Integer::new_from_unsigned(scope, index);
@ -984,7 +990,7 @@ fn uint32_to_name<'s>(
}
fn indexed_property_query<'s>(
scope: &mut v8::HandleScope<'s>,
scope: &mut v8::PinScope<'s, '_>,
index: u32,
args: v8::PropertyCallbackArguments<'s>,
rv: v8::ReturnValue<v8::Integer>,
@ -994,7 +1000,7 @@ fn indexed_property_query<'s>(
}
fn indexed_property_getter<'s>(
scope: &mut v8::HandleScope<'s>,
scope: &mut v8::PinScope<'s, '_>,
index: u32,
args: v8::PropertyCallbackArguments<'s>,
rv: v8::ReturnValue,
@ -1004,7 +1010,7 @@ fn indexed_property_getter<'s>(
}
fn indexed_property_setter<'s>(
scope: &mut v8::HandleScope<'s>,
scope: &mut v8::PinScope<'s, '_>,
index: u32,
value: v8::Local<'s, v8::Value>,
args: v8::PropertyCallbackArguments<'s>,
@ -1015,7 +1021,7 @@ fn indexed_property_setter<'s>(
}
fn indexed_property_descriptor<'s>(
scope: &mut v8::HandleScope<'s>,
scope: &mut v8::PinScope<'s, '_>,
index: u32,
args: v8::PropertyCallbackArguments<'s>,
rv: v8::ReturnValue,
@ -1025,7 +1031,7 @@ fn indexed_property_descriptor<'s>(
}
fn indexed_property_definer<'s>(
scope: &mut v8::HandleScope<'s>,
scope: &mut v8::PinScope<'s, '_>,
index: u32,
descriptor: &v8::PropertyDescriptor,
args: v8::PropertyCallbackArguments<'s>,
@ -1036,7 +1042,7 @@ fn indexed_property_definer<'s>(
}
fn indexed_property_deleter<'s>(
scope: &mut v8::HandleScope<'s>,
scope: &mut v8::PinScope<'s, '_>,
index: u32,
args: v8::PropertyCallbackArguments<'s>,
mut rv: v8::ReturnValue<v8::Boolean>,
@ -1065,7 +1071,7 @@ fn indexed_property_deleter<'s>(
#[op2]
#[serde]
pub fn op_vm_create_script<'a>(
scope: &mut v8::HandleScope<'a>,
scope: &mut v8::PinScope<'a, '_>,
source: v8::Local<'a, v8::String>,
filename: v8::Local<'a, v8::Value>,
line_offset: i32,
@ -1088,7 +1094,7 @@ pub fn op_vm_create_script<'a>(
#[op2(reentrant)]
pub fn op_vm_script_run_in_context<'a>(
scope: &mut v8::HandleScope<'a>,
scope: &mut v8::PinScope<'a, '_>,
#[cppgc] script: &ContextifyScript,
sandbox: Option<v8::Local<'a, v8::Object>>,
#[serde] timeout: i64,
@ -1106,7 +1112,7 @@ pub fn op_vm_script_run_in_context<'a>(
#[op2(fast)]
pub fn op_vm_create_context(
scope: &mut v8::HandleScope,
scope: &mut v8::PinScope<'_, '_>,
sandbox_obj: v8::Local<v8::Object>,
#[string] name: String,
#[string] origin: String,
@ -1133,7 +1139,7 @@ pub fn op_vm_create_context(
#[op2(fast)]
pub fn op_vm_is_context(
scope: &mut v8::HandleScope,
scope: &mut v8::PinScope<'_, '_>,
sandbox_obj: v8::Local<v8::Value>,
) -> bool {
sandbox_obj
@ -1156,7 +1162,7 @@ struct CompileResult<'s> {
#[op2]
#[serde]
pub fn op_vm_compile_function<'s>(
scope: &mut v8::HandleScope<'s>,
scope: &mut v8::PinScope<'s, '_>,
source: v8::Local<'s, v8::String>,
filename: v8::Local<'s, v8::Value>,
line_offset: i32,
@ -1237,8 +1243,7 @@ pub fn op_vm_compile_function<'s>(
v8::script_compiler::CompileOptions::NoCompileOptions
};
let scope = &mut v8::TryCatch::new(scope);
v8::tc_scope!(scope, scope);
let Some(function) = v8::script_compiler::compile_function(
scope,
&mut source,
@ -1279,7 +1284,7 @@ pub fn op_vm_compile_function<'s>(
#[op2]
pub fn op_vm_script_get_source_map_url<'s>(
scope: &mut v8::HandleScope<'s>,
scope: &mut v8::PinScope<'s, '_>,
#[cppgc] script: &ContextifyScript,
) -> v8::Local<'s, v8::Value> {
let unbound_script = script.script.get(scope).unwrap();
@ -1288,7 +1293,7 @@ pub fn op_vm_script_get_source_map_url<'s>(
#[op2]
pub fn op_vm_script_create_cached_data<'s>(
scope: &mut v8::HandleScope<'s>,
scope: &mut v8::PinScope<'s, '_>,
#[cppgc] script: &ContextifyScript,
) -> v8::Local<'s, v8::Value> {
let unbound_script = script.script.get(scope).unwrap();

View file

@ -1,696 +0,0 @@
// Copyright 2018-2025 the Deno authors. MIT license.
use deno_core::v8;
use deno_core::v8::MapFnTo;
use deno_error::JsErrorBox;
use crate::create_host_defined_options;
pub const PRIVATE_SYMBOL_NAME: v8::OneByteConst =
v8::String::create_external_onebyte_const(b"node:contextify:context");
/// An unbounded script that can be run in a context.
#[derive(Debug)]
pub struct ContextifyScript {
script: v8::Global<v8::UnboundScript>,
}
impl ContextifyScript {
pub fn new(
scope: &mut v8::HandleScope,
source_str: v8::Local<v8::String>,
) -> Result<Self, JsErrorBox> {
let resource_name = v8::undefined(scope);
let host_defined_options = create_host_defined_options(scope);
let origin = v8::ScriptOrigin::new(
scope,
resource_name.into(),
0,
0,
false,
0,
None,
false,
false,
false,
Some(host_defined_options),
);
let mut source =
v8::script_compiler::Source::new(source_str, Some(&origin));
let unbound_script = v8::script_compiler::compile_unbound_script(
scope,
&mut source,
v8::script_compiler::CompileOptions::NoCompileOptions,
v8::script_compiler::NoCacheReason::NoReason,
)
.ok_or_else(|| JsErrorBox::type_error("Failed to compile script"))?;
let script = v8::Global::new(scope, unbound_script);
Ok(Self { script })
}
// TODO(littledivy): Support `options`
pub fn eval_machine<'s>(
&self,
scope: &mut v8::HandleScope<'s>,
_context: v8::Local<v8::Context>,
) -> Option<v8::Local<'s, v8::Value>> {
let tc_scope = &mut v8::TryCatch::new(scope);
let unbound_script = v8::Local::new(tc_scope, self.script.clone());
let script = unbound_script.bind_to_current_context(tc_scope);
let result = script.run(tc_scope);
if tc_scope.has_caught() {
// If there was an exception thrown during script execution, re-throw it.
if !tc_scope.has_terminated() {
tc_scope.rethrow();
}
return None;
}
Some(result.unwrap())
}
}
pub struct ContextifyContext {
context: v8::TracedReference<v8::Context>,
sandbox: v8::TracedReference<v8::Object>,
}
unsafe impl deno_core::GarbageCollected for ContextifyContext {
fn trace(&self, visitor: &v8::cppgc::Visitor) {
visitor.trace(&self.context);
visitor.trace(&self.sandbox);
}
}
impl ContextifyContext {
pub fn attach(
scope: &mut v8::HandleScope,
sandbox_obj: v8::Local<v8::Object>,
) {
let tmp = init_global_template(scope, ContextInitMode::UseSnapshot);
let context = create_v8_context(scope, tmp, ContextInitMode::UseSnapshot);
Self::from_context(scope, context, sandbox_obj);
}
fn from_context(
scope: &mut v8::HandleScope,
v8_context: v8::Local<v8::Context>,
sandbox_obj: v8::Local<v8::Object>,
) {
let main_context = scope.get_current_context();
let context_state = main_context.get_aligned_pointer_from_embedder_data(
deno_core::CONTEXT_STATE_SLOT_INDEX,
);
let module_map = main_context
.get_aligned_pointer_from_embedder_data(deno_core::MODULE_MAP_SLOT_INDEX);
v8_context.set_security_token(main_context.get_security_token(scope));
// SAFETY: set embedder data from the creation context
unsafe {
v8_context.set_aligned_pointer_in_embedder_data(
deno_core::CONTEXT_STATE_SLOT_INDEX,
context_state,
);
v8_context.set_aligned_pointer_in_embedder_data(
deno_core::MODULE_MAP_SLOT_INDEX,
module_map,
);
}
let context = v8::TracedReference::new(scope, v8_context);
let sandbox = v8::TracedReference::new(scope, sandbox_obj);
let wrapper =
deno_core::cppgc::make_cppgc_object(scope, Self { context, sandbox });
let ptr =
deno_core::cppgc::try_unwrap_cppgc_object::<Self>(scope, wrapper.into());
// SAFETY: We are storing a pointer to the ContextifyContext
// in the embedder data of the v8::Context. The contextified wrapper
// lives longer than the execution context, so this should be safe.
unsafe {
v8_context.set_aligned_pointer_in_embedder_data(
3,
&*ptr.unwrap() as *const ContextifyContext as _,
);
}
let private_str =
v8::String::new_from_onebyte_const(scope, &PRIVATE_SYMBOL_NAME);
let private_symbol = v8::Private::for_api(scope, private_str);
sandbox_obj.set_private(scope, private_symbol, wrapper.into());
}
pub fn from_sandbox_obj<'a>(
scope: &mut v8::HandleScope<'a>,
sandbox_obj: v8::Local<v8::Object>,
) -> Option<&'a Self> {
let private_str =
v8::String::new_from_onebyte_const(scope, &PRIVATE_SYMBOL_NAME);
let private_symbol = v8::Private::for_api(scope, private_str);
sandbox_obj
.get_private(scope, private_symbol)
.and_then(|wrapper| {
deno_core::cppgc::try_unwrap_cppgc_object::<Self>(scope, wrapper)
// SAFETY: the lifetime of the scope does not actually bind to
// the lifetime of this reference at all, but the object we read
// it from does, so it will be alive at least that long.
.map(|r| unsafe { &*(&*r as *const _) })
})
}
pub fn is_contextify_context(
scope: &mut v8::HandleScope,
object: v8::Local<v8::Object>,
) -> bool {
Self::from_sandbox_obj(scope, object).is_some()
}
pub fn context<'a>(
&self,
scope: &mut v8::HandleScope<'a>,
) -> v8::Local<'a, v8::Context> {
self.context.get(scope).unwrap()
}
fn global_proxy<'s>(
&self,
scope: &mut v8::HandleScope<'s>,
) -> v8::Local<'s, v8::Object> {
let ctx = self.context(scope);
ctx.global(scope)
}
fn sandbox<'a>(
&self,
scope: &mut v8::HandleScope<'a>,
) -> v8::Local<'a, v8::Object> {
self.sandbox.get(scope).unwrap()
}
fn get<'a, 'c>(
scope: &mut v8::HandleScope<'a>,
object: v8::Local<'a, v8::Object>,
) -> Option<&'c ContextifyContext> {
let context = object.get_creation_context(scope)?;
let context_ptr = context.get_aligned_pointer_from_embedder_data(3);
if context_ptr.is_null() {
return None;
}
// SAFETY: We are storing a pointer to the ContextifyContext
// in the embedder data of the v8::Context during creation.
Some(unsafe { &*(context_ptr as *const ContextifyContext) })
}
}
pub const VM_CONTEXT_INDEX: usize = 0;
#[derive(PartialEq)]
pub enum ContextInitMode {
ForSnapshot,
UseSnapshot,
}
pub fn create_v8_context<'a>(
scope: &mut v8::HandleScope<'a, ()>,
object_template: v8::Local<v8::ObjectTemplate>,
mode: ContextInitMode,
) -> v8::Local<'a, v8::Context> {
let scope = &mut v8::EscapableHandleScope::new(scope);
let context = if mode == ContextInitMode::UseSnapshot {
v8::Context::from_snapshot(scope, VM_CONTEXT_INDEX, Default::default())
.unwrap()
} else {
let ctx = v8::Context::new(
scope,
v8::ContextOptions {
global_template: Some(object_template),
..Default::default()
},
);
// SAFETY: ContextifyContexts will update this to a pointer to the native object
unsafe {
ctx.set_aligned_pointer_in_embedder_data(1, std::ptr::null_mut());
ctx.set_aligned_pointer_in_embedder_data(2, std::ptr::null_mut());
ctx.set_aligned_pointer_in_embedder_data(3, std::ptr::null_mut());
ctx.clear_all_slots();
};
ctx
};
scope.escape(context)
}
#[derive(Debug, Clone)]
struct SlotContextifyGlobalTemplate(v8::Global<v8::ObjectTemplate>);
pub fn init_global_template<'a>(
scope: &mut v8::HandleScope<'a, ()>,
mode: ContextInitMode,
) -> v8::Local<'a, v8::ObjectTemplate> {
let maybe_object_template_slot =
scope.get_slot::<SlotContextifyGlobalTemplate>();
if maybe_object_template_slot.is_none() {
let global_object_template = init_global_template_inner(scope);
if mode == ContextInitMode::UseSnapshot {
let contextify_global_template_slot = SlotContextifyGlobalTemplate(
v8::Global::new(scope, global_object_template),
);
scope.set_slot(contextify_global_template_slot);
}
global_object_template
} else {
let object_template_slot = maybe_object_template_slot
.expect("ContextifyGlobalTemplate slot should be already populated.")
.clone();
v8::Local::new(scope, object_template_slot.0)
}
}
// Using thread_local! to get around compiler bug.
//
// See NOTE in ext/node/global.rs#L12
thread_local! {
pub static GETTER_MAP_FN: v8::NamedPropertyGetterCallback<'static> = property_getter.map_fn_to();
pub static SETTER_MAP_FN: v8::NamedPropertySetterCallback<'static> = property_setter.map_fn_to();
pub static DELETER_MAP_FN: v8::NamedPropertyDeleterCallback<'static> = property_deleter.map_fn_to();
pub static ENUMERATOR_MAP_FN: v8::NamedPropertyEnumeratorCallback<'static> = property_enumerator.map_fn_to();
pub static DEFINER_MAP_FN: v8::NamedPropertyDefinerCallback<'static> = property_definer.map_fn_to();
pub static DESCRIPTOR_MAP_FN: v8::NamedPropertyGetterCallback<'static> = property_descriptor.map_fn_to();
}
thread_local! {
pub static INDEXED_GETTER_MAP_FN: v8::IndexedPropertyGetterCallback<'static> = indexed_property_getter.map_fn_to();
pub static INDEXED_SETTER_MAP_FN: v8::IndexedPropertySetterCallback<'static> = indexed_property_setter.map_fn_to();
pub static INDEXED_DELETER_MAP_FN: v8::IndexedPropertyDeleterCallback<'static> = indexed_property_deleter.map_fn_to();
pub static INDEXED_DEFINER_MAP_FN: v8::IndexedPropertyDefinerCallback<'static> = indexed_property_definer.map_fn_to();
pub static INDEXED_DESCRIPTOR_MAP_FN: v8::IndexedPropertyGetterCallback<'static> = indexed_property_descriptor.map_fn_to();
}
pub fn init_global_template_inner<'a>(
scope: &mut v8::HandleScope<'a, ()>,
) -> v8::Local<'a, v8::ObjectTemplate> {
let global_object_template = v8::ObjectTemplate::new(scope);
global_object_template.set_internal_field_count(3);
let named_property_handler_config = {
let mut config = v8::NamedPropertyHandlerConfiguration::new()
.flags(v8::PropertyHandlerFlags::HAS_NO_SIDE_EFFECT);
config = GETTER_MAP_FN.with(|getter| config.getter_raw(*getter));
config = SETTER_MAP_FN.with(|setter| config.setter_raw(*setter));
config = DELETER_MAP_FN.with(|deleter| config.deleter_raw(*deleter));
config =
ENUMERATOR_MAP_FN.with(|enumerator| config.enumerator_raw(*enumerator));
config = DEFINER_MAP_FN.with(|definer| config.definer_raw(*definer));
config =
DESCRIPTOR_MAP_FN.with(|descriptor| config.descriptor_raw(*descriptor));
config
};
let indexed_property_handler_config = {
let mut config = v8::IndexedPropertyHandlerConfiguration::new()
.flags(v8::PropertyHandlerFlags::HAS_NO_SIDE_EFFECT);
config = INDEXED_GETTER_MAP_FN.with(|getter| config.getter_raw(*getter));
config = INDEXED_SETTER_MAP_FN.with(|setter| config.setter_raw(*setter));
config =
INDEXED_DELETER_MAP_FN.with(|deleter| config.deleter_raw(*deleter));
config =
ENUMERATOR_MAP_FN.with(|enumerator| config.enumerator_raw(*enumerator));
config =
INDEXED_DEFINER_MAP_FN.with(|definer| config.definer_raw(*definer));
config = INDEXED_DESCRIPTOR_MAP_FN
.with(|descriptor| config.descriptor_raw(*descriptor));
config
};
global_object_template
.set_named_property_handler(named_property_handler_config);
global_object_template
.set_indexed_property_handler(indexed_property_handler_config);
global_object_template
}
fn property_getter<'s>(
scope: &mut v8::HandleScope<'s>,
key: v8::Local<'s, v8::Name>,
args: v8::PropertyCallbackArguments<'s>,
mut ret: v8::ReturnValue,
) -> v8::Intercepted {
let Some(ctx) = ContextifyContext::get(scope, args.this()) else {
return v8::Intercepted::No;
};
let sandbox = ctx.sandbox(scope);
let tc_scope = &mut v8::TryCatch::new(scope);
let maybe_rv = sandbox.get_real_named_property(tc_scope, key).or_else(|| {
ctx
.global_proxy(tc_scope)
.get_real_named_property(tc_scope, key)
});
if let Some(mut rv) = maybe_rv {
if tc_scope.has_caught() && !tc_scope.has_terminated() {
tc_scope.rethrow();
}
if rv == sandbox {
rv = ctx.global_proxy(tc_scope).into();
}
ret.set(rv);
return v8::Intercepted::Yes;
}
v8::Intercepted::No
}
fn property_setter<'s>(
scope: &mut v8::HandleScope<'s>,
key: v8::Local<'s, v8::Name>,
value: v8::Local<'s, v8::Value>,
args: v8::PropertyCallbackArguments<'s>,
mut rv: v8::ReturnValue<()>,
) -> v8::Intercepted {
let Some(ctx) = ContextifyContext::get(scope, args.this()) else {
return v8::Intercepted::No;
};
let (attributes, is_declared_on_global_proxy) = match ctx
.global_proxy(scope)
.get_real_named_property_attributes(scope, key)
{
Some(attr) => (attr, true),
None => (v8::PropertyAttribute::NONE, false),
};
let mut read_only = attributes.is_read_only();
let (attributes, is_declared_on_sandbox) = match ctx
.sandbox(scope)
.get_real_named_property_attributes(scope, key)
{
Some(attr) => (attr, true),
None => (v8::PropertyAttribute::NONE, false),
};
read_only |= attributes.is_read_only();
if read_only {
return v8::Intercepted::No;
}
// true for x = 5
// false for this.x = 5
// false for Object.defineProperty(this, 'foo', ...)
// false for vmResult.x = 5 where vmResult = vm.runInContext();
let is_contextual_store = ctx.global_proxy(scope) != args.this();
// Indicator to not return before setting (undeclared) function declarations
// on the sandbox in strict mode, i.e. args.ShouldThrowOnError() = true.
// True for 'function f() {}', 'this.f = function() {}',
// 'var f = function()'.
// In effect only for 'function f() {}' because
// var f = function(), is_declared = true
// this.f = function() {}, is_contextual_store = false.
let is_function = value.is_function();
let is_declared = is_declared_on_global_proxy || is_declared_on_sandbox;
if !is_declared
&& args.should_throw_on_error()
&& is_contextual_store
&& !is_function
{
return v8::Intercepted::No;
}
if !is_declared && key.is_symbol() {
return v8::Intercepted::No;
};
if ctx.sandbox(scope).set(scope, key.into(), value).is_none() {
return v8::Intercepted::No;
}
if is_declared_on_sandbox {
if let Some(desc) =
ctx.sandbox(scope).get_own_property_descriptor(scope, key)
{
if !desc.is_undefined() {
let desc_obj: v8::Local<v8::Object> = desc.try_into().unwrap();
// We have to specify the return value for any contextual or get/set
// property
let get_key =
v8::String::new_external_onebyte_static(scope, b"get").unwrap();
let set_key =
v8::String::new_external_onebyte_static(scope, b"get").unwrap();
if desc_obj
.has_own_property(scope, get_key.into())
.unwrap_or(false)
|| desc_obj
.has_own_property(scope, set_key.into())
.unwrap_or(false)
{
rv.set_bool(true);
return v8::Intercepted::Yes;
}
}
}
}
v8::Intercepted::No
}
fn property_deleter<'s>(
scope: &mut v8::HandleScope<'s>,
key: v8::Local<'s, v8::Name>,
args: v8::PropertyCallbackArguments<'s>,
mut rv: v8::ReturnValue<v8::Boolean>,
) -> v8::Intercepted {
let Some(ctx) = ContextifyContext::get(scope, args.this()) else {
return v8::Intercepted::No;
};
let context = ctx.context(scope);
let sandbox = ctx.sandbox(scope);
let context_scope = &mut v8::ContextScope::new(scope, context);
if !sandbox.delete(context_scope, key.into()).unwrap_or(false) {
return v8::Intercepted::No;
}
rv.set_bool(false);
v8::Intercepted::Yes
}
fn property_enumerator<'s>(
scope: &mut v8::HandleScope<'s>,
args: v8::PropertyCallbackArguments<'s>,
mut rv: v8::ReturnValue<v8::Array>,
) {
let Some(ctx) = ContextifyContext::get(scope, args.this()) else {
return;
};
let context = ctx.context(scope);
let sandbox = ctx.sandbox(scope);
let context_scope = &mut v8::ContextScope::new(scope, context);
let Some(properties) = sandbox
.get_property_names(context_scope, v8::GetPropertyNamesArgs::default())
else {
return;
};
rv.set(properties);
}
fn property_definer<'s>(
scope: &mut v8::HandleScope<'s>,
key: v8::Local<'s, v8::Name>,
desc: &v8::PropertyDescriptor,
args: v8::PropertyCallbackArguments<'s>,
_: v8::ReturnValue<()>,
) -> v8::Intercepted {
let Some(ctx) = ContextifyContext::get(scope, args.this()) else {
return v8::Intercepted::No;
};
let context = ctx.context(scope);
let (attributes, is_declared) = match ctx
.global_proxy(scope)
.get_real_named_property_attributes(scope, key)
{
Some(attr) => (attr, true),
None => (v8::PropertyAttribute::NONE, false),
};
let read_only = attributes.is_read_only();
let dont_delete = attributes.is_dont_delete();
// If the property is set on the global as read_only, don't change it on
// the global or sandbox.
if is_declared && read_only && dont_delete {
return v8::Intercepted::No;
}
let sandbox = ctx.sandbox(scope);
let scope = &mut v8::ContextScope::new(scope, context);
let define_prop_on_sandbox =
|scope: &mut v8::HandleScope,
desc_for_sandbox: &mut v8::PropertyDescriptor| {
if desc.has_enumerable() {
desc_for_sandbox.set_enumerable(desc.enumerable());
}
if desc.has_configurable() {
desc_for_sandbox.set_configurable(desc.configurable());
}
sandbox.define_property(scope, key, desc_for_sandbox);
};
if desc.has_get() || desc.has_set() {
let mut desc_for_sandbox = v8::PropertyDescriptor::new_from_get_set(
if desc.has_get() {
desc.get()
} else {
v8::undefined(scope).into()
},
if desc.has_set() {
desc.set()
} else {
v8::undefined(scope).into()
},
);
define_prop_on_sandbox(scope, &mut desc_for_sandbox);
} else {
let value = if desc.has_value() {
desc.value()
} else {
v8::undefined(scope).into()
};
if desc.has_writable() {
let mut desc_for_sandbox =
v8::PropertyDescriptor::new_from_value_writable(value, desc.writable());
define_prop_on_sandbox(scope, &mut desc_for_sandbox);
} else {
let mut desc_for_sandbox = v8::PropertyDescriptor::new_from_value(value);
define_prop_on_sandbox(scope, &mut desc_for_sandbox);
}
}
v8::Intercepted::Yes
}
fn property_descriptor<'s>(
scope: &mut v8::HandleScope<'s>,
key: v8::Local<'s, v8::Name>,
args: v8::PropertyCallbackArguments<'s>,
mut rv: v8::ReturnValue,
) -> v8::Intercepted {
let Some(ctx) = ContextifyContext::get(scope, args.this()) else {
return v8::Intercepted::No;
};
let context = ctx.context(scope);
let sandbox = ctx.sandbox(scope);
let scope = &mut v8::ContextScope::new(scope, context);
if sandbox.has_own_property(scope, key).unwrap_or(false) {
if let Some(desc) = sandbox.get_own_property_descriptor(scope, key) {
rv.set(desc);
return v8::Intercepted::Yes;
}
}
v8::Intercepted::No
}
fn uint32_to_name<'s>(
scope: &mut v8::HandleScope<'s>,
index: u32,
) -> v8::Local<'s, v8::Name> {
let int = v8::Integer::new_from_unsigned(scope, index);
let u32 = v8::Local::<v8::Uint32>::try_from(int).unwrap();
u32.to_string(scope).unwrap().into()
}
fn indexed_property_getter<'s>(
scope: &mut v8::HandleScope<'s>,
index: u32,
args: v8::PropertyCallbackArguments<'s>,
rv: v8::ReturnValue,
) -> v8::Intercepted {
let key = uint32_to_name(scope, index);
property_getter(scope, key, args, rv)
}
fn indexed_property_setter<'s>(
scope: &mut v8::HandleScope<'s>,
index: u32,
value: v8::Local<'s, v8::Value>,
args: v8::PropertyCallbackArguments<'s>,
rv: v8::ReturnValue<()>,
) -> v8::Intercepted {
let key = uint32_to_name(scope, index);
property_setter(scope, key, value, args, rv)
}
fn indexed_property_deleter<'s>(
scope: &mut v8::HandleScope<'s>,
index: u32,
args: v8::PropertyCallbackArguments<'s>,
mut rv: v8::ReturnValue<v8::Boolean>,
) -> v8::Intercepted {
let Some(ctx) = ContextifyContext::get(scope, args.this()) else {
return v8::Intercepted::No;
};
let context = ctx.context(scope);
let sandbox = ctx.sandbox(scope);
let context_scope = &mut v8::ContextScope::new(scope, context);
if !sandbox.delete_index(context_scope, index).unwrap_or(false) {
return v8::Intercepted::No;
}
// Delete failed on the sandbox, intercept and do not delete on
// the global object.
rv.set_bool(false);
v8::Intercepted::No
}
fn indexed_property_definer<'s>(
scope: &mut v8::HandleScope<'s>,
index: u32,
descriptor: &v8::PropertyDescriptor,
args: v8::PropertyCallbackArguments<'s>,
rv: v8::ReturnValue<()>,
) -> v8::Intercepted {
let key = uint32_to_name(scope, index);
property_definer(scope, key, descriptor, args, rv)
}
fn indexed_property_descriptor<'s>(
scope: &mut v8::HandleScope<'s>,
index: u32,
args: v8::PropertyCallbackArguments<'s>,
rv: v8::ReturnValue,
) -> v8::Intercepted {
let key = uint32_to_name(scope, index);
property_descriptor(scope, key, args, rv)
}

View file

@ -273,7 +273,7 @@ impl ZlibInner {
fn check_error(
error_info: Option<(i32, String)>,
scope: &mut v8::HandleScope,
scope: &mut v8::PinScope<'_, '_>,
this: &v8::Global<v8::Object>,
) -> bool {
let Some((err, msg)) = error_info else {
@ -413,7 +413,7 @@ impl Zlib {
pub fn write_sync(
&self,
#[this] this: v8::Global<v8::Object>,
scope: &mut v8::HandleScope,
scope: &mut v8::PinScope<'_, '_>,
#[smi] flush: i32,
#[buffer] input: &[u8],
#[smi] in_off: u32,
@ -448,7 +448,7 @@ impl Zlib {
fn write(
&self,
#[this] this: v8::Global<v8::Object>,
scope: &mut v8::HandleScope,
scope: &mut v8::PinScope<'_, '_>,
#[smi] flush: i32,
#[buffer] input: &[u8],
#[smi] in_off: u32,
@ -633,7 +633,7 @@ impl BrotliEncoder {
pub fn write(
&self,
#[this] this: v8::Global<v8::Object>,
scope: &mut v8::HandleScope,
scope: &mut v8::PinScope<'_, '_>,
#[smi] flush: u8,
#[buffer] input: &[u8],
#[smi] in_off: u32,
@ -810,7 +810,7 @@ impl BrotliDecoder {
pub fn write(
&self,
#[this] this: v8::Global<v8::Object>,
scope: &mut v8::HandleScope,
scope: &mut v8::PinScope<'_, '_>,
#[smi] _flush: i32,
#[buffer] input: &[u8],
#[smi] in_off: u32,

View file

@ -151,7 +151,7 @@ fn dt_change_notif(isolate: &mut v8::Isolate, key: &str) {
#[op2(fast, stack_trace)]
fn op_set_env(
state: &mut OpState,
scope: &mut v8::HandleScope,
scope: &mut v8::PinScope<'_, '_>,
#[string] key: &str,
#[string] value: &str,
) -> Result<(), OsError> {
@ -520,7 +520,7 @@ fn get_cpu_usage() -> (std::time::Duration, std::time::Duration) {
#[op2(fast)]
fn op_runtime_memory_usage(
scope: &mut v8::HandleScope,
scope: &mut v8::PinScope<'_, '_>,
#[buffer] out: &mut [f64],
) {
let s = scope.get_heap_statistics();

View file

@ -1142,7 +1142,7 @@ impl DenoIdGenerator {
}
fn parse_trace_id(
scope: &mut v8::HandleScope<'_>,
scope: &mut v8::PinScope<'_, '_>,
trace_id: v8::Local<'_, v8::Value>,
) -> TraceId {
if let Ok(string) = trace_id.try_cast() {
@ -1171,7 +1171,7 @@ fn parse_trace_id(
}
fn parse_span_id(
scope: &mut v8::HandleScope<'_>,
scope: &mut v8::PinScope<'_, '_>,
span_id: v8::Local<'_, v8::Value>,
) -> SpanId {
if let Ok(string) = span_id.try_cast() {
@ -1260,7 +1260,7 @@ macro_rules! attr {
#[op2(fast)]
fn op_otel_log<'s>(
scope: &mut v8::HandleScope<'s>,
scope: &mut v8::PinScope<'s, '_>,
message: v8::Local<'s, v8::Value>,
#[smi] level: i32,
span: v8::Local<'s, v8::Value>,
@ -1320,7 +1320,7 @@ fn op_otel_log<'s>(
#[op2(fast)]
fn op_otel_log_foreign(
scope: &mut v8::HandleScope<'_>,
scope: &mut v8::PinScope<'_, '_>,
#[string] message: String,
#[smi] level: i32,
trace_id: v8::Local<'_, v8::Value>,
@ -1389,7 +1389,7 @@ pub fn report_event(name: &'static str, data: impl std::fmt::Display) {
}
fn owned_string<'s>(
scope: &mut v8::HandleScope<'s>,
scope: &mut v8::PinScope<'s, '_>,
string: v8::Local<'s, v8::String>,
) -> String {
let x = v8::ValueView::new(scope, string);
@ -1445,7 +1445,7 @@ impl OtelTracer {
#[cppgc]
fn start_span<'s>(
&self,
scope: &mut v8::HandleScope<'s>,
scope: &mut v8::PinScope<'s, '_>,
#[cppgc] parent: Option<&OtelSpan>,
name: v8::Local<'s, v8::Value>,
#[smi] span_kind: u8,
@ -1525,7 +1525,7 @@ impl OtelTracer {
#[cppgc]
fn start_span_foreign<'s>(
&self,
scope: &mut v8::HandleScope<'s>,
scope: &mut v8::PinScope<'s, '_>,
parent_trace_id: v8::Local<'s, v8::Value>,
parent_span_id: v8::Local<'s, v8::Value>,
name: v8::Local<'s, v8::Value>,
@ -1754,7 +1754,7 @@ fn span_attributes(
#[op2(fast)]
fn op_otel_span_attribute1<'s>(
scope: &mut v8::HandleScope<'s>,
scope: &mut v8::PinScope<'s, '_>,
span: v8::Local<'_, v8::Value>,
#[smi] location: u32,
key: v8::Local<'s, v8::Value>,
@ -1778,7 +1778,7 @@ fn op_otel_span_attribute1<'s>(
#[op2(fast)]
fn op_otel_span_attribute2<'s>(
scope: &mut v8::HandleScope<'s>,
scope: &mut v8::PinScope<'s, '_>,
span: v8::Local<'_, v8::Value>,
#[smi] location: u32,
key1: v8::Local<'s, v8::Value>,
@ -1806,7 +1806,7 @@ fn op_otel_span_attribute2<'s>(
#[allow(clippy::too_many_arguments)]
#[op2(fast)]
fn op_otel_span_attribute3<'s>(
scope: &mut v8::HandleScope<'s>,
scope: &mut v8::PinScope<'s, '_>,
span: v8::Local<'_, v8::Value>,
#[smi] location: u32,
key1: v8::Local<'s, v8::Value>,
@ -1836,7 +1836,7 @@ fn op_otel_span_attribute3<'s>(
#[op2(fast)]
fn op_otel_span_update_name<'s>(
scope: &mut v8::HandleScope<'s>,
scope: &mut v8::PinScope<'s, '_>,
span: v8::Local<'s, v8::Value>,
name: v8::Local<'s, v8::Value>,
) {
@ -1857,7 +1857,7 @@ fn op_otel_span_update_name<'s>(
#[op2(fast)]
fn op_otel_span_add_link<'s>(
scope: &mut v8::HandleScope<'s>,
scope: &mut v8::PinScope<'s, '_>,
span: v8::Local<'s, v8::Value>,
trace_id: v8::Local<'s, v8::Value>,
span_id: v8::Local<'s, v8::Value>,
@ -1936,7 +1936,7 @@ impl OtelMeter {
#[cppgc]
fn create_counter<'s>(
&self,
scope: &mut v8::HandleScope<'s>,
scope: &mut v8::PinScope<'s, '_>,
name: v8::Local<'s, v8::Value>,
description: v8::Local<'s, v8::Value>,
unit: v8::Local<'s, v8::Value>,
@ -1955,7 +1955,7 @@ impl OtelMeter {
#[cppgc]
fn create_up_down_counter<'s>(
&self,
scope: &mut v8::HandleScope<'s>,
scope: &mut v8::PinScope<'s, '_>,
name: v8::Local<'s, v8::Value>,
description: v8::Local<'s, v8::Value>,
unit: v8::Local<'s, v8::Value>,
@ -1974,7 +1974,7 @@ impl OtelMeter {
#[cppgc]
fn create_gauge<'s>(
&self,
scope: &mut v8::HandleScope<'s>,
scope: &mut v8::PinScope<'s, '_>,
name: v8::Local<'s, v8::Value>,
description: v8::Local<'s, v8::Value>,
unit: v8::Local<'s, v8::Value>,
@ -1993,7 +1993,7 @@ impl OtelMeter {
#[cppgc]
fn create_histogram<'s>(
&self,
scope: &mut v8::HandleScope<'s>,
scope: &mut v8::PinScope<'s, '_>,
name: v8::Local<'s, v8::Value>,
description: v8::Local<'s, v8::Value>,
unit: v8::Local<'s, v8::Value>,
@ -2034,7 +2034,7 @@ impl OtelMeter {
#[cppgc]
fn create_observable_counter<'s>(
&self,
scope: &mut v8::HandleScope<'s>,
scope: &mut v8::PinScope<'s, '_>,
name: v8::Local<'s, v8::Value>,
description: v8::Local<'s, v8::Value>,
unit: v8::Local<'s, v8::Value>,
@ -2055,7 +2055,7 @@ impl OtelMeter {
#[cppgc]
fn create_observable_up_down_counter<'s>(
&self,
scope: &mut v8::HandleScope<'s>,
scope: &mut v8::PinScope<'s, '_>,
name: v8::Local<'s, v8::Value>,
description: v8::Local<'s, v8::Value>,
unit: v8::Local<'s, v8::Value>,
@ -2076,7 +2076,7 @@ impl OtelMeter {
#[cppgc]
fn create_observable_gauge<'s>(
&self,
scope: &mut v8::HandleScope<'s>,
scope: &mut v8::PinScope<'s, '_>,
name: v8::Local<'s, v8::Value>,
description: v8::Local<'s, v8::Value>,
unit: v8::Local<'s, v8::Value>,
@ -2115,7 +2115,7 @@ unsafe impl GarbageCollected for Instrument {
fn create_instrument<'a, 'b, T>(
cb: impl FnOnce(String) -> InstrumentBuilder<'b, T>,
cb2: impl FnOnce(InstrumentBuilder<'b, T>) -> Instrument,
scope: &mut v8::HandleScope<'a>,
scope: &mut v8::PinScope<'a, '_>,
name: v8::Local<'a, v8::Value>,
description: v8::Local<'a, v8::Value>,
unit: v8::Local<'a, v8::Value>,
@ -2137,7 +2137,7 @@ fn create_instrument<'a, 'b, T>(
fn create_async_instrument<'a, 'b, T>(
cb: impl FnOnce(String) -> AsyncInstrumentBuilder<'b, T, f64>,
cb2: impl FnOnce(AsyncInstrumentBuilder<'b, T, f64>),
scope: &mut v8::HandleScope<'a>,
scope: &mut v8::PinScope<'a, '_>,
name: v8::Local<'a, v8::Value>,
description: v8::Local<'a, v8::Value>,
unit: v8::Local<'a, v8::Value>,
@ -2196,7 +2196,7 @@ fn op_otel_metric_record0(
#[op2(fast)]
fn op_otel_metric_record1(
state: &mut OpState,
scope: &mut v8::HandleScope<'_>,
scope: &mut v8::PinScope<'_, '_>,
instrument: v8::Local<'_, v8::Value>,
value: f64,
key1: v8::Local<'_, v8::Value>,
@ -2236,7 +2236,7 @@ fn op_otel_metric_record1(
#[op2(fast)]
fn op_otel_metric_record2(
state: &mut OpState,
scope: &mut v8::HandleScope<'_>,
scope: &mut v8::PinScope<'_, '_>,
instrument: v8::Local<'_, v8::Value>,
value: f64,
key1: v8::Local<'_, v8::Value>,
@ -2284,7 +2284,7 @@ fn op_otel_metric_record2(
#[op2(fast)]
fn op_otel_metric_record3(
state: &mut OpState,
scope: &mut v8::HandleScope<'_>,
scope: &mut v8::PinScope<'_, '_>,
instrument: v8::Local<'_, v8::Value>,
value: f64,
key1: v8::Local<'_, v8::Value>,
@ -2355,7 +2355,7 @@ fn op_otel_metric_observable_record0(
#[op2(fast)]
fn op_otel_metric_observable_record1(
state: &mut OpState,
scope: &mut v8::HandleScope<'_>,
scope: &mut v8::PinScope<'_, '_>,
instrument: v8::Local<'_, v8::Value>,
value: f64,
key1: v8::Local<'_, v8::Value>,
@ -2388,7 +2388,7 @@ fn op_otel_metric_observable_record1(
#[op2(fast)]
fn op_otel_metric_observable_record2(
state: &mut OpState,
scope: &mut v8::HandleScope<'_>,
scope: &mut v8::PinScope<'_, '_>,
instrument: v8::Local<'_, v8::Value>,
value: f64,
key1: v8::Local<'_, v8::Value>,
@ -2427,7 +2427,7 @@ fn op_otel_metric_observable_record2(
#[op2(fast)]
fn op_otel_metric_observable_record3(
state: &mut OpState,
scope: &mut v8::HandleScope<'_>,
scope: &mut v8::PinScope<'_, '_>,
instrument: v8::Local<'_, v8::Value>,
value: f64,
key1: v8::Local<'_, v8::Value>,
@ -2471,7 +2471,7 @@ fn op_otel_metric_observable_record3(
#[allow(clippy::too_many_arguments)]
#[op2(fast)]
fn op_otel_metric_attribute3<'s>(
scope: &mut v8::HandleScope<'s>,
scope: &mut v8::PinScope<'s, '_>,
state: &mut OpState,
#[smi] capacity: u32,
key1: v8::Local<'s, v8::Value>,
@ -2549,25 +2549,27 @@ struct GcMetricData(RefCell<GcMetricDataInner>);
impl GcMetricData {
extern "C" fn prologue_callback(
isolate: *mut v8::Isolate,
isolate: v8::UnsafeRawIsolatePtr,
_gc_type: v8::GCType,
_flags: v8::GCCallbackFlags,
_data: *mut c_void,
) {
// SAFETY: Isolate is valid during callback
let isolate = unsafe { &mut *isolate };
let isolate =
unsafe { v8::Isolate::from_raw_isolate_ptr_unchecked(isolate) };
let this = isolate.get_slot::<Self>().unwrap();
this.0.borrow_mut().start = Instant::now();
}
extern "C" fn epilogue_callback(
isolate: *mut v8::Isolate,
isolate: v8::UnsafeRawIsolatePtr,
gc_type: v8::GCType,
_flags: v8::GCCallbackFlags,
_data: *mut c_void,
) {
// SAFETY: Isolate is valid during callback
let isolate = unsafe { &mut *isolate };
let isolate =
unsafe { v8::Isolate::from_raw_isolate_ptr_unchecked(isolate) };
let this = isolate.get_slot::<Self>().unwrap();
let this = this.0.borrow_mut();
@ -2599,7 +2601,7 @@ struct HeapMetricData {
}
#[op2(fast)]
fn op_otel_enable_isolate_metrics(scope: &mut v8::HandleScope) {
fn op_otel_enable_isolate_metrics(scope: &mut v8::PinScope<'_, '_>) {
if scope.get_slot::<GcMetricData>().is_some() {
return;
}
@ -2661,7 +2663,7 @@ fn op_otel_enable_isolate_metrics(scope: &mut v8::HandleScope) {
}
#[op2(fast)]
fn op_otel_collect_isolate_metrics(scope: &mut v8::HandleScope) {
fn op_otel_collect_isolate_metrics(scope: &mut v8::PinScope<'_, '_>) {
let data = scope.get_slot::<HeapMetricData>().unwrap().clone();
for i in 0..scope.get_number_of_data_slots() {
let Some(space) = scope.get_heap_space_statistics(i as _) else {

View file

@ -208,7 +208,7 @@ fn op_encoding_normalize_label(
#[op2]
fn op_encoding_decode_utf8<'a>(
scope: &mut v8::HandleScope<'a>,
scope: &mut v8::PinScope<'a, '_>,
#[anybuffer] zero_copy: &[u8],
ignore_bom: bool,
) -> Result<v8::Local<'a, v8::String>, WebError> {
@ -365,7 +365,7 @@ unsafe impl deno_core::GarbageCollected for TextDecoderResource {
#[op2(fast(op_encoding_encode_into_fast))]
#[allow(deprecated)]
fn op_encoding_encode_into(
scope: &mut v8::HandleScope,
scope: &mut v8::PinScope<'_, '_>,
input: v8::Local<v8::Value>,
#[buffer] buffer: &mut [u8],
#[buffer] out_buf: &mut [u32],

View file

@ -80,7 +80,7 @@ impl GPUAdapter {
#[getter]
#[global]
fn info(&self, scope: &mut v8::HandleScope) -> v8::Global<v8::Object> {
fn info(&self, scope: &mut v8::PinScope<'_, '_>) -> v8::Global<v8::Object> {
self.info.get(scope, |_| {
let info = self.instance.adapter_get_info(self.id);
let limits = self.instance.adapter_limits(self.id);
@ -95,7 +95,10 @@ impl GPUAdapter {
#[getter]
#[global]
fn features(&self, scope: &mut v8::HandleScope) -> v8::Global<v8::Object> {
fn features(
&self,
scope: &mut v8::PinScope<'_, '_>,
) -> v8::Global<v8::Object> {
self.features.get(scope, |scope| {
let features = self.instance.adapter_features(self.id);
let features = features_to_feature_names(features);
@ -105,7 +108,7 @@ impl GPUAdapter {
#[getter]
#[global]
fn limits(&self, scope: &mut v8::HandleScope) -> v8::Global<v8::Object> {
fn limits(&self, scope: &mut v8::PinScope<'_, '_>) -> v8::Global<v8::Object> {
self.limits.get(scope, |_| {
let adapter_limits = self.instance.adapter_limits(self.id);
GPUSupportedLimits(adapter_limits)
@ -117,8 +120,8 @@ impl GPUAdapter {
fn request_device(
&self,
state: &mut OpState,
isolate_ptr: *mut v8::Isolate,
scope: &mut v8::HandleScope,
isolate: &v8::Isolate,
scope: &mut v8::PinScope<'_, '_>,
#[webidl] descriptor: GPUDeviceDescriptor,
) -> Result<v8::Global<v8::Value>, CreateDeviceError> {
let features = self.instance.adapter_features(self.id);
@ -202,6 +205,9 @@ impl GPUAdapter {
let context = v8::Global::new(scope, context);
let task_device = device.clone();
// SAFETY: just grabbing the raw pointer
let isolate_ptr = unsafe { isolate.as_raw_isolate_ptr() };
deno_unsync::spawn(async move {
loop {
// TODO(@crowlKats): check for uncaptured_receiver.is_closed instead once tokio is upgraded
@ -216,8 +222,9 @@ impl GPUAdapter {
};
// SAFETY: eh, it's safe
let isolate: &mut v8::Isolate = unsafe { &mut *isolate_ptr };
let scope = &mut v8::HandleScope::with_context(isolate, &context);
let mut isolate =
unsafe { v8::Isolate::from_raw_isolate_ptr_unchecked(isolate_ptr) };
v8::scope_with_context!(scope, &mut isolate, &context);
let error = deno_core::error::to_v8_error(scope, &error);
let error_event_class =
@ -439,7 +446,7 @@ unsafe impl GarbageCollected for GPUSupportedFeatures {
impl GPUSupportedFeatures {
pub fn new(
scope: &mut v8::HandleScope,
scope: &mut v8::PinScope<'_, '_>,
features: HashSet<GPUFeatureName>,
) -> Self {
let set = v8::Set::new(scope);

View file

@ -6,8 +6,8 @@ use deno_core::GarbageCollected;
use deno_core::WebIDL;
use deno_core::cppgc::Ref;
use deno_core::op2;
use deno_core::v8::HandleScope;
use deno_core::v8::Local;
use deno_core::v8::PinScope;
use deno_core::v8::Value;
use deno_core::webidl::ContextFn;
use deno_core::webidl::WebIdlConverter;
@ -104,7 +104,7 @@ impl<'a> WebIdlConverter<'a> for GPUBindingResource {
type Options = ();
fn convert<'b>(
scope: &mut HandleScope<'a>,
scope: &mut PinScope<'a, '_>,
value: Local<'a, Value>,
prefix: Cow<'static, str>,
context: ContextFn<'b>,

View file

@ -202,7 +202,7 @@ impl GPUBuffer {
fn get_mapped_range<'s>(
&self,
scope: &mut v8::HandleScope<'s>,
scope: &mut v8::PinScope<'s, '_>,
#[webidl(default = 0)] offset: u64,
#[webidl] size: Option<u64>,
) -> Result<v8::Local<'s, v8::ArrayBuffer>, BufferError> {
@ -253,7 +253,7 @@ impl GPUBuffer {
}
#[nofast]
fn unmap(&self, scope: &mut v8::HandleScope) -> Result<(), BufferError> {
fn unmap(&self, scope: &mut v8::PinScope<'_, '_>) -> Result<(), BufferError> {
for ab in self.mapped_js_buffers.replace(vec![]) {
let ab = ab.open(scope);
ab.detach(None);

View file

@ -156,7 +156,7 @@ impl UnsafeWindowSurface {
fn get_context(
&self,
#[this] this: v8::Global<v8::Object>,
scope: &mut v8::HandleScope,
scope: &mut v8::PinScope<'_, '_>,
) -> v8::Global<v8::Object> {
self.context.get(scope, |_| GPUCanvasContext {
surface_id: self.id,
@ -169,7 +169,10 @@ impl UnsafeWindowSurface {
}
#[nofast]
fn present(&self, scope: &mut v8::HandleScope) -> Result<(), JsErrorBox> {
fn present(
&self,
scope: &mut v8::PinScope<'_, '_>,
) -> Result<(), JsErrorBox> {
let Some(context) = self.context.try_unwrap(scope) else {
return Err(JsErrorBox::type_error("getContext was never called"));
};
@ -178,7 +181,7 @@ impl UnsafeWindowSurface {
}
#[fast]
fn resize(&self, width: u32, height: u32, scope: &mut v8::HandleScope) {
fn resize(&self, width: u32, height: u32, scope: &mut v8::PinScope<'_, '_>) {
self.width.replace(width);
self.height.replace(height);
@ -210,7 +213,7 @@ impl<'a> FromV8<'a> for UnsafeWindowSurfaceOptions {
type Error = JsErrorBox;
fn from_v8(
scope: &mut v8::HandleScope<'a>,
scope: &mut v8::PinScope<'a, '_>,
value: Local<'a, Value>,
) -> Result<Self, Self::Error> {
let obj = value

View file

@ -146,7 +146,7 @@ impl GPUComputePassEncoder {
fn set_bind_group<'a>(
&self,
scope: &mut v8::HandleScope<'a>,
scope: &mut v8::PinScope<'a, '_>,
#[webidl(options(enforce_range = true))] index: u32,
#[webidl] bind_group: Nullable<Ref<crate::bind_group::GPUBindGroup>>,
dynamic_offsets: v8::Local<'a, v8::Value>,

View file

@ -96,7 +96,10 @@ impl GPUDevice {
#[getter]
#[global]
fn features(&self, scope: &mut v8::HandleScope) -> v8::Global<v8::Object> {
fn features(
&self,
scope: &mut v8::PinScope<'_, '_>,
) -> v8::Global<v8::Object> {
self.features.get(scope, |scope| {
let features = self.instance.device_features(self.id);
let features = features_to_feature_names(features);
@ -106,7 +109,7 @@ impl GPUDevice {
#[getter]
#[global]
fn limits(&self, scope: &mut v8::HandleScope) -> v8::Global<v8::Object> {
fn limits(&self, scope: &mut v8::PinScope<'_, '_>) -> v8::Global<v8::Object> {
self.limits.get(scope, |_| {
let limits = self.instance.device_limits(self.id);
GPUSupportedLimits(limits)
@ -117,7 +120,7 @@ impl GPUDevice {
#[global]
fn adapter_info(
&self,
scope: &mut v8::HandleScope,
scope: &mut v8::PinScope<'_, '_>,
) -> v8::Global<v8::Object> {
self.adapter_info.get(scope, |_| {
let info = self.instance.adapter_get_info(self.adapter);
@ -133,7 +136,7 @@ impl GPUDevice {
#[getter]
#[global]
fn queue(&self, scope: &mut v8::HandleScope) -> v8::Global<v8::Object> {
fn queue(&self, scope: &mut v8::PinScope<'_, '_>) -> v8::Global<v8::Object> {
self.queue_obj.get(scope, |_| GPUQueue {
id: self.queue,
error_handler: self.error_handler.clone(),
@ -631,7 +634,7 @@ impl GPUDevice {
#[global]
fn pop_error_scope(
&self,
scope: &mut v8::HandleScope,
scope: &mut v8::PinScope<'_, '_>,
) -> Result<v8::Global<v8::Value>, JsErrorBox> {
if self.error_handler.is_lost.get().is_some() {
let val = v8::null(scope).cast::<v8::Value>();

View file

@ -107,7 +107,7 @@ deno_core::extension!(
#[cppgc]
pub fn op_create_gpu(
state: &mut OpState,
scope: &mut v8::HandleScope,
scope: &mut v8::PinScope<'_, '_>,
webidl_brand: v8::Local<v8::Value>,
set_event_target_data: v8::Local<v8::Value>,
error_event_class: v8::Local<v8::Value>,
@ -237,11 +237,11 @@ impl<T: GarbageCollected + 'static> SameObject<T> {
pub fn get<F>(
&self,
scope: &mut v8::HandleScope,
scope: &mut v8::PinScope<'_, '_>,
f: F,
) -> v8::Global<v8::Object>
where
F: FnOnce(&mut v8::HandleScope) -> T,
F: FnOnce(&mut v8::PinScope<'_, '_>) -> T,
{
self
.cell
@ -256,7 +256,7 @@ impl<T: GarbageCollected + 'static> SameObject<T> {
#[allow(unused)]
pub fn set(
&self,
scope: &mut v8::HandleScope,
scope: &mut v8::PinScope<'_, '_>,
value: T,
) -> Result<(), v8::Global<v8::Object>> {
let obj = deno_core::cppgc::make_cppgc_object(scope, value);
@ -265,7 +265,7 @@ impl<T: GarbageCollected + 'static> SameObject<T> {
pub fn try_unwrap(
&self,
scope: &mut v8::HandleScope,
scope: &mut v8::PinScope<'_, '_>,
) -> Option<deno_core::cppgc::UnsafePtr<T>> {
let obj = self.cell.get()?;
let val = v8::Local::new(scope, obj);

View file

@ -137,7 +137,7 @@ impl GPURenderBundleEncoder {
fn set_bind_group<'a>(
&self,
scope: &mut v8::HandleScope<'a>,
scope: &mut v8::PinScope<'a, '_>,
#[webidl(options(enforce_range = true))] index: u32,
#[webidl] bind_group: Nullable<Ref<crate::bind_group::GPUBindGroup>>,
dynamic_offsets: v8::Local<'a, v8::Value>,

View file

@ -212,7 +212,7 @@ impl GPURenderPassEncoder {
fn set_bind_group<'a>(
&self,
scope: &mut v8::HandleScope<'a>,
scope: &mut v8::PinScope<'a, '_>,
#[webidl(options(enforce_range = true))] index: u32,
#[webidl] bind_group: Nullable<Ref<crate::bind_group::GPUBindGroup>>,
dynamic_offsets: v8::Local<'a, v8::Value>,

View file

@ -142,7 +142,7 @@ impl GPUCanvasContext {
fn get_current_texture<'s>(
&self,
scope: &mut v8::HandleScope<'s>,
scope: &mut v8::PinScope<'s, '_>,
) -> Result<v8::Local<'s, v8::Object>, SurfaceError> {
let config = self.config.borrow();
let Some(config) = config.as_ref() else {
@ -195,7 +195,7 @@ impl GPUCanvasContext {
impl GPUCanvasContext {
pub fn present(
&self,
scope: &mut v8::HandleScope,
scope: &mut v8::PinScope<'_, '_>,
) -> Result<(), SurfaceError> {
let config = self.config.borrow();
let Some(config) = config.as_ref() else {

View file

@ -35,7 +35,7 @@ impl<'a> WebIdlConverter<'a> for GPUExtent3D {
type Options = ();
fn convert<'b>(
scope: &mut v8::HandleScope<'a>,
scope: &mut v8::PinScope<'a, '_>,
value: v8::Local<'a, v8::Value>,
prefix: Cow<'static, str>,
context: ContextFn<'b>,
@ -145,7 +145,7 @@ impl<'a> WebIdlConverter<'a> for GPUOrigin3D {
type Options = ();
fn convert<'b>(
scope: &mut v8::HandleScope<'a>,
scope: &mut v8::PinScope<'a, '_>,
value: v8::Local<'a, v8::Value>,
prefix: Cow<'static, str>,
context: ContextFn<'b>,
@ -240,7 +240,7 @@ impl<'a> WebIdlConverter<'a> for GPUColor {
type Options = ();
fn convert<'b>(
scope: &mut v8::HandleScope<'a>,
scope: &mut v8::PinScope<'a, '_>,
value: v8::Local<'a, v8::Value>,
prefix: Cow<'static, str>,
context: ContextFn<'b>,
@ -346,7 +346,7 @@ impl<'a> WebIdlConverter<'a> for GPUPipelineLayoutOrGPUAutoLayoutMode {
type Options = ();
fn convert<'b>(
scope: &mut v8::HandleScope<'a>,
scope: &mut v8::PinScope<'a, '_>,
value: v8::Local<'a, v8::Value>,
prefix: Cow<'static, str>,
context: ContextFn<'b>,

View file

@ -81,7 +81,7 @@ pub fn create_runtime_snapshot(
})),
with_runtime_cb: Some(Box::new(|rt| {
let isolate = rt.v8_isolate();
let scope = &mut v8::HandleScope::new(isolate);
v8::scope!(scope, isolate);
let tmpl = deno_node::init_global_template(
scope,

View file

@ -116,7 +116,7 @@ pub enum WorkerThreadType {
impl<'s> WorkerThreadType {
pub fn to_v8(
&self,
scope: &mut v8::HandleScope<'s>,
scope: &mut v8::PinScope<'s, '_>,
) -> v8::Local<'s, v8::String> {
v8::String::new(
scope,
@ -704,7 +704,7 @@ impl WebWorker {
let bootstrap_fn_global = {
let context = js_runtime.main_context();
let scope = &mut js_runtime.handle_scope();
deno_core::scope!(scope, &mut js_runtime);
let context_local = v8::Local::new(scope, context);
let global_obj = context_local.global(scope);
let bootstrap_str =
@ -751,7 +751,7 @@ impl WebWorker {
// Instead of using name for log we use `worker-${id}` because
// WebWorkers can have empty string as name.
{
let scope = &mut self.js_runtime.handle_scope();
deno_core::scope!(scope, &mut self.js_runtime);
let args = options.as_v8(scope);
let bootstrap_fn = self.bootstrap_fn_global.take().unwrap();
let bootstrap_fn = v8::Local::new(scope, bootstrap_fn);
@ -1003,7 +1003,7 @@ impl WebWorker {
// Starts polling for messages from worker host from JavaScript.
fn start_polling_for_messages(&mut self) {
let poll_for_messages_fn = self.poll_for_messages_fn.take().unwrap();
let scope = &mut self.js_runtime.handle_scope();
deno_core::scope!(scope, &mut self.js_runtime);
let poll_for_messages =
v8::Local::<v8::Value>::new(scope, poll_for_messages_fn);
let fn_ = v8::Local::<v8::Function>::try_from(poll_for_messages).unwrap();
@ -1015,7 +1015,7 @@ impl WebWorker {
fn has_message_event_listener(&mut self) -> bool {
let has_message_event_listener_fn =
self.has_message_event_listener_fn.as_ref().unwrap();
let scope = &mut self.js_runtime.handle_scope();
deno_core::scope!(scope, &mut self.js_runtime);
let has_message_event_listener =
v8::Local::<v8::Value>::new(scope, has_message_event_listener_fn);
let fn_ =

View file

@ -98,7 +98,8 @@ pub fn create_validate_import_attributes_callback(
enable_raw_imports: Arc<AtomicBool>,
) -> deno_core::ValidateImportAttributesCb {
Box::new(
move |scope: &mut v8::HandleScope, attributes: &HashMap<String, String>| {
move |scope: &mut v8::PinScope<'_, '_>,
attributes: &HashMap<String, String>| {
let valid_attribute = |kind: &str| {
enable_raw_imports.load(Ordering::Relaxed)
&& matches!(kind, "bytes" | "text")
@ -642,7 +643,7 @@ impl MainWorker {
dispatch_process_exit_event_fn_global,
) = {
let context = js_runtime.main_context();
let scope = &mut js_runtime.handle_scope();
deno_core::scope!(scope, &mut js_runtime);
let context_local = v8::Local::new(scope, context);
let global_obj = context_local.global(scope);
let bootstrap_str =
@ -750,8 +751,8 @@ impl MainWorker {
}
}
let scope = &mut self.js_runtime.handle_scope();
let scope = &mut v8::TryCatch::new(scope);
deno_core::scope!(scope, &mut self.js_runtime);
v8::tc_scope!(scope, scope);
let args = options.as_v8(scope);
let bootstrap_fn = self.bootstrap_fn_global.take().unwrap();
let bootstrap_fn = v8::Local::new(scope, bootstrap_fn);
@ -947,8 +948,8 @@ impl MainWorker {
///
/// Does not poll event loop, and thus not await any of the "load" event handlers.
pub fn dispatch_load_event(&mut self) -> Result<(), Box<JsError>> {
let scope = &mut self.js_runtime.handle_scope();
let tc_scope = &mut v8::TryCatch::new(scope);
deno_core::scope!(scope, &mut self.js_runtime);
v8::tc_scope!(tc_scope, scope);
let dispatch_load_event_fn =
v8::Local::new(tc_scope, &self.dispatch_load_event_fn_global);
let undefined = v8::undefined(tc_scope);
@ -964,8 +965,8 @@ impl MainWorker {
///
/// Does not poll event loop, and thus not await any of the "unload" event handlers.
pub fn dispatch_unload_event(&mut self) -> Result<(), Box<JsError>> {
let scope = &mut self.js_runtime.handle_scope();
let tc_scope = &mut v8::TryCatch::new(scope);
deno_core::scope!(scope, &mut self.js_runtime);
v8::tc_scope!(tc_scope, scope);
let dispatch_unload_event_fn =
v8::Local::new(tc_scope, &self.dispatch_unload_event_fn_global);
let undefined = v8::undefined(tc_scope);
@ -979,8 +980,8 @@ impl MainWorker {
/// Dispatches process.emit("exit") event for node compat.
pub fn dispatch_process_exit_event(&mut self) -> Result<(), Box<JsError>> {
let scope = &mut self.js_runtime.handle_scope();
let tc_scope = &mut v8::TryCatch::new(scope);
deno_core::scope!(scope, &mut self.js_runtime);
v8::tc_scope!(tc_scope, scope);
let dispatch_process_exit_event_fn =
v8::Local::new(tc_scope, &self.dispatch_process_exit_event_fn_global);
let undefined = v8::undefined(tc_scope);
@ -996,8 +997,8 @@ impl MainWorker {
/// indicating if the event was prevented and thus event loop should continue
/// running.
pub fn dispatch_beforeunload_event(&mut self) -> Result<bool, Box<JsError>> {
let scope = &mut self.js_runtime.handle_scope();
let tc_scope = &mut v8::TryCatch::new(scope);
deno_core::scope!(scope, &mut self.js_runtime);
v8::tc_scope!(tc_scope, scope);
let dispatch_beforeunload_event_fn =
v8::Local::new(tc_scope, &self.dispatch_beforeunload_event_fn_global);
let undefined = v8::undefined(tc_scope);
@ -1015,8 +1016,8 @@ impl MainWorker {
pub fn dispatch_process_beforeexit_event(
&mut self,
) -> Result<bool, Box<JsError>> {
let scope = &mut self.js_runtime.handle_scope();
let tc_scope = &mut v8::TryCatch::new(scope);
deno_core::scope!(scope, &mut self.js_runtime);
v8::tc_scope!(tc_scope, scope);
let dispatch_process_beforeexit_event_fn = v8::Local::new(
tc_scope,
&self.dispatch_process_beforeexit_event_fn_global,
@ -1322,7 +1323,7 @@ impl ModuleLoader for PlaceholderModuleLoader {
fn get_host_defined_options<'s>(
&self,
scope: &mut v8::HandleScope<'s>,
scope: &mut v8::PinScope<'s, '_>,
name: &str,
) -> Option<v8::Local<'s, v8::Data>> {
self

View file

@ -211,7 +211,7 @@ impl BootstrapOptions {
/// Return the v8 equivalent of this structure.
pub fn as_v8<'s>(
&self,
scope: &mut v8::HandleScope<'s>,
scope: &mut v8::PinScope<'s, '_>,
) -> v8::Local<'s, v8::Value> {
let scope = RefCell::new(scope);
let ser = deno_core::serde_v8::Serializer::new(&scope);