diff --git a/api/src/analysis.rs b/api/src/analysis.rs index fd5bfa9c..a66de38a 100644 --- a/api/src/analysis.rs +++ b/api/src/analysis.rs @@ -186,6 +186,7 @@ async fn analyze_package_inner( .analyzer .get_parsed_source(module.specifier()) { + check_for_banned_extensions(&parsed_source)?; check_for_banned_syntax(&parsed_source)?; check_for_banned_triple_slash_directives(&parsed_source)?; } @@ -802,6 +803,21 @@ fn collect_dependencies( Ok(dependencies) } +fn check_for_banned_extensions( + parsed_source: &ParsedSource, +) -> Result<(), PublishError> { + match parsed_source.media_type() { + deno_ast::MediaType::Cjs | deno_ast::MediaType::Cts => { + Err(PublishError::CommonJs { + specifier: parsed_source.specifier().to_string(), + line: 0, + column: 0, + }) + } + _ => Ok(()), + } +} + fn check_for_banned_syntax( parsed_source: &ParsedSource, ) -> Result<(), PublishError> { @@ -957,8 +973,15 @@ fn check_for_banned_triple_slash_directives( #[cfg(test)] mod tests { fn parse(source: &str) -> deno_ast::ParsedSource { - let specifier = deno_ast::ModuleSpecifier::parse("file:///mod.ts").unwrap(); let media_type = deno_ast::MediaType::TypeScript; + parse_with_media_type(source, media_type) + } + + fn parse_with_media_type( + source: &str, + media_type: deno_ast::MediaType, + ) -> deno_ast::ParsedSource { + let specifier = deno_ast::ModuleSpecifier::parse("file:///mod.ts").unwrap(); deno_ast::parse_module(deno_ast::ParseParams { specifier, text: source.into(), @@ -970,6 +993,27 @@ mod tests { .unwrap() } + #[test] + fn banned_extensions() { + let x = + parse_with_media_type("let x = 1;", deno_ast::MediaType::TypeScript); + assert!(super::check_for_banned_extensions(&x).is_ok()); + + let x = parse_with_media_type("let x = 1;", deno_ast::MediaType::Cjs); + let err = super::check_for_banned_extensions(&x).unwrap_err(); + assert!( + matches!(err, super::PublishError::CommonJs { .. }), + "{err:?}", + ); + + let x = parse_with_media_type("let x = 1;", deno_ast::MediaType::Cts); + let err = super::check_for_banned_extensions(&x).unwrap_err(); + assert!( + matches!(err, super::PublishError::CommonJs { .. }), + "{err:?}", + ); + } + #[test] fn banned_triple_slash_directives() { let x = parse("let x = 1;"); diff --git a/api/src/gcp.rs b/api/src/gcp.rs index 7dffbbd9..37f847f6 100644 --- a/api/src/gcp.rs +++ b/api/src/gcp.rs @@ -573,12 +573,18 @@ impl FakeGcsTester { assert!(self.proc.is_none()); - #[cfg(target_os = "macos")] + #[cfg(all(target_os = "macos", target_arch = "aarch64"))] let p = concat!( env!("CARGO_MANIFEST_DIR"), "/../tools/bin/darwin-arm64/fake-gcs-server" ); + #[cfg(all(target_os = "macos", target_arch = "x86_64"))] + let p = concat!( + env!("CARGO_MANIFEST_DIR"), + "/../tools/bin/darwin-amd64/fake-gcs-server" + ); + #[cfg(target_os = "linux")] let p = concat!( env!("CARGO_MANIFEST_DIR"), diff --git a/api/src/publish.rs b/api/src/publish.rs index e2df5d91..85118fd9 100644 --- a/api/src/publish.rs +++ b/api/src/publish.rs @@ -1309,6 +1309,16 @@ pub mod tests { assert_eq!(task.status, PublishingTaskStatus::Success, "{task:#?}"); } + #[tokio::test] + async fn cjs_import() { + let t = TestSetup::new().await; + let bytes = create_mock_tarball("cjs_import"); + let task = process_tarball_setup(&t, bytes).await; + assert_eq!(task.status, PublishingTaskStatus::Failure, "{task:#?}"); + let error = task.error.unwrap(); + assert_eq!(error.code, "commonJs"); + } + #[tokio::test] async fn npm_tarball() { let t = TestSetup::new().await; diff --git a/api/testdata/tarballs/cjs_import/jsr.json b/api/testdata/tarballs/cjs_import/jsr.json new file mode 100644 index 00000000..35b9ed05 --- /dev/null +++ b/api/testdata/tarballs/cjs_import/jsr.json @@ -0,0 +1,5 @@ +{ + "name": "@scope/foo", + "version": "1.2.3", + "exports": "./mod.ts" +} \ No newline at end of file diff --git a/api/testdata/tarballs/cjs_import/mod.ts b/api/testdata/tarballs/cjs_import/mod.ts new file mode 100644 index 00000000..5455679a --- /dev/null +++ b/api/testdata/tarballs/cjs_import/mod.ts @@ -0,0 +1,3 @@ +import { test } from "./other.cjs"; // bad + +export const hello = `Hello, ${test}!`; diff --git a/api/testdata/tarballs/cjs_import/other.cjs b/api/testdata/tarballs/cjs_import/other.cjs new file mode 100644 index 00000000..e89508f4 --- /dev/null +++ b/api/testdata/tarballs/cjs_import/other.cjs @@ -0,0 +1 @@ +exports.test = "test"; diff --git a/frontend/docs/troubleshooting.md b/frontend/docs/troubleshooting.md index 5e07e445..4adf704f 100644 --- a/frontend/docs/troubleshooting.md +++ b/frontend/docs/troubleshooting.md @@ -91,8 +91,9 @@ source. ### `commonJs` -The package being published contains CommonJS code like `require()`. This is -disallowed because JSR is ESM only. +The package being published imports code from CommonJS files with a `.cjs` or +`.cts` extension or contains CommonJS code like `require()`. This is disallowed +because JSR is ESM only. You can fix this error by removing the CommonJS code from your source.