diff --git a/Cargo.lock b/Cargo.lock index d590ccdad5..b289012d39 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -589,6 +589,7 @@ dependencies = [ "flaky_test", "fwdansi", "http", + "import_map", "indexmap", "jsonc-parser", "lazy_static", @@ -1748,6 +1749,19 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb56e1aa765b4b4f3aadfab769793b7087bb03a4ea4920644a6d238e2df5b9ed" +[[package]] +name = "import_map" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae79a7af71e92e4038963b64884106d28d508da6bf3c7f36294efcb3bb3b003d" +dependencies = [ + "indexmap", + "log", + "serde", + "serde_json", + "url", +] + [[package]] name = "indexmap" version = "1.6.2" diff --git a/cli/Cargo.toml b/cli/Cargo.toml index 9f18a5b6d7..2a1179aa52 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -65,6 +65,7 @@ env_logger = "0.8.4" fancy-regex = "0.7.1" filetime = "0.2.14" http = "0.2.4" +import_map = "0.3.0" # TODO(lucacasonato): unlock when https://github.com/tkaitchuck/aHash/issues/95 is resolved indexmap = { version = "=1.6.2", features = ["serde"] } jsonc-parser = { version = "0.17.0", features = ["serde"] } diff --git a/cli/errors.rs b/cli/errors.rs index 7be406fe73..c26479b447 100644 --- a/cli/errors.rs +++ b/cli/errors.rs @@ -9,9 +9,9 @@ //! Diagnostics are compile-time type errors, whereas JsErrors are runtime //! exceptions. -use crate::import_map::ImportMapError; use deno_ast::Diagnostic; use deno_core::error::AnyError; +use import_map::ImportMapError; fn get_import_map_error_class(_: &ImportMapError) -> &'static str { "URIError" diff --git a/cli/import_map.rs b/cli/import_map.rs deleted file mode 100644 index 31384ecef8..0000000000 --- a/cli/import_map.rs +++ /dev/null @@ -1,867 +0,0 @@ -// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. - -use deno_core::error::AnyError; -use deno_core::serde::Serialize; -use deno_core::serde_json; -use deno_core::serde_json::Map; -use deno_core::serde_json::Value; -use deno_core::url::Url; -use indexmap::IndexMap; -use log::debug; -use log::info; -use std::cmp::Ordering; -use std::collections::HashSet; -use std::error::Error; -use std::fmt; - -#[derive(Debug)] -pub enum ImportMapError { - UnmappedBareSpecifier(String, Option), - Other(String), -} - -impl fmt::Display for ImportMapError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - ImportMapError::UnmappedBareSpecifier(specifier, maybe_referrer) => write!( - f, - "Relative import path \"{}\" not prefixed with / or ./ or ../ and not in import map{}", - specifier, - match maybe_referrer { - Some(referrer) => format!(" from \"{}\"", referrer), - None => format!(""), - } - ), - ImportMapError::Other(message) => f.pad(message), - } - } -} - -impl Error for ImportMapError {} - -// https://url.spec.whatwg.org/#special-scheme -const SPECIAL_PROTOCOLS: &[&str] = - &["ftp", "file", "http", "https", "ws", "wss"]; -fn is_special(url: &Url) -> bool { - SPECIAL_PROTOCOLS.contains(&url.scheme()) -} - -type SpecifierMap = IndexMap>; -type ScopesMap = IndexMap; - -#[derive(Debug, Clone, Serialize)] -pub struct ImportMap { - #[serde(skip)] - base_url: String, - - imports: SpecifierMap, - scopes: ScopesMap, -} - -impl ImportMap { - pub fn from_json( - base_url: &str, - json_string: &str, - ) -> Result { - let v: Value = match serde_json::from_str(json_string) { - Ok(v) => v, - Err(err) => { - return Err(ImportMapError::Other(format!( - "Unable to parse import map JSON: {}", - err.to_string() - ))); - } - }; - - match v { - Value::Object(_) => {} - _ => { - return Err(ImportMapError::Other( - "Import map JSON must be an object".to_string(), - )); - } - } - - let mut diagnostics = vec![]; - let normalized_imports = match &v.get("imports") { - Some(imports_map) => { - if !imports_map.is_object() { - return Err(ImportMapError::Other( - "Import map's 'imports' must be an object".to_string(), - )); - } - - let imports_map = imports_map.as_object().unwrap(); - ImportMap::parse_specifier_map(imports_map, base_url, &mut diagnostics) - } - None => IndexMap::new(), - }; - - let normalized_scopes = match &v.get("scopes") { - Some(scope_map) => { - if !scope_map.is_object() { - return Err(ImportMapError::Other( - "Import map's 'scopes' must be an object".to_string(), - )); - } - - let scope_map = scope_map.as_object().unwrap(); - ImportMap::parse_scope_map(scope_map, base_url, &mut diagnostics)? - } - None => IndexMap::new(), - }; - - let mut keys: HashSet = v - .as_object() - .unwrap() - .keys() - .map(|k| k.to_string()) - .collect(); - keys.remove("imports"); - keys.remove("scopes"); - for key in keys { - diagnostics.push(format!("Invalid top-level key \"{}\". Only \"imports\" and \"scopes\" can be present.", key)); - } - - let import_map = ImportMap { - base_url: base_url.to_string(), - imports: normalized_imports, - scopes: normalized_scopes, - }; - - if !diagnostics.is_empty() { - info!("Import map diagnostics:"); - for diagnotic in diagnostics { - info!(" - {}", diagnotic); - } - } - - Ok(import_map) - } - - fn try_url_like_specifier(specifier: &str, base: &str) -> Option { - if specifier.starts_with('/') - || specifier.starts_with("./") - || specifier.starts_with("../") - { - if let Ok(base_url) = Url::parse(base) { - if let Ok(url) = base_url.join(specifier) { - return Some(url); - } - } - } - - if let Ok(url) = Url::parse(specifier) { - return Some(url); - } - - None - } - - /// Parse provided key as import map specifier. - /// - /// Specifiers must be valid URLs (eg. "`https://deno.land/x/std/testing/asserts.ts`") - /// or "bare" specifiers (eg. "moment"). - fn normalize_specifier_key( - specifier_key: &str, - base_url: &str, - diagnostics: &mut Vec, - ) -> Option { - // ignore empty keys - if specifier_key.is_empty() { - diagnostics.push("Invalid empty string specifier.".to_string()); - return None; - } - - if let Some(url) = - ImportMap::try_url_like_specifier(specifier_key, base_url) - { - return Some(url.to_string()); - } - - // "bare" specifier - Some(specifier_key.to_string()) - } - - fn append_specifier_to_base( - base: &Url, - specifier: &str, - ) -> Result { - let mut base = base.clone(); - let is_relative_or_absolute_specifier = specifier.starts_with("../") - || specifier.starts_with("./") - || specifier.starts_with('/'); - - // The specifier could be a windows path such as "C:/a/test.ts" in which - // case we don't want to use `join` because it will make the specifier - // the url since it contains what looks to be a uri scheme. To work around - // this, we append the specifier to the path segments of the base url when - // the specifier is not relative or absolute. - let mut maybe_query_string_and_fragment = None; - if !is_relative_or_absolute_specifier && base.path_segments_mut().is_ok() { - { - let mut segments = base.path_segments_mut().unwrap(); - segments.pop_if_empty(); - - // Handle query-string and fragment first, otherwise they would be percent-encoded - // by `extend()` - let prefix = match specifier.find(&['?', '#'][..]) { - Some(idx) => { - maybe_query_string_and_fragment = Some(&specifier[idx..]); - &specifier[..idx] - } - None => specifier, - }; - segments.extend(prefix.split('/')); - } - - if let Some(query_string_and_fragment) = maybe_query_string_and_fragment { - Ok(base.join(query_string_and_fragment)?) - } else { - Ok(base) - } - } else { - Ok(base.join(specifier)?) - } - } - - /// Convert provided JSON map to valid SpecifierMap. - /// - /// From specification: - /// - order of iteration must be retained - /// - SpecifierMap's keys are sorted in longest and alphabetic order - fn parse_specifier_map( - json_map: &Map, - base_url: &str, - diagnostics: &mut Vec, - ) -> SpecifierMap { - let mut normalized_map: SpecifierMap = SpecifierMap::new(); - - // Order is preserved because of "preserve_order" feature of "serde_json". - for (specifier_key, value) in json_map.iter() { - let normalized_specifier_key = match ImportMap::normalize_specifier_key( - specifier_key, - base_url, - diagnostics, - ) { - Some(s) => s, - None => continue, - }; - - let potential_address = match value { - Value::String(address) => address.to_string(), - _ => { - diagnostics.push(format!("Invalid address {:#?} for the specifier key \"{}\". Addresses must be strings.", value, specifier_key)); - normalized_map.insert(normalized_specifier_key, None); - continue; - } - }; - - let address_url = - match ImportMap::try_url_like_specifier(&potential_address, base_url) { - Some(url) => url, - None => { - diagnostics.push(format!( - "Invalid address \"{}\" for the specifier key \"{}\".", - potential_address, specifier_key - )); - normalized_map.insert(normalized_specifier_key, None); - continue; - } - }; - - let address_url_string = address_url.to_string(); - if specifier_key.ends_with('/') && !address_url_string.ends_with('/') { - diagnostics.push(format!( - "Invalid target address {:?} for package specifier {:?}. \ - Package address targets must end with \"/\".", - address_url_string, specifier_key - )); - normalized_map.insert(normalized_specifier_key, None); - continue; - } - - normalized_map.insert(normalized_specifier_key, Some(address_url)); - } - - // Sort in longest and alphabetical order. - normalized_map.sort_by(|k1, _v1, k2, _v2| match k1.cmp(k2) { - Ordering::Greater => Ordering::Less, - Ordering::Less => Ordering::Greater, - // JSON guarantees that there can't be duplicate keys - Ordering::Equal => unreachable!(), - }); - - normalized_map - } - - /// Convert provided JSON map to valid ScopeMap. - /// - /// From specification: - /// - order of iteration must be retained - /// - ScopeMap's keys are sorted in longest and alphabetic order - fn parse_scope_map( - scope_map: &Map, - base_url: &str, - diagnostics: &mut Vec, - ) -> Result { - let mut normalized_map: ScopesMap = ScopesMap::new(); - - // Order is preserved because of "preserve_order" feature of "serde_json". - for (scope_prefix, potential_specifier_map) in scope_map.iter() { - if !potential_specifier_map.is_object() { - return Err(ImportMapError::Other(format!( - "The value for the {:?} scope prefix must be an object", - scope_prefix - ))); - } - - let potential_specifier_map = - potential_specifier_map.as_object().unwrap(); - - let scope_prefix_url = - match Url::parse(base_url).unwrap().join(scope_prefix) { - Ok(url) => url.to_string(), - _ => { - diagnostics.push(format!( - "Invalid scope \"{}\" (parsed against base URL \"{}\").", - scope_prefix, base_url - )); - continue; - } - }; - - let norm_map = ImportMap::parse_specifier_map( - potential_specifier_map, - base_url, - diagnostics, - ); - - normalized_map.insert(scope_prefix_url, norm_map); - } - - // Sort in longest and alphabetical order. - normalized_map.sort_by(|k1, _v1, k2, _v2| match k1.cmp(k2) { - Ordering::Greater => Ordering::Less, - Ordering::Less => Ordering::Greater, - // JSON guarantees that there can't be duplicate keys - Ordering::Equal => unreachable!(), - }); - - Ok(normalized_map) - } - - fn resolve_scopes_match( - scopes: &ScopesMap, - normalized_specifier: &str, - as_url: Option<&Url>, - referrer: &str, - ) -> Result, ImportMapError> { - // exact-match - if let Some(scope_imports) = scopes.get(referrer) { - let scope_match = ImportMap::resolve_imports_match( - scope_imports, - normalized_specifier, - as_url, - )?; - // Return only if there was actual match (not None). - if scope_match.is_some() { - return Ok(scope_match); - } - } - - for (normalized_scope_key, scope_imports) in scopes.iter() { - if normalized_scope_key.ends_with('/') - && referrer.starts_with(normalized_scope_key) - { - let scope_match = ImportMap::resolve_imports_match( - scope_imports, - normalized_specifier, - as_url, - )?; - // Return only if there was actual match (not None). - if scope_match.is_some() { - return Ok(scope_match); - } - } - } - - Ok(None) - } - - fn resolve_imports_match( - specifier_map: &SpecifierMap, - normalized_specifier: &str, - as_url: Option<&Url>, - ) -> Result, ImportMapError> { - // exact-match - if let Some(maybe_address) = specifier_map.get(normalized_specifier) { - if let Some(address) = maybe_address { - return Ok(Some(address.clone())); - } else { - return Err(ImportMapError::Other(format!( - "Blocked by null entry for \"{:?}\"", - normalized_specifier - ))); - } - } - - // Package-prefix match - // "most-specific wins", i.e. when there are multiple matching keys, - // choose the longest. - for (specifier_key, maybe_address) in specifier_map.iter() { - if !specifier_key.ends_with('/') { - continue; - } - - if !normalized_specifier.starts_with(specifier_key) { - continue; - } - - if let Some(url) = as_url { - if !is_special(url) { - continue; - } - } - - let resolution_result = maybe_address.as_ref().ok_or_else(|| { - ImportMapError::Other(format!( - "Blocked by null entry for \"{:?}\"", - specifier_key - )) - })?; - - // Enforced by parsing. - assert!(resolution_result.to_string().ends_with('/')); - - let after_prefix = &normalized_specifier[specifier_key.len()..]; - - let url = match ImportMap::append_specifier_to_base( - resolution_result, - after_prefix, - ) { - Ok(url) => url, - Err(_) => { - return Err(ImportMapError::Other(format!( - "Failed to resolve the specifier \"{:?}\" as its after-prefix - portion \"{:?}\" could not be URL-parsed relative to the URL prefix - \"{:?}\" mapped to by the prefix \"{:?}\"", - normalized_specifier, - after_prefix, - resolution_result, - specifier_key - ))); - } - }; - - if !url.as_str().starts_with(resolution_result.as_str()) { - return Err(ImportMapError::Other(format!( - "The specifier \"{:?}\" backtracks above its prefix \"{:?}\"", - normalized_specifier, specifier_key - ))); - } - - return Ok(Some(url)); - } - - debug!( - "Specifier {:?} was not mapped in import map.", - normalized_specifier - ); - - Ok(None) - } - - pub fn resolve( - &self, - specifier: &str, - referrer: &str, - ) -> Result { - let as_url: Option = - ImportMap::try_url_like_specifier(specifier, referrer); - let normalized_specifier = if let Some(url) = as_url.as_ref() { - url.to_string() - } else { - specifier.to_string() - }; - - let scopes_match = ImportMap::resolve_scopes_match( - &self.scopes, - &normalized_specifier, - as_url.as_ref(), - &referrer.to_string(), - )?; - - // match found in scopes map - if let Some(scopes_match) = scopes_match { - return Ok(scopes_match); - } - - let imports_match = ImportMap::resolve_imports_match( - &self.imports, - &normalized_specifier, - as_url.as_ref(), - )?; - - // match found in import map - if let Some(imports_match) = imports_match { - return Ok(imports_match); - } - - // The specifier was able to be turned into a URL, but wasn't remapped into anything. - if let Some(as_url) = as_url { - return Ok(as_url); - } - - Err(ImportMapError::UnmappedBareSpecifier( - specifier.to_string(), - Some(referrer.to_string()), - )) - } -} - -#[cfg(test)] -mod tests { - - use super::*; - use std::path::Path; - use std::path::PathBuf; - use walkdir::WalkDir; - - #[derive(Debug)] - enum TestKind { - Resolution { - given_specifier: String, - expected_specifier: Option, - base_url: String, - }, - Parse { - expected_import_map: Value, - }, - } - - #[derive(Debug)] - struct ImportMapTestCase { - name: String, - import_map: String, - import_map_base_url: String, - kind: TestKind, - } - - fn load_import_map_wpt_tests() -> Vec { - let mut found_test_files = vec![]; - let repo_root = Path::new(env!("CARGO_MANIFEST_DIR")).parent().unwrap(); - let import_map_wpt_path = - repo_root.join("test_util/wpt/import-maps/data-driven/resources"); - eprintln!("import map wpt path {:#?}", import_map_wpt_path); - for entry in WalkDir::new(import_map_wpt_path) - .contents_first(true) - .into_iter() - .filter_entry(|e| { - eprintln!("entry {:#?}", e); - if let Some(ext) = e.path().extension() { - return ext.to_string_lossy() == "json"; - } - false - }) - .filter_map(|e| match e { - Ok(e) => Some(e), - _ => None, - }) - .map(|e| PathBuf::from(e.path())) - { - found_test_files.push(entry); - } - - let mut file_contents = vec![]; - - for file in found_test_files { - let content = std::fs::read_to_string(file).unwrap(); - file_contents.push(content); - } - - file_contents - } - - fn parse_import_map_tests(test_str: &str) -> Vec { - let json_file: serde_json::Value = serde_json::from_str(test_str).unwrap(); - let maybe_name = json_file - .get("name") - .map(|s| s.as_str().unwrap().to_string()); - return parse_test_object(&json_file, maybe_name, None, None, None, None); - - fn parse_test_object( - test_obj: &Value, - maybe_name_prefix: Option, - maybe_import_map: Option, - maybe_base_url: Option, - maybe_import_map_base_url: Option, - maybe_expected_import_map: Option, - ) -> Vec { - let maybe_import_map_base_url = - if let Some(base_url) = test_obj.get("importMapBaseURL") { - Some(base_url.as_str().unwrap().to_string()) - } else { - maybe_import_map_base_url - }; - - let maybe_base_url = if let Some(base_url) = test_obj.get("baseURL") { - Some(base_url.as_str().unwrap().to_string()) - } else { - maybe_base_url - }; - - let maybe_expected_import_map = - if let Some(im) = test_obj.get("expectedParsedImportMap") { - Some(im.to_owned()) - } else { - maybe_expected_import_map - }; - - let maybe_import_map = if let Some(import_map) = test_obj.get("importMap") - { - Some(if import_map.is_string() { - import_map.as_str().unwrap().to_string() - } else { - serde_json::to_string(import_map).unwrap() - }) - } else { - maybe_import_map - }; - - if let Some(nested_tests) = test_obj.get("tests") { - let nested_tests_obj = nested_tests.as_object().unwrap(); - let mut collected = vec![]; - for (name, test_obj) in nested_tests_obj { - let nested_name = if let Some(ref name_prefix) = maybe_name_prefix { - format!("{}: {}", name_prefix, name) - } else { - name.to_string() - }; - let parsed_nested_tests = parse_test_object( - test_obj, - Some(nested_name), - maybe_import_map.clone(), - maybe_base_url.clone(), - maybe_import_map_base_url.clone(), - maybe_expected_import_map.clone(), - ); - collected.extend(parsed_nested_tests) - } - return collected; - } - - let mut collected_cases = vec![]; - if let Some(results) = test_obj.get("expectedResults") { - let expected_results = results.as_object().unwrap(); - for (given, expected) in expected_results { - let name = if let Some(ref name_prefix) = maybe_name_prefix { - format!("{}: {}", name_prefix, given) - } else { - given.to_string() - }; - let given_specifier = given.to_string(); - let expected_specifier = expected.as_str().map(|str| str.to_string()); - - let test_case = ImportMapTestCase { - name, - import_map_base_url: maybe_import_map_base_url.clone().unwrap(), - import_map: maybe_import_map.clone().unwrap(), - kind: TestKind::Resolution { - given_specifier, - expected_specifier, - base_url: maybe_base_url.clone().unwrap(), - }, - }; - - collected_cases.push(test_case); - } - } else if let Some(expected_import_map) = maybe_expected_import_map { - let test_case = ImportMapTestCase { - name: maybe_name_prefix.unwrap(), - import_map_base_url: maybe_import_map_base_url.unwrap(), - import_map: maybe_import_map.unwrap(), - kind: TestKind::Parse { - expected_import_map, - }, - }; - - collected_cases.push(test_case); - } else { - eprintln!("unreachable {:#?}", test_obj); - unreachable!(); - } - - collected_cases - } - } - - fn run_import_map_test_cases(tests: Vec) { - for test in tests { - match &test.kind { - TestKind::Resolution { - given_specifier, - expected_specifier, - base_url, - } => { - let import_map = - ImportMap::from_json(&test.import_map_base_url, &test.import_map) - .unwrap(); - let maybe_resolved = import_map - .resolve(given_specifier, base_url) - .ok() - .map(|url| url.to_string()); - assert_eq!(expected_specifier, &maybe_resolved, "{}", test.name); - } - TestKind::Parse { - expected_import_map, - } => { - if matches!(expected_import_map, Value::Null) { - assert!(ImportMap::from_json( - &test.import_map_base_url, - &test.import_map - ) - .is_err()); - } else { - let import_map = - ImportMap::from_json(&test.import_map_base_url, &test.import_map) - .unwrap(); - let import_map_value = serde_json::to_value(import_map).unwrap(); - assert_eq!(expected_import_map, &import_map_value, "{}", test.name); - } - } - } - } - } - - #[test] - fn wpt() { - let test_file_contents = load_import_map_wpt_tests(); - eprintln!("Found test files {}", test_file_contents.len()); - - for test_file in test_file_contents { - let tests = parse_import_map_tests(&test_file); - run_import_map_test_cases(tests); - } - } - - #[test] - fn from_json_1() { - let base_url = "https://deno.land"; - - // empty JSON - assert!(ImportMap::from_json(base_url, "{}").is_ok()); - - let non_object_strings = vec!["null", "true", "1", "\"foo\"", "[]"]; - - // invalid JSON - for non_object in non_object_strings.to_vec() { - assert!(ImportMap::from_json(base_url, non_object).is_err()); - } - - // invalid JSON message test - assert_eq!( - ImportMap::from_json(base_url, "{\"a\":1,}") - .unwrap_err() - .to_string(), - "Unable to parse import map JSON: trailing comma at line 1 column 8", - ); - - // invalid schema: 'imports' is non-object - for non_object in non_object_strings.to_vec() { - assert!(ImportMap::from_json( - base_url, - &format!("{{\"imports\": {}}}", non_object), - ) - .is_err()); - } - - // invalid schema: 'scopes' is non-object - for non_object in non_object_strings.to_vec() { - assert!(ImportMap::from_json( - base_url, - &format!("{{\"scopes\": {}}}", non_object), - ) - .is_err()); - } - } - - #[test] - fn from_json_2() { - let json_map = r#"{ - "imports": { - "foo": "https://example.com/1", - "bar": ["https://example.com/2"], - "fizz": null - } - }"#; - let result = ImportMap::from_json("https://deno.land", json_map); - assert!(result.is_ok()); - } - - #[test] - fn mapped_windows_file_specifier() { - // from issue #11530 - let mut specifiers = SpecifierMap::new(); - specifiers.insert( - "file:///".to_string(), - Some(Url::parse("http://localhost/").unwrap()), - ); - - let resolved_specifier = ImportMap::resolve_imports_match( - &specifiers, - "file:///C:/folder/file.ts", - None, - ) - .unwrap() - .unwrap(); - - assert_eq!( - resolved_specifier.as_str(), - "http://localhost/C:/folder/file.ts" - ); - } - - #[test] - fn querystring() { - let json_map = r#"{ - "imports": { - "npm/": "https://esm.sh/" - } - }"#; - let import_map = - ImportMap::from_json("https://deno.land", json_map).unwrap(); - - let resolved = import_map - .resolve("npm/postcss-modules@4.2.2?no-check", "https://deno.land") - .unwrap(); - assert_eq!( - resolved.as_str(), - "https://esm.sh/postcss-modules@4.2.2?no-check" - ); - - let resolved = import_map - .resolve("npm/key/a?b?c", "https://deno.land") - .unwrap(); - assert_eq!(resolved.as_str(), "https://esm.sh/key/a?b?c"); - - let resolved = import_map - .resolve( - "npm/postcss-modules@4.2.2?no-check#fragment", - "https://deno.land", - ) - .unwrap(); - assert_eq!( - resolved.as_str(), - "https://esm.sh/postcss-modules@4.2.2?no-check#fragment" - ); - - let resolved = import_map - .resolve("npm/postcss-modules@4.2.2#fragment", "https://deno.land") - .unwrap(); - assert_eq!( - resolved.as_str(), - "https://esm.sh/postcss-modules@4.2.2#fragment" - ); - } -} diff --git a/cli/lsp/analysis.rs b/cli/lsp/analysis.rs index 12b54a5032..8edb8d014f 100644 --- a/cli/lsp/analysis.rs +++ b/cli/lsp/analysis.rs @@ -5,7 +5,6 @@ use super::tsc; use crate::ast; use crate::ast::Location; -use crate::import_map::ImportMap; use crate::lsp::documents::DocumentData; use crate::module_graph::parse_deno_types; use crate::module_graph::parse_ts_reference; @@ -30,6 +29,7 @@ use deno_core::url; use deno_core::ModuleResolutionError; use deno_core::ModuleSpecifier; use deno_lint::rules; +use import_map::ImportMap; use lspower::lsp; use lspower::lsp::Position; use lspower::lsp::Range; diff --git a/cli/lsp/language_server.rs b/cli/lsp/language_server.rs index f2b03a0aaf..93d24f9bd8 100644 --- a/cli/lsp/language_server.rs +++ b/cli/lsp/language_server.rs @@ -7,6 +7,7 @@ use deno_core::serde_json; use deno_core::serde_json::json; use deno_core::serde_json::Value; use deno_core::ModuleSpecifier; +use import_map::ImportMap; use log::error; use log::info; use log::warn; @@ -56,7 +57,6 @@ use crate::config_file::ConfigFile; use crate::config_file::TsConfig; use crate::deno_dir; use crate::fs_util; -use crate::import_map::ImportMap; use crate::logger; use crate::tools::fmt::format_file; use crate::tools::fmt::format_parsed_module; diff --git a/cli/lsp/sources.rs b/cli/lsp/sources.rs index 6207bb3eb4..d453c6972b 100644 --- a/cli/lsp/sources.rs +++ b/cli/lsp/sources.rs @@ -13,11 +13,11 @@ use crate::file_fetcher::SUPPORTED_SCHEMES; use crate::flags::Flags; use crate::http_cache; use crate::http_cache::HttpCache; -use crate::import_map::ImportMap; use crate::module_graph::GraphBuilder; use crate::program_state::ProgramState; use crate::specifier_handler::FetchHandler; use crate::text_encoding; +use import_map::ImportMap; use deno_ast::MediaType; use deno_core::error::anyhow; diff --git a/cli/main.rs b/cli/main.rs index 985bf68dd0..f988728c42 100644 --- a/cli/main.rs +++ b/cli/main.rs @@ -18,7 +18,6 @@ mod fmt_errors; mod fs_util; mod http_cache; mod http_util; -mod import_map; mod info; mod lockfile; mod logger; diff --git a/cli/module_graph.rs b/cli/module_graph.rs index c88f2af57d..00301e6bbc 100644 --- a/cli/module_graph.rs +++ b/cli/module_graph.rs @@ -11,8 +11,6 @@ use crate::config_file::ConfigFile; use crate::config_file::IgnoredCompilerOptions; use crate::config_file::TsConfig; use crate::diagnostics::Diagnostics; -use crate::import_map::ImportMap; -use crate::import_map::ImportMapError; use crate::info; use crate::lockfile::Lockfile; use crate::specifier_handler::CachedModule; @@ -51,6 +49,8 @@ use deno_core::ModuleResolutionError; use deno_core::ModuleSource; use deno_core::ModuleSpecifier; use deno_graph::analyze_dependencies; +use import_map::ImportMap; +use import_map::ImportMapError; use log::debug; use regex::Regex; use std::collections::HashMap; diff --git a/cli/module_loader.rs b/cli/module_loader.rs index 349e72393e..575919495d 100644 --- a/cli/module_loader.rs +++ b/cli/module_loader.rs @@ -1,6 +1,5 @@ // Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -use crate::import_map::ImportMap; use crate::module_graph::TypeLib; use crate::program_state::ProgramState; use deno_core::error::AnyError; @@ -11,6 +10,7 @@ use deno_core::ModuleLoader; use deno_core::ModuleSpecifier; use deno_core::OpState; use deno_runtime::permissions::Permissions; +use import_map::ImportMap; use std::cell::RefCell; use std::pin::Pin; use std::rc::Rc; diff --git a/cli/ops/runtime_compiler.rs b/cli/ops/runtime_compiler.rs index 3965016dcf..01bfa3ad58 100644 --- a/cli/ops/runtime_compiler.rs +++ b/cli/ops/runtime_compiler.rs @@ -1,6 +1,5 @@ // Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -use crate::import_map::ImportMap; use crate::module_graph::BundleType; use crate::module_graph::EmitOptions; use crate::module_graph::GraphBuilder; @@ -20,6 +19,7 @@ use deno_core::serde_json::json; use deno_core::serde_json::Value; use deno_core::OpState; use deno_runtime::permissions::Permissions; +use import_map::ImportMap; use serde::Deserialize; use std::cell::RefCell; use std::collections::HashMap; diff --git a/cli/program_state.rs b/cli/program_state.rs index 089f2b8639..6b723ca3d1 100644 --- a/cli/program_state.rs +++ b/cli/program_state.rs @@ -7,7 +7,6 @@ use crate::file_fetcher::CacheSetting; use crate::file_fetcher::FileFetcher; use crate::flags; use crate::http_cache; -use crate::import_map::ImportMap; use crate::lockfile::Lockfile; use crate::module_graph::CheckOptions; use crate::module_graph::GraphBuilder; @@ -16,11 +15,6 @@ use crate::module_graph::TypeLib; use crate::source_maps::SourceMapGetter; use crate::specifier_handler::FetchHandler; use crate::version; -use deno_core::SharedArrayBufferStore; -use deno_runtime::deno_broadcast_channel::InMemoryBroadcastChannel; -use deno_runtime::deno_web::BlobStore; -use deno_runtime::inspector_server::InspectorServer; -use deno_runtime::permissions::Permissions; use deno_core::error::anyhow; use deno_core::error::get_custom_error_class; @@ -31,9 +25,15 @@ use deno_core::resolve_url; use deno_core::url::Url; use deno_core::ModuleSource; use deno_core::ModuleSpecifier; +use deno_core::SharedArrayBufferStore; +use deno_runtime::deno_broadcast_channel::InMemoryBroadcastChannel; +use deno_runtime::deno_web::BlobStore; +use deno_runtime::inspector_server::InspectorServer; +use deno_runtime::permissions::Permissions; use deno_tls::rustls::RootCertStore; use deno_tls::rustls_native_certs::load_native_certs; use deno_tls::webpki_roots::TLS_SERVER_ROOTS; +use import_map::ImportMap; use log::debug; use log::warn; use std::collections::HashMap; diff --git a/cli/tools/doc.rs b/cli/tools/doc.rs index cde601f1a2..a02c858f05 100644 --- a/cli/tools/doc.rs +++ b/cli/tools/doc.rs @@ -4,7 +4,6 @@ use crate::colors; use crate::file_fetcher::File; use crate::flags::Flags; use crate::get_types; -use crate::import_map::ImportMap; use crate::program_state::ProgramState; use crate::write_json_to_stdout; use crate::write_to_stdout_ignore_sigpipe; @@ -21,6 +20,7 @@ use deno_graph::source::Loader; use deno_graph::source::Resolver; use deno_graph::ModuleSpecifier; use deno_runtime::permissions::Permissions; +use import_map::ImportMap; use std::path::PathBuf; use std::sync::Arc;