diff --git a/api/src/analysis.rs b/api/src/analysis.rs
index eb70b5dc..443eb84f 100644
--- a/api/src/analysis.rs
+++ b/api/src/analysis.rs
@@ -5,6 +5,7 @@ use std::collections::HashSet;
use std::sync::Arc;
use deno_ast::swc::common::comments::CommentKind;
+use deno_ast::swc::common::Span;
use deno_ast::LineAndColumnDisplay;
use deno_ast::MediaType;
use deno_ast::ModuleSpecifier;
@@ -727,6 +728,54 @@ fn check_for_banned_syntax(
continue;
}
},
+ ast::ModuleDecl::Import(n) => {
+ if let Some(with) = &n.with {
+ let range =
+ Span::new(n.src.span.hi(), with.span.lo(), n.src.span.ctxt)
+ .range();
+ let keyword = parsed_source.text_info().range_text(&range);
+ if keyword.contains("assert") {
+ let (line, column) = line_col(&with.span.range());
+ return Err(PublishError::BannedImportAssertion {
+ specifier: parsed_source.specifier().to_string(),
+ line,
+ column,
+ });
+ }
+ }
+ }
+ ast::ModuleDecl::ExportNamed(n) => {
+ if let Some(with) = &n.with {
+ let src = n.src.as_ref().unwrap();
+ let range =
+ Span::new(src.span.hi(), with.span.lo(), src.span.ctxt).range();
+ let keyword = parsed_source.text_info().range_text(&range);
+ if keyword.contains("assert") {
+ let (line, column) = line_col(&with.span.range());
+ return Err(PublishError::BannedImportAssertion {
+ specifier: parsed_source.specifier().to_string(),
+ line,
+ column,
+ });
+ }
+ }
+ }
+ ast::ModuleDecl::ExportAll(n) => {
+ if let Some(with) = &n.with {
+ let range =
+ Span::new(n.src.span.hi(), with.span.lo(), n.src.span.ctxt)
+ .range();
+ let keyword = parsed_source.text_info().range_text(&range);
+ if keyword.contains("assert") {
+ let (line, column) = line_col(&with.span.range());
+ return Err(PublishError::BannedImportAssertion {
+ specifier: parsed_source.specifier().to_string(),
+ line,
+ column,
+ });
+ }
+ }
+ }
_ => continue,
},
ast::ModuleItem::Stmt(n) => match n {
@@ -920,5 +969,29 @@ mod tests {
let x = parse("import express = React.foo;");
assert!(super::check_for_banned_syntax(&x).is_ok());
+
+ let x = parse("import './data.json' assert { type: 'json' }");
+ let err = super::check_for_banned_syntax(&x).unwrap_err();
+ assert!(
+ matches!(err, super::PublishError::BannedImportAssertion { .. }),
+ "{err:?}",
+ );
+
+ let x = parse("export { a } from './data.json' assert { type: 'json' }");
+ let err = super::check_for_banned_syntax(&x).unwrap_err();
+ assert!(
+ matches!(err, super::PublishError::BannedImportAssertion { .. }),
+ "{err:?}",
+ );
+
+ let x = parse("export * from './data.json' assert { type: 'json' }");
+ let err = super::check_for_banned_syntax(&x).unwrap_err();
+ assert!(
+ matches!(err, super::PublishError::BannedImportAssertion { .. }),
+ "{err:?}",
+ );
+
+ let x = parse("export * from './data.json' with { type: 'json' }");
+ assert!(super::check_for_banned_syntax(&x).is_ok(), "{err:?}",);
}
}
diff --git a/api/src/publish.rs b/api/src/publish.rs
index e88475b1..e3a03ad1 100644
--- a/api/src/publish.rs
+++ b/api/src/publish.rs
@@ -972,6 +972,41 @@ pub mod tests {
assert_eq!(error.code, "invalidPath");
}
+ #[tokio::test]
+ async fn import_assertions() {
+ let t = TestSetup::new().await;
+
+ let bytes = create_mock_tarball("import_assertions");
+ let task = process_tarball_setup2(
+ &t,
+ bytes,
+ &PackageName::try_from("foo").unwrap(),
+ &Version::try_from("1.2.3").unwrap(),
+ false,
+ )
+ .await;
+ assert_eq!(task.status, PublishingTaskStatus::Failure, "{task:#?}");
+ let error = task.error.unwrap();
+ assert_eq!(error.code, "bannedImportAssertion");
+ assert_eq!(error.message, "import assertions are not allowed, use import attributes instead (replace 'assert' with 'with') file:///mod.ts:1:29");
+ }
+
+ #[tokio::test]
+ async fn import_attributes() {
+ let t = TestSetup::new().await;
+
+ let bytes = create_mock_tarball("import_attributes");
+ let task = process_tarball_setup2(
+ &t,
+ bytes,
+ &PackageName::try_from("foo").unwrap(),
+ &Version::try_from("1.2.3").unwrap(),
+ false,
+ )
+ .await;
+ assert_eq!(task.status, PublishingTaskStatus::Success, "{task:#?}");
+ }
+
#[tokio::test]
async fn jsr_jsonc() {
let t = TestSetup::new().await;
diff --git a/api/src/tarball.rs b/api/src/tarball.rs
index 49e233fd..b3f8f4ff 100644
--- a/api/src/tarball.rs
+++ b/api/src/tarball.rs
@@ -485,7 +485,7 @@ pub enum PublishError {
#[error("invalid external import to '{specifier}', only 'jsr:', 'npm:', 'data:' and 'node:' imports are allowed ({info})")]
InvalidExternalImport { specifier: String, info: String },
- #[error("Modifying global types is not allowed {specifier}:{line}:{column}")]
+ #[error("modifying global types is not allowed {specifier}:{line}:{column}")]
GlobalTypeAugmentation {
specifier: String,
line: usize,
@@ -499,13 +499,20 @@ pub enum PublishError {
column: usize,
},
- #[error("Triple slash directives that modify globals (for example, '/// ' or '/// ') are not allowed. Instead instruct the user of your package to specify these directives. {specifier}:{line}:{column}")]
+ #[error("triple slash directives that modify globals (for example, '/// ' or '/// ') are not allowed. Instead instruct the user of your package to specify these directives. {specifier}:{line}:{column}")]
BannedTripleSlashDirectives {
specifier: String,
line: usize,
column: usize,
},
+ #[error("import assertions are not allowed, use import attributes instead (replace 'assert' with 'with') {specifier}:{line}:{column}")]
+ BannedImportAssertion {
+ specifier: String,
+ line: usize,
+ column: usize,
+ },
+
#[error(
"file at path '{path}' too large, max size is {max_size}, got {size}"
)]
@@ -614,6 +621,9 @@ impl PublishError {
PublishError::BannedTripleSlashDirectives { .. } => {
Some("bannedTripleSlashDirectives")
}
+ PublishError::BannedImportAssertion { .. } => {
+ Some("bannedImportAssertion")
+ }
PublishError::InvalidExternalImport { .. } => {
Some("invalidExternalImport")
}
diff --git a/api/testdata/tarballs/import_assertions/data.json b/api/testdata/tarballs/import_assertions/data.json
new file mode 100644
index 00000000..d1cc1b4e
--- /dev/null
+++ b/api/testdata/tarballs/import_assertions/data.json
@@ -0,0 +1 @@
+"abc"
diff --git a/api/testdata/tarballs/import_assertions/jsr.json b/api/testdata/tarballs/import_assertions/jsr.json
new file mode 100644
index 00000000..94c22c0e
--- /dev/null
+++ b/api/testdata/tarballs/import_assertions/jsr.json
@@ -0,0 +1,5 @@
+{
+ "name": "@scope/foo",
+ "version": "1.2.3",
+ "exports": "./mod.ts"
+}
diff --git a/api/testdata/tarballs/import_assertions/mod.ts b/api/testdata/tarballs/import_assertions/mod.ts
new file mode 100644
index 00000000..2568964b
--- /dev/null
+++ b/api/testdata/tarballs/import_assertions/mod.ts
@@ -0,0 +1 @@
+import "./data.json" assert { type: "json" };
diff --git a/api/testdata/tarballs/import_attributes/data.json b/api/testdata/tarballs/import_attributes/data.json
new file mode 100644
index 00000000..d1cc1b4e
--- /dev/null
+++ b/api/testdata/tarballs/import_attributes/data.json
@@ -0,0 +1 @@
+"abc"
diff --git a/api/testdata/tarballs/import_attributes/jsr.json b/api/testdata/tarballs/import_attributes/jsr.json
new file mode 100644
index 00000000..94c22c0e
--- /dev/null
+++ b/api/testdata/tarballs/import_attributes/jsr.json
@@ -0,0 +1,5 @@
+{
+ "name": "@scope/foo",
+ "version": "1.2.3",
+ "exports": "./mod.ts"
+}
diff --git a/api/testdata/tarballs/import_attributes/mod.ts b/api/testdata/tarballs/import_attributes/mod.ts
new file mode 100644
index 00000000..16f4d15b
--- /dev/null
+++ b/api/testdata/tarballs/import_attributes/mod.ts
@@ -0,0 +1 @@
+import "./data.json" with { type: "json" };
diff --git a/frontend/docs/troubleshooting.md b/frontend/docs/troubleshooting.md
index 7d8651b3..77e12d4c 100644
--- a/frontend/docs/troubleshooting.md
+++ b/frontend/docs/troubleshooting.md
@@ -105,6 +105,17 @@ allowed by JSR. JSR only allows triple slash directives that are
You can fix this error by removing the triple slash directive from your source.
+### `bannedImportAssertion`
+
+The package being published contains the legacy "import assertions" syntax,
+which is not allowed by JSR. JSR only allows the new "import attributes" syntax.
+
+`import "./data.json" assert { type: "json" };` is not allowed.
+`import "./data.json" with { type: "json" };` is allowed.
+
+You can fix this error by updating the import assertion to an import attribute,
+by replacing `assert` with `with`.
+
### `fileTooLarge`
The package being published contains a file that is too large. JSR only allows