Repository: denoland/deno (language: rust)

Issue:
Panic on inconsistent exports in package.json
Version: Deno 2.0.0-rc.10

Steps to reproduce:

1. Create a dir with a `package.json` containing `{ "exports": { ".": "./a", "a": "./a" } }`
2. Run `RUST_BACKTRACE=1 deno task`

Expected result: Some reasonable error message.

Result:

```
============================================================
Deno has panicked. This is a bug in Deno. Please report this
at https://github.com/denoland/deno/issues/new.
If you can reliably reproduce this panic, include the
reproduction steps and re-run with the RUST_BACKTRACE=1 env
var set and include the backtrace in your report.

Platform: linux x86_64
Version: 2.0.0-rc.10
Args: ["deno", "task"]

thread 'main' panicked at /home/runner/.cargo/registry/src/index.crates.io-6f17d22bba15001f/deno_package_json-0.1.2/src/lib.rs:401:7:
"exports" cannot contains some keys starting with '.' and some not.
        The exports object must either be an object of package subpath keys
        or an object of main entry condition name keys only.
stack backtrace:
   0: rust_begin_unwind
   1: core::panicking::panic_fmt
   2: deno_package_json::PackageJson::load_from_value
   3: deno_package_json::PackageJson::load_from_path
   4: deno_config::workspace::discovery::discover_workspace_config_files_for_single_dir::{{closure}}
   5: deno_config::workspace::discovery::discover_workspace_config_files_for_single_dir
   6: deno_config::workspace::WorkspaceDirectory::discover
   7: deno::args::CliOptions::from_flags
   8: deno::factory::CliFactory::cli_options
   9: deno::tools::task::execute_script::{{closure}}
  10: deno::spawn_subcommand::{{closure}}
  11: <deno_unsync::tokio::task::MaskFutureAsSend<F> as core::future::future::Future>::poll
  12: tokio::runtime::task::raw::poll
  13: deno::main
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
```


Discussion / hints:
Related, the `patch` feature also fails instead of erroring when the `exports` shape is invalid https://github.com/denoland/deno/issues/25435

