diff --git a/bench_util/js_runtime.rs b/bench_util/js_runtime.rs index f87fa3b03a..0495d6d8dc 100644 --- a/bench_util/js_runtime.rs +++ b/bench_util/js_runtime.rs @@ -9,7 +9,7 @@ use crate::profiling::is_profiling; pub fn create_js_runtime(setup: impl FnOnce() -> Vec) -> JsRuntime { JsRuntime::new(RuntimeOptions { - extensions: setup(), + extensions_with_js: setup(), ..Default::default() }) } diff --git a/cli/build.rs b/cli/build.rs index 15be033fd8..4865cadb56 100644 --- a/cli/build.rs +++ b/cli/build.rs @@ -243,6 +243,7 @@ mod ts { Ok(()) }) .build()], + extensions_with_js: vec![], additional_files: files, compression_cb: Some(Box::new(|vec, snapshot_slice| { vec.extend_from_slice( @@ -304,6 +305,7 @@ fn create_cli_snapshot(snapshot_path: PathBuf, files: Vec) { snapshot_path, startup_snapshot: Some(deno_runtime::js::deno_isolate_init()), extensions, + extensions_with_js: vec![], additional_files: files, compression_cb: Some(Box::new(|vec, snapshot_slice| { lzzzz::lz4_hc::compress_to_vec( diff --git a/core/runtime.rs b/core/runtime.rs index 9ee3aad70c..5272266260 100644 --- a/core/runtime.rs +++ b/core/runtime.rs @@ -87,6 +87,7 @@ pub struct JsRuntime { built_from_snapshot: bool, allocations: IsolateAllocations, extensions: Vec, + extensions_with_js: Vec, event_loop_middlewares: Vec>, // Marks if this is considered the top-level runtime. Used only be inspector. is_main: bool, @@ -240,10 +241,23 @@ pub struct RuntimeOptions { /// executed tries to load modules. pub module_loader: Option>, - /// JsRuntime extensions, not to be confused with ES modules - /// these are sets of ops and other JS code to be initialized. + /// JsRuntime extensions, not to be confused with ES modules. + /// Only ops registered by extensions will be initialized. If you need + /// to execute JS code from extensions, use `extensions_with_js` options + /// instead. pub extensions: Vec, + /// JsRuntime extensions, not to be confused with ES modules. + /// Ops registered by extensions will be initialized and JS code will be + /// executed. If you don't need to execute JS code from extensions, use + /// `extensions` option instead. + /// + /// This is useful when creating snapshots, in such case you would pass + /// extensions using `extensions_with_js`, later when creating a runtime + /// from the snapshot, you would pass these extensions using `extensions` + /// option. + pub extensions_with_js: Vec, + /// V8 snapshot that should be loaded on startup. /// /// Currently can't be used with `will_snapshot`. @@ -339,11 +353,20 @@ impl JsRuntime { let has_startup_snapshot = options.startup_snapshot.is_some(); // Add builtins extension - options - .extensions - .insert(0, crate::ops_builtin::init_builtins()); + if !has_startup_snapshot { + options + .extensions_with_js + .insert(0, crate::ops_builtin::init_builtins()); + } else { + options + .extensions + .insert(0, crate::ops_builtin::init_builtins()); + } - let ops = Self::collect_ops(&mut options.extensions); + let ops = Self::collect_ops( + &mut options.extensions, + &mut options.extensions_with_js, + ); let mut op_state = OpState::new(ops.len()); if let Some(get_error_class_fn) = options.get_error_class_fn { @@ -539,6 +562,7 @@ impl JsRuntime { allocations: IsolateAllocations::default(), event_loop_middlewares: Vec::with_capacity(options.extensions.len()), extensions: options.extensions, + extensions_with_js: options.extensions_with_js, state: state_rc, module_map: Some(module_map_rc), is_main: options.is_main, @@ -547,12 +571,8 @@ impl JsRuntime { // Init resources and ops before extensions to make sure they are // available during the initialization process. js_runtime.init_extension_ops().unwrap(); - // TODO(@AaronO): diff extensions inited in snapshot and those provided - // for now we assume that snapshot and extensions always match - if !has_startup_snapshot { - let realm = js_runtime.global_realm(); - js_runtime.init_extension_js(&realm).unwrap(); - } + let realm = js_runtime.global_realm(); + js_runtime.init_extension_js(&realm).unwrap(); // Init callbacks (opresolve) js_runtime.init_cbs(); @@ -682,7 +702,8 @@ impl JsRuntime { /// Initializes JS of provided Extensions in the given realm fn init_extension_js(&mut self, realm: &JsRealm) -> Result<(), Error> { // Take extensions to avoid double-borrow - let mut extensions: Vec = std::mem::take(&mut self.extensions); + let mut extensions: Vec = + std::mem::take(&mut self.extensions_with_js); for m in extensions.iter_mut() { let js_files = m.init_js(); for (filename, source) in js_files { @@ -691,15 +712,22 @@ impl JsRuntime { } } // Restore extensions - self.extensions = extensions; + self.extensions_with_js = extensions; Ok(()) } /// Collects ops from extensions & applies middleware - fn collect_ops(extensions: &mut [Extension]) -> Vec { + fn collect_ops( + extensions: &mut [Extension], + extensions_with_js: &mut [Extension], + ) -> Vec { + let mut exts = vec![]; + exts.extend(extensions); + exts.extend(extensions_with_js); + // Middleware - let middleware: Vec> = extensions + let middleware: Vec> = exts .iter_mut() .filter_map(|e| e.init_middleware()) .collect(); @@ -708,7 +736,7 @@ impl JsRuntime { let macroware = move |d| middleware.iter().fold(d, |d, m| m(d)); // Flatten ops, apply middlware & override disabled ops - extensions + exts .iter_mut() .filter_map(|e| e.init_ops()) .flatten() @@ -733,22 +761,41 @@ impl JsRuntime { fn init_extension_ops(&mut self) -> Result<(), Error> { let op_state = self.op_state(); // Take extensions to avoid double-borrow - let mut extensions: Vec = std::mem::take(&mut self.extensions); + { + let mut extensions: Vec = std::mem::take(&mut self.extensions); - // Setup state - for e in extensions.iter_mut() { - // ops are already registered during in bindings::initialize_context(); - e.init_state(&mut op_state.borrow_mut())?; + // Setup state + for e in extensions.iter_mut() { + // ops are already registered during in bindings::initialize_context(); + e.init_state(&mut op_state.borrow_mut())?; - // Setup event-loop middleware - if let Some(middleware) = e.init_event_loop_middleware() { - self.event_loop_middlewares.push(middleware); + // Setup event-loop middleware + if let Some(middleware) = e.init_event_loop_middleware() { + self.event_loop_middlewares.push(middleware); + } } + + // Restore extensions + self.extensions = extensions; } + { + let mut extensions: Vec = + std::mem::take(&mut self.extensions_with_js); - // Restore extensions - self.extensions = extensions; + // Setup state + for e in extensions.iter_mut() { + // ops are already registered during in bindings::initialize_context(); + e.init_state(&mut op_state.borrow_mut())?; + // Setup event-loop middleware + if let Some(middleware) = e.init_event_loop_middleware() { + self.event_loop_middlewares.push(middleware); + } + } + + // Restore extensions + self.extensions_with_js = extensions; + } Ok(()) } diff --git a/core/snapshot_util.rs b/core/snapshot_util.rs index b408bad564..bacc0c6aeb 100644 --- a/core/snapshot_util.rs +++ b/core/snapshot_util.rs @@ -12,6 +12,7 @@ pub struct CreateSnapshotOptions { pub snapshot_path: PathBuf, pub startup_snapshot: Option, pub extensions: Vec, + pub extensions_with_js: Vec, pub additional_files: Vec, pub compression_cb: Option>, } @@ -21,6 +22,7 @@ pub fn create_snapshot(create_snapshot_options: CreateSnapshotOptions) { will_snapshot: true, startup_snapshot: create_snapshot_options.startup_snapshot, extensions: create_snapshot_options.extensions, + extensions_with_js: create_snapshot_options.extensions_with_js, ..Default::default() }); diff --git a/runtime/build.rs b/runtime/build.rs index bab7745cc3..62a3da03b8 100644 --- a/runtime/build.rs +++ b/runtime/build.rs @@ -120,7 +120,7 @@ mod not_docs { } fn create_runtime_snapshot(snapshot_path: PathBuf, files: Vec) { - let extensions: Vec = vec![ + let extensions_with_js: Vec = vec![ deno_webidl::init(), deno_console::init(), deno_url::init(), @@ -154,7 +154,8 @@ mod not_docs { cargo_manifest_dir: env!("CARGO_MANIFEST_DIR"), snapshot_path, startup_snapshot: None, - extensions, + extensions: vec![], + extensions_with_js, additional_files: files, compression_cb: Some(Box::new(|vec, snapshot_slice| { lzzzz::lz4_hc::compress_to_vec(