mirror of
https://github.com/denoland/deno.git
synced 2025-01-21 04:52:26 -05:00
Merge branch 'main' into lsc_cache
This commit is contained in:
commit
d62e31af02
103 changed files with 1772 additions and 770 deletions
2
.github/workflows/ci.generate.ts
vendored
2
.github/workflows/ci.generate.ts
vendored
|
@ -5,7 +5,7 @@ import { stringify } from "jsr:@std/yaml@^0.221/stringify";
|
|||
// Bump this number when you want to purge the cache.
|
||||
// Note: the tools/release/01_bump_crate_versions.ts script will update this version
|
||||
// automatically via regex, so ensure that this line maintains this format.
|
||||
const cacheVersion = 35;
|
||||
const cacheVersion = 36;
|
||||
|
||||
const ubuntuX86Runner = "ubuntu-24.04";
|
||||
const ubuntuX86XlRunner = "ubuntu-24.04-xl";
|
||||
|
|
8
.github/workflows/ci.yml
vendored
8
.github/workflows/ci.yml
vendored
|
@ -184,8 +184,8 @@ jobs:
|
|||
~/.cargo/registry/index
|
||||
~/.cargo/registry/cache
|
||||
~/.cargo/git/db
|
||||
key: '35-cargo-home-${{ matrix.os }}-${{ matrix.arch }}-${{ hashFiles(''Cargo.lock'') }}'
|
||||
restore-keys: '35-cargo-home-${{ matrix.os }}-${{ matrix.arch }}-'
|
||||
key: '36-cargo-home-${{ matrix.os }}-${{ matrix.arch }}-${{ hashFiles(''Cargo.lock'') }}'
|
||||
restore-keys: '36-cargo-home-${{ matrix.os }}-${{ matrix.arch }}-'
|
||||
if: '!(matrix.skip)'
|
||||
- uses: dsherret/rust-toolchain-file@v1
|
||||
if: '!(matrix.skip)'
|
||||
|
@ -379,7 +379,7 @@ jobs:
|
|||
!./target/*/*.zip
|
||||
!./target/*/*.tar.gz
|
||||
key: never_saved
|
||||
restore-keys: '35-cargo-target-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.profile }}-${{ matrix.job }}-'
|
||||
restore-keys: '36-cargo-target-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.profile }}-${{ matrix.job }}-'
|
||||
- name: Apply and update mtime cache
|
||||
if: '!(matrix.skip) && (!startsWith(github.ref, ''refs/tags/''))'
|
||||
uses: ./.github/mtime_cache
|
||||
|
@ -689,7 +689,7 @@ jobs:
|
|||
!./target/*/gn_root
|
||||
!./target/*/*.zip
|
||||
!./target/*/*.tar.gz
|
||||
key: '35-cargo-target-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.profile }}-${{ matrix.job }}-${{ github.sha }}'
|
||||
key: '36-cargo-target-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.profile }}-${{ matrix.job }}-${{ github.sha }}'
|
||||
publish-canary:
|
||||
name: publish canary
|
||||
runs-on: ubuntu-24.04
|
||||
|
|
96
Cargo.lock
generated
96
Cargo.lock
generated
|
@ -1244,7 +1244,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno"
|
||||
version = "2.1.5"
|
||||
version = "2.1.6"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"async-trait",
|
||||
|
@ -1422,7 +1422,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_bench_util"
|
||||
version = "0.179.0"
|
||||
version = "0.180.0"
|
||||
dependencies = [
|
||||
"bencher",
|
||||
"deno_core",
|
||||
|
@ -1431,7 +1431,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_broadcast_channel"
|
||||
version = "0.179.0"
|
||||
version = "0.180.0"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"deno_core",
|
||||
|
@ -1443,7 +1443,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_cache"
|
||||
version = "0.117.0"
|
||||
version = "0.118.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-stream",
|
||||
|
@ -1497,7 +1497,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_canvas"
|
||||
version = "0.54.0"
|
||||
version = "0.55.0"
|
||||
dependencies = [
|
||||
"deno_core",
|
||||
"deno_error",
|
||||
|
@ -1536,7 +1536,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_console"
|
||||
version = "0.185.0"
|
||||
version = "0.186.0"
|
||||
dependencies = [
|
||||
"deno_core",
|
||||
]
|
||||
|
@ -1587,7 +1587,7 @@ checksum = "fe4dccb6147bb3f3ba0c7a48e993bfeb999d2c2e47a81badee80e2b370c8d695"
|
|||
|
||||
[[package]]
|
||||
name = "deno_cron"
|
||||
version = "0.65.0"
|
||||
version = "0.66.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
|
@ -1601,7 +1601,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_crypto"
|
||||
version = "0.199.0"
|
||||
version = "0.200.0"
|
||||
dependencies = [
|
||||
"aes",
|
||||
"aes-gcm",
|
||||
|
@ -1694,7 +1694,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_fetch"
|
||||
version = "0.209.0"
|
||||
version = "0.210.0"
|
||||
dependencies = [
|
||||
"base64 0.21.7",
|
||||
"bytes",
|
||||
|
@ -1731,7 +1731,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_ffi"
|
||||
version = "0.172.0"
|
||||
version = "0.173.0"
|
||||
dependencies = [
|
||||
"deno_core",
|
||||
"deno_error",
|
||||
|
@ -1752,7 +1752,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_fs"
|
||||
version = "0.95.0"
|
||||
version = "0.96.0"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"base32",
|
||||
|
@ -1810,7 +1810,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_http"
|
||||
version = "0.183.0"
|
||||
version = "0.184.0"
|
||||
dependencies = [
|
||||
"async-compression",
|
||||
"async-trait",
|
||||
|
@ -1850,7 +1850,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_io"
|
||||
version = "0.95.0"
|
||||
version = "0.96.0"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"deno_core",
|
||||
|
@ -1872,7 +1872,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_kv"
|
||||
version = "0.93.0"
|
||||
version = "0.94.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
|
@ -1905,7 +1905,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_lib"
|
||||
version = "0.1.1"
|
||||
version = "0.2.0"
|
||||
dependencies = [
|
||||
"deno_cache_dir",
|
||||
"deno_error",
|
||||
|
@ -1971,7 +1971,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_napi"
|
||||
version = "0.116.0"
|
||||
version = "0.117.0"
|
||||
dependencies = [
|
||||
"deno_core",
|
||||
"deno_error",
|
||||
|
@ -2000,7 +2000,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_net"
|
||||
version = "0.177.0"
|
||||
version = "0.178.0"
|
||||
dependencies = [
|
||||
"deno_core",
|
||||
"deno_error",
|
||||
|
@ -2019,7 +2019,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_node"
|
||||
version = "0.123.0"
|
||||
version = "0.124.0"
|
||||
dependencies = [
|
||||
"aead-gcm-stream",
|
||||
"aes",
|
||||
|
@ -2042,6 +2042,7 @@ dependencies = [
|
|||
"deno_package_json",
|
||||
"deno_path_util",
|
||||
"deno_permissions",
|
||||
"deno_process",
|
||||
"deno_whoami",
|
||||
"der",
|
||||
"digest",
|
||||
|
@ -2079,7 +2080,6 @@ dependencies = [
|
|||
"p384",
|
||||
"path-clean",
|
||||
"pbkdf2",
|
||||
"pin-project-lite",
|
||||
"pkcs8",
|
||||
"rand",
|
||||
"regex",
|
||||
|
@ -2132,7 +2132,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_npm_cache"
|
||||
version = "0.4.0"
|
||||
version = "0.5.0"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"base64 0.21.7",
|
||||
|
@ -2179,7 +2179,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_os"
|
||||
version = "0.1.0"
|
||||
version = "0.3.0"
|
||||
dependencies = [
|
||||
"deno_core",
|
||||
"deno_error",
|
||||
|
@ -2231,7 +2231,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_permissions"
|
||||
version = "0.44.0"
|
||||
version = "0.45.0"
|
||||
dependencies = [
|
||||
"capacity_builder 0.5.0",
|
||||
"deno_core",
|
||||
|
@ -2249,9 +2249,36 @@ dependencies = [
|
|||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "deno_process"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"deno_core",
|
||||
"deno_error",
|
||||
"deno_fs",
|
||||
"deno_io",
|
||||
"deno_os",
|
||||
"deno_path_util",
|
||||
"deno_permissions",
|
||||
"libc",
|
||||
"log",
|
||||
"memchr",
|
||||
"nix",
|
||||
"pin-project-lite",
|
||||
"rand",
|
||||
"serde",
|
||||
"simd-json",
|
||||
"tempfile",
|
||||
"thiserror 2.0.3",
|
||||
"tokio",
|
||||
"which",
|
||||
"winapi",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "deno_resolver"
|
||||
version = "0.16.0"
|
||||
version = "0.17.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
|
@ -2277,7 +2304,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_runtime"
|
||||
version = "0.193.0"
|
||||
version = "0.194.0"
|
||||
dependencies = [
|
||||
"color-print",
|
||||
"deno_ast",
|
||||
|
@ -2301,6 +2328,7 @@ dependencies = [
|
|||
"deno_os",
|
||||
"deno_path_util",
|
||||
"deno_permissions",
|
||||
"deno_process",
|
||||
"deno_resolver",
|
||||
"deno_telemetry",
|
||||
"deno_terminal 0.2.0",
|
||||
|
@ -2382,7 +2410,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_telemetry"
|
||||
version = "0.7.0"
|
||||
version = "0.8.0"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"deno_core",
|
||||
|
@ -2425,7 +2453,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_tls"
|
||||
version = "0.172.0"
|
||||
version = "0.173.0"
|
||||
dependencies = [
|
||||
"deno_core",
|
||||
"deno_error",
|
||||
|
@ -2476,7 +2504,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_url"
|
||||
version = "0.185.0"
|
||||
version = "0.186.0"
|
||||
dependencies = [
|
||||
"deno_bench_util",
|
||||
"deno_console",
|
||||
|
@ -2489,7 +2517,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_web"
|
||||
version = "0.216.0"
|
||||
version = "0.217.0"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"base64-simd 0.8.0",
|
||||
|
@ -2512,7 +2540,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_webgpu"
|
||||
version = "0.152.0"
|
||||
version = "0.153.0"
|
||||
dependencies = [
|
||||
"deno_core",
|
||||
"deno_error",
|
||||
|
@ -2526,7 +2554,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_webidl"
|
||||
version = "0.185.0"
|
||||
version = "0.186.0"
|
||||
dependencies = [
|
||||
"deno_bench_util",
|
||||
"deno_core",
|
||||
|
@ -2534,7 +2562,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_websocket"
|
||||
version = "0.190.0"
|
||||
version = "0.191.0"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"deno_core",
|
||||
|
@ -2557,7 +2585,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_webstorage"
|
||||
version = "0.180.0"
|
||||
version = "0.181.0"
|
||||
dependencies = [
|
||||
"deno_core",
|
||||
"deno_error",
|
||||
|
@ -5129,7 +5157,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "napi_sym"
|
||||
version = "0.115.0"
|
||||
version = "0.116.0"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"serde",
|
||||
|
@ -5184,7 +5212,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "node_resolver"
|
||||
version = "0.23.0"
|
||||
version = "0.24.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
|
|
65
Cargo.toml
65
Cargo.toml
|
@ -51,17 +51,17 @@ repository = "https://github.com/denoland/deno"
|
|||
deno_ast = { version = "=0.44.0", features = ["transpiling"] }
|
||||
deno_core = { version = "0.330.0" }
|
||||
|
||||
deno_bench_util = { version = "0.179.0", path = "./bench_util" }
|
||||
deno_bench_util = { version = "0.180.0", path = "./bench_util" }
|
||||
deno_config = { version = "=0.45.0", features = ["workspace", "sync"] }
|
||||
deno_lockfile = "=0.24.0"
|
||||
deno_media_type = { version = "0.2.3", features = ["module_specifier"] }
|
||||
deno_npm = "=0.27.2"
|
||||
deno_path_util = "=0.3.0"
|
||||
deno_permissions = { version = "0.44.0", path = "./runtime/permissions" }
|
||||
deno_runtime = { version = "0.193.0", path = "./runtime" }
|
||||
deno_permissions = { version = "0.45.0", path = "./runtime/permissions" }
|
||||
deno_runtime = { version = "0.194.0", path = "./runtime" }
|
||||
deno_semver = "=0.7.1"
|
||||
deno_terminal = "0.2.0"
|
||||
napi_sym = { version = "0.115.0", path = "./ext/napi/sym" }
|
||||
napi_sym = { version = "0.116.0", path = "./ext/napi/sym" }
|
||||
test_util = { package = "test_server", path = "./tests/util/server" }
|
||||
|
||||
denokv_proto = "0.9.0"
|
||||
|
@ -70,36 +70,37 @@ denokv_remote = "0.9.0"
|
|||
denokv_sqlite = { default-features = false, version = "0.9.0" }
|
||||
|
||||
# exts
|
||||
deno_broadcast_channel = { version = "0.179.0", path = "./ext/broadcast_channel" }
|
||||
deno_cache = { version = "0.117.0", path = "./ext/cache" }
|
||||
deno_canvas = { version = "0.54.0", path = "./ext/canvas" }
|
||||
deno_console = { version = "0.185.0", path = "./ext/console" }
|
||||
deno_cron = { version = "0.65.0", path = "./ext/cron" }
|
||||
deno_crypto = { version = "0.199.0", path = "./ext/crypto" }
|
||||
deno_fetch = { version = "0.209.0", path = "./ext/fetch" }
|
||||
deno_ffi = { version = "0.172.0", path = "./ext/ffi" }
|
||||
deno_fs = { version = "0.95.0", path = "./ext/fs" }
|
||||
deno_http = { version = "0.183.0", path = "./ext/http" }
|
||||
deno_io = { version = "0.95.0", path = "./ext/io" }
|
||||
deno_kv = { version = "0.93.0", path = "./ext/kv" }
|
||||
deno_napi = { version = "0.116.0", path = "./ext/napi" }
|
||||
deno_net = { version = "0.177.0", path = "./ext/net" }
|
||||
deno_node = { version = "0.123.0", path = "./ext/node" }
|
||||
deno_os = { version = "0.1.0", path = "./ext/os" }
|
||||
deno_telemetry = { version = "0.7.0", path = "./ext/telemetry" }
|
||||
deno_tls = { version = "0.172.0", path = "./ext/tls" }
|
||||
deno_url = { version = "0.185.0", path = "./ext/url" }
|
||||
deno_web = { version = "0.216.0", path = "./ext/web" }
|
||||
deno_webgpu = { version = "0.152.0", path = "./ext/webgpu" }
|
||||
deno_webidl = { version = "0.185.0", path = "./ext/webidl" }
|
||||
deno_websocket = { version = "0.190.0", path = "./ext/websocket" }
|
||||
deno_webstorage = { version = "0.180.0", path = "./ext/webstorage" }
|
||||
deno_broadcast_channel = { version = "0.180.0", path = "./ext/broadcast_channel" }
|
||||
deno_cache = { version = "0.118.0", path = "./ext/cache" }
|
||||
deno_canvas = { version = "0.55.0", path = "./ext/canvas" }
|
||||
deno_console = { version = "0.186.0", path = "./ext/console" }
|
||||
deno_cron = { version = "0.66.0", path = "./ext/cron" }
|
||||
deno_crypto = { version = "0.200.0", path = "./ext/crypto" }
|
||||
deno_fetch = { version = "0.210.0", path = "./ext/fetch" }
|
||||
deno_ffi = { version = "0.173.0", path = "./ext/ffi" }
|
||||
deno_fs = { version = "0.96.0", path = "./ext/fs" }
|
||||
deno_http = { version = "0.184.0", path = "./ext/http" }
|
||||
deno_io = { version = "0.96.0", path = "./ext/io" }
|
||||
deno_kv = { version = "0.94.0", path = "./ext/kv" }
|
||||
deno_napi = { version = "0.117.0", path = "./ext/napi" }
|
||||
deno_net = { version = "0.178.0", path = "./ext/net" }
|
||||
deno_node = { version = "0.124.0", path = "./ext/node" }
|
||||
deno_os = { version = "0.3.0", path = "./ext/os" }
|
||||
deno_process = { version = "0.1.0", path = "./ext/process" }
|
||||
deno_telemetry = { version = "0.8.0", path = "./ext/telemetry" }
|
||||
deno_tls = { version = "0.173.0", path = "./ext/tls" }
|
||||
deno_url = { version = "0.186.0", path = "./ext/url" }
|
||||
deno_web = { version = "0.217.0", path = "./ext/web" }
|
||||
deno_webgpu = { version = "0.153.0", path = "./ext/webgpu" }
|
||||
deno_webidl = { version = "0.186.0", path = "./ext/webidl" }
|
||||
deno_websocket = { version = "0.191.0", path = "./ext/websocket" }
|
||||
deno_webstorage = { version = "0.181.0", path = "./ext/webstorage" }
|
||||
|
||||
# workspace libraries
|
||||
deno_lib = { version = "=0.1.1", path = "./cli/lib" }
|
||||
deno_npm_cache = { version = "0.4.0", path = "./resolvers/npm_cache" }
|
||||
deno_resolver = { version = "0.16.0", path = "./resolvers/deno" }
|
||||
node_resolver = { version = "0.23.0", path = "./resolvers/node" }
|
||||
deno_lib = { version = "0.2.0", path = "./cli/lib" }
|
||||
deno_npm_cache = { version = "0.5.0", path = "./resolvers/npm_cache" }
|
||||
deno_resolver = { version = "0.17.0", path = "./resolvers/deno" }
|
||||
node_resolver = { version = "0.24.0", path = "./resolvers/node" }
|
||||
|
||||
aes = "=0.8.3"
|
||||
anyhow = "1.0.57"
|
||||
|
|
26
Releases.md
26
Releases.md
|
@ -6,6 +6,32 @@ https://github.com/denoland/deno/releases
|
|||
We also have one-line install commands at:
|
||||
https://github.com/denoland/deno_install
|
||||
|
||||
### 2.1.6 / 2025.01.16
|
||||
|
||||
- fix(check/lsp): correctly resolve compilerOptions.types (#27686)
|
||||
- fix(check/lsp): fix bugs with tsc type resolution, allow npm packages to
|
||||
augment `ImportMeta` (#27690)
|
||||
- fix(compile): store embedded fs case sensitivity (#27653)
|
||||
- fix(compile/windows): better handling of deno_dir on different drive letter
|
||||
than code (#27654)
|
||||
- fix(ext/console): change Temporal color (#27684)
|
||||
- fix(ext/node): add `writev` method to `FileHandle` (#27563)
|
||||
- fix(ext/node): add chown method to FileHandle class (#27638)
|
||||
- fix(ext/node): apply `@npmcli/agent` workaround to `npm-check-updates`
|
||||
(#27639)
|
||||
- fix(ext/node): fix playwright http client (#27662)
|
||||
- fix(ext/node): show bare-node-builtin hint when using an import map (#27632)
|
||||
- fix(ext/node): use primordials in `ext/node/polyfills/_fs_common.ts` (#27589)
|
||||
- fix(lsp): handle pathless untitled URIs (#27637)
|
||||
- fix(lsp/check): don't resolve unknown media types to a `.js` extension
|
||||
(#27631)
|
||||
- fix(node): Prevent node:child_process from always inheriting the parent
|
||||
environment (#27343) (#27340)
|
||||
- fix(node/fs): add utimes method to the FileHandle class (#27582)
|
||||
- fix(outdated): Use `latest` tag even when it's the same as the current version
|
||||
(#27699)
|
||||
- fix(outdated): retain strict semver specifier when updating (#27701)
|
||||
|
||||
### 2.1.5 / 2025.01.09
|
||||
|
||||
- feat(unstable): implement QUIC (#21942)
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
[package]
|
||||
name = "deno_bench_util"
|
||||
version = "0.179.0"
|
||||
version = "0.180.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
[package]
|
||||
name = "deno"
|
||||
version = "2.1.5"
|
||||
version = "2.1.6"
|
||||
authors.workspace = true
|
||||
default-run = "deno"
|
||||
edition.workspace = true
|
||||
|
|
|
@ -719,7 +719,7 @@ pub enum NpmProcessStateKind {
|
|||
}
|
||||
|
||||
static NPM_PROCESS_STATE: Lazy<Option<NpmProcessState>> = Lazy::new(|| {
|
||||
use deno_runtime::ops::process::NPM_RESOLUTION_STATE_FD_ENV_VAR_NAME;
|
||||
use deno_runtime::deno_process::NPM_RESOLUTION_STATE_FD_ENV_VAR_NAME;
|
||||
let fd = std::env::var(NPM_RESOLUTION_STATE_FD_ENV_VAR_NAME).ok()?;
|
||||
std::env::remove_var(NPM_RESOLUTION_STATE_FD_ENV_VAR_NAME);
|
||||
let fd = fd.parse::<usize>().ok()?;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
[package]
|
||||
name = "deno_lib"
|
||||
version = "0.1.1"
|
||||
version = "0.2.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
@ -28,7 +28,7 @@ node_resolver = { workspace = true, features = ["sync"] }
|
|||
parking_lot.workspace = true
|
||||
ring.workspace = true
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
sys_traits.workspace = true
|
||||
sys_traits = { workspace = true, features = ["getrandom"] }
|
||||
thiserror.workspace = true
|
||||
tokio.workspace = true
|
||||
url.workspace = true
|
||||
|
|
|
@ -25,12 +25,12 @@ use deno_runtime::deno_node::NodeExtInitServices;
|
|||
use deno_runtime::deno_node::NodeRequireLoader;
|
||||
use deno_runtime::deno_node::NodeResolver;
|
||||
use deno_runtime::deno_permissions::PermissionsContainer;
|
||||
use deno_runtime::deno_process::NpmProcessStateProviderRc;
|
||||
use deno_runtime::deno_telemetry::OtelConfig;
|
||||
use deno_runtime::deno_tls::RootCertStoreProvider;
|
||||
use deno_runtime::deno_web::BlobStore;
|
||||
use deno_runtime::fmt_errors::format_js_error;
|
||||
use deno_runtime::inspector_server::InspectorServer;
|
||||
use deno_runtime::ops::process::NpmProcessStateProviderRc;
|
||||
use deno_runtime::ops::worker_host::CreateWebWorkerCb;
|
||||
use deno_runtime::web_worker::WebWorker;
|
||||
use deno_runtime::web_worker::WebWorkerOptions;
|
||||
|
|
|
@ -73,6 +73,7 @@ use super::documents::Document;
|
|||
use super::documents::DocumentsFilter;
|
||||
use super::language_server;
|
||||
use super::language_server::StateSnapshot;
|
||||
use super::logging::lsp_log;
|
||||
use super::performance::Performance;
|
||||
use super::performance::PerformanceMark;
|
||||
use super::refactor::RefactorCodeActionData;
|
||||
|
@ -4340,7 +4341,9 @@ impl TscSpecifierMap {
|
|||
if let Some(specifier) = self.normalized_specifiers.get(original) {
|
||||
return Ok(specifier.clone());
|
||||
}
|
||||
let specifier_str = original.replace(".d.ts.d.ts", ".d.ts");
|
||||
let specifier_str = original
|
||||
.replace(".d.ts.d.ts", ".d.ts")
|
||||
.replace("$node_modules", "node_modules");
|
||||
let specifier = match ModuleSpecifier::parse(&specifier_str) {
|
||||
Ok(s) => s,
|
||||
Err(err) => return Err(err),
|
||||
|
@ -4695,7 +4698,24 @@ fn op_script_names(state: &mut OpState) -> ScriptNames {
|
|||
.graph_imports_by_referrer(scope)
|
||||
{
|
||||
for specifier in specifiers {
|
||||
script_names.insert(specifier.to_string());
|
||||
if let Ok(req_ref) =
|
||||
deno_semver::npm::NpmPackageReqReference::from_specifier(specifier)
|
||||
{
|
||||
let Some((resolved, _)) =
|
||||
state.state_snapshot.resolver.npm_to_file_url(
|
||||
&req_ref,
|
||||
scope,
|
||||
ResolutionMode::Import,
|
||||
Some(scope),
|
||||
)
|
||||
else {
|
||||
lsp_log!("failed to resolve {req_ref} to file URL");
|
||||
continue;
|
||||
};
|
||||
script_names.insert(resolved.to_string());
|
||||
} else {
|
||||
script_names.insert(specifier.to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6245,7 +6265,40 @@ mod tests {
|
|||
"kind": "keyword"
|
||||
}
|
||||
],
|
||||
"documentation": []
|
||||
"documentation": [
|
||||
{
|
||||
"text": "Outputs a message to the console",
|
||||
"kind": "text",
|
||||
},
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"name": "param",
|
||||
"text": [
|
||||
{
|
||||
"text": "data",
|
||||
"kind": "parameterName",
|
||||
},
|
||||
{
|
||||
"text": " ",
|
||||
"kind": "space",
|
||||
},
|
||||
{
|
||||
"text": "Values to be printed to the console",
|
||||
"kind": "text",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
"name": "example",
|
||||
"text": [
|
||||
{
|
||||
"text": "```ts\nconsole.log('Hello', 'World', 123);\n```",
|
||||
"kind": "text",
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
})
|
||||
);
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ use std::sync::Arc;
|
|||
use deno_core::serde_json;
|
||||
use deno_resolver::npm::ByonmNpmResolver;
|
||||
use deno_resolver::npm::ByonmNpmResolverCreateOptions;
|
||||
use deno_runtime::ops::process::NpmProcessStateProvider;
|
||||
use deno_runtime::deno_process::NpmProcessStateProvider;
|
||||
|
||||
use crate::args::NpmProcessState;
|
||||
use crate::args::NpmProcessStateKind;
|
||||
|
|
|
@ -240,7 +240,7 @@ impl<'a> LifecycleScripts<'a> {
|
|||
// However, if we concurrently run scripts in the future we will
|
||||
// have to have multiple temp files.
|
||||
let temp_file_fd =
|
||||
deno_runtime::ops::process::npm_process_state_tempfile(
|
||||
deno_runtime::deno_process::npm_process_state_tempfile(
|
||||
process_state.as_bytes(),
|
||||
)
|
||||
.map_err(LifecycleScriptsError::CreateNpmProcessState)?;
|
||||
|
@ -248,7 +248,7 @@ impl<'a> LifecycleScripts<'a> {
|
|||
let _temp_file =
|
||||
unsafe { std::fs::File::from_raw_io_handle(temp_file_fd) }; // make sure the file gets closed
|
||||
env_vars.insert(
|
||||
deno_runtime::ops::process::NPM_RESOLUTION_STATE_FD_ENV_VAR_NAME
|
||||
deno_runtime::deno_process::NPM_RESOLUTION_STATE_FD_ENV_VAR_NAME
|
||||
.to_string(),
|
||||
(temp_file_fd as usize).to_string(),
|
||||
);
|
||||
|
|
|
@ -14,7 +14,7 @@ use deno_npm::resolution::ValidSerializedNpmResolutionSnapshot;
|
|||
use deno_resolver::npm::managed::ManagedNpmResolverCreateOptions;
|
||||
use deno_resolver::npm::managed::NpmResolutionCell;
|
||||
use deno_resolver::npm::ManagedNpmResolverRc;
|
||||
use deno_runtime::ops::process::NpmProcessStateProvider;
|
||||
use deno_runtime::deno_process::NpmProcessStateProvider;
|
||||
use thiserror::Error;
|
||||
|
||||
use super::CliNpmRegistryInfoProvider;
|
||||
|
|
|
@ -12,7 +12,7 @@ use deno_core::url::Url;
|
|||
use deno_error::JsErrorBox;
|
||||
use deno_npm::npm_rc::ResolvedNpmRc;
|
||||
use deno_npm::registry::NpmPackageInfo;
|
||||
use deno_runtime::ops::process::NpmProcessStateProviderRc;
|
||||
use deno_runtime::deno_process::NpmProcessStateProviderRc;
|
||||
use deno_semver::package::PackageNv;
|
||||
use deno_semver::package::PackageReq;
|
||||
use http::HeaderName;
|
||||
|
|
|
@ -13,6 +13,7 @@ use deno_graph::Module;
|
|||
use deno_graph::ModuleError;
|
||||
use deno_graph::ModuleGraph;
|
||||
use deno_graph::ModuleLoadError;
|
||||
use deno_semver::npm::NpmPackageNvReference;
|
||||
use deno_terminal::colors;
|
||||
use once_cell::sync::Lazy;
|
||||
use regex::Regex;
|
||||
|
@ -261,6 +262,8 @@ impl TypeChecker {
|
|||
maybe_check_hash,
|
||||
} = get_tsc_roots(
|
||||
&self.sys,
|
||||
&self.npm_resolver,
|
||||
&self.node_resolver,
|
||||
&graph,
|
||||
check_js,
|
||||
check_state_hash(&self.npm_resolver),
|
||||
|
@ -373,8 +376,11 @@ struct TscRoots {
|
|||
/// redirects resolved. We need to include all the emittable files in
|
||||
/// the roots, so they get type checked and optionally emitted,
|
||||
/// otherwise they would be ignored if only imported into JavaScript.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn get_tsc_roots(
|
||||
sys: &CliSys,
|
||||
npm_resolver: &CliNpmResolver,
|
||||
node_resolver: &CliNodeResolver,
|
||||
graph: &ModuleGraph,
|
||||
check_js: bool,
|
||||
npm_cache_state_hash: Option<u64>,
|
||||
|
@ -457,6 +463,7 @@ fn get_tsc_roots(
|
|||
if let Some(hasher) = hasher {
|
||||
hasher.write_str(module.specifier.as_str());
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
}
|
||||
|
@ -493,17 +500,33 @@ fn get_tsc_roots(
|
|||
let mut pending = VecDeque::new();
|
||||
|
||||
// put in the global types first so that they're resolved before anything else
|
||||
let get_import_specifiers = || {
|
||||
graph
|
||||
.imports
|
||||
for (referrer, import) in graph.imports.iter() {
|
||||
for specifier in import
|
||||
.dependencies
|
||||
.values()
|
||||
.flat_map(|i| i.dependencies.values())
|
||||
.filter_map(|dep| dep.get_type().or_else(|| dep.get_code()))
|
||||
};
|
||||
for specifier in get_import_specifiers() {
|
||||
let specifier = graph.resolve(specifier);
|
||||
if seen.insert(specifier) {
|
||||
pending.push_back((specifier, false));
|
||||
{
|
||||
let specifier = graph.resolve(specifier);
|
||||
if seen.insert(specifier) {
|
||||
if let Ok(nv_ref) = NpmPackageNvReference::from_specifier(specifier) {
|
||||
let Some(resolved) =
|
||||
resolve_npm_nv_ref(npm_resolver, node_resolver, &nv_ref, referrer)
|
||||
else {
|
||||
result.missing_diagnostics.push(
|
||||
tsc::Diagnostic::from_missing_error(
|
||||
specifier,
|
||||
None,
|
||||
maybe_additional_sloppy_imports_message(sys, specifier),
|
||||
),
|
||||
);
|
||||
continue;
|
||||
};
|
||||
let mt = MediaType::from_specifier(&resolved);
|
||||
result.roots.push((resolved, mt));
|
||||
} else {
|
||||
pending.push_back((specifier, false));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -624,6 +647,29 @@ fn get_tsc_roots(
|
|||
result
|
||||
}
|
||||
|
||||
fn resolve_npm_nv_ref(
|
||||
npm_resolver: &CliNpmResolver,
|
||||
node_resolver: &CliNodeResolver,
|
||||
nv_ref: &NpmPackageNvReference,
|
||||
referrer: &ModuleSpecifier,
|
||||
) -> Option<ModuleSpecifier> {
|
||||
let pkg_dir = npm_resolver
|
||||
.as_managed()
|
||||
.unwrap()
|
||||
.resolve_pkg_folder_from_deno_module(nv_ref.nv())
|
||||
.ok()?;
|
||||
let resolved = node_resolver
|
||||
.resolve_package_subpath_from_deno_module(
|
||||
&pkg_dir,
|
||||
nv_ref.sub_path(),
|
||||
Some(referrer),
|
||||
node_resolver::ResolutionMode::Import,
|
||||
node_resolver::NodeResolutionKind::Types,
|
||||
)
|
||||
.ok()?;
|
||||
Some(resolved)
|
||||
}
|
||||
|
||||
/// Matches the `@ts-check` pragma.
|
||||
static TS_CHECK_RE: Lazy<Regex> =
|
||||
lazy_regex::lazy_regex!(r#"(?i)^\s*@ts-check(?:\s+|$)"#);
|
||||
|
|
|
@ -683,10 +683,21 @@ impl DepManager {
|
|||
.and_then(|info| {
|
||||
let latest_tag = info.dist_tags.get("latest")?;
|
||||
let lower_bound = &semver_compatible.as_ref()?.version;
|
||||
if latest_tag > lower_bound {
|
||||
if latest_tag >= lower_bound {
|
||||
Some(latest_tag.clone())
|
||||
} else {
|
||||
latest_version(Some(latest_tag), info.versions.keys())
|
||||
latest_version(
|
||||
Some(latest_tag),
|
||||
info.versions.iter().filter_map(
|
||||
|(version, version_info)| {
|
||||
if version_info.deprecated.is_none() {
|
||||
Some(version)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
})
|
||||
.map(|version| PackageNv {
|
||||
|
|
|
@ -280,9 +280,15 @@ fn choose_new_version_req(
|
|||
if preferred.version <= resolved?.version {
|
||||
return None;
|
||||
}
|
||||
let exact = if let Some(range) = dep.req.version_req.range() {
|
||||
range.0[0].start == range.0[0].end
|
||||
} else {
|
||||
false
|
||||
};
|
||||
Some(
|
||||
VersionReq::parse_from_specifier(
|
||||
format!("^{}", preferred.version).as_str(),
|
||||
format!("{}{}", if exact { "" } else { "^" }, preferred.version)
|
||||
.as_str(),
|
||||
)
|
||||
.unwrap(),
|
||||
)
|
||||
|
|
|
@ -500,6 +500,8 @@ delete Object.prototype.__proto__;
|
|||
// Microsoft/TypeScript#26825 but that doesn't seem to be working here,
|
||||
// so we will ignore complaints about this compiler setting.
|
||||
5070,
|
||||
// TS6053: File '{0}' not found.
|
||||
6053,
|
||||
// TS7016: Could not find a declaration file for module '...'. '...'
|
||||
// implicitly has an 'any' type. This is due to `allowJs` being off by
|
||||
// default but importing of a JavaScript module.
|
||||
|
@ -705,15 +707,14 @@ delete Object.prototype.__proto__;
|
|||
resolveTypeReferenceDirectiveReferences(
|
||||
typeDirectiveReferences,
|
||||
containingFilePath,
|
||||
redirectedReference,
|
||||
_redirectedReference,
|
||||
options,
|
||||
containingSourceFile,
|
||||
_reusedNames,
|
||||
) {
|
||||
const isCjs =
|
||||
containingSourceFile?.impliedNodeFormat === ts.ModuleKind.CommonJS;
|
||||
/** @type {Array<ts.ResolvedTypeReferenceDirectiveWithFailedLookupLocations>} */
|
||||
const result = typeDirectiveReferences.map((arg) => {
|
||||
const toResolve = typeDirectiveReferences.map((arg) => {
|
||||
/** @type {ts.FileReference} */
|
||||
const fileReference = typeof arg === "string"
|
||||
? {
|
||||
|
@ -722,46 +723,50 @@ delete Object.prototype.__proto__;
|
|||
fileName: arg,
|
||||
}
|
||||
: arg;
|
||||
if (fileReference.fileName.startsWith("npm:")) {
|
||||
/** @type {[string, ts.Extension | null] | undefined} */
|
||||
const resolved = ops.op_resolve(
|
||||
containingFilePath,
|
||||
[
|
||||
[
|
||||
fileReference.resolutionMode == null
|
||||
? isCjs
|
||||
: fileReference.resolutionMode === ts.ModuleKind.CommonJS,
|
||||
fileReference.fileName,
|
||||
],
|
||||
],
|
||||
)?.[0];
|
||||
if (resolved && resolved[1]) {
|
||||
return {
|
||||
resolvedTypeReferenceDirective: {
|
||||
primary: true,
|
||||
resolvedFileName: resolved[0],
|
||||
// todo(dsherret): we should probably be setting this
|
||||
isExternalLibraryImport: undefined,
|
||||
},
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
resolvedTypeReferenceDirective: undefined,
|
||||
};
|
||||
}
|
||||
return [
|
||||
fileReference.resolutionMode == null
|
||||
? isCjs
|
||||
: fileReference.resolutionMode === ts.ModuleKind.CommonJS,
|
||||
fileReference.fileName,
|
||||
];
|
||||
});
|
||||
|
||||
/** @type {Array<[string, ts.Extension | null] | undefined>} */
|
||||
const resolved = ops.op_resolve(
|
||||
containingFilePath,
|
||||
toResolve,
|
||||
);
|
||||
|
||||
/** @type {Array<ts.ResolvedTypeReferenceDirectiveWithFailedLookupLocations>} */
|
||||
const result = resolved.map((item) => {
|
||||
if (item && item[1]) {
|
||||
const [resolvedFileName, extension] = item;
|
||||
return {
|
||||
resolvedTypeReferenceDirective: {
|
||||
primary: true,
|
||||
resolvedFileName,
|
||||
extension,
|
||||
isExternalLibraryImport: false,
|
||||
},
|
||||
};
|
||||
} else {
|
||||
return ts.resolveTypeReferenceDirective(
|
||||
fileReference.fileName,
|
||||
containingFilePath,
|
||||
options,
|
||||
host,
|
||||
redirectedReference,
|
||||
undefined,
|
||||
containingSourceFile?.impliedNodeFormat ??
|
||||
fileReference.resolutionMode,
|
||||
);
|
||||
return {
|
||||
resolvedTypeReferenceDirective: undefined,
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
if (logDebug) {
|
||||
debug(
|
||||
"resolveTypeReferenceDirectiveReferences ",
|
||||
typeDirectiveReferences,
|
||||
containingFilePath,
|
||||
options,
|
||||
containingSourceFile?.fileName,
|
||||
" => ",
|
||||
result,
|
||||
);
|
||||
}
|
||||
return result;
|
||||
},
|
||||
resolveModuleNameLiterals(
|
||||
|
@ -1116,6 +1121,36 @@ delete Object.prototype.__proto__;
|
|||
if (IGNORED_DIAGNOSTICS.includes(diagnostic.code)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// ignore diagnostics resulting from the `ImportMeta` declaration in deno merging with
|
||||
// the one in @types/node. the types of the filename and dirname properties are different,
|
||||
// which causes tsc to error.
|
||||
const importMetaFilenameDirnameModifiersRe =
|
||||
/^All declarations of '(filename|dirname)'/;
|
||||
const importMetaFilenameDirnameTypesRe =
|
||||
/^Subsequent property declarations must have the same type.\s+Property '(filename|dirname)'/;
|
||||
// Declarations of X must have identical modifiers.
|
||||
if (diagnostic.code === 2687) {
|
||||
if (
|
||||
typeof diagnostic.messageText === "string" &&
|
||||
(importMetaFilenameDirnameModifiersRe.test(diagnostic.messageText)) &&
|
||||
(diagnostic.file?.fileName.startsWith("asset:///") ||
|
||||
diagnostic.file?.fileName?.includes("@types/node"))
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Subsequent property declarations must have the same type.
|
||||
if (diagnostic.code === 2717) {
|
||||
if (
|
||||
typeof diagnostic.messageText === "string" &&
|
||||
(importMetaFilenameDirnameTypesRe.test(diagnostic.messageText)) &&
|
||||
(diagnostic.file?.fileName.startsWith("asset:///") ||
|
||||
diagnostic.file?.fileName?.includes("@types/node"))
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// make the diagnostic for using an `export =` in an es module a warning
|
||||
if (diagnostic.code === 1203) {
|
||||
diagnostic.category = ts.DiagnosticCategory.Warning;
|
||||
|
@ -1410,7 +1445,6 @@ delete Object.prototype.__proto__;
|
|||
"ErrorConstructor",
|
||||
"gc",
|
||||
"Global",
|
||||
"ImportMeta",
|
||||
"localStorage",
|
||||
"queueMicrotask",
|
||||
"RequestInit",
|
||||
|
|
105
cli/tsc/dts/lib.deno.window.d.ts
vendored
105
cli/tsc/dts/lib.deno.window.d.ts
vendored
|
@ -119,9 +119,86 @@ declare var onunload: ((this: Window, ev: Event) => any) | null;
|
|||
declare var onunhandledrejection:
|
||||
| ((this: Window, ev: PromiseRejectionEvent) => any)
|
||||
| null;
|
||||
/** @category Storage */
|
||||
/**
|
||||
* Deno's `localStorage` API provides a way to store key-value pairs in a
|
||||
* web-like environment, similar to the Web Storage API found in browsers.
|
||||
* It allows developers to persist data across sessions in a Deno application.
|
||||
* This API is particularly useful for applications that require a simple
|
||||
* and effective way to store data locally.
|
||||
*
|
||||
* - Key-Value Storage: Stores data as key-value pairs.
|
||||
* - Persistent: Data is retained even after the application is closed.
|
||||
* - Synchronous API: Operations are performed synchronously.
|
||||
*
|
||||
* `localStorage` is similar to {@linkcode sessionStorage}, and shares the same
|
||||
* API methods, visible in the {@linkcode Storage} type.
|
||||
*
|
||||
* When using the `--location` flag, the origin for the location is used to
|
||||
* uniquely store the data. That means a location of http://example.com/a.ts
|
||||
* and http://example.com/b.ts and http://example.com:80/ would all share the
|
||||
* same storage, but https://example.com/ would be different.
|
||||
*
|
||||
* For more information, see the reference guide for
|
||||
* [Web Storage](https://docs.deno.com/runtime/reference/web_platform_apis/#web-storage)
|
||||
* and using
|
||||
* [the `--location` flag](https://docs.deno.com/runtime/reference/web_platform_apis/#location-flag).
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* // Set a value in localStorage
|
||||
* localStorage.setItem("key", "value");
|
||||
*
|
||||
* // Get a value from localStorage
|
||||
* const value = localStorage.getItem("key");
|
||||
* console.log(value); // Output: "value"
|
||||
*
|
||||
* // Remove a value from localStorage
|
||||
* localStorage.removeItem("key");
|
||||
*
|
||||
* // Clear all values from localStorage
|
||||
* localStorage.clear();
|
||||
* ```
|
||||
*
|
||||
* @see https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage
|
||||
* @category Storage */
|
||||
declare var localStorage: Storage;
|
||||
/** @category Storage */
|
||||
|
||||
/**
|
||||
* Deno's `sessionStorage` API operates similarly to the {@linkcode localStorage} API,
|
||||
* but it is intended for storing data temporarily for the duration of a session.
|
||||
* Data stored in sessionStorage is cleared when the application session or
|
||||
* process ends. This makes it suitable for temporary data that you do not need
|
||||
* to persist across user sessions.
|
||||
*
|
||||
* - Key-Value Storage: Stores data as key-value pairs.
|
||||
* - Session-Based: Data is only available for the duration of the page session.
|
||||
* - Synchronous API: Operations are performed synchronously.
|
||||
*
|
||||
* `sessionStorage` is similar to {@linkcode localStorage}, and shares the same API
|
||||
* methods, visible in the {@linkcode Storage} type.
|
||||
*
|
||||
* For more information, see the reference guide for
|
||||
* [Web Storage](https://docs.deno.com/runtime/reference/web_platform_apis/#web-storage)
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* // Set a value in sessionStorage
|
||||
* sessionStorage.setItem("key", "value");
|
||||
*
|
||||
* // Get a value from sessionStorage
|
||||
* const value = sessionStorage.getItem("key");
|
||||
* console.log(value); // Output: "value"
|
||||
*
|
||||
* // Remove a value from sessionStorage
|
||||
* sessionStorage.removeItem("key");
|
||||
*
|
||||
* // Clear all the values from sessionStorage
|
||||
* sessionStorage.clear();
|
||||
* ```
|
||||
*
|
||||
* @see https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage
|
||||
* @category Storage
|
||||
*/
|
||||
declare var sessionStorage: Storage;
|
||||
/** @category Cache */
|
||||
declare var caches: CacheStorage;
|
||||
|
@ -149,6 +226,12 @@ declare var navigator: Navigator;
|
|||
*
|
||||
* If the stdin is not interactive, it does nothing.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* // Displays the message "Acknowledge me! [Enter]" and waits for the enter key to be pressed before continuing.
|
||||
* alert("Acknowledge me!");
|
||||
* ```
|
||||
* @see https://developer.mozilla.org/en-US/docs/Web/API/Window/alert
|
||||
* @category Platform
|
||||
*
|
||||
* @param message
|
||||
|
@ -162,6 +245,15 @@ declare function alert(message?: string): void;
|
|||
*
|
||||
* If the stdin is not interactive, it returns false.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const shouldProceed = confirm("Do you want to proceed?");
|
||||
*
|
||||
* // If the user presses 'y' or 'Y', the result will be true
|
||||
* // If the user presses 'n' or 'N', the result will be false
|
||||
* console.log("Should proceed?", shouldProceed);
|
||||
* ```
|
||||
* @see https://developer.mozilla.org/en-US/docs/Web/API/Window/confirm
|
||||
* @category Platform
|
||||
*
|
||||
* @param message
|
||||
|
@ -179,6 +271,15 @@ declare function confirm(message?: string): boolean;
|
|||
*
|
||||
* If the stdin is not interactive, it returns null.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const pet = prompt("Cats or dogs?", "It's fine to love both!");
|
||||
*
|
||||
* // Displays the user's input or the default value of "It's fine to love both!"
|
||||
* console.log("Best pet:", pet);
|
||||
* ```
|
||||
* @see https://developer.mozilla.org/en-US/docs/Web/API/Window/prompt
|
||||
*
|
||||
* @category Platform
|
||||
*
|
||||
* @param message
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
[package]
|
||||
name = "deno_broadcast_channel"
|
||||
version = "0.179.0"
|
||||
version = "0.180.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
|
2
ext/cache/Cargo.toml
vendored
2
ext/cache/Cargo.toml
vendored
|
@ -2,7 +2,7 @@
|
|||
|
||||
[package]
|
||||
name = "deno_cache"
|
||||
version = "0.117.0"
|
||||
version = "0.118.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
[package]
|
||||
name = "deno_canvas"
|
||||
version = "0.54.0"
|
||||
version = "0.55.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
|
|
@ -216,7 +216,7 @@ const styles = {
|
|||
regexp: "red",
|
||||
module: "underline",
|
||||
internalError: "red",
|
||||
temporal: "magenta",
|
||||
temporal: "cyan",
|
||||
};
|
||||
|
||||
const defaultFG = 39;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
[package]
|
||||
name = "deno_console"
|
||||
version = "0.185.0"
|
||||
version = "0.186.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
|
224
ext/console/lib.deno_console.d.ts
vendored
224
ext/console/lib.deno_console.d.ts
vendored
|
@ -6,33 +6,251 @@
|
|||
/// <reference lib="esnext" />
|
||||
|
||||
/** @category I/O */
|
||||
/**
|
||||
* The Console interface provides methods for logging information to the console,
|
||||
* as well as other utility methods for debugging and inspecting code.
|
||||
* @see https://developer.mozilla.org/en-US/docs/Web/API/console
|
||||
*/
|
||||
/** Interface representing the console object that provides methods for logging, debugging, and timing */
|
||||
interface Console {
|
||||
/**
|
||||
* Tests that an expression is true. If not, logs an error message
|
||||
* @param condition The expression to test for truthiness
|
||||
* @param data Additional arguments to be printed if the assertion fails
|
||||
* @example
|
||||
* ```ts
|
||||
* console.assert(1 === 1, "This won't show");
|
||||
* console.assert(1 === 2, "This will show an error");
|
||||
* ```
|
||||
*/
|
||||
assert(condition?: boolean, ...data: any[]): void;
|
||||
|
||||
/**
|
||||
* Clears the console if the environment allows it
|
||||
* @example
|
||||
* ```ts
|
||||
* console.clear();
|
||||
* ```
|
||||
*/
|
||||
clear(): void;
|
||||
|
||||
/**
|
||||
* Maintains an internal counter for a given label, incrementing it each time the method is called
|
||||
* @param label The label to count. Defaults to 'default'
|
||||
* @example
|
||||
* ```ts
|
||||
* console.count('myCounter');
|
||||
* console.count('myCounter'); // Will show: myCounter: 2
|
||||
* ```
|
||||
*/
|
||||
count(label?: string): void;
|
||||
|
||||
/**
|
||||
* Resets the counter for a given label
|
||||
* @param label The label to reset. Defaults to 'default'
|
||||
* @example
|
||||
* ```ts
|
||||
* console.count('myCounter');
|
||||
* console.countReset('myCounter'); // Resets to 0
|
||||
* ```
|
||||
*/
|
||||
countReset(label?: string): void;
|
||||
|
||||
/**
|
||||
* Outputs a debugging message to the console
|
||||
* @param data Values to be printed to the console
|
||||
* @example
|
||||
* ```ts
|
||||
* console.debug('Debug message', { detail: 'some data' });
|
||||
* ```
|
||||
*/
|
||||
debug(...data: any[]): void;
|
||||
|
||||
/**
|
||||
* Displays a list of the properties of a specified object
|
||||
* @param item Object to display
|
||||
* @param options Formatting options
|
||||
* @example
|
||||
* ```ts
|
||||
* console.dir({ name: 'object', value: 42 }, { depth: 1 });
|
||||
* ```
|
||||
*/
|
||||
dir(item?: any, options?: any): void;
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
dirxml(...data: any[]): void;
|
||||
|
||||
/**
|
||||
* Outputs an error message to the console.
|
||||
* This method routes the output to stderr,
|
||||
* unlike other console methods that route to stdout.
|
||||
* @param data Values to be printed to the console
|
||||
* @example
|
||||
* ```ts
|
||||
* console.error('Error occurred:', new Error('Something went wrong'));
|
||||
* ```
|
||||
*/
|
||||
error(...data: any[]): void;
|
||||
|
||||
/**
|
||||
* Creates a new inline group in the console, indenting subsequent console messages
|
||||
* @param data Labels for the group
|
||||
* @example
|
||||
* ```ts
|
||||
* console.group('Group 1');
|
||||
* console.log('Inside group 1');
|
||||
* console.groupEnd();
|
||||
* ```
|
||||
*/
|
||||
group(...data: any[]): void;
|
||||
|
||||
/**
|
||||
* Creates a new inline group in the console that is initially collapsed
|
||||
* @param data Labels for the group
|
||||
* @example
|
||||
* ```ts
|
||||
* console.groupCollapsed('Details');
|
||||
* console.log('Hidden until expanded');
|
||||
* console.groupEnd();
|
||||
* ```
|
||||
*/
|
||||
groupCollapsed(...data: any[]): void;
|
||||
|
||||
/**
|
||||
* Exits the current inline group in the console
|
||||
* @example
|
||||
* ```ts
|
||||
* console.group('Group');
|
||||
* console.log('Grouped message');
|
||||
* console.groupEnd();
|
||||
* ```
|
||||
*/
|
||||
groupEnd(): void;
|
||||
|
||||
/**
|
||||
* Outputs an informational message to the console
|
||||
* @param data Values to be printed to the console
|
||||
* @example
|
||||
* ```ts
|
||||
* console.info('Application started', { version: '1.0.0' });
|
||||
* ```
|
||||
*/
|
||||
info(...data: any[]): void;
|
||||
|
||||
/**
|
||||
* Outputs a message to the console
|
||||
* @param data Values to be printed to the console
|
||||
* @example
|
||||
* ```ts
|
||||
* console.log('Hello', 'World', 123);
|
||||
* ```
|
||||
*/
|
||||
log(...data: any[]): void;
|
||||
|
||||
/**
|
||||
* Displays tabular data as a table
|
||||
* @param tabularData Data to be displayed in table format
|
||||
* @param properties Array of property names to be displayed
|
||||
* @example
|
||||
* ```ts
|
||||
* console.table([
|
||||
* { name: 'John', age: 30 },
|
||||
* { name: 'Jane', age: 25 }
|
||||
* ]);
|
||||
* ```
|
||||
*/
|
||||
table(tabularData?: any, properties?: string[]): void;
|
||||
|
||||
/**
|
||||
* Starts a timer you can use to track how long an operation takes
|
||||
* @param label Timer label. Defaults to 'default'
|
||||
* @example
|
||||
* ```ts
|
||||
* console.time('operation');
|
||||
* // ... some code
|
||||
* console.timeEnd('operation');
|
||||
* ```
|
||||
*/
|
||||
time(label?: string): void;
|
||||
|
||||
/**
|
||||
* Stops a timer that was previously started
|
||||
* @param label Timer label to stop. Defaults to 'default'
|
||||
* @example
|
||||
* ```ts
|
||||
* console.time('operation');
|
||||
* // ... some code
|
||||
* console.timeEnd('operation'); // Prints: operation: 1234ms
|
||||
* ```
|
||||
*/
|
||||
timeEnd(label?: string): void;
|
||||
|
||||
/**
|
||||
* Logs the current value of a timer that was previously started
|
||||
* @param label Timer label
|
||||
* @param data Additional data to log
|
||||
* @example
|
||||
* ```ts
|
||||
* console.time('process');
|
||||
* // ... some code
|
||||
* console.timeLog('process', 'Checkpoint A');
|
||||
* ```
|
||||
*/
|
||||
timeLog(label?: string, ...data: any[]): void;
|
||||
|
||||
/**
|
||||
* Outputs a stack trace to the console
|
||||
* @param data Values to be printed to the console
|
||||
* @example
|
||||
* ```ts
|
||||
* console.trace('Trace message');
|
||||
* ```
|
||||
*/
|
||||
trace(...data: any[]): void;
|
||||
|
||||
/**
|
||||
* Outputs a warning message to the console
|
||||
* @param data Values to be printed to the console
|
||||
* @example
|
||||
* ```ts
|
||||
* console.warn('Deprecated feature used');
|
||||
* ```
|
||||
*/
|
||||
warn(...data: any[]): void;
|
||||
|
||||
/** This method is a noop, unless used in inspector */
|
||||
/**
|
||||
* Adds a marker to the DevTools Performance panel
|
||||
* @param label Label for the timestamp
|
||||
* @example
|
||||
* ```ts
|
||||
* console.timeStamp('Navigation Start');
|
||||
* ```
|
||||
*/
|
||||
timeStamp(label?: string): void;
|
||||
|
||||
/** This method is a noop, unless used in inspector */
|
||||
/**
|
||||
* Starts recording a performance profile
|
||||
* @param label Profile label
|
||||
* @example
|
||||
* ```ts
|
||||
* console.profile('Performance Profile');
|
||||
* // ... code to profile
|
||||
* console.profileEnd('Performance Profile');
|
||||
* ```
|
||||
*/
|
||||
profile(label?: string): void;
|
||||
|
||||
/** This method is a noop, unless used in inspector */
|
||||
/**
|
||||
* Stops recording a performance profile
|
||||
* @param label Profile label to stop
|
||||
* @example
|
||||
* ```ts
|
||||
* console.profile('Performance Profile');
|
||||
* // ... code to profile
|
||||
* console.profileEnd('Performance Profile');
|
||||
* ```
|
||||
*/
|
||||
profileEnd(label?: string): void;
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
[package]
|
||||
name = "deno_cron"
|
||||
version = "0.65.0"
|
||||
version = "0.66.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
[package]
|
||||
name = "deno_crypto"
|
||||
version = "0.199.0"
|
||||
version = "0.200.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
[package]
|
||||
name = "deno_fetch"
|
||||
version = "0.209.0"
|
||||
version = "0.210.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
[package]
|
||||
name = "deno_ffi"
|
||||
version = "0.172.0"
|
||||
version = "0.173.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
[package]
|
||||
name = "deno_fs"
|
||||
version = "0.95.0"
|
||||
version = "0.96.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
[package]
|
||||
name = "deno_http"
|
||||
version = "0.183.0"
|
||||
version = "0.184.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
[package]
|
||||
name = "deno_io"
|
||||
version = "0.95.0"
|
||||
version = "0.96.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
[package]
|
||||
name = "deno_kv"
|
||||
version = "0.93.0"
|
||||
version = "0.94.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
[package]
|
||||
name = "deno_napi"
|
||||
version = "0.116.0"
|
||||
version = "0.117.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
[package]
|
||||
name = "napi_sym"
|
||||
version = "0.115.0"
|
||||
version = "0.116.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
[package]
|
||||
name = "deno_net"
|
||||
version = "0.177.0"
|
||||
version = "0.178.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
[package]
|
||||
name = "deno_node"
|
||||
version = "0.123.0"
|
||||
version = "0.124.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
@ -38,6 +38,7 @@ deno_net.workspace = true
|
|||
deno_package_json.workspace = true
|
||||
deno_path_util.workspace = true
|
||||
deno_permissions.workspace = true
|
||||
deno_process.workspace = true
|
||||
deno_whoami = "0.1.0"
|
||||
der = { version = "0.7.9", features = ["derive"] }
|
||||
digest = { version = "0.10.5", features = ["core-api", "std"] }
|
||||
|
@ -75,7 +76,6 @@ p256.workspace = true
|
|||
p384.workspace = true
|
||||
path-clean = "=0.1.0"
|
||||
pbkdf2 = "0.12.1"
|
||||
pin-project-lite = "0.2.13"
|
||||
pkcs8 = { version = "0.10.2", features = ["std", "pkcs5", "encryption"] }
|
||||
rand.workspace = true
|
||||
regex.workspace = true
|
||||
|
|
|
@ -31,8 +31,6 @@ pub use deno_package_json::PackageJson;
|
|||
use deno_permissions::PermissionCheckError;
|
||||
pub use node_resolver::PathClean;
|
||||
pub use ops::ipc::ChildPipeFd;
|
||||
pub use ops::ipc::IpcJsonStreamResource;
|
||||
pub use ops::ipc::IpcRefTracker;
|
||||
use ops::vm;
|
||||
pub use ops::vm::create_v8_context;
|
||||
pub use ops::vm::init_global_template;
|
||||
|
|
|
@ -8,38 +8,24 @@ mod impl_ {
|
|||
use std::cell::RefCell;
|
||||
use std::future::Future;
|
||||
use std::io;
|
||||
use std::mem;
|
||||
use std::pin::Pin;
|
||||
use std::rc::Rc;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::atomic::AtomicUsize;
|
||||
use std::task::ready;
|
||||
use std::task::Context;
|
||||
use std::task::Poll;
|
||||
|
||||
use deno_core::op2;
|
||||
use deno_core::serde;
|
||||
use deno_core::serde::Serializer;
|
||||
use deno_core::serde_json;
|
||||
use deno_core::v8;
|
||||
use deno_core::AsyncRefCell;
|
||||
use deno_core::CancelFuture;
|
||||
use deno_core::CancelHandle;
|
||||
use deno_core::ExternalOpsTracker;
|
||||
use deno_core::OpState;
|
||||
use deno_core::RcRef;
|
||||
use deno_core::ResourceId;
|
||||
use deno_core::ToV8;
|
||||
use deno_error::JsErrorBox;
|
||||
use deno_io::BiPipe;
|
||||
use deno_io::BiPipeRead;
|
||||
use deno_io::BiPipeWrite;
|
||||
use memchr::memchr;
|
||||
use pin_project_lite::pin_project;
|
||||
use deno_process::ipc::IpcJsonStreamError;
|
||||
pub use deno_process::ipc::IpcJsonStreamResource;
|
||||
pub use deno_process::ipc::IpcRefTracker;
|
||||
pub use deno_process::ipc::INITIAL_CAPACITY;
|
||||
use serde::Serialize;
|
||||
use tokio::io::AsyncRead;
|
||||
use tokio::io::AsyncWriteExt;
|
||||
use tokio::io::ReadBuf;
|
||||
|
||||
/// Wrapper around v8 value that implements Serialize.
|
||||
struct SerializeWrapper<'a, 'b>(
|
||||
|
@ -289,534 +275,12 @@ mod impl_ {
|
|||
stream.ref_tracker.unref();
|
||||
}
|
||||
|
||||
/// Tracks whether the IPC resources is currently
|
||||
/// refed, and allows refing/unrefing it.
|
||||
pub struct IpcRefTracker {
|
||||
refed: AtomicBool,
|
||||
tracker: OpsTracker,
|
||||
}
|
||||
|
||||
/// A little wrapper so we don't have to get an
|
||||
/// `ExternalOpsTracker` for tests. When we aren't
|
||||
/// cfg(test), this will get optimized out.
|
||||
enum OpsTracker {
|
||||
External(ExternalOpsTracker),
|
||||
#[cfg(test)]
|
||||
Test,
|
||||
}
|
||||
|
||||
impl OpsTracker {
|
||||
fn ref_(&self) {
|
||||
match self {
|
||||
Self::External(tracker) => tracker.ref_op(),
|
||||
#[cfg(test)]
|
||||
Self::Test => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn unref(&self) {
|
||||
match self {
|
||||
Self::External(tracker) => tracker.unref_op(),
|
||||
#[cfg(test)]
|
||||
Self::Test => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl IpcRefTracker {
|
||||
pub fn new(tracker: ExternalOpsTracker) -> Self {
|
||||
Self {
|
||||
refed: AtomicBool::new(false),
|
||||
tracker: OpsTracker::External(tracker),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
fn new_test() -> Self {
|
||||
Self {
|
||||
refed: AtomicBool::new(false),
|
||||
tracker: OpsTracker::Test,
|
||||
}
|
||||
}
|
||||
|
||||
fn ref_(&self) {
|
||||
if !self.refed.swap(true, std::sync::atomic::Ordering::AcqRel) {
|
||||
self.tracker.ref_();
|
||||
}
|
||||
}
|
||||
|
||||
fn unref(&self) {
|
||||
if self.refed.swap(false, std::sync::atomic::Ordering::AcqRel) {
|
||||
self.tracker.unref();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct IpcJsonStreamResource {
|
||||
read_half: AsyncRefCell<IpcJsonStream>,
|
||||
write_half: AsyncRefCell<BiPipeWrite>,
|
||||
cancel: Rc<CancelHandle>,
|
||||
queued_bytes: AtomicUsize,
|
||||
ref_tracker: IpcRefTracker,
|
||||
}
|
||||
|
||||
impl deno_core::Resource for IpcJsonStreamResource {
|
||||
fn close(self: Rc<Self>) {
|
||||
self.cancel.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
impl IpcJsonStreamResource {
|
||||
pub fn new(
|
||||
stream: i64,
|
||||
ref_tracker: IpcRefTracker,
|
||||
) -> Result<Self, std::io::Error> {
|
||||
let (read_half, write_half) = BiPipe::from_raw(stream as _)?.split();
|
||||
Ok(Self {
|
||||
read_half: AsyncRefCell::new(IpcJsonStream::new(read_half)),
|
||||
write_half: AsyncRefCell::new(write_half),
|
||||
cancel: Default::default(),
|
||||
queued_bytes: Default::default(),
|
||||
ref_tracker,
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(all(unix, test))]
|
||||
fn from_stream(
|
||||
stream: tokio::net::UnixStream,
|
||||
ref_tracker: IpcRefTracker,
|
||||
) -> Self {
|
||||
let (read_half, write_half) = stream.into_split();
|
||||
Self {
|
||||
read_half: AsyncRefCell::new(IpcJsonStream::new(read_half.into())),
|
||||
write_half: AsyncRefCell::new(write_half.into()),
|
||||
cancel: Default::default(),
|
||||
queued_bytes: Default::default(),
|
||||
ref_tracker,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(windows, test))]
|
||||
fn from_stream(
|
||||
pipe: tokio::net::windows::named_pipe::NamedPipeClient,
|
||||
ref_tracker: IpcRefTracker,
|
||||
) -> Self {
|
||||
let (read_half, write_half) = tokio::io::split(pipe);
|
||||
Self {
|
||||
read_half: AsyncRefCell::new(IpcJsonStream::new(read_half.into())),
|
||||
write_half: AsyncRefCell::new(write_half.into()),
|
||||
cancel: Default::default(),
|
||||
queued_bytes: Default::default(),
|
||||
ref_tracker,
|
||||
}
|
||||
}
|
||||
|
||||
/// writes _newline terminated_ JSON message to the IPC pipe.
|
||||
async fn write_msg_bytes(
|
||||
self: Rc<Self>,
|
||||
msg: &[u8],
|
||||
) -> Result<(), io::Error> {
|
||||
let mut write_half =
|
||||
RcRef::map(self, |r| &r.write_half).borrow_mut().await;
|
||||
write_half.write_all(msg).await?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
// Initial capacity of the buffered reader and the JSON backing buffer.
|
||||
//
|
||||
// This is a tradeoff between memory usage and performance on large messages.
|
||||
//
|
||||
// 64kb has been chosen after benchmarking 64 to 66536 << 6 - 1 bytes per message.
|
||||
const INITIAL_CAPACITY: usize = 1024 * 64;
|
||||
|
||||
/// A buffer for reading from the IPC pipe.
|
||||
/// Similar to the internal buffer of `tokio::io::BufReader`.
|
||||
///
|
||||
/// This exists to provide buffered reading while granting mutable access
|
||||
/// to the internal buffer (which isn't exposed through `tokio::io::BufReader`
|
||||
/// or the `AsyncBufRead` trait). `simd_json` requires mutable access to an input
|
||||
/// buffer for parsing, so this allows us to use the read buffer directly as the
|
||||
/// input buffer without a copy (provided the message fits).
|
||||
struct ReadBuffer {
|
||||
buffer: Box<[u8]>,
|
||||
pos: usize,
|
||||
cap: usize,
|
||||
}
|
||||
|
||||
impl ReadBuffer {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
buffer: vec![0; INITIAL_CAPACITY].into_boxed_slice(),
|
||||
pos: 0,
|
||||
cap: 0,
|
||||
}
|
||||
}
|
||||
|
||||
fn get_mut(&mut self) -> &mut [u8] {
|
||||
&mut self.buffer
|
||||
}
|
||||
|
||||
fn available_mut(&mut self) -> &mut [u8] {
|
||||
&mut self.buffer[self.pos..self.cap]
|
||||
}
|
||||
|
||||
fn consume(&mut self, n: usize) {
|
||||
self.pos = std::cmp::min(self.pos + n, self.cap);
|
||||
}
|
||||
|
||||
fn needs_fill(&self) -> bool {
|
||||
self.pos >= self.cap
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error, deno_error::JsError)]
|
||||
pub enum IpcJsonStreamError {
|
||||
#[class(inherit)]
|
||||
#[error("{0}")]
|
||||
Io(#[source] std::io::Error),
|
||||
#[class(generic)]
|
||||
#[error("{0}")]
|
||||
SimdJson(#[source] simd_json::Error),
|
||||
}
|
||||
|
||||
// JSON serialization stream over IPC pipe.
|
||||
//
|
||||
// `\n` is used as a delimiter between messages.
|
||||
struct IpcJsonStream {
|
||||
pipe: BiPipeRead,
|
||||
buffer: Vec<u8>,
|
||||
read_buffer: ReadBuffer,
|
||||
}
|
||||
|
||||
impl IpcJsonStream {
|
||||
fn new(pipe: BiPipeRead) -> Self {
|
||||
Self {
|
||||
pipe,
|
||||
buffer: Vec::with_capacity(INITIAL_CAPACITY),
|
||||
read_buffer: ReadBuffer::new(),
|
||||
}
|
||||
}
|
||||
|
||||
async fn read_msg(
|
||||
&mut self,
|
||||
) -> Result<Option<serde_json::Value>, IpcJsonStreamError> {
|
||||
let mut json = None;
|
||||
let nread = read_msg_inner(
|
||||
&mut self.pipe,
|
||||
&mut self.buffer,
|
||||
&mut json,
|
||||
&mut self.read_buffer,
|
||||
)
|
||||
.await
|
||||
.map_err(IpcJsonStreamError::Io)?;
|
||||
if nread == 0 {
|
||||
// EOF.
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
let json = match json {
|
||||
Some(v) => v,
|
||||
None => {
|
||||
// Took more than a single read and some buffering.
|
||||
simd_json::from_slice(&mut self.buffer[..nread])
|
||||
.map_err(IpcJsonStreamError::SimdJson)?
|
||||
}
|
||||
};
|
||||
|
||||
// Safety: Same as `Vec::clear` but without the `drop_in_place` for
|
||||
// each element (nop for u8). Capacity remains the same.
|
||||
unsafe {
|
||||
self.buffer.set_len(0);
|
||||
}
|
||||
|
||||
Ok(Some(json))
|
||||
}
|
||||
}
|
||||
|
||||
pin_project! {
|
||||
#[must_use = "futures do nothing unless you `.await` or poll them"]
|
||||
struct ReadMsgInner<'a, R: ?Sized> {
|
||||
reader: &'a mut R,
|
||||
buf: &'a mut Vec<u8>,
|
||||
json: &'a mut Option<serde_json::Value>,
|
||||
// The number of bytes appended to buf. This can be less than buf.len() if
|
||||
// the buffer was not empty when the operation was started.
|
||||
read: usize,
|
||||
read_buffer: &'a mut ReadBuffer,
|
||||
}
|
||||
}
|
||||
|
||||
fn read_msg_inner<'a, R>(
|
||||
reader: &'a mut R,
|
||||
buf: &'a mut Vec<u8>,
|
||||
json: &'a mut Option<serde_json::Value>,
|
||||
read_buffer: &'a mut ReadBuffer,
|
||||
) -> ReadMsgInner<'a, R>
|
||||
where
|
||||
R: AsyncRead + ?Sized + Unpin,
|
||||
{
|
||||
ReadMsgInner {
|
||||
reader,
|
||||
buf,
|
||||
json,
|
||||
read: 0,
|
||||
read_buffer,
|
||||
}
|
||||
}
|
||||
|
||||
fn read_msg_internal<R: AsyncRead + ?Sized>(
|
||||
mut reader: Pin<&mut R>,
|
||||
cx: &mut Context<'_>,
|
||||
buf: &mut Vec<u8>,
|
||||
read_buffer: &mut ReadBuffer,
|
||||
json: &mut Option<serde_json::Value>,
|
||||
read: &mut usize,
|
||||
) -> Poll<io::Result<usize>> {
|
||||
loop {
|
||||
let (done, used) = {
|
||||
// effectively a tiny `poll_fill_buf`, but allows us to get a mutable reference to the buffer.
|
||||
if read_buffer.needs_fill() {
|
||||
let mut read_buf = ReadBuf::new(read_buffer.get_mut());
|
||||
ready!(reader.as_mut().poll_read(cx, &mut read_buf))?;
|
||||
read_buffer.cap = read_buf.filled().len();
|
||||
read_buffer.pos = 0;
|
||||
}
|
||||
let available = read_buffer.available_mut();
|
||||
if let Some(i) = memchr(b'\n', available) {
|
||||
if *read == 0 {
|
||||
// Fast path: parse and put into the json slot directly.
|
||||
json.replace(
|
||||
simd_json::from_slice(&mut available[..i + 1])
|
||||
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?,
|
||||
);
|
||||
} else {
|
||||
// This is not the first read, so we have to copy the data
|
||||
// to make it contiguous.
|
||||
buf.extend_from_slice(&available[..=i]);
|
||||
}
|
||||
(true, i + 1)
|
||||
} else {
|
||||
buf.extend_from_slice(available);
|
||||
(false, available.len())
|
||||
}
|
||||
};
|
||||
|
||||
read_buffer.consume(used);
|
||||
*read += used;
|
||||
if done || used == 0 {
|
||||
return Poll::Ready(Ok(mem::replace(read, 0)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: AsyncRead + ?Sized + Unpin> Future for ReadMsgInner<'_, R> {
|
||||
type Output = io::Result<usize>;
|
||||
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
let me = self.project();
|
||||
read_msg_internal(
|
||||
Pin::new(*me.reader),
|
||||
cx,
|
||||
me.buf,
|
||||
me.read_buffer,
|
||||
me.json,
|
||||
me.read,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::rc::Rc;
|
||||
|
||||
use deno_core::serde_json::json;
|
||||
use deno_core::v8;
|
||||
use deno_core::JsRuntime;
|
||||
use deno_core::RcRef;
|
||||
use deno_core::RuntimeOptions;
|
||||
|
||||
use super::IpcJsonStreamResource;
|
||||
|
||||
#[allow(clippy::unused_async)]
|
||||
#[cfg(unix)]
|
||||
pub async fn pair() -> (Rc<IpcJsonStreamResource>, tokio::net::UnixStream) {
|
||||
let (a, b) = tokio::net::UnixStream::pair().unwrap();
|
||||
|
||||
/* Similar to how ops would use the resource */
|
||||
let a = Rc::new(IpcJsonStreamResource::from_stream(
|
||||
a,
|
||||
super::IpcRefTracker::new_test(),
|
||||
));
|
||||
(a, b)
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
pub async fn pair() -> (
|
||||
Rc<IpcJsonStreamResource>,
|
||||
tokio::net::windows::named_pipe::NamedPipeServer,
|
||||
) {
|
||||
use tokio::net::windows::named_pipe::ClientOptions;
|
||||
use tokio::net::windows::named_pipe::ServerOptions;
|
||||
|
||||
let name =
|
||||
format!(r"\\.\pipe\deno-named-pipe-test-{}", rand::random::<u32>());
|
||||
|
||||
let server = ServerOptions::new().create(name.clone()).unwrap();
|
||||
let client = ClientOptions::new().open(name).unwrap();
|
||||
|
||||
server.connect().await.unwrap();
|
||||
/* Similar to how ops would use the resource */
|
||||
let client = Rc::new(IpcJsonStreamResource::from_stream(
|
||||
client,
|
||||
super::IpcRefTracker::new_test(),
|
||||
));
|
||||
(client, server)
|
||||
}
|
||||
|
||||
#[allow(clippy::print_stdout)]
|
||||
#[tokio::test]
|
||||
async fn bench_ipc() -> Result<(), Box<dyn std::error::Error>> {
|
||||
// A simple round trip benchmark for quick dev feedback.
|
||||
//
|
||||
// Only ran when the env var is set.
|
||||
if std::env::var_os("BENCH_IPC_DENO").is_none() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let (ipc, mut fd2) = pair().await;
|
||||
let child = tokio::spawn(async move {
|
||||
use tokio::io::AsyncWriteExt;
|
||||
|
||||
let size = 1024 * 1024;
|
||||
|
||||
let stri = "x".repeat(size);
|
||||
let data = format!("\"{}\"\n", stri);
|
||||
for _ in 0..100 {
|
||||
fd2.write_all(data.as_bytes()).await?;
|
||||
}
|
||||
Ok::<_, std::io::Error>(())
|
||||
});
|
||||
|
||||
let start = std::time::Instant::now();
|
||||
let mut bytes = 0;
|
||||
|
||||
let mut ipc = RcRef::map(ipc, |r| &r.read_half).borrow_mut().await;
|
||||
loop {
|
||||
let Some(msgs) = ipc.read_msg().await? else {
|
||||
break;
|
||||
};
|
||||
bytes += msgs.as_str().unwrap().len();
|
||||
if start.elapsed().as_secs() > 5 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
let elapsed = start.elapsed();
|
||||
let mb = bytes as f64 / 1024.0 / 1024.0;
|
||||
println!("{} mb/s", mb / elapsed.as_secs_f64());
|
||||
|
||||
child.await??;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn unix_ipc_json() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let (ipc, mut fd2) = pair().await;
|
||||
let child = tokio::spawn(async move {
|
||||
use tokio::io::AsyncReadExt;
|
||||
use tokio::io::AsyncWriteExt;
|
||||
|
||||
const EXPECTED: &[u8] = b"\"hello\"\n";
|
||||
let mut buf = [0u8; EXPECTED.len()];
|
||||
let n = fd2.read_exact(&mut buf).await?;
|
||||
assert_eq!(&buf[..n], EXPECTED);
|
||||
fd2.write_all(b"\"world\"\n").await?;
|
||||
|
||||
Ok::<_, std::io::Error>(())
|
||||
});
|
||||
|
||||
ipc
|
||||
.clone()
|
||||
.write_msg_bytes(&json_to_bytes(json!("hello")))
|
||||
.await?;
|
||||
|
||||
let mut ipc = RcRef::map(ipc, |r| &r.read_half).borrow_mut().await;
|
||||
let msgs = ipc.read_msg().await?.unwrap();
|
||||
assert_eq!(msgs, json!("world"));
|
||||
|
||||
child.await??;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn json_to_bytes(v: deno_core::serde_json::Value) -> Vec<u8> {
|
||||
let mut buf = deno_core::serde_json::to_vec(&v).unwrap();
|
||||
buf.push(b'\n');
|
||||
buf
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn unix_ipc_json_multi() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let (ipc, mut fd2) = pair().await;
|
||||
let child = tokio::spawn(async move {
|
||||
use tokio::io::AsyncReadExt;
|
||||
use tokio::io::AsyncWriteExt;
|
||||
|
||||
const EXPECTED: &[u8] = b"\"hello\"\n\"world\"\n";
|
||||
let mut buf = [0u8; EXPECTED.len()];
|
||||
let n = fd2.read_exact(&mut buf).await?;
|
||||
assert_eq!(&buf[..n], EXPECTED);
|
||||
fd2.write_all(b"\"foo\"\n\"bar\"\n").await?;
|
||||
Ok::<_, std::io::Error>(())
|
||||
});
|
||||
|
||||
ipc
|
||||
.clone()
|
||||
.write_msg_bytes(&json_to_bytes(json!("hello")))
|
||||
.await?;
|
||||
ipc
|
||||
.clone()
|
||||
.write_msg_bytes(&json_to_bytes(json!("world")))
|
||||
.await?;
|
||||
|
||||
let mut ipc = RcRef::map(ipc, |r| &r.read_half).borrow_mut().await;
|
||||
let msgs = ipc.read_msg().await?.unwrap();
|
||||
assert_eq!(msgs, json!("foo"));
|
||||
|
||||
child.await??;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn unix_ipc_json_invalid() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let (ipc, mut fd2) = pair().await;
|
||||
let child = tokio::spawn(async move {
|
||||
tokio::io::AsyncWriteExt::write_all(&mut fd2, b"\n\n").await?;
|
||||
Ok::<_, std::io::Error>(())
|
||||
});
|
||||
|
||||
let mut ipc = RcRef::map(ipc, |r| &r.read_half).borrow_mut().await;
|
||||
let _err = ipc.read_msg().await.unwrap_err();
|
||||
|
||||
child.await??;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn memchr() {
|
||||
let str = b"hello world";
|
||||
assert_eq!(super::memchr(b'h', str), Some(0));
|
||||
assert_eq!(super::memchr(b'w', str), Some(6));
|
||||
assert_eq!(super::memchr(b'd', str), Some(10));
|
||||
assert_eq!(super::memchr(b'x', str), None);
|
||||
|
||||
let empty = b"";
|
||||
assert_eq!(super::memchr(b'\n', empty), None);
|
||||
}
|
||||
|
||||
fn wrap_expr(s: &str) -> String {
|
||||
format!("(function () {{ return {s}; }})()")
|
||||
}
|
||||
|
|
|
@ -53,7 +53,7 @@ import {
|
|||
convertToValidSignal,
|
||||
kEmptyObject,
|
||||
} from "ext:deno_node/internal/util.mjs";
|
||||
import { kNeedsNpmProcessState } from "ext:runtime/40_process.js";
|
||||
import { kNeedsNpmProcessState } from "ext:deno_process/40_process.js";
|
||||
|
||||
const MAX_BUFFER = 1024 * 1024;
|
||||
|
||||
|
|
|
@ -455,8 +455,13 @@ class ClientRequest extends OutgoingMessage {
|
|||
(async () => {
|
||||
try {
|
||||
const parsedUrl = new URL(url);
|
||||
let baseConnRid =
|
||||
this.socket._handle[kStreamBaseField][internalRidSymbol];
|
||||
const handle = this.socket._handle;
|
||||
if (!handle) {
|
||||
// Using non-standard socket. There's no way to handle this type of socket.
|
||||
// This should be only happening in artificial test cases
|
||||
return;
|
||||
}
|
||||
let baseConnRid = handle[kStreamBaseField][internalRidSymbol];
|
||||
if (this._encrypted) {
|
||||
[baseConnRid] = op_tls_start({
|
||||
rid: baseConnRid,
|
||||
|
@ -637,6 +642,12 @@ class ClientRequest extends OutgoingMessage {
|
|||
};
|
||||
this.socket = socket;
|
||||
this.emit("socket", socket);
|
||||
socket.once("error", (err) => {
|
||||
// This callback loosely follow `socketErrorListener` in Node.js
|
||||
// https://github.com/nodejs/node/blob/f16cd10946ca9ad272f42b94f00cf960571c9181/lib/_http_client.js#L509
|
||||
emitErrorEvent(this, err);
|
||||
socket.destroy(err);
|
||||
});
|
||||
if (socket.readyState === "opening") {
|
||||
socket.on("connect", onConnect);
|
||||
} else {
|
||||
|
|
|
@ -61,7 +61,7 @@ import {
|
|||
kExtraStdio,
|
||||
kIpc,
|
||||
kNeedsNpmProcessState,
|
||||
} from "ext:runtime/40_process.js";
|
||||
} from "ext:deno_process/40_process.js";
|
||||
|
||||
export function mapValues<T, O>(
|
||||
record: Readonly<Record<string, T>>,
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
[package]
|
||||
name = "deno_os"
|
||||
version = "0.1.0"
|
||||
version = "0.3.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
|
41
ext/process/Cargo.toml
Normal file
41
ext/process/Cargo.toml
Normal file
|
@ -0,0 +1,41 @@
|
|||
# Copyright 2018-2025 the Deno authors. MIT license.
|
||||
|
||||
[package]
|
||||
name = "deno_process"
|
||||
version = "0.1.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
readme = "README.md"
|
||||
repository.workspace = true
|
||||
description = "Subprocess APIs for Deno"
|
||||
|
||||
[lib]
|
||||
path = "lib.rs"
|
||||
|
||||
[dependencies]
|
||||
deno_core.workspace = true
|
||||
deno_error.workspace = true
|
||||
deno_fs.workspace = true
|
||||
deno_io.workspace = true
|
||||
deno_os.workspace = true
|
||||
deno_path_util.workspace = true
|
||||
deno_permissions.workspace = true
|
||||
libc.workspace = true
|
||||
log.workspace = true
|
||||
memchr = "2.7.4"
|
||||
pin-project-lite = "0.2.13"
|
||||
rand.workspace = true
|
||||
serde.workspace = true
|
||||
simd-json = "0.14.0"
|
||||
tempfile.workspace = true
|
||||
thiserror.workspace = true
|
||||
tokio.workspace = true
|
||||
which.workspace = true
|
||||
|
||||
[target.'cfg(unix)'.dependencies]
|
||||
nix = { workspace = true, features = ["signal", "process"] }
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
winapi = { workspace = true, features = [] }
|
||||
windows-sys.workspace = true
|
3
ext/process/README.md
Normal file
3
ext/process/README.md
Normal file
|
@ -0,0 +1,3 @@
|
|||
# deno_process
|
||||
|
||||
This crate implements subprocess APIs for Deno
|
558
ext/process/ipc.rs
Normal file
558
ext/process/ipc.rs
Normal file
|
@ -0,0 +1,558 @@
|
|||
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||
|
||||
#![allow(unused)]
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::future::Future;
|
||||
use std::io;
|
||||
use std::mem;
|
||||
use std::pin::Pin;
|
||||
use std::rc::Rc;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::atomic::AtomicUsize;
|
||||
use std::task::ready;
|
||||
use std::task::Context;
|
||||
use std::task::Poll;
|
||||
|
||||
use deno_core::serde;
|
||||
use deno_core::serde_json;
|
||||
use deno_core::AsyncRefCell;
|
||||
use deno_core::CancelHandle;
|
||||
use deno_core::ExternalOpsTracker;
|
||||
use deno_core::RcRef;
|
||||
use deno_io::BiPipe;
|
||||
use deno_io::BiPipeRead;
|
||||
use deno_io::BiPipeWrite;
|
||||
use memchr::memchr;
|
||||
use pin_project_lite::pin_project;
|
||||
use tokio::io::AsyncRead;
|
||||
use tokio::io::AsyncWriteExt;
|
||||
use tokio::io::ReadBuf;
|
||||
|
||||
/// Tracks whether the IPC resources is currently
|
||||
/// refed, and allows refing/unrefing it.
|
||||
pub struct IpcRefTracker {
|
||||
refed: AtomicBool,
|
||||
tracker: OpsTracker,
|
||||
}
|
||||
|
||||
/// A little wrapper so we don't have to get an
|
||||
/// `ExternalOpsTracker` for tests. When we aren't
|
||||
/// cfg(test), this will get optimized out.
|
||||
enum OpsTracker {
|
||||
External(ExternalOpsTracker),
|
||||
#[cfg(test)]
|
||||
Test,
|
||||
}
|
||||
|
||||
impl OpsTracker {
|
||||
fn ref_(&self) {
|
||||
match self {
|
||||
Self::External(tracker) => tracker.ref_op(),
|
||||
#[cfg(test)]
|
||||
Self::Test => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn unref(&self) {
|
||||
match self {
|
||||
Self::External(tracker) => tracker.unref_op(),
|
||||
#[cfg(test)]
|
||||
Self::Test => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl IpcRefTracker {
|
||||
pub fn new(tracker: ExternalOpsTracker) -> Self {
|
||||
Self {
|
||||
refed: AtomicBool::new(false),
|
||||
tracker: OpsTracker::External(tracker),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
fn new_test() -> Self {
|
||||
Self {
|
||||
refed: AtomicBool::new(false),
|
||||
tracker: OpsTracker::Test,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ref_(&self) {
|
||||
if !self.refed.swap(true, std::sync::atomic::Ordering::AcqRel) {
|
||||
self.tracker.ref_();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unref(&self) {
|
||||
if self.refed.swap(false, std::sync::atomic::Ordering::AcqRel) {
|
||||
self.tracker.unref();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct IpcJsonStreamResource {
|
||||
pub read_half: AsyncRefCell<IpcJsonStream>,
|
||||
pub write_half: AsyncRefCell<BiPipeWrite>,
|
||||
pub cancel: Rc<CancelHandle>,
|
||||
pub queued_bytes: AtomicUsize,
|
||||
pub ref_tracker: IpcRefTracker,
|
||||
}
|
||||
|
||||
impl deno_core::Resource for IpcJsonStreamResource {
|
||||
fn close(self: Rc<Self>) {
|
||||
self.cancel.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
impl IpcJsonStreamResource {
|
||||
pub fn new(
|
||||
stream: i64,
|
||||
ref_tracker: IpcRefTracker,
|
||||
) -> Result<Self, std::io::Error> {
|
||||
let (read_half, write_half) = BiPipe::from_raw(stream as _)?.split();
|
||||
Ok(Self {
|
||||
read_half: AsyncRefCell::new(IpcJsonStream::new(read_half)),
|
||||
write_half: AsyncRefCell::new(write_half),
|
||||
cancel: Default::default(),
|
||||
queued_bytes: Default::default(),
|
||||
ref_tracker,
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(all(unix, test))]
|
||||
pub fn from_stream(
|
||||
stream: tokio::net::UnixStream,
|
||||
ref_tracker: IpcRefTracker,
|
||||
) -> Self {
|
||||
let (read_half, write_half) = stream.into_split();
|
||||
Self {
|
||||
read_half: AsyncRefCell::new(IpcJsonStream::new(read_half.into())),
|
||||
write_half: AsyncRefCell::new(write_half.into()),
|
||||
cancel: Default::default(),
|
||||
queued_bytes: Default::default(),
|
||||
ref_tracker,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(windows, test))]
|
||||
pub fn from_stream(
|
||||
pipe: tokio::net::windows::named_pipe::NamedPipeClient,
|
||||
ref_tracker: IpcRefTracker,
|
||||
) -> Self {
|
||||
let (read_half, write_half) = tokio::io::split(pipe);
|
||||
Self {
|
||||
read_half: AsyncRefCell::new(IpcJsonStream::new(read_half.into())),
|
||||
write_half: AsyncRefCell::new(write_half.into()),
|
||||
cancel: Default::default(),
|
||||
queued_bytes: Default::default(),
|
||||
ref_tracker,
|
||||
}
|
||||
}
|
||||
|
||||
/// writes _newline terminated_ JSON message to the IPC pipe.
|
||||
pub async fn write_msg_bytes(
|
||||
self: Rc<Self>,
|
||||
msg: &[u8],
|
||||
) -> Result<(), io::Error> {
|
||||
let mut write_half = RcRef::map(self, |r| &r.write_half).borrow_mut().await;
|
||||
write_half.write_all(msg).await?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
// Initial capacity of the buffered reader and the JSON backing buffer.
|
||||
//
|
||||
// This is a tradeoff between memory usage and performance on large messages.
|
||||
//
|
||||
// 64kb has been chosen after benchmarking 64 to 66536 << 6 - 1 bytes per message.
|
||||
pub const INITIAL_CAPACITY: usize = 1024 * 64;
|
||||
|
||||
/// A buffer for reading from the IPC pipe.
|
||||
/// Similar to the internal buffer of `tokio::io::BufReader`.
|
||||
///
|
||||
/// This exists to provide buffered reading while granting mutable access
|
||||
/// to the internal buffer (which isn't exposed through `tokio::io::BufReader`
|
||||
/// or the `AsyncBufRead` trait). `simd_json` requires mutable access to an input
|
||||
/// buffer for parsing, so this allows us to use the read buffer directly as the
|
||||
/// input buffer without a copy (provided the message fits).
|
||||
struct ReadBuffer {
|
||||
buffer: Box<[u8]>,
|
||||
pos: usize,
|
||||
cap: usize,
|
||||
}
|
||||
|
||||
impl ReadBuffer {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
buffer: vec![0; INITIAL_CAPACITY].into_boxed_slice(),
|
||||
pos: 0,
|
||||
cap: 0,
|
||||
}
|
||||
}
|
||||
|
||||
fn get_mut(&mut self) -> &mut [u8] {
|
||||
&mut self.buffer
|
||||
}
|
||||
|
||||
fn available_mut(&mut self) -> &mut [u8] {
|
||||
&mut self.buffer[self.pos..self.cap]
|
||||
}
|
||||
|
||||
fn consume(&mut self, n: usize) {
|
||||
self.pos = std::cmp::min(self.pos + n, self.cap);
|
||||
}
|
||||
|
||||
fn needs_fill(&self) -> bool {
|
||||
self.pos >= self.cap
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error, deno_error::JsError)]
|
||||
pub enum IpcJsonStreamError {
|
||||
#[class(inherit)]
|
||||
#[error("{0}")]
|
||||
Io(#[source] std::io::Error),
|
||||
#[class(generic)]
|
||||
#[error("{0}")]
|
||||
SimdJson(#[source] simd_json::Error),
|
||||
}
|
||||
|
||||
// JSON serialization stream over IPC pipe.
|
||||
//
|
||||
// `\n` is used as a delimiter between messages.
|
||||
pub struct IpcJsonStream {
|
||||
pipe: BiPipeRead,
|
||||
buffer: Vec<u8>,
|
||||
read_buffer: ReadBuffer,
|
||||
}
|
||||
|
||||
impl IpcJsonStream {
|
||||
fn new(pipe: BiPipeRead) -> Self {
|
||||
Self {
|
||||
pipe,
|
||||
buffer: Vec::with_capacity(INITIAL_CAPACITY),
|
||||
read_buffer: ReadBuffer::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn read_msg(
|
||||
&mut self,
|
||||
) -> Result<Option<serde_json::Value>, IpcJsonStreamError> {
|
||||
let mut json = None;
|
||||
let nread = read_msg_inner(
|
||||
&mut self.pipe,
|
||||
&mut self.buffer,
|
||||
&mut json,
|
||||
&mut self.read_buffer,
|
||||
)
|
||||
.await
|
||||
.map_err(IpcJsonStreamError::Io)?;
|
||||
if nread == 0 {
|
||||
// EOF.
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
let json = match json {
|
||||
Some(v) => v,
|
||||
None => {
|
||||
// Took more than a single read and some buffering.
|
||||
simd_json::from_slice(&mut self.buffer[..nread])
|
||||
.map_err(IpcJsonStreamError::SimdJson)?
|
||||
}
|
||||
};
|
||||
|
||||
// Safety: Same as `Vec::clear` but without the `drop_in_place` for
|
||||
// each element (nop for u8). Capacity remains the same.
|
||||
unsafe {
|
||||
self.buffer.set_len(0);
|
||||
}
|
||||
|
||||
Ok(Some(json))
|
||||
}
|
||||
}
|
||||
|
||||
pin_project! {
|
||||
#[must_use = "futures do nothing unless you `.await` or poll them"]
|
||||
struct ReadMsgInner<'a, R: ?Sized> {
|
||||
reader: &'a mut R,
|
||||
buf: &'a mut Vec<u8>,
|
||||
json: &'a mut Option<serde_json::Value>,
|
||||
// The number of bytes appended to buf. This can be less than buf.len() if
|
||||
// the buffer was not empty when the operation was started.
|
||||
read: usize,
|
||||
read_buffer: &'a mut ReadBuffer,
|
||||
}
|
||||
}
|
||||
|
||||
fn read_msg_inner<'a, R>(
|
||||
reader: &'a mut R,
|
||||
buf: &'a mut Vec<u8>,
|
||||
json: &'a mut Option<serde_json::Value>,
|
||||
read_buffer: &'a mut ReadBuffer,
|
||||
) -> ReadMsgInner<'a, R>
|
||||
where
|
||||
R: AsyncRead + ?Sized + Unpin,
|
||||
{
|
||||
ReadMsgInner {
|
||||
reader,
|
||||
buf,
|
||||
json,
|
||||
read: 0,
|
||||
read_buffer,
|
||||
}
|
||||
}
|
||||
|
||||
fn read_msg_internal<R: AsyncRead + ?Sized>(
|
||||
mut reader: Pin<&mut R>,
|
||||
cx: &mut Context<'_>,
|
||||
buf: &mut Vec<u8>,
|
||||
read_buffer: &mut ReadBuffer,
|
||||
json: &mut Option<serde_json::Value>,
|
||||
read: &mut usize,
|
||||
) -> Poll<io::Result<usize>> {
|
||||
loop {
|
||||
let (done, used) = {
|
||||
// effectively a tiny `poll_fill_buf`, but allows us to get a mutable reference to the buffer.
|
||||
if read_buffer.needs_fill() {
|
||||
let mut read_buf = ReadBuf::new(read_buffer.get_mut());
|
||||
ready!(reader.as_mut().poll_read(cx, &mut read_buf))?;
|
||||
read_buffer.cap = read_buf.filled().len();
|
||||
read_buffer.pos = 0;
|
||||
}
|
||||
let available = read_buffer.available_mut();
|
||||
if let Some(i) = memchr(b'\n', available) {
|
||||
if *read == 0 {
|
||||
// Fast path: parse and put into the json slot directly.
|
||||
json.replace(
|
||||
simd_json::from_slice(&mut available[..i + 1])
|
||||
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?,
|
||||
);
|
||||
} else {
|
||||
// This is not the first read, so we have to copy the data
|
||||
// to make it contiguous.
|
||||
buf.extend_from_slice(&available[..=i]);
|
||||
}
|
||||
(true, i + 1)
|
||||
} else {
|
||||
buf.extend_from_slice(available);
|
||||
(false, available.len())
|
||||
}
|
||||
};
|
||||
|
||||
read_buffer.consume(used);
|
||||
*read += used;
|
||||
if done || used == 0 {
|
||||
return Poll::Ready(Ok(mem::replace(read, 0)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: AsyncRead + ?Sized + Unpin> Future for ReadMsgInner<'_, R> {
|
||||
type Output = io::Result<usize>;
|
||||
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
let me = self.project();
|
||||
read_msg_internal(
|
||||
Pin::new(*me.reader),
|
||||
cx,
|
||||
me.buf,
|
||||
me.read_buffer,
|
||||
me.json,
|
||||
me.read,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::rc::Rc;
|
||||
|
||||
use deno_core::serde_json::json;
|
||||
use deno_core::v8;
|
||||
use deno_core::JsRuntime;
|
||||
use deno_core::RcRef;
|
||||
use deno_core::RuntimeOptions;
|
||||
|
||||
use super::IpcJsonStreamResource;
|
||||
|
||||
#[allow(clippy::unused_async)]
|
||||
#[cfg(unix)]
|
||||
pub async fn pair() -> (Rc<IpcJsonStreamResource>, tokio::net::UnixStream) {
|
||||
let (a, b) = tokio::net::UnixStream::pair().unwrap();
|
||||
|
||||
/* Similar to how ops would use the resource */
|
||||
let a = Rc::new(IpcJsonStreamResource::from_stream(
|
||||
a,
|
||||
super::IpcRefTracker::new_test(),
|
||||
));
|
||||
(a, b)
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
pub async fn pair() -> (
|
||||
Rc<IpcJsonStreamResource>,
|
||||
tokio::net::windows::named_pipe::NamedPipeServer,
|
||||
) {
|
||||
use tokio::net::windows::named_pipe::ClientOptions;
|
||||
use tokio::net::windows::named_pipe::ServerOptions;
|
||||
|
||||
let name =
|
||||
format!(r"\\.\pipe\deno-named-pipe-test-{}", rand::random::<u32>());
|
||||
|
||||
let server = ServerOptions::new().create(name.clone()).unwrap();
|
||||
let client = ClientOptions::new().open(name).unwrap();
|
||||
|
||||
server.connect().await.unwrap();
|
||||
/* Similar to how ops would use the resource */
|
||||
let client = Rc::new(IpcJsonStreamResource::from_stream(
|
||||
client,
|
||||
super::IpcRefTracker::new_test(),
|
||||
));
|
||||
(client, server)
|
||||
}
|
||||
|
||||
#[allow(clippy::print_stdout)]
|
||||
#[tokio::test]
|
||||
async fn bench_ipc() -> Result<(), Box<dyn std::error::Error>> {
|
||||
// A simple round trip benchmark for quick dev feedback.
|
||||
//
|
||||
// Only ran when the env var is set.
|
||||
if std::env::var_os("BENCH_IPC_DENO").is_none() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let (ipc, mut fd2) = pair().await;
|
||||
let child = tokio::spawn(async move {
|
||||
use tokio::io::AsyncWriteExt;
|
||||
|
||||
let size = 1024 * 1024;
|
||||
|
||||
let stri = "x".repeat(size);
|
||||
let data = format!("\"{}\"\n", stri);
|
||||
for _ in 0..100 {
|
||||
fd2.write_all(data.as_bytes()).await?;
|
||||
}
|
||||
Ok::<_, std::io::Error>(())
|
||||
});
|
||||
|
||||
let start = std::time::Instant::now();
|
||||
let mut bytes = 0;
|
||||
|
||||
let mut ipc = RcRef::map(ipc, |r| &r.read_half).borrow_mut().await;
|
||||
loop {
|
||||
let Some(msgs) = ipc.read_msg().await? else {
|
||||
break;
|
||||
};
|
||||
bytes += msgs.as_str().unwrap().len();
|
||||
if start.elapsed().as_secs() > 5 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
let elapsed = start.elapsed();
|
||||
let mb = bytes as f64 / 1024.0 / 1024.0;
|
||||
println!("{} mb/s", mb / elapsed.as_secs_f64());
|
||||
|
||||
child.await??;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn unix_ipc_json() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let (ipc, mut fd2) = pair().await;
|
||||
let child = tokio::spawn(async move {
|
||||
use tokio::io::AsyncReadExt;
|
||||
use tokio::io::AsyncWriteExt;
|
||||
|
||||
const EXPECTED: &[u8] = b"\"hello\"\n";
|
||||
let mut buf = [0u8; EXPECTED.len()];
|
||||
let n = fd2.read_exact(&mut buf).await?;
|
||||
assert_eq!(&buf[..n], EXPECTED);
|
||||
fd2.write_all(b"\"world\"\n").await?;
|
||||
|
||||
Ok::<_, std::io::Error>(())
|
||||
});
|
||||
|
||||
ipc
|
||||
.clone()
|
||||
.write_msg_bytes(&json_to_bytes(json!("hello")))
|
||||
.await?;
|
||||
|
||||
let mut ipc = RcRef::map(ipc, |r| &r.read_half).borrow_mut().await;
|
||||
let msgs = ipc.read_msg().await?.unwrap();
|
||||
assert_eq!(msgs, json!("world"));
|
||||
|
||||
child.await??;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn json_to_bytes(v: deno_core::serde_json::Value) -> Vec<u8> {
|
||||
let mut buf = deno_core::serde_json::to_vec(&v).unwrap();
|
||||
buf.push(b'\n');
|
||||
buf
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn unix_ipc_json_multi() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let (ipc, mut fd2) = pair().await;
|
||||
let child = tokio::spawn(async move {
|
||||
use tokio::io::AsyncReadExt;
|
||||
use tokio::io::AsyncWriteExt;
|
||||
|
||||
const EXPECTED: &[u8] = b"\"hello\"\n\"world\"\n";
|
||||
let mut buf = [0u8; EXPECTED.len()];
|
||||
let n = fd2.read_exact(&mut buf).await?;
|
||||
assert_eq!(&buf[..n], EXPECTED);
|
||||
fd2.write_all(b"\"foo\"\n\"bar\"\n").await?;
|
||||
Ok::<_, std::io::Error>(())
|
||||
});
|
||||
|
||||
ipc
|
||||
.clone()
|
||||
.write_msg_bytes(&json_to_bytes(json!("hello")))
|
||||
.await?;
|
||||
ipc
|
||||
.clone()
|
||||
.write_msg_bytes(&json_to_bytes(json!("world")))
|
||||
.await?;
|
||||
|
||||
let mut ipc = RcRef::map(ipc, |r| &r.read_half).borrow_mut().await;
|
||||
let msgs = ipc.read_msg().await?.unwrap();
|
||||
assert_eq!(msgs, json!("foo"));
|
||||
|
||||
child.await??;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn unix_ipc_json_invalid() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let (ipc, mut fd2) = pair().await;
|
||||
let child = tokio::spawn(async move {
|
||||
tokio::io::AsyncWriteExt::write_all(&mut fd2, b"\n\n").await?;
|
||||
Ok::<_, std::io::Error>(())
|
||||
});
|
||||
|
||||
let mut ipc = RcRef::map(ipc, |r| &r.read_half).borrow_mut().await;
|
||||
let _err = ipc.read_msg().await.unwrap_err();
|
||||
|
||||
child.await??;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn memchr() {
|
||||
let str = b"hello world";
|
||||
assert_eq!(super::memchr(b'h', str), Some(0));
|
||||
assert_eq!(super::memchr(b'w', str), Some(6));
|
||||
assert_eq!(super::memchr(b'd', str), Some(10));
|
||||
assert_eq!(super::memchr(b'x', str), None);
|
||||
|
||||
let empty = b"";
|
||||
assert_eq!(super::memchr(b'\n', empty), None);
|
||||
}
|
||||
}
|
|
@ -38,6 +38,10 @@ use serde::Deserialize;
|
|||
use serde::Serialize;
|
||||
use tokio::process::Command;
|
||||
|
||||
pub mod ipc;
|
||||
use ipc::IpcJsonStreamResource;
|
||||
use ipc::IpcRefTracker;
|
||||
|
||||
pub const UNSTABLE_FEATURE_NAME: &str = "process";
|
||||
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Deserialize)]
|
||||
|
@ -153,6 +157,7 @@ deno_core::extension!(
|
|||
deprecated::op_run_status,
|
||||
deprecated::op_kill,
|
||||
],
|
||||
esm = ["40_process.js"],
|
||||
options = { get_npm_process_state: Option<NpmProcessStateProviderRc> },
|
||||
state = |state, options| {
|
||||
state.put::<NpmProcessStateProviderRc>(options.get_npm_process_state.unwrap_or(deno_fs::sync::MaybeArc::new(EmptyNpmProcessStateProvider)));
|
||||
|
@ -462,13 +467,10 @@ fn create_command(
|
|||
fds_to_dup.push((ipc_fd2, ipc));
|
||||
fds_to_close.push(ipc_fd2);
|
||||
/* One end returned to parent process (this) */
|
||||
let pipe_rid =
|
||||
state
|
||||
.resource_table
|
||||
.add(deno_node::IpcJsonStreamResource::new(
|
||||
ipc_fd1 as _,
|
||||
deno_node::IpcRefTracker::new(state.external_ops_tracker.clone()),
|
||||
)?);
|
||||
let pipe_rid = state.resource_table.add(IpcJsonStreamResource::new(
|
||||
ipc_fd1 as _,
|
||||
IpcRefTracker::new(state.external_ops_tracker.clone()),
|
||||
)?);
|
||||
/* The other end passed to child process via NODE_CHANNEL_FD */
|
||||
command.env("NODE_CHANNEL_FD", format!("{}", ipc));
|
||||
ipc_rid = Some(pipe_rid);
|
||||
|
@ -532,12 +534,11 @@ fn create_command(
|
|||
let (hd1, hd2) = deno_io::bi_pipe_pair_raw()?;
|
||||
|
||||
/* One end returned to parent process (this) */
|
||||
let pipe_rid = Some(state.resource_table.add(
|
||||
deno_node::IpcJsonStreamResource::new(
|
||||
let pipe_rid =
|
||||
Some(state.resource_table.add(IpcJsonStreamResource::new(
|
||||
hd1 as i64,
|
||||
deno_node::IpcRefTracker::new(state.external_ops_tracker.clone()),
|
||||
)?,
|
||||
));
|
||||
IpcRefTracker::new(state.external_ops_tracker.clone()),
|
||||
)?));
|
||||
|
||||
/* The other end passed to child process via NODE_CHANNEL_FD */
|
||||
command.env("NODE_CHANNEL_FD", format!("{}", hd2 as i64));
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
[package]
|
||||
name = "deno_telemetry"
|
||||
version = "0.7.0"
|
||||
version = "0.8.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
[package]
|
||||
name = "deno_tls"
|
||||
version = "0.172.0"
|
||||
version = "0.173.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
[package]
|
||||
name = "deno_url"
|
||||
version = "0.185.0"
|
||||
version = "0.186.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
[package]
|
||||
name = "deno_web"
|
||||
version = "0.216.0"
|
||||
version = "0.217.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
[package]
|
||||
name = "deno_webgpu"
|
||||
version = "0.152.0"
|
||||
version = "0.153.0"
|
||||
authors = ["the Deno authors"]
|
||||
edition.workspace = true
|
||||
license = "MIT"
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
[package]
|
||||
name = "deno_webidl"
|
||||
version = "0.185.0"
|
||||
version = "0.186.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
[package]
|
||||
name = "deno_websocket"
|
||||
version = "0.190.0"
|
||||
version = "0.191.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
[package]
|
||||
name = "deno_webstorage"
|
||||
version = "0.180.0"
|
||||
version = "0.181.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
[package]
|
||||
name = "deno_resolver"
|
||||
version = "0.16.0"
|
||||
version = "0.17.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
[package]
|
||||
name = "node_resolver"
|
||||
version = "0.23.0"
|
||||
version = "0.24.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
[package]
|
||||
name = "deno_npm_cache"
|
||||
version = "0.4.0"
|
||||
version = "0.5.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
[package]
|
||||
name = "deno_runtime"
|
||||
version = "0.193.0"
|
||||
version = "0.194.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
@ -60,6 +60,7 @@ deno_kv.workspace = true
|
|||
deno_tls.workspace = true
|
||||
deno_url.workspace = true
|
||||
deno_web.workspace = true
|
||||
deno_process.workspace = true
|
||||
deno_webgpu.workspace = true
|
||||
deno_webidl.workspace = true
|
||||
deno_websocket.workspace = true
|
||||
|
@ -93,6 +94,7 @@ deno_node.workspace = true
|
|||
deno_os.workspace = true
|
||||
deno_path_util.workspace = true
|
||||
deno_permissions.workspace = true
|
||||
deno_process.workspace = true
|
||||
deno_resolver.workspace = true
|
||||
deno_telemetry.workspace = true
|
||||
deno_terminal.workspace = true
|
||||
|
|
|
@ -23,7 +23,7 @@ import * as io from "ext:deno_io/12_io.js";
|
|||
import * as fs from "ext:deno_fs/30_fs.js";
|
||||
import * as os from "ext:deno_os/30_os.js";
|
||||
import * as fsEvents from "ext:runtime/40_fs_events.js";
|
||||
import * as process from "ext:runtime/40_process.js";
|
||||
import * as process from "ext:deno_process/40_process.js";
|
||||
import * as signals from "ext:deno_os/40_signals.js";
|
||||
import * as tty from "ext:runtime/40_tty.js";
|
||||
import * as kv from "ext:deno_kv/01_db.ts";
|
||||
|
|
|
@ -18,6 +18,7 @@ pub use deno_net;
|
|||
pub use deno_node;
|
||||
pub use deno_os;
|
||||
pub use deno_permissions;
|
||||
pub use deno_process;
|
||||
pub use deno_telemetry;
|
||||
pub use deno_terminal::colors;
|
||||
pub use deno_tls;
|
||||
|
@ -115,7 +116,7 @@ pub static UNSTABLE_GRANULAR_FLAGS: &[UnstableGranularFlag] = &[
|
|||
},
|
||||
// TODO(bartlomieju): consider removing it
|
||||
UnstableGranularFlag {
|
||||
name: ops::process::UNSTABLE_FEATURE_NAME,
|
||||
name: deno_process::UNSTABLE_FEATURE_NAME,
|
||||
help_text: "Enable unstable process APIs",
|
||||
show_in_help: false,
|
||||
id: 10,
|
||||
|
|
|
@ -4,7 +4,6 @@ pub mod bootstrap;
|
|||
pub mod fs_events;
|
||||
pub mod http;
|
||||
pub mod permissions;
|
||||
pub mod process;
|
||||
pub mod runtime;
|
||||
pub mod tty;
|
||||
pub mod web_worker;
|
||||
|
|
|
@ -50,14 +50,13 @@ impl TtyModeStore {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
use deno_process::JsNixError;
|
||||
#[cfg(windows)]
|
||||
use winapi::shared::minwindef::DWORD;
|
||||
#[cfg(windows)]
|
||||
use winapi::um::wincon;
|
||||
|
||||
#[cfg(unix)]
|
||||
use crate::ops::process::JsNixError;
|
||||
|
||||
deno_core::extension!(
|
||||
deno_tty,
|
||||
ops = [op_set_raw, op_console_size, op_read_line_prompt],
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
[package]
|
||||
name = "deno_permissions"
|
||||
version = "0.44.0"
|
||||
version = "0.45.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
|
|
@ -43,7 +43,6 @@ extension!(runtime,
|
|||
"10_permissions.js",
|
||||
"11_workers.js",
|
||||
"40_fs_events.js",
|
||||
"40_process.js",
|
||||
"40_tty.js",
|
||||
"41_prompt.js",
|
||||
"90_deno_ns.js",
|
||||
|
|
|
@ -311,6 +311,7 @@ pub fn create_runtime_snapshot(
|
|||
deno_io::deno_io::init_ops_and_esm(Default::default()),
|
||||
deno_fs::deno_fs::init_ops_and_esm::<Permissions>(fs.clone()),
|
||||
deno_os::deno_os::init_ops_and_esm(Default::default()),
|
||||
deno_process::deno_process::init_ops_and_esm(Default::default()),
|
||||
deno_node::deno_node::init_ops_and_esm::<
|
||||
Permissions,
|
||||
DenoInNpmPackageChecker,
|
||||
|
@ -325,7 +326,6 @@ pub fn create_runtime_snapshot(
|
|||
),
|
||||
ops::fs_events::deno_fs_events::init_ops(),
|
||||
ops::permissions::deno_permissions::init_ops(),
|
||||
ops::process::deno_process::init_ops(None),
|
||||
ops::tty::deno_tty::init_ops(),
|
||||
ops::http::deno_http_runtime::init_ops(),
|
||||
ops::bootstrap::deno_bootstrap::init_ops(Some(snapshot_options)),
|
||||
|
|
|
@ -44,6 +44,7 @@ use deno_kv::dynamic::MultiBackendDbHandler;
|
|||
use deno_node::ExtNodeSys;
|
||||
use deno_node::NodeExtInitServices;
|
||||
use deno_permissions::PermissionsContainer;
|
||||
use deno_process::NpmProcessStateProviderRc;
|
||||
use deno_terminal::colors;
|
||||
use deno_tls::RootCertStoreProvider;
|
||||
use deno_tls::TlsKeys;
|
||||
|
@ -59,7 +60,6 @@ use node_resolver::NpmPackageFolderResolver;
|
|||
|
||||
use crate::inspector_server::InspectorServer;
|
||||
use crate::ops;
|
||||
use crate::ops::process::NpmProcessStateProviderRc;
|
||||
use crate::shared::maybe_transpile_source;
|
||||
use crate::shared::runtime;
|
||||
use crate::tokio_util::create_and_run_current_thread;
|
||||
|
@ -548,6 +548,9 @@ impl WebWorker {
|
|||
services.fs.clone(),
|
||||
),
|
||||
deno_os::deno_os_worker::init_ops_and_esm(),
|
||||
deno_process::deno_process::init_ops_and_esm(
|
||||
services.npm_process_state_provider,
|
||||
),
|
||||
deno_node::deno_node::init_ops_and_esm::<
|
||||
PermissionsContainer,
|
||||
TInNpmPackageChecker,
|
||||
|
@ -562,9 +565,6 @@ impl WebWorker {
|
|||
),
|
||||
ops::fs_events::deno_fs_events::init_ops_and_esm(),
|
||||
ops::permissions::deno_permissions::init_ops_and_esm(),
|
||||
ops::process::deno_process::init_ops_and_esm(
|
||||
services.npm_process_state_provider,
|
||||
),
|
||||
ops::tty::deno_tty::init_ops_and_esm(),
|
||||
ops::http::deno_http_runtime::init_ops_and_esm(),
|
||||
ops::bootstrap::deno_bootstrap::init_ops_and_esm(
|
||||
|
|
|
@ -40,6 +40,7 @@ use deno_node::ExtNodeSys;
|
|||
use deno_node::NodeExtInitServices;
|
||||
use deno_os::ExitCode;
|
||||
use deno_permissions::PermissionsContainer;
|
||||
use deno_process::NpmProcessStateProviderRc;
|
||||
use deno_tls::RootCertStoreProvider;
|
||||
use deno_tls::TlsKeys;
|
||||
use deno_web::BlobStore;
|
||||
|
@ -51,7 +52,6 @@ use crate::code_cache::CodeCache;
|
|||
use crate::code_cache::CodeCacheType;
|
||||
use crate::inspector_server::InspectorServer;
|
||||
use crate::ops;
|
||||
use crate::ops::process::NpmProcessStateProviderRc;
|
||||
use crate::shared::maybe_transpile_source;
|
||||
use crate::shared::runtime;
|
||||
use crate::BootstrapOptions;
|
||||
|
@ -428,6 +428,9 @@ impl MainWorker {
|
|||
services.fs.clone(),
|
||||
),
|
||||
deno_os::deno_os::init_ops_and_esm(exit_code.clone()),
|
||||
deno_process::deno_process::init_ops_and_esm(
|
||||
services.npm_process_state_provider,
|
||||
),
|
||||
deno_node::deno_node::init_ops_and_esm::<
|
||||
PermissionsContainer,
|
||||
TInNpmPackageChecker,
|
||||
|
@ -442,9 +445,6 @@ impl MainWorker {
|
|||
),
|
||||
ops::fs_events::deno_fs_events::init_ops_and_esm(),
|
||||
ops::permissions::deno_permissions::init_ops_and_esm(),
|
||||
ops::process::deno_process::init_ops_and_esm(
|
||||
services.npm_process_state_provider,
|
||||
),
|
||||
ops::tty::deno_tty::init_ops_and_esm(),
|
||||
ops::http::deno_http_runtime::init_ops_and_esm(),
|
||||
ops::bootstrap::deno_bootstrap::init_ops_and_esm(
|
||||
|
|
|
@ -17296,3 +17296,119 @@ fn wildcard_augment() {
|
|||
let diagnostics = client.did_open_file(&source);
|
||||
assert_eq!(diagnostics.all().len(), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn compiler_options_types() {
|
||||
let context = TestContextBuilder::for_npm().use_temp_cwd().build();
|
||||
let mut client = context.new_lsp_command().build();
|
||||
let temp = context.temp_dir();
|
||||
let temp_dir = temp.path();
|
||||
let source = source_file(
|
||||
temp_dir.join("index.ts"),
|
||||
r#"
|
||||
const foo = [1];
|
||||
foo.augmented();
|
||||
"#,
|
||||
);
|
||||
|
||||
let deno_json = json!({
|
||||
"imports": {
|
||||
"@denotest/augments-global": "npm:@denotest/augments-global@1"
|
||||
},
|
||||
"compilerOptions": { "types": ["@denotest/augments-global"] },
|
||||
});
|
||||
|
||||
temp.write("deno.json", deno_json.to_string());
|
||||
|
||||
client.initialize_default();
|
||||
|
||||
for node_modules_dir in ["none", "auto", "manual"] {
|
||||
let mut deno_json = deno_json.clone();
|
||||
deno_json["nodeModulesDir"] = json!(node_modules_dir);
|
||||
temp.write("deno.json", deno_json.to_string());
|
||||
context.run_deno("install");
|
||||
client.did_change_watched_files(json!({
|
||||
"changes": [{
|
||||
"uri": temp.url().join("deno.json").unwrap(),
|
||||
"type": 2,
|
||||
}],
|
||||
}));
|
||||
|
||||
let diagnostics = client.did_open_file(&source);
|
||||
eprintln!("{:#?}", diagnostics.all());
|
||||
assert_eq!(diagnostics.all().len(), 0);
|
||||
client.did_close_file(&source);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn type_reference_import_meta() {
|
||||
let context = TestContextBuilder::for_npm().use_temp_cwd().build();
|
||||
let mut client = context.new_lsp_command().build();
|
||||
let temp = context.temp_dir();
|
||||
let temp_dir = temp.path();
|
||||
let source = source_file(
|
||||
temp_dir.join("index.ts"),
|
||||
r#"
|
||||
const test = import.meta.env.TEST;
|
||||
const bar = import.meta.bar;
|
||||
console.log(test, bar);
|
||||
"#,
|
||||
);
|
||||
/*
|
||||
tests type reference w/ bare specifier, type reference in an npm package,
|
||||
and augmentation of `ImportMeta` (this combination modeled after the vanilla vite template,
|
||||
which uses `vite/client`)
|
||||
|
||||
@denotest/augments-global/import-meta:
|
||||
```dts
|
||||
/// <reference types="./real-import-meta.d.ts" />
|
||||
|
||||
export type Foo = number;
|
||||
```
|
||||
|
||||
real-import-meta.d.ts:
|
||||
```dts
|
||||
interface ImportMetaEnv {
|
||||
TEST: string;
|
||||
}
|
||||
|
||||
interface ImportMeta {
|
||||
env: ImportMetaEnv;
|
||||
bar: number;
|
||||
}
|
||||
```
|
||||
*/
|
||||
temp.write(
|
||||
"types.d.ts",
|
||||
r#"
|
||||
/// <reference types="@denotest/augments-global/import-meta" />
|
||||
"#,
|
||||
);
|
||||
|
||||
let deno_json = json!({
|
||||
"imports": {
|
||||
"@denotest/augments-global": "npm:@denotest/augments-global@1"
|
||||
}
|
||||
});
|
||||
temp.write("deno.json", deno_json.to_string());
|
||||
|
||||
client.initialize_default();
|
||||
|
||||
for node_modules_dir in ["none", "auto", "manual"] {
|
||||
let mut deno_json = deno_json.clone();
|
||||
deno_json["nodeModulesDir"] = json!(node_modules_dir);
|
||||
temp.write("deno.json", deno_json.to_string());
|
||||
context.run_deno("install");
|
||||
client.did_change_watched_files(json!({
|
||||
"changes": [{
|
||||
"uri": temp.url().join("deno.json").unwrap(),
|
||||
"type": 2,
|
||||
}],
|
||||
}));
|
||||
|
||||
let diagnostics = client.did_open_file(&source);
|
||||
assert_eq!(diagnostics.all().len(), 0);
|
||||
client.did_close_file(&source);
|
||||
}
|
||||
}
|
||||
|
|
3
tests/registry/npm/@denotest/augments-global/1.0.0/import-meta.d.ts
vendored
Normal file
3
tests/registry/npm/@denotest/augments-global/1.0.0/import-meta.d.ts
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
/// <reference types="./real-import-meta.d.ts" />
|
||||
|
||||
export type Foo = number;
|
1
tests/registry/npm/@denotest/augments-global/1.0.0/index.d.ts
vendored
Normal file
1
tests/registry/npm/@denotest/augments-global/1.0.0/index.d.ts
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
import "./other.d.ts";
|
6
tests/registry/npm/@denotest/augments-global/1.0.0/other.d.ts
vendored
Normal file
6
tests/registry/npm/@denotest/augments-global/1.0.0/other.d.ts
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
export {}
|
||||
declare global {
|
||||
interface Array<T> {
|
||||
augmented(): void
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"name": "@denotest/augments-global",
|
||||
"version": "1.0.0",
|
||||
"types": "./index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./index.d.ts"
|
||||
},
|
||||
"./import-meta": {
|
||||
"types": "./import-meta.d.ts"
|
||||
}
|
||||
}
|
||||
}
|
8
tests/registry/npm/@denotest/augments-global/1.0.0/real-import-meta.d.ts
vendored
Normal file
8
tests/registry/npm/@denotest/augments-global/1.0.0/real-import-meta.d.ts
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
interface ImportMetaEnv {
|
||||
TEST: string;
|
||||
}
|
||||
|
||||
interface ImportMeta {
|
||||
env: ImportMetaEnv;
|
||||
bar: number;
|
||||
}
|
53
tests/specs/check/compiler_options_types/__test__.jsonc
Normal file
53
tests/specs/check/compiler_options_types/__test__.jsonc
Normal file
|
@ -0,0 +1,53 @@
|
|||
{
|
||||
"tempDir": true,
|
||||
"tests": {
|
||||
"node_modules_dir_none": {
|
||||
"steps": [
|
||||
{
|
||||
"args": "run -A ./set_node_modules_dir.ts none",
|
||||
"output": ""
|
||||
},
|
||||
{
|
||||
"args": "install",
|
||||
"output": "[WILDCARD]"
|
||||
},
|
||||
{
|
||||
"args": "check ./main.ts",
|
||||
"output": "Check [WILDCARD]main.ts\n"
|
||||
}
|
||||
]
|
||||
},
|
||||
"node_modules_dir_auto": {
|
||||
"steps": [
|
||||
{
|
||||
"args": "run -A ./set_node_modules_dir.ts auto",
|
||||
"output": ""
|
||||
},
|
||||
{
|
||||
"args": "install",
|
||||
"output": "[WILDCARD]"
|
||||
},
|
||||
{
|
||||
"args": "check ./main.ts",
|
||||
"output": "Check [WILDCARD]main.ts\n"
|
||||
}
|
||||
]
|
||||
},
|
||||
"node_modules_dir_manual": {
|
||||
"steps": [
|
||||
{
|
||||
"args": "run -A ./set_node_modules_dir.ts auto",
|
||||
"output": ""
|
||||
},
|
||||
{
|
||||
"args": "install",
|
||||
"output": "[WILDCARD]"
|
||||
},
|
||||
{
|
||||
"args": "check ./main.ts",
|
||||
"output": "Check [WILDCARD]main.ts\n"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
6
tests/specs/check/compiler_options_types/deno.json
Normal file
6
tests/specs/check/compiler_options_types/deno.json
Normal file
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"imports": {
|
||||
"@denotest/augments-global": "npm:@denotest/augments-global@1"
|
||||
},
|
||||
"compilerOptions": { "types": ["@denotest/augments-global"] }
|
||||
}
|
2
tests/specs/check/compiler_options_types/main.ts
Normal file
2
tests/specs/check/compiler_options_types/main.ts
Normal file
|
@ -0,0 +1,2 @@
|
|||
const foo = [1];
|
||||
foo.augmented();
|
|
@ -0,0 +1,8 @@
|
|||
if (Deno.args.length !== 1) {
|
||||
console.error("Usage: set_node_modules_dir.ts <setting>");
|
||||
Deno.exit(1);
|
||||
}
|
||||
const setting = Deno.args[0].trim();
|
||||
const denoJson = JSON.parse(Deno.readTextFileSync("./deno.json"));
|
||||
denoJson["nodeModulesDir"] = setting;
|
||||
Deno.writeTextFileSync("./deno.json", JSON.stringify(denoJson, null, 2));
|
53
tests/specs/check/import_meta_no_errors/__test__.jsonc
Normal file
53
tests/specs/check/import_meta_no_errors/__test__.jsonc
Normal file
|
@ -0,0 +1,53 @@
|
|||
{
|
||||
"tempDir": true,
|
||||
"tests": {
|
||||
"node_modules_dir_none": {
|
||||
"steps": [
|
||||
{
|
||||
"args": "run -A ./set_node_modules_dir.ts none",
|
||||
"output": ""
|
||||
},
|
||||
{
|
||||
"args": "install",
|
||||
"output": "[WILDCARD]"
|
||||
},
|
||||
{
|
||||
"args": "check --all ./main.ts",
|
||||
"output": "Check [WILDCARD]main.ts\n"
|
||||
}
|
||||
]
|
||||
},
|
||||
"node_modules_dir_auto": {
|
||||
"steps": [
|
||||
{
|
||||
"args": "run -A ./set_node_modules_dir.ts auto",
|
||||
"output": ""
|
||||
},
|
||||
{
|
||||
"args": "install",
|
||||
"output": "[WILDCARD]"
|
||||
},
|
||||
{
|
||||
"args": "check --all ./main.ts",
|
||||
"output": "Check [WILDCARD]main.ts\n"
|
||||
}
|
||||
]
|
||||
},
|
||||
"node_modules_dir_manual": {
|
||||
"steps": [
|
||||
{
|
||||
"args": "run -A ./set_node_modules_dir.ts auto",
|
||||
"output": ""
|
||||
},
|
||||
{
|
||||
"args": "install",
|
||||
"output": "[WILDCARD]"
|
||||
},
|
||||
{
|
||||
"args": "check --all ./main.ts",
|
||||
"output": "Check [WILDCARD]main.ts\n"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
5
tests/specs/check/import_meta_no_errors/deno.json
Normal file
5
tests/specs/check/import_meta_no_errors/deno.json
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"imports": {
|
||||
"@types/node": "npm:@types/node@*"
|
||||
}
|
||||
}
|
3
tests/specs/check/import_meta_no_errors/main.ts
Normal file
3
tests/specs/check/import_meta_no_errors/main.ts
Normal file
|
@ -0,0 +1,3 @@
|
|||
/// <reference types="@types/node" />
|
||||
|
||||
const _foo = import.meta.dirname;
|
|
@ -0,0 +1,8 @@
|
|||
if (Deno.args.length !== 1) {
|
||||
console.error("Usage: set_node_modules_dir.ts <setting>");
|
||||
Deno.exit(1);
|
||||
}
|
||||
const setting = Deno.args[0].trim();
|
||||
const denoJson = JSON.parse(Deno.readTextFileSync("./deno.json"));
|
||||
denoJson["nodeModulesDir"] = setting;
|
||||
Deno.writeTextFileSync("./deno.json", JSON.stringify(denoJson, null, 2));
|
53
tests/specs/check/type_reference_import_meta/__test__.jsonc
Normal file
53
tests/specs/check/type_reference_import_meta/__test__.jsonc
Normal file
|
@ -0,0 +1,53 @@
|
|||
{
|
||||
"tempDir": true,
|
||||
"tests": {
|
||||
"node_modules_dir_none": {
|
||||
"steps": [
|
||||
{
|
||||
"args": "run -A ./set_node_modules_dir.ts none",
|
||||
"output": ""
|
||||
},
|
||||
{
|
||||
"args": "install",
|
||||
"output": "[WILDCARD]"
|
||||
},
|
||||
{
|
||||
"args": "check ./main.ts",
|
||||
"output": "Check [WILDCARD]main.ts\n"
|
||||
}
|
||||
]
|
||||
},
|
||||
"node_modules_dir_auto": {
|
||||
"steps": [
|
||||
{
|
||||
"args": "run -A ./set_node_modules_dir.ts auto",
|
||||
"output": ""
|
||||
},
|
||||
{
|
||||
"args": "install",
|
||||
"output": "[WILDCARD]"
|
||||
},
|
||||
{
|
||||
"args": "check ./main.ts",
|
||||
"output": "Check [WILDCARD]main.ts\n"
|
||||
}
|
||||
]
|
||||
},
|
||||
"node_modules_dir_manual": {
|
||||
"steps": [
|
||||
{
|
||||
"args": "run -A ./set_node_modules_dir.ts auto",
|
||||
"output": ""
|
||||
},
|
||||
{
|
||||
"args": "install",
|
||||
"output": "[WILDCARD]"
|
||||
},
|
||||
{
|
||||
"args": "check ./main.ts",
|
||||
"output": "Check [WILDCARD]main.ts\n"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
6
tests/specs/check/type_reference_import_meta/deno.json
Normal file
6
tests/specs/check/type_reference_import_meta/deno.json
Normal file
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"imports": {
|
||||
"@denotest/augments-global": "npm:@denotest/augments-global@1"
|
||||
},
|
||||
"compilerOptions": { "types": ["./types.d.ts"] }
|
||||
}
|
3
tests/specs/check/type_reference_import_meta/main.ts
Normal file
3
tests/specs/check/type_reference_import_meta/main.ts
Normal file
|
@ -0,0 +1,3 @@
|
|||
const test = import.meta.env.TEST;
|
||||
const bar = import.meta.bar;
|
||||
console.log(test, bar);
|
|
@ -0,0 +1,8 @@
|
|||
if (Deno.args.length !== 1) {
|
||||
console.error("Usage: set_node_modules_dir.ts <setting>");
|
||||
Deno.exit(1);
|
||||
}
|
||||
const setting = Deno.args[0].trim();
|
||||
const denoJson = JSON.parse(Deno.readTextFileSync("./deno.json"));
|
||||
denoJson["nodeModulesDir"] = setting;
|
||||
Deno.writeTextFileSync("./deno.json", JSON.stringify(denoJson, null, 2));
|
1
tests/specs/check/type_reference_import_meta/types.d.ts
vendored
Normal file
1
tests/specs/check/type_reference_import_meta/types.d.ts
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
/// <reference types="@denotest/augments-global/import-meta" />
|
|
@ -5,7 +5,7 @@
|
|||
"@denotest/subtract": "jsr:@denotest/subtract@^0.2.0",
|
||||
"@denotest/with-subpath": "jsr:@denotest/multiple-exports@0.5.0/data-json",
|
||||
"@denotest/breaking-change-between-versions": "npm:@denotest/breaking-change-between-versions@1.0.0",
|
||||
"@denotest/bin": "npm:@denotest/bin@^1.0.0",
|
||||
"@denotest/bin": "npm:@denotest/bin@1.0.0",
|
||||
"@denotest/has-patch-versions": "npm:@denotest/has-patch-versions@^0.1.0"
|
||||
},
|
||||
"scopes": {
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
"@denotest/add": "jsr:@denotest/add@^1.0.0",
|
||||
"@denotest/add/": "jsr:/@denotest/add@^1.0.0/",
|
||||
"@denotest/subtract": "jsr:@denotest/subtract@^1.0.0",
|
||||
"@denotest/with-subpath": "jsr:@denotest/multiple-exports@^1.0.0/data-json",
|
||||
"@denotest/breaking-change-between-versions": "npm:@denotest/breaking-change-between-versions@^2.0.0",
|
||||
"@denotest/bin": "npm:@denotest/bin@^1.0.0",
|
||||
"@denotest/with-subpath": "jsr:@denotest/multiple-exports@1.0.0/data-json",
|
||||
"@denotest/breaking-change-between-versions": "npm:@denotest/breaking-change-between-versions@2.0.0",
|
||||
"@denotest/bin": "npm:@denotest/bin@1.0.0",
|
||||
"@denotest/has-patch-versions": "npm:@denotest/has-patch-versions@^0.2.0"
|
||||
},
|
||||
"scopes": {
|
||||
|
@ -13,7 +13,7 @@
|
|||
"@denotest/add": "jsr:@denotest/add@^1.0.0",
|
||||
"@denotest/add/": "jsr:/@denotest/add@^1.0.0/",
|
||||
"@denotest/subtract": "jsr:@denotest/subtract@^1.0.0",
|
||||
"@denotest/with-subpath": "jsr:@denotest/multiple-exports@^1.0.0/data-json"
|
||||
"@denotest/with-subpath": "jsr:@denotest/multiple-exports@1.0.0/data-json"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
"version": "4",
|
||||
"specifiers": {
|
||||
"jsr:@denotest/add@1": "1.0.0",
|
||||
"jsr:@denotest/multiple-exports@1": "1.0.0",
|
||||
"jsr:@denotest/multiple-exports@1.0.0": "1.0.0",
|
||||
"jsr:@denotest/subtract@1": "1.0.0",
|
||||
"npm:@denotest/bin@1": "1.0.0",
|
||||
"npm:@denotest/breaking-change-between-versions@2": "2.0.0",
|
||||
"npm:@denotest/bin@1.0.0": "1.0.0",
|
||||
"npm:@denotest/breaking-change-between-versions@2.0.0": "2.0.0",
|
||||
"npm:@denotest/has-patch-versions@0.2": "0.2.0"
|
||||
},
|
||||
"jsr": {
|
||||
|
@ -33,10 +33,10 @@
|
|||
"workspace": {
|
||||
"dependencies": [
|
||||
"jsr:@denotest/add@1",
|
||||
"jsr:@denotest/multiple-exports@1",
|
||||
"jsr:@denotest/multiple-exports@1.0.0",
|
||||
"jsr:@denotest/subtract@1",
|
||||
"npm:@denotest/bin@1",
|
||||
"npm:@denotest/breaking-change-between-versions@2",
|
||||
"npm:@denotest/bin@1.0.0",
|
||||
"npm:@denotest/breaking-change-between-versions@2.0.0",
|
||||
"npm:@denotest/has-patch-versions@0.2"
|
||||
]
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"imports": {
|
||||
"@denotest/add": "jsr:@denotest/add@^1.0.0",
|
||||
"@denotest/subtract": "jsr:@denotest/subtract@^1.0.0",
|
||||
"@denotest/breaking-change-between-versions": "npm:@denotest/breaking-change-between-versions@^2.0.0",
|
||||
"@denotest/breaking-change-between-versions": "npm:@denotest/breaking-change-between-versions@2.0.0",
|
||||
"@denotest/has-patch-versions": "npm:@denotest/has-patch-versions@^0.2.0"
|
||||
}
|
||||
}
|
||||
|
|
13
tests/specs/update/latest_not_pre_release/__test__.jsonc
Normal file
13
tests/specs/update/latest_not_pre_release/__test__.jsonc
Normal file
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"tempDir": true,
|
||||
"steps": [
|
||||
{
|
||||
"args": "install",
|
||||
"output": "[WILDCARD]"
|
||||
},
|
||||
{
|
||||
"args": "outdated",
|
||||
"output": ""
|
||||
}
|
||||
]
|
||||
}
|
5
tests/specs/update/latest_not_pre_release/package.json
Normal file
5
tests/specs/update/latest_not_pre_release/package.json
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"dependencies": {
|
||||
"@denotest/has-pre-release": "1.0.0"
|
||||
}
|
||||
}
|
|
@ -3,6 +3,6 @@
|
|||
"version": "0.1.0",
|
||||
"dependencies": {
|
||||
"@denotest/has-patch-versions": "0.1.0",
|
||||
"aliased": "npm:@denotest/bin@^1.0.0"
|
||||
"aliased": "npm:@denotest/bin@1.0.0"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
"imports": {
|
||||
"@denotest/add": "jsr:@denotest/add@^1.0.0",
|
||||
"@denotest/add/": "jsr:/@denotest/add@^1.0.0/",
|
||||
"@denotest/with-subpath": "jsr:@denotest/multiple-exports@^1.0.0/data-json",
|
||||
"@denotest/breaking-change-between-versions": "npm:@denotest/breaking-change-between-versions@^2.0.0"
|
||||
"@denotest/with-subpath": "jsr:@denotest/multiple-exports@1.0.0/data-json",
|
||||
"@denotest/breaking-change-between-versions": "npm:@denotest/breaking-change-between-versions@2.0.0"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"name": "@denotest/member-b",
|
||||
"version": "0.1.0",
|
||||
"dependencies": {
|
||||
"@denotest/has-patch-versions": "^0.2.0",
|
||||
"aliased": "npm:@denotest/bin@^1.0.0"
|
||||
"@denotest/has-patch-versions": "0.2.0",
|
||||
"aliased": "npm:@denotest/bin@1.0.0"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"version": "4",
|
||||
"specifiers": {
|
||||
"npm:@denotest/bin@1": "1.0.0",
|
||||
"npm:@denotest/breaking-change-between-versions@2": "2.0.0",
|
||||
"npm:@denotest/breaking-change-between-versions@2.0.0": "2.0.0",
|
||||
"npm:@denotest/has-patch-versions@0.2": "0.2.0"
|
||||
},
|
||||
"npm": {
|
||||
|
@ -20,7 +20,7 @@
|
|||
"packageJson": {
|
||||
"dependencies": [
|
||||
"npm:@denotest/bin@1",
|
||||
"npm:@denotest/breaking-change-between-versions@2",
|
||||
"npm:@denotest/breaking-change-between-versions@2.0.0",
|
||||
"npm:@denotest/has-patch-versions@0.2"
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"dependencies": {
|
||||
"@denotest/has-patch-versions": "^0.2.0",
|
||||
"@denotest/breaking-change-between-versions": "^2.0.0"
|
||||
"@denotest/breaking-change-between-versions": "2.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"aliased": "npm:@denotest/bin@^1.0.0"
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue