summaryrefslogtreecommitdiff
path: root/cli
diff options
context:
space:
mode:
authorDavid Sherret <dsherret@users.noreply.github.com>2023-09-07 08:09:16 -0500
committerGitHub <noreply@github.com>2023-09-07 09:09:16 -0400
commit3fc19dab47492e06043fc7add28e64693a4eb775 (patch)
tree855e952933662aef37bd20c084901ae0e488b2db /cli
parent01a761f1d4f7ff4943fbf80464a276b434d8a8f7 (diff)
feat: support import attributes (#20342)
Diffstat (limited to 'cli')
-rw-r--r--cli/Cargo.toml14
-rw-r--r--cli/bench/deno_common.js2
-rw-r--r--cli/cache/mod.rs75
-rw-r--r--cli/cache/parsed_source.rs12
-rw-r--r--cli/errors.rs9
-rw-r--r--cli/file_fetcher.rs75
-rw-r--r--cli/graph_util.rs48
-rw-r--r--cli/lsp/diagnostics.rs37
-rw-r--r--cli/lsp/documents.rs52
-rw-r--r--cli/lsp/registries.rs10
-rw-r--r--cli/module_loader.rs2
-rw-r--r--cli/resolver.rs12
-rw-r--r--cli/tests/integration/lsp_tests.rs18
-rw-r--r--cli/tests/integration/run_tests.rs44
-rw-r--r--cli/tests/testdata/import_assertions/dynamic_import.ts3
-rw-r--r--cli/tests/testdata/import_assertions/static_import.ts3
-rw-r--r--cli/tests/testdata/import_assertions/type_check.out5
-rw-r--r--cli/tests/testdata/import_assertions/type_check.ts3
-rw-r--r--cli/tests/testdata/import_attributes/data.json (renamed from cli/tests/testdata/import_assertions/data.json)0
-rw-r--r--cli/tests/testdata/import_attributes/dynamic_error.out (renamed from cli/tests/testdata/import_assertions/dynamic_error.out)0
-rw-r--r--cli/tests/testdata/import_attributes/dynamic_error.ts (renamed from cli/tests/testdata/import_assertions/dynamic_error.ts)0
-rw-r--r--cli/tests/testdata/import_attributes/dynamic_import.out (renamed from cli/tests/testdata/import_assertions/dynamic_import.out)1
-rw-r--r--cli/tests/testdata/import_attributes/dynamic_import.ts5
-rw-r--r--cli/tests/testdata/import_attributes/json_with_shebang.json (renamed from cli/tests/testdata/import_assertions/json_with_shebang.json)0
-rw-r--r--cli/tests/testdata/import_attributes/json_with_shebang.ts (renamed from cli/tests/testdata/import_assertions/json_with_shebang.ts)0
-rw-r--r--cli/tests/testdata/import_attributes/json_with_shebang.ts.out (renamed from cli/tests/testdata/import_assertions/json_with_shebang.ts.out)0
-rw-r--r--cli/tests/testdata/import_attributes/static_error.out (renamed from cli/tests/testdata/import_assertions/static_error.out)2
-rw-r--r--cli/tests/testdata/import_attributes/static_error.ts (renamed from cli/tests/testdata/import_assertions/static_error.ts)0
-rw-r--r--cli/tests/testdata/import_attributes/static_export.out (renamed from cli/tests/testdata/import_assertions/static_export.out)0
-rw-r--r--cli/tests/testdata/import_attributes/static_export.ts (renamed from cli/tests/testdata/import_assertions/static_export.ts)0
-rw-r--r--cli/tests/testdata/import_attributes/static_import.out (renamed from cli/tests/testdata/import_assertions/static_import.out)1
-rw-r--r--cli/tests/testdata/import_attributes/static_import.ts5
-rw-r--r--cli/tests/testdata/import_attributes/static_reexport.ts (renamed from cli/tests/testdata/import_assertions/static_reexport.ts)0
-rw-r--r--cli/tests/testdata/import_attributes/type_check.out12
-rw-r--r--cli/tests/testdata/import_attributes/type_check.ts5
-rw-r--r--cli/tests/testdata/run/020_json_modules.ts.out2
-rw-r--r--cli/tools/info.rs12
-rw-r--r--cli/tools/vendor/test.rs1
-rw-r--r--cli/tsc/00_typescript.js9
-rw-r--r--cli/tsc/dts/lib.es5.d.ts1
-rw-r--r--cli/tsc/mod.rs1
41 files changed, 355 insertions, 126 deletions
diff --git a/cli/Cargo.toml b/cli/Cargo.toml
index cf9717a66..a820b9894 100644
--- a/cli/Cargo.toml
+++ b/cli/Cargo.toml
@@ -46,19 +46,19 @@ winres.workspace = true
[dependencies]
deno_ast = { workspace = true, features = ["bundler", "cjs", "codegen", "dep_graph", "module_specifier", "proposal", "react", "sourcemap", "transforms", "typescript", "view", "visit"] }
-deno_cache_dir = "=0.5.2"
+deno_cache_dir = "=0.6.0"
deno_config = "=0.2.4"
deno_core = { workspace = true, features = ["include_js_files_for_snapshotting"] }
-deno_doc = "=0.65.0"
-deno_emit = "=0.26.0"
-deno_graph = "=0.52.0"
-deno_lint = { version = "=0.50.2", features = ["docs"] }
+deno_doc = "=0.66.0"
+deno_emit = "=0.27.0"
+deno_graph = "=0.54.0"
+deno_lint = { version = "=0.51.0", features = ["docs"] }
deno_lockfile.workspace = true
deno_npm.workspace = true
deno_runtime = { workspace = true, features = ["dont_create_runtime_snapshot", "exclude_runtime_main_js", "include_js_files_for_snapshotting"] }
deno_semver.workspace = true
deno_task_shell = "=0.13.2"
-eszip = "=0.50.1"
+eszip = "=0.51.0"
napi_sym.workspace = true
async-trait.workspace = true
@@ -75,7 +75,7 @@ data-url.workspace = true
dissimilar = "=1.0.4"
dprint-plugin-json = "=0.17.4"
dprint-plugin-markdown = "=0.16.0"
-dprint-plugin-typescript = "=0.86.2"
+dprint-plugin-typescript = "=0.87.1"
encoding_rs.workspace = true
env_logger = "=0.10.0"
fancy-regex = "=0.10.0"
diff --git a/cli/bench/deno_common.js b/cli/bench/deno_common.js
index 31ab05fba..210733c1a 100644
--- a/cli/bench/deno_common.js
+++ b/cli/bench/deno_common.js
@@ -7,7 +7,6 @@ Deno.bench("date_now", { n: 5e5 }, () => {
// Fast API calls
{
- // deno-lint-ignore camelcase
const { op_add } = Deno[Deno.internal].core.ops;
// deno-lint-ignore no-inner-declarations
function add(a, b) {
@@ -21,7 +20,6 @@ Deno.bench("date_now", { n: 5e5 }, () => {
Deno.bench("add_js", () => addJS(1, 2));
}
-// deno-lint-ignore camelcase
const { op_void_sync } = Deno[Deno.internal].core.ops;
function sync() {
return op_void_sync();
diff --git a/cli/cache/mod.rs b/cli/cache/mod.rs
index f75761521..58d4679d1 100644
--- a/cli/cache/mod.rs
+++ b/cli/cache/mod.rs
@@ -1,17 +1,22 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
+use crate::args::CacheSetting;
use crate::errors::get_error_class_name;
+use crate::file_fetcher::FetchOptions;
use crate::file_fetcher::FileFetcher;
use crate::util::fs::atomic_write_file;
+use deno_ast::MediaType;
use deno_core::futures;
use deno_core::futures::FutureExt;
+use deno_core::url::Url;
use deno_core::ModuleSpecifier;
use deno_graph::source::CacheInfo;
use deno_graph::source::LoadFuture;
use deno_graph::source::LoadResponse;
use deno_graph::source::Loader;
use deno_runtime::permissions::PermissionsContainer;
+use once_cell::sync::Lazy;
use std::collections::HashMap;
use std::path::Path;
use std::path::PathBuf;
@@ -96,6 +101,7 @@ pub struct FetchCacher {
file_fetcher: Arc<FileFetcher>,
file_header_overrides: HashMap<ModuleSpecifier, HashMap<String, String>>,
global_http_cache: Arc<GlobalHttpCache>,
+ parsed_source_cache: Arc<ParsedSourceCache>,
permissions: PermissionsContainer,
cache_info_enabled: bool,
maybe_local_node_modules_url: Option<ModuleSpecifier>,
@@ -107,6 +113,7 @@ impl FetchCacher {
file_fetcher: Arc<FileFetcher>,
file_header_overrides: HashMap<ModuleSpecifier, HashMap<String, String>>,
global_http_cache: Arc<GlobalHttpCache>,
+ parsed_source_cache: Arc<ParsedSourceCache>,
permissions: PermissionsContainer,
maybe_local_node_modules_url: Option<ModuleSpecifier>,
) -> Self {
@@ -115,6 +122,7 @@ impl FetchCacher {
file_fetcher,
file_header_overrides,
global_http_cache,
+ parsed_source_cache,
permissions,
cache_info_enabled: false,
maybe_local_node_modules_url,
@@ -153,7 +161,29 @@ impl FetchCacher {
}
}
+static DENO_REGISTRY_URL: Lazy<Url> = Lazy::new(|| {
+ let env_var_name = "DENO_REGISTRY_URL";
+ if let Ok(registry_url) = std::env::var(env_var_name) {
+ // ensure there is a trailing slash for the directory
+ let registry_url = format!("{}/", registry_url.trim_end_matches('/'));
+ match Url::parse(&registry_url) {
+ Ok(url) => {
+ return url;
+ }
+ Err(err) => {
+ log::debug!("Invalid {} environment variable: {:#}", env_var_name, err,);
+ }
+ }
+ }
+
+ deno_graph::source::DEFAULT_DENO_REGISTRY_URL.clone()
+});
+
impl Loader for FetchCacher {
+ fn registry_url(&self) -> &Url {
+ &DENO_REGISTRY_URL
+ }
+
fn get_cache_info(&self, specifier: &ModuleSpecifier) -> Option<CacheInfo> {
if !self.cache_info_enabled {
return None;
@@ -180,7 +210,10 @@ impl Loader for FetchCacher {
&mut self,
specifier: &ModuleSpecifier,
_is_dynamic: bool,
+ cache_setting: deno_graph::source::CacheSetting,
) -> LoadFuture {
+ use deno_graph::source::CacheSetting as LoaderCacheSetting;
+
if let Some(node_modules_url) = self.maybe_local_node_modules_url.as_ref() {
// The specifier might be in a completely different symlinked tree than
// what the resolved node_modules_url is in (ex. `/my-project-1/node_modules`
@@ -198,14 +231,31 @@ impl Loader for FetchCacher {
}
}
- let permissions = self.permissions.clone();
let file_fetcher = self.file_fetcher.clone();
let file_header_overrides = self.file_header_overrides.clone();
+ let permissions = self.permissions.clone();
let specifier = specifier.clone();
async move {
+ let maybe_cache_setting = match cache_setting {
+ LoaderCacheSetting::Use => None,
+ LoaderCacheSetting::Reload => {
+ if matches!(file_fetcher.cache_setting(), CacheSetting::Only) {
+ return Err(deno_core::anyhow::anyhow!(
+ "Failed to resolve version constraint. Try running again without --cached-only"
+ ));
+ }
+ Some(CacheSetting::ReloadAll)
+ }
+ LoaderCacheSetting::Only => Some(CacheSetting::Only),
+ };
file_fetcher
- .fetch(&specifier, permissions)
+ .fetch_with_options(FetchOptions {
+ specifier: &specifier,
+ permissions,
+ maybe_accept: None,
+ maybe_cache_setting: maybe_cache_setting.as_ref(),
+ })
.await
.map(|file| {
let maybe_headers =
@@ -236,4 +286,25 @@ impl Loader for FetchCacher {
}
.boxed()
}
+
+ fn cache_module_info(
+ &mut self,
+ specifier: &ModuleSpecifier,
+ source: &str,
+ module_info: &deno_graph::ModuleInfo,
+ ) {
+ let result = self.parsed_source_cache.cache_module_info(
+ specifier,
+ MediaType::from_specifier(specifier),
+ source,
+ module_info,
+ );
+ if let Err(err) = result {
+ log::debug!(
+ "Error saving module cache info for {}. {:#}",
+ specifier,
+ err
+ );
+ }
+ }
}
diff --git a/cli/cache/parsed_source.rs b/cli/cache/parsed_source.rs
index e231753d5..68503e6aa 100644
--- a/cli/cache/parsed_source.rs
+++ b/cli/cache/parsed_source.rs
@@ -135,6 +135,18 @@ impl ParsedSourceCache {
pub fn as_capturing_parser(&self) -> CapturingModuleParser {
CapturingModuleParser::new(None, &self.sources)
}
+
+ pub fn cache_module_info(
+ &self,
+ specifier: &ModuleSpecifier,
+ media_type: MediaType,
+ source: &str,
+ module_info: &ModuleInfo,
+ ) -> Result<(), AnyError> {
+ let source_hash = compute_source_hash(source.as_bytes());
+ ParsedSourceCacheModuleAnalyzer::new(self.db.clone(), self.sources.clone())
+ .set_module_info(specifier, media_type, &source_hash, module_info)
+ }
}
struct ParsedSourceCacheModuleAnalyzer {
diff --git a/cli/errors.rs b/cli/errors.rs
index 2ffad73b3..4ea0e000a 100644
--- a/cli/errors.rs
+++ b/cli/errors.rs
@@ -31,10 +31,11 @@ fn get_module_graph_error_class(err: &ModuleGraphError) -> &'static str {
ModuleError::InvalidTypeAssertion { .. } => "SyntaxError",
ModuleError::ParseErr(_, diagnostic) => get_diagnostic_class(diagnostic),
ModuleError::UnsupportedMediaType { .. }
- | ModuleError::UnsupportedImportAssertionType { .. } => "TypeError",
- ModuleError::Missing(_, _) | ModuleError::MissingDynamic(_, _) => {
- "NotFound"
- }
+ | ModuleError::UnsupportedImportAttributeType { .. } => "TypeError",
+ ModuleError::Missing(_, _)
+ | ModuleError::MissingDynamic(_, _)
+ | ModuleError::UnknownPackage { .. }
+ | ModuleError::UnknownPackageReq { .. } => "NotFound",
},
ModuleGraphError::ResolutionError(err) => get_resolution_error_class(err),
}
diff --git a/cli/file_fetcher.rs b/cli/file_fetcher.rs
index e486eda88..ae5cf2762 100644
--- a/cli/file_fetcher.rs
+++ b/cli/file_fetcher.rs
@@ -163,6 +163,13 @@ pub fn map_content_type(
}
}
+pub struct FetchOptions<'a> {
+ pub specifier: &'a ModuleSpecifier,
+ pub permissions: PermissionsContainer,
+ pub maybe_accept: Option<&'a str>,
+ pub maybe_cache_setting: Option<&'a CacheSetting>,
+}
+
/// A structure for resolving, fetching and caching source files.
#[derive(Debug, Clone)]
pub struct FileFetcher {
@@ -199,6 +206,10 @@ impl FileFetcher {
}
}
+ pub fn cache_setting(&self) -> &CacheSetting {
+ &self.cache_setting
+ }
+
/// Sets the log level to use when outputting the download message.
pub fn set_download_log_level(&mut self, level: log::Level) {
self.download_log_level = level;
@@ -328,6 +339,7 @@ impl FileFetcher {
permissions: PermissionsContainer,
redirect_limit: i64,
maybe_accept: Option<String>,
+ cache_setting: &CacheSetting,
) -> Pin<Box<dyn Future<Output = Result<File, AnyError>> + Send>> {
debug!("FileFetcher::fetch_remote() - specifier: {}", specifier);
if redirect_limit < 0 {
@@ -339,7 +351,7 @@ impl FileFetcher {
return futures::future::err(err).boxed();
}
- if self.should_use_cache(specifier) {
+ if self.should_use_cache(specifier, cache_setting) {
match self.fetch_cached(specifier, redirect_limit) {
Ok(Some(file)) => {
return futures::future::ok(file).boxed();
@@ -351,7 +363,7 @@ impl FileFetcher {
}
}
- if self.cache_setting == CacheSetting::Only {
+ if *cache_setting == CacheSetting::Only {
return futures::future::err(custom_error(
"NotCached",
format!(
@@ -383,6 +395,7 @@ impl FileFetcher {
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.
@@ -432,6 +445,7 @@ impl FileFetcher {
permissions,
redirect_limit - 1,
maybe_accept,
+ &cache_setting,
)
.await
}
@@ -468,8 +482,12 @@ impl FileFetcher {
}
/// Returns if the cache should be used for a given specifier.
- fn should_use_cache(&self, specifier: &ModuleSpecifier) -> bool {
- match &self.cache_setting {
+ fn should_use_cache(
+ &self,
+ specifier: &ModuleSpecifier,
+ cache_setting: &CacheSetting,
+ ) -> bool {
+ match cache_setting {
CacheSetting::ReloadAll => false,
CacheSetting::Use | CacheSetting::Only => true,
CacheSetting::RespectHeaders => {
@@ -514,18 +532,24 @@ impl FileFetcher {
specifier: &ModuleSpecifier,
permissions: PermissionsContainer,
) -> Result<File, AnyError> {
- debug!("FileFetcher::fetch() - specifier: {}", specifier);
- self.fetch_with_accept(specifier, permissions, None).await
+ self
+ .fetch_with_options(FetchOptions {
+ specifier,
+ permissions,
+ maybe_accept: None,
+ maybe_cache_setting: None,
+ })
+ .await
}
- pub async fn fetch_with_accept(
+ pub async fn fetch_with_options(
&self,
- specifier: &ModuleSpecifier,
- permissions: PermissionsContainer,
- maybe_accept: Option<&str>,
+ options: FetchOptions<'_>,
) -> Result<File, AnyError> {
+ let specifier = options.specifier;
+ debug!("FileFetcher::fetch() - specifier: {}", specifier);
let scheme = get_validated_scheme(specifier)?;
- permissions.check_specifier(specifier)?;
+ options.permissions.check_specifier(specifier)?;
if let Some(file) = self.cache.get(specifier) {
Ok(file)
} else if scheme == "file" {
@@ -545,9 +569,10 @@ impl FileFetcher {
let result = self
.fetch_remote(
specifier,
- permissions,
+ options.permissions,
10,
- maybe_accept.map(String::from),
+ options.maybe_accept.map(String::from),
+ options.maybe_cache_setting.unwrap_or(&self.cache_setting),
)
.await;
if let Ok(file) = &result {
@@ -764,7 +789,13 @@ mod tests {
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(), 1, None)
+ .fetch_remote(
+ specifier,
+ PermissionsContainer::allow_all(),
+ 1,
+ None,
+ &file_fetcher.cache_setting,
+ )
.await;
let cache_key = file_fetcher.http_cache.cache_item_key(specifier).unwrap();
(
@@ -1452,12 +1483,24 @@ mod tests {
.unwrap();
let result = file_fetcher
- .fetch_remote(&specifier, PermissionsContainer::allow_all(), 2, None)
+ .fetch_remote(
+ &specifier,
+ PermissionsContainer::allow_all(),
+ 2,
+ None,
+ &file_fetcher.cache_setting,
+ )
.await;
assert!(result.is_ok());
let result = file_fetcher
- .fetch_remote(&specifier, PermissionsContainer::allow_all(), 1, None)
+ .fetch_remote(
+ &specifier,
+ PermissionsContainer::allow_all(),
+ 1,
+ None,
+ &file_fetcher.cache_setting,
+ )
.await;
assert!(result.is_err());
diff --git a/cli/graph_util.rs b/cli/graph_util.rs
index fc530032a..6fb4b7790 100644
--- a/cli/graph_util.rs
+++ b/cli/graph_util.rs
@@ -237,6 +237,8 @@ impl ModuleGraphBuilder {
npm_resolver: Some(graph_npm_resolver),
module_analyzer: Some(&*analyzer),
reporter: maybe_file_watcher_reporter,
+ // todo(dsherret): workspace support
+ workspace_members: vec![],
},
)
.await?;
@@ -280,6 +282,8 @@ impl ModuleGraphBuilder {
npm_resolver: Some(graph_npm_resolver),
module_analyzer: Some(&*analyzer),
reporter: maybe_file_watcher_reporter,
+ // todo(dsherret): workspace support
+ workspace_members: vec![],
},
)
.await?;
@@ -338,15 +342,35 @@ impl ModuleGraphBuilder {
}
}
+ // todo(dsherret): uncomment when adding deno: specifier support
+ // add the deno specifiers to the graph if it's the first time executing
+ // if graph.deno_specifiers.is_empty() {
+ // if let Some(lockfile) = &self.lockfile {
+ // let lockfile = lockfile.lock();
+ // for (key, value) in &lockfile.content.packages.specifiers {
+ // if let Some(key) = key
+ // .strip_prefix("deno:")
+ // .and_then(|key| PackageReq::from_str(key))
+ // {
+ // if let Ok(value) = value
+ // .strip_prefix("deno:")
+ // .and_then(|value| PackageNv::from_str(value))
+ // {
+ // graph.deno_specifiers.add(key, value);
+ // }
+ // }
+ // }
+ // }
+ // }
+
graph.build(roots, loader, options).await;
// add the redirects in the graph to the lockfile
if !graph.redirects.is_empty() {
if let Some(lockfile) = &self.lockfile {
- let graph_redirects = graph
- .redirects
- .iter()
- .filter(|(from, _)| !matches!(from.scheme(), "npm" | "file"));
+ let graph_redirects = graph.redirects.iter().filter(|(from, _)| {
+ !matches!(from.scheme(), "npm" | "file" | "deno")
+ });
let mut lockfile = lockfile.lock();
for (from, to) in graph_redirects {
lockfile.insert_redirect(from.to_string(), to.to_string());
@@ -354,6 +378,21 @@ impl ModuleGraphBuilder {
}
}
+ // todo(dsherret): uncomment when adding support for deno specifiers
+ // add the deno specifiers in the graph to the lockfile
+ // if !graph.deno_specifiers.is_empty() {
+ // if let Some(lockfile) = &self.lockfile {
+ // let mappings = graph.deno_specifiers.mappings();
+ // let mut lockfile = lockfile.lock();
+ // for (from, to) in mappings {
+ // lockfile.insert_package_specifier(
+ // format!("deno:{}", from),
+ // format!("deno:{}", to),
+ // );
+ // }
+ // }
+ // }
+
// ensure that the top level package.json is installed if a
// specifier was matched in the package.json
self
@@ -382,6 +421,7 @@ impl ModuleGraphBuilder {
self.file_fetcher.clone(),
self.options.resolve_file_header_overrides(),
self.global_http_cache.clone(),
+ self.parsed_source_cache.clone(),
permissions,
self.options.node_modules_dir_specifier(),
)
diff --git a/cli/lsp/diagnostics.rs b/cli/lsp/diagnostics.rs
index 0bee08c1d..fd4142fd9 100644
--- a/cli/lsp/diagnostics.rs
+++ b/cli/lsp/diagnostics.rs
@@ -871,9 +871,9 @@ pub enum DenoDiagnostic {
/// remapped to an import map import specifier.
ImportMapRemap { from: String, to: String },
/// The import assertion type is incorrect.
- InvalidAssertType(String),
- /// A module requires an assertion type to be a valid import.
- NoAssertType,
+ InvalidAttributeType(String),
+ /// A module requires an attribute type to be a valid import.
+ NoAttributeType,
/// A remote module was not found in the cache.
NoCache(ModuleSpecifier),
/// A remote npm package reference was not found in the cache.
@@ -897,8 +897,8 @@ impl DenoDiagnostic {
match self {
Self::DenoWarn(_) => "deno-warn",
Self::ImportMapRemap { .. } => "import-map-remap",
- Self::InvalidAssertType(_) => "invalid-assert-type",
- Self::NoAssertType => "no-assert-type",
+ Self::InvalidAttributeType(_) => "invalid-attribute-type",
+ Self::NoAttributeType => "no-attribute-type",
Self::NoCache(_) => "no-cache",
Self::NoCacheNpm(_, _) => "no-cache-npm",
Self::NoLocal(_) => "no-local",
@@ -958,15 +958,15 @@ impl DenoDiagnostic {
..Default::default()
}
}
- "no-assert-type" => lsp::CodeAction {
- title: "Insert import assertion.".to_string(),
+ "no-attribute-type" => lsp::CodeAction {
+ title: "Insert import attribute.".to_string(),
kind: Some(lsp::CodeActionKind::QUICKFIX),
diagnostics: Some(vec![diagnostic.clone()]),
edit: Some(lsp::WorkspaceEdit {
changes: Some(HashMap::from([(
specifier.clone(),
vec![lsp::TextEdit {
- new_text: " assert { type: \"json\" }".to_string(),
+ new_text: " with { type: \"json\" }".to_string(),
range: lsp::Range {
start: diagnostic.range.end,
end: diagnostic.range.end,
@@ -1069,7 +1069,7 @@ impl DenoDiagnostic {
"import-map-remap"
| "no-cache"
| "no-cache-npm"
- | "no-assert-type"
+ | "no-attribute-type"
| "redirect"
| "import-node-prefix-missing"
)
@@ -1084,8 +1084,8 @@ impl DenoDiagnostic {
let (severity, message, data) = match self {
Self::DenoWarn(message) => (lsp::DiagnosticSeverity::WARNING, message.to_string(), None),
Self::ImportMapRemap { from, to } => (lsp::DiagnosticSeverity::HINT, format!("The import specifier can be remapped to \"{to}\" which will resolve it via the active import map."), Some(json!({ "from": from, "to": to }))),
- Self::InvalidAssertType(assert_type) => (lsp::DiagnosticSeverity::ERROR, format!("The module is a JSON module and expected an assertion type of \"json\". Instead got \"{assert_type}\"."), None),
- Self::NoAssertType => (lsp::DiagnosticSeverity::ERROR, "The module is a JSON module and not being imported with an import assertion. Consider adding `assert { type: \"json\" }` to the import statement.".to_string(), None),
+ Self::InvalidAttributeType(assert_type) => (lsp::DiagnosticSeverity::ERROR, format!("The module is a JSON module and expected an attribute type of \"json\". Instead got \"{assert_type}\"."), None),
+ Self::NoAttributeType => (lsp::DiagnosticSeverity::ERROR, "The module is a JSON module and not being imported with an import attribute. Consider adding `with { type: \"json\" }` to the import statement.".to_string(), None),
Self::NoCache(specifier) => (lsp::DiagnosticSeverity::ERROR, format!("Uncached or missing remote URL: {specifier}"), Some(json!({ "specifier": specifier }))),
Self::NoCacheNpm(pkg_req, specifier) => (lsp::DiagnosticSeverity::ERROR, format!("Uncached or missing npm package: {}", pkg_req), Some(json!({ "specifier": specifier }))),
Self::NoLocal(specifier) => (lsp::DiagnosticSeverity::ERROR, format!("Unable to load a local module: {specifier}\n Please check the file path."), None),
@@ -1144,15 +1144,16 @@ fn diagnose_resolution(
match maybe_assert_type {
// The module has the correct assertion type, no diagnostic
Some("json") => (),
- // The dynamic import statement is missing an assertion type, which
+ // The dynamic import statement is missing an attribute type, which
// we might not be able to statically detect, therefore we will
// not provide a potentially incorrect diagnostic.
None if is_dynamic => (),
// The module has an incorrect assertion type, diagnostic
- Some(assert_type) => diagnostics
- .push(DenoDiagnostic::InvalidAssertType(assert_type.to_string())),
- // The module is missing an assertion type, diagnostic
- None => diagnostics.push(DenoDiagnostic::NoAssertType),
+ Some(assert_type) => diagnostics.push(
+ DenoDiagnostic::InvalidAttributeType(assert_type.to_string()),
+ ),
+ // The module is missing an attribute type, diagnostic
+ None => diagnostics.push(DenoDiagnostic::NoAttributeType),
}
}
} else if let Ok(pkg_ref) =
@@ -1249,7 +1250,7 @@ fn diagnose_dependency(
&dependency.maybe_code
},
dependency.is_dynamic,
- dependency.maybe_assert_type.as_deref(),
+ dependency.maybe_attribute_type.as_deref(),
)
.iter()
.flat_map(|diag| {
@@ -1278,7 +1279,7 @@ fn diagnose_dependency(
snapshot,
&dependency.maybe_type,
dependency.is_dynamic,
- dependency.maybe_assert_type.as_deref(),
+ dependency.maybe_attribute_type.as_deref(),
)
.iter()
.map(|diag| diag.to_lsp_diagnostic(&range)),
diff --git a/cli/lsp/documents.rs b/cli/lsp/documents.rs
index 9c6710714..388f9f2e5 100644
--- a/cli/lsp/documents.rs
+++ b/cli/lsp/documents.rs
@@ -32,6 +32,7 @@ use deno_ast::SourceTextInfo;
use deno_core::error::custom_error;
use deno_core::error::AnyError;
use deno_core::futures::future;
+use deno_core::futures::FutureExt;
use deno_core::parking_lot::Mutex;
use deno_core::url;
use deno_core::ModuleSpecifier;
@@ -45,7 +46,7 @@ use deno_runtime::deno_node::PackageJson;
use deno_runtime::permissions::PermissionsContainer;
use deno_semver::npm::NpmPackageReqReference;
use deno_semver::package::PackageReq;
-use indexmap1::IndexMap;
+use indexmap::IndexMap;
use lsp::Url;
use once_cell::sync::Lazy;
use package_json::PackageJsonDepsProvider;
@@ -1551,24 +1552,53 @@ pub struct OpenDocumentsGraphLoader<'a> {
pub open_docs: &'a HashMap<ModuleSpecifier, Document>,
}
-impl<'a> deno_graph::source::Loader for OpenDocumentsGraphLoader<'a> {
- fn load(
- &mut self,
+impl<'a> OpenDocumentsGraphLoader<'a> {
+ fn load_from_docs(
+ &self,
specifier: &ModuleSpecifier,
- is_dynamic: bool,
- ) -> deno_graph::source::LoadFuture {
+ ) -> Option<deno_graph::source::LoadFuture> {
if specifier.scheme() == "file" {
if let Some(doc) = self.open_docs.get(specifier) {
- return Box::pin(future::ready(Ok(Some(
- deno_graph::source::LoadResponse::Module {
+ return Some(
+ future::ready(Ok(Some(deno_graph::source::LoadResponse::Module {
content: doc.content(),
specifier: doc.specifier().clone(),
maybe_headers: None,
- },
- ))));
+ })))
+ .boxed_local(),
+ );
}
}
- self.inner_loader.load(specifier, is_dynamic)
+ None
+ }
+}
+
+impl<'a> deno_graph::source::Loader for OpenDocumentsGraphLoader<'a> {
+ fn registry_url(&self) -> &Url {
+ self.inner_loader.registry_url()
+ }
+
+ fn load(
+ &mut self,
+ specifier: &ModuleSpecifier,
+ is_dynamic: bool,
+ cache_setting: deno_graph::source::CacheSetting,
+ ) -> deno_graph::source::LoadFuture {
+ match self.load_from_docs(specifier) {
+ Some(fut) => fut,
+ None => self.inner_loader.load(specifier, is_dynamic, cache_setting),
+ }
+ }
+
+ fn cache_module_info(
+ &mut self,
+ specifier: &deno_ast::ModuleSpecifier,
+ source: &str,
+ module_info: &deno_graph::ModuleInfo,
+ ) {
+ self
+ .inner_loader
+ .cache_module_info(specifier, source, module_info)
}
}
diff --git a/cli/lsp/registries.rs b/cli/lsp/registries.rs
index d2044ae66..ea33219e8 100644
--- a/cli/lsp/registries.rs
+++ b/cli/lsp/registries.rs
@@ -15,6 +15,7 @@ use super::path_to_regex::Token;
use crate::args::CacheSetting;
use crate::cache::GlobalHttpCache;
use crate::cache::HttpCache;
+use crate::file_fetcher::FetchOptions;
use crate::file_fetcher::FileFetcher;
use crate::http_util::HttpClient;
@@ -509,11 +510,12 @@ impl ModuleRegistry {
) -> Result<Vec<RegistryConfiguration>, AnyError> {
let fetch_result = self
.file_fetcher
- .fetch_with_accept(
+ .fetch_with_options(FetchOptions {
specifier,
- PermissionsContainer::allow_all(),
- Some("application/vnd.deno.reg.v2+json, application/vnd.deno.reg.v1+json;q=0.9, application/json;q=0.8"),
- )
+ 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,
+ })
.await;
// if there is an error fetching, we will cache an empty file, so that
// subsequent requests they are just an empty doc which will error without
diff --git a/cli/module_loader.rs b/cli/module_loader.rs
index 608ee855b..67811304b 100644
--- a/cli/module_loader.rs
+++ b/cli/module_loader.rs
@@ -145,6 +145,8 @@ impl ModuleLoadPreparer {
npm_resolver: Some(graph_npm_resolver),
module_analyzer: Some(&*analyzer),
reporter: maybe_file_watcher_reporter,
+ // todo(dsherret): workspace support
+ workspace_members: vec![],
},
)
.await?;
diff --git a/cli/resolver.rs b/cli/resolver.rs
index dfa709bcb..4fb912731 100644
--- a/cli/resolver.rs
+++ b/cli/resolver.rs
@@ -8,8 +8,8 @@ use deno_core::futures::future::LocalBoxFuture;
use deno_core::futures::FutureExt;
use deno_core::ModuleSpecifier;
use deno_core::TaskQueue;
+use deno_graph::source::NpmPackageReqResolution;
use deno_graph::source::NpmResolver;
-use deno_graph::source::PackageReqResolution;
use deno_graph::source::Resolver;
use deno_graph::source::UnknownBuiltInNodeModuleError;
use deno_graph::source::DEFAULT_JSX_IMPORT_SOURCE_MODULE;
@@ -333,9 +333,9 @@ impl NpmResolver for CliGraphResolver {
.boxed()
}
- fn resolve_npm(&self, package_req: &PackageReq) -> PackageReqResolution {
+ fn resolve_npm(&self, package_req: &PackageReq) -> NpmPackageReqResolution {
if self.no_npm {
- return PackageReqResolution::Err(anyhow!(
+ return NpmPackageReqResolution::Err(anyhow!(
"npm specifiers were requested; but --no-npm is specified"
));
}
@@ -344,13 +344,13 @@ impl NpmResolver for CliGraphResolver {
.npm_resolution
.resolve_package_req_as_pending(package_req);
match result {
- Ok(nv) => PackageReqResolution::Ok(nv),
+ Ok(nv) => NpmPackageReqResolution::Ok(nv),
Err(err) => {
if self.npm_registry_api.mark_force_reload() {
log::debug!("Restarting npm specifier resolution to check for new registry information. Error: {:#}", err);
- PackageReqResolution::ReloadRegistryInfo(err.into())
+ NpmPackageReqResolution::ReloadRegistryInfo(err.into())
} else {
- PackageReqResolution::Err(err.into())
+ NpmPackageReqResolution::Err(err.into())
}
}
}
diff --git a/cli/tests/integration/lsp_tests.rs b/cli/tests/integration/lsp_tests.rs
index c86d30456..2dea05015 100644
--- a/cli/tests/integration/lsp_tests.rs
+++ b/cli/tests/integration/lsp_tests.rs
@@ -760,7 +760,7 @@ fn lsp_deno_task() {
}
#[test]
-fn lsp_import_assertions() {
+fn lsp_import_attributes() {
let context = TestContextBuilder::new().use_temp_cwd().build();
let mut client = context.new_lsp_command().build();
client.initialize(|builder| {
@@ -806,9 +806,9 @@ fn lsp_import_assertions() {
"end": { "line": 0, "character": 27 }
},
"severity": 1,
- "code": "no-assert-type",
+ "code": "no-attribute-type",
"source": "deno",
- "message": "The module is a JSON module and not being imported with an import assertion. Consider adding `assert { type: \"json\" }` to the import statement."
+ "message": "The module is a JSON module and not being imported with an import attribute. Consider adding `with { type: \"json\" }` to the import statement."
}
])
);
@@ -831,9 +831,9 @@ fn lsp_import_assertions() {
"end": { "line": 0, "character": 27 }
},
"severity": 1,
- "code": "no-assert-type",
+ "code": "no-attribute-type",
"source": "deno",
- "message": "The module is a JSON module and not being imported with an import assertion. Consider adding `assert { type: \"json\" }` to the import statement."
+ "message": "The module is a JSON module and not being imported with an import attribute. Consider adding `with { type: \"json\" }` to the import statement."
}],
"only": ["quickfix"]
}
@@ -843,7 +843,7 @@ fn lsp_import_assertions() {
assert_eq!(
res,
json!([{
- "title": "Insert import assertion.",
+ "title": "Insert import attribute.",
"kind": "quickfix",
"diagnostics": [
{
@@ -852,9 +852,9 @@ fn lsp_import_assertions() {
"end": { "line": 0, "character": 27 }
},
"severity": 1,
- "code": "no-assert-type",
+ "code": "no-attribute-type",
"source": "deno",
- "message": "The module is a JSON module and not being imported with an import assertion. Consider adding `assert { type: \"json\" }` to the import statement."
+ "message": "The module is a JSON module and not being imported with an import attribute. Consider adding `with { type: \"json\" }` to the import statement."
}
],
"edit": {
@@ -865,7 +865,7 @@ fn lsp_import_assertions() {
"start": { "line": 0, "character": 27 },
"end": { "line": 0, "character": 27 }
},
- "newText": " assert { type: \"json\" }"
+ "newText": " with { type: \"json\" }"
}
]
}
diff --git a/cli/tests/integration/run_tests.rs b/cli/tests/integration/run_tests.rs
index e7ff19954..dd5b346ae 100644
--- a/cli/tests/integration/run_tests.rs
+++ b/cli/tests/integration/run_tests.rs
@@ -2066,14 +2066,14 @@ itest!(shebang_swc {
});
itest!(shebang_with_json_imports_tsc {
- args: "run --quiet import_assertions/json_with_shebang.ts",
- output: "import_assertions/json_with_shebang.ts.out",
+ args: "run --quiet import_attributes/json_with_shebang.ts",
+ output: "import_attributes/json_with_shebang.ts.out",
exit_code: 1,
});
itest!(shebang_with_json_imports_swc {
- args: "run --quiet --no-check import_assertions/json_with_shebang.ts",
- output: "import_assertions/json_with_shebang.ts.out",
+ args: "run --quiet --no-check import_attributes/json_with_shebang.ts",
+ output: "import_attributes/json_with_shebang.ts.out",
exit_code: 1,
});
@@ -3050,36 +3050,36 @@ itest!(issue_13562 {
output: "run/issue13562.ts.out",
});
-itest!(import_assertions_static_import {
- args: "run --allow-read import_assertions/static_import.ts",
- output: "import_assertions/static_import.out",
+itest!(import_attributes_static_import {
+ args: "run --allow-read import_attributes/static_import.ts",
+ output: "import_attributes/static_import.out",
});
-itest!(import_assertions_static_export {
- args: "run --allow-read import_assertions/static_export.ts",
- output: "import_assertions/static_export.out",
+itest!(import_attributes_static_export {
+ args: "run --allow-read import_attributes/static_export.ts",
+ output: "import_attributes/static_export.out",
});
-itest!(import_assertions_static_error {
- args: "run --allow-read import_assertions/static_error.ts",
- output: "import_assertions/static_error.out",
+itest!(import_attributes_static_error {
+ args: "run --allow-read import_attributes/static_error.ts",
+ output: "import_attributes/static_error.out",
exit_code: 1,
});
-itest!(import_assertions_dynamic_import {
- args: "run --allow-read import_assertions/dynamic_import.ts",
- output: "import_assertions/dynamic_import.out",
+itest!(import_attributes_dynamic_import {
+ args: "run --allow-read --check import_attributes/dynamic_import.ts",
+ output: "import_attributes/dynamic_import.out",
});
-itest!(import_assertions_dynamic_error {
- args: "run --allow-read import_assertions/dynamic_error.ts",
- output: "import_assertions/dynamic_error.out",
+itest!(import_attributes_dynamic_error {
+ args: "run --allow-read import_attributes/dynamic_error.ts",
+ output: "import_attributes/dynamic_error.out",
exit_code: 1,
});
-itest!(import_assertions_type_check {
- args: "run --allow-read --check import_assertions/type_check.ts",
- output: "import_assertions/type_check.out",
+itest!(import_attributes_type_check {
+ args: "run --allow-read --check import_attributes/type_check.ts",
+ output: "import_attributes/type_check.out",
exit_code: 1,
});
diff --git a/cli/tests/testdata/import_assertions/dynamic_import.ts b/cli/tests/testdata/import_assertions/dynamic_import.ts
deleted file mode 100644
index d6983852c..000000000
--- a/cli/tests/testdata/import_assertions/dynamic_import.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-const data = await import("./data.json", { assert: { type: "json" } });
-
-console.log(data);
diff --git a/cli/tests/testdata/import_assertions/static_import.ts b/cli/tests/testdata/import_assertions/static_import.ts
deleted file mode 100644
index 180ab75f2..000000000
--- a/cli/tests/testdata/import_assertions/static_import.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-import data from "./data.json" assert { type: "json" };
-
-console.log(data);
diff --git a/cli/tests/testdata/import_assertions/type_check.out b/cli/tests/testdata/import_assertions/type_check.out
deleted file mode 100644
index 8e1387456..000000000
--- a/cli/tests/testdata/import_assertions/type_check.out
+++ /dev/null
@@ -1,5 +0,0 @@
-[WILDCARD]
-error: TS2339 [ERROR]: Property 'foo' does not exist on type '{ a: string; c: { d: number; }; }'.
-console.log(data.foo);
- ~~~
- at [WILDCARD]type_check.ts:3:18
diff --git a/cli/tests/testdata/import_assertions/type_check.ts b/cli/tests/testdata/import_assertions/type_check.ts
deleted file mode 100644
index 19adb3eae..000000000
--- a/cli/tests/testdata/import_assertions/type_check.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-import data from "./data.json" assert { type: "json" };
-
-console.log(data.foo);
diff --git a/cli/tests/testdata/import_assertions/data.json b/cli/tests/testdata/import_attributes/data.json
index 37b3ee1e0..37b3ee1e0 100644
--- a/cli/tests/testdata/import_assertions/data.json
+++ b/cli/tests/testdata/import_attributes/data.json
diff --git a/cli/tests/testdata/import_assertions/dynamic_error.out b/cli/tests/testdata/import_attributes/dynamic_error.out
index 927eae0b8..927eae0b8 100644
--- a/cli/tests/testdata/import_assertions/dynamic_error.out
+++ b/cli/tests/testdata/import_attributes/dynamic_error.out
diff --git a/cli/tests/testdata/import_assertions/dynamic_error.ts b/cli/tests/testdata/import_attributes/dynamic_error.ts
index 2d9c6757f..2d9c6757f 100644
--- a/cli/tests/testdata/import_assertions/dynamic_error.ts
+++ b/cli/tests/testdata/import_attributes/dynamic_error.ts
diff --git a/cli/tests/testdata/import_assertions/dynamic_import.out b/cli/tests/testdata/import_attributes/dynamic_import.out
index 7a7b4c91f..01bc76c8a 100644
--- a/cli/tests/testdata/import_assertions/dynamic_import.out
+++ b/cli/tests/testdata/import_attributes/dynamic_import.out
@@ -1,2 +1,3 @@
[WILDCARD]
[Module: null prototype] { default: { a: "b", c: { d: 10 } } }
+[Module: null prototype] { default: { a: "b", c: { d: 10 } } }
diff --git a/cli/tests/testdata/import_attributes/dynamic_import.ts b/cli/tests/testdata/import_attributes/dynamic_import.ts
new file mode 100644
index 000000000..73f348697
--- /dev/null
+++ b/cli/tests/testdata/import_attributes/dynamic_import.ts
@@ -0,0 +1,5 @@
+const data1 = await import("./data.json", { with: { type: "json" } });
+const data2 = await import("./data.json", { assert: { type: "json" } });
+
+console.log(data1);
+console.log(data2);
diff --git a/cli/tests/testdata/import_assertions/json_with_shebang.json b/cli/tests/testdata/import_attributes/json_with_shebang.json
index b695e4457..b695e4457 100644
--- a/cli/tests/testdata/import_assertions/json_with_shebang.json
+++ b/cli/tests/testdata/import_attributes/json_with_shebang.json
diff --git a/cli/tests/testdata/import_assertions/json_with_shebang.ts b/cli/tests/testdata/import_attributes/json_with_shebang.ts
index 523bf8772..523bf8772 100644
--- a/cli/tests/testdata/import_assertions/json_with_shebang.ts
+++ b/cli/tests/testdata/import_attributes/json_with_shebang.ts
diff --git a/cli/tests/testdata/import_assertions/json_with_shebang.ts.out b/cli/tests/testdata/import_attributes/json_with_shebang.ts.out
index 23eb03720..23eb03720 100644
--- a/cli/tests/testdata/import_assertions/json_with_shebang.ts.out
+++ b/cli/tests/testdata/import_attributes/json_with_shebang.ts.out
diff --git a/cli/tests/testdata/import_assertions/static_error.out b/cli/tests/testdata/import_attributes/static_error.out
index 4efdf8682..171ae0c1a 100644
--- a/cli/tests/testdata/import_assertions/static_error.out
+++ b/cli/tests/testdata/import_attributes/static_error.out
@@ -1,4 +1,4 @@
[WILDCARD]
-error: Expected a JavaScript or TypeScript module, but identified a Json module. Consider importing Json modules with an import assertion with the type of "json".
+error: Expected a JavaScript or TypeScript module, but identified a Json module. Consider importing Json modules with an import attribute with the type of "json".
Specifier: [WILDCARD]/data.json
at [WILDCARD]static_error.ts:1:18
diff --git a/cli/tests/testdata/import_assertions/static_error.ts b/cli/tests/testdata/import_attributes/static_error.ts
index 0bc3a93f8..0bc3a93f8 100644
--- a/cli/tests/testdata/import_assertions/static_error.ts
+++ b/cli/tests/testdata/import_attributes/static_error.ts
diff --git a/cli/tests/testdata/import_assertions/static_export.out b/cli/tests/testdata/import_attributes/static_export.out
index 42fbc066c..42fbc066c 100644
--- a/cli/tests/testdata/import_assertions/static_export.out
+++ b/cli/tests/testdata/import_attributes/static_export.out
diff --git a/cli/tests/testdata/import_assertions/static_export.ts b/cli/tests/testdata/import_attributes/static_export.ts
index ac3ee694f..ac3ee694f 100644
--- a/cli/tests/testdata/import_assertions/static_export.ts
+++ b/cli/tests/testdata/import_attributes/static_export.ts
diff --git a/cli/tests/testdata/import_assertions/static_import.out b/cli/tests/testdata/import_attributes/static_import.out
index 42fbc066c..b3b71cd8f 100644
--- a/cli/tests/testdata/import_assertions/static_import.out
+++ b/cli/tests/testdata/import_attributes/static_import.out
@@ -1,2 +1,3 @@
[WILDCARD]
{ a: "b", c: { d: 10 } }
+{ a: "b", c: { d: 10 } }
diff --git a/cli/tests/testdata/import_attributes/static_import.ts b/cli/tests/testdata/import_attributes/static_import.ts
new file mode 100644
index 000000000..d46d93b4a
--- /dev/null
+++ b/cli/tests/testdata/import_attributes/static_import.ts
@@ -0,0 +1,5 @@
+import data1 from "./data.json" with { type: "json" };
+import data2 from "./data.json" assert { type: "json" };
+
+console.log(data1);
+console.log(data2);
diff --git a/cli/tests/testdata/import_assertions/static_reexport.ts b/cli/tests/testdata/import_attributes/static_reexport.ts
index 81af428be..81af428be 100644
--- a/cli/tests/testdata/import_assertions/static_reexport.ts
+++ b/cli/tests/testdata/import_attributes/static_reexport.ts
diff --git a/cli/tests/testdata/import_attributes/type_check.out b/cli/tests/testdata/import_attributes/type_check.out
new file mode 100644
index 000000000..5ecdec82d
--- /dev/null
+++ b/cli/tests/testdata/import_attributes/type_check.out
@@ -0,0 +1,12 @@
+Check file:///[WILDCARD]/type_check.ts
+error: TS2339 [ERROR]: Property 'foo' does not exist on type '{ a: string; c: { d: number; }; }'.
+console.log(data1.foo);
+ ~~~
+ at [WILDCARD]type_check.ts:4:19
+
+TS2339 [ERROR]: Property 'foo' does not exist on type '{ a: string; c: { d: number; }; }'.
+console.log(data2.foo);
+ ~~~
+ at [WILDCARD]type_check.ts:5:19
+
+Found 2 errors.
diff --git a/cli/tests/testdata/import_attributes/type_check.ts b/cli/tests/testdata/import_attributes/type_check.ts
new file mode 100644
index 000000000..ddf28e67a
--- /dev/null
+++ b/cli/tests/testdata/import_attributes/type_check.ts
@@ -0,0 +1,5 @@
+import data1 from "./data.json" with { type: "json" };
+import data2 from "./data.json" assert { type: "json" };
+
+console.log(data1.foo);
+console.log(data2.foo);
diff --git a/cli/tests/testdata/run/020_json_modules.ts.out b/cli/tests/testdata/run/020_json_modules.ts.out
index da33c40bf..750363da2 100644
--- a/cli/tests/testdata/run/020_json_modules.ts.out
+++ b/cli/tests/testdata/run/020_json_modules.ts.out
@@ -1,4 +1,4 @@
[WILDCARD]
-error: Expected a JavaScript or TypeScript module, but identified a Json module. Consider importing Json modules with an import assertion with the type of "json".
+error: Expected a JavaScript or TypeScript module, but identified a Json module. Consider importing Json modules with an import attribute with the type of "json".
Specifier: [WILDCARD]/subdir/config.json
[WILDCARD] \ No newline at end of file
diff --git a/cli/tools/info.rs b/cli/tools/info.rs
index c0dd686f8..941ba1cbd 100644
--- a/cli/tools/info.rs
+++ b/cli/tools/info.rs
@@ -645,7 +645,7 @@ impl<'a> GraphDisplayContext<'a> {
match err {
ModuleGraphError::ModuleError(err) => match err {
ModuleError::InvalidTypeAssertion { .. } => {
- self.build_error_msg(specifier, "(invalid import assertion)")
+ self.build_error_msg(specifier, "(invalid import attribute)")
}
ModuleError::LoadingErr(_, _, _) => {
self.build_error_msg(specifier, "(loading error)")
@@ -653,8 +653,8 @@ impl<'a> GraphDisplayContext<'a> {
ModuleError::ParseErr(_, _) => {
self.build_error_msg(specifier, "(parsing error)")
}
- ModuleError::UnsupportedImportAssertionType { .. } => {
- self.build_error_msg(specifier, "(unsupported import assertion)")
+ ModuleError::UnsupportedImportAttributeType { .. } => {
+ self.build_error_msg(specifier, "(unsupported import attribute)")
}
ModuleError::UnsupportedMediaType { .. } => {
self.build_error_msg(specifier, "(unsupported)")
@@ -662,6 +662,12 @@ impl<'a> GraphDisplayContext<'a> {
ModuleError::Missing(_, _) | ModuleError::MissingDynamic(_, _) => {
self.build_error_msg(specifier, "(missing)")
}
+ ModuleError::UnknownPackage { .. } => {
+ self.build_error_msg(specifier, "(unknown package)")
+ }
+ ModuleError::UnknownPackageReq { .. } => {
+ self.build_error_msg(specifier, "(unknown package constraint)")
+ }
},
ModuleGraphError::ResolutionError(_) => {
self.build_error_msg(specifier, "(resolution error)")
diff --git a/cli/tools/vendor/test.rs b/cli/tools/vendor/test.rs
index c00cc654d..a8b83bb91 100644
--- a/cli/tools/vendor/test.rs
+++ b/cli/tools/vendor/test.rs
@@ -116,6 +116,7 @@ impl Loader for TestLoader {
&mut self,
specifier: &ModuleSpecifier,
_is_dynamic: bool,
+ _cache_setting: deno_graph::source::CacheSetting,
) -> LoadFuture {
let specifier = self.redirects.get(specifier).unwrap_or(specifier);
let result = self.files.get(specifier).map(|result| match result {
diff --git a/cli/tsc/00_typescript.js b/cli/tsc/00_typescript.js
index 7ecdddc5d..08e819b90 100644
--- a/cli/tsc/00_typescript.js
+++ b/cli/tsc/00_typescript.js
@@ -33936,7 +33936,8 @@ ${lanes.join("\n")}
}
const moduleSpecifier = parseModuleSpecifier();
let assertClause;
- if (token() === 132 /* AssertKeyword */ && !scanner2.hasPrecedingLineBreak()) {
+ const hasAssertKeyword = token() === 132 /* AssertKeyword */ || token() === 118 /* WithKeyword */;
+ if (hasAssertKeyword && !scanner2.hasPrecedingLineBreak()) {
assertClause = parseAssertClause();
}
parseSemicolon();
@@ -33956,7 +33957,11 @@ ${lanes.join("\n")}
function parseAssertClause(skipAssertKeyword) {
const pos = getNodePos();
if (!skipAssertKeyword) {
- parseExpected(132 /* AssertKeyword */);
+ if (token() === 118 /* WithKeyword */) {
+ parseExpected(118 /* WithKeyword */);
+ } else {
+ parseExpected(132 /* AssertKeyword */);
+ }
}
const openBracePosition = scanner2.getTokenStart();
if (parseExpected(19 /* OpenBraceToken */)) {
diff --git a/cli/tsc/dts/lib.es5.d.ts b/cli/tsc/dts/lib.es5.d.ts
index 870d8a04c..a723d2942 100644
--- a/cli/tsc/dts/lib.es5.d.ts
+++ b/cli/tsc/dts/lib.es5.d.ts
@@ -639,6 +639,7 @@ interface ImportMeta {
*/
interface ImportCallOptions {
assert?: ImportAssertions;
+ with?: ImportAssertions;
}
/**
diff --git a/cli/tsc/mod.rs b/cli/tsc/mod.rs
index cfc9bd952..22f9d3290 100644
--- a/cli/tsc/mod.rs
+++ b/cli/tsc/mod.rs
@@ -870,6 +870,7 @@ mod tests {
&mut self,
specifier: &ModuleSpecifier,
_is_dynamic: bool,
+ _cache_setting: deno_graph::source::CacheSetting,
) -> deno_graph::source::LoadFuture {
let specifier_text = specifier
.to_string()