Repository: denoland/deno_core
Pull request #303 (2023-11-03 16:45:23)

Add option to control op registration during snapshot time
Needed for https://github.com/denoland/deno/pull/21066


Patch:
diff --git a/core/runtime/bindings.rs b/core/runtime/bindings.rs
index 32179f4..2a71efe 100644
--- a/core/runtime/bindings.rs
+++ b/core/runtime/bindings.rs
@@ -124,6 +124,16 @@ pub(crate) fn initialize_context<'s>(
   op_ctxs: &[OpCtx],
   init_mode: InitMode,
 ) -> v8::Local<'s, v8::Context> {
+  // Fast path.
+  if matches!(
+    init_mode,
+    InitMode::FromSnapshot {
+      register_ops: false
+    }
+  ) {
+    return context;
+  }
+
   let global = context.global(scope);
 
   let mut codegen = String::with_capacity(op_ctxs.len() * 200);
@@ -171,7 +181,7 @@ pub(crate) fn initialize_context<'s>(
     let op_fn = op_ctx_function(scope, op_ctx);
     op_fns.set_index(scope, op_ctx.id as u32, op_fn.into());
   }
-  if init_mode == InitMode::FromSnapshot {
+  if init_mode.is_from_snapshot() {
     op_fn.call(scope, recv.into(), &[op_fns.into()]);
   } else {
     // Bind functions to Deno.core.*
diff --git a/core/runtime/jsruntime.rs b/core/runtime/jsruntime.rs
index a6a7fbd..686cc66 100644
--- a/core/runtime/jsruntime.rs
+++ b/core/runtime/jsruntime.rs
@@ -184,16 +184,26 @@ pub(crate) enum InitMode {
   /// We have no snapshot -- this is a pristine context.
   New,
   /// We are using a snapshot, thus certain initialization steps are skipped.
-  FromSnapshot,
+  FromSnapshot {
+    // Do we need to register new ops.
+    register_ops: bool,
+  },
 }
 
 impl InitMode {
   fn from_options(options: &RuntimeOptions) -> Self {
     match options.startup_snapshot {
       None => Self::New,
-      Some(_) => Self::FromSnapshot,
+      Some(_) => Self::FromSnapshot {
+        register_ops: options.register_ops,
+      },
     }
   }
+
+  #[inline]
+  pub fn is_from_snapshot(&self) -> bool {
+    matches!(self, Self::FromSnapshot { .. })
+  }
 }
 
 pub(crate) const BUILTIN_SOURCES: [ExtensionFileSource; 3] = include_js_files!(
@@ -401,6 +411,7 @@ pub struct RuntimeOptions {
 
   /// V8 snapshot that should be loaded on startup.
   pub startup_snapshot: Option<Snapshot>,
+  pub register_ops: bool,
 
   /// Isolate creation parameters.
   pub create_params: Option<v8::CreateParams>,
@@ -683,7 +694,7 @@ impl JsRuntime {
       );
 
       // Get module map data from the snapshot
-      let snapshotted_data = if init_mode == InitMode::FromSnapshot {
+      let snapshotted_data = if init_mode.is_from_snapshot() {
         Some(snapshot_util::get_snapshotted_data(scope, context))
       } else {
         None
@@ -887,7 +898,7 @@ impl JsRuntime {
         .module_loader
         .unwrap_or_else(|| Rc::new(NoopModuleLoader));
       let module_map_rc = Rc::new(RefCell::new(ModuleMap::new(loader)));
-      if self.init_mode == InitMode::FromSnapshot {
+      if self.init_mode.is_from_snapshot() {
         let snapshotted_data =
           snapshot_util::get_snapshotted_data(scope, context);
         module_map_rc
diff --git a/core/runtime/snapshot_util.rs b/core/runtime/snapshot_util.rs
index 8febb13..6bbc57a 100644
--- a/core/runtime/snapshot_util.rs
+++ b/core/runtime/snapshot_util.rs
@@ -18,6 +18,7 @@ pub struct CreateSnapshotOptions {
   pub cargo_manifest_dir: &'static str,
   pub snapshot_path: PathBuf,
   pub startup_snapshot: Option<Snapshot>,
+  pub register_ops: bool,
   pub extensions: Vec<Extension>,
   pub compression_cb: Option<Box<CompressionCb>>,
   pub with_runtime_cb: Option<Box<WithRuntimeCb>>,
@@ -38,6 +39,7 @@ pub fn create_snapshot(
   let mut js_runtime = JsRuntimeForSnapshot::new(RuntimeOptions {
     startup_snapshot: create_snapshot_options.startup_snapshot,
     extensions: create_snapshot_options.extensions,
+    register_ops: create_snapshot_options.register_ops,
     ..Default::default()
   });
   println!(


Test patch:
diff --git a/core/runtime/tests/jsrealm.rs b/core/runtime/tests/jsrealm.rs
index efc6c60..10e2f6e 100644
--- a/core/runtime/tests/jsrealm.rs
+++ b/core/runtime/tests/jsrealm.rs
@@ -220,6 +220,7 @@ fn js_realm_init_snapshot() {
   let mut runtime = JsRuntime::new(RuntimeOptions {
     startup_snapshot: Some(Snapshot::Boxed(snapshot)),
     extensions: vec![test_ext::init_ops()],
+    register_ops: true,
     ..Default::default()
   });
   let realm = runtime.create_realm(Default::default()).unwrap();