1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-11-28 16:20:57 -05:00

refactor(cli): use CliMainWorker in standalone (#18880)

Uses `CliMainWorker` in all the cli code.
This commit is contained in:
David Sherret 2023-05-01 08:59:38 -04:00 committed by GitHub
parent 89160e7cd8
commit 94a148cdb6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 308 additions and 351 deletions

View file

@ -1202,6 +1202,11 @@ impl StorageKeyResolver {
}) })
} }
/// Creates a storage key resolver that will always resolve to being empty.
pub fn empty() -> Self {
Self(Some(None))
}
/// Resolves the storage key to use based on the current flags, config, or main module. /// Resolves the storage key to use based on the current flags, config, or main module.
pub fn resolve_storage_key( pub fn resolve_storage_key(
&self, &self,
@ -1397,5 +1402,9 @@ mod test {
resolver.resolve_storage_key(&specifier), resolver.resolve_storage_key(&specifier),
Some("value".to_string()) Some("value".to_string())
); );
// test empty
let resolver = StorageKeyResolver::empty();
assert_eq!(resolver.resolve_storage_key(&specifier), None);
} }
} }

View file

@ -20,6 +20,7 @@ use crate::tools::check::TypeChecker;
use crate::util::progress_bar::ProgressBar; use crate::util::progress_bar::ProgressBar;
use crate::util::text_encoding::code_without_source_map; use crate::util::text_encoding::code_without_source_map;
use crate::util::text_encoding::source_map_from_code; use crate::util::text_encoding::source_map_from_code;
use crate::worker::ModuleLoaderFactory;
use deno_ast::MediaType; use deno_ast::MediaType;
use deno_core::anyhow::anyhow; use deno_core::anyhow::anyhow;
@ -223,102 +224,14 @@ pub struct ModuleCodeSource {
pub media_type: MediaType, pub media_type: MediaType,
} }
struct SharedCliModuleLoaderState { struct PreparedModuleLoader {
lib_window: TsTypeLib,
lib_worker: TsTypeLib,
is_inspecting: bool,
is_repl: bool,
emitter: Arc<Emitter>, emitter: Arc<Emitter>,
graph_container: Arc<ModuleGraphContainer>, graph_container: Arc<ModuleGraphContainer>,
module_load_preparer: Arc<ModuleLoadPreparer>,
parsed_source_cache: Arc<ParsedSourceCache>, parsed_source_cache: Arc<ParsedSourceCache>,
resolver: Arc<CliGraphResolver>,
npm_module_loader: NpmModuleLoader,
} }
pub struct CliModuleLoaderFactory { impl PreparedModuleLoader {
state: Arc<SharedCliModuleLoaderState>, pub fn load_prepared_module(
}
impl CliModuleLoaderFactory {
pub fn new(
options: &CliOptions,
emitter: Arc<Emitter>,
graph_container: Arc<ModuleGraphContainer>,
module_load_preparer: Arc<ModuleLoadPreparer>,
parsed_source_cache: Arc<ParsedSourceCache>,
resolver: Arc<CliGraphResolver>,
npm_module_loader: NpmModuleLoader,
) -> Self {
Self {
state: Arc::new(SharedCliModuleLoaderState {
lib_window: options.ts_type_lib_window(),
lib_worker: options.ts_type_lib_worker(),
is_inspecting: options.is_inspecting(),
is_repl: matches!(options.sub_command(), DenoSubcommand::Repl(_)),
emitter,
graph_container,
module_load_preparer,
parsed_source_cache,
resolver,
npm_module_loader,
}),
}
}
pub fn create_for_main(
&self,
root_permissions: PermissionsContainer,
dynamic_permissions: PermissionsContainer,
) -> CliModuleLoader {
self.create_with_lib(
self.state.lib_window,
root_permissions,
dynamic_permissions,
)
}
pub fn create_for_worker(
&self,
root_permissions: PermissionsContainer,
dynamic_permissions: PermissionsContainer,
) -> CliModuleLoader {
self.create_with_lib(
self.state.lib_worker,
root_permissions,
dynamic_permissions,
)
}
fn create_with_lib(
&self,
lib: TsTypeLib,
root_permissions: PermissionsContainer,
dynamic_permissions: PermissionsContainer,
) -> CliModuleLoader {
CliModuleLoader {
lib,
root_permissions,
dynamic_permissions,
shared: self.state.clone(),
}
}
}
pub struct CliModuleLoader {
lib: TsTypeLib,
/// The initial set of permissions used to resolve the static imports in the
/// worker. These are "allow all" for main worker, and parent thread
/// permissions for Web Worker.
root_permissions: PermissionsContainer,
/// Permissions used to resolve dynamic imports, these get passed as
/// "root permissions" for Web Worker.
dynamic_permissions: PermissionsContainer,
shared: Arc<SharedCliModuleLoaderState>,
}
impl CliModuleLoader {
fn load_prepared_module(
&self, &self,
specifier: &ModuleSpecifier, specifier: &ModuleSpecifier,
maybe_referrer: Option<&ModuleSpecifier>, maybe_referrer: Option<&ModuleSpecifier>,
@ -327,7 +240,7 @@ impl CliModuleLoader {
unreachable!(); // Node built-in modules should be handled internally. unreachable!(); // Node built-in modules should be handled internally.
} }
let graph = self.shared.graph_container.graph(); let graph = self.graph_container.graph();
match graph.get(specifier) { match graph.get(specifier) {
Some(deno_graph::Module::Json(JsonModule { Some(deno_graph::Module::Json(JsonModule {
source, source,
@ -360,11 +273,9 @@ impl CliModuleLoader {
| MediaType::Jsx | MediaType::Jsx
| MediaType::Tsx => { | MediaType::Tsx => {
// get emit text // get emit text
self.shared.emitter.emit_parsed_source( self
specifier, .emitter
*media_type, .emit_parsed_source(specifier, *media_type, source)?
source,
)?
} }
MediaType::TsBuildInfo | MediaType::Wasm | MediaType::SourceMap => { MediaType::TsBuildInfo | MediaType::Wasm | MediaType::SourceMap => {
panic!("Unexpected media type {media_type} for {specifier}") panic!("Unexpected media type {media_type} for {specifier}")
@ -372,7 +283,7 @@ impl CliModuleLoader {
}; };
// at this point, we no longer need the parsed source in memory, so free it // at this point, we no longer need the parsed source in memory, so free it
self.shared.parsed_source_cache.free(specifier); self.parsed_source_cache.free(specifier);
Ok(ModuleCodeSource { Ok(ModuleCodeSource {
code, code,
@ -389,7 +300,113 @@ impl CliModuleLoader {
} }
} }
} }
}
struct SharedCliModuleLoaderState {
lib_window: TsTypeLib,
lib_worker: TsTypeLib,
is_inspecting: bool,
is_repl: bool,
graph_container: Arc<ModuleGraphContainer>,
module_load_preparer: Arc<ModuleLoadPreparer>,
prepared_module_loader: PreparedModuleLoader,
resolver: Arc<CliGraphResolver>,
npm_module_loader: NpmModuleLoader,
}
pub struct CliModuleLoaderFactory {
shared: Arc<SharedCliModuleLoaderState>,
}
impl CliModuleLoaderFactory {
pub fn new(
options: &CliOptions,
emitter: Arc<Emitter>,
graph_container: Arc<ModuleGraphContainer>,
module_load_preparer: Arc<ModuleLoadPreparer>,
parsed_source_cache: Arc<ParsedSourceCache>,
resolver: Arc<CliGraphResolver>,
npm_module_loader: NpmModuleLoader,
) -> Self {
Self {
shared: Arc::new(SharedCliModuleLoaderState {
lib_window: options.ts_type_lib_window(),
lib_worker: options.ts_type_lib_worker(),
is_inspecting: options.is_inspecting(),
is_repl: matches!(options.sub_command(), DenoSubcommand::Repl(_)),
prepared_module_loader: PreparedModuleLoader {
emitter,
graph_container: graph_container.clone(),
parsed_source_cache,
},
graph_container,
module_load_preparer,
resolver,
npm_module_loader,
}),
}
}
fn create_with_lib(
&self,
lib: TsTypeLib,
root_permissions: PermissionsContainer,
dynamic_permissions: PermissionsContainer,
) -> Rc<dyn ModuleLoader> {
Rc::new(CliModuleLoader {
lib,
root_permissions,
dynamic_permissions,
shared: self.shared.clone(),
})
}
}
impl ModuleLoaderFactory for CliModuleLoaderFactory {
fn create_for_main(
&self,
root_permissions: PermissionsContainer,
dynamic_permissions: PermissionsContainer,
) -> Rc<dyn ModuleLoader> {
self.create_with_lib(
self.shared.lib_window,
root_permissions,
dynamic_permissions,
)
}
fn create_for_worker(
&self,
root_permissions: PermissionsContainer,
dynamic_permissions: PermissionsContainer,
) -> Rc<dyn ModuleLoader> {
self.create_with_lib(
self.shared.lib_worker,
root_permissions,
dynamic_permissions,
)
}
fn create_source_map_getter(&self) -> Option<Box<dyn SourceMapGetter>> {
Some(Box::new(CliSourceMapGetter {
shared: self.shared.clone(),
}))
}
}
struct CliModuleLoader {
lib: TsTypeLib,
/// The initial set of permissions used to resolve the static imports in the
/// worker. These are "allow all" for main worker, and parent thread
/// permissions for Web Worker.
root_permissions: PermissionsContainer,
/// Permissions used to resolve dynamic imports, these get passed as
/// "root permissions" for Web Worker.
dynamic_permissions: PermissionsContainer,
shared: Arc<SharedCliModuleLoaderState>,
}
impl CliModuleLoader {
fn load_sync( fn load_sync(
&self, &self,
specifier: &ModuleSpecifier, specifier: &ModuleSpecifier,
@ -409,7 +426,10 @@ impl CliModuleLoader {
)? { )? {
code_source code_source
} else { } else {
self.load_prepared_module(specifier, maybe_referrer)? self
.shared
.prepared_module_loader
.load_prepared_module(specifier, maybe_referrer)?
}; };
let code = if self.shared.is_inspecting { let code = if self.shared.is_inspecting {
// we need the code with the source map in order for // we need the code with the source map in order for
@ -584,7 +604,11 @@ impl ModuleLoader for CliModuleLoader {
} }
} }
impl SourceMapGetter for CliModuleLoader { struct CliSourceMapGetter {
shared: Arc<SharedCliModuleLoaderState>,
}
impl SourceMapGetter for CliSourceMapGetter {
fn get_source_map(&self, file_name: &str) -> Option<Vec<u8>> { fn get_source_map(&self, file_name: &str) -> Option<Vec<u8>> {
let specifier = resolve_url(file_name).ok()?; let specifier = resolve_url(file_name).ok()?;
match specifier.scheme() { match specifier.scheme() {
@ -593,7 +617,11 @@ impl SourceMapGetter for CliModuleLoader {
"wasm" | "file" | "http" | "https" | "data" | "blob" => (), "wasm" | "file" | "http" | "https" | "data" | "blob" => (),
_ => return None, _ => return None,
} }
let source = self.load_prepared_module(&specifier, None).ok()?; let source = self
.shared
.prepared_module_loader
.load_prepared_module(&specifier, None)
.ok()?;
source_map_from_code(&source.code) source_map_from_code(&source.code)
} }

View file

@ -34,6 +34,7 @@ use crate::util::progress_bar::ProgressBar;
use crate::util::progress_bar::ProgressBarStyle; use crate::util::progress_bar::ProgressBarStyle;
use crate::worker::CliMainWorkerFactory; use crate::worker::CliMainWorkerFactory;
use crate::worker::CliMainWorkerOptions; use crate::worker::CliMainWorkerOptions;
use crate::worker::HasNodeSpecifierChecker;
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::parking_lot::Mutex; use deno_core::parking_lot::Mutex;
@ -334,9 +335,9 @@ impl ProcState {
StorageKeyResolver::from_options(&self.options), StorageKeyResolver::from_options(&self.options),
self.npm_resolver.clone(), self.npm_resolver.clone(),
self.node_resolver.clone(), self.node_resolver.clone(),
self.graph_container.clone(), Box::new(CliHasNodeSpecifierChecker(self.graph_container.clone())),
self.blob_store.clone(), self.blob_store.clone(),
CliModuleLoaderFactory::new( Box::new(CliModuleLoaderFactory::new(
&self.options, &self.options,
self.emitter.clone(), self.emitter.clone(),
self.graph_container.clone(), self.graph_container.clone(),
@ -348,7 +349,7 @@ impl ProcState {
self.node_code_translator.clone(), self.node_code_translator.clone(),
self.node_resolver.clone(), self.node_resolver.clone(),
), ),
), )),
self.root_cert_store.clone(), self.root_cert_store.clone(),
self.node_fs.clone(), self.node_fs.clone(),
self.maybe_inspector_server.clone(), self.maybe_inspector_server.clone(),
@ -383,7 +384,7 @@ impl ProcState {
} }
maybe_binary_command_name maybe_binary_command_name
}, },
origin_data_folder_path: self.dir.origin_data_folder_path(), origin_data_folder_path: Some(self.dir.origin_data_folder_path()),
seed: self.options.seed(), seed: self.options.seed(),
unsafely_ignore_certificate_errors: self unsafely_ignore_certificate_errors: self
.options .options
@ -395,6 +396,14 @@ impl ProcState {
} }
} }
struct CliHasNodeSpecifierChecker(Arc<ModuleGraphContainer>);
impl HasNodeSpecifierChecker for CliHasNodeSpecifierChecker {
fn has_node_specifier(&self) -> bool {
self.0.graph().has_node_specifier
}
}
/// Keeps track of what module specifiers were resolved as CJS. /// Keeps track of what module specifiers were resolved as CJS.
#[derive(Default)] #[derive(Default)]
pub struct CjsResolutionStore(Mutex<HashSet<ModuleSpecifier>>); pub struct CjsResolutionStore(Mutex<HashSet<ModuleSpecifier>>);

View file

@ -3,8 +3,8 @@
use crate::args::get_root_cert_store; use crate::args::get_root_cert_store;
use crate::args::CaData; use crate::args::CaData;
use crate::args::CacheSetting; use crate::args::CacheSetting;
use crate::args::StorageKeyResolver;
use crate::cache::DenoDir; use crate::cache::DenoDir;
use crate::colors;
use crate::file_fetcher::get_source_from_data_url; use crate::file_fetcher::get_source_from_data_url;
use crate::http_util::HttpClient; use crate::http_util::HttpClient;
use crate::npm::create_npm_fs_resolver; use crate::npm::create_npm_fs_resolver;
@ -12,42 +12,30 @@ use crate::npm::CliNpmRegistryApi;
use crate::npm::CliNpmResolver; use crate::npm::CliNpmResolver;
use crate::npm::NpmCache; use crate::npm::NpmCache;
use crate::npm::NpmResolution; use crate::npm::NpmResolution;
use crate::ops;
use crate::util::progress_bar::ProgressBar; use crate::util::progress_bar::ProgressBar;
use crate::util::progress_bar::ProgressBarStyle; use crate::util::progress_bar::ProgressBarStyle;
use crate::util::v8::construct_v8_flags; use crate::util::v8::construct_v8_flags;
use crate::version; use crate::worker::CliMainWorkerFactory;
use crate::worker::CliMainWorkerOptions;
use crate::worker::HasNodeSpecifierChecker;
use crate::worker::ModuleLoaderFactory;
use crate::CliGraphResolver; use crate::CliGraphResolver;
use deno_core::anyhow::Context; use deno_core::anyhow::Context;
use deno_core::error::type_error; use deno_core::error::type_error;
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::futures::task::LocalFutureObj;
use deno_core::futures::FutureExt; use deno_core::futures::FutureExt;
use deno_core::located_script_name;
use deno_core::v8_set_flags; use deno_core::v8_set_flags;
use deno_core::CompiledWasmModuleStore;
use deno_core::ModuleLoader; use deno_core::ModuleLoader;
use deno_core::ModuleSpecifier; use deno_core::ModuleSpecifier;
use deno_core::ModuleType; use deno_core::ModuleType;
use deno_core::ResolutionKind; use deno_core::ResolutionKind;
use deno_core::SharedArrayBufferStore;
use deno_graph::source::Resolver; use deno_graph::source::Resolver;
use deno_runtime::deno_broadcast_channel::InMemoryBroadcastChannel;
use deno_runtime::deno_node; use deno_runtime::deno_node;
use deno_runtime::deno_tls::rustls::RootCertStore; use deno_runtime::deno_node::NodeResolver;
use deno_runtime::deno_web::BlobStore; use deno_runtime::deno_web::BlobStore;
use deno_runtime::fmt_errors::format_js_error;
use deno_runtime::ops::worker_host::CreateWebWorkerCb;
use deno_runtime::ops::worker_host::WorkerEventCb;
use deno_runtime::permissions::Permissions; use deno_runtime::permissions::Permissions;
use deno_runtime::permissions::PermissionsContainer; use deno_runtime::permissions::PermissionsContainer;
use deno_runtime::web_worker::WebWorker;
use deno_runtime::web_worker::WebWorkerOptions;
use deno_runtime::worker::MainWorker;
use deno_runtime::worker::WorkerOptions;
use deno_runtime::BootstrapOptions;
use import_map::parse_from_json; use import_map::parse_from_json;
use log::Level;
use std::pin::Pin; use std::pin::Pin;
use std::rc::Rc; use std::rc::Rc;
use std::sync::Arc; use std::sync::Arc;
@ -137,95 +125,40 @@ impl ModuleLoader for EmbeddedModuleLoader {
} }
} }
fn web_worker_callback() -> Arc<WorkerEventCb> { struct StandaloneModuleLoaderFactory {
Arc::new(|worker| { loader: EmbeddedModuleLoader,
let fut = async move { Ok(worker) };
LocalFutureObj::new(Box::new(fut))
})
} }
struct SharedWorkerState { impl ModuleLoaderFactory for StandaloneModuleLoaderFactory {
npm_resolver: Arc<CliNpmResolver>, fn create_for_main(
root_cert_store: RootCertStore, &self,
node_fs: Arc<dyn deno_node::NodeFs>, _root_permissions: PermissionsContainer,
blob_store: BlobStore, _dynamic_permissions: PermissionsContainer,
broadcast_channel: InMemoryBroadcastChannel, ) -> Rc<dyn ModuleLoader> {
shared_array_buffer_store: SharedArrayBufferStore, Rc::new(self.loader.clone())
compiled_wasm_module_store: CompiledWasmModuleStore, }
// options
argv: Vec<String>, fn create_for_worker(
seed: Option<u64>, &self,
unsafely_ignore_certificate_errors: Option<Vec<String>>, _root_permissions: PermissionsContainer,
unstable: bool, _dynamic_permissions: PermissionsContainer,
) -> Rc<dyn ModuleLoader> {
Rc::new(self.loader.clone())
}
fn create_source_map_getter(
&self,
) -> Option<Box<dyn deno_core::SourceMapGetter>> {
None
}
} }
fn create_web_worker_callback( struct StandaloneHasNodeSpecifierChecker;
shared: &Arc<SharedWorkerState>,
module_loader: &EmbeddedModuleLoader,
) -> Arc<CreateWebWorkerCb> {
let shared = shared.clone();
let module_loader = module_loader.clone();
Arc::new(move |args| {
let module_loader = Rc::new(module_loader.clone());
let create_web_worker_cb = impl HasNodeSpecifierChecker for StandaloneHasNodeSpecifierChecker {
create_web_worker_callback(&shared, &module_loader); fn has_node_specifier(&self) -> bool {
let web_worker_cb = web_worker_callback(); false
}
let options = WebWorkerOptions {
bootstrap: BootstrapOptions {
args: shared.argv.clone(),
cpu_count: std::thread::available_parallelism()
.map(|p| p.get())
.unwrap_or(1),
debug_flag: false,
enable_testing_features: false,
locale: deno_core::v8::icu::get_language_tag(),
location: Some(args.main_module.clone()),
no_color: !colors::use_color(),
is_tty: colors::is_tty(),
runtime_version: version::deno().to_string(),
ts_version: version::TYPESCRIPT.to_string(),
unstable: shared.unstable,
user_agent: version::get_user_agent().to_string(),
inspect: false,
},
extensions: ops::cli_exts(shared.npm_resolver.clone()),
startup_snapshot: Some(crate::js::deno_isolate_init()),
unsafely_ignore_certificate_errors: shared
.unsafely_ignore_certificate_errors
.clone(),
root_cert_store: Some(shared.root_cert_store.clone()),
seed: shared.seed,
module_loader,
node_fs: Some(shared.node_fs.clone()),
npm_resolver: None, // not currently supported
create_web_worker_cb,
preload_module_cb: web_worker_cb.clone(),
pre_execute_module_cb: web_worker_cb,
format_js_error_fn: Some(Arc::new(format_js_error)),
source_map_getter: None,
worker_type: args.worker_type,
maybe_inspector_server: None,
get_error_class_fn: Some(&get_error_class_name),
blob_store: shared.blob_store.clone(),
broadcast_channel: shared.broadcast_channel.clone(),
shared_array_buffer_store: Some(shared.shared_array_buffer_store.clone()),
compiled_wasm_module_store: Some(
shared.compiled_wasm_module_store.clone(),
),
cache_storage_dir: None,
stdio: Default::default(),
};
WebWorker::bootstrap_from_options(
args.name,
args.permissions,
args.main_module,
args.worker_id,
options,
)
})
} }
pub async fn run( pub async fn run(
@ -273,26 +206,10 @@ pub async fn run(
npm_fs_resolver, npm_fs_resolver,
None, None,
)); ));
let node_resolver =
let shared = Arc::new(SharedWorkerState { Arc::new(NodeResolver::new(node_fs.clone(), npm_resolver.clone()));
npm_resolver, let module_loader_factory = StandaloneModuleLoaderFactory {
root_cert_store, loader: EmbeddedModuleLoader {
node_fs,
blob_store: BlobStore::default(),
broadcast_channel: InMemoryBroadcastChannel::default(),
shared_array_buffer_store: SharedArrayBufferStore::default(),
compiled_wasm_module_store: CompiledWasmModuleStore::default(),
argv: metadata.argv,
seed: metadata.seed,
unsafely_ignore_certificate_errors: metadata
.unsafely_ignore_certificate_errors,
unstable: metadata.unstable,
});
let permissions = PermissionsContainer::new(Permissions::from_options(
&metadata.permissions,
)?);
let module_loader = EmbeddedModuleLoader {
eszip: Arc::new(eszip), eszip: Arc::new(eszip),
maybe_import_map_resolver: metadata.maybe_import_map.map( maybe_import_map_resolver: metadata.maybe_import_map.map(
|(base, source)| { |(base, source)| {
@ -308,86 +225,49 @@ pub async fn run(
)) ))
}, },
), ),
},
}; };
let create_web_worker_cb =
create_web_worker_callback(&shared, &module_loader); let worker_factory = CliMainWorkerFactory::new(
let web_worker_cb = web_worker_callback(); StorageKeyResolver::empty(),
npm_resolver.clone(),
node_resolver,
Box::new(StandaloneHasNodeSpecifierChecker),
BlobStore::default(),
Box::new(module_loader_factory),
root_cert_store,
node_fs,
None,
CliMainWorkerOptions {
argv: metadata.argv,
debug: false,
coverage_dir: None,
enable_testing_features: false,
has_node_modules_dir: false,
inspect_brk: false,
inspect_wait: false,
is_inspecting: false,
is_npm_main: false,
location: metadata.location,
// todo(dsherret): support a binary command being compiled
maybe_binary_npm_command_name: None,
origin_data_folder_path: None,
seed: metadata.seed,
unsafely_ignore_certificate_errors: metadata
.unsafely_ignore_certificate_errors,
unstable: metadata.unstable,
},
);
v8_set_flags(construct_v8_flags(&metadata.v8_flags, vec![])); v8_set_flags(construct_v8_flags(&metadata.v8_flags, vec![]));
let options = WorkerOptions { let permissions = PermissionsContainer::new(Permissions::from_options(
bootstrap: BootstrapOptions { &metadata.permissions,
args: shared.argv.clone(), )?);
cpu_count: std::thread::available_parallelism() let mut worker = worker_factory
.map(|p| p.get()) .create_main_worker(main_module.clone(), permissions)
.unwrap_or(1), .await?;
debug_flag: metadata
.log_level
.map(|l| l == Level::Debug)
.unwrap_or(false),
enable_testing_features: false,
locale: deno_core::v8::icu::get_language_tag(),
location: metadata.location,
no_color: !colors::use_color(),
is_tty: colors::is_tty(),
runtime_version: version::deno().to_string(),
ts_version: version::TYPESCRIPT.to_string(),
unstable: metadata.unstable,
user_agent: version::get_user_agent().to_string(),
inspect: false,
},
extensions: ops::cli_exts(shared.npm_resolver.clone()),
startup_snapshot: Some(crate::js::deno_isolate_init()),
unsafely_ignore_certificate_errors: shared
.unsafely_ignore_certificate_errors
.clone(),
root_cert_store: Some(shared.root_cert_store.clone()),
seed: metadata.seed,
source_map_getter: None,
format_js_error_fn: Some(Arc::new(format_js_error)),
create_web_worker_cb,
web_worker_preload_module_cb: web_worker_cb.clone(),
web_worker_pre_execute_module_cb: web_worker_cb,
maybe_inspector_server: None,
should_break_on_first_statement: false,
should_wait_for_inspector_session: false,
module_loader: Rc::new(module_loader),
node_fs: Some(shared.node_fs.clone()),
npm_resolver: None, // not currently supported
get_error_class_fn: Some(&get_error_class_name),
cache_storage_dir: None,
origin_storage_dir: None,
blob_store: shared.blob_store.clone(),
broadcast_channel: shared.broadcast_channel.clone(),
shared_array_buffer_store: Some(shared.shared_array_buffer_store.clone()),
compiled_wasm_module_store: Some(shared.compiled_wasm_module_store.clone()),
stdio: Default::default(),
};
let mut worker = MainWorker::bootstrap_from_options(
main_module.clone(),
permissions,
options,
);
worker.execute_main_module(main_module).await?;
worker.dispatch_load_event(located_script_name!())?;
loop { let exit_code = worker.run().await?;
worker.run_event_loop(false).await?; std::process::exit(exit_code)
if !worker.dispatch_beforeunload_event(located_script_name!())? {
break;
}
}
worker.dispatch_unload_event(located_script_name!())?;
std::process::exit(0);
}
fn get_error_class_name(e: &AnyError) -> &'static str {
deno_runtime::errors::get_error_class_name(e).unwrap_or_else(|| {
panic!(
"Error '{}' contains boxed error of unsupported type:{}",
e,
e.chain().map(|e| format!("\n {e:?}")).collect::<String>()
);
})
} }

