0
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-03-03 09:31:22 -05:00

cleanup(core): recursive get & ensure helpers (#13972)

This commit is contained in:
Aaron O'Mullan 2022-03-16 09:04:38 +01:00 committed by GitHub
parent 697b60a335
commit 895e474295
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 59 additions and 45 deletions

View file

@ -153,9 +153,6 @@ pub fn initialize_context<'s>(
let scope = &mut v8::ContextScope::new(scope, context);
let deno_key = v8::String::new(scope, "Deno").unwrap();
let core_key = v8::String::new(scope, "core").unwrap();
let ops_key = v8::String::new(scope, "ops").unwrap();
// Snapshot already registered `Deno.core.ops` but
// extensions may provide ops that aren't part of the snapshot.
//
@ -164,30 +161,18 @@ pub fn initialize_context<'s>(
// tsc ops are static at snapshot time.
if snapshot_loaded {
// Grab Deno.core.ops object
let deno_val = global.get(scope, deno_key.into()).unwrap();
let deno_val = v8::Local::<v8::Object>::try_from(deno_val)
.expect("`Deno` not in global scope.");
let core_val = deno_val.get(scope, core_key.into()).unwrap();
let core_val = v8::Local::<v8::Object>::try_from(core_val)
.expect("`Deno.core` not in global scope");
let ops_val = core_val.get(scope, ops_key.into()).unwrap();
let ops_val = v8::Local::<v8::Object>::try_from(ops_val)
.expect("`Deno.core.ops` not in global scope");
let ops_obj = JsRuntime::grab_global::<v8::Object>(scope, "Deno.core.ops")
.expect("Deno.core.ops to exist");
let raw_op_state = Rc::as_ptr(&op_state) as *const c_void;
for op in ops {
set_func_raw(scope, ops_val, op.name, op.v8_fn_ptr, raw_op_state);
set_func_raw(scope, ops_obj, op.name, op.v8_fn_ptr, raw_op_state);
}
return scope.escape(context);
}
// global.Deno = { core: { ops: {} } };
let deno_val = v8::Object::new(scope);
global.set(scope, deno_key.into(), deno_val.into());
let core_val = v8::Object::new(scope);
deno_val.set(scope, core_key.into(), core_val.into());
let ops_val = v8::Object::new(scope);
core_val.set(scope, ops_key.into(), ops_val.into());
// global.Deno = { core: { } };
let core_val = JsRuntime::ensure_objs(scope, global, "Deno.core").unwrap();
// Bind functions to Deno.core.*
set_func(scope, core_val, "refOp_", ref_op);
@ -245,6 +230,7 @@ pub fn initialize_context<'s>(
set_func(scope, global, "queueMicrotask", queue_microtask);
// Bind functions to Deno.core.ops.*
let ops_val = JsRuntime::ensure_objs(scope, global, "Deno.core.ops").unwrap();
let raw_op_state = Rc::as_ptr(&op_state) as *const c_void;
for op in ops {
set_func_raw(scope, ops_val, op.name, op.v8_fn_ptr, raw_op_state);

View file

@ -507,36 +507,64 @@ impl JsRuntime {
Ok(())
}
/// Grab a Global handle to a function returned by the given expression
fn grab_fn(
scope: &mut v8::HandleScope,
code: &str,
) -> v8::Global<v8::Function> {
let code = v8::String::new(scope, code).unwrap();
let script = v8::Script::compile(scope, code, None).unwrap();
let v8_value = script.run(scope).unwrap();
let cb = v8::Local::<v8::Function>::try_from(v8_value).unwrap();
v8::Global::new(scope, cb)
/// Grab a Global handle to a v8 value returned by the expression
pub(crate) fn grab<'s, T>(
scope: &mut v8::HandleScope<'s>,
root: v8::Local<'s, v8::Value>,
path: &str,
) -> Option<v8::Local<'s, T>>
where
v8::Local<'s, T>: TryFrom<v8::Local<'s, v8::Value>, Error = v8::DataError>,
{
path
.split('.')
.fold(Some(root), |p, k| {
let p = v8::Local::<v8::Object>::try_from(p?).ok()?;
let k = v8::String::new(scope, k)?;
p.get(scope, k.into())
})?
.try_into()
.ok()
}
fn grab_obj<'s>(
pub(crate) fn grab_global<'s, T>(
scope: &mut v8::HandleScope<'s>,
code: &str,
) -> v8::Local<'s, v8::Object> {
let scope = &mut v8::EscapableHandleScope::new(scope);
let code = v8::String::new(scope, code).unwrap();
let script = v8::Script::compile(scope, code, None).unwrap();
let v8_value = script.run(scope).unwrap();
let obj = v8::Local::<v8::Object>::try_from(v8_value).unwrap();
scope.escape(obj)
path: &str,
) -> Option<v8::Local<'s, T>>
where
v8::Local<'s, T>: TryFrom<v8::Local<'s, v8::Value>, Error = v8::DataError>,
{
let context = scope.get_current_context();
let global = context.global(scope);
Self::grab(scope, global.into(), path)
}
pub(crate) fn ensure_objs<'s>(
scope: &mut v8::HandleScope<'s>,
root: v8::Local<'s, v8::Object>,
path: &str,
) -> Option<v8::Local<'s, v8::Object>> {
path.split('.').fold(Some(root), |p, k| {
let k = v8::String::new(scope, k)?.into();
match p?.get(scope, k) {
Some(v) if !v.is_null_or_undefined() => v.try_into().ok(),
_ => {
let o = v8::Object::new(scope);
p?.set(scope, k, o.into());
Some(o)
}
}
})
}
/// Grabs a reference to core.js' opresolve & syncOpsCache()
fn init_cbs(&mut self) {
let mut scope = self.handle_scope();
let recv_cb = Self::grab_fn(&mut scope, "Deno.core.opresolve");
let scope = &mut self.handle_scope();
let recv_cb =
Self::grab_global::<v8::Function>(scope, "Deno.core.opresolve").unwrap();
let recv_cb = v8::Global::new(scope, recv_cb);
// Put global handles in state
let state_rc = JsRuntime::state(&scope);
let state_rc = JsRuntime::state(scope);
let mut state = state_rc.borrow_mut();
state.js_recv_cb.replace(recv_cb);
}
@ -612,11 +640,11 @@ impl JsRuntime {
// TODO(@AaronO): make ops stable across snapshots
{
let scope = &mut self.handle_scope();
let obj = Self::grab_obj(scope, "Deno.core.ops");
let names = obj.get_own_property_names(scope).unwrap();
let o = Self::grab_global::<v8::Object>(scope, "Deno.core.ops").unwrap();
let names = o.get_own_property_names(scope).unwrap();
for i in 0..names.length() {
let key = names.get_index(scope, i).unwrap();
obj.delete(scope, key);
o.delete(scope, key);
}
}