diff --git a/Cargo.lock b/Cargo.lock index 9e72dac0df..77dc2cb4c4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -231,7 +231,7 @@ dependencies = [ "nom 7.1.3", "num-traits", "rusticata-macros", - "thiserror", + "thiserror 1.0.64", "time", ] @@ -1292,7 +1292,7 @@ dependencies = [ "test_server", "text-size", "text_lines", - "thiserror", + "thiserror 1.0.64", "tokio", "tokio-util", "tracing", @@ -1321,13 +1321,14 @@ dependencies = [ [[package]] name = "deno_ast" -version = "0.43.3" +version = "0.44.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48d00b724e06d2081a141ec1155756a0b465d413d8e2a7515221f61d482eb2ee" +checksum = "eebc7aaabfdb3ddcad32aee1b62d250149dc8b35dfbdccbb125df2bdc62da952" dependencies = [ "base64 0.21.7", + "deno_error", "deno_media_type", - "deno_terminal 0.1.1", + "deno_terminal 0.2.0", "dprint-swc-ext", "once_cell", "percent-encoding", @@ -1358,7 +1359,7 @@ dependencies = [ "swc_visit", "swc_visit_macros", "text_lines", - "thiserror", + "thiserror 2.0.3", "unicode-width", "url", ] @@ -1378,7 +1379,7 @@ version = "0.174.0" dependencies = [ "async-trait", "deno_core", - "thiserror", + "thiserror 1.0.64", "tokio", "uuid", ] @@ -1392,15 +1393,15 @@ dependencies = [ "rusqlite", "serde", "sha2", - "thiserror", + "thiserror 1.0.64", "tokio", ] [[package]] name = "deno_cache_dir" -version = "0.13.2" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08c1f52170cd7715f8006da54cde1444863a0d6fbd9c11d037a737db2dec8e22" +checksum = "cca43605c8cbce6c6787e0daf227864487c07c2b31d438c0bf43d1b38da94b7f" dependencies = [ "base32", "deno_media_type", @@ -1412,7 +1413,7 @@ dependencies = [ "serde", "serde_json", "sha2", - "thiserror", + "thiserror 1.0.64", "url", ] @@ -1424,14 +1425,14 @@ dependencies = [ "deno_webgpu", "image", "serde", - "thiserror", + "thiserror 1.0.64", ] [[package]] name = "deno_config" -version = "0.39.2" +version = "0.39.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38fb809500238be2b10eee42944a47b3ac38974e1edbb47f73afcfca7df143bf" +checksum = "ce717af3fe6788dae63965d58d5637fd62be8fe4f345f189137ffc06c51837d2" dependencies = [ "anyhow", "deno_package_json", @@ -1447,7 +1448,7 @@ dependencies = [ "phf", "serde", "serde_json", - "thiserror", + "thiserror 1.0.64", "url", ] @@ -1508,7 +1509,7 @@ dependencies = [ "chrono", "deno_core", "saffron", - "thiserror", + "thiserror 1.0.64", "tokio", ] @@ -1543,7 +1544,7 @@ dependencies = [ "sha2", "signature", "spki", - "thiserror", + "thiserror 1.0.64", "tokio", "uuid", "x25519-dalek", @@ -1551,9 +1552,9 @@ dependencies = [ [[package]] name = "deno_doc" -version = "0.161.1" +version = "0.161.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32d994915f85e873865fc341e592080a487b0a987d06177016b2d93fd62162f8" +checksum = "3af787319136f3e7f73ef551c618aeec70794522e36cd75ae35132a3bad983ef" dependencies = [ "anyhow", "cfg-if", @@ -1578,6 +1579,29 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "deno_error" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "199c66ffd17ee1a948904d33f3d3f364573951c1f9fb3f859bfe7770bf33862a" +dependencies = [ + "deno_error_macro", + "libc", + "serde", + "serde_json", +] + +[[package]] +name = "deno_error_macro" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3cd99df6ae75443907e1f959fc42ec6dcea67a7bd083e76cf23a117102c9a2ce" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + [[package]] name = "deno_fetch" version = "0.204.0" @@ -1602,7 +1626,7 @@ dependencies = [ "rustls-webpki", "serde", "serde_json", - "thiserror", + "thiserror 1.0.64", "tokio", "tokio-rustls", "tokio-socks", @@ -1627,7 +1651,7 @@ dependencies = [ "serde", "serde-value", "serde_json", - "thiserror", + "thiserror 1.0.64", "tokio", "winapi", ] @@ -1650,16 +1674,16 @@ dependencies = [ "rand", "rayon", "serde", - "thiserror", + "thiserror 1.0.64", "winapi", "windows-sys 0.52.0", ] [[package]] name = "deno_graph" -version = "0.86.2" +version = "0.86.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c3f4be49dad28e794ff4eeb2daaf7956c97f8557097ef6f9c3ff1292e0a5c28" +checksum = "fc78ed0b4bbcb4197300f0d6e7d1edc2d2c5019cdb9dedba7ff229158441885b" dependencies = [ "anyhow", "async-trait", @@ -1679,7 +1703,7 @@ dependencies = [ "serde", "serde_json", "sha2", - "thiserror", + "thiserror 2.0.3", "twox-hash", "url", "wasm_dep_analyzer", @@ -1719,7 +1743,7 @@ dependencies = [ "scopeguard", "serde", "smallvec", - "thiserror", + "thiserror 1.0.64", "tokio", "tokio-util", ] @@ -1773,15 +1797,15 @@ dependencies = [ "rand", "rusqlite", "serde", - "thiserror", + "thiserror 1.0.64", "url", ] [[package]] name = "deno_lint" -version = "0.68.0" +version = "0.68.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb994e6d1b18223df0a756c7948143b35682941d615edffef60d5b38822f38ac" +checksum = "ce2a040657166e39c7d59ad34230f0cc829f8ea8b7b2377038cc012ec1a1ef16" dependencies = [ "anyhow", "deno_ast", @@ -1797,14 +1821,14 @@ dependencies = [ [[package]] name = "deno_lockfile" -version = "0.23.1" +version = "0.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "579117d5815aa9bae0212637d6f4d5f45f9649bb2c8988dca434077545535039" +checksum = "559c19feb00af0c34f0bd4a20e56e12463fafd5c5069d6005f3ce33008027eea" dependencies = [ "deno_semver", "serde", "serde_json", - "thiserror", + "thiserror 2.0.3", ] [[package]] @@ -1829,7 +1853,7 @@ dependencies = [ "libuv-sys-lite", "log", "napi_sym", - "thiserror", + "thiserror 1.0.64", "windows-sys 0.52.0", ] @@ -1859,7 +1883,7 @@ dependencies = [ "rustls-tokio-stream", "serde", "socket2", - "thiserror", + "thiserror 1.0.64", "tokio", ] @@ -1943,7 +1967,7 @@ dependencies = [ "sm3", "spki", "stable_deref_trait", - "thiserror", + "thiserror 1.0.64", "tokio", "tokio-eld", "url", @@ -1957,9 +1981,9 @@ dependencies = [ [[package]] name = "deno_npm" -version = "0.25.4" +version = "0.25.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6b4dc4a9f1cff63d5638e7d93042f24f46300d1cc77b86f3caaa699a7ddccf7" +checksum = "89ded7af9db5d9f2986a739d1b5fbe1c57f498e4f996ae4114728e7c6dad213f" dependencies = [ "anyhow", "async-trait", @@ -1970,7 +1994,7 @@ dependencies = [ "monch", "serde", "serde_json", - "thiserror", + "thiserror 2.0.3", "url", ] @@ -1987,20 +2011,22 @@ dependencies = [ "strum", "strum_macros", "syn 2.0.87", - "thiserror", + "thiserror 1.0.64", ] [[package]] name = "deno_package_json" -version = "0.1.2" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6cbc4c4d3eb0960b58e8f43f9fc2d3f620fcac9a03cd85203e08db5b04e83c1f" +checksum = "80b0a3d81c592624a1ae15332a04b4dc2b7c163ef1dfc7c60171f736d1babdf5" dependencies = [ + "deno_error", + "deno_path_util", "deno_semver", "indexmap 2.3.0", "serde", "serde_json", - "thiserror", + "thiserror 2.0.3", "url", ] @@ -2011,7 +2037,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff25f6e08e7a0214bbacdd6f7195c7f1ebcd850c87a624e4ff06326b68b42d99" dependencies = [ "percent-encoding", - "thiserror", + "thiserror 1.0.64", "url", ] @@ -2028,7 +2054,7 @@ dependencies = [ "once_cell", "percent-encoding", "serde", - "thiserror", + "thiserror 1.0.64", "which 4.4.2", "winapi", ] @@ -2048,7 +2074,7 @@ dependencies = [ "deno_semver", "node_resolver", "test_server", - "thiserror", + "thiserror 1.0.64", "url", ] @@ -2111,7 +2137,7 @@ dependencies = [ "signal-hook-registry", "tempfile", "test_server", - "thiserror", + "thiserror 1.0.64", "tokio", "tokio-metrics", "twox-hash", @@ -2123,14 +2149,15 @@ dependencies = [ [[package]] name = "deno_semver" -version = "0.5.16" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c957c6a57c38b7dde2315df0da0ec228911e56a74f185b108a488d0401841a67" +checksum = "4756be7351289726087408984db18b9eb5e0186907673f39f858d119d0162071" dependencies = [ + "deno_error", "monch", "once_cell", "serde", - "thiserror", + "thiserror 2.0.3", "url", ] @@ -2147,7 +2174,7 @@ dependencies = [ "nix", "os_pipe", "path-dedot", - "thiserror", + "thiserror 1.0.64", "tokio", ] @@ -2203,7 +2230,7 @@ dependencies = [ "rustls-tokio-stream", "rustls-webpki", "serde", - "thiserror", + "thiserror 1.0.64", "tokio", "webpki-roots", ] @@ -2249,7 +2276,7 @@ dependencies = [ "deno_console", "deno_core", "deno_webidl", - "thiserror", + "thiserror 1.0.64", "urlpattern", ] @@ -2270,7 +2297,7 @@ dependencies = [ "flate2", "futures", "serde", - "thiserror", + "thiserror 1.0.64", "tokio", "uuid", ] @@ -2282,7 +2309,7 @@ dependencies = [ "deno_core", "raw-window-handle", "serde", - "thiserror", + "thiserror 1.0.64", "tokio", "wgpu-core", "wgpu-types", @@ -2314,7 +2341,7 @@ dependencies = [ "once_cell", "rustls-tokio-stream", "serde", - "thiserror", + "thiserror 1.0.64", "tokio", ] @@ -2325,7 +2352,7 @@ dependencies = [ "deno_core", "deno_web", "rusqlite", - "thiserror", + "thiserror 1.0.64", ] [[package]] @@ -2397,7 +2424,7 @@ dependencies = [ "rand", "rusqlite", "serde_json", - "thiserror", + "thiserror 1.0.64", "tokio", "tokio-stream", "uuid", @@ -2690,9 +2717,9 @@ dependencies = [ [[package]] name = "dprint-plugin-typescript" -version = "0.93.2" +version = "0.93.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ff29fd136541e59d51946f0d2d353fefc886776f61a799ebfb5838b06cef13b" +checksum = "5804d1809f6191a9261f423c41cd51a50e49567d61caa5a8f6224eea94ae0d12" dependencies = [ "anyhow", "deno_ast", @@ -2838,7 +2865,7 @@ dependencies = [ "debug-ignore", "indexmap 2.3.0", "log", - "thiserror", + "thiserror 1.0.64", "zerocopy", ] @@ -2998,7 +3025,7 @@ dependencies = [ "anyhow", "async-trait", "log", - "thiserror", + "thiserror 1.0.64", "tokio", "tokio-stream", ] @@ -3033,7 +3060,7 @@ dependencies = [ "rand", "sha1", "simdutf8", - "thiserror", + "thiserror 1.0.64", "tokio", "utf-8", ] @@ -3091,7 +3118,7 @@ dependencies = [ "deno_terminal 0.1.1", "parking_lot", "regex", - "thiserror", + "thiserror 1.0.64", ] [[package]] @@ -3565,7 +3592,7 @@ dependencies = [ "pest_derive", "serde", "serde_json", - "thiserror", + "thiserror 1.0.64", ] [[package]] @@ -3651,7 +3678,7 @@ dependencies = [ "once_cell", "radix_trie", "rand", - "thiserror", + "thiserror 1.0.64", "tokio", "tracing", ] @@ -3674,7 +3701,7 @@ dependencies = [ "once_cell", "rand", "serde", - "thiserror", + "thiserror 1.0.64", "tinyvec", "tokio", "tracing", @@ -3698,7 +3725,7 @@ dependencies = [ "resolv-conf", "serde", "smallvec", - "thiserror", + "thiserror 1.0.64", "tokio", "tracing", ] @@ -3716,7 +3743,7 @@ dependencies = [ "futures-util", "hickory-proto", "serde", - "thiserror", + "thiserror 1.0.64", "time", "tokio", "tokio-util", @@ -4156,7 +4183,7 @@ dependencies = [ "percent-encoding", "serde", "serde_json", - "thiserror", + "thiserror 1.0.64", "url", ] @@ -4362,7 +4389,7 @@ dependencies = [ "anyhow", "serde", "serde_json", - "thiserror", + "thiserror 1.0.64", "uuid", ] @@ -4812,7 +4839,7 @@ dependencies = [ "serde", "spirv", "termcolor", - "thiserror", + "thiserror 1.0.64", "unicode-xid", ] @@ -4902,7 +4929,7 @@ dependencies = [ "path-clean", "regex", "serde_json", - "thiserror", + "thiserror 1.0.64", "tokio", "url", ] @@ -5099,7 +5126,7 @@ dependencies = [ "js-sys", "once_cell", "pin-project-lite", - "thiserror", + "thiserror 1.0.64", ] [[package]] @@ -5129,7 +5156,7 @@ dependencies = [ "opentelemetry_sdk", "prost", "serde_json", - "thiserror", + "thiserror 1.0.64", "tokio", "tonic", "tracing", @@ -5171,7 +5198,7 @@ dependencies = [ "percent-encoding", "rand", "serde_json", - "thiserror", + "thiserror 1.0.64", "tracing", ] @@ -5355,7 +5382,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "311fb059dee1a7b802f036316d790138c613a4e8b180c822e3925a662e9f0c95" dependencies = [ "memchr", - "thiserror", + "thiserror 1.0.64", "ucd-trie", ] @@ -5769,7 +5796,7 @@ dependencies = [ "indexmap 2.3.0", "quick-xml", "strip-ansi-escapes", - "thiserror", + "thiserror 1.0.64", "uuid", ] @@ -5794,7 +5821,7 @@ dependencies = [ "quinn-udp", "rustc-hash 1.1.0", "rustls", - "thiserror", + "thiserror 1.0.64", "tokio", "tracing", ] @@ -5811,7 +5838,7 @@ dependencies = [ "rustc-hash 2.0.0", "rustls", "slab", - "thiserror", + "thiserror 1.0.64", "tinyvec", "tracing", ] @@ -5960,7 +5987,7 @@ checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" dependencies = [ "getrandom", "libredox", - "thiserror", + "thiserror 1.0.64", ] [[package]] @@ -6584,7 +6611,7 @@ dependencies = [ "num-bigint", "serde", "smallvec", - "thiserror", + "thiserror 1.0.64", "v8", ] @@ -7587,7 +7614,16 @@ version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" dependencies = [ - "thiserror-impl", + "thiserror-impl 1.0.64", +] + +[[package]] +name = "thiserror" +version = "2.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c006c85c7651b3cf2ada4584faa36773bd07bac24acfb39f3c431b36d7e667aa" +dependencies = [ + "thiserror-impl 2.0.3", ] [[package]] @@ -7601,6 +7637,17 @@ dependencies = [ "syn 2.0.87", ] +[[package]] +name = "thiserror-impl" +version = "2.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f077553d607adc1caf65430528a576c757a71ed73944b66ebb58ef2bbd243568" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + [[package]] name = "thousands" version = "0.2.0" @@ -7753,7 +7800,7 @@ checksum = "51165dfa029d2a65969413a6cc96f354b86b464498702f174a4efa13608fd8c0" dependencies = [ "either", "futures-util", - "thiserror", + "thiserror 1.0.64", "tokio", ] @@ -8170,7 +8217,7 @@ dependencies = [ "indexmap 2.3.0", "num-bigint", "serde", - "thiserror", + "thiserror 1.0.64", "wtf8", ] @@ -8342,7 +8389,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f270206a91783fd90625c8bb0d8fbd459d0b1d1bf209b656f713f01ae7c04b8" dependencies = [ - "thiserror", + "thiserror 1.0.64", ] [[package]] @@ -8396,7 +8443,7 @@ dependencies = [ "rustc-hash 1.1.0", "serde", "smallvec", - "thiserror", + "thiserror 1.0.64", "web-sys", "wgpu-hal", "wgpu-types", @@ -8437,7 +8484,7 @@ dependencies = [ "raw-window-handle", "rustc-hash 1.1.0", "smallvec", - "thiserror", + "thiserror 1.0.64", "wasm-bindgen", "web-sys", "wgpu-types", @@ -8503,7 +8550,7 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b2b1bf557d947847a30eb73f79aa6cdb3eaf3ce02f5e9599438f77896a62b3c" dependencies = [ - "thiserror", + "thiserror 1.0.64", "windows", ] @@ -8785,7 +8832,7 @@ dependencies = [ "nom 7.1.3", "oid-registry", "rusticata-macros", - "thiserror", + "thiserror 1.0.64", "time", ] @@ -8929,7 +8976,7 @@ dependencies = [ "parking_lot", "rand", "regex", - "thiserror", + "thiserror 1.0.64", "tokio", "tokio-util", "uuid", @@ -8970,7 +9017,7 @@ dependencies = [ "flate2", "indexmap 2.3.0", "memchr", - "thiserror", + "thiserror 1.0.64", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 1ca9fcb66b..f6606b54c3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,18 +46,18 @@ license = "MIT" repository = "https://github.com/denoland/deno" [workspace.dependencies] -deno_ast = { version = "=0.43.3", features = ["transpiling"] } +deno_ast = { version = "=0.44.0", features = ["transpiling"] } deno_core = { version = "0.323.0" } deno_bench_util = { version = "0.174.0", path = "./bench_util" } -deno_config = { version = "=0.39.2", features = ["workspace", "sync"] } -deno_lockfile = "=0.23.1" +deno_config = { version = "=0.39.3", features = ["workspace", "sync"] } +deno_lockfile = "=0.23.2" deno_media_type = { version = "0.2.0", features = ["module_specifier"] } -deno_npm = "=0.25.4" +deno_npm = "=0.25.5" deno_path_util = "=0.2.1" deno_permissions = { version = "0.40.0", path = "./runtime/permissions" } deno_runtime = { version = "0.189.0", path = "./runtime" } -deno_semver = "=0.5.16" +deno_semver = "=0.6.0" deno_terminal = "0.2.0" napi_sym = { version = "0.110.0", path = "./ext/napi/sym" } test_util = { package = "test_server", path = "./tests/util/server" } @@ -115,8 +115,8 @@ console_static_text = "=0.8.1" dashmap = "5.5.3" data-encoding = "2.3.3" data-url = "=0.3.0" -deno_cache_dir = "=0.13.2" -deno_package_json = { version = "0.1.2", default-features = false } +deno_cache_dir = "=0.14.0" +deno_package_json = { version = "0.2.1", default-features = false } dlopen2 = "0.6.1" ecb = "=0.1.2" elliptic-curve = { version = "0.13.4", features = ["alloc", "arithmetic", "ecdh", "std", "pem", "jwk"] } diff --git a/cli/Cargo.toml b/cli/Cargo.toml index a21e5d5c68..ac093a7238 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -72,9 +72,9 @@ deno_ast = { workspace = true, features = ["bundler", "cjs", "codegen", "proposa deno_cache_dir.workspace = true deno_config.workspace = true deno_core = { workspace = true, features = ["include_js_files_for_snapshotting"] } -deno_doc = { version = "=0.161.1", features = ["rust", "comrak"] } -deno_graph = { version = "=0.86.2" } -deno_lint = { version = "=0.68.0", features = ["docs"] } +deno_doc = { version = "=0.161.2", features = ["rust", "comrak"] } +deno_graph = { version = "=0.86.3" } +deno_lint = { version = "=0.68.1", features = ["docs"] } deno_lockfile.workspace = true deno_npm.workspace = true deno_package_json.workspace = true @@ -108,7 +108,7 @@ dotenvy = "0.15.7" dprint-plugin-json = "=0.19.4" dprint-plugin-jupyter = "=0.1.5" dprint-plugin-markdown = "=0.17.8" -dprint-plugin-typescript = "=0.93.2" +dprint-plugin-typescript = "=0.93.3" env_logger = "=0.10.0" fancy-regex = "=0.10.0" faster-hex.workspace = true diff --git a/cli/args/deno_json.rs b/cli/args/deno_json.rs index 3e6eb617a6..c2ba31fd36 100644 --- a/cli/args/deno_json.rs +++ b/cli/args/deno_json.rs @@ -18,12 +18,10 @@ impl<'a> deno_config::fs::DenoConfigFs for DenoConfigFsAdapter<'a> { fn read_to_string_lossy( &self, path: &std::path::Path, - ) -> Result { + ) -> Result, std::io::Error> { self .0 .read_text_file_lossy_sync(path, None) - // todo(https://github.com/denoland/deno_config/pull/140): avoid clone - .map(|s| s.into_owned()) .map_err(|err| err.into_io_error()) } diff --git a/cli/args/lockfile.rs b/cli/args/lockfile.rs index a9eb8a0d7c..6c1a2ca0ef 100644 --- a/cli/args/lockfile.rs +++ b/cli/args/lockfile.rs @@ -109,9 +109,12 @@ impl CliLockfile { let Some(pkg_json) = maybe_pkg_json else { return Default::default(); }; - pkg_json - .resolve_local_package_json_deps() + let deps = pkg_json.resolve_local_package_json_deps(); + + deps + .dependencies .values() + .chain(deps.dev_dependencies.values()) .filter_map(|dep| dep.as_ref().ok()) .filter_map(|dep| match dep { PackageJsonDepValue::Req(req) => { diff --git a/cli/args/package_json.rs b/cli/args/package_json.rs index 7dc75550c3..b0f0a2f9ba 100644 --- a/cli/args/package_json.rs +++ b/cli/args/package_json.rs @@ -8,8 +8,10 @@ use deno_core::serde_json; use deno_core::url::Url; use deno_package_json::PackageJsonDepValue; use deno_package_json::PackageJsonDepValueParseError; +use deno_package_json::PackageJsonDepWorkspaceReq; use deno_semver::npm::NpmPackageReqReference; use deno_semver::package::PackageReq; +use deno_semver::VersionReq; use thiserror::Error; #[derive(Debug)] @@ -95,8 +97,14 @@ impl NpmInstallDepsProvider { if let Some(pkg_json) = &folder.pkg_json { let deps = pkg_json.resolve_local_package_json_deps(); - let mut pkg_pkgs = Vec::with_capacity(deps.len()); - for (alias, dep) in deps { + let mut pkg_pkgs = Vec::with_capacity( + deps.dependencies.len() + deps.dev_dependencies.len(), + ); + for (alias, dep) in deps + .dependencies + .into_iter() + .chain(deps.dev_dependencies.into_iter()) + { let dep = match dep { Ok(dep) => dep, Err(err) => { @@ -131,7 +139,16 @@ impl NpmInstallDepsProvider { }); } } - PackageJsonDepValue::Workspace(version_req) => { + PackageJsonDepValue::Workspace(workspace_version_req) => { + let version_req = match workspace_version_req { + PackageJsonDepWorkspaceReq::VersionReq(version_req) => { + version_req + } + PackageJsonDepWorkspaceReq::Tilde + | PackageJsonDepWorkspaceReq::Caret => { + VersionReq::parse_from_npm("*").unwrap() + } + }; if let Some(pkg) = workspace_npm_pkgs.iter().find(|pkg| { pkg.matches_name_and_version_req(&alias, &version_req) }) { diff --git a/cli/cache/mod.rs b/cli/cache/mod.rs index 73a3895a10..e3e242e975 100644 --- a/cli/cache/mod.rs +++ b/cli/cache/mod.rs @@ -23,6 +23,7 @@ use deno_graph::source::Loader; use deno_runtime::deno_fs; use deno_runtime::deno_permissions::PermissionsContainer; use node_resolver::InNpmPackageChecker; +use std::borrow::Cow; use std::collections::HashMap; use std::path::Path; use std::path::PathBuf; @@ -67,8 +68,11 @@ pub const CACHE_PERM: u32 = 0o644; pub struct RealDenoCacheEnv; impl deno_cache_dir::DenoCacheEnv for RealDenoCacheEnv { - fn read_file_bytes(&self, path: &Path) -> std::io::Result> { - std::fs::read(path) + fn read_file_bytes( + &self, + path: &Path, + ) -> std::io::Result> { + std::fs::read(path).map(Cow::Owned) } fn atomic_write_file( @@ -112,12 +116,13 @@ pub struct DenoCacheEnvFsAdapter<'a>( ); impl<'a> deno_cache_dir::DenoCacheEnv for DenoCacheEnvFsAdapter<'a> { - fn read_file_bytes(&self, path: &Path) -> std::io::Result> { + fn read_file_bytes( + &self, + path: &Path, + ) -> std::io::Result> { self .0 .read_file_sync(path, None) - // todo(https://github.com/denoland/deno_cache_dir/pull/66): avoid clone - .map(|bytes| bytes.into_owned()) .map_err(|err| err.into_io_error()) } diff --git a/cli/factory.rs b/cli/factory.rs index 5d9a2c0824..6937b750f9 100644 --- a/cli/factory.rs +++ b/cli/factory.rs @@ -504,7 +504,12 @@ impl CliFactory { let resolver = cli_options .create_workspace_resolver( self.file_fetcher()?, - if cli_options.use_byonm() { + if cli_options.use_byonm() + && !matches!( + cli_options.sub_command(), + DenoSubcommand::Publish(_) + ) + { PackageJsonDepResolution::Disabled } else { // todo(dsherret): this should be false for nodeModulesDir: true diff --git a/cli/file_fetcher.rs b/cli/file_fetcher.rs index 640f83c35c..f0adc60e3b 100644 --- a/cli/file_fetcher.rs +++ b/cli/file_fetcher.rs @@ -1540,7 +1540,7 @@ mod tests { .unwrap() .unwrap() .content; - String::from_utf8(bytes).unwrap() + String::from_utf8(bytes.into_owned()).unwrap() } #[track_caller] diff --git a/cli/lsp/config.rs b/cli/lsp/config.rs index ea77e36bcf..a629757788 100644 --- a/cli/lsp/config.rs +++ b/cli/lsp/config.rs @@ -41,6 +41,7 @@ use deno_path_util::url_to_file_path; use deno_runtime::deno_node::PackageJson; use indexmap::IndexSet; use lsp_types::ClientCapabilities; +use std::borrow::Cow; use std::collections::BTreeMap; use std::collections::BTreeSet; use std::collections::HashMap; @@ -2092,7 +2093,7 @@ impl CachedFsItems { #[derive(Default)] struct InnerData { stat_calls: CachedFsItems, - read_to_string_calls: CachedFsItems, + read_to_string_calls: CachedFsItems>, } #[derive(Default)] @@ -2113,7 +2114,7 @@ impl DenoConfigFs for CachedDenoConfigFs { fn read_to_string_lossy( &self, path: &Path, - ) -> Result { + ) -> Result, std::io::Error> { self .0 .lock() diff --git a/cli/lsp/documents.rs b/cli/lsp/documents.rs index df51c07a39..b9ec8ffc46 100644 --- a/cli/lsp/documents.rs +++ b/cli/lsp/documents.rs @@ -925,7 +925,7 @@ impl FileSystemDocuments { let content = bytes_to_content( specifier, media_type, - cached_file.content, + cached_file.content.into_owned(), maybe_charset, ) .ok()?; diff --git a/cli/lsp/jsr.rs b/cli/lsp/jsr.rs index 9a738ec287..ab570f6348 100644 --- a/cli/lsp/jsr.rs +++ b/cli/lsp/jsr.rs @@ -262,7 +262,7 @@ fn read_cached_url( cache .get(&cache.cache_item_key(url).ok()?, None) .ok()? - .map(|f| f.content) + .map(|f| f.content.into_owned()) } #[derive(Debug)] diff --git a/cli/tools/registry/diagnostics.rs b/cli/tools/registry/diagnostics.rs index ef38affc30..9c32b8e36d 100644 --- a/cli/tools/registry/diagnostics.rs +++ b/cli/tools/registry/diagnostics.rs @@ -169,7 +169,7 @@ impl Diagnostic for PublishDiagnostic { .. }) => DiagnosticLevel::Warning, FastCheck(_) => DiagnosticLevel::Error, - SpecifierUnfurl(_) => DiagnosticLevel::Warning, + SpecifierUnfurl(d) => d.level(), InvalidPath { .. } => DiagnosticLevel::Error, DuplicatePath { .. } => DiagnosticLevel::Error, UnsupportedFileType { .. } => DiagnosticLevel::Warning, @@ -187,7 +187,7 @@ impl Diagnostic for PublishDiagnostic { use PublishDiagnostic::*; match &self { FastCheck(diagnostic) => diagnostic.code(), - SpecifierUnfurl(diagnostic) => Cow::Borrowed(diagnostic.code()), + SpecifierUnfurl(diagnostic) => diagnostic.code(), InvalidPath { .. } => Cow::Borrowed("invalid-path"), DuplicatePath { .. } => Cow::Borrowed("case-insensitive-duplicate-path"), UnsupportedFileType { .. } => Cow::Borrowed("unsupported-file-type"), @@ -207,7 +207,7 @@ impl Diagnostic for PublishDiagnostic { use PublishDiagnostic::*; match &self { FastCheck(diagnostic) => diagnostic.message(), - SpecifierUnfurl(diagnostic) => Cow::Borrowed(diagnostic.message()), + SpecifierUnfurl(diagnostic) => diagnostic.message(), InvalidPath { message, .. } => Cow::Borrowed(message.as_str()), DuplicatePath { .. } => { Cow::Borrowed("package path is a case insensitive duplicate of another path in the package") @@ -243,17 +243,7 @@ impl Diagnostic for PublishDiagnostic { use PublishDiagnostic::*; match &self { FastCheck(diagnostic) => diagnostic.location(), - SpecifierUnfurl(diagnostic) => match diagnostic { - SpecifierUnfurlerDiagnostic::UnanalyzableDynamicImport { - specifier, - text_info, - range, - } => DiagnosticLocation::ModulePosition { - specifier: Cow::Borrowed(specifier), - text_info: Cow::Borrowed(text_info), - source_pos: DiagnosticSourcePos::SourcePos(range.start), - }, - }, + SpecifierUnfurl(diagnostic) => diagnostic.location(), InvalidPath { path, .. } => { DiagnosticLocation::Path { path: path.clone() } } @@ -325,24 +315,8 @@ impl Diagnostic for PublishDiagnostic { use PublishDiagnostic::*; match &self { - FastCheck(diagnostic) => diagnostic.snippet(), - SpecifierUnfurl(diagnostic) => match diagnostic { - SpecifierUnfurlerDiagnostic::UnanalyzableDynamicImport { - text_info, - range, - .. - } => Some(DiagnosticSnippet { - source: Cow::Borrowed(text_info), - highlights: vec![DiagnosticSnippetHighlight { - style: DiagnosticSnippetHighlightStyle::Warning, - range: DiagnosticSourceRange { - start: DiagnosticSourcePos::SourcePos(range.start), - end: DiagnosticSourcePos::SourcePos(range.end), - }, - description: Some("the unanalyzable dynamic import".into()), - }], - }), - }, + FastCheck(d) => d.snippet(), + SpecifierUnfurl(d) => d.snippet(), InvalidPath { .. } => None, DuplicatePath { .. } => None, UnsupportedFileType { .. } => None, @@ -380,7 +354,7 @@ impl Diagnostic for PublishDiagnostic { use PublishDiagnostic::*; match &self { FastCheck(diagnostic) => diagnostic.hint(), - SpecifierUnfurl(_) => None, + SpecifierUnfurl(d) => d.hint(), InvalidPath { .. } => Some( Cow::Borrowed("rename or remove the file, or add it to 'publish.exclude' in the config file"), ), @@ -436,9 +410,9 @@ impl Diagnostic for PublishDiagnostic { None => None, } } - SyntaxError(diagnostic) => diagnostic.snippet_fixed(), + SyntaxError(d) => d.snippet_fixed(), + SpecifierUnfurl(d) => d.snippet_fixed(), FastCheck(_) - | SpecifierUnfurl(_) | InvalidPath { .. } | DuplicatePath { .. } | UnsupportedFileType { .. } @@ -453,16 +427,8 @@ impl Diagnostic for PublishDiagnostic { fn info(&self) -> Cow<'_, [Cow<'_, str>]> { use PublishDiagnostic::*; match &self { - FastCheck(diagnostic) => { - diagnostic.info() - } - SpecifierUnfurl(diagnostic) => match diagnostic { - SpecifierUnfurlerDiagnostic::UnanalyzableDynamicImport { .. } => Cow::Borrowed(&[ - Cow::Borrowed("after publishing this package, imports from the local import map / package.json do not work"), - Cow::Borrowed("dynamic imports that can not be analyzed at publish time will not be rewritten automatically"), - Cow::Borrowed("make sure the dynamic import is resolvable at runtime without an import map / package.json") - ]), - }, + FastCheck(d) => d.info(), + SpecifierUnfurl(d) => d.info(), InvalidPath { .. } => Cow::Borrowed(&[ Cow::Borrowed("to portably support all platforms, including windows, the allowed characters in package paths are limited"), ]), @@ -503,10 +469,8 @@ impl Diagnostic for PublishDiagnostic { fn docs_url(&self) -> Option> { use PublishDiagnostic::*; match &self { - FastCheck(diagnostic) => diagnostic.docs_url(), - SpecifierUnfurl(diagnostic) => match diagnostic { - SpecifierUnfurlerDiagnostic::UnanalyzableDynamicImport { .. } => None, - }, + FastCheck(d) => d.docs_url(), + SpecifierUnfurl(d) => d.docs_url(), InvalidPath { .. } => { Some(Cow::Borrowed("https://jsr.io/go/invalid-path")) } diff --git a/cli/tools/registry/mod.rs b/cli/tools/registry/mod.rs index a866660f36..001e401459 100644 --- a/cli/tools/registry/mod.rs +++ b/cli/tools/registry/mod.rs @@ -14,7 +14,6 @@ use base64::Engine; use deno_ast::ModuleSpecifier; use deno_config::deno_json::ConfigFile; use deno_config::workspace::JsrPackageConfig; -use deno_config::workspace::PackageJsonDepResolution; use deno_config::workspace::Workspace; use deno_core::anyhow::bail; use deno_core::anyhow::Context; @@ -44,8 +43,6 @@ use crate::cache::ParsedSourceCache; use crate::factory::CliFactory; use crate::graph_util::ModuleGraphCreator; use crate::http_util::HttpClient; -use crate::resolver::CliSloppyImportsResolver; -use crate::resolver::SloppyImportsCachedFs; use crate::tools::check::CheckOptions; use crate::tools::lint::collect_no_slow_type_diagnostics; use crate::tools::registry::diagnostics::PublishDiagnostic; @@ -123,19 +120,8 @@ pub async fn publish( } let specifier_unfurler = Arc::new(SpecifierUnfurler::new( - if cli_options.unstable_sloppy_imports() { - Some(CliSloppyImportsResolver::new(SloppyImportsCachedFs::new( - cli_factory.fs().clone(), - ))) - } else { - None - }, - cli_options - .create_workspace_resolver( - cli_factory.file_fetcher()?, - PackageJsonDepResolution::Enabled, - ) - .await?, + cli_factory.sloppy_imports_resolver()?.cloned(), + cli_factory.workspace_resolver().await?.clone(), cli_options.unstable_bare_node_builtins(), )); diff --git a/cli/tools/registry/pm/deps.rs b/cli/tools/registry/pm/deps.rs index 4778d6f327..b7e1c0f0d4 100644 --- a/cli/tools/registry/pm/deps.rs +++ b/cli/tools/registry/pm/deps.rs @@ -19,8 +19,7 @@ use deno_core::futures::FutureExt; use deno_core::futures::StreamExt; use deno_core::serde_json; use deno_graph::FillFromLockfileOptions; -use deno_package_json::PackageJsonDepValue; -use deno_package_json::PackageJsonDepValueParseError; +use deno_package_json::PackageJsonDepsMap; use deno_package_json::PackageJsonRc; use deno_runtime::deno_permissions::PermissionsContainer; use deno_semver::jsr::JsrPackageReqReference; @@ -32,7 +31,6 @@ use deno_semver::VersionReq; use import_map::ImportMap; use import_map::ImportMapWithDiagnostics; use import_map::SpecifierMapEntry; -use indexmap::IndexMap; use tokio::sync::Semaphore; use crate::args::CliLockfile; @@ -269,94 +267,6 @@ enum PackageJsonDepKind { Dev, } -type PackageJsonDeps = IndexMap< - String, - Result< - (PackageJsonDepKind, PackageJsonDepValue), - PackageJsonDepValueParseError, - >, ->; - -/// Resolve the package.json's dependencies. -// TODO(nathanwhit): Remove once we update deno_package_json with dev deps split out -fn resolve_local_package_json_deps( - package_json: &PackageJsonRc, -) -> PackageJsonDeps { - /// Gets the name and raw version constraint for a registry info or - /// package.json dependency entry taking into account npm package aliases. - fn parse_dep_entry_name_and_raw_version<'a>( - key: &'a str, - value: &'a str, - ) -> (&'a str, &'a str) { - if let Some(package_and_version) = value.strip_prefix("npm:") { - if let Some((name, version)) = package_and_version.rsplit_once('@') { - // if empty, then the name was scoped and there's no version - if name.is_empty() { - (package_and_version, "*") - } else { - (name, version) - } - } else { - (package_and_version, "*") - } - } else { - (key, value) - } - } - - fn parse_entry( - key: &str, - value: &str, - ) -> Result { - if let Some(workspace_key) = value.strip_prefix("workspace:") { - let version_req = VersionReq::parse_from_npm(workspace_key)?; - return Ok(PackageJsonDepValue::Workspace(version_req)); - } - if value.starts_with("file:") - || value.starts_with("git:") - || value.starts_with("http:") - || value.starts_with("https:") - { - return Err(PackageJsonDepValueParseError::Unsupported { - scheme: value.split(':').next().unwrap().to_string(), - }); - } - let (name, version_req) = parse_dep_entry_name_and_raw_version(key, value); - let result = VersionReq::parse_from_npm(version_req); - match result { - Ok(version_req) => Ok(PackageJsonDepValue::Req(PackageReq { - name: name.to_string(), - version_req, - })), - Err(err) => Err(PackageJsonDepValueParseError::VersionReq(err)), - } - } - - fn insert_deps( - deps: Option<&IndexMap>, - result: &mut PackageJsonDeps, - kind: PackageJsonDepKind, - ) { - if let Some(deps) = deps { - for (key, value) in deps { - result.entry(key.to_string()).or_insert_with(|| { - parse_entry(key, value).map(|entry| (kind, entry)) - }); - } - } - } - - let deps = package_json.dependencies.as_ref(); - let dev_deps = package_json.dev_dependencies.as_ref(); - let mut result = IndexMap::new(); - - // favors the deps over dev_deps - insert_deps(deps, &mut result, PackageJsonDepKind::Normal); - insert_deps(dev_deps, &mut result, PackageJsonDepKind::Dev); - - result -} - fn add_deps_from_deno_json( deno_json: &Arc, mut filter: impl DepFilter, @@ -406,40 +316,64 @@ fn add_deps_from_deno_json( fn add_deps_from_package_json( package_json: &PackageJsonRc, - mut filter: impl DepFilter, + filter: impl DepFilter, deps: &mut Vec, ) { - let package_json_deps = resolve_local_package_json_deps(package_json); - for (k, v) in package_json_deps { - let (package_dep_kind, v) = match v { - Ok((k, v)) => (k, v), - Err(e) => { - log::warn!("bad package json dep value: {e}"); - continue; - } - }; - match v { - deno_package_json::PackageJsonDepValue::Req(req) => { - let alias = k.as_str(); - let alias = (alias != req.name).then(|| alias.to_string()); - if !filter.should_include(alias.as_deref(), &req, DepKind::Npm) { + let package_json_deps = package_json.resolve_local_package_json_deps(); + + fn iterate( + package_json: &PackageJsonRc, + mut filter: impl DepFilter, + package_dep_kind: PackageJsonDepKind, + package_json_deps: PackageJsonDepsMap, + deps: &mut Vec, + ) { + for (k, v) in package_json_deps { + let v = match v { + Ok(v) => v, + Err(e) => { + log::warn!("bad package json dep value: {e}"); continue; } - let id = DepId(deps.len()); - deps.push(Dep { - id, - kind: DepKind::Npm, - location: DepLocation::PackageJson( - package_json.clone(), - KeyPath::from_parts([package_dep_kind.into(), k.into()]), - ), - req, - alias, - }) + }; + match v { + deno_package_json::PackageJsonDepValue::Req(req) => { + let alias = k.as_str(); + let alias = (alias != req.name).then(|| alias.to_string()); + if !filter.should_include(alias.as_deref(), &req, DepKind::Npm) { + continue; + } + let id = DepId(deps.len()); + deps.push(Dep { + id, + kind: DepKind::Npm, + location: DepLocation::PackageJson( + package_json.clone(), + KeyPath::from_parts([package_dep_kind.into(), k.into()]), + ), + req, + alias, + }) + } + deno_package_json::PackageJsonDepValue::Workspace(_) => continue, } - deno_package_json::PackageJsonDepValue::Workspace(_) => continue, } } + + iterate( + package_json, + filter, + PackageJsonDepKind::Normal, + package_json_deps.dependencies, + deps, + ); + iterate( + package_json, + filter, + PackageJsonDepKind::Dev, + package_json_deps.dev_dependencies, + deps, + ); } fn deps_from_workspace( diff --git a/cli/tools/registry/unfurl.rs b/cli/tools/registry/unfurl.rs index 90343ac656..bf6aaaf50d 100644 --- a/cli/tools/registry/unfurl.rs +++ b/cli/tools/registry/unfurl.rs @@ -1,19 +1,35 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. +use std::borrow::Cow; +use std::sync::Arc; + +use deno_ast::diagnostics::Diagnostic; +use deno_ast::diagnostics::DiagnosticLevel; +use deno_ast::diagnostics::DiagnosticLocation; +use deno_ast::diagnostics::DiagnosticSnippet; +use deno_ast::diagnostics::DiagnosticSnippetHighlight; +use deno_ast::diagnostics::DiagnosticSnippetHighlightStyle; +use deno_ast::diagnostics::DiagnosticSourcePos; +use deno_ast::diagnostics::DiagnosticSourceRange; use deno_ast::ParsedSource; use deno_ast::SourceRange; use deno_ast::SourceTextInfo; +use deno_ast::SourceTextProvider; use deno_config::workspace::MappedResolution; use deno_config::workspace::PackageJsonDepResolution; use deno_config::workspace::WorkspaceResolver; +use deno_core::anyhow; use deno_core::ModuleSpecifier; use deno_graph::DependencyDescriptor; use deno_graph::DynamicTemplatePart; use deno_graph::ParserModuleAnalyzer; use deno_graph::TypeScriptReference; use deno_package_json::PackageJsonDepValue; +use deno_package_json::PackageJsonDepWorkspaceReq; use deno_resolver::sloppy_imports::SloppyImportsResolutionKind; use deno_runtime::deno_node::is_builtin_node_module; +use deno_semver::Version; +use deno_semver::VersionReq; use crate::resolver::CliSloppyImportsResolver; @@ -24,34 +40,163 @@ pub enum SpecifierUnfurlerDiagnostic { text_info: SourceTextInfo, range: SourceRange, }, + ResolvingNpmWorkspacePackage { + specifier: ModuleSpecifier, + package_name: String, + text_info: SourceTextInfo, + range: SourceRange, + reason: String, + }, } -impl SpecifierUnfurlerDiagnostic { - pub fn code(&self) -> &'static str { +impl Diagnostic for SpecifierUnfurlerDiagnostic { + fn level(&self) -> DiagnosticLevel { match self { - Self::UnanalyzableDynamicImport { .. } => "unanalyzable-dynamic-import", - } - } - - pub fn message(&self) -> &'static str { - match self { - Self::UnanalyzableDynamicImport { .. } => { - "unable to analyze dynamic import" + SpecifierUnfurlerDiagnostic::UnanalyzableDynamicImport { .. } => { + DiagnosticLevel::Warning + } + SpecifierUnfurlerDiagnostic::ResolvingNpmWorkspacePackage { .. } => { + DiagnosticLevel::Error } } } + + fn code(&self) -> Cow<'_, str> { + match self { + Self::UnanalyzableDynamicImport { .. } => "unanalyzable-dynamic-import", + Self::ResolvingNpmWorkspacePackage { .. } => "npm-workspace-package", + } + .into() + } + + fn message(&self) -> Cow<'_, str> { + match self { + Self::UnanalyzableDynamicImport { .. } => { + "unable to analyze dynamic import".into() + } + Self::ResolvingNpmWorkspacePackage { + package_name, + reason, + .. + } => format!( + "failed resolving npm workspace package '{}': {}", + package_name, reason + ) + .into(), + } + } + + fn location(&self) -> deno_ast::diagnostics::DiagnosticLocation { + match self { + SpecifierUnfurlerDiagnostic::UnanalyzableDynamicImport { + specifier, + text_info, + range, + } => DiagnosticLocation::ModulePosition { + specifier: Cow::Borrowed(specifier), + text_info: Cow::Borrowed(text_info), + source_pos: DiagnosticSourcePos::SourcePos(range.start), + }, + SpecifierUnfurlerDiagnostic::ResolvingNpmWorkspacePackage { + specifier, + text_info, + range, + .. + } => DiagnosticLocation::ModulePosition { + specifier: Cow::Borrowed(specifier), + text_info: Cow::Borrowed(text_info), + source_pos: DiagnosticSourcePos::SourcePos(range.start), + }, + } + } + + fn snippet(&self) -> Option> { + match self { + SpecifierUnfurlerDiagnostic::UnanalyzableDynamicImport { + text_info, + range, + .. + } => Some(DiagnosticSnippet { + source: Cow::Borrowed(text_info), + highlights: vec![DiagnosticSnippetHighlight { + style: DiagnosticSnippetHighlightStyle::Warning, + range: DiagnosticSourceRange { + start: DiagnosticSourcePos::SourcePos(range.start), + end: DiagnosticSourcePos::SourcePos(range.end), + }, + description: Some("the unanalyzable dynamic import".into()), + }], + }), + SpecifierUnfurlerDiagnostic::ResolvingNpmWorkspacePackage { + text_info, + range, + .. + } => Some(DiagnosticSnippet { + source: Cow::Borrowed(text_info), + highlights: vec![DiagnosticSnippetHighlight { + style: DiagnosticSnippetHighlightStyle::Warning, + range: DiagnosticSourceRange { + start: DiagnosticSourcePos::SourcePos(range.start), + end: DiagnosticSourcePos::SourcePos(range.end), + }, + description: Some("the unresolved import".into()), + }], + }), + } + } + + fn hint(&self) -> Option> { + match self { + SpecifierUnfurlerDiagnostic::UnanalyzableDynamicImport { .. } => { + None + } + SpecifierUnfurlerDiagnostic::ResolvingNpmWorkspacePackage { .. } => Some( + "make sure the npm workspace package is resolvable and has a version field in its package.json".into() + ), + } + } + + fn snippet_fixed( + &self, + ) -> Option> { + None + } + + fn info(&self) -> Cow<'_, [Cow<'_, str>]> { + match self { + SpecifierUnfurlerDiagnostic::UnanalyzableDynamicImport { .. } => Cow::Borrowed(&[ + Cow::Borrowed("after publishing this package, imports from the local import map / package.json do not work"), + Cow::Borrowed("dynamic imports that can not be analyzed at publish time will not be rewritten automatically"), + Cow::Borrowed("make sure the dynamic import is resolvable at runtime without an import map / package.json") + ]), + SpecifierUnfurlerDiagnostic::ResolvingNpmWorkspacePackage { .. } => { + Cow::Borrowed(&[]) + }, + } + } + + fn docs_url(&self) -> Option> { + None + } +} + +enum UnfurlSpecifierError { + Workspace { + package_name: String, + reason: String, + }, } pub struct SpecifierUnfurler { - sloppy_imports_resolver: Option, - workspace_resolver: WorkspaceResolver, + sloppy_imports_resolver: Option>, + workspace_resolver: Arc, bare_node_builtins: bool, } impl SpecifierUnfurler { pub fn new( - sloppy_imports_resolver: Option, - workspace_resolver: WorkspaceResolver, + sloppy_imports_resolver: Option>, + workspace_resolver: Arc, bare_node_builtins: bool, ) -> Self { debug_assert_eq!( @@ -65,11 +210,45 @@ impl SpecifierUnfurler { } } + fn unfurl_specifier_reporting_diagnostic( + &self, + referrer: &ModuleSpecifier, + specifier: &str, + text_info: &SourceTextInfo, + range: &deno_graph::PositionRange, + diagnostic_reporter: &mut dyn FnMut(SpecifierUnfurlerDiagnostic), + ) -> Option { + match self.unfurl_specifier(referrer, specifier) { + Ok(maybe_unfurled) => maybe_unfurled, + Err(diagnostic) => match diagnostic { + UnfurlSpecifierError::Workspace { + package_name, + reason, + } => { + let range = to_range(text_info, range); + diagnostic_reporter( + SpecifierUnfurlerDiagnostic::ResolvingNpmWorkspacePackage { + specifier: referrer.clone(), + package_name, + text_info: text_info.clone(), + range: SourceRange::new( + text_info.start_pos() + range.start, + text_info.start_pos() + range.end, + ), + reason, + }, + ); + None + } + }, + } + } + fn unfurl_specifier( &self, referrer: &ModuleSpecifier, specifier: &str, - ) -> Option { + ) -> Result, UnfurlSpecifierError> { let resolved = if let Ok(resolved) = self.workspace_resolver.resolve(specifier, referrer) { @@ -120,8 +299,40 @@ impl SpecifierUnfurler { )) .ok() } - PackageJsonDepValue::Workspace(version_req) => { - // todo(#24612): consider warning or error when this is also a jsr package? + PackageJsonDepValue::Workspace(workspace_version_req) => { + let version_req = match workspace_version_req { + PackageJsonDepWorkspaceReq::VersionReq(version_req) => { + Cow::Borrowed(version_req) + } + PackageJsonDepWorkspaceReq::Caret => { + let version = self + .find_workspace_npm_dep_version(alias) + .map_err(|err| UnfurlSpecifierError::Workspace { + package_name: alias.to_string(), + reason: err.to_string(), + })?; + // version was validated, so ok to unwrap + Cow::Owned( + VersionReq::parse_from_npm(&format!("^{}", version)) + .unwrap(), + ) + } + PackageJsonDepWorkspaceReq::Tilde => { + let version = self + .find_workspace_npm_dep_version(alias) + .map_err(|err| UnfurlSpecifierError::Workspace { + package_name: alias.to_string(), + reason: err.to_string(), + })?; + // version was validated, so ok to unwrap + Cow::Owned( + VersionReq::parse_from_npm(&format!("~{}", version)) + .unwrap(), + ) + } + }; + // todo(#24612): warn when this is also a jsr package telling + // people to map the specifiers in the import map ModuleSpecifier::parse(&format!( "npm:{}@{}{}", alias, @@ -151,10 +362,14 @@ impl SpecifierUnfurler { None if self.bare_node_builtins && is_builtin_node_module(specifier) => { format!("node:{specifier}").parse().unwrap() } - None => ModuleSpecifier::options() + None => match ModuleSpecifier::options() .base_url(Some(referrer)) .parse(specifier) - .ok()?, + .ok() + { + Some(value) => value, + None => return Ok(None), + }, }; // TODO(lucacasonato): this requires integration in deno_graph first // let resolved = if let Ok(specifier) = @@ -188,7 +403,7 @@ impl SpecifierUnfurler { }; let relative_resolved = relative_url(&resolved, referrer); if relative_resolved == specifier { - None // nothing to unfurl + Ok(None) // nothing to unfurl } else { log::debug!( "Unfurled specifier: {} from {} -> {}", @@ -196,7 +411,29 @@ impl SpecifierUnfurler { referrer, relative_resolved ); - Some(relative_resolved) + Ok(Some(relative_resolved)) + } + } + + fn find_workspace_npm_dep_version( + &self, + pkg_name: &str, + ) -> Result { + // todo(#24612): warn when this is also a jsr package telling + // people to map the specifiers in the import map + let pkg_json = self + .workspace_resolver + .package_jsons() + .find(|pkg| pkg.name.as_deref() == Some(pkg_name)) + .ok_or_else(|| { + anyhow::anyhow!("unable to find npm package in workspace") + })?; + if let Some(version) = &pkg_json.version { + Ok(Version::parse_from_npm(version)?) + } else { + Err(anyhow::anyhow!( + "missing version in package.json of npm package", + )) } } @@ -208,6 +445,7 @@ impl SpecifierUnfurler { text_info: &SourceTextInfo, dep: &deno_graph::DynamicDependencyDescriptor, text_changes: &mut Vec, + diagnostic_reporter: &mut dyn FnMut(SpecifierUnfurlerDiagnostic), ) -> bool { match &dep.argument { deno_graph::DynamicArgument::String(specifier) => { @@ -217,8 +455,14 @@ impl SpecifierUnfurler { let Some(relative_index) = maybe_relative_index else { return true; // always say it's analyzable for a string }; - let unfurled = self.unfurl_specifier(module_url, specifier); - if let Some(unfurled) = unfurled { + let maybe_unfurled = self.unfurl_specifier_reporting_diagnostic( + module_url, + specifier, + text_info, + &dep.argument_range, + diagnostic_reporter, + ); + if let Some(unfurled) = maybe_unfurled { let start = range.start + relative_index; text_changes.push(deno_ast::TextChange { range: start..start + specifier.len(), @@ -238,7 +482,13 @@ impl SpecifierUnfurler { if !specifier.ends_with('/') { return false; } - let unfurled = self.unfurl_specifier(module_url, specifier); + let unfurled = self.unfurl_specifier_reporting_diagnostic( + module_url, + specifier, + text_info, + &dep.argument_range, + diagnostic_reporter, + ); let Some(unfurled) = unfurled else { return true; // nothing to unfurl }; @@ -280,8 +530,15 @@ impl SpecifierUnfurler { let analyze_specifier = |specifier: &str, range: &deno_graph::PositionRange, - text_changes: &mut Vec| { - if let Some(unfurled) = self.unfurl_specifier(url, specifier) { + text_changes: &mut Vec, + diagnostic_reporter: &mut dyn FnMut(SpecifierUnfurlerDiagnostic)| { + if let Some(unfurled) = self.unfurl_specifier_reporting_diagnostic( + url, + specifier, + text_info, + range, + diagnostic_reporter, + ) { text_changes.push(deno_ast::TextChange { range: to_range(text_info, range), new_text: unfurled, @@ -295,11 +552,17 @@ impl SpecifierUnfurler { &dep.specifier, &dep.specifier_range, &mut text_changes, + diagnostic_reporter, ); } DependencyDescriptor::Dynamic(dep) => { - let success = - self.try_unfurl_dynamic_dep(url, text_info, dep, &mut text_changes); + let success = self.try_unfurl_dynamic_dep( + url, + text_info, + dep, + &mut text_changes, + diagnostic_reporter, + ); if !success { let start_pos = text_info.line_start(dep.argument_range.start.line) @@ -326,6 +589,7 @@ impl SpecifierUnfurler { &specifier_with_range.text, &specifier_with_range.range, &mut text_changes, + diagnostic_reporter, ); } for jsdoc in &module_info.jsdoc_imports { @@ -333,6 +597,7 @@ impl SpecifierUnfurler { &jsdoc.specifier.text, &jsdoc.specifier.range, &mut text_changes, + diagnostic_reporter, ); } if let Some(specifier_with_range) = &module_info.jsx_import_source { @@ -340,6 +605,7 @@ impl SpecifierUnfurler { &specifier_with_range.text, &specifier_with_range.range, &mut text_changes, + diagnostic_reporter, ); } @@ -458,10 +724,10 @@ mod tests { ); let fs = Arc::new(RealFs); let unfurler = SpecifierUnfurler::new( - Some(CliSloppyImportsResolver::new(SloppyImportsCachedFs::new( - fs, + Some(Arc::new(CliSloppyImportsResolver::new( + SloppyImportsCachedFs::new(fs), ))), - workspace_resolver, + Arc::new(workspace_resolver), true, ); @@ -547,4 +813,114 @@ const warn2 = await import(`${expr}`); assert_eq!(unfurled_source, expected_source); } } + + #[test] + fn test_unfurling_npm_dep_workspace_specifier() { + let cwd = testdata_path().join("unfurl").to_path_buf(); + + let pkg_json_add = PackageJson::load_from_value( + cwd.join("add/package.json"), + json!({ "name": "add", "version": "0.1.0", }), + ); + let pkg_json_subtract = PackageJson::load_from_value( + cwd.join("subtract/package.json"), + json!({ "name": "subtract", "version": "0.2.0", }), + ); + let pkg_json_publishing = PackageJson::load_from_value( + cwd.join("publish/package.json"), + json!({ + "name": "@denotest/main", + "version": "1.0.0", + "dependencies": { + "add": "workspace:~", + "subtract": "workspace:^", + "non-existent": "workspace:~", + } + }), + ); + let root_pkg_json = PackageJson::load_from_value( + cwd.join("package.json"), + json!({ "workspaces": ["./publish", "./subtract", "./add"] }), + ); + let workspace_resolver = WorkspaceResolver::new_raw( + Arc::new(ModuleSpecifier::from_directory_path(&cwd).unwrap()), + None, + vec![ResolverWorkspaceJsrPackage { + is_patch: false, + base: ModuleSpecifier::from_directory_path( + cwd.join("publish/jsr.json"), + ) + .unwrap(), + name: "@denotest/main".to_string(), + version: Some(Version::parse_standard("1.0.0").unwrap()), + exports: IndexMap::from([(".".to_string(), "mod.ts".to_string())]), + }], + vec![ + Arc::new(root_pkg_json), + Arc::new(pkg_json_add), + Arc::new(pkg_json_subtract), + Arc::new(pkg_json_publishing), + ], + deno_config::workspace::PackageJsonDepResolution::Enabled, + ); + let fs = Arc::new(RealFs); + let unfurler = SpecifierUnfurler::new( + Some(Arc::new(CliSloppyImportsResolver::new( + SloppyImportsCachedFs::new(fs), + ))), + Arc::new(workspace_resolver), + true, + ); + + { + let source_code = r#"import add from "add"; +import subtract from "subtract"; + +console.log(add, subtract); +"#; + let specifier = + ModuleSpecifier::from_file_path(cwd.join("publish").join("mod.ts")) + .unwrap(); + let source = parse_ast(&specifier, source_code); + let mut d = Vec::new(); + let mut reporter = |diagnostic| d.push(diagnostic); + let unfurled_source = unfurler.unfurl(&specifier, &source, &mut reporter); + assert_eq!(d.len(), 0); + // it will inline the version + let expected_source = r#"import add from "npm:add@~0.1.0"; +import subtract from "npm:subtract@^0.2.0"; + +console.log(add, subtract); +"#; + assert_eq!(unfurled_source, expected_source); + } + + { + let source_code = r#"import nonExistent from "non-existent"; +console.log(nonExistent); +"#; + let specifier = + ModuleSpecifier::from_file_path(cwd.join("publish").join("other.ts")) + .unwrap(); + let source = parse_ast(&specifier, source_code); + let mut d = Vec::new(); + let mut reporter = |diagnostic| d.push(diagnostic); + let unfurled_source = unfurler.unfurl(&specifier, &source, &mut reporter); + assert_eq!(d.len(), 1); + match &d[0] { + SpecifierUnfurlerDiagnostic::ResolvingNpmWorkspacePackage { + package_name, + reason, + .. + } => { + assert_eq!(package_name, "non-existent"); + assert_eq!(reason, "unable to find npm package in workspace"); + } + _ => unreachable!(), + } + // won't make any changes, but the above will be a fatal error + assert!(matches!(d[0].level(), DiagnosticLevel::Error)); + assert_eq!(unfurled_source, source_code); + } + } } diff --git a/ext/node/lib.rs b/ext/node/lib.rs index 9986b0f607..bf593ad432 100644 --- a/ext/node/lib.rs +++ b/ext/node/lib.rs @@ -872,12 +872,10 @@ impl deno_package_json::fs::DenoPkgJsonFs for DenoFsNodeResolverEnv { fn read_to_string_lossy( &self, path: &std::path::Path, - ) -> Result { + ) -> Result, std::io::Error> { self .fs .read_text_file_lossy_sync(path, None) - // todo(https://github.com/denoland/deno_package_json/pull/9): don't clone - .map(|text| text.into_owned()) .map_err(|err| err.into_io_error()) } } @@ -888,12 +886,10 @@ impl<'a> deno_package_json::fs::DenoPkgJsonFs for DenoPkgJsonFsAdapter<'a> { fn read_to_string_lossy( &self, path: &Path, - ) -> Result { + ) -> Result, std::io::Error> { self .0 .read_text_file_lossy_sync(path, None) - // todo(https://github.com/denoland/deno_package_json/pull/9): don't clone - .map(|text| text.into_owned()) .map_err(|err| err.into_io_error()) } } diff --git a/resolvers/deno/npm/byonm.rs b/resolvers/deno/npm/byonm.rs index e9182d47a1..771f23ce23 100644 --- a/resolvers/deno/npm/byonm.rs +++ b/resolvers/deno/npm/byonm.rs @@ -179,7 +179,11 @@ impl ByonmNpmResolver { pkg_json: &PackageJson, ) -> Option { let deps = pkg_json.resolve_local_package_json_deps(); - for (key, value) in deps { + for (key, value) in deps + .dependencies + .into_iter() + .chain(deps.dev_dependencies.into_iter()) + { if let Ok(value) = value { match value { PackageJsonDepValue::Req(dep_req) => { diff --git a/tests/specs/npm/workspace_version_wildcards/__test__.jsonc b/tests/specs/npm/workspace_version_wildcards/__test__.jsonc new file mode 100644 index 0000000000..1dfb3dc6a5 --- /dev/null +++ b/tests/specs/npm/workspace_version_wildcards/__test__.jsonc @@ -0,0 +1,10 @@ +{ + "tempDir": true, + "steps": [{ + "args": "install", + "output": "[WILDCARD]" + }, { + "args": "run e/main.ts", + "output": "main.out" + }] +} diff --git a/tests/specs/npm/workspace_version_wildcards/a/mod.ts b/tests/specs/npm/workspace_version_wildcards/a/mod.ts new file mode 100644 index 0000000000..784e2aed80 --- /dev/null +++ b/tests/specs/npm/workspace_version_wildcards/a/mod.ts @@ -0,0 +1,3 @@ +export function sayHello() { + console.log("Hello from a!"); +} diff --git a/tests/specs/npm/workspace_version_wildcards/a/package.json b/tests/specs/npm/workspace_version_wildcards/a/package.json new file mode 100644 index 0000000000..0b4b7cedc6 --- /dev/null +++ b/tests/specs/npm/workspace_version_wildcards/a/package.json @@ -0,0 +1,7 @@ +{ + "name": "@denotest/a", + "version": "1.0.0", + "exports": { + ".": "./mod.ts" + } +} diff --git a/tests/specs/npm/workspace_version_wildcards/b/mod.ts b/tests/specs/npm/workspace_version_wildcards/b/mod.ts new file mode 100644 index 0000000000..74b0441515 --- /dev/null +++ b/tests/specs/npm/workspace_version_wildcards/b/mod.ts @@ -0,0 +1,3 @@ +export function sayHello() { + console.log("Hello from b!"); +} diff --git a/tests/specs/npm/workspace_version_wildcards/b/package.json b/tests/specs/npm/workspace_version_wildcards/b/package.json new file mode 100644 index 0000000000..d01d890f72 --- /dev/null +++ b/tests/specs/npm/workspace_version_wildcards/b/package.json @@ -0,0 +1,7 @@ +{ + "name": "@denotest/b", + "version": "1.0.0", + "exports": { + ".": "./mod.ts" + } +} diff --git a/tests/specs/npm/workspace_version_wildcards/c/mod.ts b/tests/specs/npm/workspace_version_wildcards/c/mod.ts new file mode 100644 index 0000000000..462fbd398c --- /dev/null +++ b/tests/specs/npm/workspace_version_wildcards/c/mod.ts @@ -0,0 +1,3 @@ +export function sayHello() { + console.log("Hello from c!"); +} diff --git a/tests/specs/npm/workspace_version_wildcards/c/package.json b/tests/specs/npm/workspace_version_wildcards/c/package.json new file mode 100644 index 0000000000..caf23c77cd --- /dev/null +++ b/tests/specs/npm/workspace_version_wildcards/c/package.json @@ -0,0 +1,7 @@ +{ + "name": "@denotest/c", + "version": "1.0.0", + "exports": { + ".": "./mod.ts" + } +} diff --git a/tests/specs/npm/workspace_version_wildcards/d/mod.ts b/tests/specs/npm/workspace_version_wildcards/d/mod.ts new file mode 100644 index 0000000000..a21866ee89 --- /dev/null +++ b/tests/specs/npm/workspace_version_wildcards/d/mod.ts @@ -0,0 +1,3 @@ +export function sayHello() { + console.log("Hello from d!"); +} diff --git a/tests/specs/npm/workspace_version_wildcards/d/package.json b/tests/specs/npm/workspace_version_wildcards/d/package.json new file mode 100644 index 0000000000..b908366c25 --- /dev/null +++ b/tests/specs/npm/workspace_version_wildcards/d/package.json @@ -0,0 +1,7 @@ +{ + "name": "@denotest/d", + "version": "1.2.3", + "exports": { + ".": "./mod.ts" + } +} diff --git a/tests/specs/npm/workspace_version_wildcards/e/main.ts b/tests/specs/npm/workspace_version_wildcards/e/main.ts new file mode 100644 index 0000000000..c626db09e8 --- /dev/null +++ b/tests/specs/npm/workspace_version_wildcards/e/main.ts @@ -0,0 +1,9 @@ +import * as a from "@denotest/a"; +import * as b from "@denotest/b"; +import * as c from "@denotest/c"; +import * as d from "@denotest/d"; + +a.sayHello(); +b.sayHello(); +c.sayHello(); +d.sayHello(); diff --git a/tests/specs/npm/workspace_version_wildcards/e/package.json b/tests/specs/npm/workspace_version_wildcards/e/package.json new file mode 100644 index 0000000000..9dca2bb729 --- /dev/null +++ b/tests/specs/npm/workspace_version_wildcards/e/package.json @@ -0,0 +1,10 @@ +{ + "name": "@denotest/e", + "version": "1.0.0", + "dependencies": { + "@denotest/a": "workspace:*", + "@denotest/b": "workspace:~", + "@denotest/c": "workspace:^", + "@denotest/d": "workspace:1.2.3" + } +} diff --git a/tests/specs/npm/workspace_version_wildcards/main.out b/tests/specs/npm/workspace_version_wildcards/main.out new file mode 100644 index 0000000000..ac501447e5 --- /dev/null +++ b/tests/specs/npm/workspace_version_wildcards/main.out @@ -0,0 +1,4 @@ +Hello from a! +Hello from b! +Hello from c! +Hello from d! diff --git a/tests/specs/npm/workspace_version_wildcards/main.ts b/tests/specs/npm/workspace_version_wildcards/main.ts new file mode 100644 index 0000000000..316503b9ca --- /dev/null +++ b/tests/specs/npm/workspace_version_wildcards/main.ts @@ -0,0 +1,6 @@ +// should resolve these as bare specifiers within the workspace +import * as a from "@denotest/a"; +import * as c from "@denotest/c"; + +a.sayHello(); +c.sayHello(); diff --git a/tests/specs/npm/workspace_version_wildcards/package.json b/tests/specs/npm/workspace_version_wildcards/package.json new file mode 100644 index 0000000000..0516fa6921 --- /dev/null +++ b/tests/specs/npm/workspace_version_wildcards/package.json @@ -0,0 +1,9 @@ +{ + "workspaces": [ + "./a", + "./b", + "./c", + "./d", + "./e" + ] +}