View file

@ -13,7 +13,9 @@ use deno_core::url::Url;
use deno_core::CompiledWasmModuleStore; use deno_core::CompiledWasmModuleStore;
use deno_core::Extension; use deno_core::Extension;
use deno_core::ModuleId; use deno_core::ModuleId;
use deno_core::ModuleLoader;
use deno_core::SharedArrayBufferStore; use deno_core::SharedArrayBufferStore;
use deno_core::SourceMapGetter;
use deno_runtime::colors; use deno_runtime::colors;
use deno_runtime::deno_broadcast_channel::InMemoryBroadcastChannel; use deno_runtime::deno_broadcast_channel::InMemoryBroadcastChannel;
use deno_runtime::deno_node; use deno_runtime::deno_node;
@ -35,8 +37,6 @@ use deno_semver::npm::NpmPackageReqReference;
use crate::args::StorageKeyResolver; use crate::args::StorageKeyResolver;
use crate::errors; use crate::errors;
use crate::graph_util::ModuleGraphContainer;
use crate::module_loader::CliModuleLoaderFactory;
use crate::npm::CliNpmResolver; use crate::npm::CliNpmResolver;
use crate::ops; use crate::ops;
use crate::tools; use crate::tools;
@ -44,6 +44,28 @@ use crate::tools::coverage::CoverageCollector;
use crate::util::checksum; use crate::util::checksum;
use crate::version; use crate::version;
pub trait ModuleLoaderFactory: Send + Sync {
fn create_for_main(
&self,
root_permissions: PermissionsContainer,
dynamic_permissions: PermissionsContainer,
) -> Rc<dyn ModuleLoader>;
fn create_for_worker(
&self,
root_permissions: PermissionsContainer,
dynamic_permissions: PermissionsContainer,
) -> Rc<dyn ModuleLoader>;
fn create_source_map_getter(&self) -> Option<Box<dyn SourceMapGetter>>;
}
// todo(dsherret): this is temporary and we should remove this
// once we no longer conditionally initialize the node runtime
pub trait HasNodeSpecifierChecker: Send + Sync {
fn has_node_specifier(&self) -> bool;
}
pub struct CliMainWorkerOptions { pub struct CliMainWorkerOptions {
pub argv: Vec<String>, pub argv: Vec<String>,
pub debug: bool, pub debug: bool,
@ -56,26 +78,34 @@ pub struct CliMainWorkerOptions {
pub is_npm_main: bool, pub is_npm_main: bool,
pub location: Option<Url>, pub location: Option<Url>,
pub maybe_binary_npm_command_name: Option<String>, pub maybe_binary_npm_command_name: Option<String>,
pub origin_data_folder_path: PathBuf, pub origin_data_folder_path: Option<PathBuf>,
pub seed: Option<u64>, pub seed: Option<u64>,
pub unsafely_ignore_certificate_errors: Option<Vec<String>>, pub unsafely_ignore_certificate_errors: Option<Vec<String>>,
pub unstable: bool, pub unstable: bool,
} }
struct SharedWorkerState { struct SharedWorkerState {
pub options: CliMainWorkerOptions, options: CliMainWorkerOptions,
pub storage_key_resolver: StorageKeyResolver, storage_key_resolver: StorageKeyResolver,
pub npm_resolver: Arc<CliNpmResolver>, npm_resolver: Arc<CliNpmResolver>,
pub node_resolver: Arc<NodeResolver>, node_resolver: Arc<NodeResolver>,
pub graph_container: Arc<ModuleGraphContainer>, has_node_specifier_checker: Box<dyn HasNodeSpecifierChecker>,
pub blob_store: BlobStore, blob_store: BlobStore,
pub broadcast_channel: InMemoryBroadcastChannel, broadcast_channel: InMemoryBroadcastChannel,
pub shared_array_buffer_store: SharedArrayBufferStore, shared_array_buffer_store: SharedArrayBufferStore,
pub compiled_wasm_module_store: CompiledWasmModuleStore, compiled_wasm_module_store: CompiledWasmModuleStore,
pub module_loader_factory: CliModuleLoaderFactory, module_loader_factory: Box<dyn ModuleLoaderFactory>,
pub root_cert_store: RootCertStore, root_cert_store: RootCertStore,
pub node_fs: Arc<dyn deno_node::NodeFs>, node_fs: Arc<dyn deno_node::NodeFs>,
pub maybe_inspector_server: Option<Arc<InspectorServer>>, maybe_inspector_server: Option<Arc<InspectorServer>>,
}
impl SharedWorkerState {
pub fn should_initialize_node_runtime(&self) -> bool {
self.npm_resolver.has_packages()
|| self.has_node_specifier_checker.has_node_specifier()
|| self.options.is_npm_main
}
} }
pub struct CliMainWorker { pub struct CliMainWorker {
@ -227,9 +257,7 @@ impl CliMainWorker {
&mut self, &mut self,
id: ModuleId, id: ModuleId,
) -> Result<(), AnyError> { ) -> Result<(), AnyError> {
if self.shared.npm_resolver.has_packages() if self.shared.should_initialize_node_runtime() {
|| self.shared.graph_container.graph().has_node_specifier
{
self.initialize_main_module_for_node()?; self.initialize_main_module_for_node()?;
} }
self.worker.evaluate_module(id).await self.worker.evaluate_module(id).await
@ -275,9 +303,9 @@ impl CliMainWorkerFactory {
storage_key_resolver: StorageKeyResolver, storage_key_resolver: StorageKeyResolver,
npm_resolver: Arc<CliNpmResolver>, npm_resolver: Arc<CliNpmResolver>,
node_resolver: Arc<NodeResolver>, node_resolver: Arc<NodeResolver>,
graph_container: Arc<ModuleGraphContainer>, has_node_specifier_checker: Box<dyn HasNodeSpecifierChecker>,
blob_store: BlobStore, blob_store: BlobStore,
module_loader_factory: CliModuleLoaderFactory, module_loader_factory: Box<dyn ModuleLoaderFactory>,
root_cert_store: RootCertStore, root_cert_store: RootCertStore,
node_fs: Arc<dyn deno_node::NodeFs>, node_fs: Arc<dyn deno_node::NodeFs>,
maybe_inspector_server: Option<Arc<InspectorServer>>, maybe_inspector_server: Option<Arc<InspectorServer>>,
@ -289,7 +317,7 @@ impl CliMainWorkerFactory {
storage_key_resolver, storage_key_resolver,
npm_resolver, npm_resolver,
node_resolver, node_resolver,
graph_container, has_node_specifier_checker,
blob_store, blob_store,
broadcast_channel: Default::default(), broadcast_channel: Default::default(),
shared_array_buffer_store: Default::default(), shared_array_buffer_store: Default::default(),
@ -345,11 +373,11 @@ impl CliMainWorkerFactory {
(main_module, false) (main_module, false)
}; };
let module_loader = let module_loader = shared
Rc::new(shared.module_loader_factory.create_for_main( .module_loader_factory
PermissionsContainer::allow_all(), .create_for_main(PermissionsContainer::allow_all(), permissions.clone());
permissions.clone(), let maybe_source_map_getter =
)); shared.module_loader_factory.create_source_map_getter();
let maybe_inspector_server = shared.maybe_inspector_server.clone(); let maybe_inspector_server = shared.maybe_inspector_server.clone();
let create_web_worker_cb = let create_web_worker_cb =
@ -366,6 +394,8 @@ impl CliMainWorkerFactory {
shared shared
.options .options
.origin_data_folder_path .origin_data_folder_path
.as_ref()
.unwrap() // must be set if storage key resolver returns a value
.join(checksum::gen(&[key.as_bytes()])) .join(checksum::gen(&[key.as_bytes()]))
}); });
let cache_storage_dir = maybe_storage_key.map(|key| { let cache_storage_dir = maybe_storage_key.map(|key| {
@ -405,7 +435,7 @@ impl CliMainWorkerFactory {
.clone(), .clone(),
root_cert_store: Some(shared.root_cert_store.clone()), root_cert_store: Some(shared.root_cert_store.clone()),
seed: shared.options.seed, seed: shared.options.seed,
source_map_getter: Some(Box::new(module_loader.clone())), source_map_getter: maybe_source_map_getter,
format_js_error_fn: Some(Arc::new(format_js_error)), format_js_error_fn: Some(Arc::new(format_js_error)),
create_web_worker_cb, create_web_worker_cb,
web_worker_preload_module_cb, web_worker_preload_module_cb,
@ -461,7 +491,7 @@ fn create_web_worker_pre_execute_module_callback(
let shared = shared.clone(); let shared = shared.clone();
let fut = async move { let fut = async move {
// this will be up to date after pre-load // this will be up to date after pre-load
if shared.npm_resolver.has_packages() { if shared.should_initialize_node_runtime() {
deno_node::initialize_runtime( deno_node::initialize_runtime(
&mut worker.js_runtime, &mut worker.js_runtime,
shared.options.has_node_modules_dir, shared.options.has_node_modules_dir,
@ -482,11 +512,12 @@ fn create_web_worker_callback(
Arc::new(move |args| { Arc::new(move |args| {
let maybe_inspector_server = shared.maybe_inspector_server.clone(); let maybe_inspector_server = shared.maybe_inspector_server.clone();
let module_loader = let module_loader = shared.module_loader_factory.create_for_worker(
Rc::new(shared.module_loader_factory.create_for_worker(
args.parent_permissions.clone(), args.parent_permissions.clone(),
args.permissions.clone(), args.permissions.clone(),
)); );
let maybe_source_map_getter =
shared.module_loader_factory.create_source_map_getter();
let create_web_worker_cb = let create_web_worker_cb =
create_web_worker_callback(shared.clone(), stdio.clone()); create_web_worker_callback(shared.clone(), stdio.clone());
let preload_module_cb = create_web_worker_preload_module_callback(&shared); let preload_module_cb = create_web_worker_preload_module_callback(&shared);
@ -536,7 +567,7 @@ fn create_web_worker_callback(
preload_module_cb, preload_module_cb,
pre_execute_module_cb, pre_execute_module_cb,
format_js_error_fn: Some(Arc::new(format_js_error)), format_js_error_fn: Some(Arc::new(format_js_error)),
source_map_getter: Some(Box::new(module_loader.clone())), source_map_getter: maybe_source_map_getter,
module_loader, module_loader,
node_fs: Some(shared.node_fs.clone()), node_fs: Some(shared.node_fs.clone()),
npm_resolver: Some(shared.npm_resolver.clone()), npm_resolver: Some(shared.npm_resolver.clone()),