2022-11-26 22:40:31 -05:00
|
|
|
#[allow(non_camel_case_types)]
|
|
|
|
///Auto-generated by `deno_ops`, i.e: `#[op]`
|
|
|
|
///
|
|
|
|
///Use `op_void_async::decl()` to get an op-declaration
|
|
|
|
///you can include in a `deno_core::Extension`.
|
|
|
|
pub struct op_void_async;
|
|
|
|
#[doc(hidden)]
|
|
|
|
impl op_void_async {
|
|
|
|
pub fn name() -> &'static str {
|
|
|
|
stringify!(op_void_async)
|
|
|
|
}
|
|
|
|
pub fn v8_fn_ptr<'scope>() -> deno_core::v8::FunctionCallback {
|
|
|
|
use deno_core::v8::MapFnTo;
|
|
|
|
Self::v8_func.map_fn_to()
|
|
|
|
}
|
|
|
|
pub fn decl<'scope>() -> deno_core::OpDecl {
|
|
|
|
deno_core::OpDecl {
|
|
|
|
name: Self::name(),
|
|
|
|
v8_fn_ptr: Self::v8_fn_ptr(),
|
|
|
|
enabled: true,
|
|
|
|
fast_fn: Some(
|
|
|
|
Box::new(op_void_async_fast {
|
|
|
|
_phantom: ::std::marker::PhantomData,
|
|
|
|
}),
|
|
|
|
),
|
|
|
|
is_async: true,
|
|
|
|
is_unstable: false,
|
|
|
|
is_v8: false,
|
|
|
|
argc: 0usize,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#[inline]
|
|
|
|
#[allow(clippy::too_many_arguments)]
|
|
|
|
async fn call() {}
|
|
|
|
pub fn v8_func<'scope>(
|
|
|
|
scope: &mut deno_core::v8::HandleScope<'scope>,
|
|
|
|
args: deno_core::v8::FunctionCallbackArguments,
|
|
|
|
mut rv: deno_core::v8::ReturnValue,
|
|
|
|
) {
|
|
|
|
use deno_core::futures::FutureExt;
|
|
|
|
let ctx = unsafe {
|
|
|
|
&*(deno_core::v8::Local::<deno_core::v8::External>::cast(args.data()).value()
|
|
|
|
as *const deno_core::_ops::OpCtx)
|
|
|
|
};
|
|
|
|
let op_id = ctx.id;
|
feat(core): Reland support for async ops in realms (#17204)
Currently realms are supported on `deno_core`, but there was no support
for async ops anywhere other than the main realm. The main issue is that
the `js_recv_cb` callback, which resolves promises corresponding to
async ops, was only set for the main realm, so async ops in other realms
would never resolve. Furthermore, promise ID's are specific to each
realm, which meant that async ops from other realms would result in a
wrong promise from the main realm being resolved.
This change takes the `ContextState` struct added in #17050, and adds to
it a `js_recv_cb` callback for each realm. Combined with the fact that
that same PR also added a list of known realms to `JsRuntimeState`, and
that #17174 made `OpCtx` instances realm-specific and had them include
an index into that list of known realms, this makes it possible to know
the current realm in the `queue_async_op` and `queue_fast_async_op`
methods, and therefore to send the results of promises for each realm to
that realm, and prevent the ID's from getting mixed up.
Additionally, since promise ID's are no longer unique to the isolate,
having a single set of unrefed ops doesn't work. This change therefore
also moves `unrefed_ops` from `JsRuntimeState` to `ContextState`, and
adds the lengths of the unrefed op sets for all known realms to get the
total number of unrefed ops to compare in the event loop.
This PR is a reland of #14734 after it was reverted in #16366, except
that `ContextState` and `JsRuntimeState::known_realms` were previously
relanded in #17050. Another significant difference with the original PR
is passing around an index into `JsRuntimeState::known_realms` instead
of a `v8::Global<v8::Context>` to identify the realm, because async op
queuing in fast calls cannot call into V8, and therefore cannot have
access to V8 globals. This also simplified the implementation of
`resolve_async_ops`.
Co-authored-by: Luis Malheiro <luismalheiro@gmail.com>
2023-01-14 08:40:16 -05:00
|
|
|
let realm_idx = ctx.realm_idx;
|
2022-11-26 22:40:31 -05:00
|
|
|
let promise_id = args.get(0);
|
|
|
|
let promise_id = deno_core::v8::Local::<
|
|
|
|
deno_core::v8::Integer,
|
|
|
|
>::try_from(promise_id)
|
|
|
|
.map(|l| l.value() as deno_core::PromiseId)
|
|
|
|
.map_err(deno_core::anyhow::Error::from);
|
|
|
|
let promise_id: deno_core::PromiseId = match promise_id {
|
|
|
|
Ok(promise_id) => promise_id,
|
|
|
|
Err(err) => {
|
|
|
|
deno_core::_ops::throw_type_error(
|
|
|
|
scope,
|
|
|
|
format!("invalid promise id: {}", err),
|
|
|
|
);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
let get_class = {
|
|
|
|
let state = ::std::cell::RefCell::borrow(&ctx.state);
|
|
|
|
state.tracker.track_async(op_id);
|
|
|
|
state.get_error_class_fn
|
|
|
|
};
|
|
|
|
deno_core::_ops::queue_async_op(
|
|
|
|
ctx,
|
|
|
|
scope,
|
|
|
|
false,
|
|
|
|
async move {
|
|
|
|
let result = Self::call().await;
|
|
|
|
let result = Ok(result);
|
feat(core): Reland support for async ops in realms (#17204)
Currently realms are supported on `deno_core`, but there was no support
for async ops anywhere other than the main realm. The main issue is that
the `js_recv_cb` callback, which resolves promises corresponding to
async ops, was only set for the main realm, so async ops in other realms
would never resolve. Furthermore, promise ID's are specific to each
realm, which meant that async ops from other realms would result in a
wrong promise from the main realm being resolved.
This change takes the `ContextState` struct added in #17050, and adds to
it a `js_recv_cb` callback for each realm. Combined with the fact that
that same PR also added a list of known realms to `JsRuntimeState`, and
that #17174 made `OpCtx` instances realm-specific and had them include
an index into that list of known realms, this makes it possible to know
the current realm in the `queue_async_op` and `queue_fast_async_op`
methods, and therefore to send the results of promises for each realm to
that realm, and prevent the ID's from getting mixed up.
Additionally, since promise ID's are no longer unique to the isolate,
having a single set of unrefed ops doesn't work. This change therefore
also moves `unrefed_ops` from `JsRuntimeState` to `ContextState`, and
adds the lengths of the unrefed op sets for all known realms to get the
total number of unrefed ops to compare in the event loop.
This PR is a reland of #14734 after it was reverted in #16366, except
that `ContextState` and `JsRuntimeState::known_realms` were previously
relanded in #17050. Another significant difference with the original PR
is passing around an index into `JsRuntimeState::known_realms` instead
of a `v8::Global<v8::Context>` to identify the realm, because async op
queuing in fast calls cannot call into V8, and therefore cannot have
access to V8 globals. This also simplified the implementation of
`resolve_async_ops`.
Co-authored-by: Luis Malheiro <luismalheiro@gmail.com>
2023-01-14 08:40:16 -05:00
|
|
|
(
|
|
|
|
realm_idx,
|
|
|
|
promise_id,
|
|
|
|
op_id,
|
|
|
|
deno_core::_ops::to_op_result(get_class, result),
|
|
|
|
)
|
2022-11-26 22:40:31 -05:00
|
|
|
},
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
2022-11-11 08:44:53 -05:00
|
|
|
struct op_void_async_fast {
|
|
|
|
_phantom: ::std::marker::PhantomData<()>,
|
|
|
|
}
|
|
|
|
impl<'scope> deno_core::v8::fast_api::FastFunction for op_void_async_fast {
|
|
|
|
fn function(&self) -> *const ::std::ffi::c_void {
|
|
|
|
op_void_async_fast_fn as *const ::std::ffi::c_void
|
|
|
|
}
|
|
|
|
fn args(&self) -> &'static [deno_core::v8::fast_api::Type] {
|
|
|
|
use deno_core::v8::fast_api::Type::*;
|
|
|
|
use deno_core::v8::fast_api::CType;
|
|
|
|
&[V8Value, Int32, CallbackOptions]
|
|
|
|
}
|
|
|
|
fn return_type(&self) -> deno_core::v8::fast_api::CType {
|
|
|
|
deno_core::v8::fast_api::CType::Void
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fn op_void_async_fast_fn<'scope>(
|
|
|
|
_: deno_core::v8::Local<deno_core::v8::Object>,
|
|
|
|
__promise_id: i32,
|
|
|
|
fast_api_callback_options: *mut deno_core::v8::fast_api::FastApiCallbackOptions,
|
|
|
|
) -> () {
|
|
|
|
use deno_core::v8;
|
|
|
|
use deno_core::_ops;
|
|
|
|
let __opts: &mut v8::fast_api::FastApiCallbackOptions = unsafe {
|
|
|
|
&mut *fast_api_callback_options
|
|
|
|
};
|
|
|
|
let __ctx = unsafe {
|
|
|
|
&*(v8::Local::<v8::External>::cast(unsafe { __opts.data.data }).value()
|
|
|
|
as *const _ops::OpCtx)
|
|
|
|
};
|
|
|
|
let op_state = __ctx.state.clone();
|
|
|
|
let result = op_void_async::call();
|
|
|
|
let __op_id = __ctx.id;
|
|
|
|
let __state = ::std::cell::RefCell::borrow(&__ctx.state);
|
|
|
|
__state.tracker.track_async(__op_id);
|
feat(core): Reland support for async ops in realms (#17204)
Currently realms are supported on `deno_core`, but there was no support
for async ops anywhere other than the main realm. The main issue is that
the `js_recv_cb` callback, which resolves promises corresponding to
async ops, was only set for the main realm, so async ops in other realms
would never resolve. Furthermore, promise ID's are specific to each
realm, which meant that async ops from other realms would result in a
wrong promise from the main realm being resolved.
This change takes the `ContextState` struct added in #17050, and adds to
it a `js_recv_cb` callback for each realm. Combined with the fact that
that same PR also added a list of known realms to `JsRuntimeState`, and
that #17174 made `OpCtx` instances realm-specific and had them include
an index into that list of known realms, this makes it possible to know
the current realm in the `queue_async_op` and `queue_fast_async_op`
methods, and therefore to send the results of promises for each realm to
that realm, and prevent the ID's from getting mixed up.
Additionally, since promise ID's are no longer unique to the isolate,
having a single set of unrefed ops doesn't work. This change therefore
also moves `unrefed_ops` from `JsRuntimeState` to `ContextState`, and
adds the lengths of the unrefed op sets for all known realms to get the
total number of unrefed ops to compare in the event loop.
This PR is a reland of #14734 after it was reverted in #16366, except
that `ContextState` and `JsRuntimeState::known_realms` were previously
relanded in #17050. Another significant difference with the original PR
is passing around an index into `JsRuntimeState::known_realms` instead
of a `v8::Global<v8::Context>` to identify the realm, because async op
queuing in fast calls cannot call into V8, and therefore cannot have
access to V8 globals. This also simplified the implementation of
`resolve_async_ops`.
Co-authored-by: Luis Malheiro <luismalheiro@gmail.com>
2023-01-14 08:40:16 -05:00
|
|
|
let realm_idx = __ctx.realm_idx;
|
2022-11-11 08:44:53 -05:00
|
|
|
let result = _ops::queue_fast_async_op(
|
|
|
|
__ctx,
|
|
|
|
async move {
|
|
|
|
let result = result.await;
|
feat(core): Reland support for async ops in realms (#17204)
Currently realms are supported on `deno_core`, but there was no support
for async ops anywhere other than the main realm. The main issue is that
the `js_recv_cb` callback, which resolves promises corresponding to
async ops, was only set for the main realm, so async ops in other realms
would never resolve. Furthermore, promise ID's are specific to each
realm, which meant that async ops from other realms would result in a
wrong promise from the main realm being resolved.
This change takes the `ContextState` struct added in #17050, and adds to
it a `js_recv_cb` callback for each realm. Combined with the fact that
that same PR also added a list of known realms to `JsRuntimeState`, and
that #17174 made `OpCtx` instances realm-specific and had them include
an index into that list of known realms, this makes it possible to know
the current realm in the `queue_async_op` and `queue_fast_async_op`
methods, and therefore to send the results of promises for each realm to
that realm, and prevent the ID's from getting mixed up.
Additionally, since promise ID's are no longer unique to the isolate,
having a single set of unrefed ops doesn't work. This change therefore
also moves `unrefed_ops` from `JsRuntimeState` to `ContextState`, and
adds the lengths of the unrefed op sets for all known realms to get the
total number of unrefed ops to compare in the event loop.
This PR is a reland of #14734 after it was reverted in #16366, except
that `ContextState` and `JsRuntimeState::known_realms` were previously
relanded in #17050. Another significant difference with the original PR
is passing around an index into `JsRuntimeState::known_realms` instead
of a `v8::Global<v8::Context>` to identify the realm, because async op
queuing in fast calls cannot call into V8, and therefore cannot have
access to V8 globals. This also simplified the implementation of
`resolve_async_ops`.
Co-authored-by: Luis Malheiro <luismalheiro@gmail.com>
2023-01-14 08:40:16 -05:00
|
|
|
(realm_idx, __promise_id, __op_id, _ops::OpResult::Ok(result.into()))
|
2022-11-11 08:44:53 -05:00
|
|
|
},
|
|
|
|
);
|
|
|
|
result
|
|
|
|
}
|