1
0
Fork 0
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:
Bartek Iwańczuk 2019-11-25 15:33:23 +01:00 committed by Ry Dahl
parent bca23e6433
commit 658ec2aaf9
10 changed files with 81 additions and 47 deletions

View file

@ -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]

View file

@ -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),

View file

@ -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 [];

View file

@ -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!");

View file

@ -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);
} }

View file

@ -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.

View file

@ -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])

View file

@ -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])

View file

@ -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])

View file

@ -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());