0
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-02-01 12:16:11 -05:00

Merge remote-tracking branch 'upstream/main' into check-workspace-member-compiler-options

This commit is contained in:
Nayeem Rahman 2024-11-30 01:09:30 +00:00
commit 14b3eb2789
45 changed files with 1356 additions and 630 deletions

235
Cargo.lock generated
View file

@ -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,13 +1425,13 @@ dependencies = [
"deno_webgpu",
"image",
"serde",
"thiserror",
"thiserror 1.0.64",
]
[[package]]
name = "deno_config"
version = "0.39.2"
source = "git+https://github.com/denoland/deno_config.git?rev=485e7a71f1057437d2a2c4adddbfbe348a812667#485e7a71f1057437d2a2c4adddbfbe348a812667"
version = "0.39.3"
source = "git+https://github.com/denoland/deno_config.git?branch=compiler-options-from-workspace-member#81d8e844624a8f6b3961213d1480dcc923d08b11"
dependencies = [
"anyhow",
"deno_package_json",
@ -1446,7 +1447,7 @@ dependencies = [
"phf",
"serde",
"serde_json",
"thiserror",
"thiserror 1.0.64",
"url",
]
@ -1507,7 +1508,7 @@ dependencies = [
"chrono",
"deno_core",
"saffron",
"thiserror",
"thiserror 1.0.64",
"tokio",
]
@ -1542,7 +1543,7 @@ dependencies = [
"sha2",
"signature",
"spki",
"thiserror",
"thiserror 1.0.64",
"tokio",
"uuid",
"x25519-dalek",
@ -1550,9 +1551,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",
@ -1577,6 +1578,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"
@ -1601,7 +1625,7 @@ dependencies = [
"rustls-webpki",
"serde",
"serde_json",
"thiserror",
"thiserror 1.0.64",
"tokio",
"tokio-rustls",
"tokio-socks",
@ -1626,7 +1650,7 @@ dependencies = [
"serde",
"serde-value",
"serde_json",
"thiserror",
"thiserror 1.0.64",
"tokio",
"winapi",
]
@ -1649,16 +1673,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",
@ -1678,7 +1702,7 @@ dependencies = [
"serde",
"serde_json",
"sha2",
"thiserror",
"thiserror 2.0.3",
"twox-hash",
"url",
"wasm_dep_analyzer",
@ -1718,7 +1742,7 @@ dependencies = [
"scopeguard",
"serde",
"smallvec",
"thiserror",
"thiserror 1.0.64",
"tokio",
"tokio-util",
]
@ -1772,15 +1796,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",
@ -1796,14 +1820,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]]
@ -1828,7 +1852,7 @@ dependencies = [
"libuv-sys-lite",
"log",
"napi_sym",
"thiserror",
"thiserror 1.0.64",
"windows-sys 0.52.0",
]
@ -1858,7 +1882,7 @@ dependencies = [
"rustls-tokio-stream",
"serde",
"socket2",
"thiserror",
"thiserror 1.0.64",
"tokio",
]
@ -1942,7 +1966,7 @@ dependencies = [
"sm3",
"spki",
"stable_deref_trait",
"thiserror",
"thiserror 1.0.64",
"tokio",
"tokio-eld",
"url",
@ -1956,9 +1980,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",
@ -1969,7 +1993,7 @@ dependencies = [
"monch",
"serde",
"serde_json",
"thiserror",
"thiserror 2.0.3",
"url",
]
@ -1986,20 +2010,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",
]
@ -2010,7 +2036,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff25f6e08e7a0214bbacdd6f7195c7f1ebcd850c87a624e4ff06326b68b42d99"
dependencies = [
"percent-encoding",
"thiserror",
"thiserror 1.0.64",
"url",
]
@ -2027,7 +2053,7 @@ dependencies = [
"once_cell",
"percent-encoding",
"serde",
"thiserror",
"thiserror 1.0.64",
"which 4.4.2",
"winapi",
]
@ -2047,7 +2073,7 @@ dependencies = [
"deno_semver",
"node_resolver",
"test_server",
"thiserror",
"thiserror 1.0.64",
"url",
]
@ -2110,7 +2136,7 @@ dependencies = [
"signal-hook-registry",
"tempfile",
"test_server",
"thiserror",
"thiserror 1.0.64",
"tokio",
"tokio-metrics",
"twox-hash",
@ -2122,32 +2148,33 @@ 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",
]
[[package]]
name = "deno_task_shell"
version = "0.18.1"
version = "0.20.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4f444918f7102c1a5a143e9d57809e499fb4d365070519bf2e8bdb16d586af2a"
checksum = "01e09966ce29f8d26b652a43355397e1df43b85759e7824196bf0ceaeaa9a2f4"
dependencies = [
"anyhow",
"futures",
"glob",
"monch",
"nix",
"os_pipe",
"path-dedot",
"thiserror",
"thiserror 1.0.64",
"tokio",
"tokio-util",
]
[[package]]
@ -2202,7 +2229,7 @@ dependencies = [
"rustls-tokio-stream",
"rustls-webpki",
"serde",
"thiserror",
"thiserror 1.0.64",
"tokio",
"webpki-roots",
]
@ -2248,7 +2275,7 @@ dependencies = [
"deno_console",
"deno_core",
"deno_webidl",
"thiserror",
"thiserror 1.0.64",
"urlpattern",
]
@ -2269,7 +2296,7 @@ dependencies = [
"flate2",
"futures",
"serde",
"thiserror",
"thiserror 1.0.64",
"tokio",
"uuid",
]
@ -2281,7 +2308,7 @@ dependencies = [
"deno_core",
"raw-window-handle",
"serde",
"thiserror",
"thiserror 1.0.64",
"tokio",
"wgpu-core",
"wgpu-types",
@ -2313,7 +2340,7 @@ dependencies = [
"once_cell",
"rustls-tokio-stream",
"serde",
"thiserror",
"thiserror 1.0.64",
"tokio",
]
@ -2324,7 +2351,7 @@ dependencies = [
"deno_core",
"deno_web",
"rusqlite",
"thiserror",
"thiserror 1.0.64",
]
[[package]]
@ -2396,7 +2423,7 @@ dependencies = [
"rand",
"rusqlite",
"serde_json",
"thiserror",
"thiserror 1.0.64",
"tokio",
"tokio-stream",
"uuid",
@ -2689,9 +2716,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",
@ -2837,7 +2864,7 @@ dependencies = [
"debug-ignore",
"indexmap 2.3.0",
"log",
"thiserror",
"thiserror 1.0.64",
"zerocopy",
]
@ -2997,7 +3024,7 @@ dependencies = [
"anyhow",
"async-trait",
"log",
"thiserror",
"thiserror 1.0.64",
"tokio",
"tokio-stream",
]
@ -3032,7 +3059,7 @@ dependencies = [
"rand",
"sha1",
"simdutf8",
"thiserror",
"thiserror 1.0.64",
"tokio",
"utf-8",
]
@ -3090,7 +3117,7 @@ dependencies = [
"deno_terminal 0.1.1",
"parking_lot",
"regex",
"thiserror",
"thiserror 1.0.64",
]
[[package]]
@ -3564,7 +3591,7 @@ dependencies = [
"pest_derive",
"serde",
"serde_json",
"thiserror",
"thiserror 1.0.64",
]
[[package]]
@ -3650,7 +3677,7 @@ dependencies = [
"once_cell",
"radix_trie",
"rand",
"thiserror",
"thiserror 1.0.64",
"tokio",
"tracing",
]
@ -3673,7 +3700,7 @@ dependencies = [
"once_cell",
"rand",
"serde",
"thiserror",
"thiserror 1.0.64",
"tinyvec",
"tokio",
"tracing",
@ -3697,7 +3724,7 @@ dependencies = [
"resolv-conf",
"serde",
"smallvec",
"thiserror",
"thiserror 1.0.64",
"tokio",
"tracing",
]
@ -3715,7 +3742,7 @@ dependencies = [
"futures-util",
"hickory-proto",
"serde",
"thiserror",
"thiserror 1.0.64",
"time",
"tokio",
"tokio-util",
@ -4155,7 +4182,7 @@ dependencies = [
"percent-encoding",
"serde",
"serde_json",
"thiserror",
"thiserror 1.0.64",
"url",
]
@ -4361,7 +4388,7 @@ dependencies = [
"anyhow",
"serde",
"serde_json",
"thiserror",
"thiserror 1.0.64",
"uuid",
]
@ -4811,7 +4838,7 @@ dependencies = [
"serde",
"spirv",
"termcolor",
"thiserror",
"thiserror 1.0.64",
"unicode-xid",
]
@ -4901,7 +4928,7 @@ dependencies = [
"path-clean",
"regex",
"serde_json",
"thiserror",
"thiserror 1.0.64",
"tokio",
"url",
]
@ -5098,7 +5125,7 @@ dependencies = [
"js-sys",
"once_cell",
"pin-project-lite",
"thiserror",
"thiserror 1.0.64",
]
[[package]]
@ -5128,7 +5155,7 @@ dependencies = [
"opentelemetry_sdk",
"prost",
"serde_json",
"thiserror",
"thiserror 1.0.64",
"tokio",
"tonic",
"tracing",
@ -5170,7 +5197,7 @@ dependencies = [
"percent-encoding",
"rand",
"serde_json",
"thiserror",
"thiserror 1.0.64",
"tracing",
]
@ -5354,7 +5381,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "311fb059dee1a7b802f036316d790138c613a4e8b180c822e3925a662e9f0c95"
dependencies = [
"memchr",
"thiserror",
"thiserror 1.0.64",
"ucd-trie",
]
@ -5768,7 +5795,7 @@ dependencies = [
"indexmap 2.3.0",
"quick-xml",
"strip-ansi-escapes",
"thiserror",
"thiserror 1.0.64",
"uuid",
]
@ -5793,7 +5820,7 @@ dependencies = [
"quinn-udp",
"rustc-hash 1.1.0",
"rustls",
"thiserror",
"thiserror 1.0.64",
"tokio",
"tracing",
]
@ -5810,7 +5837,7 @@ dependencies = [
"rustc-hash 2.0.0",
"rustls",
"slab",
"thiserror",
"thiserror 1.0.64",
"tinyvec",
"tracing",
]
@ -5959,7 +5986,7 @@ checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891"
dependencies = [
"getrandom",
"libredox",
"thiserror",
"thiserror 1.0.64",
]
[[package]]
@ -6583,7 +6610,7 @@ dependencies = [
"num-bigint",
"serde",
"smallvec",
"thiserror",
"thiserror 1.0.64",
"v8",
]
@ -7586,7 +7613,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]]
@ -7600,6 +7636,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"
@ -7752,7 +7799,7 @@ checksum = "51165dfa029d2a65969413a6cc96f354b86b464498702f174a4efa13608fd8c0"
dependencies = [
"either",
"futures-util",
"thiserror",
"thiserror 1.0.64",
"tokio",
]
@ -8169,7 +8216,7 @@ dependencies = [
"indexmap 2.3.0",
"num-bigint",
"serde",
"thiserror",
"thiserror 1.0.64",
"wtf8",
]
@ -8341,7 +8388,7 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f270206a91783fd90625c8bb0d8fbd459d0b1d1bf209b656f713f01ae7c04b8"
dependencies = [
"thiserror",
"thiserror 1.0.64",
]
[[package]]
@ -8395,7 +8442,7 @@ dependencies = [
"rustc-hash 1.1.0",
"serde",
"smallvec",
"thiserror",
"thiserror 1.0.64",
"web-sys",
"wgpu-hal",
"wgpu-types",
@ -8436,7 +8483,7 @@ dependencies = [
"raw-window-handle",
"rustc-hash 1.1.0",
"smallvec",
"thiserror",
"thiserror 1.0.64",
"wasm-bindgen",
"web-sys",
"wgpu-types",
@ -8502,7 +8549,7 @@ version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b2b1bf557d947847a30eb73f79aa6cdb3eaf3ce02f5e9599438f77896a62b3c"
dependencies = [
"thiserror",
"thiserror 1.0.64",
"windows",
]
@ -8784,7 +8831,7 @@ dependencies = [
"nom 7.1.3",
"oid-registry",
"rusticata-macros",
"thiserror",
"thiserror 1.0.64",
"time",
]
@ -8928,7 +8975,7 @@ dependencies = [
"parking_lot",
"rand",
"regex",
"thiserror",
"thiserror 1.0.64",
"tokio",
"tokio-util",
"uuid",
@ -8969,7 +9016,7 @@ dependencies = [
"flate2",
"indexmap 2.3.0",
"memchr",
"thiserror",
"thiserror 1.0.64",
]
[[package]]

View file

@ -46,19 +46,19 @@ 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" }
# TODO(nayeemrmn): Use proper version when https://github.com/denoland/deno_config/pull/143 lands!
deno_config = { git = "https://github.com/denoland/deno_config.git", rev = "485e7a71f1057437d2a2c4adddbfbe348a812667", features = ["workspace", "sync"] }
deno_lockfile = "=0.23.1"
deno_config = { git = "https://github.com/denoland/deno_config.git", branch = "compiler-options-from-workspace-member", 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" }
@ -116,8 +116,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"] }

View file

@ -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
@ -82,7 +82,7 @@ deno_path_util.workspace = true
deno_resolver.workspace = true
deno_runtime = { workspace = true, features = ["include_js_files_for_snapshotting"] }
deno_semver.workspace = true
deno_task_shell = "=0.18.1"
deno_task_shell = "=0.20.1"
deno_telemetry.workspace = true
deno_terminal.workspace = true
libsui = "0.5.0"
@ -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

View file

@ -18,12 +18,10 @@ impl<'a> deno_config::fs::DenoConfigFs for DenoConfigFsAdapter<'a> {
fn read_to_string_lossy(
&self,
path: &std::path::Path,
) -> Result<String, std::io::Error> {
) -> Result<std::borrow::Cow<'static, str>, 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())
}

View file

@ -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) => {

View file

@ -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)
}) {

15
cli/cache/mod.rs vendored
View file

@ -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<Vec<u8>> {
std::fs::read(path)
fn read_file_bytes(
&self,
path: &Path,
) -> std::io::Result<Cow<'static, [u8]>> {
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<Vec<u8>> {
fn read_file_bytes(
&self,
path: &Path,
) -> std::io::Result<Cow<'static, [u8]>> {
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())
}

View file

@ -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

View file

@ -1540,7 +1540,7 @@ mod tests {
.unwrap()
.unwrap()
.content;
String::from_utf8(bytes).unwrap()
String::from_utf8(bytes.into_owned()).unwrap()
}
#[track_caller]

View file

@ -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;
@ -2093,7 +2094,7 @@ impl<T: Clone> CachedFsItems<T> {
#[derive(Default)]
struct InnerData {
stat_calls: CachedFsItems<deno_config::fs::FsMetadata>,
read_to_string_calls: CachedFsItems<String>,
read_to_string_calls: CachedFsItems<Cow<'static, str>>,
}
#[derive(Default)]
@ -2114,7 +2115,7 @@ impl DenoConfigFs for CachedDenoConfigFs {
fn read_to_string_lossy(
&self,
path: &Path,
) -> Result<String, std::io::Error> {
) -> Result<Cow<'static, str>, std::io::Error> {
self
.0
.lock()

View file

@ -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()?;

View file

@ -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)]

View file

@ -1297,16 +1297,10 @@ impl TsServer {
{
// When an LSP request is cancelled by the client, the future this is being
// executed under and any local variables here will be dropped at the next
// await point. To pass on that cancellation to the TS thread, we make this
// wrapper which cancels the request's token on drop.
struct DroppableToken(CancellationToken);
impl Drop for DroppableToken {
fn drop(&mut self) {
self.0.cancel();
}
}
// await point. To pass on that cancellation to the TS thread, we use drop_guard
// which cancels the request's token on drop.
let token = token.child_token();
let droppable_token = DroppableToken(token.clone());
let droppable_token = token.clone().drop_guard();
let (tx, mut rx) = oneshot::channel::<Result<String, AnyError>>();
let change = self.pending_change.lock().take();
@ -1320,7 +1314,7 @@ impl TsServer {
tokio::select! {
value = &mut rx => {
let value = value??;
drop(droppable_token);
droppable_token.disarm();
Ok(serde_json::from_str(&value)?)
}
_ = token.cancelled() => {

View file

@ -9,6 +9,7 @@ use deno_npm::resolution::NpmResolutionSnapshot;
use deno_runtime::deno_io::FromRawIoHandle;
use deno_semver::package::PackageNv;
use deno_semver::Version;
use deno_task_shell::KillSignal;
use std::borrow::Cow;
use std::collections::HashSet;
use std::rc::Rc;
@ -155,6 +156,29 @@ impl<'a> LifecycleScripts<'a> {
packages: &[NpmResolutionPackage],
root_node_modules_dir_path: &Path,
progress_bar: &ProgressBar,
) -> Result<(), AnyError> {
let kill_signal = KillSignal::default();
let _drop_signal = kill_signal.clone().drop_guard();
// we don't run with signals forwarded because once signals
// are setup then they're process wide.
self
.finish_with_cancellation(
snapshot,
packages,
root_node_modules_dir_path,
progress_bar,
kill_signal,
)
.await
}
async fn finish_with_cancellation(
self,
snapshot: &NpmResolutionSnapshot,
packages: &[NpmResolutionPackage],
root_node_modules_dir_path: &Path,
progress_bar: &ProgressBar,
kill_signal: KillSignal,
) -> Result<(), AnyError> {
self.warn_not_run_scripts()?;
let get_package_path =
@ -246,6 +270,7 @@ impl<'a> LifecycleScripts<'a> {
stderr: TaskStdio::piped(),
stdout: TaskStdio::piped(),
}),
kill_signal: kill_signal.clone(),
},
)
.await?;

View file

@ -14,6 +14,7 @@ use deno_runtime::deno_node::NodeResolver;
use deno_semver::package::PackageNv;
use deno_task_shell::ExecutableCommand;
use deno_task_shell::ExecuteResult;
use deno_task_shell::KillSignal;
use deno_task_shell::ShellCommand;
use deno_task_shell::ShellCommandContext;
use deno_task_shell::ShellPipeReader;
@ -22,6 +23,7 @@ use lazy_regex::Lazy;
use regex::Regex;
use tokio::task::JoinHandle;
use tokio::task::LocalSet;
use tokio_util::sync::CancellationToken;
use crate::npm::CliNpmResolver;
use crate::npm::InnerCliNpmResolverRef;
@ -45,9 +47,11 @@ impl TaskStdio {
pub fn stdout() -> Self {
Self(None, ShellPipeWriter::stdout())
}
pub fn stderr() -> Self {
Self(None, ShellPipeWriter::stderr())
}
pub fn piped() -> Self {
let (r, w) = deno_task_shell::pipe();
Self(Some(r), w)
@ -62,8 +66,8 @@ pub struct TaskIo {
impl Default for TaskIo {
fn default() -> Self {
Self {
stderr: TaskStdio::stderr(),
stdout: TaskStdio::stdout(),
stderr: TaskStdio::stderr(),
}
}
}
@ -78,6 +82,7 @@ pub struct RunTaskOptions<'a> {
pub custom_commands: HashMap<String, Rc<dyn ShellCommand>>,
pub root_node_modules_dir: Option<&'a Path>,
pub stdio: Option<TaskIo>,
pub kill_signal: KillSignal,
}
pub type TaskCustomCommands = HashMap<String, Rc<dyn ShellCommand>>;
@ -96,8 +101,12 @@ pub async fn run_task(
.with_context(|| format!("Error parsing script '{}'.", opts.task_name))?;
let env_vars =
prepare_env_vars(opts.env_vars, opts.init_cwd, opts.root_node_modules_dir);
let state =
deno_task_shell::ShellState::new(env_vars, opts.cwd, opts.custom_commands);
let state = deno_task_shell::ShellState::new(
env_vars,
opts.cwd,
opts.custom_commands,
opts.kill_signal,
);
let stdio = opts.stdio.unwrap_or_default();
let (
TaskStdio(stdout_read, stdout_write),
@ -537,6 +546,80 @@ fn resolve_managed_npm_commands(
Ok(result)
}
/// Runs a deno task future forwarding any signals received
/// to the process.
///
/// Signal listeners and ctrl+c listening will be setup.
pub async fn run_future_forwarding_signals<TOutput>(
kill_signal: KillSignal,
future: impl std::future::Future<Output = TOutput>,
) -> TOutput {
fn spawn_future_with_cancellation(
future: impl std::future::Future<Output = ()> + 'static,
token: CancellationToken,
) {
deno_core::unsync::spawn(async move {
tokio::select! {
_ = future => {}
_ = token.cancelled() => {}
}
});
}
let token = CancellationToken::new();
let _token_drop_guard = token.clone().drop_guard();
let _drop_guard = kill_signal.clone().drop_guard();
spawn_future_with_cancellation(
listen_ctrl_c(kill_signal.clone()),
token.clone(),
);
#[cfg(unix)]
spawn_future_with_cancellation(
listen_and_forward_all_signals(kill_signal),
token,
);
future.await
}
async fn listen_ctrl_c(kill_signal: KillSignal) {
while let Ok(()) = tokio::signal::ctrl_c().await {
kill_signal.send(deno_task_shell::SignalKind::SIGINT)
}
}
#[cfg(unix)]
async fn listen_and_forward_all_signals(kill_signal: KillSignal) {
use deno_core::futures::FutureExt;
use deno_runtime::signal::SIGNAL_NUMS;
// listen and forward every signal we support
let mut futures = Vec::with_capacity(SIGNAL_NUMS.len());
for signo in SIGNAL_NUMS.iter().copied() {
if signo == libc::SIGKILL || signo == libc::SIGSTOP {
continue; // skip, can't listen to these
}
let kill_signal = kill_signal.clone();
futures.push(
async move {
let Ok(mut stream) = tokio::signal::unix::signal(
tokio::signal::unix::SignalKind::from_raw(signo),
) else {
return;
};
let signal_kind: deno_task_shell::SignalKind = signo.into();
while let Some(()) = stream.recv().await {
kill_signal.send(signal_kind);
}
}
.boxed_local(),
)
}
futures::future::join_all(futures).await;
}
#[cfg(test)]
mod test {

View file

@ -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<Cow<'_, str>> {
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"))
}

View file

@ -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(),
));

View file

@ -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<PackageJsonDepValue, PackageJsonDepValueParseError> {
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<String, String>>,
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<ConfigFile>,
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<Dep>,
) {
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<Dep>,
) {
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(

View file

@ -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<deno_ast::diagnostics::DiagnosticSnippet<'_>> {
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<Cow<'_, str>> {
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<deno_ast::diagnostics::DiagnosticSnippet<'_>> {
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<Cow<'_, str>> {
None
}
}
enum UnfurlSpecifierError {
Workspace {
package_name: String,
reason: String,
},
}
pub struct SpecifierUnfurler {
sloppy_imports_resolver: Option<CliSloppyImportsResolver>,
workspace_resolver: WorkspaceResolver,
sloppy_imports_resolver: Option<Arc<CliSloppyImportsResolver>>,
workspace_resolver: Arc<WorkspaceResolver>,
bare_node_builtins: bool,
}
impl SpecifierUnfurler {
pub fn new(
sloppy_imports_resolver: Option<CliSloppyImportsResolver>,
workspace_resolver: WorkspaceResolver,
sloppy_imports_resolver: Option<Arc<CliSloppyImportsResolver>>,
workspace_resolver: Arc<WorkspaceResolver>,
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<String> {
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<String> {
) -> Result<Option<String>, 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<Version, anyhow::Error> {
// 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<deno_ast::TextChange>,
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<deno_ast::TextChange>| {
if let Some(unfurled) = self.unfurl_specifier(url, specifier) {
text_changes: &mut Vec<deno_ast::TextChange>,
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);
}
}
}

View file

@ -26,6 +26,7 @@ use deno_core::futures::StreamExt;
use deno_core::url::Url;
use deno_path_util::normalize_path;
use deno_runtime::deno_node::NodeResolver;
use deno_task_shell::KillSignal;
use deno_task_shell::ShellCommand;
use indexmap::IndexMap;
use regex::Regex;
@ -37,6 +38,7 @@ use crate::colors;
use crate::factory::CliFactory;
use crate::npm::CliNpmResolver;
use crate::task_runner;
use crate::task_runner::run_future_forwarding_signals;
use crate::util::fs::canonicalize_path;
#[derive(Debug)]
@ -226,28 +228,33 @@ pub async fn execute_script(
concurrency: no_of_concurrent_tasks.into(),
};
if task_flags.eval {
return task_runner
.run_deno_task(
&Url::from_directory_path(cli_options.initial_cwd()).unwrap(),
"",
&TaskDefinition {
command: task_flags.task.as_ref().unwrap().to_string(),
dependencies: vec![],
description: None,
},
)
.await;
}
for task_config in &packages_task_configs {
let exit_code = task_runner.run_tasks(task_config).await?;
if exit_code > 0 {
return Ok(exit_code);
let kill_signal = KillSignal::default();
run_future_forwarding_signals(kill_signal.clone(), async {
if task_flags.eval {
return task_runner
.run_deno_task(
&Url::from_directory_path(cli_options.initial_cwd()).unwrap(),
"",
&TaskDefinition {
command: task_flags.task.as_ref().unwrap().to_string(),
dependencies: vec![],
description: None,
},
kill_signal,
)
.await;
}
}
Ok(0)
for task_config in &packages_task_configs {
let exit_code = task_runner.run_tasks(task_config, &kill_signal).await?;
if exit_code > 0 {
return Ok(exit_code);
}
}
Ok(0)
})
.await
}
struct RunSingleOptions<'a> {
@ -255,6 +262,7 @@ struct RunSingleOptions<'a> {
script: &'a str,
cwd: &'a Path,
custom_commands: HashMap<String, Rc<dyn ShellCommand>>,
kill_signal: KillSignal,
}
struct TaskRunner<'a> {
@ -270,9 +278,10 @@ impl<'a> TaskRunner<'a> {
pub async fn run_tasks(
&self,
pkg_tasks_config: &PackageTaskInfo,
kill_signal: &KillSignal,
) -> Result<i32, deno_core::anyhow::Error> {
match sort_tasks_topo(pkg_tasks_config) {
Ok(sorted) => self.run_tasks_in_parallel(sorted).await,
Ok(sorted) => self.run_tasks_in_parallel(sorted, kill_signal).await,
Err(err) => match err {
TaskError::NotFound(name) => {
if self.task_flags.is_run {
@ -307,6 +316,7 @@ impl<'a> TaskRunner<'a> {
async fn run_tasks_in_parallel(
&self,
tasks: Vec<ResolvedTask<'a>>,
kill_signal: &KillSignal,
) -> Result<i32, deno_core::anyhow::Error> {
struct PendingTasksContext<'a> {
completed: HashSet<usize>,
@ -327,6 +337,7 @@ impl<'a> TaskRunner<'a> {
fn get_next_task<'b>(
&mut self,
runner: &'b TaskRunner<'b>,
kill_signal: &KillSignal,
) -> Option<
LocalBoxFuture<'b, Result<(i32, &'a ResolvedTask<'a>), AnyError>>,
>
@ -349,15 +360,23 @@ impl<'a> TaskRunner<'a> {
}
self.running.insert(task.id);
let kill_signal = kill_signal.clone();
return Some(
async move {
match task.task_or_script {
TaskOrScript::Task(_, def) => {
runner.run_deno_task(task.folder_url, task.name, def).await
runner
.run_deno_task(task.folder_url, task.name, def, kill_signal)
.await
}
TaskOrScript::Script(scripts, _) => {
runner
.run_npm_script(task.folder_url, task.name, scripts)
.run_npm_script(
task.folder_url,
task.name,
scripts,
kill_signal,
)
.await
}
}
@ -380,7 +399,7 @@ impl<'a> TaskRunner<'a> {
while context.has_remaining_tasks() {
while queue.len() < self.concurrency {
if let Some(task) = context.get_next_task(self) {
if let Some(task) = context.get_next_task(self, kill_signal) {
queue.push(task);
} else {
break;
@ -409,6 +428,7 @@ impl<'a> TaskRunner<'a> {
dir_url: &Url,
task_name: &str,
definition: &TaskDefinition,
kill_signal: KillSignal,
) -> Result<i32, deno_core::anyhow::Error> {
let cwd = match &self.task_flags.cwd {
Some(path) => canonicalize_path(&PathBuf::from(path))
@ -426,6 +446,7 @@ impl<'a> TaskRunner<'a> {
script: &definition.command,
cwd: &cwd,
custom_commands,
kill_signal,
})
.await
}
@ -435,6 +456,7 @@ impl<'a> TaskRunner<'a> {
dir_url: &Url,
task_name: &str,
scripts: &IndexMap<String, String>,
kill_signal: KillSignal,
) -> Result<i32, deno_core::anyhow::Error> {
// ensure the npm packages are installed if using a managed resolver
if let Some(npm_resolver) = self.npm_resolver.as_managed() {
@ -466,6 +488,7 @@ impl<'a> TaskRunner<'a> {
script,
cwd: &cwd,
custom_commands: custom_commands.clone(),
kill_signal: kill_signal.clone(),
})
.await?;
if exit_code > 0 {
@ -486,6 +509,7 @@ impl<'a> TaskRunner<'a> {
script,
cwd,
custom_commands,
kill_signal,
} = opts;
output_task(
@ -504,6 +528,7 @@ impl<'a> TaskRunner<'a> {
argv: self.cli_options.argv(),
root_node_modules_dir: self.npm_resolver.root_node_modules_path(),
stdio: None,
kill_signal,
})
.await?
.exit_code,

View file

@ -872,12 +872,10 @@ impl deno_package_json::fs::DenoPkgJsonFs for DenoFsNodeResolverEnv {
fn read_to_string_lossy(
&self,
path: &std::path::Path,
) -> Result<String, std::io::Error> {
) -> Result<Cow<'static, str>, 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<String, std::io::Error> {
) -> Result<Cow<'static, str>, 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())
}
}

View file

@ -179,7 +179,11 @@ impl<Fs: DenoResolverFs, TEnv: NodeResolverEnv> ByonmNpmResolver<Fs, TEnv> {
pkg_json: &PackageJson,
) -> Option<String> {
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) => {

View file

@ -34,6 +34,7 @@ pub mod inspector_server;
pub mod js;
pub mod ops;
pub mod permissions;
pub mod signal;
pub mod snapshot;
pub mod sys_info;
pub mod tokio_util;

View file

@ -256,9 +256,7 @@ impl TryFrom<ExitStatus> for ChildStatus {
success: false,
code: 128 + signal,
#[cfg(unix)]
signal: Some(
crate::ops::signal::signal_int_to_str(signal)?.to_string(),
),
signal: Some(crate::signal::signal_int_to_str(signal)?.to_string()),
#[cfg(not(unix))]
signal: None,
}
@ -1076,7 +1074,8 @@ mod deprecated {
#[cfg(unix)]
pub fn kill(pid: i32, signal: &str) -> Result<(), ProcessError> {
let signo = super::super::signal::signal_str_to_int(signal)?;
let signo = crate::signal::signal_str_to_int(signal)
.map_err(SignalError::InvalidSignalStr)?;
use nix::sys::signal::kill as unix_kill;
use nix::sys::signal::Signal;
use nix::unistd::Pid;
@ -1099,7 +1098,12 @@ mod deprecated {
use winapi::um::winnt::PROCESS_TERMINATE;
if !matches!(signal, "SIGKILL" | "SIGTERM") {
Err(SignalError::InvalidSignalStr(signal.to_string()).into())
Err(
SignalError::InvalidSignalStr(crate::signal::InvalidSignalStrError(
signal.to_string(),
))
.into(),
)
} else if pid <= 0 {
Err(ProcessError::InvalidPid)
} else {

View file

@ -46,34 +46,10 @@ deno_core::extension!(
#[derive(Debug, thiserror::Error)]
pub enum SignalError {
#[cfg(any(
target_os = "android",
target_os = "linux",
target_os = "openbsd",
target_os = "openbsd",
target_os = "macos",
target_os = "solaris",
target_os = "illumos"
))]
#[error("Invalid signal: {0}")]
InvalidSignalStr(String),
#[cfg(any(
target_os = "android",
target_os = "linux",
target_os = "openbsd",
target_os = "openbsd",
target_os = "macos",
target_os = "solaris",
target_os = "illumos"
))]
#[error("Invalid signal: {0}")]
InvalidSignalInt(libc::c_int),
#[cfg(target_os = "windows")]
#[error("Windows only supports ctrl-c (SIGINT) and ctrl-break (SIGBREAK), but got {0}")]
InvalidSignalStr(String),
#[cfg(target_os = "windows")]
#[error("Windows only supports ctrl-c (SIGINT) and ctrl-break (SIGBREAK), but got {0}")]
InvalidSignalInt(libc::c_int),
#[error(transparent)]
InvalidSignalStr(#[from] crate::signal::InvalidSignalStrError),
#[error(transparent)]
InvalidSignalInt(#[from] crate::signal::InvalidSignalIntError),
#[error("Binding to signal '{0}' is not allowed")]
SignalNotAllowed(String),
#[error("{0}")]
@ -181,218 +157,6 @@ impl Resource for SignalStreamResource {
}
}
macro_rules! first_literal {
($head:literal $(, $tail:literal)*) => {
$head
};
}
macro_rules! signal_dict {
($(($number:literal, $($name:literal)|+)),*) => {
pub fn signal_str_to_int(s: &str) -> Result<libc::c_int, SignalError> {
match s {
$($($name)|* => Ok($number),)*
_ => Err(SignalError::InvalidSignalStr(s.to_string())),
}
}
pub fn signal_int_to_str(s: libc::c_int) -> Result<&'static str, SignalError> {
match s {
$($number => Ok(first_literal!($($name),+)),)*
_ => Err(SignalError::InvalidSignalInt(s)),
}
}
}
}
#[cfg(target_os = "freebsd")]
signal_dict!(
(1, "SIGHUP"),
(2, "SIGINT"),
(3, "SIGQUIT"),
(4, "SIGILL"),
(5, "SIGTRAP"),
(6, "SIGABRT" | "SIGIOT"),
(7, "SIGEMT"),
(8, "SIGFPE"),
(9, "SIGKILL"),
(10, "SIGBUS"),
(11, "SIGSEGV"),
(12, "SIGSYS"),
(13, "SIGPIPE"),
(14, "SIGALRM"),
(15, "SIGTERM"),
(16, "SIGURG"),
(17, "SIGSTOP"),
(18, "SIGTSTP"),
(19, "SIGCONT"),
(20, "SIGCHLD"),
(21, "SIGTTIN"),
(22, "SIGTTOU"),
(23, "SIGIO"),
(24, "SIGXCPU"),
(25, "SIGXFSZ"),
(26, "SIGVTALRM"),
(27, "SIGPROF"),
(28, "SIGWINCH"),
(29, "SIGINFO"),
(30, "SIGUSR1"),
(31, "SIGUSR2"),
(32, "SIGTHR"),
(33, "SIGLIBRT")
);
#[cfg(target_os = "openbsd")]
signal_dict!(
(1, "SIGHUP"),
(2, "SIGINT"),
(3, "SIGQUIT"),
(4, "SIGILL"),
(5, "SIGTRAP"),
(6, "SIGABRT" | "SIGIOT"),
(7, "SIGEMT"),
(8, "SIGKILL"),
(10, "SIGBUS"),
(11, "SIGSEGV"),
(12, "SIGSYS"),
(13, "SIGPIPE"),
(14, "SIGALRM"),
(15, "SIGTERM"),
(16, "SIGURG"),
(17, "SIGSTOP"),
(18, "SIGTSTP"),
(19, "SIGCONT"),
(20, "SIGCHLD"),
(21, "SIGTTIN"),
(22, "SIGTTOU"),
(23, "SIGIO"),
(24, "SIGXCPU"),
(25, "SIGXFSZ"),
(26, "SIGVTALRM"),
(27, "SIGPROF"),
(28, "SIGWINCH"),
(29, "SIGINFO"),
(30, "SIGUSR1"),
(31, "SIGUSR2"),
(32, "SIGTHR")
);
#[cfg(any(target_os = "android", target_os = "linux"))]
signal_dict!(
(1, "SIGHUP"),
(2, "SIGINT"),
(3, "SIGQUIT"),
(4, "SIGILL"),
(5, "SIGTRAP"),
(6, "SIGABRT" | "SIGIOT"),
(7, "SIGBUS"),
(8, "SIGFPE"),
(9, "SIGKILL"),
(10, "SIGUSR1"),
(11, "SIGSEGV"),
(12, "SIGUSR2"),
(13, "SIGPIPE"),
(14, "SIGALRM"),
(15, "SIGTERM"),
(16, "SIGSTKFLT"),
(17, "SIGCHLD"),
(18, "SIGCONT"),
(19, "SIGSTOP"),
(20, "SIGTSTP"),
(21, "SIGTTIN"),
(22, "SIGTTOU"),
(23, "SIGURG"),
(24, "SIGXCPU"),
(25, "SIGXFSZ"),
(26, "SIGVTALRM"),
(27, "SIGPROF"),
(28, "SIGWINCH"),
(29, "SIGIO" | "SIGPOLL"),
(30, "SIGPWR"),
(31, "SIGSYS" | "SIGUNUSED")
);
#[cfg(target_os = "macos")]
signal_dict!(
(1, "SIGHUP"),
(2, "SIGINT"),
(3, "SIGQUIT"),
(4, "SIGILL"),
(5, "SIGTRAP"),
(6, "SIGABRT" | "SIGIOT"),
(7, "SIGEMT"),
(8, "SIGFPE"),
(9, "SIGKILL"),
(10, "SIGBUS"),
(11, "SIGSEGV"),
(12, "SIGSYS"),
(13, "SIGPIPE"),
(14, "SIGALRM"),
(15, "SIGTERM"),
(16, "SIGURG"),
(17, "SIGSTOP"),
(18, "SIGTSTP"),
(19, "SIGCONT"),
(20, "SIGCHLD"),
(21, "SIGTTIN"),
(22, "SIGTTOU"),
(23, "SIGIO"),
(24, "SIGXCPU"),
(25, "SIGXFSZ"),
(26, "SIGVTALRM"),
(27, "SIGPROF"),
(28, "SIGWINCH"),
(29, "SIGINFO"),
(30, "SIGUSR1"),
(31, "SIGUSR2")
);
#[cfg(any(target_os = "solaris", target_os = "illumos"))]
signal_dict!(
(1, "SIGHUP"),
(2, "SIGINT"),
(3, "SIGQUIT"),
(4, "SIGILL"),
(5, "SIGTRAP"),
(6, "SIGABRT" | "SIGIOT"),
(7, "SIGEMT"),
(8, "SIGFPE"),
(9, "SIGKILL"),
(10, "SIGBUS"),
(11, "SIGSEGV"),
(12, "SIGSYS"),
(13, "SIGPIPE"),
(14, "SIGALRM"),
(15, "SIGTERM"),
(16, "SIGUSR1"),
(17, "SIGUSR2"),
(18, "SIGCHLD"),
(19, "SIGPWR"),
(20, "SIGWINCH"),
(21, "SIGURG"),
(22, "SIGPOLL"),
(23, "SIGSTOP"),
(24, "SIGTSTP"),
(25, "SIGCONT"),
(26, "SIGTTIN"),
(27, "SIGTTOU"),
(28, "SIGVTALRM"),
(29, "SIGPROF"),
(30, "SIGXCPU"),
(31, "SIGXFSZ"),
(32, "SIGWAITING"),
(33, "SIGLWP"),
(34, "SIGFREEZE"),
(35, "SIGTHAW"),
(36, "SIGCANCEL"),
(37, "SIGLOST"),
(38, "SIGXRES"),
(39, "SIGJVM1"),
(40, "SIGJVM2")
);
#[cfg(target_os = "windows")]
signal_dict!((2, "SIGINT"), (21, "SIGBREAK"));
#[cfg(unix)]
#[op2(fast)]
#[smi]
@ -400,7 +164,7 @@ fn op_signal_bind(
state: &mut OpState,
#[string] sig: &str,
) -> Result<ResourceId, SignalError> {
let signo = signal_str_to_int(sig)?;
let signo = crate::signal::signal_str_to_int(sig)?;
if signal_hook_registry::FORBIDDEN.contains(&signo) {
return Err(SignalError::SignalNotAllowed(sig.to_string()));
}
@ -437,7 +201,7 @@ fn op_signal_bind(
state: &mut OpState,
#[string] sig: &str,
) -> Result<ResourceId, SignalError> {
let signo = signal_str_to_int(sig)?;
let signo = crate::signal::signal_str_to_int(sig)?;
let resource = SignalStreamResource {
signal: AsyncRefCell::new(match signo {
// SIGINT

257
runtime/signal.rs Normal file
View file

@ -0,0 +1,257 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
#[cfg(target_os = "windows")]
#[derive(Debug, thiserror::Error)]
#[error("Windows only supports ctrl-c (SIGINT) and ctrl-break (SIGBREAK), but got {0}")]
pub struct InvalidSignalStrError(pub String);
#[cfg(any(
target_os = "android",
target_os = "linux",
target_os = "openbsd",
target_os = "openbsd",
target_os = "macos",
target_os = "solaris",
target_os = "illumos"
))]
#[derive(Debug, thiserror::Error)]
#[error("Invalid signal: {0}")]
pub struct InvalidSignalStrError(pub String);
#[cfg(target_os = "windows")]
#[derive(Debug, thiserror::Error)]
#[error("Windows only supports ctrl-c (SIGINT) and ctrl-break (SIGBREAK), but got {0}")]
pub struct InvalidSignalIntError(pub libc::c_int);
#[cfg(any(
target_os = "android",
target_os = "linux",
target_os = "openbsd",
target_os = "openbsd",
target_os = "macos",
target_os = "solaris",
target_os = "illumos"
))]
#[derive(Debug, thiserror::Error)]
#[error("Invalid signal: {0}")]
pub struct InvalidSignalIntError(pub libc::c_int);
macro_rules! first_literal {
($head:literal $(, $tail:literal)*) => {
$head
};
}
macro_rules! signal_dict {
($(($number:literal, $($name:literal)|+)),*) => {
pub const SIGNAL_NUMS: &'static [libc::c_int] = &[
$(
$number
),*
];
pub fn signal_str_to_int(s: &str) -> Result<libc::c_int, InvalidSignalStrError> {
match s {
$($($name)|* => Ok($number),)*
_ => Err(InvalidSignalStrError(s.to_string())),
}
}
pub fn signal_int_to_str(s: libc::c_int) -> Result<&'static str, InvalidSignalIntError> {
match s {
$($number => Ok(first_literal!($($name),+)),)*
_ => Err(InvalidSignalIntError(s)),
}
}
}
}
#[cfg(target_os = "freebsd")]
signal_dict!(
(1, "SIGHUP"),
(2, "SIGINT"),
(3, "SIGQUIT"),
(4, "SIGILL"),
(5, "SIGTRAP"),
(6, "SIGABRT" | "SIGIOT"),
(7, "SIGEMT"),
(8, "SIGFPE"),
(9, "SIGKILL"),
(10, "SIGBUS"),
(11, "SIGSEGV"),
(12, "SIGSYS"),
(13, "SIGPIPE"),
(14, "SIGALRM"),
(15, "SIGTERM"),
(16, "SIGURG"),
(17, "SIGSTOP"),
(18, "SIGTSTP"),
(19, "SIGCONT"),
(20, "SIGCHLD"),
(21, "SIGTTIN"),
(22, "SIGTTOU"),
(23, "SIGIO"),
(24, "SIGXCPU"),
(25, "SIGXFSZ"),
(26, "SIGVTALRM"),
(27, "SIGPROF"),
(28, "SIGWINCH"),
(29, "SIGINFO"),
(30, "SIGUSR1"),
(31, "SIGUSR2"),
(32, "SIGTHR"),
(33, "SIGLIBRT")
);
#[cfg(target_os = "openbsd")]
signal_dict!(
(1, "SIGHUP"),
(2, "SIGINT"),
(3, "SIGQUIT"),
(4, "SIGILL"),
(5, "SIGTRAP"),
(6, "SIGABRT" | "SIGIOT"),
(7, "SIGEMT"),
(8, "SIGKILL"),
(10, "SIGBUS"),
(11, "SIGSEGV"),
(12, "SIGSYS"),
(13, "SIGPIPE"),
(14, "SIGALRM"),
(15, "SIGTERM"),
(16, "SIGURG"),
(17, "SIGSTOP"),
(18, "SIGTSTP"),
(19, "SIGCONT"),
(20, "SIGCHLD"),
(21, "SIGTTIN"),
(22, "SIGTTOU"),
(23, "SIGIO"),
(24, "SIGXCPU"),
(25, "SIGXFSZ"),
(26, "SIGVTALRM"),
(27, "SIGPROF"),
(28, "SIGWINCH"),
(29, "SIGINFO"),
(30, "SIGUSR1"),
(31, "SIGUSR2"),
(32, "SIGTHR")
);
#[cfg(any(target_os = "android", target_os = "linux"))]
signal_dict!(
(1, "SIGHUP"),
(2, "SIGINT"),
(3, "SIGQUIT"),
(4, "SIGILL"),
(5, "SIGTRAP"),
(6, "SIGABRT" | "SIGIOT"),
(7, "SIGBUS"),
(8, "SIGFPE"),
(9, "SIGKILL"),
(10, "SIGUSR1"),
(11, "SIGSEGV"),
(12, "SIGUSR2"),
(13, "SIGPIPE"),
(14, "SIGALRM"),
(15, "SIGTERM"),
(16, "SIGSTKFLT"),
(17, "SIGCHLD"),
(18, "SIGCONT"),
(19, "SIGSTOP"),
(20, "SIGTSTP"),
(21, "SIGTTIN"),
(22, "SIGTTOU"),
(23, "SIGURG"),
(24, "SIGXCPU"),
(25, "SIGXFSZ"),
(26, "SIGVTALRM"),
(27, "SIGPROF"),
(28, "SIGWINCH"),
(29, "SIGIO" | "SIGPOLL"),
(30, "SIGPWR"),
(31, "SIGSYS" | "SIGUNUSED")
);
#[cfg(target_os = "macos")]
signal_dict!(
(1, "SIGHUP"),
(2, "SIGINT"),
(3, "SIGQUIT"),
(4, "SIGILL"),
(5, "SIGTRAP"),
(6, "SIGABRT" | "SIGIOT"),
(7, "SIGEMT"),
(8, "SIGFPE"),
(9, "SIGKILL"),
(10, "SIGBUS"),
(11, "SIGSEGV"),
(12, "SIGSYS"),
(13, "SIGPIPE"),
(14, "SIGALRM"),
(15, "SIGTERM"),
(16, "SIGURG"),
(17, "SIGSTOP"),
(18, "SIGTSTP"),
(19, "SIGCONT"),
(20, "SIGCHLD"),
(21, "SIGTTIN"),
(22, "SIGTTOU"),
(23, "SIGIO"),
(24, "SIGXCPU"),
(25, "SIGXFSZ"),
(26, "SIGVTALRM"),
(27, "SIGPROF"),
(28, "SIGWINCH"),
(29, "SIGINFO"),
(30, "SIGUSR1"),
(31, "SIGUSR2")
);
#[cfg(any(target_os = "solaris", target_os = "illumos"))]
signal_dict!(
(1, "SIGHUP"),
(2, "SIGINT"),
(3, "SIGQUIT"),
(4, "SIGILL"),
(5, "SIGTRAP"),
(6, "SIGABRT" | "SIGIOT"),
(7, "SIGEMT"),
(8, "SIGFPE"),
(9, "SIGKILL"),
(10, "SIGBUS"),
(11, "SIGSEGV"),
(12, "SIGSYS"),
(13, "SIGPIPE"),
(14, "SIGALRM"),
(15, "SIGTERM"),
(16, "SIGUSR1"),
(17, "SIGUSR2"),
(18, "SIGCHLD"),
(19, "SIGPWR"),
(20, "SIGWINCH"),
(21, "SIGURG"),
(22, "SIGPOLL"),
(23, "SIGSTOP"),
(24, "SIGTSTP"),
(25, "SIGCONT"),
(26, "SIGTTIN"),
(27, "SIGTTOU"),
(28, "SIGVTALRM"),
(29, "SIGPROF"),
(30, "SIGXCPU"),
(31, "SIGXFSZ"),
(32, "SIGWAITING"),
(33, "SIGLWP"),
(34, "SIGFREEZE"),
(35, "SIGTHAW"),
(36, "SIGCANCEL"),
(37, "SIGLOST"),
(38, "SIGXRES"),
(39, "SIGJVM1"),
(40, "SIGJVM2")
);
#[cfg(target_os = "windows")]
signal_dict!((2, "SIGINT"), (21, "SIGBREAK"));

View file

@ -0,0 +1,10 @@
{
"tempDir": true,
"steps": [{
"args": "install",
"output": "[WILDCARD]"
}, {
"args": "run e/main.ts",
"output": "main.out"
}]
}

View file

@ -0,0 +1,3 @@
export function sayHello() {
console.log("Hello from a!");
}

View file

@ -0,0 +1,7 @@
{
"name": "@denotest/a",
"version": "1.0.0",
"exports": {
".": "./mod.ts"
}
}

View file

@ -0,0 +1,3 @@
export function sayHello() {
console.log("Hello from b!");
}

View file

@ -0,0 +1,7 @@
{
"name": "@denotest/b",
"version": "1.0.0",
"exports": {
".": "./mod.ts"
}
}

View file

@ -0,0 +1,3 @@
export function sayHello() {
console.log("Hello from c!");
}

View file

@ -0,0 +1,7 @@
{
"name": "@denotest/c",
"version": "1.0.0",
"exports": {
".": "./mod.ts"
}
}

View file

@ -0,0 +1,3 @@
export function sayHello() {
console.log("Hello from d!");
}

View file

@ -0,0 +1,7 @@
{
"name": "@denotest/d",
"version": "1.2.3",
"exports": {
".": "./mod.ts"
}
}

View file

@ -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();

View file

@ -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"
}
}

View file

@ -0,0 +1,4 @@
Hello from a!
Hello from b!
Hello from c!
Hello from d!

View file

@ -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();

View file

@ -0,0 +1,9 @@
{
"workspaces": [
"./a",
"./b",
"./c",
"./d",
"./e"
]
}

View file

@ -0,0 +1,8 @@
{
// signals don't really exist on windows
"if": "unix",
// this runs a deno task
"args": "run -A --check sender.ts",
// just ensure this doesn't hang and completes successfully
"output": "[WILDCARD]"
}

View file

@ -0,0 +1,5 @@
{
"tasks": {
"listener": "deno run listener.ts"
}
}

View file

@ -0,0 +1,16 @@
import { signals } from "./signals.ts";
for (const signal of signals) {
Deno.addSignalListener(signal, () => {
console.log("Received", signal);
if (signal === "SIGTERM") {
Deno.exit(0);
}
});
}
setInterval(() => {
// keep alive
}, 1000);
console.log("Ready");

View file

@ -0,0 +1,55 @@
import { signals } from "./signals.ts";
class StdoutReader {
readonly #reader: ReadableStreamDefaultReader<string>;
#text = "";
constructor(stream: ReadableStream<Uint8Array>) {
const textStream = stream.pipeThrough(new TextDecoderStream());
this.#reader = textStream.getReader();
}
[Symbol.dispose]() {
this.#reader.releaseLock();
}
async waitForText(waitingText: string) {
if (this.#text.includes(waitingText)) {
return;
}
while (true) {
const { value, done } = await this.#reader.read();
if (value) {
this.#text += value;
if (this.#text.includes(waitingText)) {
break;
}
}
if (done) {
throw new Error("Did not find text: " + waitingText);
}
}
}
}
const command = new Deno.Command(Deno.execPath(), {
args: ["task", "listener"],
stdout: "piped",
});
const child = command.spawn();
const reader = new StdoutReader(child.stdout!);
await reader.waitForText("Ready");
for (const signal of signals) {
if (signal === "SIGTERM") {
continue;
}
console.error("Sending", signal);
child.kill(signal);
await reader.waitForText("Received " + signal);
}
console.error("Sending SIGTERM");
child.kill("SIGTERM");

View file

@ -0,0 +1,65 @@
const signals = [
"SIGABRT",
"SIGALRM",
"SIGBUS",
"SIGCHLD",
"SIGCONT",
"SIGEMT",
"SIGFPE",
"SIGHUP",
"SIGILL",
"SIGINFO",
"SIGINT",
"SIGIO",
"SIGPOLL",
"SIGPIPE",
"SIGPROF",
"SIGPWR",
"SIGQUIT",
"SIGSEGV",
"SIGSTKFLT",
"SIGSYS",
"SIGTERM",
"SIGTRAP",
"SIGTSTP",
"SIGTTIN",
"SIGTTOU",
"SIGURG",
"SIGUSR1",
"SIGUSR2",
"SIGVTALRM",
"SIGWINCH",
"SIGXCPU",
"SIGXFSZ",
] as const;
// SIGKILL and SIGSTOP are not stoppable, SIGBREAK is for windows, and SIGUNUSED is not defined
type SignalsToTest = Exclude<
Deno.Signal,
"SIGKILL" | "SIGSTOP" | "SIGBREAK" | "SIGUNUSED"
>;
type EnsureAllSignalsIncluded = SignalsToTest extends typeof signals[number]
? typeof signals[number] extends SignalsToTest ? true
: never
: never;
const _checkSignals: EnsureAllSignalsIncluded = true;
const osSpecificSignals = signals.filter((s) => {
switch (s) {
case "SIGEMT":
return Deno.build.os === "darwin";
case "SIGINFO":
case "SIGFPE":
case "SIGILL":
case "SIGSEGV":
return Deno.build.os === "freebsd";
case "SIGPOLL":
case "SIGPWR":
case "SIGSTKFLT":
return Deno.build.os === "linux";
default:
return true;
}
});
export { osSpecificSignals as signals };