mirror of
https://github.com/denoland/deno.git
synced 2025-02-01 20:25:12 -05:00
fix(core): nuke Deno.core.ops pre-snapshot (#13970)
To avoid OOB & other ExternalReference snapshot serialization issues Co-authored-by: Bert Belder <bertbelder@gmail.com>
This commit is contained in:
parent
163e1d6192
commit
07d8431f10
2 changed files with 99 additions and 85 deletions
152
core/bindings.rs
152
core/bindings.rs
|
@ -14,6 +14,7 @@ use crate::PromiseId;
|
|||
use crate::ZeroCopyBuf;
|
||||
use anyhow::Error;
|
||||
use log::debug;
|
||||
use once_cell::sync::Lazy;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
use serde_v8::to_v8;
|
||||
|
@ -29,88 +30,77 @@ use v8::SharedArrayBuffer;
|
|||
use v8::ValueDeserializerHelper;
|
||||
use v8::ValueSerializerHelper;
|
||||
|
||||
pub fn external_references(
|
||||
ops: &[OpPair],
|
||||
op_state: Rc<RefCell<OpState>>,
|
||||
) -> v8::ExternalReferences {
|
||||
let mut refs = vec![
|
||||
v8::ExternalReference {
|
||||
function: ref_op.map_fn_to(),
|
||||
},
|
||||
v8::ExternalReference {
|
||||
function: unref_op.map_fn_to(),
|
||||
},
|
||||
v8::ExternalReference {
|
||||
function: set_macrotask_callback.map_fn_to(),
|
||||
},
|
||||
v8::ExternalReference {
|
||||
function: set_nexttick_callback.map_fn_to(),
|
||||
},
|
||||
v8::ExternalReference {
|
||||
function: set_promise_reject_callback.map_fn_to(),
|
||||
},
|
||||
v8::ExternalReference {
|
||||
function: set_uncaught_exception_callback.map_fn_to(),
|
||||
},
|
||||
v8::ExternalReference {
|
||||
function: run_microtasks.map_fn_to(),
|
||||
},
|
||||
v8::ExternalReference {
|
||||
function: has_tick_scheduled.map_fn_to(),
|
||||
},
|
||||
v8::ExternalReference {
|
||||
function: set_has_tick_scheduled.map_fn_to(),
|
||||
},
|
||||
v8::ExternalReference {
|
||||
function: eval_context.map_fn_to(),
|
||||
},
|
||||
v8::ExternalReference {
|
||||
function: queue_microtask.map_fn_to(),
|
||||
},
|
||||
v8::ExternalReference {
|
||||
function: create_host_object.map_fn_to(),
|
||||
},
|
||||
v8::ExternalReference {
|
||||
function: encode.map_fn_to(),
|
||||
},
|
||||
v8::ExternalReference {
|
||||
function: decode.map_fn_to(),
|
||||
},
|
||||
v8::ExternalReference {
|
||||
function: serialize.map_fn_to(),
|
||||
},
|
||||
v8::ExternalReference {
|
||||
function: deserialize.map_fn_to(),
|
||||
},
|
||||
v8::ExternalReference {
|
||||
function: get_promise_details.map_fn_to(),
|
||||
},
|
||||
v8::ExternalReference {
|
||||
function: get_proxy_details.map_fn_to(),
|
||||
},
|
||||
v8::ExternalReference {
|
||||
function: is_proxy.map_fn_to(),
|
||||
},
|
||||
v8::ExternalReference {
|
||||
function: memory_usage.map_fn_to(),
|
||||
},
|
||||
v8::ExternalReference {
|
||||
function: call_console.map_fn_to(),
|
||||
},
|
||||
v8::ExternalReference {
|
||||
function: set_wasm_streaming_callback.map_fn_to(),
|
||||
},
|
||||
];
|
||||
let op_refs = ops
|
||||
.iter()
|
||||
.map(|(_, opref)| v8::ExternalReference { function: *opref });
|
||||
refs.extend(op_refs);
|
||||
let raw_op_state = Rc::as_ptr(&op_state) as *mut c_void;
|
||||
refs.push(v8::ExternalReference {
|
||||
pointer: raw_op_state,
|
||||
pub static EXTERNAL_REFERENCES: Lazy<v8::ExternalReferences> =
|
||||
Lazy::new(|| {
|
||||
v8::ExternalReferences::new(&[
|
||||
v8::ExternalReference {
|
||||
function: ref_op.map_fn_to(),
|
||||
},
|
||||
v8::ExternalReference {
|
||||
function: unref_op.map_fn_to(),
|
||||
},
|
||||
v8::ExternalReference {
|
||||
function: set_macrotask_callback.map_fn_to(),
|
||||
},
|
||||
v8::ExternalReference {
|
||||
function: set_nexttick_callback.map_fn_to(),
|
||||
},
|
||||
v8::ExternalReference {
|
||||
function: set_promise_reject_callback.map_fn_to(),
|
||||
},
|
||||
v8::ExternalReference {
|
||||
function: set_uncaught_exception_callback.map_fn_to(),
|
||||
},
|
||||
v8::ExternalReference {
|
||||
function: run_microtasks.map_fn_to(),
|
||||
},
|
||||
v8::ExternalReference {
|
||||
function: has_tick_scheduled.map_fn_to(),
|
||||
},
|
||||
v8::ExternalReference {
|
||||
function: set_has_tick_scheduled.map_fn_to(),
|
||||
},
|
||||
v8::ExternalReference {
|
||||
function: eval_context.map_fn_to(),
|
||||
},
|
||||
v8::ExternalReference {
|
||||
function: queue_microtask.map_fn_to(),
|
||||
},
|
||||
v8::ExternalReference {
|
||||
function: create_host_object.map_fn_to(),
|
||||
},
|
||||
v8::ExternalReference {
|
||||
function: encode.map_fn_to(),
|
||||
},
|
||||
v8::ExternalReference {
|
||||
function: decode.map_fn_to(),
|
||||
},
|
||||
v8::ExternalReference {
|
||||
function: serialize.map_fn_to(),
|
||||
},
|
||||
v8::ExternalReference {
|
||||
function: deserialize.map_fn_to(),
|
||||
},
|
||||
v8::ExternalReference {
|
||||
function: get_promise_details.map_fn_to(),
|
||||
},
|
||||
v8::ExternalReference {
|
||||
function: get_proxy_details.map_fn_to(),
|
||||
},
|
||||
v8::ExternalReference {
|
||||
function: is_proxy.map_fn_to(),
|
||||
},
|
||||
v8::ExternalReference {
|
||||
function: memory_usage.map_fn_to(),
|
||||
},
|
||||
v8::ExternalReference {
|
||||
function: call_console.map_fn_to(),
|
||||
},
|
||||
v8::ExternalReference {
|
||||
function: set_wasm_streaming_callback.map_fn_to(),
|
||||
},
|
||||
])
|
||||
});
|
||||
v8::ExternalReferences::new(&refs)
|
||||
}
|
||||
|
||||
pub fn script_origin<'a>(
|
||||
s: &mut v8::HandleScope<'a>,
|
||||
|
|
|
@ -297,13 +297,12 @@ impl JsRuntime {
|
|||
|
||||
let op_state = Rc::new(RefCell::new(op_state));
|
||||
|
||||
let refs = bindings::external_references(&ops, op_state.clone());
|
||||
let refs: &'static v8::ExternalReferences = Box::leak(Box::new(refs));
|
||||
let global_context;
|
||||
let (mut isolate, maybe_snapshot_creator) = if options.will_snapshot {
|
||||
// TODO(ry) Support loading snapshots before snapshotting.
|
||||
assert!(options.startup_snapshot.is_none());
|
||||
let mut creator = v8::SnapshotCreator::new(Some(refs));
|
||||
let mut creator =
|
||||
v8::SnapshotCreator::new(Some(&bindings::EXTERNAL_REFERENCES));
|
||||
let isolate = unsafe { creator.get_owned_isolate() };
|
||||
let mut isolate = JsRuntime::setup_isolate(isolate);
|
||||
{
|
||||
|
@ -319,7 +318,7 @@ impl JsRuntime {
|
|||
.create_params
|
||||
.take()
|
||||
.unwrap_or_else(v8::Isolate::create_params)
|
||||
.external_references(&**refs);
|
||||
.external_references(&**bindings::EXTERNAL_REFERENCES);
|
||||
let snapshot_loaded = if let Some(snapshot) = options.startup_snapshot {
|
||||
params = match snapshot {
|
||||
Snapshot::Static(data) => params.snapshot_blob(data),
|
||||
|
@ -518,6 +517,18 @@ impl JsRuntime {
|
|||
v8::Global::new(scope, cb)
|
||||
}
|
||||
|
||||
fn grab_obj<'s>(
|
||||
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)
|
||||
}
|
||||
|
||||
/// Grabs a reference to core.js' opresolve & syncOpsCache()
|
||||
fn init_cbs(&mut self) {
|
||||
let mut scope = self.handle_scope();
|
||||
|
@ -594,6 +605,19 @@ impl JsRuntime {
|
|||
/// be a different type if `RuntimeOptions::js_error_create_fn` has been set.
|
||||
pub fn snapshot(&mut self) -> v8::StartupData {
|
||||
assert!(self.snapshot_creator.is_some());
|
||||
|
||||
// Nuke Deno.core.ops.* to avoid ExternalReference snapshotting issues
|
||||
// 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();
|
||||
for i in 0..names.length() {
|
||||
let key = names.get_index(scope, i).unwrap();
|
||||
obj.delete(scope, key);
|
||||
}
|
||||
}
|
||||
|
||||
let state = Self::state(self.v8_isolate());
|
||||
|
||||
// Note: create_blob() method must not be called from within a HandleScope.
|
||||
|
|
Loading…
Add table
Reference in a new issue