summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Sherret <dsherret@users.noreply.github.com>2024-02-24 00:21:09 -0500
committerGitHub <noreply@github.com>2024-02-24 00:21:09 -0500
commit6567dc94a901aaae1b4e5b8e84d48bc72d46ee2e (patch)
treeff3674957c66c40e9d4cc5e1fc1c04b353bf6a46
parent76e8e02bba75f23097d28cec13829c2f5cfa4a25 (diff)
fix(lsp): import map expansion (#22553)
-rw-r--r--Cargo.lock26
-rw-r--r--cli/Cargo.toml12
-rw-r--r--cli/args/import_map.rs66
-rw-r--r--cli/args/mod.rs271
-rw-r--r--cli/factory.rs5
-rw-r--r--cli/lsp/config.rs6
-rw-r--r--cli/lsp/documents.rs2
-rw-r--r--cli/lsp/language_server.rs148
-rw-r--r--cli/tools/bundle.rs2
-rw-r--r--cli/tools/vendor/mod.rs19
-rw-r--r--cli/util/import_map.rs12
-rw-r--r--tests/testdata/run/workspaces/basic/main.out3
12 files changed, 201 insertions, 371 deletions
diff --git a/Cargo.lock b/Cargo.lock
index d72d3fc8c..21483e927 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1229,12 +1229,13 @@ dependencies = [
[[package]]
name = "deno_config"
-version = "0.10.0"
+version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ba7641dd37ffcc1aeb06dff206a3bdd9e9a52f177f5edd43b734933174c38067"
+checksum = "bc52f2cedd7f47b50fb67191f9cb1c5633b47017fb7da5b586278763110879e5"
dependencies = [
"anyhow",
"glob",
+ "import_map",
"indexmap",
"jsonc-parser",
"log",
@@ -1338,9 +1339,9 @@ dependencies = [
[[package]]
name = "deno_doc"
-version = "0.110.1"
+version = "0.113.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "48c55c586e5bbcb6571ec57da57ebcae27f9ad5e8d218794300f444fad53e913"
+checksum = "394381b3a23173f7bcb309e49ee29f33b8815495ca61fbdc8cb030439dc9d6ed"
dependencies = [
"ammonia",
"anyhow",
@@ -1362,9 +1363,9 @@ dependencies = [
[[package]]
name = "deno_emit"
-version = "0.38.1"
+version = "0.38.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4b115e4df6b17e49bb6732a30725e70c28c5704f2b4d4f9a8547e0d532a1484b"
+checksum = "23593513889bc5d607f9750c858f9cc113f47cb045d87eea7c6cd6605639915c"
dependencies = [
"anyhow",
"base64",
@@ -1433,9 +1434,9 @@ dependencies = [
[[package]]
name = "deno_graph"
-version = "0.69.0"
+version = "0.69.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "98448adebbc12b8b1fc0eb42ce06cf3830dff0dcb48f3276039360b90405612f"
+checksum = "73c83b0538ee10854dcf0f24aa05ec79f62e308b358cefd65d30f9d0959a9dc3"
dependencies = [
"anyhow",
"async-trait",
@@ -2463,9 +2464,9 @@ dependencies = [
[[package]]
name = "eszip"
-version = "0.64.1"
+version = "0.64.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4d0670761c56597adcc00a65e42ac04d1f4b0ffa3f577cd7f386e85f7e4a1eb5"
+checksum = "97374d7fd863b2b44ca217e739a1eb83361d0e5e2358d201145dac1aa3fa6a21"
dependencies = [
"anyhow",
"base64",
@@ -3385,12 +3386,13 @@ dependencies = [
[[package]]
name = "import_map"
-version = "0.18.3"
+version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4bad4ef70a3e0f2ee403925d77d1e7b74e471b57ea75593f332aac31b57958b4"
+checksum = "696717335b077e26921a60be7b7bdc15d1246074f1ac79d9e8560792535f7d07"
dependencies = [
"indexmap",
"log",
+ "percent-encoding",
"serde",
"serde_json",
"url",
diff --git a/cli/Cargo.toml b/cli/Cargo.toml
index ad1e024b7..1097d8d98 100644
--- a/cli/Cargo.toml
+++ b/cli/Cargo.toml
@@ -64,11 +64,11 @@ winres.workspace = true
[dependencies]
deno_ast = { workspace = true, features = ["bundler", "cjs", "codegen", "proposal", "react", "sourcemap", "transforms", "typescript", "view", "visit"] }
deno_cache_dir = { workspace = true }
-deno_config = "=0.10.0"
+deno_config = "=0.11.0"
deno_core = { workspace = true, features = ["include_js_files_for_snapshotting"] }
-deno_doc = { version = "=0.110.1", features = ["html"] }
-deno_emit = "=0.38.1"
-deno_graph = { version = "=0.69.0", features = ["tokio_executor"] }
+deno_doc = { version = "=0.113.1", features = ["html"] }
+deno_emit = "=0.38.2"
+deno_graph = { version = "=0.69.4", features = ["tokio_executor"] }
deno_lint = { version = "=0.57.1", features = ["docs"] }
deno_lockfile.workspace = true
deno_npm = "=0.17.0"
@@ -76,7 +76,7 @@ deno_runtime = { workspace = true, features = ["include_js_files_for_snapshottin
deno_semver = "=0.5.4"
deno_task_shell = "=0.14.3"
deno_terminal.workspace = true
-eszip = "=0.64.1"
+eszip = "=0.64.2"
napi_sym.workspace = true
async-trait.workspace = true
@@ -107,7 +107,7 @@ fs3.workspace = true
glob = "0.3.1"
hex.workspace = true
ignore = "0.4"
-import_map = { version = "=0.18.3", features = ["ext"] }
+import_map = { version = "=0.19.0", features = ["ext"] }
indexmap.workspace = true
jsonc-parser = { version = "=0.23.0", features = ["serde"] }
lazy-regex.workspace = true
diff --git a/cli/args/import_map.rs b/cli/args/import_map.rs
index da4f0eb85..517c3bff6 100644
--- a/cli/args/import_map.rs
+++ b/cli/args/import_map.rs
@@ -1,5 +1,6 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
+use deno_core::anyhow::Context;
use deno_core::error::AnyError;
use deno_core::serde_json;
use deno_core::url::Url;
@@ -11,35 +12,66 @@ use log::warn;
use super::ConfigFile;
use crate::file_fetcher::FileFetcher;
-pub async fn resolve_import_map_from_specifier(
- specifier: &Url,
+pub async fn resolve_import_map(
+ specified_specifier: Option<&Url>,
maybe_config_file: Option<&ConfigFile>,
file_fetcher: &FileFetcher,
+) -> Result<Option<ImportMap>, AnyError> {
+ if let Some(specifier) = specified_specifier {
+ resolve_import_map_from_specifier(specifier.clone(), file_fetcher)
+ .await
+ .with_context(|| format!("Unable to load '{}' import map", specifier))
+ .map(Some)
+ } else if let Some(config_file) = maybe_config_file {
+ let maybe_url_and_value = config_file
+ .to_import_map_value(|specifier| {
+ let specifier = specifier.clone();
+ async move {
+ let file = file_fetcher
+ .fetch(&specifier, PermissionsContainer::allow_all())
+ .await?
+ .into_text_decoded()?;
+ Ok(file.source.to_string())
+ }
+ })
+ .await
+ .with_context(|| {
+ format!(
+ "Unable to resolve import map in '{}'",
+ config_file.specifier
+ )
+ })?;
+ match maybe_url_and_value {
+ Some((url, value)) => {
+ import_map_from_value(url.into_owned(), value).map(Some)
+ }
+ None => Ok(None),
+ }
+ } else {
+ Ok(None)
+ }
+}
+
+async fn resolve_import_map_from_specifier(
+ specifier: Url,
+ file_fetcher: &FileFetcher,
) -> Result<ImportMap, AnyError> {
let value: serde_json::Value = if specifier.scheme() == "data" {
let data_url_text =
- deno_graph::source::RawDataUrl::parse(specifier)?.decode()?;
+ deno_graph::source::RawDataUrl::parse(&specifier)?.decode()?;
serde_json::from_str(&data_url_text)?
} else {
- let import_map_config = maybe_config_file
- .as_ref()
- .filter(|c| c.specifier == *specifier);
- match import_map_config {
- Some(config) => config.to_import_map_value(),
- None => {
- let file = file_fetcher
- .fetch(specifier, PermissionsContainer::allow_all())
- .await?
- .into_text_decoded()?;
- serde_json::from_str(&file.source)?
- }
- }
+ let file = file_fetcher
+ .fetch(&specifier, PermissionsContainer::allow_all())
+ .await?
+ .into_text_decoded()?;
+ serde_json::from_str(&file.source)?
};
import_map_from_value(specifier, value)
}
pub fn import_map_from_value(
- specifier: &Url,
+ specifier: Url,
json_value: serde_json::Value,
) -> Result<ImportMap, AnyError> {
debug_assert!(
diff --git a/cli/args/mod.rs b/cli/args/mod.rs
index c5044fe65..9aa819a30 100644
--- a/cli/args/mod.rs
+++ b/cli/args/mod.rs
@@ -6,7 +6,7 @@ mod import_map;
mod lockfile;
pub mod package_json;
-pub use self::import_map::resolve_import_map_from_specifier;
+pub use self::import_map::resolve_import_map;
use self::package_json::PackageJsonDeps;
use ::import_map::ImportMap;
use deno_core::resolve_url_or_path;
@@ -34,11 +34,9 @@ pub use lockfile::LockfileError;
pub use package_json::PackageJsonDepsProvider;
use deno_ast::ModuleSpecifier;
-use deno_core::anyhow::anyhow;
use deno_core::anyhow::bail;
use deno_core::anyhow::Context;
use deno_core::error::AnyError;
-use deno_core::normalize_path;
use deno_core::parking_lot::Mutex;
use deno_core::serde_json;
use deno_core::url::Url;
@@ -875,10 +873,11 @@ impl CliOptions {
}
}
- /// Based on an optional command line import map path and an optional
- /// configuration file, return a resolved module specifier to an import map
- /// and a boolean indicating if unknown keys should not result in diagnostics.
- pub fn resolve_import_map_specifier(
+ /// Resolve the specifier for a specified import map.
+ ///
+ /// This will NOT include the config file if it
+ /// happens to be an import map.
+ pub fn resolve_specified_import_map_specifier(
&self,
) -> Result<Option<ModuleSpecifier>, AnyError> {
match self.overrides.import_map_specifier.clone() {
@@ -896,94 +895,55 @@ impl CliOptions {
file_fetcher: &FileFetcher,
) -> Result<Option<ImportMap>, AnyError> {
if let Some(workspace_config) = self.maybe_workspace_config.as_ref() {
+ let root_config_file = self.maybe_config_file.as_ref().unwrap();
let base_import_map_config = ::import_map::ext::ImportMapConfig {
- base_url: self.maybe_config_file.as_ref().unwrap().specifier.clone(),
- import_map_value: workspace_config.base_import_map_value.clone(),
+ base_url: root_config_file.specifier.clone(),
+ import_map_value: root_config_file.to_import_map_value_from_imports(),
};
let children_configs = workspace_config
.members
.iter()
- .map(|member| {
- let mut import_map_value = member.config_file.to_import_map_value();
-
- let expanded_import_map_value = ::import_map::ext::expand_imports(
- ::import_map::ext::ImportMapConfig {
- base_url: member.config_file.specifier.clone(),
- import_map_value: import_map_value.clone(),
- },
- );
-
- import_map_value
- .as_object_mut()
- .unwrap()
- .insert("imports".to_string(), expanded_import_map_value);
- ::import_map::ext::ImportMapConfig {
- base_url: member.config_file.specifier.clone(),
- import_map_value,
- }
+ .map(|member| ::import_map::ext::ImportMapConfig {
+ base_url: member.config_file.specifier.clone(),
+ import_map_value: member
+ .config_file
+ .to_import_map_value_from_imports(),
})
.collect();
- let maybe_import_map = ::import_map::ext::create_synthetic_import_map(
- base_import_map_config,
- children_configs,
- );
- if let Some((_import_map_url, import_map)) = maybe_import_map {
- log::debug!(
- "Workspace config generated this import map {}",
- serde_json::to_string_pretty(&import_map).unwrap()
+ let (import_map_url, import_map) =
+ ::import_map::ext::create_synthetic_import_map(
+ base_import_map_config,
+ children_configs,
);
- let maybe_import_map_result = import_map::import_map_from_value(
- // TODO(bartlomieju): maybe should be stored on the workspace config?
- &self.maybe_config_file.as_ref().unwrap().specifier,
- import_map,
- )
- .map(Some);
-
- return match maybe_import_map_result {
- Ok(maybe_import_map) => {
- if let Some(mut import_map) = maybe_import_map {
- import_map.ext_expand_imports();
- Ok(Some(import_map))
- } else {
- Ok(None)
- }
- }
- Err(err) => Err(err),
- };
- }
+ log::debug!(
+ "Workspace config generated this import map {}",
+ serde_json::to_string_pretty(&import_map).unwrap()
+ );
+ let maybe_import_map_result =
+ import_map::import_map_from_value(import_map_url, import_map).map(Some);
+
+ return maybe_import_map_result;
}
- let import_map_specifier = match self.resolve_import_map_specifier()? {
- Some(specifier) => specifier,
- None => return Ok(None),
- };
+ if self
+ .overrides
+ .import_map_specifier
+ .as_ref()
+ .map(|s| s.is_none())
+ == Some(true)
+ {
+ // overrode to not use an import map
+ return Ok(None);
+ }
- let maybe_import_map_result = resolve_import_map_from_specifier(
- &import_map_specifier,
+ let import_map_specifier = self.resolve_specified_import_map_specifier()?;
+ resolve_import_map(
+ import_map_specifier.as_ref(),
self.maybe_config_file().as_ref(),
file_fetcher,
)
.await
- .with_context(|| {
- format!("Unable to load '{import_map_specifier}' import map")
- })
- .map(Some);
-
- match maybe_import_map_result {
- Ok(maybe_import_map) => {
- if let Some(mut import_map) = maybe_import_map {
- let url = import_map.base_url().as_str();
- if url.ends_with("deno.json") || url.ends_with("deno.jsonc") {
- import_map.ext_expand_imports();
- }
- Ok(Some(import_map))
- } else {
- Ok(None)
- }
- }
- Err(err) => Err(err),
- }
}
pub fn node_ipc_fd(&self) -> Option<i64> {
@@ -1124,7 +1084,7 @@ impl CliOptions {
self
.maybe_config_file
.as_ref()
- .and_then(|c| c.node_modules_dir_flag())
+ .and_then(|c| c.json.node_modules_dir)
})
}
@@ -1613,7 +1573,7 @@ impl CliOptions {
Vec::with_capacity(2)
};
if let Ok(Some(import_map_path)) = self
- .resolve_import_map_specifier()
+ .resolve_specified_import_map_specifier()
.map(|ms| ms.and_then(|ref s| s.to_file_path().ok()))
{
paths.push(import_map_path);
@@ -1638,9 +1598,9 @@ fn resolve_node_modules_folder(
) -> Result<Option<PathBuf>, AnyError> {
let use_node_modules_dir = flags
.node_modules_dir
- .or_else(|| maybe_config_file.and_then(|c| c.node_modules_dir_flag()))
+ .or_else(|| maybe_config_file.and_then(|c| c.json.node_modules_dir))
.or(flags.vendor)
- .or_else(|| maybe_config_file.and_then(|c| c.vendor_dir_flag()));
+ .or_else(|| maybe_config_file.and_then(|c| c.json.vendor));
let path = if use_node_modules_dir == Some(false) {
return Ok(None);
} else if let Some(state) = &*NPM_PROCESS_STATE {
@@ -1668,7 +1628,7 @@ fn resolve_vendor_folder(
) -> Option<PathBuf> {
let use_vendor_dir = flags
.vendor
- .or_else(|| maybe_config_file.and_then(|c| c.vendor_dir_flag()))
+ .or_else(|| maybe_config_file.and_then(|c| c.json.vendor))
.unwrap_or(false);
// Unlike the node_modules directory, there is no need to canonicalize
// this directory because it's just used as a cache and the resolved
@@ -1693,7 +1653,7 @@ fn resolve_import_map_specifier(
) -> Result<Option<ModuleSpecifier>, AnyError> {
if let Some(import_map_path) = maybe_import_map_path {
if let Some(config_file) = &maybe_config_file {
- if config_file.to_import_map_path().is_some() {
+ if config_file.json.import_map.is_some() {
log::warn!("{} the configuration file \"{}\" contains an entry for \"importMap\" that is being ignored.", colors::yellow("Warning"), config_file.specifier);
}
}
@@ -1702,53 +1662,16 @@ fn resolve_import_map_specifier(
.with_context(|| {
format!("Bad URL (\"{import_map_path}\") for import map.")
})?;
- return Ok(Some(specifier));
+ Ok(Some(specifier))
} else if let Some(config_file) = &maybe_config_file {
- // if the config file is an import map we prefer to use it, over `importMap`
- // field
- if config_file.is_an_import_map() {
- if let Some(_import_map_path) = config_file.to_import_map_path() {
- log::warn!("{} \"importMap\" setting is ignored when \"imports\" or \"scopes\" are specified in the config file.", colors::yellow("Warning"));
- }
-
- return Ok(Some(config_file.specifier.clone()));
- }
-
- // when the import map is specifier in a config file, it needs to be
- // resolved relative to the config file, versus the CWD like with the flag
- // and with config files, we support both local and remote config files,
- // so we have treat them differently.
- if let Some(import_map_path) = config_file.to_import_map_path() {
- // if the import map is an absolute URL, use it as is
- if let Ok(specifier) = deno_core::resolve_url(&import_map_path) {
- return Ok(Some(specifier));
- }
- let specifier =
- // with local config files, it might be common to specify an import
- // map like `"importMap": "import-map.json"`, which is resolvable if
- // the file is resolved like a file path, so we will coerce the config
- // file into a file path if possible and join the import map path to
- // the file path.
- if let Ok(config_file_path) = config_file.specifier.to_file_path() {
- let import_map_file_path = normalize_path(config_file_path
- .parent()
- .ok_or_else(|| {
- anyhow!("Bad config file specifier: {}", config_file.specifier)
- })?
- .join(&import_map_path));
- ModuleSpecifier::from_file_path(import_map_file_path).unwrap()
- // otherwise if the config file is remote, we have no choice but to
- // use "import resolution" with the config file as the base.
- } else {
- deno_core::resolve_import(&import_map_path, config_file.specifier.as_str())
- .with_context(|| format!(
- "Bad URL (\"{import_map_path}\") for import map."
- ))?
- };
- return Ok(Some(specifier));
+ // if the config file is an import map we prefer to use it, over `importMap` field
+ if config_file.is_an_import_map() && config_file.json.import_map.is_some() {
+ log::warn!("{} \"importMap\" setting is ignored when \"imports\" or \"scopes\" are specified in the config file.", colors::yellow("Warning"));
}
+ Ok(None)
+ } else {
+ Ok(None)
}
- Ok(None)
}
pub struct StorageKeyResolver(Option<Option<String>>);
@@ -1847,74 +1770,6 @@ mod test {
use super::*;
use pretty_assertions::assert_eq;
- #[cfg(not(windows))]
- #[test]
- fn resolve_import_map_config_file() {
- let config_text = r#"{
- "importMap": "import_map.json"
- }"#;
- let config_specifier =
- ModuleSpecifier::parse("file:///deno/deno.jsonc").unwrap();
- let config_file = ConfigFile::new(config_text, config_specifier).unwrap();
- let actual = resolve_import_map_specifier(
- None,
- Some(&config_file),
- &PathBuf::from("/"),
- );
- assert!(actual.is_ok());
- let actual = actual.unwrap();
- assert_eq!(
- actual,
- Some(ModuleSpecifier::parse("file:///deno/import_map.json").unwrap(),)
- );
- }
-
- #[test]
- fn resolve_import_map_remote_config_file_local() {
- let config_text = r#"{
- "importMap": "https://example.com/import_map.json"
- }"#;
- let config_specifier =
- ModuleSpecifier::parse("file:///deno/deno.jsonc").unwrap();
- let config_file = ConfigFile::new(config_text, config_specifier).unwrap();
- let actual = resolve_import_map_specifier(
- None,
- Some(&config_file),
- &PathBuf::from("/"),
- );
- assert!(actual.is_ok());
- let actual = actual.unwrap();
- assert_eq!(
- actual,
- Some(
- ModuleSpecifier::parse("https://example.com/import_map.json").unwrap()
- )
- );
- }
-
- #[test]
- fn resolve_import_map_config_file_remote() {
- let config_text = r#"{
- "importMap": "./import_map.json"
- }"#;
- let config_specifier =
- ModuleSpecifier::parse("https://example.com/deno.jsonc").unwrap();
- let config_file = ConfigFile::new(config_text, config_specifier).unwrap();
- let actual = resolve_import_map_specifier(
- None,
- Some(&config_file),
- &PathBuf::from("/"),
- );
- assert!(actual.is_ok());
- let actual = actual.unwrap();
- assert_eq!(
- actual,
- Some(
- ModuleSpecifier::parse("https://example.com/import_map.json").unwrap()
- )
- );
- }
-
#[test]
fn resolve_import_map_flags_take_precedence() {
let config_text = r#"{
@@ -1938,26 +1793,6 @@ mod test {
}
#[test]
- fn resolve_import_map_embedded_take_precedence() {
- let config_text = r#"{
- "importMap": "import_map.json",
- "imports": {},
- }"#;
- let config_specifier =
- ModuleSpecifier::parse("file:///deno/deno.jsonc").unwrap();
- let config_file =
- ConfigFile::new(config_text, config_specifier.clone()).unwrap();
- let actual = resolve_import_map_specifier(
- None,
- Some(&config_file),
- &PathBuf::from("/"),
- );
- assert!(actual.is_ok());
- let actual = actual.unwrap();
- assert_eq!(actual, Some(config_specifier));
- }
-
- #[test]
fn resolve_import_map_none() {
let config_text = r#"{}"#;
let config_specifier =
@@ -2087,7 +1922,7 @@ mod test {
"pages/[id].ts",
]
.into_iter()
- .map(|p| normalize_path(temp_dir_path.join(p)))
+ .map(|p| deno_core::normalize_path(temp_dir_path.join(p)))
.collect::<Vec<_>>()
);
}
diff --git a/cli/factory.rs b/cli/factory.rs
index 22bc6cdaf..7302c0312 100644
--- a/cli/factory.rs
+++ b/cli/factory.rs
@@ -48,7 +48,6 @@ use crate::tools::run::hmr::HmrRunner;
use crate::util::file_watcher::WatcherCommunicator;
use crate::util::fs::canonicalize_path_maybe_not_exists;
use crate::util::import_map::deno_json_deps;
-use crate::util::import_map::import_map_deps;
use crate::util::progress_bar::ProgressBar;
use crate::util::progress_bar::ProgressBarStyle;
use crate::worker::CliMainWorkerFactory;
@@ -343,8 +342,8 @@ impl CliFactory {
Some(workspace_config) => deno_lockfile::WorkspaceConfig {
root: WorkspaceMemberConfig {
package_json_deps,
- dependencies: import_map_deps(
- &workspace_config.base_import_map_value,
+ dependencies: deno_json_deps(
+ self.options.maybe_config_file().as_ref().unwrap(),
)
.into_iter()
.map(|req| req.to_string())
diff --git a/cli/lsp/config.rs b/cli/lsp/config.rs
index d0909b926..3d24c8c20 100644
--- a/cli/lsp/config.rs
+++ b/cli/lsp/config.rs
@@ -1238,12 +1238,12 @@ fn resolve_node_modules_dir(config_file: &ConfigFile) -> Option<PathBuf> {
// `nodeModulesDir: true` setting in the deno.json file. This is to
// reduce the chance of modifying someone's node_modules directory
// without them having asked us to do so.
- let explicitly_disabled = config_file.node_modules_dir_flag() == Some(false);
+ let explicitly_disabled = config_file.json.node_modules_dir == Some(false);
if explicitly_disabled {
return None;
}
- let enabled = config_file.node_modules_dir_flag() == Some(true)
- || config_file.vendor_dir_flag() == Some(true);
+ let enabled = config_file.json.node_modules_dir == Some(true)
+ || config_file.json.vendor == Some(true);
if !enabled {
return None;
}
diff --git a/cli/lsp/documents.rs b/cli/lsp/documents.rs
index ddff92342..66ebe5115 100644
--- a/cli/lsp/documents.rs
+++ b/cli/lsp/documents.rs
@@ -1420,7 +1420,7 @@ impl Documents {
options.document_preload_limit,
options.maybe_import_map.as_deref(),
maybe_jsx_config.as_ref(),
- options.maybe_config_file.and_then(|c| c.vendor_dir_flag()),
+ options.maybe_config_file.and_then(|c| c.json.vendor),
maybe_package_json_deps.as_ref(),
options.maybe_config_file.map(|c| &c.json.unstable),
);
diff --git a/cli/lsp/language_server.rs b/cli/lsp/language_server.rs
index 7e24c6e51..185cde6f9 100644
--- a/cli/lsp/language_server.rs
+++ b/cli/lsp/language_server.rs
@@ -89,7 +89,7 @@ use super::tsc::TsServer;
use super::urls;
use crate::args::get_root_cert_store;
use crate::args::package_json;
-use crate::args::resolve_import_map_from_specifier;
+use crate::args::resolve_import_map;
use crate::args::CaData;
use crate::args::CacheSetting;
use crate::args::CliOptions;
@@ -250,8 +250,6 @@ pub struct Inner {
maybe_global_cache_path: Option<PathBuf>,
/// An optional import map which is used to resolve modules.
maybe_import_map: Option<Arc<ImportMap>>,
- /// The URL for the import map which is used to determine relative imports.
- maybe_import_map_uri: Option<Url>,
/// An optional package.json configuration file.
maybe_package_json: Option<PackageJson>,
/// Configuration for formatter which has been taken from specified config file.
@@ -539,7 +537,6 @@ impl Inner {
initial_cwd: initial_cwd.clone(),
maybe_global_cache_path: None,
maybe_import_map: None,
- maybe_import_map_uri: None,
maybe_package_json: None,
fmt_options: FmtOptions::new_with_base(initial_cwd.clone()),
task_queue: Default::default(),
@@ -894,18 +891,18 @@ impl Inner {
let mark = self.performance.mark("lsp.update_import_map");
let maybe_import_map_url = self.resolve_import_map_specifier()?;
- if let Some(import_map_url) = maybe_import_map_url {
- if import_map_url.scheme() != "data" {
- lsp_log!(" Resolved import map: \"{}\"", import_map_url);
+ let maybe_import_map = self
+ .fetch_import_map(
+ maybe_import_map_url.as_ref(),
+ CacheSetting::RespectHeaders,
+ )
+ .await?;
+ if let Some(import_map) = maybe_import_map {
+ if import_map.base_url().scheme() != "data" {
+ lsp_log!(" Resolved import map: \"{}\"", import_map.base_url());
}
-
- let import_map = self
- .fetch_import_map(&import_map_url, CacheSetting::RespectHeaders)
- .await?;
- self.maybe_import_map_uri = Some(import_map_url);
self.maybe_import_map = Some(Arc::new(import_map));
} else {
- self.maybe_import_map_uri = None;
self.maybe_import_map = None;
}
self.performance.measure(mark);
@@ -914,22 +911,15 @@ impl Inner {
async fn fetch_import_map(
&self,
- import_map_url: &ModuleSpecifier,
+ import_map_url: Option<&ModuleSpecifier>,
cache_setting: CacheSetting,
- ) -> Result<ImportMap, AnyError> {
- resolve_import_map_from_specifier(
+ ) -> Result<Option<ImportMap>, AnyError> {
+ resolve_import_map(
import_map_url,
self.config.maybe_config_file(),
&self.create_file_fetcher(cache_setting),
)
.await
- .map_err(|err| {
- anyhow!(
- "Failed to load the import map at: {}. {:#}",
- import_map_url,
- err
- )
- })
}
fn create_file_fetcher(&self, cache_setting: CacheSetting) -> FileFetcher {
@@ -948,76 +938,40 @@ impl Inner {
fn resolve_import_map_specifier(
&self,
) -> Result<Option<ModuleSpecifier>, AnyError> {
- Ok(
- if let Some(import_map_str) = self
- .config
- .workspace_settings()
- .import_map
- .clone()
- .and_then(|s| if s.is_empty() { None } else { Some(s) })
- {
- lsp_log!(
- "Setting import map from workspace settings: \"{}\"",
- import_map_str
- );
- if let Some(config_file) = self.config.maybe_config_file() {
- if let Some(import_map_path) = config_file.to_import_map_path() {
- lsp_log!("Warning: Import map \"{}\" configured in \"{}\" being ignored due to an import map being explicitly configured in workspace settings.", import_map_path, config_file.specifier);
- }
- }
- if let Ok(url) = Url::parse(&import_map_str) {
- Some(url)
- } else if let Some(root_uri) = self.config.root_uri() {
- let root_path = specifier_to_file_path(root_uri)?;
- let import_map_path = root_path.join(&import_map_str);
- let import_map_url =
- Url::from_file_path(import_map_path).map_err(|_| {
- anyhow!("Bad file path for import map: {}", import_map_str)
- })?;
- Some(import_map_url)
- } else {
- return Err(anyhow!(
- "The path to the import map (\"{}\") is not resolvable.",
- import_map_str
- ));
- }
- } else if let Some(config_file) = self.config.maybe_config_file() {
- if config_file.is_an_import_map() {
- lsp_log!(
- "Setting import map defined in configuration file: \"{}\"",
- config_file.specifier
- );
- let import_map_url = config_file.specifier.clone();
- Some(import_map_url)
- } else if let Some(import_map_path) = config_file.to_import_map_path() {
- lsp_log!(
- "Setting import map from configuration file: \"{}\"",
- import_map_path
- );
- let specifier = if let Ok(config_file_path) =
- config_file.specifier.to_file_path()
- {
- let import_map_file_path = config_file_path
- .parent()
- .ok_or_else(|| {
- anyhow!("Bad config file specifier: {}", config_file.specifier)
- })?
- .join(&import_map_path);
- ModuleSpecifier::from_file_path(import_map_file_path).unwrap()
- } else {
- deno_core::resolve_import(
- &import_map_path,
- config_file.specifier.as_str(),
- )?
- };
- Some(specifier)
- } else {
- None
- }
- } else {
- None
- },
- )
+ let Some(import_map_str) = self
+ .config
+ .workspace_settings()
+ .import_map
+ .clone()
+ .and_then(|s| if s.is_empty() { None } else { Some(s) })
+ else {
+ return Ok(None);
+ };
+ lsp_log!(
+ "Setting import map from workspace settings: \"{}\"",
+ import_map_str
+ );
+ if let Some(config_file) = self.config.maybe_config_file() {
+ if let Some(import_map_path) = &config_file.json.import_map {
+ lsp_log!("Warning: Import map \"{}\" configured in \"{}\" being ignored due to an import map being explicitly configured in workspace settings.", import_map_path, config_file.specifier);
+ }
+ }
+ if let Ok(url) = Url::parse(&import_map_str) {
+ Ok(Some(url))
+ } else if let Some(root_uri) = self.config.root_uri() {
+ let root_path = specifier_to_file_path(root_uri)?;
+ let import_map_path = root_path.join(&import_map_str);
+ let import_map_url =
+ Url::from_file_path(import_map_path).map_err(|_| {
+ anyhow!("Bad file path for import map: {}", import_map_str)
+ })?;
+ Ok(Some(import_map_url))
+ } else {
+ Err(anyhow!(
+ "The path to the import map (\"{}\") is not resolvable.",
+ import_map_str
+ ))
+ }
}
pub fn update_debug_flag(&self) {
@@ -1671,9 +1625,9 @@ impl Inner {
// if the current import map, or config file has changed, we need to
// reload the import map
let import_map_changed = self
- .maybe_import_map_uri
+ .maybe_import_map
.as_ref()
- .map(|uri| changes.contains(uri))
+ .map(|import_map| changes.contains(import_map.base_url()))
.unwrap_or(false);
if touched || import_map_changed {
if let Err(err) = self.update_import_map().await {
@@ -3696,7 +3650,9 @@ impl Inner {
self.config.maybe_lockfile().cloned(),
self.maybe_package_json.clone(),
)?;
- cli_options.set_import_map_specifier(self.maybe_import_map_uri.clone());
+ cli_options.set_import_map_specifier(
+ self.maybe_import_map.as_ref().map(|m| m.base_url().clone()),
+ );
let open_docs = self.documents.documents(DocumentsFilter::OpenDiagnosable);
Ok(Some(PrepareCacheResult {
diff --git a/cli/tools/bundle.rs b/cli/tools/bundle.rs
index c0b1ce31b..0a992fcb0 100644
--- a/cli/tools/bundle.rs
+++ b/cli/tools/bundle.rs
@@ -82,7 +82,7 @@ async fn bundle_action(
.collect();
if let Ok(Some(import_map_path)) = cli_options
- .resolve_import_map_specifier()
+ .resolve_specified_import_map_specifier()
.map(|ms| ms.and_then(|ref s| s.to_file_path().ok()))
{
paths_to_watch.push(import_map_path);
diff --git a/cli/tools/vendor/mod.rs b/cli/tools/vendor/mod.rs
index f168f84a2..975cf08f1 100644
--- a/cli/tools/vendor/mod.rs
+++ b/cli/tools/vendor/mod.rs
@@ -173,9 +173,24 @@ fn validate_options(
options: &mut CliOptions,
output_dir: &Path,
) -> Result<(), AnyError> {
+ let import_map_specifier = options
+ .resolve_specified_import_map_specifier()?
+ .or_else(|| {
+ let config_file = options.maybe_config_file().as_ref()?;
+ config_file
+ .to_import_map_specifier()
+ .ok()
+ .flatten()
+ .or_else(|| {
+ if config_file.is_an_import_map() {
+ Some(config_file.specifier.clone())
+ } else {
+ None
+ }
+ })
+ });
// check the import map
- if let Some(import_map_path) = options
- .resolve_import_map_specifier()?
+ if let Some(import_map_path) = import_map_specifier
.and_then(|p| specifier_to_file_path(&p).ok())
.and_then(|p| canonicalize_path(&p).ok())
{
diff --git a/cli/util/import_map.rs b/cli/util/import_map.rs
index 9adc41af0..a075443ba 100644
--- a/cli/util/import_map.rs
+++ b/cli/util/import_map.rs
@@ -17,16 +17,6 @@ use deno_semver::npm::NpmPackageReqReference;
use crate::resolver::MappedSpecifierResolver;
-pub fn import_map_deps(value: &serde_json::Value) -> HashSet<JsrDepPackageReq> {
- let Some(obj) = value.as_object() else {
- return Default::default();
- };
- let values = imports_values(obj.get("imports"))
- .into_iter()
- .chain(scope_values(obj.get("scopes")));
- values_to_set(values)
-}
-
pub fn deno_json_deps(
config: &deno_config::ConfigFile,
) -> HashSet<JsrDepPackageReq> {
@@ -335,7 +325,7 @@ mod tests {
}
});
let ImportMapWithDiagnostics { import_map, .. } =
- import_map::parse_from_value(&deno_json_url, value).unwrap();
+ import_map::parse_from_value(deno_json_url, value).unwrap();
let mapped_resolved = MappedSpecifierResolver::new(
Some(Arc::new(import_map)),
Arc::new(PackageJsonDepsProvider::new(None)),
diff --git a/tests/testdata/run/workspaces/basic/main.out b/tests/testdata/run/workspaces/basic/main.out
index 77e0de4d1..a955ac54c 100644
--- a/tests/testdata/run/workspaces/basic/main.out
+++ b/tests/testdata/run/workspaces/basic/main.out
@@ -1,6 +1,7 @@
[WILDCARD]Workspace config generated this import map {
"imports": {
- "chalk": "npm:chalk"
+ "chalk": "npm:chalk",
+ "chalk/": "npm:/chalk/"
},
"scopes": {
"./foo/": {