diff options
| author | Bartek Iwańczuk <biwanczuk@gmail.com> | 2023-06-14 00:36:16 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-06-13 22:36:16 +0000 |
| commit | 60bf79c18410fd332b6b9b7c222e6d3d62bfe3f8 (patch) | |
| tree | 070934eb82d906ee341d1ad4d1390f0b75860529 /core | |
| parent | 82dd90f98d6817caadcb9b6bd81aba80b2ee848d (diff) | |
Revert "refactor(core): cleanup feature flags for js source inclusion… (#19490)
… (#19463)"
This reverts commit ceb03cfb037cf7024a5048b17b508ddda59cfa05.
This is being reverted because it causes 3.5Mb increase in the binary
size,
due to runtime JS code being included in the binary, even though it's
already snapshotted.
CC @nayeemrmn
Diffstat (limited to 'core')
| -rw-r--r-- | core/00_primordials.js | 3 | ||||
| -rw-r--r-- | core/01_core.js | 3 | ||||
| -rw-r--r-- | core/02_error.js | 3 | ||||
| -rw-r--r-- | core/Cargo.toml | 6 | ||||
| -rw-r--r-- | core/extensions.rs | 133 | ||||
| -rw-r--r-- | core/inspector.rs | 3 | ||||
| -rw-r--r-- | core/lib.rs | 1 | ||||
| -rw-r--r-- | core/modules.rs | 27 | ||||
| -rw-r--r-- | core/runtime.rs | 80 | ||||
| -rw-r--r-- | core/snapshot_util.rs | 30 |
10 files changed, 184 insertions, 105 deletions
diff --git a/core/00_primordials.js b/core/00_primordials.js index b85aa6673..60474e649 100644 --- a/core/00_primordials.js +++ b/core/00_primordials.js @@ -34,9 +34,6 @@ "use strict"; (() => { - if (globalThis.__bootstrap) { - return; - } const primordials = {}; const { diff --git a/core/01_core.js b/core/01_core.js index 8b5a4ff66..13aa17c7e 100644 --- a/core/01_core.js +++ b/core/01_core.js @@ -2,9 +2,6 @@ "use strict"; ((window) => { - if (globalThis.__bootstrap.core) { - return; - } const { Array, ArrayPrototypeFill, diff --git a/core/02_error.js b/core/02_error.js index ffca10a32..b29dc9b4e 100644 --- a/core/02_error.js +++ b/core/02_error.js @@ -2,9 +2,6 @@ "use strict"; ((window) => { - if (globalThis.__bootstrap.core.prepareStackTrace) { - return; - } const core = Deno.core; const ops = core.ops; const { diff --git a/core/Cargo.toml b/core/Cargo.toml index 251f15429..b9cb265e8 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -16,10 +16,7 @@ path = "lib.rs" [features] default = ["v8_use_custom_libcxx"] v8_use_custom_libcxx = ["v8/use_custom_libcxx"] -# Enable to exclude JS sources from the binary (e.g. if they are already snapshotted). -exclude_js_sources = [] -# Enable to override `exclude_js_sources` (e.g. for snapshot creation in `build.rs`). -force_include_js_sources = ["exclude_js_sources"] +include_js_files_for_snapshotting = [] [dependencies] anyhow.workspace = true @@ -50,4 +47,3 @@ path = "examples/http_bench_json_ops/main.rs" # These dependencies are only used for the 'http_bench_*_ops' examples. [dev-dependencies] deno_ast.workspace = true -deno_core = { workspace = true, features = ["force_include_js_sources"] } diff --git a/core/extensions.rs b/core/extensions.rs index ab0578106..fa6d7851e 100644 --- a/core/extensions.rs +++ b/core/extensions.rs @@ -1,15 +1,32 @@ // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. use crate::modules::ModuleCode; use crate::OpState; +use anyhow::Context as _; +use anyhow::Error; use std::cell::RefCell; +use std::path::PathBuf; use std::rc::Rc; use std::task::Context; use v8::fast_api::FastFunction; #[derive(Clone, Debug)] +pub enum ExtensionFileSourceCode { + /// Source code is included in the binary produced. Either by being defined + /// inline, or included using `include_str!()`. If you are snapshotting, this + /// will result in two copies of the source code being included - one in the + /// snapshot, the other the static string in the `Extension`. + IncludedInBinary(&'static str), + + // Source code is loaded from a file on disk. It's meant to be used if the + // embedder is creating snapshots. Files will be loaded from the filesystem + // during the build time and they will only be present in the V8 snapshot. + LoadedFromFsDuringSnapshot(PathBuf), +} + +#[derive(Clone, Debug)] pub struct ExtensionFileSource { pub specifier: &'static str, - pub code: &'static str, + pub code: ExtensionFileSourceCode, } impl ExtensionFileSource { @@ -17,14 +34,29 @@ impl ExtensionFileSource { s.chars().filter(|c| !c.is_ascii()).collect::<String>() } - pub fn load(&self) -> ModuleCode { - debug_assert!( - self.code.is_ascii(), - "Extension code must be 7-bit ASCII: {} (found {})", - self.specifier, - Self::find_non_ascii(self.code) - ); - ModuleCode::from_static(self.code) + pub fn load(&self) -> Result<ModuleCode, Error> { + match &self.code { + ExtensionFileSourceCode::IncludedInBinary(code) => { + debug_assert!( + code.is_ascii(), + "Extension code must be 7-bit ASCII: {} (found {})", + self.specifier, + Self::find_non_ascii(code) + ); + Ok(ModuleCode::from_static(code)) + } + ExtensionFileSourceCode::LoadedFromFsDuringSnapshot(path) => { + let msg = || format!("Failed to read \"{}\"", path.display()); + let s = std::fs::read_to_string(path).with_context(msg)?; + debug_assert!( + s.is_ascii(), + "Extension code must be 7-bit ASCII: {} (found {})", + self.specifier, + Self::find_non_ascii(&s) + ); + Ok(s.into()) + } + } } } @@ -155,7 +187,6 @@ macro_rules! extension { $(, esm = [ $( dir $dir_esm:literal , )? $( $esm:literal ),* $(,)? ] )? $(, esm_setup_script = $esm_setup_script:expr )? $(, js = [ $( dir $dir_js:literal , )? $( $js:literal ),* $(,)? ] )? - $(, force_include_js_sources $($force_include_js_sources:block)? )? // dummy variable $(, options = { $( $options_id:ident : $options_type:ty ),* $(,)? } )? $(, middleware = $middleware_fn:expr )? $(, state = $state_fn:expr )? @@ -180,9 +211,9 @@ macro_rules! extension { #[inline(always)] #[allow(unused_variables)] fn with_js(ext: &mut $crate::ExtensionBuilder) { - ext.esm( - $crate::include_js_files!( $name $( force_include_js_sources $($force_include_js_sources)?, )? $( $( dir $dir_esm , )? $( $esm , )* )? ) - ); + $( ext.esm( + $crate::include_js_files!( $name $( dir $dir_esm , )? $( $esm , )* ) + ); )? $( ext.esm(vec![ExtensionFileSource { specifier: "ext:setup", @@ -192,9 +223,9 @@ macro_rules! extension { $( ext.esm_entry_point($esm_entry_point); )? - ext.js( - $crate::include_js_files!( $name $( force_include_js_sources $($force_include_js_sources)?, )? $( $( dir $dir_js , )? $( $js , )* )? ) - ); + $( ext.js( + $crate::include_js_files!( $name $( dir $dir_js , )? $( $js , )* ) + ); )? } // If ops were specified, add those ops to the extension. @@ -254,7 +285,7 @@ macro_rules! extension { } #[allow(dead_code)] - pub fn init $( < $( $param : $type + 'static ),+ > )? ( $( $( $options_id : $options_type ),* )? ) -> $crate::Extension + pub fn init_ops_and_esm $( < $( $param : $type + 'static ),+ > )? ( $( $( $options_id : $options_type ),* )? ) -> $crate::Extension $( where $( $bound : $bound_type ),+ )? { let mut ext = Self::ext(); @@ -265,6 +296,17 @@ macro_rules! extension { Self::with_customizer(&mut ext); ext.take() } + + #[allow(dead_code)] + pub fn init_ops $( < $( $param : $type + 'static ),+ > )? ( $( $( $options_id : $options_type ),* )? ) -> $crate::Extension + $( where $( $bound : $bound_type ),+ )? + { + let mut ext = Self::ext(); + Self::with_ops $( ::< $( $param ),+ > )?(&mut ext); + Self::with_state_and_middleware $( ::< $( $param ),+ > )?(&mut ext, $( $( $options_id , )* )? ); + Self::with_customizer(&mut ext); + ext.take() + } } }; @@ -566,49 +608,54 @@ impl ExtensionBuilder { /// - "ext:my_extension/js/01_hello.js" /// - "ext:my_extension/js/02_goodbye.js" /// ``` -#[cfg(not(all( - feature = "exclude_js_sources", - not(feature = "force_include_js_sources") -)))] +#[cfg(not(feature = "include_js_files_for_snapshotting"))] #[macro_export] macro_rules! include_js_files { - ($name:ident $(force_include_js_sources $($dummy:block)?,)? $(dir $dir:literal,)? $($file:literal,)*) => { - $crate::force_include_js_files!($name $(dir $dir,)? $($file,)*) - }; -} - -#[cfg(all( - feature = "exclude_js_sources", - not(feature = "force_include_js_sources") -))] -#[macro_export] -macro_rules! include_js_files { - ($name:ident force_include_js_sources $($dummy:block)?, $(dir $dir:literal,)? $($file:literal,)*) => { - $crate::force_include_js_files!($name $(dir $dir,)? $($file,)*) + ($name:ident dir $dir:literal, $($file:literal,)+) => { + vec![ + $($crate::ExtensionFileSource { + specifier: concat!("ext:", stringify!($name), "/", $file), + code: $crate::ExtensionFileSourceCode::IncludedInBinary( + include_str!(concat!($dir, "/", $file) + )), + },)+ + ] }; - ($name:ident $(dir $dir:literal,)? $($file:literal,)*) => { - vec![] + ($name:ident $($file:literal,)+) => { + vec![ + $($crate::ExtensionFileSource { + specifier: concat!("ext:", stringify!($name), "/", $file), + code: $crate::ExtensionFileSourceCode::IncludedInBinary( + include_str!($file) + ), + },)+ + ] }; } +#[cfg(feature = "include_js_files_for_snapshotting")] #[macro_export] -macro_rules! force_include_js_files { - ($name:ident dir $dir:literal, $($file:literal,)*) => { +macro_rules! include_js_files { + ($name:ident dir $dir:literal, $($file:literal,)+) => { vec![ $($crate::ExtensionFileSource { specifier: concat!("ext:", stringify!($name), "/", $file), - code: include_str!(concat!($dir, "/", $file)), - },)* + code: $crate::ExtensionFileSourceCode::LoadedFromFsDuringSnapshot( + std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")).join($dir).join($file) + ), + },)+ ] }; - ($name:ident $($file:literal,)*) => { + ($name:ident $($file:literal,)+) => { vec![ $($crate::ExtensionFileSource { specifier: concat!("ext:", stringify!($name), "/", $file), - code: include_str!($file), - },)* + code: $crate::ExtensionFileSourceCode::LoadedFromFsDuringSnapshot( + std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")).join($file) + ), + },)+ ] }; } diff --git a/core/inspector.rs b/core/inspector.rs index d7592fbe4..d7c84608f 100644 --- a/core/inspector.rs +++ b/core/inspector.rs @@ -365,9 +365,6 @@ impl JsRuntimeInspector { w.poll_state = PollState::Parked; w.parked_thread.replace(thread::current()); } - PollState::Parked => { - w.parked_thread.replace(thread::current()); - } _ => unreachable!(), }; w.poll_state diff --git a/core/lib.rs b/core/lib.rs index 729182a4f..336d9c2b9 100644 --- a/core/lib.rs +++ b/core/lib.rs @@ -60,6 +60,7 @@ pub use crate::async_cell::RcRef; pub use crate::extensions::Extension; pub use crate::extensions::ExtensionBuilder; pub use crate::extensions::ExtensionFileSource; +pub use crate::extensions::ExtensionFileSourceCode; pub use crate::extensions::OpDecl; pub use crate::extensions::OpMiddlewareFn; pub use crate::fast_string::FastString; diff --git a/core/modules.rs b/core/modules.rs index 5d9fe2fc4..4f1875ae5 100644 --- a/core/modules.rs +++ b/core/modules.rs @@ -438,7 +438,7 @@ impl ModuleLoader for ExtModuleLoader { let result = if let Some(load_callback) = &self.maybe_load_callback { load_callback(source) } else { - Ok(source.load()) + source.load() }; match result { Ok(code) => { @@ -459,6 +459,29 @@ impl ModuleLoader for ExtModuleLoader { } } +impl Drop for ExtModuleLoader { + fn drop(&mut self) { + let sources = self.sources.get_mut(); + let used_specifiers = self.used_specifiers.get_mut(); + let unused_modules: Vec<_> = sources + .iter() + .filter(|(k, _)| !used_specifiers.contains(k.as_str())) + .collect(); + + if !unused_modules.is_empty() { + let mut msg = + "Following modules were passed to ExtModuleLoader but never used:\n" + .to_string(); + for m in unused_modules { + msg.push_str(" - "); + msg.push_str(m.0); + msg.push('\n'); + } + panic!("{}", msg); + } + } +} + /// Basic file system module loader. /// /// Note that this loader will **block** event loop @@ -2021,7 +2044,7 @@ import "/a.js"; deno_core::extension!(test_ext, ops = [op_test]); let mut runtime = JsRuntime::new(RuntimeOptions { - extensions: vec![test_ext::init()], + extensions: vec![test_ext::init_ops()], module_loader: Some(loader), ..Default::default() }); diff --git a/core/runtime.rs b/core/runtime.rs index 29064df63..ecfd0bd57 100644 --- a/core/runtime.rs +++ b/core/runtime.rs @@ -510,7 +510,7 @@ impl JsRuntime { maybe_load_callback: Option<ExtModuleLoaderCb>, ) -> JsRuntime { let init_mode = InitMode::from_options(&options); - let (op_state, ops) = Self::create_opstate(&mut options); + let (op_state, ops) = Self::create_opstate(&mut options, init_mode); let op_state = Rc::new(RefCell::new(op_state)); // Collect event-loop middleware @@ -860,7 +860,7 @@ impl JsRuntime { realm.execute_script( self.v8_isolate(), file_source.specifier, - file_source.load(), + file_source.load()?, )?; } } @@ -963,11 +963,20 @@ impl JsRuntime { } /// Initializes ops of provided Extensions - fn create_opstate(options: &mut RuntimeOptions) -> (OpState, Vec<OpDecl>) { + fn create_opstate( + options: &mut RuntimeOptions, + init_mode: InitMode, + ) -> (OpState, Vec<OpDecl>) { // Add built-in extension - options - .extensions - .insert(0, crate::ops_builtin::core::init()); + if init_mode == InitMode::FromSnapshot { + options + .extensions + .insert(0, crate::ops_builtin::core::init_ops()); + } else { + options + .extensions + .insert(0, crate::ops_builtin::core::init_ops_and_esm()); + } let ops = Self::collect_ops(&mut options.extensions); @@ -1849,19 +1858,6 @@ impl JsRuntime { .map(|handle| v8::Local::new(tc_scope, handle)) .expect("ModuleInfo not found"); let mut status = module.get_status(); - if status == v8::ModuleStatus::Evaluated { - let (sender, receiver) = oneshot::channel(); - sender.send(Ok(())).unwrap(); - return receiver; - } - if status == v8::ModuleStatus::Errored { - let (sender, receiver) = oneshot::channel(); - let exception = module.get_exception(); - sender - .send(exception_to_err_result(tc_scope, exception, false)) - .unwrap(); - return receiver; - } assert_eq!( status, v8::ModuleStatus::Instantiated, @@ -2707,7 +2703,7 @@ pub mod tests { } ); let mut runtime = JsRuntime::new(RuntimeOptions { - extensions: vec![test_ext::init(mode, dispatch_count.clone())], + extensions: vec![test_ext::init_ops(mode, dispatch_count.clone())], get_error_class_fn: Some(&|error| { crate::error::get_custom_error_class(error).unwrap() }), @@ -3122,7 +3118,7 @@ pub mod tests { deno_core::extension!(test_ext, ops = [op_err]); let mut runtime = JsRuntime::new(RuntimeOptions { - extensions: vec![test_ext::init()], + extensions: vec![test_ext::init_ops()], get_error_class_fn: Some(&get_error_class_name), ..Default::default() }); @@ -3728,7 +3724,7 @@ main(); deno_core::extension!(test_ext, ops = [op_err_sync, op_err_async]); let mut runtime = JsRuntime::new(RuntimeOptions { - extensions: vec![test_ext::init()], + extensions: vec![test_ext::init_ops()], ..Default::default() }); @@ -3890,7 +3886,7 @@ assertEquals(1, notify_return_value); state = |state| state.put(InnerState(42)) ); let mut runtime = JsRuntime::new(RuntimeOptions { - extensions: vec![test_ext::init()], + extensions: vec![test_ext::init_ops()], ..Default::default() }); @@ -3921,7 +3917,7 @@ assertEquals(1, notify_return_value); ops = [op_sync_serialize_object_with_numbers_as_keys] ); let mut runtime = JsRuntime::new(RuntimeOptions { - extensions: vec![test_ext::init()], + extensions: vec![test_ext::init_ops()], ..Default::default() }); @@ -3963,7 +3959,7 @@ Deno.core.ops.op_sync_serialize_object_with_numbers_as_keys({ ops = [op_async_serialize_object_with_numbers_as_keys] ); let mut runtime = JsRuntime::new(RuntimeOptions { - extensions: vec![test_ext::init()], + extensions: vec![test_ext::init_ops()], ..Default::default() }); @@ -3999,7 +3995,7 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", { deno_core::extension!(test_ext, ops = [op_async_sleep]); let mut runtime = JsRuntime::new(RuntimeOptions { - extensions: vec![test_ext::init()], + extensions: vec![test_ext::init_ops()], ..Default::default() }); @@ -4054,7 +4050,7 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", { deno_core::extension!(test_ext, ops = [op_macrotask, op_next_tick]); let mut runtime = JsRuntime::new(RuntimeOptions { - extensions: vec![test_ext::init()], + extensions: vec![test_ext::init_ops()], ..Default::default() }); @@ -4195,7 +4191,7 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", { deno_core::extension!(test_ext, ops = [op_promise_reject]); let mut runtime = JsRuntime::new(RuntimeOptions { - extensions: vec![test_ext::init()], + extensions: vec![test_ext::init_ops()], ..Default::default() }); @@ -4338,7 +4334,7 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", { } let mut runtime = JsRuntime::new(RuntimeOptions { - extensions: vec![test_ext::init()], + extensions: vec![test_ext::init_ops()], module_loader: Some(Rc::new(ModsLoader)), ..Default::default() }); @@ -4363,7 +4359,7 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", { deno_core::extension!(test_ext, ops = [op_err]); let mut runtime = JsRuntime::new(RuntimeOptions { - extensions: vec![test_ext::init()], + extensions: vec![test_ext::init_ops()], ..Default::default() }); assert!(runtime @@ -4388,7 +4384,7 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", { deno_core::extension!(test_ext, ops = [op_add_4]); let mut runtime = JsRuntime::new(RuntimeOptions { - extensions: vec![test_ext::init()], + extensions: vec![test_ext::init_ops()], ..Default::default() }); let r = runtime @@ -4411,7 +4407,7 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", { deno_core::extension!(test_ext, ops_fn = ops); let mut runtime = JsRuntime::new(RuntimeOptions { - extensions: vec![test_ext::init()], + extensions: vec![test_ext::init_ops()], ..Default::default() }); let err = runtime @@ -4440,7 +4436,7 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", { deno_core::extension!(test_ext, ops = [op_sum_take, op_boomerang]); let mut runtime = JsRuntime::new(RuntimeOptions { - extensions: vec![test_ext::init()], + extensions: vec![test_ext::init_ops()], ..Default::default() }); @@ -4509,7 +4505,7 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", { middleware = |op| if op.is_unstable { op.disable() } else { op } ); let mut runtime = JsRuntime::new(RuntimeOptions { - extensions: vec![test_ext::init()], + extensions: vec![test_ext::init_ops()], ..Default::default() }); runtime @@ -4557,7 +4553,7 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", { deno_core::extension!(test_ext, ops = [op_test]); let mut runtime = JsRuntime::new(RuntimeOptions { - extensions: vec![test_ext::init()], + extensions: vec![test_ext::init_ops()], ..Default::default() }); let realm = runtime.create_realm().unwrap(); @@ -4590,7 +4586,7 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", { deno_core::extension!(test_ext, ops = [op_test]); let mut runtime = JsRuntime::new(RuntimeOptions { startup_snapshot: Some(Snapshot::Boxed(snapshot)), - extensions: vec![test_ext::init()], + extensions: vec![test_ext::init_ops()], ..Default::default() }); let realm = runtime.create_realm().unwrap(); @@ -4624,7 +4620,7 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", { deno_core::extension!(test_ext, ops = [op_test]); let mut runtime = JsRuntime::new(RuntimeOptions { - extensions: vec![test_ext::init()], + extensions: vec![test_ext::init_ops()], get_error_class_fn: Some(&|error| { crate::error::get_custom_error_class(error).unwrap() }), @@ -4672,7 +4668,7 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", { deno_core::extension!(test_ext, ops = [op_test]); let mut runtime = JsRuntime::new(RuntimeOptions { - extensions: vec![test_ext::init()], + extensions: vec![test_ext::init_ops()], get_error_class_fn: Some(&|error| { crate::error::get_custom_error_class(error).unwrap() }), @@ -4749,7 +4745,7 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", { deno_core::extension!(test_ext, ops = [op_pending]); let mut runtime = JsRuntime::new(RuntimeOptions { - extensions: vec![test_ext::init()], + extensions: vec![test_ext::init_ops()], ..Default::default() }); @@ -4796,7 +4792,7 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", { deno_core::extension!(test_ext, ops = [op_pending]); let mut runtime = JsRuntime::new(RuntimeOptions { - extensions: vec![test_ext::init()], + extensions: vec![test_ext::init_ops()], ..Default::default() }); @@ -4896,7 +4892,7 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", { deno_core::extension!(test_ext, ops = [a::op_test, op_test]); JsRuntime::new(RuntimeOptions { - extensions: vec![test_ext::init()], + extensions: vec![test_ext::init_ops()], ..Default::default() }); } @@ -4915,7 +4911,7 @@ Deno.core.opAsync("op_async_serialize_object_with_numbers_as_keys", { deno_core::extension!(test_ext, ops = [op_test_sync, op_test_async]); let mut runtime = JsRuntime::new(RuntimeOptions { - extensions: vec![test_ext::init()], + extensions: vec![test_ext::init_ops()], ..Default::default() }); diff --git a/core/snapshot_util.rs b/core/snapshot_util.rs index 200a81d15..88c273147 100644 --- a/core/snapshot_util.rs +++ b/core/snapshot_util.rs @@ -22,7 +22,16 @@ pub struct CreateSnapshotOptions { pub snapshot_module_load_cb: Option<ExtModuleLoaderCb>, } -pub fn create_snapshot(create_snapshot_options: CreateSnapshotOptions) { +pub struct CreateSnapshotOutput { + /// Any files marked as LoadedFromFsDuringSnapshot are collected here and should be + /// printed as 'cargo:rerun-if-changed' lines from your build script. + pub files_loaded_during_snapshot: Vec<PathBuf>, +} + +#[must_use = "The files listed by create_snapshot should be printed as 'cargo:rerun-if-changed' lines"] +pub fn create_snapshot( + create_snapshot_options: CreateSnapshotOptions, +) -> CreateSnapshotOutput { let mut mark = Instant::now(); let js_runtime = JsRuntimeForSnapshot::new( @@ -42,6 +51,22 @@ pub fn create_snapshot(create_snapshot_options: CreateSnapshotOptions) { ); mark = Instant::now(); + let mut files_loaded_during_snapshot = vec![]; + for source in js_runtime + .extensions() + .iter() + .flat_map(|e| vec![e.get_esm_sources(), e.get_js_sources()]) + .flatten() + .flatten() + { + use crate::ExtensionFileSourceCode; + if let ExtensionFileSourceCode::LoadedFromFsDuringSnapshot(path) = + &source.code + { + files_loaded_during_snapshot.push(path.clone()); + } + } + let snapshot = js_runtime.snapshot(); let snapshot_slice: &[u8] = &snapshot; println!( @@ -87,6 +112,9 @@ pub fn create_snapshot(create_snapshot_options: CreateSnapshotOptions) { Instant::now().saturating_duration_since(mark), create_snapshot_options.snapshot_path.display(), ); + CreateSnapshotOutput { + files_loaded_during_snapshot, + } } pub type FilterFn = Box<dyn Fn(&PathBuf) -> bool>; |
