summaryrefslogtreecommitdiff
path: root/core/bindings.rs
diff options
context:
space:
mode:
Diffstat (limited to 'core/bindings.rs')
-rw-r--r--core/bindings.rs92
1 files changed, 89 insertions, 3 deletions
diff --git a/core/bindings.rs b/core/bindings.rs
index 1a869f3c4..b50c77df2 100644
--- a/core/bindings.rs
+++ b/core/bindings.rs
@@ -97,6 +97,7 @@ pub fn initialize_context<'s>(
scope: &mut v8::HandleScope<'s, ()>,
op_ctxs: &[OpCtx],
snapshot_loaded: bool,
+ will_snapshot: bool,
) -> v8::Local<'s, v8::Context> {
let scope = &mut v8::EscapableHandleScope::new(scope);
@@ -112,7 +113,9 @@ pub fn initialize_context<'s>(
let ops_obj = JsRuntime::grab_global::<v8::Object>(scope, "Deno.core.ops")
.expect("Deno.core.ops to exist");
initialize_ops(scope, ops_obj, op_ctxs, snapshot_loaded);
-
+ if !will_snapshot {
+ initialize_async_ops_info(scope, ops_obj, op_ctxs);
+ }
return scope.escape(context);
}
@@ -124,8 +127,10 @@ pub fn initialize_context<'s>(
// Bind functions to Deno.core.ops.*
let ops_obj = JsRuntime::ensure_objs(scope, global, "Deno.core.ops").unwrap();
-
- initialize_ops(scope, ops_obj, op_ctxs, snapshot_loaded);
+ if !will_snapshot {
+ initialize_async_ops_info(scope, ops_obj, op_ctxs);
+ }
+ initialize_ops(scope, ops_obj, op_ctxs, !will_snapshot);
scope.escape(context)
}
@@ -586,3 +591,84 @@ pub fn throw_type_error(scope: &mut v8::HandleScope, message: impl AsRef<str>) {
let exception = v8::Exception::type_error(scope, message);
scope.throw_exception(exception);
}
+
+struct AsyncOpsInfo {
+ ptr: *const OpCtx,
+ len: usize,
+}
+
+impl<'s> IntoIterator for &'s AsyncOpsInfo {
+ type Item = &'s OpCtx;
+ type IntoIter = AsyncOpsInfoIterator<'s>;
+
+ fn into_iter(self) -> Self::IntoIter {
+ AsyncOpsInfoIterator {
+ // SAFETY: OpCtx slice is valid for the lifetime of the Isolate
+ info: unsafe { std::slice::from_raw_parts(self.ptr, self.len) },
+ index: 0,
+ }
+ }
+}
+
+struct AsyncOpsInfoIterator<'s> {
+ info: &'s [OpCtx],
+ index: usize,
+}
+
+impl<'s> Iterator for AsyncOpsInfoIterator<'s> {
+ type Item = &'s OpCtx;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ loop {
+ match self.info.get(self.index) {
+ Some(ctx) if ctx.decl.is_async => {
+ self.index += 1;
+ return Some(ctx);
+ }
+ Some(_) => {
+ self.index += 1;
+ }
+ None => return None,
+ }
+ }
+ }
+}
+
+fn async_ops_info(
+ scope: &mut v8::HandleScope,
+ args: v8::FunctionCallbackArguments,
+ mut rv: v8::ReturnValue,
+) {
+ let async_op_names = v8::Object::new(scope);
+ let external: v8::Local<v8::External> = args.data().try_into().unwrap();
+ let info: &AsyncOpsInfo =
+ // SAFETY: external is guaranteed to be a valid pointer to AsyncOpsInfo
+ unsafe { &*(external.value() as *const AsyncOpsInfo) };
+ for ctx in info {
+ let name = v8::String::new(scope, ctx.decl.name).unwrap();
+ let argc = v8::Integer::new(scope, ctx.decl.argc as i32);
+ async_op_names.set(scope, name.into(), argc.into());
+ }
+ rv.set(async_op_names.into());
+}
+
+fn initialize_async_ops_info(
+ scope: &mut v8::HandleScope,
+ ops_obj: v8::Local<v8::Object>,
+ op_ctxs: &[OpCtx],
+) {
+ let key = v8::String::new(scope, "asyncOpsInfo").unwrap();
+ let external = v8::External::new(
+ scope,
+ Box::into_raw(Box::new(AsyncOpsInfo {
+ ptr: op_ctxs as *const [OpCtx] as _,
+ len: op_ctxs.len(),
+ })) as *mut c_void,
+ );
+ let val = v8::Function::builder(async_ops_info)
+ .data(external.into())
+ .build(scope)
+ .unwrap();
+ val.set_name(key);
+ ops_obj.set(scope, key.into(), val.into());
+}