mirror of
https://github.com/denoland/deno.git
synced 2025-01-21 04:52:26 -05:00
refactor: update deno_core and use more concrete errors (#27620)
waiting for https://github.com/denoland/deno_core/pull/1043 Fixes #27672
This commit is contained in:
parent
b55451b178
commit
054075730c
22 changed files with 474 additions and 202 deletions
20
Cargo.lock
generated
20
Cargo.lock
generated
|
@ -1532,9 +1532,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_core"
|
name = "deno_core"
|
||||||
version = "0.330.0"
|
version = "0.331.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fd38bbbd68ed873165ccb630322704b44140d3a8c8d50f898beac4d1a8a3358c"
|
checksum = "ce2d1779358cad2bc56d71176298767be628d707bb75585f6f8a4be2da8ccda1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"az",
|
"az",
|
||||||
|
@ -1658,9 +1658,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_error"
|
name = "deno_error"
|
||||||
version = "0.5.3"
|
version = "0.5.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c4da6a58de6932a96f84e133c072fd3b525966ee122a71f3efd48bbff2eed5ac"
|
checksum = "9c23dbc46d5804814b08b4675838f9884e3a52916987ec5105af36d42f9911b5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"deno_error_macro",
|
"deno_error_macro",
|
||||||
"libc",
|
"libc",
|
||||||
|
@ -1672,9 +1672,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_error_macro"
|
name = "deno_error_macro"
|
||||||
version = "0.5.3"
|
version = "0.5.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "46351dff93aed2039407c91e2ded2a5591e42d2795ab3d111288625bb710d3d2"
|
checksum = "babccedee31ce7e57c3e6dff2cb3ab8d68c49d0df8222fe0d11d628e65192790"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -2151,9 +2151,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_ops"
|
name = "deno_ops"
|
||||||
version = "0.206.0"
|
version = "0.207.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4c25ffa9d088ea00748dbef870bba110ac22ebf8cf7b2e9eb288409c5d852af3"
|
checksum = "96f000a21f6969b4c945bc8e9e785aa439f11ca4fd3fbddcd5bebc102167eb37"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"indexmap 2.3.0",
|
"indexmap 2.3.0",
|
||||||
"proc-macro-rules",
|
"proc-macro-rules",
|
||||||
|
@ -6947,9 +6947,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_v8"
|
name = "serde_v8"
|
||||||
version = "0.239.0"
|
version = "0.240.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3caa6d882827148e5d9052d9d8d6d1c9d6ad426ed00cab46cafb8c07a0e7126a"
|
checksum = "cd0494d74c40ab94f53a19485de359ea6a55f05341b817b93440b673c1ce8ec6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"deno_error",
|
"deno_error",
|
||||||
"num-bigint",
|
"num-bigint",
|
||||||
|
|
|
@ -49,7 +49,7 @@ repository = "https://github.com/denoland/deno"
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
deno_ast = { version = "=0.44.0", features = ["transpiling"] }
|
deno_ast = { version = "=0.44.0", features = ["transpiling"] }
|
||||||
deno_core = { version = "0.330.0" }
|
deno_core = { version = "0.331.0" }
|
||||||
|
|
||||||
deno_bench_util = { version = "0.180.0", path = "./bench_util" }
|
deno_bench_util = { version = "0.180.0", path = "./bench_util" }
|
||||||
deno_config = { version = "=0.45.0", features = ["workspace", "sync"] }
|
deno_config = { version = "=0.45.0", features = ["workspace", "sync"] }
|
||||||
|
@ -123,7 +123,7 @@ dashmap = "5.5.3"
|
||||||
data-encoding = "2.3.3"
|
data-encoding = "2.3.3"
|
||||||
data-url = "=0.3.1"
|
data-url = "=0.3.1"
|
||||||
deno_cache_dir = "=0.16.0"
|
deno_cache_dir = "=0.16.0"
|
||||||
deno_error = "=0.5.3"
|
deno_error = "=0.5.5"
|
||||||
deno_package_json = { version = "0.4.0", default-features = false }
|
deno_package_json = { version = "0.4.0", default-features = false }
|
||||||
deno_unsync = "0.4.2"
|
deno_unsync = "0.4.2"
|
||||||
dlopen2 = "0.6.1"
|
dlopen2 = "0.6.1"
|
||||||
|
|
|
@ -61,11 +61,13 @@ impl<'a, T> std::ops::DerefMut for Guard<'a, T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, thiserror::Error, deno_error::JsError)]
|
#[derive(Debug, thiserror::Error, deno_error::JsError)]
|
||||||
#[error("Failed writing lockfile")]
|
pub enum AtomicWriteFileWithRetriesError {
|
||||||
#[class(inherit)]
|
#[class(inherit)]
|
||||||
struct AtomicWriteFileWithRetriesError {
|
#[error(transparent)]
|
||||||
#[source]
|
Changed(JsErrorBox),
|
||||||
source: std::io::Error,
|
#[class(inherit)]
|
||||||
|
#[error("Failed writing lockfile")]
|
||||||
|
Io(#[source] std::io::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CliLockfile {
|
impl CliLockfile {
|
||||||
|
@ -87,12 +89,16 @@ impl CliLockfile {
|
||||||
self.lockfile.lock().overwrite
|
self.lockfile.lock().overwrite
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_if_changed(&self) -> Result<(), JsErrorBox> {
|
pub fn write_if_changed(
|
||||||
|
&self,
|
||||||
|
) -> Result<(), AtomicWriteFileWithRetriesError> {
|
||||||
if self.skip_write {
|
if self.skip_write {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
self.error_if_changed()?;
|
self
|
||||||
|
.error_if_changed()
|
||||||
|
.map_err(AtomicWriteFileWithRetriesError::Changed)?;
|
||||||
let mut lockfile = self.lockfile.lock();
|
let mut lockfile = self.lockfile.lock();
|
||||||
let Some(bytes) = lockfile.resolve_write_bytes() else {
|
let Some(bytes) = lockfile.resolve_write_bytes() else {
|
||||||
return Ok(()); // nothing to do
|
return Ok(()); // nothing to do
|
||||||
|
@ -105,9 +111,7 @@ impl CliLockfile {
|
||||||
&bytes,
|
&bytes,
|
||||||
cache::CACHE_PERM,
|
cache::CACHE_PERM,
|
||||||
)
|
)
|
||||||
.map_err(|source| {
|
.map_err(AtomicWriteFileWithRetriesError::Io)?;
|
||||||
JsErrorBox::from_err(AtomicWriteFileWithRetriesError { source })
|
|
||||||
})?;
|
|
||||||
lockfile.has_content_changed = false;
|
lockfile.has_content_changed = false;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,6 +82,7 @@ use deno_terminal::colors;
|
||||||
use dotenvy::from_filename;
|
use dotenvy::from_filename;
|
||||||
pub use flags::*;
|
pub use flags::*;
|
||||||
use import_map::resolve_import_map_value_from_specifier;
|
use import_map::resolve_import_map_value_from_specifier;
|
||||||
|
pub use lockfile::AtomicWriteFileWithRetriesError;
|
||||||
pub use lockfile::CliLockfile;
|
pub use lockfile::CliLockfile;
|
||||||
pub use lockfile::CliLockfileReadFromPathOptions;
|
pub use lockfile::CliLockfileReadFromPathOptions;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
|
|
|
@ -112,9 +112,9 @@ impl Emitter {
|
||||||
&self,
|
&self,
|
||||||
specifier: &ModuleSpecifier,
|
specifier: &ModuleSpecifier,
|
||||||
media_type: MediaType,
|
media_type: MediaType,
|
||||||
module_kind: deno_ast::ModuleKind,
|
module_kind: ModuleKind,
|
||||||
source: &Arc<str>,
|
source: &Arc<str>,
|
||||||
) -> Result<String, AnyError> {
|
) -> Result<String, EmitParsedSourceHelperError> {
|
||||||
// Note: keep this in sync with the sync version below
|
// Note: keep this in sync with the sync version below
|
||||||
let helper = EmitParsedSourceHelper(self);
|
let helper = EmitParsedSourceHelper(self);
|
||||||
match helper.pre_emit_parsed_source(specifier, module_kind, source) {
|
match helper.pre_emit_parsed_source(specifier, module_kind, source) {
|
||||||
|
|
|
@ -201,7 +201,7 @@ async fn run_subcommand(flags: Arc<Flags>) -> Result<i32, AnyError> {
|
||||||
match result {
|
match result {
|
||||||
Ok(v) => Ok(v),
|
Ok(v) => Ok(v),
|
||||||
Err(script_err) => {
|
Err(script_err) => {
|
||||||
if let Some(ResolvePkgFolderFromDenoReqError::Byonm(ByonmResolvePkgFolderFromDenoReqError::UnmatchedReq(_))) = util::result::any_and_jserrorbox_downcast_ref::<ResolvePkgFolderFromDenoReqError>(&script_err) {
|
if let Some(worker::CreateCustomWorkerError::ResolvePkgFolderFromDenoReq(ResolvePkgFolderFromDenoReqError::Byonm(ByonmResolvePkgFolderFromDenoReqError::UnmatchedReq(_)))) = util::result::any_and_jserrorbox_downcast_ref::<worker::CreateCustomWorkerError>(&script_err) {
|
||||||
if flags.node_modules_dir.is_none() {
|
if flags.node_modules_dir.is_none() {
|
||||||
let mut flags = flags.deref().clone();
|
let mut flags = flags.deref().clone();
|
||||||
let watch = match &flags.subcommand {
|
let watch = match &flags.subcommand {
|
||||||
|
|
|
@ -13,8 +13,6 @@ use std::sync::Arc;
|
||||||
|
|
||||||
use deno_ast::MediaType;
|
use deno_ast::MediaType;
|
||||||
use deno_ast::ModuleKind;
|
use deno_ast::ModuleKind;
|
||||||
use deno_core::anyhow::anyhow;
|
|
||||||
use deno_core::anyhow::Context;
|
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
use deno_core::error::ModuleLoaderError;
|
use deno_core::error::ModuleLoaderError;
|
||||||
use deno_core::futures::future::FutureExt;
|
use deno_core::futures::future::FutureExt;
|
||||||
|
@ -45,6 +43,7 @@ use deno_lib::worker::ModuleLoaderFactory;
|
||||||
use deno_resolver::npm::DenoInNpmPackageChecker;
|
use deno_resolver::npm::DenoInNpmPackageChecker;
|
||||||
use deno_runtime::code_cache;
|
use deno_runtime::code_cache;
|
||||||
use deno_runtime::deno_node::create_host_defined_options;
|
use deno_runtime::deno_node::create_host_defined_options;
|
||||||
|
use deno_runtime::deno_node::ops::require::UnableToGetCwdError;
|
||||||
use deno_runtime::deno_node::NodeRequireLoader;
|
use deno_runtime::deno_node::NodeRequireLoader;
|
||||||
use deno_runtime::deno_permissions::PermissionsContainer;
|
use deno_runtime::deno_permissions::PermissionsContainer;
|
||||||
use deno_semver::npm::NpmPackageReqReference;
|
use deno_semver::npm::NpmPackageReqReference;
|
||||||
|
@ -99,6 +98,11 @@ pub enum PrepareModuleLoadError {
|
||||||
Check(#[from] CheckError),
|
Check(#[from] CheckError),
|
||||||
#[class(inherit)]
|
#[class(inherit)]
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
|
AtomicWriteFileWithRetries(
|
||||||
|
#[from] crate::args::AtomicWriteFileWithRetriesError,
|
||||||
|
),
|
||||||
|
#[class(inherit)]
|
||||||
|
#[error(transparent)]
|
||||||
Other(#[from] JsErrorBox),
|
Other(#[from] JsErrorBox),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -419,6 +423,55 @@ impl ModuleLoaderFactory for CliModuleLoaderFactory {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, thiserror::Error, deno_error::JsError)]
|
||||||
|
pub enum LoadCodeSourceError {
|
||||||
|
#[class(inherit)]
|
||||||
|
#[error(transparent)]
|
||||||
|
NpmModuleLoad(crate::resolver::NpmModuleLoadError),
|
||||||
|
#[class(inherit)]
|
||||||
|
#[error(transparent)]
|
||||||
|
LoadPreparedModule(#[from] LoadPreparedModuleError),
|
||||||
|
#[class(generic)]
|
||||||
|
#[error("Loading unprepared module: {}{}", .specifier, .maybe_referrer.as_ref().map(|r| format!(", imported from: {}", r)).unwrap_or_default())]
|
||||||
|
LoadUnpreparedModule {
|
||||||
|
specifier: ModuleSpecifier,
|
||||||
|
maybe_referrer: Option<ModuleSpecifier>,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, thiserror::Error, deno_error::JsError)]
|
||||||
|
pub enum LoadPreparedModuleError {
|
||||||
|
#[class(inherit)]
|
||||||
|
#[error(transparent)]
|
||||||
|
NpmModuleLoad(#[from] crate::emit::EmitParsedSourceHelperError),
|
||||||
|
#[class(inherit)]
|
||||||
|
#[error(transparent)]
|
||||||
|
LoadMaybeCjs(#[from] LoadMaybeCjsError),
|
||||||
|
#[class(inherit)]
|
||||||
|
#[error(transparent)]
|
||||||
|
Other(#[from] JsErrorBox),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, thiserror::Error, deno_error::JsError)]
|
||||||
|
pub enum LoadMaybeCjsError {
|
||||||
|
#[class(inherit)]
|
||||||
|
#[error(transparent)]
|
||||||
|
NpmModuleLoad(#[from] crate::emit::EmitParsedSourceHelperError),
|
||||||
|
#[class(inherit)]
|
||||||
|
#[error(transparent)]
|
||||||
|
TranslateCjsToEsm(#[from] node_resolver::analyze::TranslateCjsToEsmError),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, thiserror::Error, deno_error::JsError)]
|
||||||
|
#[class(inherit)]
|
||||||
|
#[error("Could not resolve '{reference}'")]
|
||||||
|
pub struct CouldNotResolveError {
|
||||||
|
reference: deno_semver::npm::NpmPackageNvReference,
|
||||||
|
#[source]
|
||||||
|
#[inherit]
|
||||||
|
source: node_resolver::errors::PackageSubpathResolveError,
|
||||||
|
}
|
||||||
|
|
||||||
struct CliModuleLoaderInner<TGraphContainer: ModuleGraphContainer> {
|
struct CliModuleLoaderInner<TGraphContainer: ModuleGraphContainer> {
|
||||||
lib: TsTypeLib,
|
lib: TsTypeLib,
|
||||||
is_worker: bool,
|
is_worker: bool,
|
||||||
|
@ -443,7 +496,10 @@ impl<TGraphContainer: ModuleGraphContainer>
|
||||||
maybe_referrer: Option<&ModuleSpecifier>,
|
maybe_referrer: Option<&ModuleSpecifier>,
|
||||||
requested_module_type: RequestedModuleType,
|
requested_module_type: RequestedModuleType,
|
||||||
) -> Result<ModuleSource, ModuleLoaderError> {
|
) -> Result<ModuleSource, ModuleLoaderError> {
|
||||||
let code_source = self.load_code_source(specifier, maybe_referrer).await?;
|
let code_source = self
|
||||||
|
.load_code_source(specifier, maybe_referrer)
|
||||||
|
.await
|
||||||
|
.map_err(JsErrorBox::from_err)?;
|
||||||
let code = if self.shared.is_inspecting
|
let code = if self.shared.is_inspecting
|
||||||
|| code_source.media_type == MediaType::Wasm
|
|| code_source.media_type == MediaType::Wasm
|
||||||
{
|
{
|
||||||
|
@ -504,7 +560,7 @@ impl<TGraphContainer: ModuleGraphContainer>
|
||||||
&self,
|
&self,
|
||||||
specifier: &ModuleSpecifier,
|
specifier: &ModuleSpecifier,
|
||||||
maybe_referrer: Option<&ModuleSpecifier>,
|
maybe_referrer: Option<&ModuleSpecifier>,
|
||||||
) -> Result<ModuleCodeStringSource, AnyError> {
|
) -> Result<ModuleCodeStringSource, LoadCodeSourceError> {
|
||||||
if let Some(code_source) = self.load_prepared_module(specifier).await? {
|
if let Some(code_source) = self.load_prepared_module(specifier).await? {
|
||||||
return Ok(code_source);
|
return Ok(code_source);
|
||||||
}
|
}
|
||||||
|
@ -513,14 +569,14 @@ impl<TGraphContainer: ModuleGraphContainer>
|
||||||
.shared
|
.shared
|
||||||
.npm_module_loader
|
.npm_module_loader
|
||||||
.load(specifier, maybe_referrer)
|
.load(specifier, maybe_referrer)
|
||||||
.await;
|
.await
|
||||||
|
.map_err(LoadCodeSourceError::NpmModuleLoad);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut msg = format!("Loading unprepared module: {specifier}");
|
Err(LoadCodeSourceError::LoadUnpreparedModule {
|
||||||
if let Some(referrer) = maybe_referrer {
|
specifier: specifier.clone(),
|
||||||
msg = format!("{}, imported from: {}", msg, referrer.as_str());
|
maybe_referrer: maybe_referrer.cloned(),
|
||||||
}
|
})
|
||||||
Err(anyhow!(msg))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_referrer(
|
fn resolve_referrer(
|
||||||
|
@ -543,7 +599,8 @@ impl<TGraphContainer: ModuleGraphContainer>
|
||||||
.map_err(|e| e.into())
|
.map_err(|e| e.into())
|
||||||
} else {
|
} else {
|
||||||
// this cwd check is slow, so try to avoid it
|
// this cwd check is slow, so try to avoid it
|
||||||
let cwd = std::env::current_dir().context("Unable to get CWD")?;
|
let cwd = std::env::current_dir()
|
||||||
|
.map_err(|e| JsErrorBox::from_err(UnableToGetCwdError(e)))?;
|
||||||
deno_core::resolve_path(referrer, &cwd).map_err(|e| e.into())
|
deno_core::resolve_path(referrer, &cwd).map_err(|e| e.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -622,8 +679,11 @@ impl<TGraphContainer: ModuleGraphContainer>
|
||||||
ResolutionMode::Import,
|
ResolutionMode::Import,
|
||||||
NodeResolutionKind::Execution,
|
NodeResolutionKind::Execution,
|
||||||
)
|
)
|
||||||
.with_context(|| {
|
.map_err(|source| {
|
||||||
format!("Could not resolve '{}'.", module.nv_reference)
|
JsErrorBox::from_err(CouldNotResolveError {
|
||||||
|
reference: module.nv_reference.clone(),
|
||||||
|
source,
|
||||||
|
})
|
||||||
})?
|
})?
|
||||||
}
|
}
|
||||||
Some(Module::Node(module)) => module.specifier.clone(),
|
Some(Module::Node(module)) => module.specifier.clone(),
|
||||||
|
@ -644,7 +704,7 @@ impl<TGraphContainer: ModuleGraphContainer>
|
||||||
async fn load_prepared_module(
|
async fn load_prepared_module(
|
||||||
&self,
|
&self,
|
||||||
specifier: &ModuleSpecifier,
|
specifier: &ModuleSpecifier,
|
||||||
) -> Result<Option<ModuleCodeStringSource>, AnyError> {
|
) -> Result<Option<ModuleCodeStringSource>, LoadPreparedModuleError> {
|
||||||
// Note: keep this in sync with the sync version below
|
// Note: keep this in sync with the sync version below
|
||||||
let graph = self.graph_container.graph();
|
let graph = self.graph_container.graph();
|
||||||
match self.load_prepared_module_or_defer_emit(&graph, specifier)? {
|
match self.load_prepared_module_or_defer_emit(&graph, specifier)? {
|
||||||
|
@ -676,7 +736,8 @@ impl<TGraphContainer: ModuleGraphContainer>
|
||||||
}) => self
|
}) => self
|
||||||
.load_maybe_cjs(specifier, media_type, source)
|
.load_maybe_cjs(specifier, media_type, source)
|
||||||
.await
|
.await
|
||||||
.map(Some),
|
.map(Some)
|
||||||
|
.map_err(LoadPreparedModuleError::LoadMaybeCjs),
|
||||||
None => Ok(None),
|
None => Ok(None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -837,7 +898,7 @@ impl<TGraphContainer: ModuleGraphContainer>
|
||||||
specifier: &ModuleSpecifier,
|
specifier: &ModuleSpecifier,
|
||||||
media_type: MediaType,
|
media_type: MediaType,
|
||||||
original_source: &Arc<str>,
|
original_source: &Arc<str>,
|
||||||
) -> Result<ModuleCodeStringSource, AnyError> {
|
) -> Result<ModuleCodeStringSource, LoadMaybeCjsError> {
|
||||||
let js_source = if media_type.is_emittable() {
|
let js_source = if media_type.is_emittable() {
|
||||||
Cow::Owned(
|
Cow::Owned(
|
||||||
self
|
self
|
||||||
|
|
17
cli/node.rs
17
cli/node.rs
|
@ -5,13 +5,14 @@ use std::sync::Arc;
|
||||||
|
|
||||||
use deno_ast::MediaType;
|
use deno_ast::MediaType;
|
||||||
use deno_ast::ModuleSpecifier;
|
use deno_ast::ModuleSpecifier;
|
||||||
use deno_core::error::AnyError;
|
use deno_error::JsErrorBox;
|
||||||
use deno_graph::ParsedSourceStore;
|
use deno_graph::ParsedSourceStore;
|
||||||
use deno_resolver::npm::DenoInNpmPackageChecker;
|
use deno_resolver::npm::DenoInNpmPackageChecker;
|
||||||
use deno_runtime::deno_fs;
|
use deno_runtime::deno_fs;
|
||||||
use deno_runtime::deno_node::RealIsBuiltInNodeModuleChecker;
|
use deno_runtime::deno_node::RealIsBuiltInNodeModuleChecker;
|
||||||
use node_resolver::analyze::CjsAnalysis as ExtNodeCjsAnalysis;
|
use node_resolver::analyze::CjsAnalysis as ExtNodeCjsAnalysis;
|
||||||
use node_resolver::analyze::CjsAnalysisExports;
|
use node_resolver::analyze::CjsAnalysisExports;
|
||||||
|
use node_resolver::analyze::CjsCodeAnalysisError;
|
||||||
use node_resolver::analyze::CjsCodeAnalyzer;
|
use node_resolver::analyze::CjsCodeAnalyzer;
|
||||||
use node_resolver::analyze::NodeCodeTranslator;
|
use node_resolver::analyze::NodeCodeTranslator;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
@ -75,7 +76,7 @@ impl CliCjsCodeAnalyzer {
|
||||||
&self,
|
&self,
|
||||||
specifier: &ModuleSpecifier,
|
specifier: &ModuleSpecifier,
|
||||||
source: &str,
|
source: &str,
|
||||||
) -> Result<CliCjsAnalysis, AnyError> {
|
) -> Result<CliCjsAnalysis, CjsCodeAnalysisError> {
|
||||||
let source_hash = CacheDBHash::from_hashable(source);
|
let source_hash = CacheDBHash::from_hashable(source);
|
||||||
if let Some(analysis) =
|
if let Some(analysis) =
|
||||||
self.cache.get_cjs_analysis(specifier.as_str(), source_hash)
|
self.cache.get_cjs_analysis(specifier.as_str(), source_hash)
|
||||||
|
@ -102,9 +103,10 @@ impl CliCjsCodeAnalyzer {
|
||||||
deno_core::unsync::spawn_blocking({
|
deno_core::unsync::spawn_blocking({
|
||||||
let specifier = specifier.clone();
|
let specifier = specifier.clone();
|
||||||
let source: Arc<str> = source.into();
|
let source: Arc<str> = source.into();
|
||||||
move || -> Result<_, AnyError> {
|
move || -> Result<_, CjsCodeAnalysisError> {
|
||||||
let parsed_source =
|
let parsed_source = maybe_parsed_source
|
||||||
maybe_parsed_source.map(Ok).unwrap_or_else(|| {
|
.map(Ok)
|
||||||
|
.unwrap_or_else(|| {
|
||||||
deno_ast::parse_program(deno_ast::ParseParams {
|
deno_ast::parse_program(deno_ast::ParseParams {
|
||||||
specifier,
|
specifier,
|
||||||
text: source,
|
text: source,
|
||||||
|
@ -113,7 +115,8 @@ impl CliCjsCodeAnalyzer {
|
||||||
scope_analysis: false,
|
scope_analysis: false,
|
||||||
maybe_syntax: None,
|
maybe_syntax: None,
|
||||||
})
|
})
|
||||||
})?;
|
})
|
||||||
|
.map_err(JsErrorBox::from_err)?;
|
||||||
let is_script = parsed_source.compute_is_script();
|
let is_script = parsed_source.compute_is_script();
|
||||||
let is_cjs = cjs_tracker.is_cjs_with_known_is_script(
|
let is_cjs = cjs_tracker.is_cjs_with_known_is_script(
|
||||||
parsed_source.specifier(),
|
parsed_source.specifier(),
|
||||||
|
@ -151,7 +154,7 @@ impl CjsCodeAnalyzer for CliCjsCodeAnalyzer {
|
||||||
&self,
|
&self,
|
||||||
specifier: &ModuleSpecifier,
|
specifier: &ModuleSpecifier,
|
||||||
source: Option<Cow<'a, str>>,
|
source: Option<Cow<'a, str>>,
|
||||||
) -> Result<ExtNodeCjsAnalysis<'a>, AnyError> {
|
) -> Result<ExtNodeCjsAnalysis<'a>, CjsCodeAnalysisError> {
|
||||||
let source = match source {
|
let source = match source {
|
||||||
Some(source) => source,
|
Some(source) => source,
|
||||||
None => {
|
None => {
|
||||||
|
|
105
cli/resolver.rs
105
cli/resolver.rs
|
@ -1,6 +1,7 @@
|
||||||
// Copyright 2018-2025 the Deno authors. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
use std::path::PathBuf;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
|
@ -8,8 +9,6 @@ use dashmap::DashSet;
|
||||||
use deno_ast::MediaType;
|
use deno_ast::MediaType;
|
||||||
use deno_config::workspace::MappedResolutionDiagnostic;
|
use deno_config::workspace::MappedResolutionDiagnostic;
|
||||||
use deno_config::workspace::MappedResolutionError;
|
use deno_config::workspace::MappedResolutionError;
|
||||||
use deno_core::anyhow::Context;
|
|
||||||
use deno_core::error::AnyError;
|
|
||||||
use deno_core::url::Url;
|
use deno_core::url::Url;
|
||||||
use deno_core::ModuleSourceCode;
|
use deno_core::ModuleSourceCode;
|
||||||
use deno_core::ModuleSpecifier;
|
use deno_core::ModuleSpecifier;
|
||||||
|
@ -84,6 +83,62 @@ pub struct NpmModuleLoader {
|
||||||
node_code_translator: Arc<CliNodeCodeTranslator>,
|
node_code_translator: Arc<CliNodeCodeTranslator>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Error, deno_error::JsError)]
|
||||||
|
pub enum NpmModuleLoadError {
|
||||||
|
#[class(inherit)]
|
||||||
|
#[error(transparent)]
|
||||||
|
NotSupportedKindInNpm(#[from] NotSupportedKindInNpmError),
|
||||||
|
#[class(inherit)]
|
||||||
|
#[error(transparent)]
|
||||||
|
ClosestPkgJson(#[from] node_resolver::errors::ClosestPkgJsonError),
|
||||||
|
#[class(inherit)]
|
||||||
|
#[error(transparent)]
|
||||||
|
TranslateCjsToEsm(#[from] node_resolver::analyze::TranslateCjsToEsmError),
|
||||||
|
#[class(inherit)]
|
||||||
|
#[error("{}", format_message(file_path, maybe_referrer))]
|
||||||
|
Fs {
|
||||||
|
file_path: PathBuf,
|
||||||
|
maybe_referrer: Option<ModuleSpecifier>,
|
||||||
|
#[source]
|
||||||
|
#[inherit]
|
||||||
|
source: deno_runtime::deno_io::fs::FsError,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
fn format_message(
|
||||||
|
file_path: &std::path::Path,
|
||||||
|
maybe_referrer: &Option<ModuleSpecifier>,
|
||||||
|
) -> String {
|
||||||
|
if file_path.is_dir() {
|
||||||
|
// directory imports are not allowed when importing from an
|
||||||
|
// ES module, so provide the user with a helpful error message
|
||||||
|
let dir_path = file_path;
|
||||||
|
let mut msg = "Directory import ".to_string();
|
||||||
|
msg.push_str(&dir_path.to_string_lossy());
|
||||||
|
if let Some(referrer) = maybe_referrer {
|
||||||
|
msg.push_str(" is not supported resolving import from ");
|
||||||
|
msg.push_str(referrer.as_str());
|
||||||
|
let entrypoint_name = ["index.mjs", "index.js", "index.cjs"]
|
||||||
|
.iter()
|
||||||
|
.find(|e| dir_path.join(e).is_file());
|
||||||
|
if let Some(entrypoint_name) = entrypoint_name {
|
||||||
|
msg.push_str("\nDid you mean to import ");
|
||||||
|
msg.push_str(entrypoint_name);
|
||||||
|
msg.push_str(" within the directory?");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
msg
|
||||||
|
} else {
|
||||||
|
let mut msg = "Unable to load ".to_string();
|
||||||
|
msg.push_str(&file_path.to_string_lossy());
|
||||||
|
if let Some(referrer) = maybe_referrer {
|
||||||
|
msg.push_str(" imported from ");
|
||||||
|
msg.push_str(referrer.as_str());
|
||||||
|
}
|
||||||
|
msg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl NpmModuleLoader {
|
impl NpmModuleLoader {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
cjs_tracker: Arc<CliCjsTracker>,
|
cjs_tracker: Arc<CliCjsTracker>,
|
||||||
|
@ -101,50 +156,26 @@ impl NpmModuleLoader {
|
||||||
&self,
|
&self,
|
||||||
specifier: &ModuleSpecifier,
|
specifier: &ModuleSpecifier,
|
||||||
maybe_referrer: Option<&ModuleSpecifier>,
|
maybe_referrer: Option<&ModuleSpecifier>,
|
||||||
) -> Result<ModuleCodeStringSource, AnyError> {
|
) -> Result<ModuleCodeStringSource, NpmModuleLoadError> {
|
||||||
let file_path = specifier.to_file_path().unwrap();
|
let file_path = specifier.to_file_path().unwrap();
|
||||||
let code = self
|
let code = self
|
||||||
.fs
|
.fs
|
||||||
.read_file_async(file_path.clone(), None)
|
.read_file_async(file_path.clone(), None)
|
||||||
.await
|
.await
|
||||||
.map_err(AnyError::from)
|
.map_err(|source| NpmModuleLoadError::Fs {
|
||||||
.with_context(|| {
|
file_path,
|
||||||
if file_path.is_dir() {
|
maybe_referrer: maybe_referrer.cloned(),
|
||||||
// directory imports are not allowed when importing from an
|
source,
|
||||||
// ES module, so provide the user with a helpful error message
|
|
||||||
let dir_path = file_path;
|
|
||||||
let mut msg = "Directory import ".to_string();
|
|
||||||
msg.push_str(&dir_path.to_string_lossy());
|
|
||||||
if let Some(referrer) = &maybe_referrer {
|
|
||||||
msg.push_str(" is not supported resolving import from ");
|
|
||||||
msg.push_str(referrer.as_str());
|
|
||||||
let entrypoint_name = ["index.mjs", "index.js", "index.cjs"]
|
|
||||||
.iter()
|
|
||||||
.find(|e| dir_path.join(e).is_file());
|
|
||||||
if let Some(entrypoint_name) = entrypoint_name {
|
|
||||||
msg.push_str("\nDid you mean to import ");
|
|
||||||
msg.push_str(entrypoint_name);
|
|
||||||
msg.push_str(" within the directory?");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
msg
|
|
||||||
} else {
|
|
||||||
let mut msg = "Unable to load ".to_string();
|
|
||||||
msg.push_str(&file_path.to_string_lossy());
|
|
||||||
if let Some(referrer) = &maybe_referrer {
|
|
||||||
msg.push_str(" imported from ");
|
|
||||||
msg.push_str(referrer.as_str());
|
|
||||||
}
|
|
||||||
msg
|
|
||||||
}
|
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let media_type = MediaType::from_specifier(specifier);
|
let media_type = MediaType::from_specifier(specifier);
|
||||||
if media_type.is_emittable() {
|
if media_type.is_emittable() {
|
||||||
return Err(AnyError::from(NotSupportedKindInNpmError {
|
return Err(NpmModuleLoadError::NotSupportedKindInNpm(
|
||||||
media_type,
|
NotSupportedKindInNpmError {
|
||||||
specifier: specifier.clone(),
|
media_type,
|
||||||
}));
|
specifier: specifier.clone(),
|
||||||
|
},
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let code = if self.cjs_tracker.is_maybe_cjs(specifier, media_type)? {
|
let code = if self.cjs_tracker.is_maybe_cjs(specifier, media_type)? {
|
||||||
|
|
|
@ -37,6 +37,7 @@ use deno_core::futures::AsyncReadExt;
|
||||||
use deno_core::futures::AsyncSeekExt;
|
use deno_core::futures::AsyncSeekExt;
|
||||||
use deno_core::serde_json;
|
use deno_core::serde_json;
|
||||||
use deno_core::url::Url;
|
use deno_core::url::Url;
|
||||||
|
use deno_error::JsErrorBox;
|
||||||
use deno_graph::ModuleGraph;
|
use deno_graph::ModuleGraph;
|
||||||
use deno_lib::cache::DenoDir;
|
use deno_lib::cache::DenoDir;
|
||||||
use deno_lib::standalone::virtual_fs::FileSystemCaseSensitivity;
|
use deno_lib::standalone::virtual_fs::FileSystemCaseSensitivity;
|
||||||
|
@ -278,7 +279,7 @@ impl StandaloneModules {
|
||||||
pub fn resolve_specifier<'a>(
|
pub fn resolve_specifier<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
specifier: &'a ModuleSpecifier,
|
specifier: &'a ModuleSpecifier,
|
||||||
) -> Result<Option<&'a ModuleSpecifier>, AnyError> {
|
) -> Result<Option<&'a ModuleSpecifier>, JsErrorBox> {
|
||||||
if specifier.scheme() == "file" {
|
if specifier.scheme() == "file" {
|
||||||
Ok(Some(specifier))
|
Ok(Some(specifier))
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -414,7 +414,8 @@ impl ModuleLoader for EmbeddedModuleLoader {
|
||||||
let code_source = shared
|
let code_source = shared
|
||||||
.npm_module_loader
|
.npm_module_loader
|
||||||
.load(&original_specifier, maybe_referrer.as_ref())
|
.load(&original_specifier, maybe_referrer.as_ref())
|
||||||
.await?;
|
.await
|
||||||
|
.map_err(JsErrorBox::from_err)?;
|
||||||
let code_cache_entry = shared.get_code_cache(
|
let code_cache_entry = shared.get_code_cache(
|
||||||
&code_source.found_url,
|
&code_source.found_url,
|
||||||
code_source.code.as_bytes(),
|
code_source.code.as_bytes(),
|
||||||
|
@ -477,7 +478,8 @@ impl ModuleLoader for EmbeddedModuleLoader {
|
||||||
let source = shared
|
let source = shared
|
||||||
.node_code_translator
|
.node_code_translator
|
||||||
.translate_cjs_to_esm(&module_specifier, Some(source))
|
.translate_cjs_to_esm(&module_specifier, Some(source))
|
||||||
.await?;
|
.await
|
||||||
|
.map_err(JsErrorBox::from_err)?;
|
||||||
let module_source = match source {
|
let module_source = match source {
|
||||||
Cow::Owned(source) => ModuleSourceCode::String(source.into()),
|
Cow::Owned(source) => ModuleSourceCode::String(source.into()),
|
||||||
Cow::Borrowed(source) => {
|
Cow::Borrowed(source) => {
|
||||||
|
|
|
@ -17,6 +17,7 @@ use deno_core::url::Url;
|
||||||
use deno_core::FastString;
|
use deno_core::FastString;
|
||||||
use deno_core::ModuleSourceCode;
|
use deno_core::ModuleSourceCode;
|
||||||
use deno_core::ModuleType;
|
use deno_core::ModuleType;
|
||||||
|
use deno_error::JsErrorBox;
|
||||||
use deno_lib::standalone::virtual_fs::VirtualDirectoryEntries;
|
use deno_lib::standalone::virtual_fs::VirtualDirectoryEntries;
|
||||||
use deno_npm::resolution::SerializedNpmResolutionSnapshot;
|
use deno_npm::resolution::SerializedNpmResolutionSnapshot;
|
||||||
use deno_npm::resolution::SerializedNpmResolutionSnapshotPackage;
|
use deno_npm::resolution::SerializedNpmResolutionSnapshotPackage;
|
||||||
|
@ -441,12 +442,15 @@ impl RemoteModulesStore {
|
||||||
pub fn resolve_specifier<'a>(
|
pub fn resolve_specifier<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
specifier: &'a Url,
|
specifier: &'a Url,
|
||||||
) -> Result<Option<&'a Url>, AnyError> {
|
) -> Result<Option<&'a Url>, JsErrorBox> {
|
||||||
let mut count = 0;
|
let mut count = 0;
|
||||||
let mut current = specifier;
|
let mut current = specifier;
|
||||||
loop {
|
loop {
|
||||||
if count > 10 {
|
if count > 10 {
|
||||||
bail!("Too many redirects resolving '{}'", specifier);
|
return Err(JsErrorBox::generic(format!(
|
||||||
|
"Too many redirects resolving '{}'",
|
||||||
|
specifier
|
||||||
|
)));
|
||||||
}
|
}
|
||||||
match self.specifiers.get(current) {
|
match self.specifiers.get(current) {
|
||||||
Some(RemoteModulesStoreSpecifierValue::Redirect(to)) => {
|
Some(RemoteModulesStoreSpecifierValue::Redirect(to)) => {
|
||||||
|
|
|
@ -48,6 +48,7 @@ use crate::util::fs::collect_specifiers;
|
||||||
use crate::util::path::is_script_ext;
|
use crate::util::path::is_script_ext;
|
||||||
use crate::util::path::matches_pattern_or_exact_path;
|
use crate::util::path::matches_pattern_or_exact_path;
|
||||||
use crate::worker::CliMainWorkerFactory;
|
use crate::worker::CliMainWorkerFactory;
|
||||||
|
use crate::worker::CreateCustomWorkerError;
|
||||||
|
|
||||||
mod mitata;
|
mod mitata;
|
||||||
mod reporters;
|
mod reporters;
|
||||||
|
@ -164,7 +165,7 @@ async fn bench_specifier(
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
Ok(()) => Ok(()),
|
Ok(()) => Ok(()),
|
||||||
Err(CoreError::Js(error)) => {
|
Err(CreateCustomWorkerError::Core(CoreError::Js(error))) => {
|
||||||
sender.send(BenchEvent::UncaughtError(
|
sender.send(BenchEvent::UncaughtError(
|
||||||
specifier.to_string(),
|
specifier.to_string(),
|
||||||
Box::new(error),
|
Box::new(error),
|
||||||
|
@ -182,7 +183,7 @@ async fn bench_specifier_inner(
|
||||||
specifier: ModuleSpecifier,
|
specifier: ModuleSpecifier,
|
||||||
sender: &UnboundedSender<BenchEvent>,
|
sender: &UnboundedSender<BenchEvent>,
|
||||||
filter: TestFilter,
|
filter: TestFilter,
|
||||||
) -> Result<(), CoreError> {
|
) -> Result<(), CreateCustomWorkerError> {
|
||||||
let mut worker = worker_factory
|
let mut worker = worker_factory
|
||||||
.create_custom_worker(
|
.create_custom_worker(
|
||||||
WorkerExecutionMode::Bench,
|
WorkerExecutionMode::Bench,
|
||||||
|
@ -201,7 +202,7 @@ async fn bench_specifier_inner(
|
||||||
// Ensure that there are no pending exceptions before we start running tests
|
// Ensure that there are no pending exceptions before we start running tests
|
||||||
worker.run_up_to_duration(Duration::from_millis(0)).await?;
|
worker.run_up_to_duration(Duration::from_millis(0)).await?;
|
||||||
|
|
||||||
worker.dispatch_load_event()?;
|
worker.dispatch_load_event().map_err(CoreError::Js)?;
|
||||||
|
|
||||||
let benchmarks = {
|
let benchmarks = {
|
||||||
let state_rc = worker.js_runtime.op_state();
|
let state_rc = worker.js_runtime.op_state();
|
||||||
|
@ -236,11 +237,13 @@ async fn bench_specifier_inner(
|
||||||
used_only,
|
used_only,
|
||||||
names: benchmarks.iter().map(|(d, _)| d.name.clone()).collect(),
|
names: benchmarks.iter().map(|(d, _)| d.name.clone()).collect(),
|
||||||
}))
|
}))
|
||||||
.map_err(JsErrorBox::from_err)?;
|
.map_err(JsErrorBox::from_err)
|
||||||
|
.map_err(CoreError::JsBox)?;
|
||||||
for (desc, function) in benchmarks {
|
for (desc, function) in benchmarks {
|
||||||
sender
|
sender
|
||||||
.send(BenchEvent::Wait(desc.id))
|
.send(BenchEvent::Wait(desc.id))
|
||||||
.map_err(JsErrorBox::from_err)?;
|
.map_err(JsErrorBox::from_err)
|
||||||
|
.map_err(CoreError::JsBox)?;
|
||||||
let call = worker.js_runtime.call(&function);
|
let call = worker.js_runtime.call(&function);
|
||||||
let result = worker
|
let result = worker
|
||||||
.js_runtime
|
.js_runtime
|
||||||
|
@ -249,18 +252,26 @@ async fn bench_specifier_inner(
|
||||||
let scope = &mut worker.js_runtime.handle_scope();
|
let scope = &mut worker.js_runtime.handle_scope();
|
||||||
let result = v8::Local::new(scope, result);
|
let result = v8::Local::new(scope, result);
|
||||||
let result = serde_v8::from_v8::<BenchResult>(scope, result)
|
let result = serde_v8::from_v8::<BenchResult>(scope, result)
|
||||||
.map_err(JsErrorBox::from_err)?;
|
.map_err(JsErrorBox::from_err)
|
||||||
|
.map_err(CoreError::JsBox)?;
|
||||||
sender
|
sender
|
||||||
.send(BenchEvent::Result(desc.id, result))
|
.send(BenchEvent::Result(desc.id, result))
|
||||||
.map_err(JsErrorBox::from_err)?;
|
.map_err(JsErrorBox::from_err)
|
||||||
|
.map_err(CoreError::JsBox)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ignore `defaultPrevented` of the `beforeunload` event. We don't allow the
|
// Ignore `defaultPrevented` of the `beforeunload` event. We don't allow the
|
||||||
// event loop to continue beyond what's needed to await results.
|
// event loop to continue beyond what's needed to await results.
|
||||||
worker.dispatch_beforeunload_event()?;
|
worker
|
||||||
worker.dispatch_process_beforeexit_event()?;
|
.dispatch_beforeunload_event()
|
||||||
worker.dispatch_unload_event()?;
|
.map_err(CoreError::Js)?;
|
||||||
worker.dispatch_process_exit_event()?;
|
worker
|
||||||
|
.dispatch_process_beforeexit_event()
|
||||||
|
.map_err(CoreError::Js)?;
|
||||||
|
worker.dispatch_unload_event().map_err(CoreError::Js)?;
|
||||||
|
worker
|
||||||
|
.dispatch_process_exit_event()
|
||||||
|
.map_err(CoreError::Js)?;
|
||||||
|
|
||||||
// Ensure the worker has settled so we can catch any remaining unhandled rejections. We don't
|
// Ensure the worker has settled so we can catch any remaining unhandled rejections. We don't
|
||||||
// want to wait forever here.
|
// want to wait forever here.
|
||||||
|
|
|
@ -18,10 +18,12 @@ use deno_config::glob::PathOrPatternSet;
|
||||||
use deno_core::anyhow::anyhow;
|
use deno_core::anyhow::anyhow;
|
||||||
use deno_core::anyhow::Context;
|
use deno_core::anyhow::Context;
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
|
use deno_core::error::CoreError;
|
||||||
use deno_core::serde_json;
|
use deno_core::serde_json;
|
||||||
use deno_core::sourcemap::SourceMap;
|
use deno_core::sourcemap::SourceMap;
|
||||||
use deno_core::url::Url;
|
use deno_core::url::Url;
|
||||||
use deno_core::LocalInspectorSession;
|
use deno_core::LocalInspectorSession;
|
||||||
|
use deno_error::JsErrorBox;
|
||||||
use deno_resolver::npm::DenoInNpmPackageChecker;
|
use deno_resolver::npm::DenoInNpmPackageChecker;
|
||||||
use node_resolver::InNpmPackageChecker;
|
use node_resolver::InNpmPackageChecker;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
|
@ -53,7 +55,7 @@ pub struct CoverageCollector {
|
||||||
|
|
||||||
#[async_trait::async_trait(?Send)]
|
#[async_trait::async_trait(?Send)]
|
||||||
impl crate::worker::CoverageCollector for CoverageCollector {
|
impl crate::worker::CoverageCollector for CoverageCollector {
|
||||||
async fn start_collecting(&mut self) -> Result<(), AnyError> {
|
async fn start_collecting(&mut self) -> Result<(), CoreError> {
|
||||||
self.enable_debugger().await?;
|
self.enable_debugger().await?;
|
||||||
self.enable_profiler().await?;
|
self.enable_profiler().await?;
|
||||||
self
|
self
|
||||||
|
@ -67,7 +69,7 @@ impl crate::worker::CoverageCollector for CoverageCollector {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn stop_collecting(&mut self) -> Result<(), AnyError> {
|
async fn stop_collecting(&mut self) -> Result<(), CoreError> {
|
||||||
fs::create_dir_all(&self.dir)?;
|
fs::create_dir_all(&self.dir)?;
|
||||||
|
|
||||||
let script_coverages = self.take_precise_coverage().await?.result;
|
let script_coverages = self.take_precise_coverage().await?.result;
|
||||||
|
@ -88,7 +90,8 @@ impl crate::worker::CoverageCollector for CoverageCollector {
|
||||||
let filepath = self.dir.join(filename);
|
let filepath = self.dir.join(filename);
|
||||||
|
|
||||||
let mut out = BufWriter::new(File::create(&filepath)?);
|
let mut out = BufWriter::new(File::create(&filepath)?);
|
||||||
let coverage = serde_json::to_string(&script_coverage)?;
|
let coverage = serde_json::to_string(&script_coverage)
|
||||||
|
.map_err(JsErrorBox::from_err)?;
|
||||||
let formatted_coverage =
|
let formatted_coverage =
|
||||||
format_json(&filepath, &coverage, &Default::default())
|
format_json(&filepath, &coverage, &Default::default())
|
||||||
.ok()
|
.ok()
|
||||||
|
@ -111,7 +114,7 @@ impl CoverageCollector {
|
||||||
Self { dir, session }
|
Self { dir, session }
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn enable_debugger(&mut self) -> Result<(), AnyError> {
|
async fn enable_debugger(&mut self) -> Result<(), CoreError> {
|
||||||
self
|
self
|
||||||
.session
|
.session
|
||||||
.post_message::<()>("Debugger.enable", None)
|
.post_message::<()>("Debugger.enable", None)
|
||||||
|
@ -119,7 +122,7 @@ impl CoverageCollector {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn enable_profiler(&mut self) -> Result<(), AnyError> {
|
async fn enable_profiler(&mut self) -> Result<(), CoreError> {
|
||||||
self
|
self
|
||||||
.session
|
.session
|
||||||
.post_message::<()>("Profiler.enable", None)
|
.post_message::<()>("Profiler.enable", None)
|
||||||
|
@ -127,7 +130,7 @@ impl CoverageCollector {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn disable_debugger(&mut self) -> Result<(), AnyError> {
|
async fn disable_debugger(&mut self) -> Result<(), CoreError> {
|
||||||
self
|
self
|
||||||
.session
|
.session
|
||||||
.post_message::<()>("Debugger.disable", None)
|
.post_message::<()>("Debugger.disable", None)
|
||||||
|
@ -135,7 +138,7 @@ impl CoverageCollector {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn disable_profiler(&mut self) -> Result<(), AnyError> {
|
async fn disable_profiler(&mut self) -> Result<(), CoreError> {
|
||||||
self
|
self
|
||||||
.session
|
.session
|
||||||
.post_message::<()>("Profiler.disable", None)
|
.post_message::<()>("Profiler.disable", None)
|
||||||
|
@ -146,26 +149,28 @@ impl CoverageCollector {
|
||||||
async fn start_precise_coverage(
|
async fn start_precise_coverage(
|
||||||
&mut self,
|
&mut self,
|
||||||
parameters: cdp::StartPreciseCoverageArgs,
|
parameters: cdp::StartPreciseCoverageArgs,
|
||||||
) -> Result<cdp::StartPreciseCoverageResponse, AnyError> {
|
) -> Result<cdp::StartPreciseCoverageResponse, CoreError> {
|
||||||
let return_value = self
|
let return_value = self
|
||||||
.session
|
.session
|
||||||
.post_message("Profiler.startPreciseCoverage", Some(parameters))
|
.post_message("Profiler.startPreciseCoverage", Some(parameters))
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let return_object = serde_json::from_value(return_value)?;
|
let return_object =
|
||||||
|
serde_json::from_value(return_value).map_err(JsErrorBox::from_err)?;
|
||||||
|
|
||||||
Ok(return_object)
|
Ok(return_object)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn take_precise_coverage(
|
async fn take_precise_coverage(
|
||||||
&mut self,
|
&mut self,
|
||||||
) -> Result<cdp::TakePreciseCoverageResponse, AnyError> {
|
) -> Result<cdp::TakePreciseCoverageResponse, CoreError> {
|
||||||
let return_value = self
|
let return_value = self
|
||||||
.session
|
.session
|
||||||
.post_message::<()>("Profiler.takePreciseCoverage", None)
|
.post_message::<()>("Profiler.takePreciseCoverage", None)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let return_object = serde_json::from_value(return_value)?;
|
let return_object =
|
||||||
|
serde_json::from_value(return_value).map_err(JsErrorBox::from_err)?;
|
||||||
|
|
||||||
Ok(return_object)
|
Ok(return_object)
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,6 +87,7 @@ use crate::util::path::is_script_ext;
|
||||||
use crate::util::path::matches_pattern_or_exact_path;
|
use crate::util::path::matches_pattern_or_exact_path;
|
||||||
use crate::worker::CliMainWorkerFactory;
|
use crate::worker::CliMainWorkerFactory;
|
||||||
use crate::worker::CoverageCollector;
|
use crate::worker::CoverageCollector;
|
||||||
|
use crate::worker::CreateCustomWorkerError;
|
||||||
|
|
||||||
mod channel;
|
mod channel;
|
||||||
pub mod fmt;
|
pub mod fmt;
|
||||||
|
@ -614,7 +615,10 @@ async fn configure_main_worker(
|
||||||
permissions_container: PermissionsContainer,
|
permissions_container: PermissionsContainer,
|
||||||
worker_sender: TestEventWorkerSender,
|
worker_sender: TestEventWorkerSender,
|
||||||
options: &TestSpecifierOptions,
|
options: &TestSpecifierOptions,
|
||||||
) -> Result<(Option<Box<dyn CoverageCollector>>, MainWorker), CoreError> {
|
) -> Result<
|
||||||
|
(Option<Box<dyn CoverageCollector>>, MainWorker),
|
||||||
|
CreateCustomWorkerError,
|
||||||
|
> {
|
||||||
let mut worker = worker_factory
|
let mut worker = worker_factory
|
||||||
.create_custom_worker(
|
.create_custom_worker(
|
||||||
WorkerExecutionMode::Test,
|
WorkerExecutionMode::Test,
|
||||||
|
@ -647,7 +651,7 @@ async fn configure_main_worker(
|
||||||
&worker.js_runtime.op_state(),
|
&worker.js_runtime.op_state(),
|
||||||
TestEvent::UncaughtError(specifier.to_string(), Box::new(err)),
|
TestEvent::UncaughtError(specifier.to_string(), Box::new(err)),
|
||||||
)
|
)
|
||||||
.map_err(JsErrorBox::from_err)?;
|
.map_err(|e| CoreError::JsBox(JsErrorBox::from_err(e)))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Err(err) => Err(err),
|
Err(err) => Err(err),
|
||||||
|
@ -687,7 +691,7 @@ pub async fn test_specifier(
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
Ok(()) => Ok(()),
|
Ok(()) => Ok(()),
|
||||||
Err(CoreError::Js(err)) => {
|
Err(TestSpecifierError::Core(CoreError::Js(err))) => {
|
||||||
send_test_event(
|
send_test_event(
|
||||||
&worker.js_runtime.op_state(),
|
&worker.js_runtime.op_state(),
|
||||||
TestEvent::UncaughtError(specifier.to_string(), Box::new(err)),
|
TestEvent::UncaughtError(specifier.to_string(), Box::new(err)),
|
||||||
|
@ -698,6 +702,16 @@ pub async fn test_specifier(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, thiserror::Error, deno_error::JsError)]
|
||||||
|
pub enum TestSpecifierError {
|
||||||
|
#[class(inherit)]
|
||||||
|
#[error(transparent)]
|
||||||
|
Core(#[from] CoreError),
|
||||||
|
#[class(inherit)]
|
||||||
|
#[error(transparent)]
|
||||||
|
RunTestsForWorker(#[from] RunTestsForWorkerErr),
|
||||||
|
}
|
||||||
|
|
||||||
/// Test a single specifier as documentation containing test programs, an executable test module or
|
/// Test a single specifier as documentation containing test programs, an executable test module or
|
||||||
/// both.
|
/// both.
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
|
@ -707,19 +721,21 @@ async fn test_specifier_inner(
|
||||||
specifier: ModuleSpecifier,
|
specifier: ModuleSpecifier,
|
||||||
fail_fast_tracker: FailFastTracker,
|
fail_fast_tracker: FailFastTracker,
|
||||||
options: TestSpecifierOptions,
|
options: TestSpecifierOptions,
|
||||||
) -> Result<(), CoreError> {
|
) -> Result<(), TestSpecifierError> {
|
||||||
// Ensure that there are no pending exceptions before we start running tests
|
// Ensure that there are no pending exceptions before we start running tests
|
||||||
worker.run_up_to_duration(Duration::from_millis(0)).await?;
|
worker.run_up_to_duration(Duration::from_millis(0)).await?;
|
||||||
|
|
||||||
worker.dispatch_load_event()?;
|
worker.dispatch_load_event().map_err(CoreError::Js)?;
|
||||||
|
|
||||||
run_tests_for_worker(worker, &specifier, &options, &fail_fast_tracker)
|
run_tests_for_worker(worker, &specifier, &options, &fail_fast_tracker)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
// Ignore `defaultPrevented` of the `beforeunload` event. We don't allow the
|
// Ignore `defaultPrevented` of the `beforeunload` event. We don't allow the
|
||||||
// event loop to continue beyond what's needed to await results.
|
// event loop to continue beyond what's needed to await results.
|
||||||
worker.dispatch_beforeunload_event()?;
|
worker
|
||||||
worker.dispatch_unload_event()?;
|
.dispatch_beforeunload_event()
|
||||||
|
.map_err(CoreError::Js)?;
|
||||||
|
worker.dispatch_unload_event().map_err(CoreError::Js)?;
|
||||||
|
|
||||||
// Ensure all output has been flushed
|
// Ensure all output has been flushed
|
||||||
_ = worker
|
_ = worker
|
||||||
|
@ -780,12 +796,25 @@ pub fn send_test_event(
|
||||||
.send(event)
|
.send(event)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, thiserror::Error, deno_error::JsError)]
|
||||||
|
pub enum RunTestsForWorkerErr {
|
||||||
|
#[class(inherit)]
|
||||||
|
#[error(transparent)]
|
||||||
|
ChannelClosed(#[from] ChannelClosedError),
|
||||||
|
#[class(inherit)]
|
||||||
|
#[error(transparent)]
|
||||||
|
Core(#[from] CoreError),
|
||||||
|
#[class(inherit)]
|
||||||
|
#[error(transparent)]
|
||||||
|
SerdeV8(#[from] serde_v8::Error),
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn run_tests_for_worker(
|
pub async fn run_tests_for_worker(
|
||||||
worker: &mut MainWorker,
|
worker: &mut MainWorker,
|
||||||
specifier: &ModuleSpecifier,
|
specifier: &ModuleSpecifier,
|
||||||
options: &TestSpecifierOptions,
|
options: &TestSpecifierOptions,
|
||||||
fail_fast_tracker: &FailFastTracker,
|
fail_fast_tracker: &FailFastTracker,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), RunTestsForWorkerErr> {
|
||||||
let state_rc = worker.js_runtime.op_state();
|
let state_rc = worker.js_runtime.op_state();
|
||||||
// Take whatever tests have been registered
|
// Take whatever tests have been registered
|
||||||
let TestContainer(tests, test_functions) =
|
let TestContainer(tests, test_functions) =
|
||||||
|
@ -814,7 +843,7 @@ async fn run_tests_for_worker_inner(
|
||||||
test_functions: Vec<v8::Global<v8::Function>>,
|
test_functions: Vec<v8::Global<v8::Function>>,
|
||||||
options: &TestSpecifierOptions,
|
options: &TestSpecifierOptions,
|
||||||
fail_fast_tracker: &FailFastTracker,
|
fail_fast_tracker: &FailFastTracker,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), RunTestsForWorkerErr> {
|
||||||
let unfiltered = tests.len();
|
let unfiltered = tests.len();
|
||||||
let state_rc = worker.js_runtime.op_state();
|
let state_rc = worker.js_runtime.op_state();
|
||||||
|
|
||||||
|
@ -1109,7 +1138,7 @@ async fn wait_for_activity_to_stabilize(
|
||||||
before: RuntimeActivityStats,
|
before: RuntimeActivityStats,
|
||||||
sanitize_ops: bool,
|
sanitize_ops: bool,
|
||||||
sanitize_resources: bool,
|
sanitize_resources: bool,
|
||||||
) -> Result<Option<RuntimeActivityDiff>, AnyError> {
|
) -> Result<Option<RuntimeActivityDiff>, CoreError> {
|
||||||
// First, check to see if there's any diff at all. If not, just continue.
|
// First, check to see if there's any diff at all. If not, just continue.
|
||||||
let after = stats.clone().capture(filter);
|
let after = stats.clone().capture(filter);
|
||||||
let mut diff = RuntimeActivityStats::diff(&before, &after);
|
let mut diff = RuntimeActivityStats::diff(&before, &after);
|
||||||
|
|
|
@ -36,7 +36,7 @@ pub fn any_and_jserrorbox_downcast_ref<
|
||||||
})
|
})
|
||||||
.or_else(|| {
|
.or_else(|| {
|
||||||
err.downcast_ref::<CoreError>().and_then(|e| match e {
|
err.downcast_ref::<CoreError>().and_then(|e| match e {
|
||||||
CoreError::JsNative(e) => e.as_any().downcast_ref::<E>(),
|
CoreError::JsBox(e) => e.as_any().downcast_ref::<E>(),
|
||||||
_ => None,
|
_ => None,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
116
cli/worker.rs
116
cli/worker.rs
|
@ -4,8 +4,6 @@ use std::path::Path;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use deno_ast::ModuleSpecifier;
|
use deno_ast::ModuleSpecifier;
|
||||||
use deno_core::anyhow::bail;
|
|
||||||
use deno_core::error::AnyError;
|
|
||||||
use deno_core::error::CoreError;
|
use deno_core::error::CoreError;
|
||||||
use deno_core::futures::FutureExt;
|
use deno_core::futures::FutureExt;
|
||||||
use deno_core::v8;
|
use deno_core::v8;
|
||||||
|
@ -19,6 +17,7 @@ use deno_runtime::deno_permissions::PermissionsContainer;
|
||||||
use deno_runtime::worker::MainWorker;
|
use deno_runtime::worker::MainWorker;
|
||||||
use deno_runtime::WorkerExecutionMode;
|
use deno_runtime::WorkerExecutionMode;
|
||||||
use deno_semver::npm::NpmPackageReqReference;
|
use deno_semver::npm::NpmPackageReqReference;
|
||||||
|
use node_resolver::errors::ResolvePkgJsonBinExportError;
|
||||||
use node_resolver::NodeResolutionKind;
|
use node_resolver::NodeResolutionKind;
|
||||||
use node_resolver::ResolutionMode;
|
use node_resolver::ResolutionMode;
|
||||||
use sys_traits::EnvCurrentDir;
|
use sys_traits::EnvCurrentDir;
|
||||||
|
@ -52,8 +51,8 @@ pub trait CliCodeCache: code_cache::CodeCache {
|
||||||
|
|
||||||
#[async_trait::async_trait(?Send)]
|
#[async_trait::async_trait(?Send)]
|
||||||
pub trait CoverageCollector: Send + Sync {
|
pub trait CoverageCollector: Send + Sync {
|
||||||
async fn start_collecting(&mut self) -> Result<(), AnyError>;
|
async fn start_collecting(&mut self) -> Result<(), CoreError>;
|
||||||
async fn stop_collecting(&mut self) -> Result<(), AnyError>;
|
async fn stop_collecting(&mut self) -> Result<(), CoreError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type CreateHmrRunnerCb = Box<
|
pub type CreateHmrRunnerCb = Box<
|
||||||
|
@ -91,7 +90,7 @@ impl CliMainWorker {
|
||||||
self.worker.into_main_worker()
|
self.worker.into_main_worker()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn setup_repl(&mut self) -> Result<(), AnyError> {
|
pub async fn setup_repl(&mut self) -> Result<(), CoreError> {
|
||||||
self.worker.run_event_loop(false).await?;
|
self.worker.run_event_loop(false).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -172,7 +171,7 @@ impl CliMainWorker {
|
||||||
Ok(self.worker.exit_code())
|
Ok(self.worker.exit_code())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn run_for_watcher(self) -> Result<(), AnyError> {
|
pub async fn run_for_watcher(self) -> Result<(), CoreError> {
|
||||||
/// The FileWatcherModuleExecutor provides module execution with safe dispatching of life-cycle events by tracking the
|
/// The FileWatcherModuleExecutor provides module execution with safe dispatching of life-cycle events by tracking the
|
||||||
/// state of any pending events and emitting accordingly on drop in the case of a future
|
/// state of any pending events and emitting accordingly on drop in the case of a future
|
||||||
/// cancellation.
|
/// cancellation.
|
||||||
|
@ -191,7 +190,7 @@ impl CliMainWorker {
|
||||||
|
|
||||||
/// Execute the given main module emitting load and unload events before and after execution
|
/// Execute the given main module emitting load and unload events before and after execution
|
||||||
/// respectively.
|
/// respectively.
|
||||||
pub async fn execute(&mut self) -> Result<(), AnyError> {
|
pub async fn execute(&mut self) -> Result<(), CoreError> {
|
||||||
self.inner.execute_main_module().await?;
|
self.inner.execute_main_module().await?;
|
||||||
self.inner.worker.dispatch_load_event()?;
|
self.inner.worker.dispatch_load_event()?;
|
||||||
self.pending_unload = true;
|
self.pending_unload = true;
|
||||||
|
@ -245,7 +244,7 @@ impl CliMainWorker {
|
||||||
|
|
||||||
pub async fn maybe_setup_hmr_runner(
|
pub async fn maybe_setup_hmr_runner(
|
||||||
&mut self,
|
&mut self,
|
||||||
) -> Result<Option<Box<dyn HmrRunner>>, AnyError> {
|
) -> Result<Option<Box<dyn HmrRunner>>, CoreError> {
|
||||||
let Some(setup_hmr_runner) = self.shared.create_hmr_runner.as_ref() else {
|
let Some(setup_hmr_runner) = self.shared.create_hmr_runner.as_ref() else {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
};
|
};
|
||||||
|
@ -267,7 +266,7 @@ impl CliMainWorker {
|
||||||
|
|
||||||
pub async fn maybe_setup_coverage_collector(
|
pub async fn maybe_setup_coverage_collector(
|
||||||
&mut self,
|
&mut self,
|
||||||
) -> Result<Option<Box<dyn CoverageCollector>>, AnyError> {
|
) -> Result<Option<Box<dyn CoverageCollector>>, CoreError> {
|
||||||
let Some(create_coverage_collector) =
|
let Some(create_coverage_collector) =
|
||||||
self.shared.create_coverage_collector.as_ref()
|
self.shared.create_coverage_collector.as_ref()
|
||||||
else {
|
else {
|
||||||
|
@ -296,6 +295,58 @@ impl CliMainWorker {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, thiserror::Error, deno_error::JsError)]
|
||||||
|
pub enum ResolveBinaryEntrypointError {
|
||||||
|
#[class(inherit)]
|
||||||
|
#[error(transparent)]
|
||||||
|
ResolvePkgJsonBinExport(ResolvePkgJsonBinExportError),
|
||||||
|
#[class(generic)]
|
||||||
|
#[error("{original:#}\n\nFallback failed: {fallback:#}")]
|
||||||
|
Fallback {
|
||||||
|
fallback: ResolveBinaryEntrypointFallbackError,
|
||||||
|
original: ResolvePkgJsonBinExportError,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, thiserror::Error, deno_error::JsError)]
|
||||||
|
pub enum ResolveBinaryEntrypointFallbackError {
|
||||||
|
#[class(inherit)]
|
||||||
|
#[error(transparent)]
|
||||||
|
PackageSubpathResolve(node_resolver::errors::PackageSubpathResolveError),
|
||||||
|
#[class(generic)]
|
||||||
|
#[error("Cannot find module '{0}'")]
|
||||||
|
ModuleNotFound(ModuleSpecifier),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, thiserror::Error, deno_error::JsError)]
|
||||||
|
pub enum CreateCustomWorkerError {
|
||||||
|
#[class(inherit)]
|
||||||
|
#[error(transparent)]
|
||||||
|
Io(#[from] std::io::Error),
|
||||||
|
#[class(inherit)]
|
||||||
|
#[error(transparent)]
|
||||||
|
Core(#[from] CoreError),
|
||||||
|
#[class(inherit)]
|
||||||
|
#[error(transparent)]
|
||||||
|
ResolvePkgFolderFromDenoReq(
|
||||||
|
#[from] deno_resolver::npm::ResolvePkgFolderFromDenoReqError,
|
||||||
|
),
|
||||||
|
#[class(inherit)]
|
||||||
|
#[error(transparent)]
|
||||||
|
UrlParse(#[from] deno_core::url::ParseError),
|
||||||
|
#[class(inherit)]
|
||||||
|
#[error(transparent)]
|
||||||
|
ResolveBinaryEntrypoint(#[from] ResolveBinaryEntrypointError),
|
||||||
|
#[class(inherit)]
|
||||||
|
#[error(transparent)]
|
||||||
|
NpmPackageReq(JsErrorBox),
|
||||||
|
#[class(inherit)]
|
||||||
|
#[error(transparent)]
|
||||||
|
AtomicWriteFileWithRetries(
|
||||||
|
#[from] crate::args::AtomicWriteFileWithRetriesError,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
pub struct CliMainWorkerFactory {
|
pub struct CliMainWorkerFactory {
|
||||||
lib_main_worker_factory: LibMainWorkerFactory<CliSys>,
|
lib_main_worker_factory: LibMainWorkerFactory<CliSys>,
|
||||||
maybe_lockfile: Option<Arc<CliLockfile>>,
|
maybe_lockfile: Option<Arc<CliLockfile>>,
|
||||||
|
@ -344,7 +395,7 @@ impl CliMainWorkerFactory {
|
||||||
&self,
|
&self,
|
||||||
mode: WorkerExecutionMode,
|
mode: WorkerExecutionMode,
|
||||||
main_module: ModuleSpecifier,
|
main_module: ModuleSpecifier,
|
||||||
) -> Result<CliMainWorker, CoreError> {
|
) -> Result<CliMainWorker, CreateCustomWorkerError> {
|
||||||
self
|
self
|
||||||
.create_custom_worker(
|
.create_custom_worker(
|
||||||
mode,
|
mode,
|
||||||
|
@ -363,7 +414,7 @@ impl CliMainWorkerFactory {
|
||||||
permissions: PermissionsContainer,
|
permissions: PermissionsContainer,
|
||||||
custom_extensions: Vec<Extension>,
|
custom_extensions: Vec<Extension>,
|
||||||
stdio: deno_runtime::deno_io::Stdio,
|
stdio: deno_runtime::deno_io::Stdio,
|
||||||
) -> Result<CliMainWorker, CoreError> {
|
) -> Result<CliMainWorker, CreateCustomWorkerError> {
|
||||||
let main_module = if let Ok(package_ref) =
|
let main_module = if let Ok(package_ref) =
|
||||||
NpmPackageReqReference::from_specifier(&main_module)
|
NpmPackageReqReference::from_specifier(&main_module)
|
||||||
{
|
{
|
||||||
|
@ -381,19 +432,20 @@ impl CliMainWorkerFactory {
|
||||||
PackageCaching::All
|
PackageCaching::All
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.await?;
|
.await
|
||||||
|
.map_err(CreateCustomWorkerError::NpmPackageReq)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// use a fake referrer that can be used to discover the package.json if necessary
|
// use a fake referrer that can be used to discover the package.json if necessary
|
||||||
let referrer = ModuleSpecifier::from_directory_path(
|
let referrer =
|
||||||
self.sys.env_current_dir().map_err(JsErrorBox::from_err)?,
|
ModuleSpecifier::from_directory_path(self.sys.env_current_dir()?)
|
||||||
)
|
.unwrap()
|
||||||
.unwrap()
|
.join("package.json")?;
|
||||||
.join("package.json")?;
|
let package_folder =
|
||||||
let package_folder = self
|
self.npm_resolver.resolve_pkg_folder_from_deno_module_req(
|
||||||
.npm_resolver
|
package_ref.req(),
|
||||||
.resolve_pkg_folder_from_deno_module_req(package_ref.req(), &referrer)
|
&referrer,
|
||||||
.map_err(JsErrorBox::from_err)?;
|
)?;
|
||||||
let main_module = self
|
let main_module = self
|
||||||
.resolve_binary_entrypoint(&package_folder, package_ref.sub_path())?;
|
.resolve_binary_entrypoint(&package_folder, package_ref.sub_path())?;
|
||||||
|
|
||||||
|
@ -447,7 +499,7 @@ impl CliMainWorkerFactory {
|
||||||
&self,
|
&self,
|
||||||
package_folder: &Path,
|
package_folder: &Path,
|
||||||
sub_path: Option<&str>,
|
sub_path: Option<&str>,
|
||||||
) -> Result<ModuleSpecifier, AnyError> {
|
) -> Result<ModuleSpecifier, ResolveBinaryEntrypointError> {
|
||||||
match self
|
match self
|
||||||
.node_resolver
|
.node_resolver
|
||||||
.resolve_binary_export(package_folder, sub_path)
|
.resolve_binary_export(package_folder, sub_path)
|
||||||
|
@ -459,10 +511,13 @@ impl CliMainWorkerFactory {
|
||||||
self.resolve_binary_entrypoint_fallback(package_folder, sub_path);
|
self.resolve_binary_entrypoint_fallback(package_folder, sub_path);
|
||||||
match result {
|
match result {
|
||||||
Ok(Some(specifier)) => Ok(specifier),
|
Ok(Some(specifier)) => Ok(specifier),
|
||||||
Ok(None) => Err(original_err.into()),
|
Ok(None) => Err(
|
||||||
Err(fallback_err) => {
|
ResolveBinaryEntrypointError::ResolvePkgJsonBinExport(original_err),
|
||||||
bail!("{:#}\n\nFallback failed: {:#}", original_err, fallback_err)
|
),
|
||||||
}
|
Err(fallback_err) => Err(ResolveBinaryEntrypointError::Fallback {
|
||||||
|
original: original_err,
|
||||||
|
fallback: fallback_err,
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -473,7 +528,7 @@ impl CliMainWorkerFactory {
|
||||||
&self,
|
&self,
|
||||||
package_folder: &Path,
|
package_folder: &Path,
|
||||||
sub_path: Option<&str>,
|
sub_path: Option<&str>,
|
||||||
) -> Result<Option<ModuleSpecifier>, AnyError> {
|
) -> Result<Option<ModuleSpecifier>, ResolveBinaryEntrypointFallbackError> {
|
||||||
// only fallback if the user specified a sub path
|
// only fallback if the user specified a sub path
|
||||||
if sub_path.is_none() {
|
if sub_path.is_none() {
|
||||||
// it's confusing to users if the package doesn't have any binary
|
// it's confusing to users if the package doesn't have any binary
|
||||||
|
@ -490,7 +545,8 @@ impl CliMainWorkerFactory {
|
||||||
/* referrer */ None,
|
/* referrer */ None,
|
||||||
ResolutionMode::Import,
|
ResolutionMode::Import,
|
||||||
NodeResolutionKind::Execution,
|
NodeResolutionKind::Execution,
|
||||||
)?;
|
)
|
||||||
|
.map_err(ResolveBinaryEntrypointFallbackError::PackageSubpathResolve)?;
|
||||||
if specifier
|
if specifier
|
||||||
.to_file_path()
|
.to_file_path()
|
||||||
.map(|p| p.exists())
|
.map(|p| p.exists())
|
||||||
|
@ -498,7 +554,9 @@ impl CliMainWorkerFactory {
|
||||||
{
|
{
|
||||||
Ok(Some(specifier))
|
Ok(Some(specifier))
|
||||||
} else {
|
} else {
|
||||||
bail!("Cannot find module '{}'", specifier)
|
Err(ResolveBinaryEntrypointFallbackError::ModuleNotFound(
|
||||||
|
specifier,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,9 +99,6 @@ pub enum QuicError {
|
||||||
#[class(range)]
|
#[class(range)]
|
||||||
#[error("Connection has reached the maximum number of concurrent outgoing {0} streams")]
|
#[error("Connection has reached the maximum number of concurrent outgoing {0} streams")]
|
||||||
MaxStreams(&'static str),
|
MaxStreams(&'static str),
|
||||||
#[class(generic)]
|
|
||||||
#[error("{0}")]
|
|
||||||
Core(#[from] deno_core::error::AnyError),
|
|
||||||
#[class(inherit)]
|
#[class(inherit)]
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Other(#[from] JsErrorBox),
|
Other(#[from] JsErrorBox),
|
||||||
|
|
|
@ -106,10 +106,15 @@ pub enum RequireErrorKind {
|
||||||
JsErrorBox,
|
JsErrorBox,
|
||||||
),
|
),
|
||||||
#[class(inherit)]
|
#[class(inherit)]
|
||||||
#[error("Unable to get CWD: {0}")]
|
#[error(transparent)]
|
||||||
UnableToGetCwd(#[inherit] std::io::Error),
|
UnableToGetCwd(UnableToGetCwdError),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, thiserror::Error, deno_error::JsError)]
|
||||||
|
#[error("Unable to get CWD")]
|
||||||
|
#[class(inherit)]
|
||||||
|
pub struct UnableToGetCwdError(#[source] pub std::io::Error);
|
||||||
|
|
||||||
#[op2]
|
#[op2]
|
||||||
#[serde]
|
#[serde]
|
||||||
pub fn op_require_init_paths() -> Vec<String> {
|
pub fn op_require_init_paths() -> Vec<String> {
|
||||||
|
@ -177,7 +182,7 @@ pub fn op_require_node_module_paths<
|
||||||
} else {
|
} else {
|
||||||
let current_dir = &sys
|
let current_dir = &sys
|
||||||
.env_current_dir()
|
.env_current_dir()
|
||||||
.map_err(RequireErrorKind::UnableToGetCwd)?;
|
.map_err(|e| RequireErrorKind::UnableToGetCwd(UnableToGetCwdError(e)))?;
|
||||||
normalize_path(current_dir.join(from))
|
normalize_path(current_dir.join(from))
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -6,8 +6,7 @@ use std::collections::HashSet;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use anyhow::Context;
|
use deno_error::JsErrorBox;
|
||||||
use anyhow::Error as AnyError;
|
|
||||||
use deno_path_util::url_from_file_path;
|
use deno_path_util::url_from_file_path;
|
||||||
use deno_path_util::url_to_file_path;
|
use deno_path_util::url_to_file_path;
|
||||||
use futures::future::LocalBoxFuture;
|
use futures::future::LocalBoxFuture;
|
||||||
|
@ -43,6 +42,16 @@ pub struct CjsAnalysisExports {
|
||||||
pub reexports: Vec<String>,
|
pub reexports: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, thiserror::Error, deno_error::JsError)]
|
||||||
|
pub enum CjsCodeAnalysisError {
|
||||||
|
#[class(inherit)]
|
||||||
|
#[error(transparent)]
|
||||||
|
ClosestPkgJson(#[from] crate::errors::ClosestPkgJsonError),
|
||||||
|
#[class(inherit)]
|
||||||
|
#[error(transparent)]
|
||||||
|
Other(#[from] JsErrorBox),
|
||||||
|
}
|
||||||
|
|
||||||
/// Code analyzer for CJS and ESM files.
|
/// Code analyzer for CJS and ESM files.
|
||||||
#[async_trait::async_trait(?Send)]
|
#[async_trait::async_trait(?Send)]
|
||||||
pub trait CjsCodeAnalyzer {
|
pub trait CjsCodeAnalyzer {
|
||||||
|
@ -57,7 +66,28 @@ pub trait CjsCodeAnalyzer {
|
||||||
&self,
|
&self,
|
||||||
specifier: &Url,
|
specifier: &Url,
|
||||||
maybe_source: Option<Cow<'a, str>>,
|
maybe_source: Option<Cow<'a, str>>,
|
||||||
) -> Result<CjsAnalysis<'a>, AnyError>;
|
) -> Result<CjsAnalysis<'a>, CjsCodeAnalysisError>;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, thiserror::Error, deno_error::JsError)]
|
||||||
|
pub enum TranslateCjsToEsmError {
|
||||||
|
#[class(inherit)]
|
||||||
|
#[error(transparent)]
|
||||||
|
CjsCodeAnalysis(#[from] CjsCodeAnalysisError),
|
||||||
|
#[class(inherit)]
|
||||||
|
#[error(transparent)]
|
||||||
|
ExportAnalysis(#[from] JsErrorBox),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, thiserror::Error, deno_error::JsError)]
|
||||||
|
#[class(generic)]
|
||||||
|
#[error("Could not load '{reexport}' ({reexport_specifier}) referenced from {referrer}")]
|
||||||
|
pub struct CjsAnalysisCouldNotLoadError {
|
||||||
|
reexport: String,
|
||||||
|
reexport_specifier: Url,
|
||||||
|
referrer: Url,
|
||||||
|
#[source]
|
||||||
|
source: CjsCodeAnalysisError,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct NodeCodeTranslator<
|
pub struct NodeCodeTranslator<
|
||||||
|
@ -128,7 +158,7 @@ impl<
|
||||||
&self,
|
&self,
|
||||||
entry_specifier: &Url,
|
entry_specifier: &Url,
|
||||||
source: Option<Cow<'a, str>>,
|
source: Option<Cow<'a, str>>,
|
||||||
) -> Result<Cow<'a, str>, AnyError> {
|
) -> Result<Cow<'a, str>, TranslateCjsToEsmError> {
|
||||||
let mut temp_var_count = 0;
|
let mut temp_var_count = 0;
|
||||||
|
|
||||||
let analysis = self
|
let analysis = self
|
||||||
|
@ -164,7 +194,7 @@ impl<
|
||||||
// surface errors afterwards in a deterministic way
|
// surface errors afterwards in a deterministic way
|
||||||
if !errors.is_empty() {
|
if !errors.is_empty() {
|
||||||
errors.sort_by_cached_key(|e| e.to_string());
|
errors.sort_by_cached_key(|e| e.to_string());
|
||||||
return Err(errors.remove(0));
|
return Err(TranslateCjsToEsmError::ExportAnalysis(errors.remove(0)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,7 +238,7 @@ impl<
|
||||||
all_exports: &mut BTreeSet<String>,
|
all_exports: &mut BTreeSet<String>,
|
||||||
// this goes through the modules concurrently, so collect
|
// this goes through the modules concurrently, so collect
|
||||||
// the errors in order to be deterministic
|
// the errors in order to be deterministic
|
||||||
errors: &mut Vec<anyhow::Error>,
|
errors: &mut Vec<JsErrorBox>,
|
||||||
) {
|
) {
|
||||||
struct Analysis {
|
struct Analysis {
|
||||||
reexport_specifier: url::Url,
|
reexport_specifier: url::Url,
|
||||||
|
@ -216,7 +246,7 @@ impl<
|
||||||
analysis: CjsAnalysis<'static>,
|
analysis: CjsAnalysis<'static>,
|
||||||
}
|
}
|
||||||
|
|
||||||
type AnalysisFuture<'a> = LocalBoxFuture<'a, Result<Analysis, AnyError>>;
|
type AnalysisFuture<'a> = LocalBoxFuture<'a, Result<Analysis, JsErrorBox>>;
|
||||||
|
|
||||||
let mut handled_reexports: HashSet<Url> = HashSet::default();
|
let mut handled_reexports: HashSet<Url> = HashSet::default();
|
||||||
handled_reexports.insert(entry_specifier.clone());
|
handled_reexports.insert(entry_specifier.clone());
|
||||||
|
@ -227,7 +257,7 @@ impl<
|
||||||
|referrer: url::Url,
|
|referrer: url::Url,
|
||||||
reexports: Vec<String>,
|
reexports: Vec<String>,
|
||||||
analyze_futures: &mut FuturesUnordered<AnalysisFuture<'a>>,
|
analyze_futures: &mut FuturesUnordered<AnalysisFuture<'a>>,
|
||||||
errors: &mut Vec<anyhow::Error>| {
|
errors: &mut Vec<JsErrorBox>| {
|
||||||
// 1. Resolve the re-exports and start a future to analyze each one
|
// 1. Resolve the re-exports and start a future to analyze each one
|
||||||
for reexport in reexports {
|
for reexport in reexports {
|
||||||
let result = self.resolve(
|
let result = self.resolve(
|
||||||
|
@ -256,11 +286,13 @@ impl<
|
||||||
let analysis = cjs_code_analyzer
|
let analysis = cjs_code_analyzer
|
||||||
.analyze_cjs(&reexport_specifier, None)
|
.analyze_cjs(&reexport_specifier, None)
|
||||||
.await
|
.await
|
||||||
.with_context(|| {
|
.map_err(|source| {
|
||||||
format!(
|
JsErrorBox::from_err(CjsAnalysisCouldNotLoadError {
|
||||||
"Could not load '{}' ({}) referenced from {}",
|
reexport,
|
||||||
reexport, reexport_specifier, referrer
|
reexport_specifier: reexport_specifier.clone(),
|
||||||
)
|
referrer: referrer.clone(),
|
||||||
|
source,
|
||||||
|
})
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
Ok(Analysis {
|
Ok(Analysis {
|
||||||
|
@ -297,11 +329,10 @@ impl<
|
||||||
match analysis {
|
match analysis {
|
||||||
CjsAnalysis::Esm(_) => {
|
CjsAnalysis::Esm(_) => {
|
||||||
// todo(dsherret): support this once supporting requiring ES modules
|
// todo(dsherret): support this once supporting requiring ES modules
|
||||||
errors.push(anyhow::anyhow!(
|
errors.push(JsErrorBox::generic(format!(
|
||||||
"Cannot require ES module '{}' from '{}'",
|
"Cannot require ES module '{}' from '{}'",
|
||||||
reexport_specifier,
|
reexport_specifier, referrer,
|
||||||
referrer,
|
)));
|
||||||
));
|
|
||||||
}
|
}
|
||||||
CjsAnalysis::Cjs(analysis) => {
|
CjsAnalysis::Cjs(analysis) => {
|
||||||
if !analysis.reexports.is_empty() {
|
if !analysis.reexports.is_empty() {
|
||||||
|
@ -331,7 +362,7 @@ impl<
|
||||||
referrer: &Url,
|
referrer: &Url,
|
||||||
conditions: &[&str],
|
conditions: &[&str],
|
||||||
resolution_kind: NodeResolutionKind,
|
resolution_kind: NodeResolutionKind,
|
||||||
) -> Result<Option<Url>, AnyError> {
|
) -> Result<Option<Url>, JsErrorBox> {
|
||||||
if specifier.starts_with('/') {
|
if specifier.starts_with('/') {
|
||||||
todo!();
|
todo!();
|
||||||
}
|
}
|
||||||
|
@ -341,7 +372,7 @@ impl<
|
||||||
if let Some(parent) = referrer_path.parent() {
|
if let Some(parent) = referrer_path.parent() {
|
||||||
return self
|
return self
|
||||||
.file_extension_probe(parent.join(specifier), &referrer_path)
|
.file_extension_probe(parent.join(specifier), &referrer_path)
|
||||||
.and_then(|p| url_from_file_path(&p).map_err(AnyError::from))
|
.and_then(|p| url_from_file_path(&p).map_err(JsErrorBox::from_err))
|
||||||
.map(Some);
|
.map(Some);
|
||||||
} else {
|
} else {
|
||||||
todo!();
|
todo!();
|
||||||
|
@ -364,13 +395,14 @@ impl<
|
||||||
{
|
{
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
other => other,
|
other => other.map_err(JsErrorBox::from_err)?,
|
||||||
}?;
|
};
|
||||||
|
|
||||||
let package_json_path = module_dir.join("package.json");
|
let package_json_path = module_dir.join("package.json");
|
||||||
let maybe_package_json = self
|
let maybe_package_json = self
|
||||||
.pkg_json_resolver
|
.pkg_json_resolver
|
||||||
.load_package_json(&package_json_path)?;
|
.load_package_json(&package_json_path)
|
||||||
|
.map_err(JsErrorBox::from_err)?;
|
||||||
if let Some(package_json) = maybe_package_json {
|
if let Some(package_json) = maybe_package_json {
|
||||||
if let Some(exports) = &package_json.exports {
|
if let Some(exports) = &package_json.exports {
|
||||||
return Some(
|
return Some(
|
||||||
|
@ -385,7 +417,7 @@ impl<
|
||||||
conditions,
|
conditions,
|
||||||
resolution_kind,
|
resolution_kind,
|
||||||
)
|
)
|
||||||
.map_err(AnyError::from),
|
.map_err(JsErrorBox::from_err),
|
||||||
)
|
)
|
||||||
.transpose();
|
.transpose();
|
||||||
}
|
}
|
||||||
|
@ -398,29 +430,40 @@ impl<
|
||||||
let package_json_path = d.join("package.json");
|
let package_json_path = d.join("package.json");
|
||||||
let maybe_package_json = self
|
let maybe_package_json = self
|
||||||
.pkg_json_resolver
|
.pkg_json_resolver
|
||||||
.load_package_json(&package_json_path)?;
|
.load_package_json(&package_json_path)
|
||||||
|
.map_err(JsErrorBox::from_err)?;
|
||||||
if let Some(package_json) = maybe_package_json {
|
if let Some(package_json) = maybe_package_json {
|
||||||
if let Some(main) =
|
if let Some(main) =
|
||||||
package_json.main(deno_package_json::NodeModuleKind::Cjs)
|
package_json.main(deno_package_json::NodeModuleKind::Cjs)
|
||||||
{
|
{
|
||||||
return Ok(Some(url_from_file_path(&d.join(main).clean())?));
|
return Ok(Some(
|
||||||
|
url_from_file_path(&d.join(main).clean())
|
||||||
|
.map_err(JsErrorBox::from_err)?,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ok(Some(url_from_file_path(&d.join("index.js").clean())?));
|
return Ok(Some(
|
||||||
|
url_from_file_path(&d.join("index.js").clean())
|
||||||
|
.map_err(JsErrorBox::from_err)?,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
return self
|
return self
|
||||||
.file_extension_probe(d, &referrer_path)
|
.file_extension_probe(d, &referrer_path)
|
||||||
.and_then(|p| url_from_file_path(&p).map_err(AnyError::from))
|
.and_then(|p| url_from_file_path(&p).map_err(JsErrorBox::from_err))
|
||||||
.map(Some);
|
.map(Some);
|
||||||
} else if let Some(main) =
|
} else if let Some(main) =
|
||||||
package_json.main(deno_package_json::NodeModuleKind::Cjs)
|
package_json.main(deno_package_json::NodeModuleKind::Cjs)
|
||||||
{
|
{
|
||||||
return Ok(Some(url_from_file_path(&module_dir.join(main).clean())?));
|
return Ok(Some(
|
||||||
|
url_from_file_path(&module_dir.join(main).clean())
|
||||||
|
.map_err(JsErrorBox::from_err)?,
|
||||||
|
));
|
||||||
} else {
|
} else {
|
||||||
return Ok(Some(url_from_file_path(
|
return Ok(Some(
|
||||||
&module_dir.join("index.js").clean(),
|
url_from_file_path(&module_dir.join("index.js").clean())
|
||||||
)?));
|
.map_err(JsErrorBox::from_err)?,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -436,7 +479,9 @@ impl<
|
||||||
parent.join("node_modules").join(specifier)
|
parent.join("node_modules").join(specifier)
|
||||||
};
|
};
|
||||||
if let Ok(path) = self.file_extension_probe(path, &referrer_path) {
|
if let Ok(path) = self.file_extension_probe(path, &referrer_path) {
|
||||||
return Ok(Some(url_from_file_path(&path)?));
|
return Ok(Some(
|
||||||
|
url_from_file_path(&path).map_err(JsErrorBox::from_err)?,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
last = parent;
|
last = parent;
|
||||||
}
|
}
|
||||||
|
@ -448,7 +493,7 @@ impl<
|
||||||
&self,
|
&self,
|
||||||
p: PathBuf,
|
p: PathBuf,
|
||||||
referrer: &Path,
|
referrer: &Path,
|
||||||
) -> Result<PathBuf, AnyError> {
|
) -> Result<PathBuf, JsErrorBox> {
|
||||||
let p = p.clean();
|
let p = p.clean();
|
||||||
if self.sys.fs_exists_no_err(&p) {
|
if self.sys.fs_exists_no_err(&p) {
|
||||||
let file_name = p.file_name().unwrap();
|
let file_name = p.file_name().unwrap();
|
||||||
|
@ -638,13 +683,13 @@ fn parse_specifier(specifier: &str) -> Option<(String, String)> {
|
||||||
Some((package_name, package_subpath))
|
Some((package_name, package_subpath))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn not_found(path: &str, referrer: &Path) -> AnyError {
|
fn not_found(path: &str, referrer: &Path) -> JsErrorBox {
|
||||||
let msg = format!(
|
let msg = format!(
|
||||||
"[ERR_MODULE_NOT_FOUND] Cannot find module \"{}\" imported from \"{}\"",
|
"[ERR_MODULE_NOT_FOUND] Cannot find module \"{}\" imported from \"{}\"",
|
||||||
path,
|
path,
|
||||||
referrer.to_string_lossy()
|
referrer.to_string_lossy()
|
||||||
);
|
);
|
||||||
std::io::Error::new(std::io::ErrorKind::NotFound, msg).into()
|
JsErrorBox::from_err(std::io::Error::new(std::io::ErrorKind::NotFound, msg))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_double_quote_string(text: &str) -> String {
|
fn to_double_quote_string(text: &str) -> String {
|
||||||
|
|
|
@ -4,11 +4,12 @@ use std::path::Path;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use deno_core::anyhow::Context;
|
use deno_core::anyhow::Context;
|
||||||
use deno_core::error::AnyError;
|
|
||||||
use deno_path_util::normalize_path;
|
use deno_path_util::normalize_path;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn resolve_from_cwd(path: &Path) -> Result<PathBuf, AnyError> {
|
pub fn resolve_from_cwd(
|
||||||
|
path: &Path,
|
||||||
|
) -> Result<PathBuf, deno_core::anyhow::Error> {
|
||||||
if path.is_absolute() {
|
if path.is_absolute() {
|
||||||
Ok(normalize_path(path))
|
Ok(normalize_path(path))
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -10,8 +10,6 @@ use std::process;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::thread;
|
use std::thread;
|
||||||
|
|
||||||
use deno_core::anyhow::Context;
|
|
||||||
use deno_core::error::AnyError;
|
|
||||||
use deno_core::futures::channel::mpsc;
|
use deno_core::futures::channel::mpsc;
|
||||||
use deno_core::futures::channel::mpsc::UnboundedReceiver;
|
use deno_core::futures::channel::mpsc::UnboundedReceiver;
|
||||||
use deno_core::futures::channel::mpsc::UnboundedSender;
|
use deno_core::futures::channel::mpsc::UnboundedSender;
|
||||||
|
@ -49,17 +47,33 @@ pub struct InspectorServer {
|
||||||
thread_handle: Option<thread::JoinHandle<()>>,
|
thread_handle: Option<thread::JoinHandle<()>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, thiserror::Error, deno_error::JsError)]
|
||||||
|
pub enum InspectorServerError {
|
||||||
|
#[class(inherit)]
|
||||||
|
#[error(transparent)]
|
||||||
|
Io(#[from] std::io::Error),
|
||||||
|
#[class(inherit)]
|
||||||
|
#[error("Failed to start inspector server at \"{host}\"")]
|
||||||
|
Connect {
|
||||||
|
host: SocketAddr,
|
||||||
|
#[source]
|
||||||
|
#[inherit]
|
||||||
|
source: std::io::Error,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
impl InspectorServer {
|
impl InspectorServer {
|
||||||
pub fn new(host: SocketAddr, name: &'static str) -> Result<Self, AnyError> {
|
pub fn new(
|
||||||
|
host: SocketAddr,
|
||||||
|
name: &'static str,
|
||||||
|
) -> Result<Self, InspectorServerError> {
|
||||||
let (register_inspector_tx, register_inspector_rx) =
|
let (register_inspector_tx, register_inspector_rx) =
|
||||||
mpsc::unbounded::<InspectorInfo>();
|
mpsc::unbounded::<InspectorInfo>();
|
||||||
|
|
||||||
let (shutdown_server_tx, shutdown_server_rx) = broadcast::channel(1);
|
let (shutdown_server_tx, shutdown_server_rx) = broadcast::channel(1);
|
||||||
|
|
||||||
let tcp_listener =
|
let tcp_listener = std::net::TcpListener::bind(host)
|
||||||
std::net::TcpListener::bind(host).with_context(|| {
|
.map_err(|source| InspectorServerError::Connect { host, source })?;
|
||||||
format!("Failed to start inspector server at \"{}\"", host)
|
|
||||||
})?;
|
|
||||||
tcp_listener.set_nonblocking(true)?;
|
tcp_listener.set_nonblocking(true)?;
|
||||||
|
|
||||||
let thread_handle = thread::spawn(move || {
|
let thread_handle = thread::spawn(move || {
|
||||||
|
|
Loading…
Add table
Reference in a new issue