diff --git a/cli/Cargo.toml b/cli/Cargo.toml index 5ee0bd22da..c1779c1022 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -26,6 +26,11 @@ name = "lsp_bench_standalone" harness = false path = "./bench/lsp_bench_standalone.rs" +[features] +# A dev feature to disable creations and loading of snapshots in favor of +# loading JS sources at runtime. +__runtime_js_sources = ["deno_runtime/__runtime_js_sources"] + [build-dependencies] deno_runtime = { workspace = true, features = ["snapshot_from_snapshot", "include_js_files_for_snapshotting"] } deno_core = { workspace = true, features = ["include_js_files_for_snapshotting"] } diff --git a/cli/build.rs b/cli/build.rs index ecf0d3cbea..206c80d1e8 100644 --- a/cli/build.rs +++ b/cli/build.rs @@ -2,16 +2,10 @@ use std::env; use std::path::PathBuf; -use std::sync::Arc; use deno_core::snapshot_util::*; -use deno_core::Extension; use deno_core::ExtensionFileSource; use deno_core::ExtensionFileSourceCode; -use deno_runtime::deno_cache::SqliteBackedCache; -use deno_runtime::deno_http::DefaultHttpPropertyExtractor; -use deno_runtime::deno_kv::sqlite::SqliteDbHandler; -use deno_runtime::permissions::PermissionsContainer; use deno_runtime::*; mod ts { @@ -304,12 +298,10 @@ mod ts { } } -// FIXME(bartlomieju): information about which extensions were -// already snapshotted is not preserved in the snapshot. This should be -// fixed, so we can reliably depend on that information. -// deps = [runtime] +// Duplicated in `ops/mod.rs`. Keep in sync! deno_core::extension!( cli, + deps = [runtime], esm_entry_point = "ext:cli/99_main.js", esm = [ dir "js", @@ -326,8 +318,16 @@ deno_core::extension!( } ); +#[cfg(not(feature = "__runtime_js_sources"))] #[must_use = "The files listed by create_cli_snapshot should be printed as 'cargo:rerun-if-changed' lines"] fn create_cli_snapshot(snapshot_path: PathBuf) -> CreateSnapshotOutput { + use deno_core::Extension; + use deno_runtime::deno_cache::SqliteBackedCache; + use deno_runtime::deno_http::DefaultHttpPropertyExtractor; + use deno_runtime::deno_kv::sqlite::SqliteDbHandler; + use deno_runtime::permissions::PermissionsContainer; + use std::sync::Arc; + // NOTE(bartlomieju): ordering is important here, keep it in sync with // `runtime/worker.rs`, `runtime/web_worker.rs` and `runtime/build.rs`! let fs = Arc::new(deno_fs::RealFs); @@ -367,13 +367,14 @@ fn create_cli_snapshot(snapshot_path: PathBuf) -> CreateSnapshotOutput { deno_io::deno_io::init_ops(Default::default()), deno_fs::deno_fs::init_ops::(false, fs.clone()), deno_node::deno_node::init_ops::(None, fs), + deno_runtime::runtime::init_ops(), cli::init_ops_and_esm(), // NOTE: This needs to be init_ops_and_esm! ]; create_snapshot(CreateSnapshotOptions { cargo_manifest_dir: env!("CARGO_MANIFEST_DIR"), snapshot_path, - startup_snapshot: Some(deno_runtime::js::deno_isolate_init()), + startup_snapshot: deno_runtime::js::deno_isolate_init(), extensions, compression_cb: None, with_runtime_cb: None, @@ -483,10 +484,13 @@ fn main() { let compiler_snapshot_path = o.join("COMPILER_SNAPSHOT.bin"); ts::create_compiler_snapshot(compiler_snapshot_path, &c); - let cli_snapshot_path = o.join("CLI_SNAPSHOT.bin"); - let output = create_cli_snapshot(cli_snapshot_path); - for path in output.files_loaded_during_snapshot { - println!("cargo:rerun-if-changed={}", path.display()) + #[cfg(not(feature = "__runtime_js_sources"))] + { + let cli_snapshot_path = o.join("CLI_SNAPSHOT.bin"); + let output = create_cli_snapshot(cli_snapshot_path); + for path in output.files_loaded_during_snapshot { + println!("cargo:rerun-if-changed={}", path.display()) + } } #[cfg(target_os = "windows")] diff --git a/cli/js.rs b/cli/js.rs index 6a312a2066..f87bf6d732 100644 --- a/cli/js.rs +++ b/cli/js.rs @@ -3,12 +3,20 @@ use deno_core::Snapshot; use log::debug; +#[cfg(not(feature = "__runtime_js_sources"))] static CLI_SNAPSHOT: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/CLI_SNAPSHOT.bin")); -pub fn deno_isolate_init() -> Snapshot { +pub fn deno_isolate_init() -> Option { debug!("Deno isolate init with snapshots."); - Snapshot::Static(CLI_SNAPSHOT) + #[cfg(not(feature = "__runtime_js_sources"))] + { + Some(Snapshot::Static(CLI_SNAPSHOT)) + } + #[cfg(feature = "__runtime_js_sources")] + { + None + } } #[cfg(test)] @@ -18,7 +26,7 @@ mod tests { #[test] fn runtime_snapshot() { let mut js_runtime = deno_core::JsRuntime::new(deno_core::RuntimeOptions { - startup_snapshot: Some(deno_isolate_init()), + startup_snapshot: deno_isolate_init(), ..Default::default() }); js_runtime diff --git a/cli/ops/mod.rs b/cli/ops/mod.rs index 5066c44b9f..7af5f14af5 100644 --- a/cli/ops/mod.rs +++ b/cli/ops/mod.rs @@ -12,17 +12,38 @@ pub mod bench; pub mod testing; pub fn cli_exts(npm_resolver: Arc) -> Vec { - vec![deno_cli::init_ops(npm_resolver)] + vec![ + #[cfg(not(feature = "__runtime_js_sources"))] + cli::init_ops(npm_resolver), + #[cfg(feature = "__runtime_js_sources")] + cli::init_ops_and_esm(npm_resolver), + ] } -deno_core::extension!(deno_cli, +// ESM parts duplicated in `../build.rs`. Keep in sync! +deno_core::extension!(cli, + deps = [runtime], ops = [op_npm_process_state], + esm_entry_point = "ext:cli/99_main.js", + esm = [ + dir "js", + "40_testing.js", + "99_main.js" + ], options = { npm_resolver: Arc, }, state = |state, options| { state.put(options.npm_resolver); }, + customizer = |ext: &mut deno_core::Extension| { + ext.esm_files.to_mut().push(deno_core::ExtensionFileSource { + specifier: "ext:cli/runtime/js/99_main.js", + code: deno_core::ExtensionFileSourceCode::LoadedFromFsDuringSnapshot( + deno_runtime::js::PATH_FOR_99_MAIN_JS, + ), + }); + }, ); #[op] diff --git a/cli/worker.rs b/cli/worker.rs index 235e9a225c..a712dc9c64 100644 --- a/cli/worker.rs +++ b/cli/worker.rs @@ -450,7 +450,7 @@ impl CliMainWorkerFactory { inspect: shared.options.is_inspecting, }, extensions, - startup_snapshot: Some(crate::js::deno_isolate_init()), + startup_snapshot: crate::js::deno_isolate_init(), create_params: None, unsafely_ignore_certificate_errors: shared .options @@ -638,7 +638,7 @@ fn create_web_worker_callback( inspect: shared.options.is_inspecting, }, extensions, - startup_snapshot: Some(crate::js::deno_isolate_init()), + startup_snapshot: crate::js::deno_isolate_init(), unsafely_ignore_certificate_errors: shared .options .unsafely_ignore_certificate_errors @@ -688,7 +688,7 @@ mod tests { let permissions = PermissionsContainer::new(Permissions::default()); let options = WorkerOptions { - startup_snapshot: Some(crate::js::deno_isolate_init()), + startup_snapshot: crate::js::deno_isolate_init(), ..Default::default() }; diff --git a/ext/node/build.rs b/ext/node/build.rs new file mode 100644 index 0000000000..778f2da17b --- /dev/null +++ b/ext/node/build.rs @@ -0,0 +1,7 @@ +// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. + +use std::env; + +fn main() { + println!("cargo:rustc-env=TARGET={}", env::var("TARGET").unwrap()); +} diff --git a/ext/node/lib.rs b/ext/node/lib.rs index 40330dc5b0..e2643a84fa 100644 --- a/ext/node/lib.rs +++ b/ext/node/lib.rs @@ -132,12 +132,7 @@ pub static NODE_ENV_VAR_ALLOWLIST: Lazy> = Lazy::new(|| { #[op] fn op_node_build_os() -> String { - std::env::var("TARGET") - .unwrap() - .split('-') - .nth(2) - .unwrap() - .to_string() + env!("TARGET").split('-').nth(2).unwrap().to_string() } #[op(fast)] diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index 4850a52559..a7463920a2 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -23,6 +23,9 @@ snapshot_from_snapshot = [] include_js_files_for_snapshotting = [ "deno_core/include_js_files_for_snapshotting", ] +# A dev feature to disable creations and loading of snapshots in favor of +# loading JS sources at runtime. +__runtime_js_sources = ["dont_create_runtime_snapshot"] [lib] name = "deno_runtime" @@ -64,6 +67,7 @@ winres.workspace = true winapi.workspace = true [dependencies] +deno_ast.workspace = true deno_broadcast_channel.workspace = true deno_cache.workspace = true deno_console.workspace = true diff --git a/runtime/build.rs b/runtime/build.rs index 64ef246dc8..56f9d611ac 100644 --- a/runtime/build.rs +++ b/runtime/build.rs @@ -21,6 +21,7 @@ mod startup_snapshot { use deno_http::DefaultHttpPropertyExtractor; use std::path::Path; + // Duplicated in `worker.rs`. Keep in sync! fn maybe_transpile_source( source: &mut ExtensionFileSource, ) -> Result<(), AnyError> { @@ -240,6 +241,7 @@ mod startup_snapshot { } } + // Duplicated in `worker.rs`. Keep in sync! deno_core::extension!(runtime, deps = [ deno_webidl, diff --git a/runtime/js.rs b/runtime/js.rs index def2724ce3..f942493a3a 100644 --- a/runtime/js.rs +++ b/runtime/js.rs @@ -1,17 +1,21 @@ // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. -#[cfg(not(feature = "dont_create_runtime_snapshot"))] use deno_core::Snapshot; -#[cfg(not(feature = "dont_create_runtime_snapshot"))] use log::debug; #[cfg(not(feature = "dont_create_runtime_snapshot"))] static RUNTIME_SNAPSHOT: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/RUNTIME_SNAPSHOT.bin")); -#[cfg(not(feature = "dont_create_runtime_snapshot"))] -pub fn deno_isolate_init() -> Snapshot { +pub fn deno_isolate_init() -> Option { debug!("Deno isolate init with snapshots."); - Snapshot::Static(RUNTIME_SNAPSHOT) + #[cfg(not(feature = "dont_create_runtime_snapshot"))] + { + Some(Snapshot::Static(RUNTIME_SNAPSHOT)) + } + #[cfg(feature = "dont_create_runtime_snapshot")] + { + None + } } #[cfg(not(feature = "include_js_files_for_snapshotting"))] diff --git a/runtime/lib.rs b/runtime/lib.rs index 1e307f492a..248ef94dea 100644 --- a/runtime/lib.rs +++ b/runtime/lib.rs @@ -34,5 +34,6 @@ pub mod web_worker; pub mod worker; mod worker_bootstrap; +pub use worker::runtime; pub use worker_bootstrap::BootstrapOptions; pub use worker_bootstrap::WorkerLogLevel; diff --git a/runtime/web_worker.rs b/runtime/web_worker.rs index af1ae19e0e..a3b93836c3 100644 --- a/runtime/web_worker.rs +++ b/runtime/web_worker.rs @@ -4,6 +4,7 @@ use crate::inspector_server::InspectorServer; use crate::ops; use crate::permissions::PermissionsContainer; use crate::tokio_util::create_and_run_current_thread; +use crate::worker::runtime; use crate::worker::FormatJsErrorFn; use crate::BootstrapOptions; use deno_broadcast_channel::InMemoryBroadcastChannel; @@ -397,16 +398,17 @@ impl WebWorker { // NOTE(bartlomieju): ordering is important here, keep it in sync with // `runtime/build.rs`, `runtime/worker.rs` and `cli/build.rs`! - let mut extensions: Vec = vec![ + + let mut extensions = vec![ // Web APIs - deno_webidl::deno_webidl::init_ops(), - deno_console::deno_console::init_ops(), - deno_url::deno_url::init_ops(), - deno_web::deno_web::init_ops::( + deno_webidl::deno_webidl::init_ops_and_esm(), + deno_console::deno_console::init_ops_and_esm(), + deno_url::deno_url::init_ops_and_esm(), + deno_web::deno_web::init_ops_and_esm::( options.blob_store.clone(), Some(main_module.clone()), ), - deno_fetch::deno_fetch::init_ops::( + deno_fetch::deno_fetch::init_ops_and_esm::( deno_fetch::Options { user_agent: options.bootstrap.user_agent.clone(), root_cert_store_provider: options.root_cert_store_provider.clone(), @@ -417,73 +419,89 @@ impl WebWorker { ..Default::default() }, ), - deno_cache::deno_cache::init_ops::(create_cache), - deno_websocket::deno_websocket::init_ops::( + deno_cache::deno_cache::init_ops_and_esm::( + create_cache, + ), + deno_websocket::deno_websocket::init_ops_and_esm::( options.bootstrap.user_agent.clone(), options.root_cert_store_provider.clone(), options.unsafely_ignore_certificate_errors.clone(), ), - deno_webstorage::deno_webstorage::init_ops(None).disable(), - deno_crypto::deno_crypto::init_ops(options.seed), - deno_broadcast_channel::deno_broadcast_channel::init_ops( + deno_webstorage::deno_webstorage::init_ops_and_esm(None).disable(), + deno_crypto::deno_crypto::init_ops_and_esm(options.seed), + deno_broadcast_channel::deno_broadcast_channel::init_ops_and_esm( options.broadcast_channel.clone(), unstable, ), - deno_ffi::deno_ffi::init_ops::(unstable), - deno_net::deno_net::init_ops::( + deno_ffi::deno_ffi::init_ops_and_esm::(unstable), + deno_net::deno_net::init_ops_and_esm::( options.root_cert_store_provider.clone(), unstable, options.unsafely_ignore_certificate_errors.clone(), ), - deno_tls::deno_tls::init_ops(), - deno_kv::deno_kv::init_ops( + deno_tls::deno_tls::init_ops_and_esm(), + deno_kv::deno_kv::init_ops_and_esm( SqliteDbHandler::::new(None), unstable, ), - deno_napi::deno_napi::init_ops::(), - deno_http::deno_http::init_ops::(), - deno_io::deno_io::init_ops(Some(options.stdio)), - deno_fs::deno_fs::init_ops::( + deno_napi::deno_napi::init_ops_and_esm::(), + deno_http::deno_http::init_ops_and_esm::(), + deno_io::deno_io::init_ops_and_esm(Some(options.stdio)), + deno_fs::deno_fs::init_ops_and_esm::( unstable, options.fs.clone(), ), - deno_node::deno_node::init_ops::( + deno_node::deno_node::init_ops_and_esm::( options.npm_resolver, options.fs, ), // Runtime ops that are always initialized for WebWorkers - ops::web_worker::deno_web_worker::init_ops(), - ops::runtime::deno_runtime::init_ops(main_module.clone()), - ops::worker_host::deno_worker_host::init_ops( + ops::web_worker::deno_web_worker::init_ops_and_esm(), + ops::runtime::deno_runtime::init_ops_and_esm(main_module.clone()), + ops::worker_host::deno_worker_host::init_ops_and_esm( options.create_web_worker_cb.clone(), options.preload_module_cb.clone(), options.pre_execute_module_cb.clone(), options.format_js_error_fn.clone(), ), - ops::fs_events::deno_fs_events::init_ops(), - ops::os::deno_os_worker::init_ops(), - ops::permissions::deno_permissions::init_ops(), - ops::process::deno_process::init_ops(), - ops::signal::deno_signal::init_ops(), - ops::tty::deno_tty::init_ops(), - ops::http::deno_http_runtime::init_ops(), - deno_permissions_web_worker::init_ops( + ops::fs_events::deno_fs_events::init_ops_and_esm(), + ops::os::deno_os_worker::init_ops_and_esm(), + ops::permissions::deno_permissions::init_ops_and_esm(), + ops::process::deno_process::init_ops_and_esm(), + ops::signal::deno_signal::init_ops_and_esm(), + ops::tty::deno_tty::init_ops_and_esm(), + ops::http::deno_http_runtime::init_ops_and_esm(), + deno_permissions_web_worker::init_ops_and_esm( permissions, unstable, enable_testing_features, ), + runtime::init_ops_and_esm(), ]; - // Append exts + for extension in &mut extensions { + #[cfg(not(feature = "__runtime_js_sources"))] + { + extension.js_files = std::borrow::Cow::Borrowed(&[]); + extension.esm_files = std::borrow::Cow::Borrowed(&[]); + extension.esm_entry_point = None; + } + #[cfg(feature = "__runtime_js_sources")] + { + use crate::worker::maybe_transpile_source; + for source in extension.esm_files.to_mut() { + maybe_transpile_source(source).unwrap(); + } + for source in extension.js_files.to_mut() { + maybe_transpile_source(source).unwrap(); + } + } + } + extensions.extend(std::mem::take(&mut options.extensions)); - #[cfg(not(feature = "dont_create_runtime_snapshot"))] - let startup_snapshot = options - .startup_snapshot - .unwrap_or_else(crate::js::deno_isolate_init); - #[cfg(feature = "dont_create_runtime_snapshot")] - let startup_snapshot = options.startup_snapshot - .expect("deno_runtime startup snapshot is not available with 'create_runtime_snapshot' Cargo feature."); + #[cfg(all(feature = "include_js_files_for_snapshotting", feature = "dont_create_runtime_snapshot", not(feature = "__runtime_js_sources")))] + options.startup_snapshot.as_ref().expect("Sources are not embedded, snapshotting was disabled and a user snapshot was not provided."); // Clear extension modules from the module map, except preserve `node:*` // modules as `node:` specifiers. @@ -492,7 +510,9 @@ impl WebWorker { let mut js_runtime = JsRuntime::new(RuntimeOptions { module_loader: Some(options.module_loader.clone()), - startup_snapshot: Some(startup_snapshot), + startup_snapshot: options + .startup_snapshot + .or_else(crate::js::deno_isolate_init), source_map_getter: options.source_map_getter, get_error_class_fn: options.get_error_class_fn, shared_array_buffer_store: options.shared_array_buffer_store.clone(), diff --git a/runtime/worker.rs b/runtime/worker.rs index 5ce75cf718..060f5537bd 100644 --- a/runtime/worker.rs +++ b/runtime/worker.rs @@ -18,6 +18,8 @@ use deno_core::futures::Future; use deno_core::v8; use deno_core::CompiledWasmModuleStore; use deno_core::Extension; +#[cfg(feature = "__runtime_js_sources")] +use deno_core::ExtensionFileSource; use deno_core::FsModuleLoader; use deno_core::GetErrorClassFn; use deno_core::JsRuntime; @@ -59,6 +61,78 @@ impl ExitCode { } } +// Duplicated in `build.rs`. Keep in sync! +deno_core::extension!( + runtime, + esm_entry_point = "ext:runtime/90_deno_ns.js", + esm = [ + dir "js", + "01_errors.js", + "01_version.ts", + "06_util.js", + "10_permissions.js", + "11_workers.js", + "13_buffer.js", + "30_os.js", + "40_fs_events.js", + "40_http.js", + "40_process.js", + "40_signals.js", + "40_tty.js", + "41_prompt.js", + "90_deno_ns.js", + "98_global_scope.js" + ], +); + +// Duplicated in `build.rs`. Keep in sync! +#[cfg(feature = "__runtime_js_sources")] +pub fn maybe_transpile_source( + source: &mut ExtensionFileSource, +) -> Result<(), AnyError> { + use deno_ast::MediaType; + use deno_ast::ParseParams; + use deno_ast::SourceTextInfo; + use deno_core::ExtensionFileSourceCode; + use std::path::Path; + + // Always transpile `node:` built-in modules, since they might be TypeScript. + let media_type = if source.specifier.starts_with("node:") { + MediaType::TypeScript + } else { + MediaType::from_path(Path::new(&source.specifier)) + }; + + match media_type { + MediaType::TypeScript => {} + MediaType::JavaScript => return Ok(()), + MediaType::Mjs => return Ok(()), + _ => panic!( + "Unsupported media type for snapshotting {media_type:?} for file {}", + source.specifier + ), + } + let code = source.load()?; + + let parsed = deno_ast::parse_module(ParseParams { + specifier: source.specifier.to_string(), + text_info: SourceTextInfo::from_string(code.as_str().to_owned()), + media_type, + capture_tokens: false, + scope_analysis: false, + maybe_syntax: None, + })?; + let transpiled_source = parsed.transpile(&deno_ast::EmitOptions { + imports_not_used_as_values: deno_ast::ImportsNotUsedAsValues::Remove, + inline_source_map: false, + ..Default::default() + })?; + + source.code = + ExtensionFileSourceCode::Computed(transpiled_source.text.into()); + Ok(()) +} + /// This worker is created and used by almost all /// subcommands in Deno executable. /// @@ -226,14 +300,14 @@ impl MainWorker { // `runtime/build.rs`, `runtime/web_worker.rs` and `cli/build.rs`! let mut extensions = vec![ // Web APIs - deno_webidl::deno_webidl::init_ops(), - deno_console::deno_console::init_ops(), - deno_url::deno_url::init_ops(), - deno_web::deno_web::init_ops::( + deno_webidl::deno_webidl::init_ops_and_esm(), + deno_console::deno_console::init_ops_and_esm(), + deno_url::deno_url::init_ops_and_esm(), + deno_web::deno_web::init_ops_and_esm::( options.blob_store.clone(), options.bootstrap.location.clone(), ), - deno_fetch::deno_fetch::init_ops::( + deno_fetch::deno_fetch::init_ops_and_esm::( deno_fetch::Options { user_agent: options.bootstrap.user_agent.clone(), root_cert_store_provider: options.root_cert_store_provider.clone(), @@ -244,75 +318,91 @@ impl MainWorker { ..Default::default() }, ), - deno_cache::deno_cache::init_ops::(create_cache), - deno_websocket::deno_websocket::init_ops::( + deno_cache::deno_cache::init_ops_and_esm::( + create_cache, + ), + deno_websocket::deno_websocket::init_ops_and_esm::( options.bootstrap.user_agent.clone(), options.root_cert_store_provider.clone(), options.unsafely_ignore_certificate_errors.clone(), ), - deno_webstorage::deno_webstorage::init_ops( + deno_webstorage::deno_webstorage::init_ops_and_esm( options.origin_storage_dir.clone(), ), - deno_crypto::deno_crypto::init_ops(options.seed), - deno_broadcast_channel::deno_broadcast_channel::init_ops( + deno_crypto::deno_crypto::init_ops_and_esm(options.seed), + deno_broadcast_channel::deno_broadcast_channel::init_ops_and_esm( options.broadcast_channel.clone(), unstable, ), - deno_ffi::deno_ffi::init_ops::(unstable), - deno_net::deno_net::init_ops::( + deno_ffi::deno_ffi::init_ops_and_esm::(unstable), + deno_net::deno_net::init_ops_and_esm::( options.root_cert_store_provider.clone(), unstable, options.unsafely_ignore_certificate_errors.clone(), ), - deno_tls::deno_tls::init_ops(), - deno_kv::deno_kv::init_ops( + deno_tls::deno_tls::init_ops_and_esm(), + deno_kv::deno_kv::init_ops_and_esm( SqliteDbHandler::::new( options.origin_storage_dir.clone(), ), unstable, ), - deno_napi::deno_napi::init_ops::(), - deno_http::deno_http::init_ops::(), - deno_io::deno_io::init_ops(Some(options.stdio)), - deno_fs::deno_fs::init_ops::( + deno_napi::deno_napi::init_ops_and_esm::(), + deno_http::deno_http::init_ops_and_esm::(), + deno_io::deno_io::init_ops_and_esm(Some(options.stdio)), + deno_fs::deno_fs::init_ops_and_esm::( unstable, options.fs.clone(), ), - deno_node::deno_node::init_ops::( + deno_node::deno_node::init_ops_and_esm::( options.npm_resolver, options.fs, ), // Ops from this crate - ops::runtime::deno_runtime::init_ops(main_module.clone()), - ops::worker_host::deno_worker_host::init_ops( + ops::runtime::deno_runtime::init_ops_and_esm(main_module.clone()), + ops::worker_host::deno_worker_host::init_ops_and_esm( options.create_web_worker_cb.clone(), options.web_worker_preload_module_cb.clone(), options.web_worker_pre_execute_module_cb.clone(), options.format_js_error_fn.clone(), ), - ops::fs_events::deno_fs_events::init_ops(), - ops::os::deno_os::init_ops(exit_code.clone()), - ops::permissions::deno_permissions::init_ops(), - ops::process::deno_process::init_ops(), - ops::signal::deno_signal::init_ops(), - ops::tty::deno_tty::init_ops(), - ops::http::deno_http_runtime::init_ops(), - deno_permissions_worker::init_ops( + ops::fs_events::deno_fs_events::init_ops_and_esm(), + ops::os::deno_os::init_ops_and_esm(exit_code.clone()), + ops::permissions::deno_permissions::init_ops_and_esm(), + ops::process::deno_process::init_ops_and_esm(), + ops::signal::deno_signal::init_ops_and_esm(), + ops::tty::deno_tty::init_ops_and_esm(), + ops::http::deno_http_runtime::init_ops_and_esm(), + deno_permissions_worker::init_ops_and_esm( permissions, unstable, enable_testing_features, ), + runtime::init_ops_and_esm(), ]; + for extension in &mut extensions { + #[cfg(not(feature = "__runtime_js_sources"))] + { + extension.js_files = std::borrow::Cow::Borrowed(&[]); + extension.esm_files = std::borrow::Cow::Borrowed(&[]); + extension.esm_entry_point = None; + } + #[cfg(feature = "__runtime_js_sources")] + { + for source in extension.esm_files.to_mut() { + maybe_transpile_source(source).unwrap(); + } + for source in extension.js_files.to_mut() { + maybe_transpile_source(source).unwrap(); + } + } + } + extensions.extend(std::mem::take(&mut options.extensions)); - #[cfg(not(feature = "dont_create_runtime_snapshot"))] - let startup_snapshot = options - .startup_snapshot - .unwrap_or_else(crate::js::deno_isolate_init); - #[cfg(feature = "dont_create_runtime_snapshot")] - let startup_snapshot = options.startup_snapshot - .expect("deno_runtime startup snapshot is not available with 'create_runtime_snapshot' Cargo feature."); + #[cfg(all(feature = "include_js_files_for_snapshotting", feature = "dont_create_runtime_snapshot", not(feature = "__runtime_js_sources")))] + options.startup_snapshot.as_ref().expect("Sources are not embedded, snapshotting was disabled and a user snapshot was not provided."); // Clear extension modules from the module map, except preserve `node:*` // modules. @@ -321,7 +411,9 @@ impl MainWorker { let mut js_runtime = JsRuntime::new(RuntimeOptions { module_loader: Some(options.module_loader.clone()), - startup_snapshot: Some(startup_snapshot), + startup_snapshot: options + .startup_snapshot + .or_else(crate::js::deno_isolate_init), create_params: options.create_params, source_map_getter: options.source_map_getter, get_error_class_fn: options.get_error_class_fn,