diff options
author | Kitson Kelly <me@kitsonkelly.com> | 2020-11-16 13:19:31 +1100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-11-16 13:19:31 +1100 |
commit | 37fbbf8101e7003d6de3d342db38fa9c55ab568f (patch) | |
tree | 858dc6db9d06fe7feb99fba4156ffe9cb2575c63 /cli/file_fetcher.rs | |
parent | 1079e59cf4df4a463d6114dc7eefe5809aa880b7 (diff) |
fix(cli): local sources are not cached in memory (#8328)
Fixes #4743
Closes #5253
Fixes #5631
Fixes #6116
Co-authored-by: Bartek IwaĆczuk <biwanczuk@gmail.com>
Co-authored-by: Luca Casonato <lucacasonato@yahoo.com>
Diffstat (limited to 'cli/file_fetcher.rs')
-rw-r--r-- | cli/file_fetcher.rs | 72 |
1 files changed, 56 insertions, 16 deletions
diff --git a/cli/file_fetcher.rs b/cli/file_fetcher.rs index 50544bfd9..0d11852d1 100644 --- a/cli/file_fetcher.rs +++ b/cli/file_fetcher.rs @@ -451,8 +451,7 @@ impl FileFetcher { Ok(file) } else { let is_local = scheme == "file"; - - let result = if is_local { + if is_local { fetch_local(specifier) } else if !self.allow_remote { Err(custom_error( @@ -460,27 +459,42 @@ impl FileFetcher { format!("A remote specifier was requested: \"{}\", but --no-remote is specified.", specifier), )) } else { - self.fetch_remote(specifier, permissions, 10).await - }; - - if let Ok(file) = &result { - self.cache.insert(specifier.clone(), file.clone()); + let result = self.fetch_remote(specifier, permissions, 10).await; + // only cache remote resources, as they are the only things that would + // be "expensive" to fetch multiple times during an invocation, and it + // also allows local file sources to be changed, enabling things like + // dynamic import and workers to be updated while Deno is running. + if let Ok(file) = &result { + self.cache.insert(specifier.clone(), file.clone()); + } + result } - - result } } - /// Get a previously in memory cached file. - pub fn get_cached(&self, specifier: &ModuleSpecifier) -> Option<File> { - self.cache.get(specifier) - } - /// Get the location of the current HTTP cache associated with the fetcher. pub fn get_http_cache_location(&self) -> PathBuf { self.http_cache.location.clone() } + /// A synchronous way to retrieve a source file, where if the file has already + /// been cached in memory it will be returned, otherwise for local files will + /// be read from disk. + pub fn get_source(&self, specifier: &ModuleSpecifier) -> Option<File> { + let maybe_file = self.cache.get(specifier); + if maybe_file.is_none() { + let is_local = specifier.as_url().scheme() == "file"; + if is_local { + if let Ok(file) = fetch_local(specifier) { + return Some(file); + } + } + None + } else { + maybe_file + } + } + /// Insert a temporary module into the in memory cache for the file fetcher. pub fn insert_cached(&self, file: File) -> Option<File> { self.cache.insert(file.specifier.clone(), file) @@ -778,7 +792,7 @@ mod tests { } #[tokio::test] - async fn test_get_cached() { + async fn test_get_source() { let _http_server_guard = test_util::http_server(); let (file_fetcher, _) = setup(CacheSetting::Use, None); let specifier = ModuleSpecifier::resolve_url( @@ -791,7 +805,7 @@ mod tests { .await; assert!(result.is_ok()); - let maybe_file = file_fetcher.get_cached(&specifier); + let maybe_file = file_fetcher.get_source(&specifier); assert!(maybe_file.is_some()); let file = maybe_file.unwrap(); assert_eq!(file.source, "export const redirect = 1;\n"); @@ -1298,6 +1312,32 @@ mod tests { } #[tokio::test] + async fn test_fetch_local_bypasses_file_cache() { + let (file_fetcher, temp_dir) = setup(CacheSetting::Use, None); + let fixture_path = temp_dir.path().join("mod.ts"); + let specifier = + ModuleSpecifier::resolve_url_or_path(&fixture_path.to_string_lossy()) + .unwrap(); + fs::write(fixture_path.clone(), r#"console.log("hello deno");"#) + .expect("could not write file"); + let result = file_fetcher + .fetch(&specifier, &Permissions::allow_all()) + .await; + assert!(result.is_ok()); + let file = result.unwrap(); + assert_eq!(file.source, r#"console.log("hello deno");"#); + + fs::write(fixture_path, r#"console.log("goodbye deno");"#) + .expect("could not write file"); + let result = file_fetcher + .fetch(&specifier, &Permissions::allow_all()) + .await; + assert!(result.is_ok()); + let file = result.unwrap(); + assert_eq!(file.source, r#"console.log("goodbye deno");"#); + } + + #[tokio::test] async fn test_fetch_local_utf_16be() { let expected = String::from_utf8( b"\xEF\xBB\xBFconsole.log(\"Hello World\");\x0A".to_vec(), |