Fix patch:
diff --git a/Cargo.lock b/Cargo.lock
index 8200e6b15608ed..9ed3eab2c2fd6d 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1716,9 +1716,9 @@ dependencies = [
 
 [[package]]
 name = "deno_config"
-version = "0.49.1"
+version = "0.50.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1bbde052743fd8729836d337de950fbffd79e3edb6fa8d5894e95b7d62dea15b"
+checksum = "56792005d20f0b38f2e190b15918362440bebc0065b825af59d6022be465f764"
 dependencies = [
  "boxed_error",
  "capacity_builder 0.5.0",
@@ -2411,9 +2411,9 @@ dependencies = [
 
 [[package]]
 name = "deno_package_json"
-version = "0.4.2"
+version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d07d26dbfcc01e636aef86f9baff7faf5338398e74d283d8fe01e39068f48049"
+checksum = "fb8582ef20e0c5ed9bc43e93f593a461b63bd106311117feb3baf9ce8ea03d95"
 dependencies = [
  "boxed_error",
  "deno_error",
diff --git a/Cargo.toml b/Cargo.toml
index 122974739fb5d4..44c084a533a8e6 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -54,7 +54,7 @@ deno_ast = { version = "=0.44.0", features = ["transpiling"] }
 deno_core = { version = "0.338.0" }
 
 deno_bench_util = { version = "0.186.0", path = "./bench_util" }
-deno_config = { version = "=0.49.1", features = ["workspace"] }
+deno_config = { version = "=0.50.0", features = ["workspace"] }
 deno_lockfile = "=0.24.0"
 deno_media_type = { version = "=0.2.6", features = ["module_specifier"] }
 deno_npm = "=0.27.2"
@@ -130,7 +130,7 @@ data-encoding = "2.3.3"
 data-url = "=0.3.1"
 deno_cache_dir = "=0.18.0"
 deno_error = "=0.5.5"
-deno_package_json = { version = "=0.4.2", default-features = false }
+deno_package_json = { version = "=0.5.0", default-features = false }
 deno_unsync = "0.4.2"
 dlopen2 = "0.6.1"
 ecb = "=0.1.2"
diff --git a/cli/rt/run.rs b/cli/rt/run.rs
index 1eca838cba643b..3dd26122d00c0d 100644
--- a/cli/rt/run.rs
+++ b/cli/rt/run.rs
@@ -841,10 +841,10 @@ pub async fn run(
           .to_file_path()
           .unwrap();
         let pkg_json =
-          deno_package_json::PackageJson::load_from_value(path, json);
-        Arc::new(pkg_json)
+          deno_package_json::PackageJson::load_from_value(path, json)?;
+        Ok(Arc::new(pkg_json))
       })
-      .collect();
+      .collect::<Result<Vec<_>, AnyError>>()?;
     WorkspaceResolver::new_raw(
       root_dir_url.clone(),
       import_map,
diff --git a/cli/tools/publish/unfurl.rs b/cli/tools/publish/unfurl.rs
index 815a98438df593..510270882bbacf 100644
--- a/cli/tools/publish/unfurl.rs
+++ b/cli/tools/publish/unfurl.rs
@@ -731,7 +731,8 @@ mod tests {
           "chalk": 5
         }
       }),
-    );
+    )
+    .unwrap();
     let workspace_resolver = WorkspaceResolver::new_raw(
       Arc::new(ModuleSpecifier::from_directory_path(&cwd).unwrap()),
       Some(import_map),
@@ -867,11 +868,13 @@ export type * from "./c.d.ts";
     let pkg_json_add = PackageJson::load_from_value(
       cwd.join("add/package.json"),
       json!({ "name": "add", "version": "0.1.0", }),
-    );
+    )
+    .unwrap();
     let pkg_json_subtract = PackageJson::load_from_value(
       cwd.join("subtract/package.json"),
       json!({ "name": "subtract", "version": "0.2.0", }),
-    );
+    )
+    .unwrap();
     let pkg_json_publishing = PackageJson::load_from_value(
       cwd.join("publish/package.json"),
       json!({
@@ -883,11 +886,13 @@ export type * from "./c.d.ts";
           "non-existent": "workspace:~",
         }
       }),
-    );
+    )
+    .unwrap();
     let root_pkg_json = PackageJson::load_from_value(
       cwd.join("package.json"),
       json!({ "workspaces": ["./publish", "./subtract", "./add"] }),
-    );
+    )
+    .unwrap();
     let sys = CliSys::default();
     let workspace_resolver = WorkspaceResolver::new_raw(
       Arc::new(ModuleSpecifier::from_directory_path(&cwd).unwrap()),
diff --git a/resolvers/deno/workspace.rs b/resolvers/deno/workspace.rs
index b7169497222435..c51a13f9956e95 100644
--- a/resolvers/deno/workspace.rs
+++ b/resolvers/deno/workspace.rs
@@ -1174,7 +1174,7 @@ impl<TSys: FsMetadata + FsRead> WorkspaceResolver<TSys> {
           url_to_file_path(&root_dir_url.join(&relative_path).unwrap())
             .unwrap();
         let pkg_json =
-          deno_package_json::PackageJson::load_from_value(path, json);
+          deno_package_json::PackageJson::load_from_value(path, json).unwrap();
         PackageJsonRc::new(pkg_json)
       })
       .collect();
diff --git a/resolvers/node/resolution.rs b/resolvers/node/resolution.rs
index 66ab8b8ac5a2b8..cc2299d3a93835 100644
--- a/resolvers/node/resolution.rs
+++ b/resolvers/node/resolution.rs
@@ -2112,7 +2112,7 @@ mod tests {
   use super::*;
 
   fn build_package_json(json: Value) -> PackageJson {
-    PackageJson::load_from_value(PathBuf::from("/package.json"), json)
+    PackageJson::load_from_value(PathBuf::from("/package.json"), json).unwrap()
   }
 
   #[test]


Test patch: