summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron O'Mullan <aaron.omullan@gmail.com>2022-03-15 22:50:17 +0100
committerGitHub <noreply@github.com>2022-03-15 22:50:17 +0100
commit07d8431f100e8df5f523adf542b47f8b91af3539 (patch)
tree97241da33c3f0e9f45617bdbd0a81d64c49b8e51
parent163e1d61920fbc6a0bdb18adc57b249b2d600472 (diff)
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>
-rw-r--r--core/bindings.rs152
-rw-r--r--core/runtime.rs32
2 files changed, 99 insertions, 85 deletions
diff --git a/core/bindings.rs b/core/bindings.rs
index 2ab55187d..0a87c0ffa 100644
--- a/core/bindings.rs
+++ b/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>,
diff --git a/core/runtime.rs b/core/runtime.rs
index 019065526..c95ef6a20 100644
--- a/core/runtime.rs
+++ b/core/runtime.rs
@@ -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.