mirror of
https://github.com/denoland/deno.git
synced 2024-12-26 00:59:24 -05:00
better error message for missing module (#3402)
This commit is contained in:
parent
bca23e6433
commit
658ec2aaf9
10 changed files with 81 additions and 47 deletions
|
@ -134,6 +134,7 @@ impl SourceFileFetcher {
|
||||||
pub fn fetch_source_file_async(
|
pub fn fetch_source_file_async(
|
||||||
self: &Self,
|
self: &Self,
|
||||||
specifier: &ModuleSpecifier,
|
specifier: &ModuleSpecifier,
|
||||||
|
maybe_referrer: Option<ModuleSpecifier>,
|
||||||
) -> Pin<Box<SourceFileFuture>> {
|
) -> Pin<Box<SourceFileFuture>> {
|
||||||
let module_url = specifier.as_url().to_owned();
|
let module_url = specifier.as_url().to_owned();
|
||||||
debug!("fetch_source_file. specifier {} ", &module_url);
|
debug!("fetch_source_file. specifier {} ", &module_url);
|
||||||
|
@ -156,12 +157,16 @@ impl SourceFileFetcher {
|
||||||
.then(move |result| {
|
.then(move |result| {
|
||||||
let mut out = match result.map_err(|err| {
|
let mut out = match result.map_err(|err| {
|
||||||
if err.kind() == ErrorKind::NotFound {
|
if err.kind() == ErrorKind::NotFound {
|
||||||
// For NotFound, change the message to something better.
|
let msg = if let Some(referrer) = maybe_referrer {
|
||||||
DenoError::new(
|
format!(
|
||||||
ErrorKind::NotFound,
|
"Cannot resolve module \"{}\" from \"{}\"",
|
||||||
format!("Cannot resolve module \"{}\"", module_url.to_string()),
|
module_url.to_string(),
|
||||||
|
referrer
|
||||||
)
|
)
|
||||||
.into()
|
} else {
|
||||||
|
format!("Cannot resolve module \"{}\"", module_url.to_string())
|
||||||
|
};
|
||||||
|
DenoError::new(ErrorKind::NotFound, msg).into()
|
||||||
} else {
|
} else {
|
||||||
err
|
err
|
||||||
}
|
}
|
||||||
|
@ -1011,10 +1016,12 @@ mod tests {
|
||||||
);
|
);
|
||||||
|
|
||||||
// first download
|
// first download
|
||||||
tokio_util::run(fetcher.fetch_source_file_async(&specifier).then(|r| {
|
tokio_util::run(fetcher.fetch_source_file_async(&specifier, None).then(
|
||||||
|
|r| {
|
||||||
assert!(r.is_ok());
|
assert!(r.is_ok());
|
||||||
futures::future::ok(())
|
futures::future::ok(())
|
||||||
}));
|
},
|
||||||
|
));
|
||||||
|
|
||||||
let result = fs::File::open(&headers_file_name);
|
let result = fs::File::open(&headers_file_name);
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
|
@ -1026,10 +1033,12 @@ mod tests {
|
||||||
// download file again, it should use already fetched file even though `use_disk_cache` is set to
|
// download file again, it should use already fetched file even though `use_disk_cache` is set to
|
||||||
// false, this can be verified using source header file creation timestamp (should be
|
// false, this can be verified using source header file creation timestamp (should be
|
||||||
// the same as after first download)
|
// the same as after first download)
|
||||||
tokio_util::run(fetcher.fetch_source_file_async(&specifier).then(|r| {
|
tokio_util::run(fetcher.fetch_source_file_async(&specifier, None).then(
|
||||||
|
|r| {
|
||||||
assert!(r.is_ok());
|
assert!(r.is_ok());
|
||||||
futures::future::ok(())
|
futures::future::ok(())
|
||||||
}));
|
},
|
||||||
|
));
|
||||||
|
|
||||||
let result = fs::File::open(&headers_file_name);
|
let result = fs::File::open(&headers_file_name);
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
|
@ -1443,20 +1452,24 @@ mod tests {
|
||||||
// Test failure case.
|
// Test failure case.
|
||||||
let specifier =
|
let specifier =
|
||||||
ModuleSpecifier::resolve_url(file_url!("/baddir/hello.ts")).unwrap();
|
ModuleSpecifier::resolve_url(file_url!("/baddir/hello.ts")).unwrap();
|
||||||
tokio_util::run(fetcher.fetch_source_file_async(&specifier).then(|r| {
|
tokio_util::run(fetcher.fetch_source_file_async(&specifier, None).then(
|
||||||
|
|r| {
|
||||||
assert!(r.is_err());
|
assert!(r.is_err());
|
||||||
futures::future::ok(())
|
futures::future::ok(())
|
||||||
}));
|
},
|
||||||
|
));
|
||||||
|
|
||||||
let p = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
let p = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
||||||
.join("js/main.ts")
|
.join("js/main.ts")
|
||||||
.to_owned();
|
.to_owned();
|
||||||
let specifier =
|
let specifier =
|
||||||
ModuleSpecifier::resolve_url_or_path(p.to_str().unwrap()).unwrap();
|
ModuleSpecifier::resolve_url_or_path(p.to_str().unwrap()).unwrap();
|
||||||
tokio_util::run(fetcher.fetch_source_file_async(&specifier).then(|r| {
|
tokio_util::run(fetcher.fetch_source_file_async(&specifier, None).then(
|
||||||
|
|r| {
|
||||||
assert!(r.is_ok());
|
assert!(r.is_ok());
|
||||||
futures::future::ok(())
|
futures::future::ok(())
|
||||||
}));
|
},
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -1467,20 +1480,24 @@ mod tests {
|
||||||
// Test failure case.
|
// Test failure case.
|
||||||
let specifier =
|
let specifier =
|
||||||
ModuleSpecifier::resolve_url(file_url!("/baddir/hello.ts")).unwrap();
|
ModuleSpecifier::resolve_url(file_url!("/baddir/hello.ts")).unwrap();
|
||||||
tokio_util::run(fetcher.fetch_source_file_async(&specifier).then(|r| {
|
tokio_util::run(fetcher.fetch_source_file_async(&specifier, None).then(
|
||||||
|
|r| {
|
||||||
assert!(r.is_err());
|
assert!(r.is_err());
|
||||||
futures::future::ok(())
|
futures::future::ok(())
|
||||||
}));
|
},
|
||||||
|
));
|
||||||
|
|
||||||
let p = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
let p = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
||||||
.join("js/main.ts")
|
.join("js/main.ts")
|
||||||
.to_owned();
|
.to_owned();
|
||||||
let specifier =
|
let specifier =
|
||||||
ModuleSpecifier::resolve_url_or_path(p.to_str().unwrap()).unwrap();
|
ModuleSpecifier::resolve_url_or_path(p.to_str().unwrap()).unwrap();
|
||||||
tokio_util::run(fetcher.fetch_source_file_async(&specifier).then(|r| {
|
tokio_util::run(fetcher.fetch_source_file_async(&specifier, None).then(
|
||||||
|
|r| {
|
||||||
assert!(r.is_ok());
|
assert!(r.is_ok());
|
||||||
futures::future::ok(())
|
futures::future::ok(())
|
||||||
}));
|
},
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -124,13 +124,14 @@ impl ThreadSafeGlobalState {
|
||||||
pub fn fetch_compiled_module(
|
pub fn fetch_compiled_module(
|
||||||
self: &Self,
|
self: &Self,
|
||||||
module_specifier: &ModuleSpecifier,
|
module_specifier: &ModuleSpecifier,
|
||||||
|
maybe_referrer: Option<ModuleSpecifier>,
|
||||||
) -> impl Future<Output = Result<CompiledModule, ErrBox>> {
|
) -> impl Future<Output = Result<CompiledModule, ErrBox>> {
|
||||||
let state1 = self.clone();
|
let state1 = self.clone();
|
||||||
let state2 = self.clone();
|
let state2 = self.clone();
|
||||||
|
|
||||||
self
|
self
|
||||||
.file_fetcher
|
.file_fetcher
|
||||||
.fetch_source_file_async(&module_specifier)
|
.fetch_source_file_async(&module_specifier, maybe_referrer)
|
||||||
.and_then(move |out| match out.media_type {
|
.and_then(move |out| match out.media_type {
|
||||||
msg::MediaType::Unknown => state1.js_compiler.compile_async(&out),
|
msg::MediaType::Unknown => state1.js_compiler.compile_async(&out),
|
||||||
msg::MediaType::Json => state1.json_compiler.compile_async(&out),
|
msg::MediaType::Json => state1.json_compiler.compile_async(&out),
|
||||||
|
|
|
@ -171,7 +171,8 @@ class SourceFile {
|
||||||
|
|
||||||
/** Cache the source file to be able to be retrieved by `moduleSpecifier` and
|
/** Cache the source file to be able to be retrieved by `moduleSpecifier` and
|
||||||
* `containingFile`. */
|
* `containingFile`. */
|
||||||
cache(moduleSpecifier: string, containingFile: string): void {
|
cache(moduleSpecifier: string, containingFile?: string): void {
|
||||||
|
containingFile = containingFile || "";
|
||||||
let innerCache = SourceFile._specifierCache.get(containingFile);
|
let innerCache = SourceFile._specifierCache.get(containingFile);
|
||||||
if (!innerCache) {
|
if (!innerCache) {
|
||||||
innerCache = new Map();
|
innerCache = new Map();
|
||||||
|
@ -269,7 +270,7 @@ function fetchAsset(name: string): string {
|
||||||
/** Ops to Rust to resolve and fetch modules meta data. */
|
/** Ops to Rust to resolve and fetch modules meta data. */
|
||||||
function fetchSourceFiles(
|
function fetchSourceFiles(
|
||||||
specifiers: string[],
|
specifiers: string[],
|
||||||
referrer: string
|
referrer?: string
|
||||||
): Promise<SourceFileJson[]> {
|
): Promise<SourceFileJson[]> {
|
||||||
util.log("compiler::fetchSourceFiles", { specifiers, referrer });
|
util.log("compiler::fetchSourceFiles", { specifiers, referrer });
|
||||||
return sendAsync(dispatch.OP_FETCH_SOURCE_FILES, {
|
return sendAsync(dispatch.OP_FETCH_SOURCE_FILES, {
|
||||||
|
@ -286,7 +287,7 @@ function fetchSourceFiles(
|
||||||
* that should be actually resolved. */
|
* that should be actually resolved. */
|
||||||
async function processImports(
|
async function processImports(
|
||||||
specifiers: Array<[string, string]>,
|
specifiers: Array<[string, string]>,
|
||||||
referrer = ""
|
referrer?: string
|
||||||
): Promise<SourceFileJson[]> {
|
): Promise<SourceFileJson[]> {
|
||||||
if (!specifiers.length) {
|
if (!specifiers.length) {
|
||||||
return [];
|
return [];
|
||||||
|
|
|
@ -176,7 +176,7 @@ async fn print_file_info(worker: Worker, module_specifier: ModuleSpecifier) {
|
||||||
|
|
||||||
let maybe_source_file = global_state_
|
let maybe_source_file = global_state_
|
||||||
.file_fetcher
|
.file_fetcher
|
||||||
.fetch_source_file_async(&module_specifier)
|
.fetch_source_file_async(&module_specifier, None)
|
||||||
.await;
|
.await;
|
||||||
if let Err(err) = maybe_source_file {
|
if let Err(err) = maybe_source_file {
|
||||||
println!("{}", err);
|
println!("{}", err);
|
||||||
|
@ -197,7 +197,7 @@ async fn print_file_info(worker: Worker, module_specifier: ModuleSpecifier) {
|
||||||
|
|
||||||
let maybe_compiled = global_state_
|
let maybe_compiled = global_state_
|
||||||
.clone()
|
.clone()
|
||||||
.fetch_compiled_module(&module_specifier)
|
.fetch_compiled_module(&module_specifier, None)
|
||||||
.await;
|
.await;
|
||||||
if let Err(e) = maybe_compiled {
|
if let Err(e) = maybe_compiled {
|
||||||
debug!("compiler error exiting!");
|
debug!("compiler error exiting!");
|
||||||
|
|
|
@ -51,7 +51,7 @@ fn op_cache(
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
struct FetchSourceFilesArgs {
|
struct FetchSourceFilesArgs {
|
||||||
specifiers: Vec<String>,
|
specifiers: Vec<String>,
|
||||||
referrer: String,
|
referrer: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn op_fetch_source_files(
|
fn op_fetch_source_files(
|
||||||
|
@ -65,14 +65,23 @@ fn op_fetch_source_files(
|
||||||
// to this. Need a test to demonstrate the hole.
|
// to this. Need a test to demonstrate the hole.
|
||||||
let is_dyn_import = false;
|
let is_dyn_import = false;
|
||||||
|
|
||||||
|
let (referrer, ref_specifier) = if let Some(referrer) = args.referrer {
|
||||||
|
let specifier = ModuleSpecifier::resolve_url(&referrer)
|
||||||
|
.expect("Referrer is not a valid specifier");
|
||||||
|
(referrer, Some(specifier))
|
||||||
|
} else {
|
||||||
|
// main script import
|
||||||
|
(".".to_string(), None)
|
||||||
|
};
|
||||||
|
|
||||||
let mut futures = vec![];
|
let mut futures = vec![];
|
||||||
for specifier in &args.specifiers {
|
for specifier in &args.specifiers {
|
||||||
let resolved_specifier =
|
let resolved_specifier =
|
||||||
state.resolve(specifier, &args.referrer, false, is_dyn_import)?;
|
state.resolve(specifier, &referrer, false, is_dyn_import)?;
|
||||||
let fut = state
|
let fut = state
|
||||||
.global_state
|
.global_state
|
||||||
.file_fetcher
|
.file_fetcher
|
||||||
.fetch_source_file_async(&resolved_specifier);
|
.fetch_source_file_async(&resolved_specifier, ref_specifier.clone());
|
||||||
futures.push(fut);
|
futures.push(fut);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -178,12 +178,13 @@ impl Loader for ThreadSafeState {
|
||||||
fn load(
|
fn load(
|
||||||
&self,
|
&self,
|
||||||
module_specifier: &ModuleSpecifier,
|
module_specifier: &ModuleSpecifier,
|
||||||
|
maybe_referrer: Option<ModuleSpecifier>,
|
||||||
) -> Pin<Box<deno::SourceCodeInfoFuture>> {
|
) -> Pin<Box<deno::SourceCodeInfoFuture>> {
|
||||||
self.metrics.resolve_count.fetch_add(1, Ordering::SeqCst);
|
self.metrics.resolve_count.fetch_add(1, Ordering::SeqCst);
|
||||||
let module_url_specified = module_specifier.to_string();
|
let module_url_specified = module_specifier.to_string();
|
||||||
let fut = self
|
let fut = self
|
||||||
.global_state
|
.global_state
|
||||||
.fetch_compiled_module(module_specifier)
|
.fetch_compiled_module(module_specifier, maybe_referrer)
|
||||||
.map_ok(|compiled_module| deno::SourceCodeInfo {
|
.map_ok(|compiled_module| deno::SourceCodeInfo {
|
||||||
// Real module name, might be different from initial specifier
|
// Real module name, might be different from initial specifier
|
||||||
// due to redirections.
|
// due to redirections.
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
[WILDCARD]error: Uncaught NotFound: Cannot resolve module "[WILDCARD]/bad-module.ts"
|
[WILDCARD]error: Uncaught NotFound: Cannot resolve module "[WILDCARD]/bad-module.ts" from "[WILDCARD]/error_004_missing_module.ts"
|
||||||
[WILDCARD]dispatch_json.ts:[WILDCARD]
|
[WILDCARD]dispatch_json.ts:[WILDCARD]
|
||||||
at DenoError ([WILDCARD]errors.ts:[WILDCARD])
|
at DenoError ([WILDCARD]errors.ts:[WILDCARD])
|
||||||
at unwrapResponse ([WILDCARD]dispatch_json.ts:[WILDCARD])
|
at unwrapResponse ([WILDCARD]dispatch_json.ts:[WILDCARD])
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
[WILDCARD]error: Uncaught NotFound: Cannot resolve module "[WILDCARD]/bad-module.ts"
|
[WILDCARD]error: Uncaught NotFound: Cannot resolve module "[WILDCARD]/bad-module.ts" from "[WILDCARD]/error_005_missing_dynamic_import.ts"
|
||||||
[WILDCARD]dispatch_json.ts:[WILDCARD]
|
[WILDCARD]dispatch_json.ts:[WILDCARD]
|
||||||
at DenoError ([WILDCARD]errors.ts:[WILDCARD])
|
at DenoError ([WILDCARD]errors.ts:[WILDCARD])
|
||||||
at unwrapResponse ([WILDCARD]dispatch_json.ts:[WILDCARD])
|
at unwrapResponse ([WILDCARD]dispatch_json.ts:[WILDCARD])
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
[WILDCARD]error: Uncaught NotFound: Cannot resolve module "[WILDCARD]/non-existent"
|
[WILDCARD]error: Uncaught NotFound: Cannot resolve module "[WILDCARD]/non-existent" from "[WILDCARD]/error_006_import_ext_failure.ts"
|
||||||
[WILDCARD]dispatch_json.ts:[WILDCARD]
|
[WILDCARD]dispatch_json.ts:[WILDCARD]
|
||||||
at DenoError ([WILDCARD]errors.ts:[WILDCARD])
|
at DenoError ([WILDCARD]errors.ts:[WILDCARD])
|
||||||
at unwrapResponse ([WILDCARD]dispatch_json.ts:[WILDCARD])
|
at unwrapResponse ([WILDCARD]dispatch_json.ts:[WILDCARD])
|
||||||
|
|
|
@ -48,6 +48,7 @@ pub trait Loader: Send + Sync {
|
||||||
fn load(
|
fn load(
|
||||||
&self,
|
&self,
|
||||||
module_specifier: &ModuleSpecifier,
|
module_specifier: &ModuleSpecifier,
|
||||||
|
maybe_referrer: Option<ModuleSpecifier>,
|
||||||
) -> Pin<Box<SourceCodeInfoFuture>>;
|
) -> Pin<Box<SourceCodeInfoFuture>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,7 +155,7 @@ impl<L: Loader + Unpin> RecursiveLoad<L> {
|
||||||
// integrated into one thing.
|
// integrated into one thing.
|
||||||
self
|
self
|
||||||
.pending
|
.pending
|
||||||
.push(self.loader.load(&module_specifier).boxed());
|
.push(self.loader.load(&module_specifier, None).boxed());
|
||||||
self.state = State::LoadingRoot;
|
self.state = State::LoadingRoot;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -166,6 +167,8 @@ impl<L: Loader + Unpin> RecursiveLoad<L> {
|
||||||
referrer: &str,
|
referrer: &str,
|
||||||
parent_id: deno_mod,
|
parent_id: deno_mod,
|
||||||
) -> Result<(), ErrBox> {
|
) -> Result<(), ErrBox> {
|
||||||
|
let referrer_specifier = ModuleSpecifier::resolve_url(referrer)
|
||||||
|
.expect("Referrer should be a valid specifier");
|
||||||
let module_specifier = self.loader.resolve(
|
let module_specifier = self.loader.resolve(
|
||||||
specifier,
|
specifier,
|
||||||
referrer,
|
referrer,
|
||||||
|
@ -181,9 +184,10 @@ impl<L: Loader + Unpin> RecursiveLoad<L> {
|
||||||
if !modules.is_registered(module_name)
|
if !modules.is_registered(module_name)
|
||||||
&& !self.is_pending.contains(&module_specifier)
|
&& !self.is_pending.contains(&module_specifier)
|
||||||
{
|
{
|
||||||
self
|
let fut = self
|
||||||
.pending
|
.loader
|
||||||
.push(self.loader.load(&module_specifier).boxed());
|
.load(&module_specifier, Some(referrer_specifier.clone()));
|
||||||
|
self.pending.push(fut.boxed());
|
||||||
self.is_pending.insert(module_specifier);
|
self.is_pending.insert(module_specifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -739,6 +743,7 @@ mod tests {
|
||||||
fn load(
|
fn load(
|
||||||
&self,
|
&self,
|
||||||
module_specifier: &ModuleSpecifier,
|
module_specifier: &ModuleSpecifier,
|
||||||
|
_maybe_referrer: Option<ModuleSpecifier>,
|
||||||
) -> Pin<Box<SourceCodeInfoFuture>> {
|
) -> Pin<Box<SourceCodeInfoFuture>> {
|
||||||
let mut loads = self.loads.lock().unwrap();
|
let mut loads = self.loads.lock().unwrap();
|
||||||
loads.push(module_specifier.to_string());
|
loads.push(module_specifier.to_string());
|
||||||
|
|
Loading…
Reference in a new issue