1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-01-11 16:42:21 -05:00

refactor(cli): extract out ProcState from CliMainWorker (#18867)

This commit is contained in:
David Sherret 2023-04-27 10:05:20 -04:00 committed by GitHub
parent 03132e19da
commit 742cc3111c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 660 additions and 421 deletions

View file

@ -817,30 +817,6 @@ impl CliOptions {
)
}
/// Resolves the storage key to use based on the current flags, config, or main module.
pub fn resolve_storage_key(
&self,
main_module: &ModuleSpecifier,
) -> Option<String> {
if let Some(location) = &self.flags.location {
// if a location is set, then the ascii serialization of the location is
// used, unless the origin is opaque, and then no storage origin is set, as
// we can't expect the origin to be reproducible
let storage_origin = location.origin();
if storage_origin.is_tuple() {
Some(storage_origin.ascii_serialization())
} else {
None
}
} else if let Some(config_file) = &self.maybe_config_file {
// otherwise we will use the path to the config file
Some(config_file.specifier.to_string())
} else {
// otherwise we will use the path to the main module
Some(main_module.to_string())
}
}
pub fn resolve_inspector_server(&self) -> Option<InspectorServer> {
let maybe_inspect_host = self
.flags
@ -1089,20 +1065,6 @@ impl CliOptions {
&self.flags.subcommand
}
pub fn trace_ops(&self) -> bool {
match self.sub_command() {
DenoSubcommand::Test(flags) => flags.trace_ops,
_ => false,
}
}
pub fn shuffle_tests(&self) -> Option<u64> {
match self.sub_command() {
DenoSubcommand::Test(flags) => flags.shuffle,
_ => None,
}
}
pub fn type_check_mode(&self) -> TypeCheckMode {
self.flags.type_check_mode
}
@ -1216,6 +1178,44 @@ fn resolve_import_map_specifier(
Ok(None)
}
pub struct StorageKeyResolver(Option<Option<String>>);
impl StorageKeyResolver {
pub fn from_options(options: &CliOptions) -> Self {
Self(if let Some(location) = &options.flags.location {
// if a location is set, then the ascii serialization of the location is
// used, unless the origin is opaque, and then no storage origin is set, as
// we can't expect the origin to be reproducible
let storage_origin = location.origin();
if storage_origin.is_tuple() {
Some(Some(storage_origin.ascii_serialization()))
} else {
Some(None)
}
} else {
// otherwise we will use the path to the config file or None to
// fall back to using the main module's path
options
.maybe_config_file
.as_ref()
.map(|config_file| Some(config_file.specifier.to_string()))
})
}
/// Resolves the storage key to use based on the current flags, config, or main module.
pub fn resolve_storage_key(
&self,
main_module: &ModuleSpecifier,
) -> Option<String> {
// use the stored value or fall back to using the path of the main module.
if let Some(maybe_value) = &self.0 {
maybe_value.clone()
} else {
Some(main_module.to_string())
}
}
}
/// Collect included and ignored files. CLI flags take precedence
/// over config file, i.e. if there's `files.ignore` in config file
/// and `--ignore` CLI flag, only the flag value is taken into account.
@ -1381,4 +1381,21 @@ mod test {
let actual = actual.unwrap();
assert_eq!(actual, None);
}
#[test]
fn storage_key_resolver_test() {
let resolver = StorageKeyResolver(None);
let specifier = ModuleSpecifier::parse("file:///a.ts").unwrap();
assert_eq!(
resolver.resolve_storage_key(&specifier),
Some(specifier.to_string())
);
let resolver = StorageKeyResolver(Some(None));
assert_eq!(resolver.resolve_storage_key(&specifier), None);
let resolver = StorageKeyResolver(Some(Some("value".to_string())));
assert_eq!(
resolver.resolve_storage_key(&specifier),
Some("value".to_string())
);
}
}

View file

