summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Sherret <dsherret@users.noreply.github.com>2024-04-18 21:43:28 -0400
committerGitHub <noreply@github.com>2024-04-19 01:43:28 +0000
commitc497e766f1a136c674d8be2467eb103c85fe1d44 (patch)
treea6b84f9950f2bdca734d8d402b60d44f99605965
parent8e77f091ad9b1f8b3dc2eaf8b4a2be2560a67354 (diff)
refactor: move redirect handling into deno_graph (#23444)
-rw-r--r--Cargo.toml2
-rw-r--r--cli/args/import_map.rs4
-rw-r--r--cli/cache/mod.rs55
-rw-r--r--cli/file_fetcher.rs451
-rw-r--r--cli/graph_util.rs8
-rw-r--r--cli/jsr.rs4
-rw-r--r--cli/lsp/config.rs2
-rw-r--r--cli/lsp/jsr.rs2
-rw-r--r--cli/lsp/npm.rs2
-rw-r--r--cli/lsp/registries.rs11
-rw-r--r--cli/npm/mod.rs2
-rw-r--r--cli/tools/coverage/mod.rs2
-rw-r--r--cli/tools/doc.rs10
-rw-r--r--cli/tools/repl/mod.rs2
-rw-r--r--cli/tools/test/mod.rs4
-rw-r--r--cli/tools/vendor/test.rs8
-rw-r--r--tests/integration/bench_tests.rs2
-rw-r--r--tests/integration/cache_tests.rs2
-rw-r--r--tests/integration/run_tests.rs2
-rw-r--r--tests/integration/test_tests.rs2
-rw-r--r--tests/specs/info/multiple_redirects/__test__.jsonc4
-rw-r--r--tests/specs/info/multiple_redirects/main.out51
-rw-r--r--tests/specs/info/multiple_redirects/main.ts2
23 files changed, 374 insertions, 260 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 808a43f3e..6eaadc669 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -48,7 +48,7 @@ deno_core = { version = "0.275.0" }
deno_bench_util = { version = "0.141.0", path = "./bench_util" }
deno_lockfile = "0.19.0"
-deno_media_type = { version = "0.1.3", features = ["module_specifier"] }
+deno_media_type = { version = "0.1.4", features = ["module_specifier"] }
deno_permissions = { version = "0.7.0", path = "./runtime/permissions" }
deno_runtime = { version = "0.155.0", path = "./runtime" }
deno_terminal = "0.1.1"
diff --git a/cli/args/import_map.rs b/cli/args/import_map.rs
index 517c3bff6..d06c4d385 100644
--- a/cli/args/import_map.rs
+++ b/cli/args/import_map.rs
@@ -28,7 +28,7 @@ pub async fn resolve_import_map(
let specifier = specifier.clone();
async move {
let file = file_fetcher
- .fetch(&specifier, PermissionsContainer::allow_all())
+ .fetch(&specifier, &PermissionsContainer::allow_all())
.await?
.into_text_decoded()?;
Ok(file.source.to_string())
@@ -62,7 +62,7 @@ async fn resolve_import_map_from_specifier(
serde_json::from_str(&data_url_text)?
} else {
let file = file_fetcher
- .fetch(&specifier, PermissionsContainer::allow_all())
+ .fetch(&specifier, &PermissionsContainer::allow_all())
.await?
.into_text_decoded()?;
serde_json::from_str(&file.source)?
diff --git a/cli/cache/mod.rs b/cli/cache/mod.rs
index aa8d3b9de..6ddeced9a 100644
--- a/cli/cache/mod.rs
+++ b/cli/cache/mod.rs
@@ -2,8 +2,10 @@
use crate::args::CacheSetting;
use crate::errors::get_error_class_name;
+use crate::file_fetcher::FetchNoFollowOptions;
use crate::file_fetcher::FetchOptions;
use crate::file_fetcher::FileFetcher;
+use crate::file_fetcher::FileOrRedirect;
use crate::npm::CliNpmResolver;
use crate::util::fs::atomic_write_file;
@@ -234,29 +236,40 @@ impl Loader for FetchCacher {
LoaderCacheSetting::Only => Some(CacheSetting::Only),
};
file_fetcher
- .fetch_with_options(FetchOptions {
- specifier: &specifier,
- permissions,
- maybe_accept: None,
- maybe_cache_setting: maybe_cache_setting.as_ref(),
- maybe_checksum: options.maybe_checksum,
+ .fetch_no_follow_with_options(FetchNoFollowOptions {
+ fetch_options: FetchOptions {
+ specifier: &specifier,
+ permissions: &permissions,
+ maybe_accept: None,
+ maybe_cache_setting: maybe_cache_setting.as_ref(),
+ },
+ maybe_checksum: options.maybe_checksum.as_ref(),
})
.await
- .map(|file| {
- let maybe_headers =
- match (file.maybe_headers, file_header_overrides.get(&specifier)) {
- (Some(headers), Some(overrides)) => {
- Some(headers.into_iter().chain(overrides.clone()).collect())
- }
- (Some(headers), None) => Some(headers),
- (None, Some(overrides)) => Some(overrides.clone()),
- (None, None) => None,
- };
- Ok(Some(LoadResponse::Module {
- specifier: file.specifier,
- maybe_headers,
- content: file.source,
- }))
+ .map(|file_or_redirect| {
+ match file_or_redirect {
+ FileOrRedirect::File(file) => {
+ let maybe_headers =
+ match (file.maybe_headers, file_header_overrides.get(&specifier)) {
+ (Some(headers), Some(overrides)) => {
+ Some(headers.into_iter().chain(overrides.clone()).collect())
+ }
+ (Some(headers), None) => Some(headers),
+ (None, Some(overrides)) => Some(overrides.clone()),
+ (None, None) => None,
+ };
+ Ok(Some(LoadResponse::Module {
+ specifier: file.specifier,
+ maybe_headers,
+ content: file.source,
+ }))
+ },
+ FileOrRedirect::Redirect(redirect_specifier) => {
+ Ok(Some(LoadResponse::Redirect {
+ specifier: redirect_specifier,
+ }))
+ },
+ }
})
.unwrap_or_else(|err| {
if let Some(io_err) = err.downcast_ref::<std::io::Error>() {
diff --git a/cli/file_fetcher.rs b/cli/file_fetcher.rs
index 3808d68ce..ee226ca34 100644
--- a/cli/file_fetcher.rs
+++ b/cli/file_fetcher.rs
@@ -20,8 +20,6 @@ use deno_core::error::custom_error;
use deno_core::error::generic_error;
use deno_core::error::uri_error;
use deno_core::error::AnyError;
-use deno_core::futures;
-use deno_core::futures::future::FutureExt;
use deno_core::parking_lot::Mutex;
use deno_core::url::Url;
use deno_core::ModuleSpecifier;
@@ -34,12 +32,11 @@ use deno_runtime::deno_fetch::reqwest::StatusCode;
use deno_runtime::deno_web::BlobStore;
use deno_runtime::permissions::PermissionsContainer;
use log::debug;
+use std::borrow::Cow;
use std::collections::HashMap;
use std::env;
use std::fs;
-use std::future::Future;
use std::path::PathBuf;
-use std::pin::Pin;
use std::sync::Arc;
use std::time::SystemTime;
@@ -56,6 +53,12 @@ pub struct TextDecodedFile {
pub source: Arc<str>,
}
+#[derive(Debug, Clone, Eq, PartialEq)]
+pub enum FileOrRedirect {
+ File(File),
+ Redirect(ModuleSpecifier),
+}
+
/// A structure representing a source file.
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct File {
@@ -145,10 +148,16 @@ fn get_validated_scheme(
pub struct FetchOptions<'a> {
pub specifier: &'a ModuleSpecifier,
- pub permissions: PermissionsContainer,
+ pub permissions: &'a PermissionsContainer,
pub maybe_accept: Option<&'a str>,
pub maybe_cache_setting: Option<&'a CacheSetting>,
- pub maybe_checksum: Option<LoaderChecksum>,
+}
+
+pub struct FetchNoFollowOptions<'a> {
+ pub fetch_options: FetchOptions<'a>,
+ /// This setting doesn't make sense to provide for `FetchOptions`
+ /// since the required checksum may change for a redirect.
+ pub maybe_checksum: Option<&'a LoaderChecksum>,
}
/// A structure for resolving, fetching and caching source files.
@@ -202,13 +211,34 @@ impl FileFetcher {
pub fn fetch_cached(
&self,
specifier: &ModuleSpecifier,
- maybe_checksum: Option<LoaderChecksum>,
redirect_limit: i64,
) -> Result<Option<File>, AnyError> {
- debug!("FileFetcher::fetch_cached - specifier: {}", specifier);
- if redirect_limit < 0 {
- return Err(custom_error("Http", "Too many redirects."));
+ let mut specifier = Cow::Borrowed(specifier);
+ for _ in 0..=redirect_limit {
+ match self.fetch_cached_no_follow(&specifier, None)? {
+ Some(FileOrRedirect::File(file)) => {
+ return Ok(Some(file));
+ }
+ Some(FileOrRedirect::Redirect(redirect_specifier)) => {
+ specifier = Cow::Owned(redirect_specifier);
+ }
+ None => {
+ return Ok(None);
+ }
+ }
}
+ Err(custom_error("Http", "Too many redirects."))
+ }
+
+ fn fetch_cached_no_follow(
+ &self,
+ specifier: &ModuleSpecifier,
+ maybe_checksum: Option<&LoaderChecksum>,
+ ) -> Result<Option<FileOrRedirect>, AnyError> {
+ debug!(
+ "FileFetcher::fetch_cached_no_follow - specifier: {}",
+ specifier
+ );
let cache_key = self.http_cache.cache_item_key(specifier)?; // compute this once
let Some(headers) = self.http_cache.read_headers(&cache_key)? else {
@@ -217,7 +247,7 @@ impl FileFetcher {
if let Some(redirect_to) = headers.get("location") {
let redirect =
deno_core::resolve_import(redirect_to, specifier.as_str())?;
- return self.fetch_cached(&redirect, maybe_checksum, redirect_limit - 1);
+ return Ok(Some(FileOrRedirect::Redirect(redirect)));
}
let Some(bytes) = self.http_cache.read_file_bytes(
&cache_key,
@@ -230,11 +260,11 @@ impl FileFetcher {
return Ok(None);
};
- Ok(Some(File {
+ Ok(Some(FileOrRedirect::File(File {
specifier: specifier.clone(),
maybe_headers: Some(headers),
source: Arc::from(bytes),
- }))
+ })))
}
/// Convert a data URL into a file, resulting in an error if the URL is
@@ -280,51 +310,33 @@ impl FileFetcher {
})
}
- /// Asynchronously fetch remote source file specified by the URL following
- /// redirects.
- ///
- /// **Note** this is a recursive method so it can't be "async", but needs to
- /// return a `Pin<Box<..>>`.
- fn fetch_remote(
+ async fn fetch_remote_no_follow(
&self,
specifier: &ModuleSpecifier,
- permissions: PermissionsContainer,
- redirect_limit: i64,
- maybe_accept: Option<String>,
+ maybe_accept: Option<&str>,
cache_setting: &CacheSetting,
- maybe_checksum: Option<LoaderChecksum>,
- ) -> Pin<Box<dyn Future<Output = Result<File, AnyError>> + Send>> {
- debug!("FileFetcher::fetch_remote() - specifier: {}", specifier);
- if redirect_limit < 0 {
- return futures::future::err(custom_error("Http", "Too many redirects."))
- .boxed();
- }
-
- if let Err(err) = permissions.check_specifier(specifier) {
- return futures::future::err(err).boxed();
- }
+ maybe_checksum: Option<&LoaderChecksum>,
+ ) -> Result<FileOrRedirect, AnyError> {
+ debug!(
+ "FileFetcher::fetch_remote_no_follow - specifier: {}",
+ specifier
+ );
if self.should_use_cache(specifier, cache_setting) {
- match self.fetch_cached(specifier, maybe_checksum.clone(), redirect_limit)
+ if let Some(file_or_redirect) =
+ self.fetch_cached_no_follow(specifier, maybe_checksum)?
{
- Ok(Some(file)) => {
- return futures::future::ok(file).boxed();
- }
- Ok(None) => {}
- Err(err) => {
- return futures::future::err(err).boxed();
- }
+ return Ok(file_or_redirect);
}
}
if *cache_setting == CacheSetting::Only {
- return futures::future::err(custom_error(
+ return Err(custom_error(
"NotCached",
format!(
"Specifier not found in cache: \"{specifier}\", --cached-only is specified."
),
- ))
- .boxed();
+ ));
}
let mut maybe_progress_guard = None;
@@ -346,12 +358,6 @@ impl FileFetcher {
.and_then(|key| self.http_cache.read_headers(&key).ok().flatten())
.and_then(|headers| headers.get("etag").cloned());
let maybe_auth_token = self.auth_tokens.get(specifier);
- let specifier = specifier.clone();
- let client = self.http_client.clone();
- let file_fetcher = self.clone();
- let cache_setting = cache_setting.clone();
- // A single pass of fetch either yields code or yields a redirect, server
- // error causes a single retry to avoid crashing hard on intermittent failures.
async fn handle_request_or_server_error(
retried: &mut bool,
@@ -372,90 +378,75 @@ impl FileFetcher {
}
}
- async move {
- let mut maybe_etag = maybe_etag;
- let mut retried = false;
- let result = loop {
- let result = match fetch_once(
- &client,
- FetchOnceArgs {
- url: specifier.clone(),
- maybe_accept: maybe_accept.clone(),
- maybe_etag: maybe_etag.clone(),
- maybe_auth_token: maybe_auth_token.clone(),
- maybe_progress_guard: maybe_progress_guard.as_ref(),
- },
- )
- .await?
- {
- FetchOnceResult::NotModified => {
- let file = file_fetcher
- .fetch_cached(&specifier, maybe_checksum.clone(), 10)?;
- match file {
- Some(file) => Ok(file),
- None => {
- // Someone may have deleted the body from the cache since
- // it's currently stored in a separate file from the headers,
- // so delete the etag and try again
- if maybe_etag.is_some() {
- debug!("Cache body not found. Trying again without etag.");
- maybe_etag = None;
- continue;
- } else {
- // should never happen
- bail!("Your deno cache directory is in an unrecoverable state. Please delete it and try again.")
- }
+ let mut maybe_etag = maybe_etag;
+ let mut retried = false; // retry intermittent failures
+ let result = loop {
+ let result = match fetch_no_follow(
+ &self.http_client,
+ FetchOnceArgs {
+ url: specifier.clone(),
+ maybe_accept: maybe_accept.map(ToOwned::to_owned),
+ maybe_etag: maybe_etag.clone(),
+ maybe_auth_token: maybe_auth_token.clone(),
+ maybe_progress_guard: maybe_progress_guard.as_ref(),
+ },
+ )
+ .await?
+ {
+ FetchOnceResult::NotModified => {
+ let file_or_redirect =
+ self.fetch_cached_no_follow(specifier, maybe_checksum)?;
+ match file_or_redirect {
+ Some(file_or_redirect) => Ok(file_or_redirect),
+ None => {
+ // Someone may have deleted the body from the cache since
+ // it's currently stored in a separate file from the headers,
+ // so delete the etag and try again
+ if maybe_etag.is_some() {
+ debug!("Cache body not found. Trying again without etag.");
+ maybe_etag = None;
+ continue;
+ } else {
+ // should never happen
+ bail!("Your deno cache directory is in an unrecoverable state. Please delete it and try again.")
}
}
}
- FetchOnceResult::Redirect(redirect_url, headers) => {
- file_fetcher.http_cache.set(&specifier, headers, &[])?;
- file_fetcher
- .fetch_remote(
- &redirect_url,
- permissions,
- redirect_limit - 1,
- maybe_accept,
- &cache_setting,
- maybe_checksum,
- )
- .await
- }
- FetchOnceResult::Code(bytes, headers) => {
- file_fetcher
- .http_cache
- .set(&specifier, headers.clone(), &bytes)?;
- if let Some(checksum) = &maybe_checksum {
- checksum.check_source(&bytes)?;
- }
- Ok(File {
- specifier,
- maybe_headers: Some(headers),
- source: Arc::from(bytes),
- })
- }
- FetchOnceResult::RequestError(err) => {
- handle_request_or_server_error(&mut retried, &specifier, err)
- .await?;
- continue;
- }
- FetchOnceResult::ServerError(status) => {
- handle_request_or_server_error(
- &mut retried,
- &specifier,
- status.to_string(),
- )
- .await?;
- continue;
+ }
+ FetchOnceResult::Redirect(redirect_url, headers) => {
+ self.http_cache.set(specifier, headers, &[])?;
+ Ok(FileOrRedirect::Redirect(redirect_url))
+ }
+ FetchOnceResult::Code(bytes, headers) => {
+ self.http_cache.set(specifier, headers.clone(), &bytes)?;
+ if let Some(checksum) = &maybe_checksum {
+ checksum.check_source(&bytes)?;
}
- };
- break result;
+ Ok(FileOrRedirect::File(File {
+ specifier: specifier.clone(),
+ maybe_headers: Some(headers),
+ source: Arc::from(bytes),
+ }))
+ }
+ FetchOnceResult::RequestError(err) => {
+ handle_request_or_server_error(&mut retried, specifier, err).await?;
+ continue;
+ }
+ FetchOnceResult::ServerError(status) => {
+ handle_request_or_server_error(
+ &mut retried,
+ specifier,
+ status.to_string(),
+ )
+ .await?;
+ continue;
+ }
};
+ break result;
+ };
- drop(maybe_progress_guard);
- result
- }
- .boxed()
+ drop(maybe_progress_guard);
+ result
}
/// Returns if the cache should be used for a given specifier.
@@ -508,7 +499,7 @@ impl FileFetcher {
pub async fn fetch(
&self,
specifier: &ModuleSpecifier,
- permissions: PermissionsContainer,
+ permissions: &PermissionsContainer,
) -> Result<File, AnyError> {
self
.fetch_with_options(FetchOptions {
@@ -516,7 +507,6 @@ impl FileFetcher {
permissions,
maybe_accept: None,
maybe_cache_setting: None,
- maybe_checksum: None,
})
.await
}
@@ -525,20 +515,68 @@ impl FileFetcher {
&self,
options: FetchOptions<'_>,
) -> Result<File, AnyError> {
+ self.fetch_with_options_and_max_redirect(options, 10).await
+ }
+
+ async fn fetch_with_options_and_max_redirect(
+ &self,
+ options: FetchOptions<'_>,
+ max_redirect: usize,
+ ) -> Result<File, AnyError> {
+ let mut specifier = Cow::Borrowed(options.specifier);
+ for _ in 0..=max_redirect {
+ match self
+ .fetch_no_follow_with_options(FetchNoFollowOptions {
+ fetch_options: FetchOptions {
+ specifier: &specifier,
+ permissions: options.permissions,
+ maybe_accept: options.maybe_accept,
+ maybe_cache_setting: options.maybe_cache_setting,
+ },
+ maybe_checksum: None,
+ })
+ .await?
+ {
+ FileOrRedirect::File(file) => {
+ return Ok(file);
+ }
+ FileOrRedirect::Redirect(redirect_specifier) => {
+ specifier = Cow::Owned(redirect_specifier);
+ }
+ }
+ }
+
+ Err(custom_error("Http", "Too many redirects."))
+ }
+
+ /// Fetches without following redirects.
+ pub async fn fetch_no_follow_with_options(
+ &self,
+ options: FetchNoFollowOptions<'_>,
+ ) -> Result<FileOrRedirect, AnyError> {
+ let maybe_checksum = options.maybe_checksum;
+ let options = options.fetch_options;
let specifier = options.specifier;
- debug!("FileFetcher::fetch() - specifier: {}", specifier);
+ // note: this debug output is used by the tests
+ debug!(
+ "FileFetcher::fetch_no_follow_with_options - specifier: {}",
+ specifier
+ );
let scheme = get_validated_scheme(specifier)?;
options.permissions.check_specifier(specifier)?;
if let Some(file) = self.memory_files.get(specifier) {
- Ok(file)
+ Ok(FileOrRedirect::File(file))
} else if scheme == "file" {
// we do not in memory cache files, as this would prevent files on the
// disk changing effecting things like workers and dynamic imports.
- fetch_local(specifier)
+ fetch_local(specifier).map(FileOrRedirect::File)
} else if scheme == "data" {
- self.fetch_data_url(specifier)
+ self.fetch_data_url(specifier).map(FileOrRedirect::File)
} else if scheme == "blob" {
- self.fetch_blob_url(specifier).await
+ self
+ .fetch_blob_url(specifier)
+ .await
+ .map(FileOrRedirect::File)
} else if !self.allow_remote {
Err(custom_error(
"NoRemote",
@@ -546,13 +584,11 @@ impl FileFetcher {
))
} else {
self
- .fetch_remote(
+ .fetch_remote_no_follow(
specifier,
- options.permissions,
- 10,
- options.maybe_accept.map(String::from),
+ options.maybe_accept,
options.maybe_cache_setting.unwrap_or(&self.cache_setting),
- options.maybe_checksum,
+ maybe_checksum,
)
.await
}
@@ -605,7 +641,7 @@ struct FetchOnceArgs<'a> {
/// yields Code(ResultPayload).
/// If redirect occurs, does not follow and
/// yields Redirect(url).
-async fn fetch_once<'a>(
+async fn fetch_no_follow<'a>(
http_client: &HttpClient,
args: FetchOnceArgs<'a>,
) -> Result<FetchOnceResult, AnyError> {
@@ -746,25 +782,26 @@ mod tests {
async fn test_fetch(specifier: &ModuleSpecifier) -> (File, FileFetcher) {
let (file_fetcher, _) = setup(CacheSetting::ReloadAll, None);
let result = file_fetcher
- .fetch(specifier, PermissionsContainer::allow_all())
+ .fetch(specifier, &PermissionsContainer::allow_all())
.await;
assert!(result.is_ok());
(result.unwrap(), file_fetcher)
}
- async fn test_fetch_remote(
+ async fn test_fetch_options_remote(
specifier: &ModuleSpecifier,
) -> (File, HashMap<String, String>) {
let _http_server_guard = test_util::http_server();
let (file_fetcher, _) = setup(CacheSetting::ReloadAll, None);
let result: Result<File, AnyError> = file_fetcher
- .fetch_remote(
- specifier,
- PermissionsContainer::allow_all(),
+ .fetch_with_options_and_max_redirect(
+ FetchOptions {
+ specifier,
+ permissions: &PermissionsContainer::allow_all(),
+ maybe_accept: None,
+ maybe_cache_setting: Some(&file_fetcher.cache_setting),
+ },
1,
- None,
- &file_fetcher.cache_setting,
- None,
)
.await;
let cache_key = file_fetcher.http_cache.cache_item_key(specifier).unwrap();
@@ -788,7 +825,7 @@ mod tests {
) {
let url_str = format!("http://127.0.0.1:4545/encoding/{fixture}");
let specifier = resolve_url(&url_str).unwrap();
- let (file, headers) = test_fetch_remote(&specifier).await;
+ let (file, headers) = test_fetch_options_remote(&specifier).await;
let (media_type, maybe_charset) =
deno_graph::source::resolve_media_type_and_charset_from_headers(
&specifier,
@@ -857,7 +894,7 @@ mod tests {
file_fetcher.insert_memory_files(file.clone());
let result = file_fetcher
- .fetch(&specifier, PermissionsContainer::allow_all())
+ .fetch(&specifier, &PermissionsContainer::allow_all())
.await;
assert!(result.is_ok());
let result_file = result.unwrap();
@@ -870,7 +907,7 @@ mod tests {
let specifier = resolve_url("data:application/typescript;base64,ZXhwb3J0IGNvbnN0IGEgPSAiYSI7CgpleHBvcnQgZW51bSBBIHsKICBBLAogIEIsCiAgQywKfQo=").unwrap();
let result = file_fetcher
- .fetch(&specifier, PermissionsContainer::allow_all())
+ .fetch(&specifier, &PermissionsContainer::allow_all())
.await;
assert!(result.is_ok());
let file = result.unwrap().into_text_decoded().unwrap();
@@ -901,7 +938,7 @@ mod tests {
);
let result = file_fetcher
- .fetch(&specifier, PermissionsContainer::allow_all())
+ .fetch(&specifier, &PermissionsContainer::allow_all())
.await;
assert!(result.is_ok());
let file = result.unwrap().into_text_decoded().unwrap();
@@ -923,7 +960,7 @@ mod tests {
ModuleSpecifier::parse("http://localhost:4545/subdir/mod2.ts").unwrap();
let result = file_fetcher
- .fetch(&specifier, PermissionsContainer::allow_all())
+ .fetch(&specifier, &PermissionsContainer::allow_all())
.await;
assert!(result.is_ok());
let file = result.unwrap().into_text_decoded().unwrap();
@@ -943,7 +980,7 @@ mod tests {
.unwrap();
let result = file_fetcher_01
- .fetch(&specifier, PermissionsContainer::allow_all())
+ .fetch(&specifier, &PermissionsContainer::allow_all())
.await;
assert!(result.is_ok());
let file = result.unwrap().into_text_decoded().unwrap();
@@ -969,7 +1006,7 @@ mod tests {
.unwrap();
let result = file_fetcher_02
- .fetch(&specifier, PermissionsContainer::allow_all())
+ .fetch(&specifier, &PermissionsContainer::allow_all())
.await;
assert!(result.is_ok());
let file = result.unwrap().into_text_decoded().unwrap();
@@ -994,7 +1031,7 @@ mod tests {
None,
);
let result = file_fetcher
- .fetch(&specifier, PermissionsContainer::allow_all())
+ .fetch(&specifier, &PermissionsContainer::allow_all())
.await;
assert!(result.is_ok());
let file = result.unwrap().into_text_decoded().unwrap();
@@ -1027,7 +1064,7 @@ mod tests {
);
let result = file_fetcher
- .fetch(&specifier, PermissionsContainer::allow_all())
+ .fetch(&specifier, &PermissionsContainer::allow_all())
.await;
assert!(result.is_ok());
let cache_key =
@@ -1063,7 +1100,7 @@ mod tests {
None,
);
let result = file_fetcher
- .fetch(&specifier, PermissionsContainer::allow_all())
+ .fetch(&specifier, &PermissionsContainer::allow_all())
.await;
assert!(result.is_ok());
@@ -1102,7 +1139,7 @@ mod tests {
.unwrap();
let result = file_fetcher
- .fetch(&specifier, PermissionsContainer::allow_all())
+ .fetch(&specifier, &PermissionsContainer::allow_all())
.await;
assert!(result.is_ok());
let file = result.unwrap();
@@ -1143,7 +1180,7 @@ mod tests {
.unwrap();
let result = file_fetcher
- .fetch(&specifier, PermissionsContainer::allow_all())
+ .fetch(&specifier, &PermissionsContainer::allow_all())
.await;
assert!(result.is_ok());
let file = result.unwrap();
@@ -1203,7 +1240,7 @@ mod tests {
);
let result = file_fetcher
- .fetch(&specifier, PermissionsContainer::allow_all())
+ .fetch(&specifier, &PermissionsContainer::allow_all())
.await;
assert!(result.is_ok());
@@ -1242,7 +1279,7 @@ mod tests {
None,
);
let result = file_fetcher
- .fetch(&redirected_specifier, PermissionsContainer::allow_all())
+ .fetch(&redirected_specifier, &PermissionsContainer::allow_all())
.await;
assert!(result.is_ok());
@@ -1280,33 +1317,35 @@ mod tests {
.unwrap();
let result = file_fetcher
- .fetch_remote(
- &specifier,
- PermissionsContainer::allow_all(),
+ .fetch_with_options_and_max_redirect(
+ FetchOptions {
+ specifier: &specifier,
+ permissions: &PermissionsContainer::allow_all(),
+ maybe_accept: None,
+ maybe_cache_setting: Some(&file_fetcher.cache_setting),
+ },
2,
- None,
- &file_fetcher.cache_setting,
- None,
)
.await;
assert!(result.is_ok());
let result = file_fetcher
- .fetch_remote(
- &specifier,
- PermissionsContainer::allow_all(),
+ .fetch_with_options_and_max_redirect(
+ FetchOptions {
+ specifier: &specifier,
+ permissions: &PermissionsContainer::allow_all(),
+ maybe_accept: None,
+ maybe_cache_setting: Some(&file_fetcher.cache_setting),
+ },
1,
- None,
- &file_fetcher.cache_setting,
- None,
)
.await;
assert!(result.is_err());
- let result = file_fetcher.fetch_cached(&specifier, None, 2);
+ let result = file_fetcher.fetch_cached(&specifier, 2);
assert!(result.is_ok());
- let result = file_fetcher.fetch_cached(&specifier, None, 1);
+ let result = file_fetcher.fetch_cached(&specifier, 1);
assert!(result.is_err());
}
@@ -1323,7 +1362,7 @@ mod tests {
.unwrap();
let result = file_fetcher
- .fetch(&specifier, PermissionsContainer::allow_all())
+ .fetch(&specifier, &PermissionsContainer::allow_all())
.await;
assert!(result.is_ok());
let file = result.unwrap();
@@ -1369,7 +1408,7 @@ mod tests {
resolve_url("http://localhost:4545/run/002_hello.ts").unwrap();
let result = file_fetcher
- .fetch(&specifier, PermissionsContainer::allow_all())
+ .fetch(&specifier, &PermissionsContainer::allow_all())
.await;
assert!(result.is_err());
let err = result.unwrap_err();
@@ -1402,7 +1441,7 @@ mod tests {
resolve_url("http://localhost:4545/run/002_hello.ts").unwrap();
let result = file_fetcher_01
- .fetch(&specifier, PermissionsContainer::allow_all())
+ .fetch(&specifier, &PermissionsContainer::allow_all())
.await;
assert!(result.is_err());
let err = result.unwrap_err();
@@ -1410,12 +1449,12 @@ mod tests {
assert_eq!(get_custom_error_class(&err), Some("NotCached"));
let result = file_fetcher_02
- .fetch(&specifier, PermissionsContainer::allow_all())
+ .fetch(&specifier, &PermissionsContainer::allow_all())
.await;
assert!(result.is_ok());
let result = file_fetcher_01
- .fetch(&specifier, PermissionsContainer::allow_all())
+ .fetch(&specifier, &PermissionsContainer::allow_all())
.await;
assert!(result.is_ok());
}
@@ -1427,7 +1466,7 @@ mod tests {
let specifier = ModuleSpecifier::from_file_path(&fixture_path).unwrap();
fs::write(fixture_path.clone(), r#"console.log("hello deno");"#).unwrap();
let result = file_fetcher
- .fetch(&specifier, PermissionsContainer::allow_all())
+ .fetch(&specifier, &PermissionsContainer::allow_all())
.await;
assert!(result.is_ok());
let file = result.unwrap().into_text_decoded().unwrap();
@@ -1435,7 +1474,7 @@ mod tests {
fs::write(fixture_path, r#"console.log("goodbye deno");"#).unwrap();
let result = file_fetcher
- .fetch(&specifier, PermissionsContainer::allow_all())
+ .fetch(&specifier, &PermissionsContainer::allow_all())
.await;
assert!(result.is_ok());
let file = result.unwrap().into_text_decoded().unwrap();
@@ -1451,7 +1490,7 @@ mod tests {
let specifier =
ModuleSpecifier::parse("http://localhost:4545/dynamic").unwrap();
let result = file_fetcher
- .fetch(&specifier, PermissionsContainer::allow_all())
+ .fetch(&specifier, &PermissionsContainer::allow_all())
.await;
assert!(result.is_ok());
let file = result.unwrap();
@@ -1460,7 +1499,7 @@ mod tests {
let (file_fetcher, _) =
setup(CacheSetting::RespectHeaders, Some(temp_dir.clone()));
let result = file_fetcher
- .fetch(&specifier, PermissionsContainer::allow_all())
+ .fetch(&specifier, &PermissionsContainer::allow_all())
.await;
assert!(result.is_ok());
let file = result.unwrap();
@@ -1478,7 +1517,7 @@ mod tests {
let specifier =
ModuleSpecifier::parse("http://localhost:4545/dynamic_cache").unwrap();
let result = file_fetcher
- .fetch(&specifier, PermissionsContainer::allow_all())
+ .fetch(&specifier, &PermissionsContainer::allow_all())
.await;
assert!(result.is_ok());
let file = result.unwrap();
@@ -1487,7 +1526,7 @@ mod tests {
let (file_fetcher, _) =
setup(CacheSetting::RespectHeaders, Some(temp_dir.clone()));
let result = file_fetcher
- .fetch(&specifier, PermissionsContainer::allow_all())
+ .fetch(&specifier, &PermissionsContainer::allow_all())
.await;
assert!(result.is_ok());
let file = result.unwrap();
@@ -1551,7 +1590,7 @@ mod tests {
// Relies on external http server. See target/debug/test_server
let url = Url::parse("http://127.0.0.1:4545/assets/fixture.json").unwrap();
let client = create_test_client();
- let result = fetch_once(
+ let result = fetch_no_follow(
&client,
FetchOnceArgs {
url,
@@ -1579,7 +1618,7 @@ mod tests {
let url = Url::parse("http://127.0.0.1:4545/run/import_compression/gziped")
.unwrap();
let client = create_test_client();
- let result = fetch_once(
+ let result = fetch_no_follow(
&client,
FetchOnceArgs {
url,
@@ -1608,7 +1647,7 @@ mod tests {
let _http_server_guard = test_util::http_server();
let url = Url::parse("http://127.0.0.1:4545/etag_script.ts").unwrap();
let client = create_test_client();
- let result = fetch_once(
+ let result = fetch_no_follow(
&client,
FetchOnceArgs {
url: url.clone(),
@@ -1631,7 +1670,7 @@ mod tests {
panic!();
}
- let res = fetch_once(
+ let res = fetch_no_follow(
&client,
FetchOnceArgs {
url,
@@ -1652,7 +1691,7 @@ mod tests {
let url = Url::parse("http://127.0.0.1:4545/run/import_compression/brotli")
.unwrap();
let client = create_test_client();
- let result = fetch_once(
+ let result = fetch_no_follow(
&client,
FetchOnceArgs {
url,
@@ -1683,7 +1722,7 @@ mod tests {
// Relies on external http server. See target/debug/test_server
let url = Url::parse("http://127.0.0.1:4545/echo_accept").unwrap();
let client = create_test_client();
- let result = fetch_once(
+ let result = fetch_no_follow(
&client,
FetchOnceArgs {
url,
@@ -1702,7 +1741,7 @@ mod tests {
}
#[tokio::test]
- async fn test_fetch_once_with_redirect() {
+ async fn test_fetch_no_follow_with_redirect() {
let _http_server_guard = test_util::http_server();
// Relies on external http server. See target/debug/test_server
let url = Url::parse("http://127.0.0.1:4546/assets/fixture.json").unwrap();
@@ -1710,7 +1749,7 @@ mod tests {
let target_url =
Url::parse("http://localhost:4545/assets/fixture.json").unwrap();
let client = create_test_client();
- let result = fetch_once(
+ let result = fetch_no_follow(
&client,
FetchOnceArgs {
url,
@@ -1747,7 +1786,7 @@ mod tests {
)
.unwrap(),
);
- let result = fetch_once(
+ let result = fetch_no_follow(
&client,
FetchOnceArgs {
url,
@@ -1796,7 +1835,7 @@ mod tests {
.unwrap(),
);
- let result = fetch_once(
+ let result = fetch_no_follow(
&client,
FetchOnceArgs {
url,
@@ -1860,7 +1899,7 @@ mod tests {
.unwrap(),
);
- let result = fetch_once(
+ let result = fetch_no_follow(
&client,
FetchOnceArgs {
url,
@@ -1915,7 +1954,7 @@ mod tests {
)
.unwrap(),
);
- let result = fetch_once(
+ let result = fetch_no_follow(
&client,
FetchOnceArgs {
url,
@@ -1958,7 +1997,7 @@ mod tests {
)
.unwrap(),
);
- let result = fetch_once(
+ let result = fetch_no_follow(
&client,
FetchOnceArgs {
url: url.clone(),
@@ -1982,7 +2021,7 @@ mod tests {
panic!();
}
- let res = fetch_once(
+ let res = fetch_no_follow(
&client,
FetchOnceArgs {
url,
@@ -2018,7 +2057,7 @@ mod tests {
)
.unwrap(),
);
- let result = fetch_once(
+ let result = fetch_no_follow(
&client,
FetchOnceArgs {
url,
@@ -2049,7 +2088,7 @@ mod tests {
let url_str = "http://127.0.0.1:4545/bad_redirect";
let url = Url::parse(url_str).unwrap();
let client = create_test_client();
- let result = fetch_once(
+ let result = fetch_no_follow(
&client,
FetchOnceArgs {
url,
@@ -2072,7 +2111,7 @@ mod tests {
let url_str = "http://127.0.0.1:4545/server_error";
let url = Url::parse(url_str).unwrap();
let client = create_test_client();
- let result = fetch_once(
+ let result = fetch_no_follow(
&client,
FetchOnceArgs {
url,
@@ -2097,7 +2136,7 @@ mod tests {
let url_str = "http://127.0.0.1:9999/";
let url = Url::parse(url_str).unwrap();
let client = create_test_client();
- let result = fetch_once(
+ let result = fetch_no_follow(
&client,
FetchOnceArgs {
url,
diff --git a/cli/graph_util.rs b/cli/graph_util.rs
index 8f0790605..8d78da3ed 100644
--- a/cli/graph_util.rs
+++ b/cli/graph_util.rs
@@ -451,17 +451,17 @@ impl ModuleGraphBuilder {
options.roots,
loader.as_mut_loader(),
deno_graph::BuildOptions {
+ imports: maybe_imports,
is_dynamic: options.is_dynamic,
- jsr_url_provider: &CliJsrUrlProvider,
passthrough_jsr_specifiers: false,
+ workspace_members: &workspace_members,
executor: Default::default(),
- imports: maybe_imports,
- resolver: Some(graph_resolver),
file_system: &DenoGraphFsAdapter(self.fs.as_ref()),
+ jsr_url_provider: &CliJsrUrlProvider,
npm_resolver: Some(graph_npm_resolver),
module_analyzer: &analyzer,
reporter: maybe_file_watcher_reporter,
- workspace_members: &workspace_members,
+ resolver: Some(graph_resolver),
},
)
.await
diff --git a/cli/jsr.rs b/cli/jsr.rs
index 1e194da71..9a929982a 100644
--- a/cli/jsr.rs
+++ b/cli/jsr.rs
@@ -234,7 +234,7 @@ impl JsrFetchResolver {
let meta_url = jsr_url().join(&format!("{}/meta.json", name)).ok()?;
let file = self
.file_fetcher
- .fetch(&meta_url, PermissionsContainer::allow_all())
+ .fetch(&meta_url, &PermissionsContainer::allow_all())
.await
.ok()?;
serde_json::from_slice::<JsrPackageInfo>(&file.source).ok()
@@ -257,7 +257,7 @@ impl JsrFetchResolver {
.ok()?;
let file = self
.file_fetcher
- .fetch(&meta_url, PermissionsContainer::allow_all())
+ .fetch(&meta_url, &PermissionsContainer::allow_all())
.await
.ok()?;
partial_jsr_package_version_info_from_slice(&file.source).ok()
diff --git a/cli/lsp/config.rs b/cli/lsp/config.rs
index 15bd93ced..ec736f365 100644
--- a/cli/lsp/config.rs
+++ b/cli/lsp/config.rs
@@ -1393,7 +1393,7 @@ impl ConfigData {
if import_map_value.is_none() {
if let Some(file_fetcher) = file_fetcher {
let fetch_result = file_fetcher
- .fetch(specifier, PermissionsContainer::allow_all())
+ .fetch(specifier, &PermissionsContainer::allow_all())
.await;
let value_result = fetch_result.and_then(|f| {
serde_json::from_slice::<Value>(&f.source).map_err(|e| e.into())
diff --git a/cli/lsp/jsr.rs b/cli/lsp/jsr.rs
index a9c35aad6..ca0dae958 100644
--- a/cli/lsp/jsr.rs
+++ b/cli/lsp/jsr.rs
@@ -51,7 +51,7 @@ impl PackageSearchApi for CliJsrSearchApi {
search_url.query_pairs_mut().append_pair("query", query);
let file = self
.file_fetcher
- .fetch(&search_url, PermissionsContainer::allow_all())
+ .fetch(&search_url, &PermissionsContainer::allow_all())
.await?
.into_text_decoded()?;
let names = Arc::new(parse_jsr_search_response(&file.source)?);
diff --git a/cli/lsp/npm.rs b/cli/lsp/npm.rs
index 33cf48675..830aaed95 100644
--- a/cli/lsp/npm.rs
+++ b/cli/lsp/npm.rs
@@ -48,7 +48,7 @@ impl PackageSearchApi for CliNpmSearchApi {
.append_pair("text", &format!("{} boost-exact:false", query));
let file = self
.file_fetcher
- .fetch(&search_url, PermissionsContainer::allow_all())
+ .fetch(&search_url, &PermissionsContainer::allow_all())
.await?
.into_text_decoded()?;
let names = Arc::new(parse_npm_search_response(&file.source)?);
diff --git a/cli/lsp/registries.rs b/cli/lsp/registries.rs
index b0eeb9df0..a145322b5 100644
--- a/cli/lsp/registries.rs
+++ b/cli/lsp/registries.rs
@@ -512,10 +512,9 @@ impl ModuleRegistry {
.file_fetcher
.fetch_with_options(FetchOptions {
specifier,
- permissions: PermissionsContainer::allow_all(),
+ permissions: &PermissionsContainer::allow_all(),
maybe_accept: Some("application/vnd.deno.reg.v2+json, application/vnd.deno.reg.v1+json;q=0.9, application/json;q=0.8"),
maybe_cache_setting: None,
- maybe_checksum: None,
})
.await;
// if there is an error fetching, we will cache an empty file, so that
@@ -609,7 +608,7 @@ impl ModuleRegistry {
.ok()?;
let file = self
.file_fetcher
- .fetch(&endpoint, PermissionsContainer::allow_all())
+ .fetch(&endpoint, &PermissionsContainer::allow_all())
.await
.ok()?
.into_text_decoded()
@@ -975,7 +974,7 @@ impl ModuleRegistry {
let specifier = Url::parse(url).ok()?;
let file = self
.file_fetcher
- .fetch(&specifier, PermissionsContainer::allow_all())
+ .fetch(&specifier, &PermissionsContainer::allow_all())
.await
.ok()?
.into_text_decoded()
@@ -1034,7 +1033,7 @@ impl ModuleRegistry {
let specifier = ModuleSpecifier::parse(url).ok()?;
let file = self
.file_fetcher
- .fetch(&specifier, PermissionsContainer::allow_all())
+ .fetch(&specifier, &PermissionsContainer::allow_all())
.await
.map_err(|err| {
error!(
@@ -1072,7 +1071,7 @@ impl ModuleRegistry {
.ok()?;
let file = self
.file_fetcher
- .fetch(&specifier, PermissionsContainer::allow_all())
+ .fetch(&specifier, &PermissionsContainer::allow_all())
.await
.map_err(|err| {
error!(
diff --git a/cli/npm/mod.rs b/cli/npm/mod.rs
index c17918c67..8de803ce4 100644
--- a/cli/npm/mod.rs
+++ b/cli/npm/mod.rs
@@ -142,7 +142,7 @@ impl NpmFetchResolver {
let info_url = npm_registry_url().join(name).ok()?;
let file = self
.file_fetcher
- .fetch(&info_url, PermissionsContainer::allow_all())
+ .fetch(&info_url, &PermissionsContainer::allow_all())
.await
.ok()?;
serde_json::from_slice::<NpmPackageInfo>(&file.source).ok()
diff --git a/cli/tools/coverage/mod.rs b/cli/tools/coverage/mod.rs
index 763022c1f..47841b037 100644
--- a/cli/tools/coverage/mod.rs
+++ b/cli/tools/coverage/mod.rs
@@ -529,7 +529,7 @@ pub async fn cover_files(
file_fetcher.get_source(&module_specifier)
} else {
file_fetcher
- .fetch_cached(&module_specifier, None, 10)
+ .fetch_cached(&module_specifier, 10)
.with_context(|| {
format!("Failed to fetch \"{module_specifier}\" from cache.")
})?
diff --git a/cli/tools/doc.rs b/cli/tools/doc.rs
index 68f7663f4..1ff5623cc 100644
--- a/cli/tools/doc.rs
+++ b/cli/tools/doc.rs
@@ -54,17 +54,17 @@ async fn generate_doc_nodes_for_builtin_types(
vec![source_file_specifier.clone()],
&loader,
deno_graph::BuildOptions {
- module_analyzer: analyzer,
- file_system: &NullFileSystem,
- is_dynamic: false,
imports: Vec::new(),
+ is_dynamic: false,
+ passthrough_jsr_specifiers: false,
+ workspace_members: &[],
executor: Default::default(),
+ file_system: &NullFileSystem,
jsr_url_provider: Default::default(),
- passthrough_jsr_specifiers: false,
+ module_analyzer: analyzer,
npm_resolver: None,
reporter: None,
resolver: None,
- workspace_members: &[],
},
)
.await;
diff --git a/cli/tools/repl/mod.rs b/cli/tools/repl/mod.rs
index 80ab2a2d2..03b8e512e 100644
--- a/cli/tools/repl/mod.rs
+++ b/cli/tools/repl/mod.rs
@@ -145,7 +145,7 @@ async fn read_eval_file(
deno_core::resolve_url_or_path(eval_file, cli_options.initial_cwd())?;
let file = file_fetcher
- .fetch(&specifier, PermissionsContainer::allow_all())
+ .fetch(&specifier, &PermissionsContainer::allow_all())
.await?;
Ok(file.into_text_decoded()?.source)
diff --git a/cli/tools/test/mod.rs b/cli/tools/test/mod.rs
index 390a60762..013d8c084 100644
--- a/cli/tools/test/mod.rs
+++ b/cli/tools/test/mod.rs
@@ -1277,7 +1277,7 @@ async fn fetch_inline_files(
for specifier in specifiers {
let fetch_permissions = PermissionsContainer::allow_all();
let file = file_fetcher
- .fetch(&specifier, fetch_permissions)
+ .fetch(&specifier, &fetch_permissions)
.await?
.into_text_decoded()?;
@@ -1688,7 +1688,7 @@ async fn fetch_specifiers_with_test_mode(
for (specifier, mode) in &mut specifiers_with_mode {
let file = file_fetcher
- .fetch(specifier, PermissionsContainer::allow_all())
+ .fetch(specifier, &PermissionsContainer::allow_all())
.await?;
let (media_type, _) = file.resolve_media_type_and_charset();
diff --git a/cli/tools/vendor/test.rs b/cli/tools/vendor/test.rs
index 21efc0d8f..b4993565d 100644
--- a/cli/tools/vendor/test.rs
+++ b/cli/tools/vendor/test.rs
@@ -116,7 +116,13 @@ impl Loader for TestLoader {
specifier: &ModuleSpecifier,
_options: deno_graph::source::LoadOptions,
) -> LoadFuture {
- let specifier = self.redirects.get(specifier).unwrap_or(specifier);
+ if let Some(redirect) = self.redirects.get(specifier) {
+ return Box::pin(futures::future::ready(Ok(Some(
+ LoadResponse::Redirect {
+ specifier: redirect.clone(),
+ },
+ ))));
+ }
let result = self.files.get(specifier).map(|result| match result {
Ok(result) => Ok(LoadResponse::Module {
specifier: specifier.clone(),
diff --git a/tests/integration/bench_tests.rs b/tests/integration/bench_tests.rs
index e0d3f8724..3306a0f96 100644
--- a/tests/integration/bench_tests.rs
+++ b/tests/integration/bench_tests.rs
@@ -280,7 +280,7 @@ fn conditionally_loads_type_graph() {
.new_command()
.args("bench --reload -L debug run/type_directives_js_main.js")
.run();
- output.assert_matches_text("[WILDCARD] - FileFetcher::fetch() - specifier: file:///[WILDCARD]/subdir/type_reference.d.ts[WILDCARD]");
+ output.assert_matches_text("[WILDCARD] - FileFetcher::fetch_no_follow_with_options - specifier: file:///[WILDCARD]/subdir/type_reference.d.ts[WILDCARD]");
let output = context
.new_command()
.args("bench --reload -L debug --no-check run/type_directives_js_main.js")
diff --git a/tests/integration/cache_tests.rs b/tests/integration/cache_tests.rs
index 988cbc996..ff206c654 100644
--- a/tests/integration/cache_tests.rs
+++ b/tests/integration/cache_tests.rs
@@ -177,5 +177,5 @@ fn loads_type_graph() {
.new_command()
.args("cache --reload -L debug run/type_directives_js_main.js")
.run();
- output.assert_matches_text("[WILDCARD] - FileFetcher::fetch() - specifier: file:///[WILDCARD]/subdir/type_reference.d.ts[WILDCARD]");
+ output.assert_matches_text("[WILDCARD] - FileFetcher::fetch_no_follow_with_options - specifier: file:///[WILDCARD]/subdir/type_reference.d.ts[WILDCARD]");
}
diff --git a/tests/integration/run_tests.rs b/tests/integration/run_tests.rs
index e477a98d6..7b0bc78ed 100644
--- a/tests/integration/run_tests.rs
+++ b/tests/integration/run_tests.rs
@@ -1686,7 +1686,7 @@ fn type_directives_js_main() {
.new_command()
.args("run --reload -L debug --check run/type_directives_js_main.js")
.run();
- output.assert_matches_text("[WILDCARD] - FileFetcher::fetch() - specifier: file:///[WILDCARD]/subdir/type_reference.d.ts[WILDCARD]");
+ output.assert_matches_text("[WILDCARD] - FileFetcher::fetch_no_follow_with_options - specifier: file:///[WILDCARD]/subdir/type_reference.d.ts[WILDCARD]");
let output = context
.new_command()
.args("run --reload -L debug run/type_directives_js_main.js")
diff --git a/tests/integration/test_tests.rs b/tests/integration/test_tests.rs
index 33abdf22c..2bf2b3109 100644
--- a/tests/integration/test_tests.rs
+++ b/tests/integration/test_tests.rs
@@ -668,7 +668,7 @@ fn conditionally_loads_type_graph() {
.new_command()
.args("test --reload -L debug run/type_directives_js_main.js")
.run();
- output.assert_matches_text("[WILDCARD] - FileFetcher::fetch() - specifier: file:///[WILDCARD]/subdir/type_reference.d.ts[WILDCARD]");
+ output.assert_matches_text("[WILDCARD] - FileFetcher::fetch_no_follow_with_options - specifier: file:///[WILDCARD]/subdir/type_reference.d.ts[WILDCARD]");
let output = context
.new_command()
.args("test --reload -L debug --no-check run/type_directives_js_main.js")
diff --git a/tests/specs/info/multiple_redirects/__test__.jsonc b/tests/specs/info/multiple_redirects/__test__.jsonc
new file mode 100644
index 000000000..0e1808e0a
--- /dev/null
+++ b/tests/specs/info/multiple_redirects/__test__.jsonc
@@ -0,0 +1,4 @@
+{
+ "args": "info --json main.ts",
+ "output": "main.out"
+}
diff --git a/tests/specs/info/multiple_redirects/main.out b/tests/specs/info/multiple_redirects/main.out
new file mode 100644
index 000000000..bd18c1728
--- /dev/null
+++ b/tests/specs/info/multiple_redirects/main.out
@@ -0,0 +1,51 @@
+Download http://localhost:4548/subdir/redirects/redirect1.js
+Download http://localhost:4546/subdir/redirects/redirect1.js
+Download http://localhost:4545/subdir/redirects/redirect1.js
+{
+ "roots": [
+ "file:///[WILDLINE]/multiple_redirects/main.ts"
+ ],
+ "modules": [
+ {
+ "kind": "esm",
+ "dependencies": [
+ {
+ "specifier": "http://localhost:4548/subdir/redirects/redirect1.js",
+ "code": {
+ "specifier": "http://localhost:4548/subdir/redirects/redirect1.js",
+ "span": {
+ "start": {
+ "line": 0,
+ "character": 22
+ },
+ "end": {
+ "line": 0,
+ "character": 75
+ }
+ }
+ }
+ }
+ ],
+ "local": "[WILDLINE]main.ts",
+ "emit": null,
+ "map": null,
+ "size": 97,
+ "mediaType": "TypeScript",
+ "specifier": "file:///[WILDLINE]/multiple_redirects/main.ts"
+ },
+ {
+ "kind": "esm",
+ "local": "[WILDLINE]",
+ "emit": null,
+ "map": null,
+ "size": 27,
+ "mediaType": "JavaScript",
+ "specifier": "http://localhost:4545/subdir/redirects/redirect1.js"
+ }
+ ],
+ "redirects": {
+ "http://localhost:4546/subdir/redirects/redirect1.js": "http://localhost:4545/subdir/redirects/redirect1.js",
+ "http://localhost:4548/subdir/redirects/redirect1.js": "http://localhost:4546/subdir/redirects/redirect1.js"
+ },
+ "npmPackages": {}
+}
diff --git a/tests/specs/info/multiple_redirects/main.ts b/tests/specs/info/multiple_redirects/main.ts
new file mode 100644
index 000000000..99287b39a
--- /dev/null
+++ b/tests/specs/info/multiple_redirects/main.ts
@@ -0,0 +1,2 @@
+import { value } from "http://localhost:4548/subdir/redirects/redirect1.js";
+console.log(value);