@ -257,10 +257,11 @@ impl TestRun {
let tests: Arc<RwLock<IndexMap<usize, test::TestDescription>>> =
Arc::new(RwLock::new(IndexMap::new()));
let mut test_steps = IndexMap::new();
let worker_factory = Arc::new(ps.into_cli_main_worker_factory());
let join_handles = queue.into_iter().map(move |specifier| {
let specifier = specifier.clone();
let ps = ps.clone();
let worker_factory = worker_factory.clone();
let permissions = permissions.clone();
let mut sender = sender.clone();
let fail_fast_tracker = fail_fast_tracker.clone();
@ -288,12 +289,16 @@ impl TestRun {
Ok(())
} else {
run_local(test::test_specifier(
&ps,
&worker_factory,
permissions,
specifier,
sender.clone(),
fail_fast_tracker,
filter,
&test::TestSpecifierOptions {
filter,
shuffle: None,
trace_ops: false,
},
))
};
if let Err(error) = file_result {

View file

@ -14,7 +14,6 @@ use crate::node;
use crate::node::CliNodeCodeTranslator;
use crate::proc_state::CjsResolutionStore;
use crate::proc_state::FileWatcherReporter;
use crate::proc_state::ProcState;
use crate::resolver::CliGraphResolver;
use crate::tools::check;
use crate::tools::check::TypeChecker;
@ -224,6 +223,88 @@ pub struct ModuleCodeSource {
pub media_type: MediaType,
}
struct SharedCliModuleLoaderState {
lib_window: TsTypeLib,
lib_worker: TsTypeLib,
is_inspecting: bool,
is_repl: bool,
emitter: Arc<Emitter>,
graph_container: Arc<ModuleGraphContainer>,
module_load_preparer: Arc<ModuleLoadPreparer>,
parsed_source_cache: Arc<ParsedSourceCache>,
resolver: Arc<CliGraphResolver>,
npm_module_loader: NpmModuleLoader,
}
pub struct CliModuleLoaderFactory {
state: 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 {
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
@ -233,62 +314,10 @@ pub struct CliModuleLoader {
/// Permissions used to resolve dynamic imports, these get passed as
/// "root permissions" for Web Worker.
dynamic_permissions: PermissionsContainer,
cli_options: Arc<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,
shared: Arc<SharedCliModuleLoaderState>,
}
impl CliModuleLoader {
pub fn new(
ps: ProcState,
root_permissions: PermissionsContainer,
dynamic_permissions: PermissionsContainer,
) -> Rc<Self> {
Rc::new(CliModuleLoader {
lib: ps.options.ts_type_lib_window(),
root_permissions,
dynamic_permissions,
cli_options: ps.options.clone(),
emitter: ps.emitter.clone(),
graph_container: ps.graph_container.clone(),
module_load_preparer: ps.module_load_preparer.clone(),
parsed_source_cache: ps.parsed_source_cache.clone(),
resolver: ps.resolver.clone(),
npm_module_loader: NpmModuleLoader::new(
ps.cjs_resolutions.clone(),
ps.node_code_translator.clone(),
ps.node_resolver.clone(),
),
})
}
pub fn new_for_worker(
ps: ProcState,
root_permissions: PermissionsContainer,
dynamic_permissions: PermissionsContainer,
) -> Rc<Self> {
Rc::new(CliModuleLoader {
lib: ps.options.ts_type_lib_worker(),
root_permissions,
dynamic_permissions,
cli_options: ps.options.clone(),
emitter: ps.emitter.clone(),
graph_container: ps.graph_container.clone(),
module_load_preparer: ps.module_load_preparer.clone(),
parsed_source_cache: ps.parsed_source_cache.clone(),
resolver: ps.resolver.clone(),
npm_module_loader: NpmModuleLoader::new(
ps.cjs_resolutions.clone(),
ps.node_code_translator.clone(),
ps.node_resolver.clone(),
),
})
}
fn load_prepared_module(
&self,
specifier: &ModuleSpecifier,
@ -298,7 +327,7 @@ impl CliModuleLoader {
unreachable!(); // Node built-in modules should be handled internally.
}
let graph = self.graph_container.graph();
let graph = self.shared.graph_container.graph();
match graph.get(specifier) {
Some(deno_graph::Module::Json(JsonModule {
source,
@ -331,9 +360,11 @@ impl CliModuleLoader {
| MediaType::Jsx
| MediaType::Tsx => {
// get emit text
self
.emitter
.emit_parsed_source(specifier, *media_type, source)?
self.shared.emitter.emit_parsed_source(
specifier,
*media_type,
source,
)?
}
MediaType::TsBuildInfo | MediaType::Wasm | MediaType::SourceMap => {
panic!("Unexpected media type {media_type} for {specifier}")
@ -341,7 +372,7 @@ impl CliModuleLoader {
};
// at this point, we no longer need the parsed source in memory, so free it
self.parsed_source_cache.free(specifier);
self.shared.parsed_source_cache.free(specifier);
Ok(ModuleCodeSource {
code,
@ -370,15 +401,17 @@ impl CliModuleLoader {
} else {
&self.root_permissions
};
let code_source = if let Some(code_source) = self
.npm_module_loader
.load_sync(specifier, maybe_referrer, permissions)?
{
let code_source = if let Some(code_source) =
self.shared.npm_module_loader.load_sync(
specifier,
maybe_referrer,
permissions,
)? {
code_source
} else {
self.load_prepared_module(specifier, maybe_referrer)?
};
let code = if self.cli_options.is_inspecting() {
let code = if self.shared.is_inspecting {
// we need the code with the source map in order for
// it to work with --inspect or --inspect-brk
code_source.code
@ -418,15 +451,15 @@ impl ModuleLoader for CliModuleLoader {
let referrer_result = deno_core::resolve_url_or_path(referrer, &cwd);
if let Ok(referrer) = referrer_result.as_ref() {
if let Some(result) = self.npm_module_loader.resolve_if_in_npm_package(
specifier,
referrer,
permissions,
) {
if let Some(result) = self
.shared
.npm_module_loader
.resolve_if_in_npm_package(specifier, referrer, permissions)
{
return result;
}
let graph = self.graph_container.graph();
let graph = self.shared.graph_container.graph();
let maybe_resolved = match graph.get(referrer) {
Some(Module::Esm(module)) => {
module.dependencies.get(specifier).map(|d| &d.maybe_code)
@ -440,6 +473,7 @@ impl ModuleLoader for CliModuleLoader {
return match graph.get(specifier) {
Some(Module::Npm(module)) => self
.shared
.npm_module_loader
.resolve_npm_module(module, permissions),
Some(Module::Node(module)) => {
@ -471,9 +505,7 @@ impl ModuleLoader for CliModuleLoader {
// FIXME(bartlomieju): this is a hacky way to provide compatibility with REPL
// and `Deno.core.evalContext` API. Ideally we should always have a referrer filled
// but sadly that's not the case due to missing APIs in V8.
let is_repl =
matches!(self.cli_options.sub_command(), DenoSubcommand::Repl(_));
let referrer = if referrer.is_empty() && is_repl {
let referrer = if referrer.is_empty() && self.shared.is_repl {
deno_core::resolve_path("./$deno$repl.ts", &cwd)?
} else {
referrer_result?
@ -481,9 +513,9 @@ impl ModuleLoader for CliModuleLoader {
// FIXME(bartlomieju): this is another hack way to provide NPM specifier
// support in REPL. This should be fixed.
let resolution = self.resolver.resolve(specifier, &referrer);
let resolution = self.shared.resolver.resolve(specifier, &referrer);
if is_repl {
if self.shared.is_repl {
let specifier = resolution
.as_ref()
.ok()
@ -494,6 +526,7 @@ impl ModuleLoader for CliModuleLoader {
NpmPackageReqReference::from_specifier(&specifier)
{
return self
.shared
.npm_module_loader
.resolve_for_repl(&reference, permissions);
}
@ -526,12 +559,14 @@ impl ModuleLoader for CliModuleLoader {
_maybe_referrer: Option<String>,
is_dynamic: bool,
) -> Pin<Box<dyn Future<Output = Result<(), AnyError>>>> {
if let Some(result) = self.npm_module_loader.maybe_prepare_load(specifier) {
if let Some(result) =
self.shared.npm_module_loader.maybe_prepare_load(specifier)
{
return Box::pin(deno_core::futures::future::ready(result));
}
let specifier = specifier.clone();
let module_load_preparer = self.module_load_preparer.clone();
let module_load_preparer = self.shared.module_load_preparer.clone();
let root_permissions = if is_dynamic {
self.dynamic_permissions.clone()
@ -567,7 +602,7 @@ impl SourceMapGetter for CliModuleLoader {
file_name: &str,
line_number: usize,
) -> Option<String> {
let graph = self.graph_container.graph();
let graph = self.shared.graph_container.graph();
let code = match graph.get(&resolve_url(file_name).ok()?) {
Some(deno_graph::Module::Esm(module)) => &module.source,
Some(deno_graph::Module::Json(module)) => &module.source,

View file

@ -4,6 +4,7 @@ use crate::args::CliOptions;
use crate::args::DenoSubcommand;
use crate::args::Flags;
use crate::args::Lockfile;
use crate::args::StorageKeyResolver;
use crate::args::TsConfigType;
use crate::cache::Caches;
use crate::cache::DenoDir;
@ -16,7 +17,9 @@ use crate::file_fetcher::FileFetcher;
use crate::graph_util::ModuleGraphBuilder;
use crate::graph_util::ModuleGraphContainer;
use crate::http_util::HttpClient;
use crate::module_loader::CliModuleLoaderFactory;
use crate::module_loader::ModuleLoadPreparer;
use crate::module_loader::NpmModuleLoader;
use crate::node::CliCjsEsmCodeAnalyzer;
use crate::node::CliNodeCodeTranslator;
use crate::npm::create_npm_fs_resolver;
@ -29,20 +32,20 @@ use crate::resolver::CliGraphResolver;
use crate::tools::check::TypeChecker;
use crate::util::progress_bar::ProgressBar;
use crate::util::progress_bar::ProgressBarStyle;
use crate::worker::CliMainWorkerFactory;
use crate::worker::CliMainWorkerOptions;
use deno_core::error::AnyError;
use deno_core::parking_lot::Mutex;
use deno_core::CompiledWasmModuleStore;
use deno_core::ModuleSpecifier;
use deno_core::SharedArrayBufferStore;
use deno_runtime::deno_broadcast_channel::InMemoryBroadcastChannel;
use deno_runtime::deno_node;
use deno_runtime::deno_node::analyze::NodeCodeTranslator;
use deno_runtime::deno_node::NodeResolver;
use deno_runtime::deno_tls::rustls::RootCertStore;
use deno_runtime::deno_web::BlobStore;
use deno_runtime::inspector_server::InspectorServer;
use deno_semver::npm::NpmPackageReqReference;
use import_map::ImportMap;
use log::warn;
use std::collections::HashSet;
@ -70,9 +73,6 @@ pub struct Inner {
pub maybe_inspector_server: Option<Arc<InspectorServer>>,
pub root_cert_store: RootCertStore,
pub blob_store: BlobStore,
pub broadcast_channel: InMemoryBroadcastChannel,
pub shared_array_buffer_store: SharedArrayBufferStore,
pub compiled_wasm_module_store: CompiledWasmModuleStore,
pub parsed_source_cache: Arc<ParsedSourceCache>,
pub resolver: Arc<CliGraphResolver>,
maybe_file_watcher_reporter: Option<FileWatcherReporter>,
@ -142,9 +142,6 @@ impl ProcState {
maybe_inspector_server: self.maybe_inspector_server.clone(),
root_cert_store: self.root_cert_store.clone(),
blob_store: self.blob_store.clone(),
broadcast_channel: Default::default(),
shared_array_buffer_store: Default::default(),
compiled_wasm_module_store: Default::default(),
parsed_source_cache: self.parsed_source_cache.clone(),
resolver: self.resolver.clone(),
maybe_file_watcher_reporter: self.maybe_file_watcher_reporter.clone(),
@ -203,9 +200,6 @@ impl ProcState {
_ => {}
}
let blob_store = BlobStore::default();
let broadcast_channel = InMemoryBroadcastChannel::default();
let shared_array_buffer_store = SharedArrayBufferStore::default();
let compiled_wasm_module_store = CompiledWasmModuleStore::default();
let deps_cache_location = dir.deps_folder_path();
let http_cache = HttpCache::new(&deps_cache_location);
let root_cert_store = cli_options.resolve_root_cert_store()?;
@ -358,9 +352,6 @@ impl ProcState {
maybe_inspector_server,
root_cert_store,
blob_store,
broadcast_channel,
shared_array_buffer_store,
compiled_wasm_module_store,
parsed_source_cache,
resolver,
maybe_file_watcher_reporter,
@ -378,6 +369,73 @@ impl ProcState {
progress_bar,
})))
}
// todo(dsherret): this is a transitory method as we separate out
// ProcState from more code
pub fn into_cli_main_worker_factory(self) -> CliMainWorkerFactory {
CliMainWorkerFactory::new(
StorageKeyResolver::from_options(&self.options),
self.npm_resolver.clone(),
self.node_resolver.clone(),
self.graph_container.clone(),
self.blob_store.clone(),
CliModuleLoaderFactory::new(
&self.options,
self.emitter.clone(),
self.graph_container.clone(),
self.module_load_preparer.clone(),
self.parsed_source_cache.clone(),
self.resolver.clone(),
NpmModuleLoader::new(
self.cjs_resolutions.clone(),
self.node_code_translator.clone(),
self.node_resolver.clone(),
),
),
self.root_cert_store.clone(),
self.node_fs.clone(),
self.maybe_inspector_server.clone(),
CliMainWorkerOptions {
argv: self.options.argv().clone(),
debug: self
.options
.log_level()
.map(|l| l == log::Level::Debug)
.unwrap_or(false),
coverage_dir: self.options.coverage_dir(),
enable_testing_features: self.options.enable_testing_features(),
has_node_modules_dir: self.options.has_node_modules_dir(),
inspect_brk: self.options.inspect_brk().is_some(),
inspect_wait: self.options.inspect_wait().is_some(),
is_inspecting: self.options.is_inspecting(),
is_npm_main: self.options.is_npm_main(),
location: self.options.location_flag().clone(),
maybe_binary_npm_command_name: {
let mut maybe_binary_command_name = None;
if let DenoSubcommand::Run(flags) = self.options.sub_command() {
if let Ok(pkg_ref) = NpmPackageReqReference::from_str(&flags.script)
{
// if the user ran a binary command, we'll need to set process.argv[0]
// to be the name of the binary command instead of deno
let binary_name = pkg_ref
.sub_path
.as_deref()
.unwrap_or(pkg_ref.req.name.as_str());
maybe_binary_command_name = Some(binary_name.to_string());
}
}
maybe_binary_command_name
},
origin_data_folder_path: self.dir.origin_data_folder_path(),
seed: self.options.seed(),
unsafely_ignore_certificate_errors: self
.options
.unsafely_ignore_certificate_errors()
.clone(),
unstable: self.options.unstable(),
},
)
}
}
/// Keeps track of what module specifiers were resolved as CJS.

View file

@ -15,7 +15,7 @@ use crate::util::file_watcher::ResolutionResult;
use crate::util::fs::collect_specifiers;
use crate::util::path::is_supported_ext;
use crate::version::get_user_agent;
use crate::worker::create_custom_worker;
use crate::worker::CliMainWorkerFactory;
use deno_core::error::generic_error;
use deno_core::error::AnyError;
@ -48,6 +48,7 @@ use tokio::sync::mpsc::UnboundedSender;
struct BenchSpecifierOptions {
filter: TestFilter,
json: bool,
log_level: Option<log::Level>,
}
#[derive(Debug, Clone, Eq, PartialEq, Deserialize)]
@ -434,20 +435,20 @@ async fn check_specifiers(
/// Run a single specifier as an executable bench module.
async fn bench_specifier(
ps: ProcState,
worker_factory: &CliMainWorkerFactory,
permissions: Permissions,
specifier: ModuleSpecifier,
sender: UnboundedSender<BenchEvent>,
filter: TestFilter,
) -> Result<(), AnyError> {
let mut worker = create_custom_worker(
&ps,
specifier.clone(),
PermissionsContainer::new(permissions),
vec![ops::bench::deno_bench::init_ops(sender.clone())],
Default::default(),
)
.await?;
let mut worker = worker_factory
.create_custom_worker(
specifier.clone(),
PermissionsContainer::new(permissions),
vec![ops::bench::deno_bench::init_ops(sender.clone())],
Default::default(),
)
.await?;
// We execute the main module as a side module so that import.meta.main is not set.
worker.execute_side_module_possibly_with_npm().await?;
@ -508,26 +509,29 @@ async fn bench_specifier(
/// Test a collection of specifiers with test modes concurrently.
async fn bench_specifiers(
ps: &ProcState,
worker_factory: Arc<CliMainWorkerFactory>,
permissions: &Permissions,
specifiers: Vec<ModuleSpecifier>,
options: BenchSpecifierOptions,
) -> Result<(), AnyError> {
let log_level = ps.options.log_level();
let (sender, mut receiver) = unbounded_channel::<BenchEvent>();
let log_level = options.log_level;
let option_for_handles = options.clone();
let join_handles = specifiers.into_iter().map(move |specifier| {
let ps = ps.clone();
let worker_factory = worker_factory.clone();
let permissions = permissions.clone();
let specifier = specifier;
let sender = sender.clone();
let options = option_for_handles.clone();
tokio::task::spawn_blocking(move || {
let future =
bench_specifier(ps, permissions, specifier, sender, options.filter);
let future = bench_specifier(
&worker_factory,
permissions,
specifier,
sender,
options.filter,
);
run_local(future)
})
});
@ -650,13 +654,16 @@ pub async fn run_benchmarks(
return Ok(());
}
let log_level = ps.options.log_level();
let worker_factory = Arc::new(ps.into_cli_main_worker_factory());
bench_specifiers(
&ps,
worker_factory,
&permissions,
specifiers,
BenchSpecifierOptions {
filter: TestFilter::from_flag(&bench_options.filter),
json: bench_options.json,
log_level,
},
)
.await?;
@ -809,13 +816,16 @@ pub async fn run_benchmarks_with_watch(
return Ok(());
}
let log_level = ps.options.log_level();
let worker_factory = Arc::new(ps.into_cli_main_worker_factory());
bench_specifiers(
&ps,
worker_factory,
permissions,
specifiers,
BenchSpecifierOptions {
filter: TestFilter::from_flag(&bench_options.filter),
json: bench_options.json,
log_level,
},
)
.await?;

View file

@ -1,10 +1,11 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
use crate::args::CliOptions;
use crate::args::Flags;
use crate::args::ReplFlags;
use crate::colors;
use crate::file_fetcher::FileFetcher;
use crate::proc_state::ProcState;
use crate::worker::create_main_worker;
use deno_core::error::AnyError;
use deno_runtime::permissions::Permissions;
use deno_runtime::permissions::PermissionsContainer;
@ -65,14 +66,14 @@ async fn read_line_and_poll(
}
async fn read_eval_file(
ps: &ProcState,
cli_options: &CliOptions,
file_fetcher: &FileFetcher,
eval_file: &str,
) -> Result<String, AnyError> {
let specifier =
deno_core::resolve_url_or_path(eval_file, ps.options.initial_cwd())?;
deno_core::resolve_url_or_path(eval_file, cli_options.initial_cwd())?;
let file = ps
.file_fetcher
let file = file_fetcher
.fetch(&specifier, PermissionsContainer::allow_all())
.await?;
@ -82,17 +83,24 @@ async fn read_eval_file(
pub async fn run(flags: Flags, repl_flags: ReplFlags) -> Result<i32, AnyError> {
let ps = ProcState::from_flags(flags).await?;
let main_module = ps.options.resolve_main_module()?;
let mut worker = create_main_worker(
&ps,
main_module,
PermissionsContainer::new(Permissions::from_options(
&ps.options.permissions_options(),
)?),
)
.await?;
let permissions = PermissionsContainer::new(Permissions::from_options(
&ps.options.permissions_options(),
)?);
let cli_options = ps.options.clone();
let npm_resolver = ps.npm_resolver.clone();
let resolver = ps.resolver.clone();
let dir = ps.dir.clone();
let file_fetcher = ps.file_fetcher.clone();
let worker_factory = ps.into_cli_main_worker_factory();
let mut worker = worker_factory
.create_main_worker(main_module, permissions)
.await?;
worker.setup_repl().await?;
let worker = worker.into_main_worker();
let mut repl_session = ReplSession::initialize(ps.clone(), worker).await?;
let mut repl_session =
ReplSession::initialize(&cli_options, npm_resolver, resolver, worker)
.await?;
let mut rustyline_channel = rustyline_channel();
let helper = EditorHelper {
@ -100,12 +108,12 @@ pub async fn run(flags: Flags, repl_flags: ReplFlags) -> Result<i32, AnyError> {
sync_sender: rustyline_channel.0,
};
let history_file_path = ps.dir.repl_history_file_path();
let history_file_path = dir.repl_history_file_path();
let editor = ReplEditor::new(helper, history_file_path)?;
if let Some(eval_files) = repl_flags.eval_files {
for eval_file in eval_files {
match read_eval_file(&ps, &eval_file).await {
match read_eval_file(&cli_options, &file_fetcher, &eval_file).await {
Ok(eval_source) => {
let output = repl_session
.evaluate_line_and_get_output(&eval_source)
@ -132,7 +140,7 @@ pub async fn run(flags: Flags, repl_flags: ReplFlags) -> Result<i32, AnyError> {
// Doing this manually, instead of using `log::info!` because these messages
// are supposed to go to stdout, not stderr.
if !ps.options.is_quiet() {
if !cli_options.is_quiet() {
println!("Deno {}", crate::version::deno());
println!("exit using ctrl+d, ctrl+c, or close()");
if repl_flags.is_default_command {

View file

@ -1,8 +1,12 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
use std::sync::Arc;
use crate::args::CliOptions;
use crate::colors;
use crate::lsp::ReplLanguageServer;
use crate::ProcState;
use crate::npm::CliNpmResolver;
use crate::resolver::CliGraphResolver;
use deno_ast::swc::ast as swc_ast;
use deno_ast::swc::visit::noop_visit_type;
@ -117,7 +121,9 @@ struct TsEvaluateResponse {
}
pub struct ReplSession {
proc_state: ProcState,
has_node_modules_dir: bool,
npm_resolver: Arc<CliNpmResolver>,
resolver: Arc<CliGraphResolver>,
pub worker: MainWorker,
session: LocalInspectorSession,
pub context_id: u64,
@ -132,7 +138,9 @@ pub struct ReplSession {
impl ReplSession {
pub async fn initialize(
proc_state: ProcState,
cli_options: &CliOptions,
npm_resolver: Arc<CliNpmResolver>,
resolver: Arc<CliGraphResolver>,
mut worker: MainWorker,
) -> Result<Self, AnyError> {
let language_server = ReplLanguageServer::new_initialized().await?;
@ -171,14 +179,14 @@ impl ReplSession {
}
assert_ne!(context_id, 0);
let referrer = deno_core::resolve_path(
"./$deno$repl.ts",
proc_state.options.initial_cwd(),
)
.unwrap();
let referrer =
deno_core::resolve_path("./$deno$repl.ts", cli_options.initial_cwd())
.unwrap();
let mut repl_session = ReplSession {
proc_state,
has_node_modules_dir: cli_options.has_node_modules_dir(),
npm_resolver,
resolver,
worker,
session,
context_id,
@ -487,7 +495,6 @@ impl ReplSession {
.iter()
.flat_map(|i| {
self
.proc_state
.resolver
.resolve(i, &self.referrer)
.ok()
@ -506,22 +513,17 @@ impl ReplSession {
if !self.has_initialized_node_runtime {
deno_node::initialize_runtime(
&mut self.worker.js_runtime,
self.proc_state.options.has_node_modules_dir(),
self.has_node_modules_dir,
None,
)?;
self.has_initialized_node_runtime = true;
}
self
.proc_state
.npm_resolver
.add_package_reqs(npm_imports)
.await?;
self.npm_resolver.add_package_reqs(npm_imports).await?;
// prevent messages in the repl about @types/node not being cached
if has_node_specifier {
self
.proc_state
.npm_resolver
.inject_synthetic_types_node_package()
.await?;

View file

@ -13,7 +13,6 @@ use crate::args::Flags;
use crate::file_fetcher::File;
use crate::proc_state::ProcState;
use crate::util;
use crate::worker::create_main_worker;
pub async fn run_script(flags: Flags) -> Result<i32, AnyError> {
if !flags.has_permission() && flags.has_permission_in_argv() {
@ -48,7 +47,10 @@ To grant permissions, set them before the script argument. For example:
let permissions = PermissionsContainer::new(Permissions::from_options(
&ps.options.permissions_options(),
)?);
let mut worker = create_main_worker(&ps, main_module, permissions).await?;
let worker_factory = ps.into_cli_main_worker_factory();
let mut worker = worker_factory
.create_main_worker(main_module, permissions)
.await?;
let exit_code = worker.run().await?;
Ok(exit_code)
@ -58,15 +60,9 @@ pub async fn run_from_stdin(flags: Flags) -> Result<i32, AnyError> {
let ps = ProcState::from_flags(flags).await?;
let main_module = ps.options.resolve_main_module()?;
let mut worker = create_main_worker(
&ps,
main_module.clone(),
PermissionsContainer::new(Permissions::from_options(
&ps.options.permissions_options(),
)?),
)
.await?;
let permissions = PermissionsContainer::new(Permissions::from_options(
&ps.options.permissions_options(),
)?);
let mut source = Vec::new();
std::io::stdin().read_to_end(&mut source)?;
// Create a dummy source file.
@ -75,13 +71,17 @@ pub async fn run_from_stdin(flags: Flags) -> Result<i32, AnyError> {
maybe_types: None,
media_type: MediaType::TypeScript,
source: String::from_utf8(source)?.into(),
specifier: main_module,
specifier: main_module.clone(),
maybe_headers: None,
};
// Save our fake file into file fetcher cache
// to allow module access by TS compiler
ps.file_fetcher.insert_cached(source_file);
let worker_factory = ps.into_cli_main_worker_factory();
let mut worker = worker_factory
.create_main_worker(main_module, permissions)
.await?;
let exit_code = worker.run().await?;
Ok(exit_code)
}
@ -102,7 +102,10 @@ async fn run_with_watch(flags: Flags) -> Result<i32, AnyError> {
let permissions = PermissionsContainer::new(Permissions::from_options(
&ps.options.permissions_options(),
)?);
let worker = create_main_worker(&ps, main_module, permissions).await?;
let worker_factory = ps.into_cli_main_worker_factory();
let worker = worker_factory
.create_main_worker(main_module, permissions)
.await?;
worker.run_for_watcher().await?;
Ok(())
@ -132,8 +135,6 @@ pub async fn eval_command(
let permissions = PermissionsContainer::new(Permissions::from_options(
&ps.options.permissions_options(),
)?);
let mut worker =
create_main_worker(&ps, main_module.clone(), permissions).await?;
// Create a dummy source file.
let source_code = if eval_flags.print {
format!("console.log({})", eval_flags.code)
@ -147,13 +148,18 @@ pub async fn eval_command(
maybe_types: None,
media_type: MediaType::Unknown,
source: String::from_utf8(source_code)?.into(),
specifier: main_module,
specifier: main_module.clone(),
maybe_headers: None,
};
// Save our fake file into file fetcher cache
// to allow module access by TS compiler.
ps.file_fetcher.insert_cached(file);
let mut worker = ps
.into_cli_main_worker_factory()
.create_main_worker(main_module, permissions)
.await?;
let exit_code = worker.run().await?;
Ok(exit_code)
}

View file

@ -17,7 +17,7 @@ use crate::util::fs::collect_specifiers;
use crate::util::path::get_extension;
use crate::util::path::is_supported_ext;
use crate::util::path::mapped_specifier_for_tsc;
use crate::worker::create_custom_worker;
use crate::worker::CliMainWorkerFactory;
use deno_ast::swc::common::comments::CommentKind;
use deno_ast::MediaType;
@ -336,10 +336,18 @@ pub struct TestSummary {
}
#[derive(Debug, Clone)]
struct TestSpecifierOptions {
struct TestSpecifiersOptions {
concurrent_jobs: NonZeroUsize,
fail_fast: Option<NonZeroUsize>,
filter: TestFilter,
log_level: Option<log::Level>,
specifier: TestSpecifierOptions,
}
#[derive(Debug, Clone)]
pub struct TestSpecifierOptions {
pub shuffle: Option<u64>,
pub filter: TestFilter,
pub trace_ops: bool,
}
impl TestSummary {
@ -907,30 +915,30 @@ pub fn format_test_error(js_error: &JsError) -> String {
/// Test a single specifier as documentation containing test programs, an executable test module or
/// both.
pub async fn test_specifier(
ps: &ProcState,
worker_factory: &CliMainWorkerFactory,
permissions: Permissions,
specifier: ModuleSpecifier,
mut sender: TestEventSender,
fail_fast_tracker: FailFastTracker,
filter: TestFilter,
options: &TestSpecifierOptions,
) -> Result<(), AnyError> {
if fail_fast_tracker.should_stop() {
return Ok(());
}
let stdout = StdioPipe::File(sender.stdout());
let stderr = StdioPipe::File(sender.stderr());
let mut worker = create_custom_worker(
ps,
specifier.clone(),
PermissionsContainer::new(permissions),
vec![ops::testing::deno_test::init_ops(sender.clone())],
Stdio {
stdin: StdioPipe::Inherit,
stdout,
stderr,
},
)
.await?;
let mut worker = worker_factory
.create_custom_worker(
specifier.clone(),
PermissionsContainer::new(permissions),
vec![ops::testing::deno_test::init_ops(sender.clone())],
Stdio {
stdin: StdioPipe::Inherit,
stdout,
stderr,
},
)
.await?;
let mut coverage_collector = worker.maybe_setup_coverage_collector().await?;
@ -951,7 +959,7 @@ pub async fn test_specifier(
}
let mut worker = worker.into_main_worker();
if ps.options.trace_ops() {
if options.trace_ops {
worker.js_runtime.execute_script_static(
located_script_name!(),
"Deno[Deno.internal].enableOpCallTracing();",
@ -971,9 +979,9 @@ pub async fn test_specifier(
let tests = if used_only { only } else { no_only };
let mut tests = tests
.into_iter()
.filter(|(d, _)| filter.includes(&d.name))
.filter(|(d, _)| options.filter.includes(&d.name))
.collect::<Vec<_>>();
if let Some(seed) = ps.options.shuffle_tests() {
if let Some(seed) = options.shuffle {
tests.shuffle(&mut SmallRng::seed_from_u64(seed));
}
sender.send(TestEvent::Plan(TestPlan {
@ -1288,13 +1296,12 @@ static HAS_TEST_RUN_SIGINT_HANDLER: AtomicBool = AtomicBool::new(false);
/// Test a collection of specifiers with test modes concurrently.
async fn test_specifiers(
ps: &ProcState,
worker_factory: Arc<CliMainWorkerFactory>,
permissions: &Permissions,
specifiers: Vec<ModuleSpecifier>,
options: TestSpecifierOptions,
options: TestSpecifiersOptions,
) -> Result<(), AnyError> {
let log_level = ps.options.log_level();
let specifiers = if let Some(seed) = ps.options.shuffle_tests() {
let specifiers = if let Some(seed) = options.specifier.shuffle {
let mut rng = SmallRng::seed_from_u64(seed);
let mut specifiers = specifiers;
specifiers.sort();
@ -1316,19 +1323,19 @@ async fn test_specifiers(
HAS_TEST_RUN_SIGINT_HANDLER.store(true, Ordering::Relaxed);
let join_handles = specifiers.into_iter().map(move |specifier| {
let ps = ps.clone();
let worker_factory = worker_factory.clone();
let permissions = permissions.clone();
let sender = sender.clone();
let options = options.clone();
let fail_fast_tracker = FailFastTracker::new(options.fail_fast);
let specifier_options = options.specifier.clone();
tokio::task::spawn_blocking(move || {
run_local(test_specifier(
&ps,
&worker_factory,
permissions,
specifier,
sender.clone(),
fail_fast_tracker,
options.filter,
&specifier_options,
))
})
});
@ -1339,7 +1346,7 @@ async fn test_specifiers(
let mut reporter = Box::new(PrettyTestReporter::new(
concurrent_jobs.get() > 1,
log_level != Some(Level::Error),
options.log_level != Some(Level::Error),
));
let handler = {
@ -1626,6 +1633,7 @@ pub async fn run_tests(
// file would have impact on other files, which is undesirable.
let permissions =
Permissions::from_options(&ps.options.permissions_options())?;
let log_level = ps.options.log_level();
let specifiers_with_mode = fetch_specifiers_with_test_mode(
&ps,
@ -1644,8 +1652,10 @@ pub async fn run_tests(
return Ok(());
}
let worker_factory = Arc::new(ps.into_cli_main_worker_factory());
test_specifiers(
&ps,
worker_factory,
&permissions,
specifiers_with_mode
.into_iter()
@ -1654,10 +1664,15 @@ pub async fn run_tests(
_ => Some(s),
})
.collect(),
TestSpecifierOptions {
TestSpecifiersOptions {
concurrent_jobs: test_options.concurrent_jobs,
fail_fast: test_options.fail_fast,
filter: TestFilter::from_flag(&test_options.filter),
log_level,
specifier: TestSpecifierOptions {
filter: TestFilter::from_flag(&test_options.filter),
shuffle: test_options.shuffle,
trace_ops: test_options.trace_ops,
},
},
)
.await?;
@ -1676,6 +1691,7 @@ pub async fn run_tests_with_watch(
let permissions =
Permissions::from_options(&ps.options.permissions_options())?;
let no_check = ps.options.type_check_mode() == TypeCheckMode::None;
let log_level = ps.options.log_level();
let ps = RefCell::new(ps);
@ -1816,8 +1832,10 @@ pub async fn run_tests_with_watch(
return Ok(());
}
let worker_factory = Arc::new(ps.into_cli_main_worker_factory());
test_specifiers(
&ps,
worker_factory,
permissions,
specifiers_with_mode
.into_iter()
@ -1826,10 +1844,15 @@ pub async fn run_tests_with_watch(
_ => Some(s),
})
.collect(),
TestSpecifierOptions {
TestSpecifiersOptions {
concurrent_jobs: test_options.concurrent_jobs,
fail_fast: test_options.fail_fast,
filter: TestFilter::from_flag(&test_options.filter),
log_level,
specifier: TestSpecifierOptions {
filter: TestFilter::from_flag(&test_options.filter),
shuffle: test_options.shuffle,
trace_ops: test_options.trace_ops,
},
},
)
.await?;

View file

@ -1,6 +1,7 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
use std::path::PathBuf;
use std::rc::Rc;
use std::sync::Arc;
use deno_ast::ModuleSpecifier;
@ -8,12 +9,20 @@ use deno_core::error::AnyError;
use deno_core::futures::task::LocalFutureObj;
use deno_core::futures::FutureExt;
use deno_core::located_script_name;
use deno_core::url::Url;
use deno_core::CompiledWasmModuleStore;
use deno_core::Extension;
use deno_core::ModuleId;
use deno_core::SharedArrayBufferStore;
use deno_runtime::colors;
use deno_runtime::deno_broadcast_channel::InMemoryBroadcastChannel;
use deno_runtime::deno_node;
use deno_runtime::deno_node::NodeResolution;
use deno_runtime::deno_node::NodeResolver;
use deno_runtime::deno_tls::rustls::RootCertStore;
use deno_runtime::deno_web::BlobStore;
use deno_runtime::fmt_errors::format_js_error;
use deno_runtime::inspector_server::InspectorServer;
use deno_runtime::ops::worker_host::CreateWebWorkerCb;
use deno_runtime::ops::worker_host::WorkerEventCb;
use deno_runtime::permissions::PermissionsContainer;
@ -24,21 +33,56 @@ use deno_runtime::worker::WorkerOptions;
use deno_runtime::BootstrapOptions;
use deno_semver::npm::NpmPackageReqReference;
use crate::args::DenoSubcommand;
use crate::args::StorageKeyResolver;
use crate::errors;
use crate::module_loader::CliModuleLoader;
use crate::graph_util::ModuleGraphContainer;
use crate::module_loader::CliModuleLoaderFactory;
use crate::npm::CliNpmResolver;
use crate::ops;
use crate::proc_state::ProcState;
use crate::tools;
use crate::tools::coverage::CoverageCollector;
use crate::util::checksum;
use crate::version;
pub struct CliMainWorkerOptions {
pub argv: Vec<String>,
pub debug: bool,
pub coverage_dir: Option<String>,
pub enable_testing_features: bool,
pub has_node_modules_dir: bool,
pub inspect_brk: bool,
pub inspect_wait: bool,
pub is_inspecting: bool,
pub is_npm_main: bool,
pub location: Option<Url>,
pub maybe_binary_npm_command_name: Option<String>,
pub origin_data_folder_path: PathBuf,
pub seed: Option<u64>,
pub unsafely_ignore_certificate_errors: Option<Vec<String>>,
pub unstable: bool,
}
struct SharedWorkerState {
pub options: CliMainWorkerOptions,
pub storage_key_resolver: StorageKeyResolver,
pub npm_resolver: Arc<CliNpmResolver>,
pub node_resolver: Arc<NodeResolver>,
pub graph_container: Arc<ModuleGraphContainer>,
pub blob_store: BlobStore,
pub broadcast_channel: InMemoryBroadcastChannel,
pub shared_array_buffer_store: SharedArrayBufferStore,
pub compiled_wasm_module_store: CompiledWasmModuleStore,
pub module_loader_factory: CliModuleLoaderFactory,
pub root_cert_store: RootCertStore,
pub node_fs: Arc<dyn deno_node::NodeFs>,
pub maybe_inspector_server: Option<Arc<InspectorServer>>,
}
pub struct CliMainWorker {
main_module: ModuleSpecifier,
is_main_cjs: bool,
worker: MainWorker,
ps: ProcState,
shared: Arc<SharedWorkerState>,
}
impl CliMainWorker {
@ -62,7 +106,7 @@ impl CliMainWorker {
&mut self.worker.js_runtime,
&self.main_module.to_file_path().unwrap().to_string_lossy(),
true,
self.ps.options.inspect_brk().is_some(),
self.shared.options.inspect_brk,
)?;
} else {
self.execute_main_module_possibly_with_npm().await?;
@ -183,8 +227,8 @@ impl CliMainWorker {
&mut self,
id: ModuleId,
) -> Result<(), AnyError> {
if self.ps.npm_resolver.has_packages()
|| self.ps.graph_container.graph().has_node_specifier
if self.shared.npm_resolver.has_packages()
|| self.shared.graph_container.graph().has_node_specifier
{
self.initialize_main_module_for_node()?;
}
@ -192,24 +236,10 @@ impl CliMainWorker {
}
fn initialize_main_module_for_node(&mut self) -> Result<(), AnyError> {
let mut maybe_binary_command_name = None;
if let DenoSubcommand::Run(flags) = self.ps.options.sub_command() {
if let Ok(pkg_ref) = NpmPackageReqReference::from_str(&flags.script) {
// if the user ran a binary command, we'll need to set process.argv[0]
// to be the name of the binary command instead of deno
let binary_name = pkg_ref
.sub_path
.as_deref()
.unwrap_or(pkg_ref.req.name.as_str());
maybe_binary_command_name = Some(binary_name.to_string());
}
}
deno_node::initialize_runtime(
&mut self.worker.js_runtime,
self.ps.options.has_node_modules_dir(),
maybe_binary_command_name,
self.shared.options.has_node_modules_dir,
self.shared.options.maybe_binary_npm_command_name.as_deref(),
)?;
Ok(())
@ -218,7 +248,7 @@ impl CliMainWorker {
pub async fn maybe_setup_coverage_collector(
&mut self,
) -> Result<Option<CoverageCollector>, AnyError> {
if let Some(ref coverage_dir) = self.ps.options.coverage_dir() {
if let Some(coverage_dir) = &self.shared.options.coverage_dir {
let session = self.worker.create_inspector_session().await;
let coverage_dir = PathBuf::from(coverage_dir);
@ -235,142 +265,188 @@ impl CliMainWorker {
}
}
pub async fn create_main_worker(
ps: &ProcState,
main_module: ModuleSpecifier,
permissions: PermissionsContainer,
) -> Result<CliMainWorker, AnyError> {
create_custom_worker(ps, main_module, permissions, vec![], Default::default())
.await
pub struct CliMainWorkerFactory {
shared: Arc<SharedWorkerState>,
}
pub async fn create_custom_worker(
ps: &ProcState,
main_module: ModuleSpecifier,
permissions: PermissionsContainer,
mut custom_extensions: Vec<Extension>,
stdio: deno_runtime::deno_io::Stdio,
) -> Result<CliMainWorker, AnyError> {
let (main_module, is_main_cjs) = if let Ok(package_ref) =
NpmPackageReqReference::from_specifier(&main_module)
{
ps.npm_resolver
.add_package_reqs(vec![package_ref.req.clone()])
.await?;
let node_resolution =
ps.node_resolver.resolve_binary_export(&package_ref)?;
let is_main_cjs = matches!(node_resolution, NodeResolution::CommonJs(_));
(node_resolution.into_url(), is_main_cjs)
} else if ps.options.is_npm_main() {
let node_resolution =
ps.node_resolver.url_to_node_resolution(main_module)?;
let is_main_cjs = matches!(node_resolution, NodeResolution::CommonJs(_));
(node_resolution.into_url(), is_main_cjs)
} else {
(main_module, false)
};
impl CliMainWorkerFactory {
#[allow(clippy::too_many_arguments)]
pub fn new(
storage_key_resolver: StorageKeyResolver,
npm_resolver: Arc<CliNpmResolver>,
node_resolver: Arc<NodeResolver>,
graph_container: Arc<ModuleGraphContainer>,
blob_store: BlobStore,
module_loader_factory: CliModuleLoaderFactory,
root_cert_store: RootCertStore,
node_fs: Arc<dyn deno_node::NodeFs>,
maybe_inspector_server: Option<Arc<InspectorServer>>,
options: CliMainWorkerOptions,
) -> Self {
Self {
shared: Arc::new(SharedWorkerState {
options,
storage_key_resolver,
npm_resolver,
node_resolver,
graph_container,
blob_store,
broadcast_channel: Default::default(),
shared_array_buffer_store: Default::default(),
compiled_wasm_module_store: Default::default(),
module_loader_factory,
root_cert_store,
node_fs,
maybe_inspector_server,
}),
}
}
let module_loader = CliModuleLoader::new(
ps.clone(),
PermissionsContainer::allow_all(),
permissions.clone(),
);
pub async fn create_main_worker(
&self,
main_module: ModuleSpecifier,
permissions: PermissionsContainer,
) -> Result<CliMainWorker, AnyError> {
self
.create_custom_worker(
main_module,
permissions,
vec![],
Default::default(),
)
.await
}
let maybe_inspector_server = ps.maybe_inspector_server.clone();
pub async fn create_custom_worker(
&self,
main_module: ModuleSpecifier,
permissions: PermissionsContainer,
mut custom_extensions: Vec<Extension>,
stdio: deno_runtime::deno_io::Stdio,
) -> Result<CliMainWorker, AnyError> {
let shared = &self.shared;
let (main_module, is_main_cjs) = if let Ok(package_ref) =
NpmPackageReqReference::from_specifier(&main_module)
{
shared
.npm_resolver
.add_package_reqs(vec![package_ref.req.clone()])
.await?;
let node_resolution =
shared.node_resolver.resolve_binary_export(&package_ref)?;
let is_main_cjs = matches!(node_resolution, NodeResolution::CommonJs(_));
(node_resolution.into_url(), is_main_cjs)
} else if shared.options.is_npm_main {
let node_resolution =
shared.node_resolver.url_to_node_resolution(main_module)?;
let is_main_cjs = matches!(node_resolution, NodeResolution::CommonJs(_));
(node_resolution.into_url(), is_main_cjs)
} else {
(main_module, false)
};
let create_web_worker_cb =
create_web_worker_callback(ps.clone(), stdio.clone());
let web_worker_preload_module_cb =
create_web_worker_preload_module_callback(ps.clone());
let web_worker_pre_execute_module_cb =
create_web_worker_pre_execute_module_callback(ps.clone());
let module_loader =
Rc::new(shared.module_loader_factory.create_for_main(
PermissionsContainer::allow_all(),
permissions.clone(),
));
let maybe_inspector_server = shared.maybe_inspector_server.clone();
let maybe_storage_key = ps.options.resolve_storage_key(&main_module);
let origin_storage_dir = maybe_storage_key.as_ref().map(|key| {
ps.dir
.origin_data_folder_path()
.join(checksum::gen(&[key.as_bytes()]))
});
let cache_storage_dir = maybe_storage_key.map(|key| {
// TODO(@satyarohith): storage quota management
// Note: we currently use temp_dir() to avoid managing storage size.
std::env::temp_dir()
.join("deno_cache")
.join(checksum::gen(&[key.as_bytes()]))
});
let create_web_worker_cb =
create_web_worker_callback(shared.clone(), stdio.clone());
let web_worker_preload_module_cb =
create_web_worker_preload_module_callback(shared);
let web_worker_pre_execute_module_cb =
create_web_worker_pre_execute_module_callback(shared.clone());
let mut extensions = ops::cli_exts(ps.npm_resolver.clone());
extensions.append(&mut custom_extensions);
let options = WorkerOptions {
bootstrap: BootstrapOptions {
args: ps.options.argv().clone(),
cpu_count: std::thread::available_parallelism()
.map(|p| p.get())
.unwrap_or(1),
debug_flag: ps
let maybe_storage_key = shared
.storage_key_resolver
.resolve_storage_key(&main_module);
let origin_storage_dir = maybe_storage_key.as_ref().map(|key| {
shared
.options
.log_level()
.map(|l| l == log::Level::Debug)
.unwrap_or(false),
enable_testing_features: ps.options.enable_testing_features(),
locale: deno_core::v8::icu::get_language_tag(),
location: ps.options.location_flag().clone(),
no_color: !colors::use_color(),
is_tty: colors::is_tty(),
runtime_version: version::deno().to_string(),
ts_version: version::TYPESCRIPT.to_string(),
unstable: ps.options.unstable(),
user_agent: version::get_user_agent().to_string(),
inspect: ps.options.is_inspecting(),
},
extensions,
startup_snapshot: Some(crate::js::deno_isolate_init()),
unsafely_ignore_certificate_errors: ps
.options
.unsafely_ignore_certificate_errors()
.clone(),
root_cert_store: Some(ps.root_cert_store.clone()),
seed: ps.options.seed(),
source_map_getter: Some(Box::new(module_loader.clone())),
format_js_error_fn: Some(Arc::new(format_js_error)),
create_web_worker_cb,
web_worker_preload_module_cb,
web_worker_pre_execute_module_cb,
maybe_inspector_server,
should_break_on_first_statement: ps.options.inspect_brk().is_some(),
should_wait_for_inspector_session: ps.options.inspect_wait().is_some(),
module_loader,
node_fs: Some(ps.node_fs.clone()),
npm_resolver: Some(ps.npm_resolver.clone()),
get_error_class_fn: Some(&errors::get_error_class_name),
cache_storage_dir,
origin_storage_dir,
blob_store: ps.blob_store.clone(),
broadcast_channel: ps.broadcast_channel.clone(),
shared_array_buffer_store: Some(ps.shared_array_buffer_store.clone()),
compiled_wasm_module_store: Some(ps.compiled_wasm_module_store.clone()),
stdio,
};
.origin_data_folder_path
.join(checksum::gen(&[key.as_bytes()]))
});
let cache_storage_dir = maybe_storage_key.map(|key| {
// TODO(@satyarohith): storage quota management
// Note: we currently use temp_dir() to avoid managing storage size.
std::env::temp_dir()
.join("deno_cache")
.join(checksum::gen(&[key.as_bytes()]))
});
let worker = MainWorker::bootstrap_from_options(
main_module.clone(),
permissions,
options,
);
let mut extensions = ops::cli_exts(shared.npm_resolver.clone());
extensions.append(&mut custom_extensions);
Ok(CliMainWorker {
main_module,
is_main_cjs,
worker,
ps: ps.clone(),
})
let options = WorkerOptions {
bootstrap: BootstrapOptions {
args: shared.options.argv.clone(),
cpu_count: std::thread::available_parallelism()
.map(|p| p.get())
.unwrap_or(1),
debug_flag: shared.options.debug,
enable_testing_features: shared.options.enable_testing_features,
locale: deno_core::v8::icu::get_language_tag(),
location: shared.options.location.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.options.unstable,
user_agent: version::get_user_agent().to_string(),
inspect: shared.options.is_inspecting,
},
extensions,
startup_snapshot: Some(crate::js::deno_isolate_init()),
unsafely_ignore_certificate_errors: shared
.options
.unsafely_ignore_certificate_errors
.clone(),
root_cert_store: Some(shared.root_cert_store.clone()),
seed: shared.options.seed,
source_map_getter: Some(Box::new(module_loader.clone())),
format_js_error_fn: Some(Arc::new(format_js_error)),
create_web_worker_cb,
web_worker_preload_module_cb,
web_worker_pre_execute_module_cb,
maybe_inspector_server,
should_break_on_first_statement: shared.options.inspect_brk,
should_wait_for_inspector_session: shared.options.inspect_wait,
module_loader,
node_fs: Some(shared.node_fs.clone()),
npm_resolver: Some(shared.npm_resolver.clone()),
get_error_class_fn: Some(&errors::get_error_class_name),
cache_storage_dir,
origin_storage_dir,
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,
};
let worker = MainWorker::bootstrap_from_options(
main_module.clone(),
permissions,
options,
);
Ok(CliMainWorker {
main_module,
is_main_cjs,
worker,
shared: shared.clone(),
})
}
}
// TODO(bartlomieju): this callback could have default value
// and not be required
fn create_web_worker_preload_module_callback(
_ps: ProcState,
_shared: &Arc<SharedWorkerState>,
) -> Arc<WorkerEventCb> {
Arc::new(move |worker| {
let fut = async move { Ok(worker) };
@ -379,16 +455,16 @@ fn create_web_worker_preload_module_callback(
}
fn create_web_worker_pre_execute_module_callback(
ps: ProcState,
shared: Arc<SharedWorkerState>,
) -> Arc<WorkerEventCb> {
Arc::new(move |mut worker| {
let ps = ps.clone();
let shared = shared.clone();
let fut = async move {
// this will be up to date after pre-load
if ps.npm_resolver.has_packages() {
if shared.npm_resolver.has_packages() {
deno_node::initialize_runtime(
&mut worker.js_runtime,
ps.options.has_node_modules_dir(),
shared.options.has_node_modules_dir,
None,
)?;
}
@ -400,27 +476,28 @@ fn create_web_worker_pre_execute_module_callback(
}
fn create_web_worker_callback(
ps: ProcState,
shared: Arc<SharedWorkerState>,
stdio: deno_runtime::deno_io::Stdio,
) -> Arc<CreateWebWorkerCb> {
Arc::new(move |args| {
let maybe_inspector_server = ps.maybe_inspector_server.clone();
let maybe_inspector_server = shared.maybe_inspector_server.clone();
let module_loader = CliModuleLoader::new_for_worker(
ps.clone(),
args.parent_permissions.clone(),
args.permissions.clone(),
);
let module_loader =
Rc::new(shared.module_loader_factory.create_for_worker(
args.parent_permissions.clone(),
args.permissions.clone(),
));
let create_web_worker_cb =
create_web_worker_callback(ps.clone(), stdio.clone());
let preload_module_cb =
create_web_worker_preload_module_callback(ps.clone());
create_web_worker_callback(shared.clone(), stdio.clone());
let preload_module_cb = create_web_worker_preload_module_callback(&shared);
let pre_execute_module_cb =
create_web_worker_pre_execute_module_callback(ps.clone());
create_web_worker_pre_execute_module_callback(shared.clone());
let extensions = ops::cli_exts(ps.npm_resolver.clone());
let extensions = ops::cli_exts(shared.npm_resolver.clone());
let maybe_storage_key = ps.options.resolve_storage_key(&args.main_module);
let maybe_storage_key = shared
.storage_key_resolver
.resolve_storage_key(&args.main_module);
let cache_storage_dir = maybe_storage_key.map(|key| {
// TODO(@satyarohith): storage quota management
// Note: we currently use temp_dir() to avoid managing storage size.
@ -431,49 +508,47 @@ fn create_web_worker_callback(
let options = WebWorkerOptions {
bootstrap: BootstrapOptions {
args: ps.options.argv().clone(),
args: shared.options.argv.clone(),
cpu_count: std::thread::available_parallelism()
.map(|p| p.get())
.unwrap_or(1),
debug_flag: ps
.options
.log_level()
.map(|l| l == log::Level::Debug)
.unwrap_or(false),
enable_testing_features: ps.options.enable_testing_features(),
debug_flag: shared.options.debug,
enable_testing_features: shared.options.enable_testing_features,
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: ps.options.unstable(),
unstable: shared.options.unstable,
user_agent: version::get_user_agent().to_string(),
inspect: ps.options.is_inspecting(),
inspect: shared.options.is_inspecting,
},
extensions,
startup_snapshot: Some(crate::js::deno_isolate_init()),
unsafely_ignore_certificate_errors: ps
unsafely_ignore_certificate_errors: shared
.options
.unsafely_ignore_certificate_errors()
.unsafely_ignore_certificate_errors
.clone(),
root_cert_store: Some(ps.root_cert_store.clone()),
seed: ps.options.seed(),
root_cert_store: Some(shared.root_cert_store.clone()),
seed: shared.options.seed,
create_web_worker_cb,
preload_module_cb,
pre_execute_module_cb,
format_js_error_fn: Some(Arc::new(format_js_error)),
source_map_getter: Some(Box::new(module_loader.clone())),
module_loader,
node_fs: Some(ps.node_fs.clone()),
npm_resolver: Some(ps.npm_resolver.clone()),
node_fs: Some(shared.node_fs.clone()),
npm_resolver: Some(shared.npm_resolver.clone()),
worker_type: args.worker_type,
maybe_inspector_server,
get_error_class_fn: Some(&errors::get_error_class_name),
blob_store: ps.blob_store.clone(),
broadcast_channel: ps.broadcast_channel.clone(),
shared_array_buffer_store: Some(ps.shared_array_buffer_store.clone()),
compiled_wasm_module_store: Some(ps.compiled_wasm_module_store.clone()),
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: stdio.clone(),
cache_storage_dir,
};

View file

@ -534,10 +534,10 @@ deno_core::extension!(deno_node,
pub fn initialize_runtime(
js_runtime: &mut JsRuntime,
uses_local_node_modules_dir: bool,
maybe_binary_command_name: Option<String>,
maybe_binary_command_name: Option<&str>,
) -> Result<(), AnyError> {
let argv0 = if let Some(binary_command_name) = maybe_binary_command_name {
serde_json::to_string(binary_command_name.as_str())?
serde_json::to_string(binary_command_name)?
} else {
"undefined".to_string()
};