mirror of
https://github.com/denoland/deno.git
synced 2024-12-01 16:51:13 -05:00
Merge branch 'main' into open-flag-on-serve
This commit is contained in:
commit
8e63dea5ae
81 changed files with 1410 additions and 244 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.
|
// Bump this number when you want to purge the cache.
|
||||||
// Note: the tools/release/01_bump_crate_versions.ts script will update this version
|
// 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.
|
// automatically via regex, so ensure that this line maintains this format.
|
||||||
const cacheVersion = 24;
|
const cacheVersion = 25;
|
||||||
|
|
||||||
const ubuntuX86Runner = "ubuntu-24.04";
|
const ubuntuX86Runner = "ubuntu-24.04";
|
||||||
const ubuntuX86XlRunner = "ubuntu-24.04-xl";
|
const ubuntuX86XlRunner = "ubuntu-24.04-xl";
|
||||||
|
|
8
.github/workflows/ci.yml
vendored
8
.github/workflows/ci.yml
vendored
|
@ -361,8 +361,8 @@ jobs:
|
||||||
path: |-
|
path: |-
|
||||||
~/.cargo/registry/index
|
~/.cargo/registry/index
|
||||||
~/.cargo/registry/cache
|
~/.cargo/registry/cache
|
||||||
key: '24-cargo-home-${{ matrix.os }}-${{ matrix.arch }}-${{ hashFiles(''Cargo.lock'') }}'
|
key: '25-cargo-home-${{ matrix.os }}-${{ matrix.arch }}-${{ hashFiles(''Cargo.lock'') }}'
|
||||||
restore-keys: '24-cargo-home-${{ matrix.os }}-${{ matrix.arch }}'
|
restore-keys: '25-cargo-home-${{ matrix.os }}-${{ matrix.arch }}'
|
||||||
if: '!(matrix.skip)'
|
if: '!(matrix.skip)'
|
||||||
- name: Restore cache build output (PR)
|
- name: Restore cache build output (PR)
|
||||||
uses: actions/cache/restore@v4
|
uses: actions/cache/restore@v4
|
||||||
|
@ -375,7 +375,7 @@ jobs:
|
||||||
!./target/*/*.zip
|
!./target/*/*.zip
|
||||||
!./target/*/*.tar.gz
|
!./target/*/*.tar.gz
|
||||||
key: never_saved
|
key: never_saved
|
||||||
restore-keys: '24-cargo-target-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.profile }}-${{ matrix.job }}-'
|
restore-keys: '25-cargo-target-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.profile }}-${{ matrix.job }}-'
|
||||||
- name: Apply and update mtime cache
|
- name: Apply and update mtime cache
|
||||||
if: '!(matrix.skip) && (!startsWith(github.ref, ''refs/tags/''))'
|
if: '!(matrix.skip) && (!startsWith(github.ref, ''refs/tags/''))'
|
||||||
uses: ./.github/mtime_cache
|
uses: ./.github/mtime_cache
|
||||||
|
@ -685,7 +685,7 @@ jobs:
|
||||||
!./target/*/*.zip
|
!./target/*/*.zip
|
||||||
!./target/*/*.sha256sum
|
!./target/*/*.sha256sum
|
||||||
!./target/*/*.tar.gz
|
!./target/*/*.tar.gz
|
||||||
key: '24-cargo-target-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.profile }}-${{ matrix.job }}-${{ github.sha }}'
|
key: '25-cargo-target-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.profile }}-${{ matrix.job }}-${{ github.sha }}'
|
||||||
publish-canary:
|
publish-canary:
|
||||||
name: publish canary
|
name: publish canary
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
|
|
62
Cargo.lock
generated
62
Cargo.lock
generated
|
@ -1154,7 +1154,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno"
|
name = "deno"
|
||||||
version = "2.0.5"
|
version = "2.0.6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anstream",
|
"anstream",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
|
@ -1323,7 +1323,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_bench_util"
|
name = "deno_bench_util"
|
||||||
version = "0.170.0"
|
version = "0.171.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bencher",
|
"bencher",
|
||||||
"deno_core",
|
"deno_core",
|
||||||
|
@ -1332,7 +1332,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_broadcast_channel"
|
name = "deno_broadcast_channel"
|
||||||
version = "0.170.0"
|
version = "0.171.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"deno_core",
|
"deno_core",
|
||||||
|
@ -1343,7 +1343,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_cache"
|
name = "deno_cache"
|
||||||
version = "0.108.0"
|
version = "0.109.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"deno_core",
|
"deno_core",
|
||||||
|
@ -1376,7 +1376,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_canvas"
|
name = "deno_canvas"
|
||||||
version = "0.45.0"
|
version = "0.46.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"deno_core",
|
"deno_core",
|
||||||
"deno_webgpu",
|
"deno_webgpu",
|
||||||
|
@ -1411,7 +1411,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_console"
|
name = "deno_console"
|
||||||
version = "0.176.0"
|
version = "0.177.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"deno_core",
|
"deno_core",
|
||||||
]
|
]
|
||||||
|
@ -1456,7 +1456,7 @@ checksum = "a13951ea98c0a4c372f162d669193b4c9d991512de9f2381dd161027f34b26b1"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_cron"
|
name = "deno_cron"
|
||||||
version = "0.56.0"
|
version = "0.57.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
|
@ -1469,7 +1469,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_crypto"
|
name = "deno_crypto"
|
||||||
version = "0.190.0"
|
version = "0.191.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aes",
|
"aes",
|
||||||
"aes-gcm",
|
"aes-gcm",
|
||||||
|
@ -1531,7 +1531,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_fetch"
|
name = "deno_fetch"
|
||||||
version = "0.200.0"
|
version = "0.201.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64 0.21.7",
|
"base64 0.21.7",
|
||||||
"bytes",
|
"bytes",
|
||||||
|
@ -1564,7 +1564,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_ffi"
|
name = "deno_ffi"
|
||||||
version = "0.163.0"
|
version = "0.164.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"deno_core",
|
"deno_core",
|
||||||
"deno_permissions",
|
"deno_permissions",
|
||||||
|
@ -1584,7 +1584,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_fs"
|
name = "deno_fs"
|
||||||
version = "0.86.0"
|
version = "0.87.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"base32",
|
"base32",
|
||||||
|
@ -1635,7 +1635,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_http"
|
name = "deno_http"
|
||||||
version = "0.174.0"
|
version = "0.175.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-compression",
|
"async-compression",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
|
@ -1674,7 +1674,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_io"
|
name = "deno_io"
|
||||||
version = "0.86.0"
|
version = "0.87.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"deno_core",
|
"deno_core",
|
||||||
|
@ -1695,7 +1695,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_kv"
|
name = "deno_kv"
|
||||||
version = "0.84.0"
|
version = "0.85.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
|
@ -1767,7 +1767,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_napi"
|
name = "deno_napi"
|
||||||
version = "0.107.0"
|
version = "0.108.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"deno_core",
|
"deno_core",
|
||||||
"deno_permissions",
|
"deno_permissions",
|
||||||
|
@ -1795,7 +1795,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_net"
|
name = "deno_net"
|
||||||
version = "0.168.0"
|
version = "0.169.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"deno_core",
|
"deno_core",
|
||||||
"deno_permissions",
|
"deno_permissions",
|
||||||
|
@ -1812,7 +1812,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_node"
|
name = "deno_node"
|
||||||
version = "0.113.0"
|
version = "0.114.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aead-gcm-stream",
|
"aead-gcm-stream",
|
||||||
"aes",
|
"aes",
|
||||||
|
@ -1961,7 +1961,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_permissions"
|
name = "deno_permissions"
|
||||||
version = "0.36.0"
|
version = "0.37.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"deno_core",
|
"deno_core",
|
||||||
"deno_path_util",
|
"deno_path_util",
|
||||||
|
@ -1979,7 +1979,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_resolver"
|
name = "deno_resolver"
|
||||||
version = "0.8.0"
|
version = "0.9.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"base32",
|
"base32",
|
||||||
|
@ -1995,7 +1995,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_runtime"
|
name = "deno_runtime"
|
||||||
version = "0.185.0"
|
version = "0.186.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"color-print",
|
"color-print",
|
||||||
"deno_ast",
|
"deno_ast",
|
||||||
|
@ -2113,7 +2113,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_tls"
|
name = "deno_tls"
|
||||||
version = "0.163.0"
|
version = "0.164.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"deno_core",
|
"deno_core",
|
||||||
"deno_native_certs",
|
"deno_native_certs",
|
||||||
|
@ -2162,7 +2162,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_url"
|
name = "deno_url"
|
||||||
version = "0.176.0"
|
version = "0.177.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"deno_bench_util",
|
"deno_bench_util",
|
||||||
"deno_console",
|
"deno_console",
|
||||||
|
@ -2174,7 +2174,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_web"
|
name = "deno_web"
|
||||||
version = "0.207.0"
|
version = "0.208.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"base64-simd 0.8.0",
|
"base64-simd 0.8.0",
|
||||||
|
@ -2196,7 +2196,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_webgpu"
|
name = "deno_webgpu"
|
||||||
version = "0.143.0"
|
version = "0.144.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"deno_core",
|
"deno_core",
|
||||||
"raw-window-handle",
|
"raw-window-handle",
|
||||||
|
@ -2209,7 +2209,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_webidl"
|
name = "deno_webidl"
|
||||||
version = "0.176.0"
|
version = "0.177.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"deno_bench_util",
|
"deno_bench_util",
|
||||||
"deno_core",
|
"deno_core",
|
||||||
|
@ -2217,7 +2217,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_websocket"
|
name = "deno_websocket"
|
||||||
version = "0.181.0"
|
version = "0.182.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"deno_core",
|
"deno_core",
|
||||||
|
@ -2239,7 +2239,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_webstorage"
|
name = "deno_webstorage"
|
||||||
version = "0.171.0"
|
version = "0.172.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"deno_core",
|
"deno_core",
|
||||||
"deno_web",
|
"deno_web",
|
||||||
|
@ -4561,7 +4561,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "napi_sym"
|
name = "napi_sym"
|
||||||
version = "0.106.0"
|
version = "0.107.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"quote",
|
"quote",
|
||||||
"serde",
|
"serde",
|
||||||
|
@ -4616,7 +4616,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "node_resolver"
|
name = "node_resolver"
|
||||||
version = "0.15.0"
|
version = "0.16.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
|
@ -8485,9 +8485,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zeromq"
|
name = "zeromq"
|
||||||
version = "0.4.0"
|
version = "0.4.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fb0560d00172817b7f7c2265060783519c475702ae290b154115ca75e976d4d0"
|
checksum = "6a4528179201f6eecf211961a7d3276faa61554c82651ecc66387f68fc3004bd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"asynchronous-codec",
|
"asynchronous-codec",
|
||||||
|
|
58
Cargo.toml
58
Cargo.toml
|
@ -48,16 +48,16 @@ repository = "https://github.com/denoland/deno"
|
||||||
deno_ast = { version = "=0.43.3", features = ["transpiling"] }
|
deno_ast = { version = "=0.43.3", features = ["transpiling"] }
|
||||||
deno_core = { version = "0.318.0" }
|
deno_core = { version = "0.318.0" }
|
||||||
|
|
||||||
deno_bench_util = { version = "0.170.0", path = "./bench_util" }
|
deno_bench_util = { version = "0.171.0", path = "./bench_util" }
|
||||||
deno_lockfile = "=0.23.1"
|
deno_lockfile = "=0.23.1"
|
||||||
deno_media_type = { version = "0.2.0", features = ["module_specifier"] }
|
deno_media_type = { version = "0.2.0", features = ["module_specifier"] }
|
||||||
deno_npm = "=0.25.4"
|
deno_npm = "=0.25.4"
|
||||||
deno_path_util = "=0.2.1"
|
deno_path_util = "=0.2.1"
|
||||||
deno_permissions = { version = "0.36.0", path = "./runtime/permissions" }
|
deno_permissions = { version = "0.37.0", path = "./runtime/permissions" }
|
||||||
deno_runtime = { version = "0.185.0", path = "./runtime" }
|
deno_runtime = { version = "0.186.0", path = "./runtime" }
|
||||||
deno_semver = "=0.5.16"
|
deno_semver = "=0.5.16"
|
||||||
deno_terminal = "0.2.0"
|
deno_terminal = "0.2.0"
|
||||||
napi_sym = { version = "0.106.0", path = "./ext/napi/sym" }
|
napi_sym = { version = "0.107.0", path = "./ext/napi/sym" }
|
||||||
test_util = { package = "test_server", path = "./tests/util/server" }
|
test_util = { package = "test_server", path = "./tests/util/server" }
|
||||||
|
|
||||||
denokv_proto = "0.8.1"
|
denokv_proto = "0.8.1"
|
||||||
|
@ -66,32 +66,32 @@ denokv_remote = "0.8.1"
|
||||||
denokv_sqlite = { default-features = false, version = "0.8.2" }
|
denokv_sqlite = { default-features = false, version = "0.8.2" }
|
||||||
|
|
||||||
# exts
|
# exts
|
||||||
deno_broadcast_channel = { version = "0.170.0", path = "./ext/broadcast_channel" }
|
deno_broadcast_channel = { version = "0.171.0", path = "./ext/broadcast_channel" }
|
||||||
deno_cache = { version = "0.108.0", path = "./ext/cache" }
|
deno_cache = { version = "0.109.0", path = "./ext/cache" }
|
||||||
deno_canvas = { version = "0.45.0", path = "./ext/canvas" }
|
deno_canvas = { version = "0.46.0", path = "./ext/canvas" }
|
||||||
deno_console = { version = "0.176.0", path = "./ext/console" }
|
deno_console = { version = "0.177.0", path = "./ext/console" }
|
||||||
deno_cron = { version = "0.56.0", path = "./ext/cron" }
|
deno_cron = { version = "0.57.0", path = "./ext/cron" }
|
||||||
deno_crypto = { version = "0.190.0", path = "./ext/crypto" }
|
deno_crypto = { version = "0.191.0", path = "./ext/crypto" }
|
||||||
deno_fetch = { version = "0.200.0", path = "./ext/fetch" }
|
deno_fetch = { version = "0.201.0", path = "./ext/fetch" }
|
||||||
deno_ffi = { version = "0.163.0", path = "./ext/ffi" }
|
deno_ffi = { version = "0.164.0", path = "./ext/ffi" }
|
||||||
deno_fs = { version = "0.86.0", path = "./ext/fs" }
|
deno_fs = { version = "0.87.0", path = "./ext/fs" }
|
||||||
deno_http = { version = "0.174.0", path = "./ext/http" }
|
deno_http = { version = "0.175.0", path = "./ext/http" }
|
||||||
deno_io = { version = "0.86.0", path = "./ext/io" }
|
deno_io = { version = "0.87.0", path = "./ext/io" }
|
||||||
deno_kv = { version = "0.84.0", path = "./ext/kv" }
|
deno_kv = { version = "0.85.0", path = "./ext/kv" }
|
||||||
deno_napi = { version = "0.107.0", path = "./ext/napi" }
|
deno_napi = { version = "0.108.0", path = "./ext/napi" }
|
||||||
deno_net = { version = "0.168.0", path = "./ext/net" }
|
deno_net = { version = "0.169.0", path = "./ext/net" }
|
||||||
deno_node = { version = "0.113.0", path = "./ext/node" }
|
deno_node = { version = "0.114.0", path = "./ext/node" }
|
||||||
deno_tls = { version = "0.163.0", path = "./ext/tls" }
|
deno_tls = { version = "0.164.0", path = "./ext/tls" }
|
||||||
deno_url = { version = "0.176.0", path = "./ext/url" }
|
deno_url = { version = "0.177.0", path = "./ext/url" }
|
||||||
deno_web = { version = "0.207.0", path = "./ext/web" }
|
deno_web = { version = "0.208.0", path = "./ext/web" }
|
||||||
deno_webgpu = { version = "0.143.0", path = "./ext/webgpu" }
|
deno_webgpu = { version = "0.144.0", path = "./ext/webgpu" }
|
||||||
deno_webidl = { version = "0.176.0", path = "./ext/webidl" }
|
deno_webidl = { version = "0.177.0", path = "./ext/webidl" }
|
||||||
deno_websocket = { version = "0.181.0", path = "./ext/websocket" }
|
deno_websocket = { version = "0.182.0", path = "./ext/websocket" }
|
||||||
deno_webstorage = { version = "0.171.0", path = "./ext/webstorage" }
|
deno_webstorage = { version = "0.172.0", path = "./ext/webstorage" }
|
||||||
|
|
||||||
# resolvers
|
# resolvers
|
||||||
deno_resolver = { version = "0.8.0", path = "./resolvers/deno" }
|
deno_resolver = { version = "0.9.0", path = "./resolvers/deno" }
|
||||||
node_resolver = { version = "0.15.0", path = "./resolvers/node" }
|
node_resolver = { version = "0.16.0", path = "./resolvers/node" }
|
||||||
|
|
||||||
aes = "=0.8.3"
|
aes = "=0.8.3"
|
||||||
anyhow = "1.0.57"
|
anyhow = "1.0.57"
|
||||||
|
@ -204,7 +204,7 @@ webpki-root-certs = "0.26.5"
|
||||||
webpki-roots = "0.26"
|
webpki-roots = "0.26"
|
||||||
which = "4.2.5"
|
which = "4.2.5"
|
||||||
yoke = { version = "0.7.4", features = ["derive"] }
|
yoke = { version = "0.7.4", features = ["derive"] }
|
||||||
zeromq = { version = "=0.4.0", default-features = false, features = ["tcp-transport", "tokio-runtime"] }
|
zeromq = { version = "=0.4.1", default-features = false, features = ["tcp-transport", "tokio-runtime"] }
|
||||||
zstd = "=0.12.4"
|
zstd = "=0.12.4"
|
||||||
|
|
||||||
# crypto
|
# crypto
|
||||||
|
|
12
Releases.md
12
Releases.md
|
@ -6,6 +6,18 @@ https://github.com/denoland/deno/releases
|
||||||
We also have one-line install commands at:
|
We also have one-line install commands at:
|
||||||
https://github.com/denoland/deno_install
|
https://github.com/denoland/deno_install
|
||||||
|
|
||||||
|
### 2.0.6 / 2024.11.10
|
||||||
|
|
||||||
|
- feat(ext/http): abort event when request is cancelled (#26781)
|
||||||
|
- feat(ext/http): abort signal when request is cancelled (#26761)
|
||||||
|
- feat(lsp): auto-import completions from byonm dependencies (#26680)
|
||||||
|
- fix(ext/cache): don't panic when creating cache (#26780)
|
||||||
|
- fix(ext/node): better inspector support (#26471)
|
||||||
|
- fix(fmt): don't use self-closing tags in HTML (#26754)
|
||||||
|
- fix(install): cache jsr deps from all workspace config files (#26779)
|
||||||
|
- fix(node:zlib): gzip & gzipSync should accept ArrayBuffer (#26762)
|
||||||
|
- fix: performance.timeOrigin (#26787)
|
||||||
|
|
||||||
### 2.0.5 / 2024.11.05
|
### 2.0.5 / 2024.11.05
|
||||||
|
|
||||||
- fix(add): better error message when adding package that only has pre-release
|
- fix(add): better error message when adding package that only has pre-release
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "deno_bench_util"
|
name = "deno_bench_util"
|
||||||
version = "0.170.0"
|
version = "0.171.0"
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "deno"
|
name = "deno"
|
||||||
version = "2.0.5"
|
version = "2.0.6"
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
default-run = "deno"
|
default-run = "deno"
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
|
|
|
@ -10,6 +10,7 @@ use super::tsc;
|
||||||
use super::urls::url_to_uri;
|
use super::urls::url_to_uri;
|
||||||
|
|
||||||
use crate::args::jsr_url;
|
use crate::args::jsr_url;
|
||||||
|
use crate::lsp::logging::lsp_warn;
|
||||||
use crate::lsp::search::PackageSearchApi;
|
use crate::lsp::search::PackageSearchApi;
|
||||||
use crate::tools::lint::CliLinter;
|
use crate::tools::lint::CliLinter;
|
||||||
use crate::util::path::relative_specifier;
|
use crate::util::path::relative_specifier;
|
||||||
|
@ -747,8 +748,14 @@ pub fn ts_changes_to_edit(
|
||||||
) -> Result<Option<lsp::WorkspaceEdit>, AnyError> {
|
) -> Result<Option<lsp::WorkspaceEdit>, AnyError> {
|
||||||
let mut text_document_edits = Vec::new();
|
let mut text_document_edits = Vec::new();
|
||||||
for change in changes {
|
for change in changes {
|
||||||
let text_document_edit = change.to_text_document_edit(language_server)?;
|
let edit = match change.to_text_document_edit(language_server) {
|
||||||
text_document_edits.push(text_document_edit);
|
Ok(e) => e,
|
||||||
|
Err(err) => {
|
||||||
|
lsp_warn!("Couldn't covert text document edit: {:#}", err);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
text_document_edits.push(edit);
|
||||||
}
|
}
|
||||||
Ok(Some(lsp::WorkspaceEdit {
|
Ok(Some(lsp::WorkspaceEdit {
|
||||||
changes: None,
|
changes: None,
|
||||||
|
|
|
@ -18,6 +18,7 @@ pub struct BinEntries<'a> {
|
||||||
seen_names: HashMap<&'a str, &'a NpmPackageId>,
|
seen_names: HashMap<&'a str, &'a NpmPackageId>,
|
||||||
/// The bin entries
|
/// The bin entries
|
||||||
entries: Vec<(&'a NpmResolutionPackage, PathBuf)>,
|
entries: Vec<(&'a NpmResolutionPackage, PathBuf)>,
|
||||||
|
sorted: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the name of the default binary for the given package.
|
/// Returns the name of the default binary for the given package.
|
||||||
|
@ -31,6 +32,20 @@ fn default_bin_name(package: &NpmResolutionPackage) -> &str {
|
||||||
.map_or(package.id.nv.name.as_str(), |(_, name)| name)
|
.map_or(package.id.nv.name.as_str(), |(_, name)| name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn warn_missing_entrypoint(
|
||||||
|
bin_name: &str,
|
||||||
|
package_path: &Path,
|
||||||
|
entrypoint: &Path,
|
||||||
|
) {
|
||||||
|
log::warn!(
|
||||||
|
"{} Trying to set up '{}' bin for \"{}\", but the entry point \"{}\" doesn't exist.",
|
||||||
|
deno_terminal::colors::yellow("Warning"),
|
||||||
|
bin_name,
|
||||||
|
package_path.display(),
|
||||||
|
entrypoint.display()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> BinEntries<'a> {
|
impl<'a> BinEntries<'a> {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self::default()
|
Self::default()
|
||||||
|
@ -42,6 +57,7 @@ impl<'a> BinEntries<'a> {
|
||||||
package: &'a NpmResolutionPackage,
|
package: &'a NpmResolutionPackage,
|
||||||
package_path: PathBuf,
|
package_path: PathBuf,
|
||||||
) {
|
) {
|
||||||
|
self.sorted = false;
|
||||||
// check for a new collision, if we haven't already
|
// check for a new collision, if we haven't already
|
||||||
// found one
|
// found one
|
||||||
match package.bin.as_ref().unwrap() {
|
match package.bin.as_ref().unwrap() {
|
||||||
|
@ -79,16 +95,21 @@ impl<'a> BinEntries<'a> {
|
||||||
&str, // bin name
|
&str, // bin name
|
||||||
&str, // bin script
|
&str, // bin script
|
||||||
) -> Result<(), AnyError>,
|
) -> Result<(), AnyError>,
|
||||||
|
mut filter: impl FnMut(&NpmResolutionPackage) -> bool,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), AnyError> {
|
||||||
if !self.collisions.is_empty() {
|
if !self.collisions.is_empty() && !self.sorted {
|
||||||
// walking the dependency tree to find out the depth of each package
|
// walking the dependency tree to find out the depth of each package
|
||||||
// is sort of expensive, so we only do it if there's a collision
|
// is sort of expensive, so we only do it if there's a collision
|
||||||
sort_by_depth(snapshot, &mut self.entries, &mut self.collisions);
|
sort_by_depth(snapshot, &mut self.entries, &mut self.collisions);
|
||||||
|
self.sorted = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut seen = HashSet::new();
|
let mut seen = HashSet::new();
|
||||||
|
|
||||||
for (package, package_path) in &self.entries {
|
for (package, package_path) in &self.entries {
|
||||||
|
if !filter(package) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if let Some(bin_entries) = &package.bin {
|
if let Some(bin_entries) = &package.bin {
|
||||||
match bin_entries {
|
match bin_entries {
|
||||||
deno_npm::registry::NpmPackageVersionBinEntry::String(script) => {
|
deno_npm::registry::NpmPackageVersionBinEntry::String(script) => {
|
||||||
|
@ -118,8 +139,8 @@ impl<'a> BinEntries<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Collect the bin entries into a vec of (name, script path)
|
/// Collect the bin entries into a vec of (name, script path)
|
||||||
pub fn into_bin_files(
|
pub fn collect_bin_files(
|
||||||
mut self,
|
&mut self,
|
||||||
snapshot: &NpmResolutionSnapshot,
|
snapshot: &NpmResolutionSnapshot,
|
||||||
) -> Vec<(String, PathBuf)> {
|
) -> Vec<(String, PathBuf)> {
|
||||||
let mut bins = Vec::new();
|
let mut bins = Vec::new();
|
||||||
|
@ -131,17 +152,18 @@ impl<'a> BinEntries<'a> {
|
||||||
bins.push((name.to_string(), package_path.join(script)));
|
bins.push((name.to_string(), package_path.join(script)));
|
||||||
Ok(())
|
Ok(())
|
||||||
},
|
},
|
||||||
|
|_| true,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
bins
|
bins
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Finish setting up the bin entries, writing the necessary files
|
fn set_up_entries_filtered(
|
||||||
/// to disk.
|
|
||||||
pub fn finish(
|
|
||||||
mut self,
|
mut self,
|
||||||
snapshot: &NpmResolutionSnapshot,
|
snapshot: &NpmResolutionSnapshot,
|
||||||
bin_node_modules_dir_path: &Path,
|
bin_node_modules_dir_path: &Path,
|
||||||
|
filter: impl FnMut(&NpmResolutionPackage) -> bool,
|
||||||
|
mut handler: impl FnMut(&EntrySetupOutcome<'_>),
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), AnyError> {
|
||||||
if !self.entries.is_empty() && !bin_node_modules_dir_path.exists() {
|
if !self.entries.is_empty() && !bin_node_modules_dir_path.exists() {
|
||||||
std::fs::create_dir_all(bin_node_modules_dir_path).with_context(
|
std::fs::create_dir_all(bin_node_modules_dir_path).with_context(
|
||||||
|
@ -160,18 +182,54 @@ impl<'a> BinEntries<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
},
|
},
|
||||||
|package, package_path, name, script| {
|
|package, package_path, name, script| {
|
||||||
set_up_bin_entry(
|
let outcome = set_up_bin_entry(
|
||||||
package,
|
package,
|
||||||
name,
|
name,
|
||||||
script,
|
script,
|
||||||
package_path,
|
package_path,
|
||||||
bin_node_modules_dir_path,
|
bin_node_modules_dir_path,
|
||||||
)
|
)?;
|
||||||
|
handler(&outcome);
|
||||||
|
Ok(())
|
||||||
},
|
},
|
||||||
|
filter,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Finish setting up the bin entries, writing the necessary files
|
||||||
|
/// to disk.
|
||||||
|
pub fn finish(
|
||||||
|
self,
|
||||||
|
snapshot: &NpmResolutionSnapshot,
|
||||||
|
bin_node_modules_dir_path: &Path,
|
||||||
|
handler: impl FnMut(&EntrySetupOutcome<'_>),
|
||||||
|
) -> Result<(), AnyError> {
|
||||||
|
self.set_up_entries_filtered(
|
||||||
|
snapshot,
|
||||||
|
bin_node_modules_dir_path,
|
||||||
|
|_| true,
|
||||||
|
handler,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Finish setting up the bin entries, writing the necessary files
|
||||||
|
/// to disk.
|
||||||
|
pub fn finish_only(
|
||||||
|
self,
|
||||||
|
snapshot: &NpmResolutionSnapshot,
|
||||||
|
bin_node_modules_dir_path: &Path,
|
||||||
|
handler: impl FnMut(&EntrySetupOutcome<'_>),
|
||||||
|
only: &HashSet<&NpmPackageId>,
|
||||||
|
) -> Result<(), AnyError> {
|
||||||
|
self.set_up_entries_filtered(
|
||||||
|
snapshot,
|
||||||
|
bin_node_modules_dir_path,
|
||||||
|
|package| only.contains(&package.id),
|
||||||
|
handler,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// walk the dependency tree to find out the depth of each package
|
// walk the dependency tree to find out the depth of each package
|
||||||
|
@ -233,16 +291,17 @@ fn sort_by_depth(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_up_bin_entry(
|
pub fn set_up_bin_entry<'a>(
|
||||||
package: &NpmResolutionPackage,
|
package: &'a NpmResolutionPackage,
|
||||||
bin_name: &str,
|
bin_name: &'a str,
|
||||||
#[allow(unused_variables)] bin_script: &str,
|
#[allow(unused_variables)] bin_script: &str,
|
||||||
#[allow(unused_variables)] package_path: &Path,
|
#[allow(unused_variables)] package_path: &'a Path,
|
||||||
bin_node_modules_dir_path: &Path,
|
bin_node_modules_dir_path: &Path,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<EntrySetupOutcome<'a>, AnyError> {
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
{
|
{
|
||||||
set_up_bin_shim(package, bin_name, bin_node_modules_dir_path)?;
|
set_up_bin_shim(package, bin_name, bin_node_modules_dir_path)?;
|
||||||
|
Ok(EntrySetupOutcome::Success)
|
||||||
}
|
}
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
{
|
{
|
||||||
|
@ -252,9 +311,8 @@ pub fn set_up_bin_entry(
|
||||||
bin_script,
|
bin_script,
|
||||||
package_path,
|
package_path,
|
||||||
bin_node_modules_dir_path,
|
bin_node_modules_dir_path,
|
||||||
)?;
|
)
|
||||||
}
|
}
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
|
@ -301,14 +359,39 @@ fn make_executable_if_exists(path: &Path) -> Result<bool, AnyError> {
|
||||||
Ok(true)
|
Ok(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum EntrySetupOutcome<'a> {
|
||||||
|
#[cfg_attr(windows, allow(dead_code))]
|
||||||
|
MissingEntrypoint {
|
||||||
|
bin_name: &'a str,
|
||||||
|
package_path: &'a Path,
|
||||||
|
entrypoint: PathBuf,
|
||||||
|
package: &'a NpmResolutionPackage,
|
||||||
|
},
|
||||||
|
Success,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> EntrySetupOutcome<'a> {
|
||||||
|
pub fn warn_if_failed(&self) {
|
||||||
|
match self {
|
||||||
|
EntrySetupOutcome::MissingEntrypoint {
|
||||||
|
bin_name,
|
||||||
|
package_path,
|
||||||
|
entrypoint,
|
||||||
|
..
|
||||||
|
} => warn_missing_entrypoint(bin_name, package_path, entrypoint),
|
||||||
|
EntrySetupOutcome::Success => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
fn symlink_bin_entry(
|
fn symlink_bin_entry<'a>(
|
||||||
_package: &NpmResolutionPackage,
|
package: &'a NpmResolutionPackage,
|
||||||
bin_name: &str,
|
bin_name: &'a str,
|
||||||
bin_script: &str,
|
bin_script: &str,
|
||||||
package_path: &Path,
|
package_path: &'a Path,
|
||||||
bin_node_modules_dir_path: &Path,
|
bin_node_modules_dir_path: &Path,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<EntrySetupOutcome<'a>, AnyError> {
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::os::unix::fs::symlink;
|
use std::os::unix::fs::symlink;
|
||||||
let link = bin_node_modules_dir_path.join(bin_name);
|
let link = bin_node_modules_dir_path.join(bin_name);
|
||||||
|
@ -318,14 +401,12 @@ fn symlink_bin_entry(
|
||||||
format!("Can't set up '{}' bin at {}", bin_name, original.display())
|
format!("Can't set up '{}' bin at {}", bin_name, original.display())
|
||||||
})?;
|
})?;
|
||||||
if !found {
|
if !found {
|
||||||
log::warn!(
|
return Ok(EntrySetupOutcome::MissingEntrypoint {
|
||||||
"{} Trying to set up '{}' bin for \"{}\", but the entry point \"{}\" doesn't exist.",
|
|
||||||
deno_terminal::colors::yellow("Warning"),
|
|
||||||
bin_name,
|
bin_name,
|
||||||
package_path.display(),
|
package_path,
|
||||||
original.display()
|
entrypoint: original,
|
||||||
);
|
package,
|
||||||
return Ok(());
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let original_relative =
|
let original_relative =
|
||||||
|
@ -348,7 +429,7 @@ fn symlink_bin_entry(
|
||||||
original_relative.display()
|
original_relative.display()
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
return Ok(());
|
return Ok(EntrySetupOutcome::Success);
|
||||||
}
|
}
|
||||||
return Err(err).with_context(|| {
|
return Err(err).with_context(|| {
|
||||||
format!(
|
format!(
|
||||||
|
@ -359,5 +440,5 @@ fn symlink_bin_entry(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(EntrySetupOutcome::Success)
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ use deno_runtime::deno_io::FromRawIoHandle;
|
||||||
use deno_semver::package::PackageNv;
|
use deno_semver::package::PackageNv;
|
||||||
use deno_semver::Version;
|
use deno_semver::Version;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
use std::collections::HashSet;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
@ -61,7 +62,7 @@ impl<'a> LifecycleScripts<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn has_lifecycle_scripts(
|
pub fn has_lifecycle_scripts(
|
||||||
package: &NpmResolutionPackage,
|
package: &NpmResolutionPackage,
|
||||||
package_path: &Path,
|
package_path: &Path,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
|
@ -83,7 +84,7 @@ fn is_broken_default_install_script(script: &str, package_path: &Path) -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> LifecycleScripts<'a> {
|
impl<'a> LifecycleScripts<'a> {
|
||||||
fn can_run_scripts(&self, package_nv: &PackageNv) -> bool {
|
pub fn can_run_scripts(&self, package_nv: &PackageNv) -> bool {
|
||||||
if !self.strategy.can_run_scripts() {
|
if !self.strategy.can_run_scripts() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -98,6 +99,9 @@ impl<'a> LifecycleScripts<'a> {
|
||||||
PackagesAllowedScripts::None => false,
|
PackagesAllowedScripts::None => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn has_run_scripts(&self, package: &NpmResolutionPackage) -> bool {
|
||||||
|
self.strategy.has_run(package)
|
||||||
|
}
|
||||||
/// Register a package for running lifecycle scripts, if applicable.
|
/// Register a package for running lifecycle scripts, if applicable.
|
||||||
///
|
///
|
||||||
/// `package_path` is the path containing the package's code (its root dir).
|
/// `package_path` is the path containing the package's code (its root dir).
|
||||||
|
@ -110,12 +114,12 @@ impl<'a> LifecycleScripts<'a> {
|
||||||
) {
|
) {
|
||||||
if has_lifecycle_scripts(package, &package_path) {
|
if has_lifecycle_scripts(package, &package_path) {
|
||||||
if self.can_run_scripts(&package.id.nv) {
|
if self.can_run_scripts(&package.id.nv) {
|
||||||
if !self.strategy.has_run(package) {
|
if !self.has_run_scripts(package) {
|
||||||
self
|
self
|
||||||
.packages_with_scripts
|
.packages_with_scripts
|
||||||
.push((package, package_path.into_owned()));
|
.push((package, package_path.into_owned()));
|
||||||
}
|
}
|
||||||
} else if !self.strategy.has_run(package)
|
} else if !self.has_run_scripts(package)
|
||||||
&& (self.config.explicit_install || !self.strategy.has_warned(package))
|
&& (self.config.explicit_install || !self.strategy.has_warned(package))
|
||||||
{
|
{
|
||||||
// Skip adding `esbuild` as it is known that it can work properly without lifecycle script
|
// Skip adding `esbuild` as it is known that it can work properly without lifecycle script
|
||||||
|
@ -149,22 +153,32 @@ impl<'a> LifecycleScripts<'a> {
|
||||||
self,
|
self,
|
||||||
snapshot: &NpmResolutionSnapshot,
|
snapshot: &NpmResolutionSnapshot,
|
||||||
packages: &[NpmResolutionPackage],
|
packages: &[NpmResolutionPackage],
|
||||||
root_node_modules_dir_path: Option<&Path>,
|
root_node_modules_dir_path: &Path,
|
||||||
progress_bar: &ProgressBar,
|
progress_bar: &ProgressBar,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), AnyError> {
|
||||||
self.warn_not_run_scripts()?;
|
self.warn_not_run_scripts()?;
|
||||||
let get_package_path =
|
let get_package_path =
|
||||||
|p: &NpmResolutionPackage| self.strategy.package_path(p);
|
|p: &NpmResolutionPackage| self.strategy.package_path(p);
|
||||||
let mut failed_packages = Vec::new();
|
let mut failed_packages = Vec::new();
|
||||||
|
let mut bin_entries = BinEntries::new();
|
||||||
if !self.packages_with_scripts.is_empty() {
|
if !self.packages_with_scripts.is_empty() {
|
||||||
|
let package_ids = self
|
||||||
|
.packages_with_scripts
|
||||||
|
.iter()
|
||||||
|
.map(|(p, _)| &p.id)
|
||||||
|
.collect::<HashSet<_>>();
|
||||||
// get custom commands for each bin available in the node_modules dir (essentially
|
// get custom commands for each bin available in the node_modules dir (essentially
|
||||||
// the scripts that are in `node_modules/.bin`)
|
// the scripts that are in `node_modules/.bin`)
|
||||||
let base =
|
let base = resolve_baseline_custom_commands(
|
||||||
resolve_baseline_custom_commands(snapshot, packages, get_package_path)?;
|
&mut bin_entries,
|
||||||
|
snapshot,
|
||||||
|
packages,
|
||||||
|
get_package_path,
|
||||||
|
)?;
|
||||||
let init_cwd = &self.config.initial_cwd;
|
let init_cwd = &self.config.initial_cwd;
|
||||||
let process_state = crate::npm::managed::npm_process_state(
|
let process_state = crate::npm::managed::npm_process_state(
|
||||||
snapshot.as_valid_serialized(),
|
snapshot.as_valid_serialized(),
|
||||||
root_node_modules_dir_path,
|
Some(root_node_modules_dir_path),
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut env_vars = crate::task_runner::real_env_vars();
|
let mut env_vars = crate::task_runner::real_env_vars();
|
||||||
|
@ -221,7 +235,7 @@ impl<'a> LifecycleScripts<'a> {
|
||||||
custom_commands: custom_commands.clone(),
|
custom_commands: custom_commands.clone(),
|
||||||
init_cwd,
|
init_cwd,
|
||||||
argv: &[],
|
argv: &[],
|
||||||
root_node_modules_dir: root_node_modules_dir_path,
|
root_node_modules_dir: Some(root_node_modules_dir_path),
|
||||||
stdio: Some(crate::task_runner::TaskIo {
|
stdio: Some(crate::task_runner::TaskIo {
|
||||||
stderr: TaskStdio::piped(),
|
stderr: TaskStdio::piped(),
|
||||||
stdout: TaskStdio::piped(),
|
stdout: TaskStdio::piped(),
|
||||||
|
@ -262,6 +276,17 @@ impl<'a> LifecycleScripts<'a> {
|
||||||
}
|
}
|
||||||
self.strategy.did_run_scripts(package)?;
|
self.strategy.did_run_scripts(package)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// re-set up bin entries for the packages which we've run scripts for.
|
||||||
|
// lifecycle scripts can create files that are linked to by bin entries,
|
||||||
|
// and the only reliable way to handle this is to re-link bin entries
|
||||||
|
// (this is what PNPM does as well)
|
||||||
|
bin_entries.finish_only(
|
||||||
|
snapshot,
|
||||||
|
&root_node_modules_dir_path.join(".bin"),
|
||||||
|
|outcome| outcome.warn_if_failed(),
|
||||||
|
&package_ids,
|
||||||
|
)?;
|
||||||
}
|
}
|
||||||
if failed_packages.is_empty() {
|
if failed_packages.is_empty() {
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -281,9 +306,10 @@ impl<'a> LifecycleScripts<'a> {
|
||||||
// take in all (non copy) packages from snapshot,
|
// take in all (non copy) packages from snapshot,
|
||||||
// and resolve the set of available binaries to create
|
// and resolve the set of available binaries to create
|
||||||
// custom commands available to the task runner
|
// custom commands available to the task runner
|
||||||
fn resolve_baseline_custom_commands(
|
fn resolve_baseline_custom_commands<'a>(
|
||||||
snapshot: &NpmResolutionSnapshot,
|
bin_entries: &mut BinEntries<'a>,
|
||||||
packages: &[NpmResolutionPackage],
|
snapshot: &'a NpmResolutionSnapshot,
|
||||||
|
packages: &'a [NpmResolutionPackage],
|
||||||
get_package_path: impl Fn(&NpmResolutionPackage) -> PathBuf,
|
get_package_path: impl Fn(&NpmResolutionPackage) -> PathBuf,
|
||||||
) -> Result<crate::task_runner::TaskCustomCommands, AnyError> {
|
) -> Result<crate::task_runner::TaskCustomCommands, AnyError> {
|
||||||
let mut custom_commands = crate::task_runner::TaskCustomCommands::new();
|
let mut custom_commands = crate::task_runner::TaskCustomCommands::new();
|
||||||
|
@ -306,6 +332,7 @@ fn resolve_baseline_custom_commands(
|
||||||
// doing it for packages that are set up already.
|
// doing it for packages that are set up already.
|
||||||
// realistically, scripts won't be run very often so it probably isn't too big of an issue.
|
// realistically, scripts won't be run very often so it probably isn't too big of an issue.
|
||||||
resolve_custom_commands_from_packages(
|
resolve_custom_commands_from_packages(
|
||||||
|
bin_entries,
|
||||||
custom_commands,
|
custom_commands,
|
||||||
snapshot,
|
snapshot,
|
||||||
packages,
|
packages,
|
||||||
|
@ -320,12 +347,12 @@ fn resolve_custom_commands_from_packages<
|
||||||
'a,
|
'a,
|
||||||
P: IntoIterator<Item = &'a NpmResolutionPackage>,
|
P: IntoIterator<Item = &'a NpmResolutionPackage>,
|
||||||
>(
|
>(
|
||||||
|
bin_entries: &mut BinEntries<'a>,
|
||||||
mut commands: crate::task_runner::TaskCustomCommands,
|
mut commands: crate::task_runner::TaskCustomCommands,
|
||||||
snapshot: &'a NpmResolutionSnapshot,
|
snapshot: &'a NpmResolutionSnapshot,
|
||||||
packages: P,
|
packages: P,
|
||||||
get_package_path: impl Fn(&'a NpmResolutionPackage) -> PathBuf,
|
get_package_path: impl Fn(&'a NpmResolutionPackage) -> PathBuf,
|
||||||
) -> Result<crate::task_runner::TaskCustomCommands, AnyError> {
|
) -> Result<crate::task_runner::TaskCustomCommands, AnyError> {
|
||||||
let mut bin_entries = BinEntries::new();
|
|
||||||
for package in packages {
|
for package in packages {
|
||||||
let package_path = get_package_path(package);
|
let package_path = get_package_path(package);
|
||||||
|
|
||||||
|
@ -333,7 +360,7 @@ fn resolve_custom_commands_from_packages<
|
||||||
bin_entries.add(package, package_path);
|
bin_entries.add(package, package_path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let bins = bin_entries.into_bin_files(snapshot);
|
let bins: Vec<(String, PathBuf)> = bin_entries.collect_bin_files(snapshot);
|
||||||
for (bin_name, script_path) in bins {
|
for (bin_name, script_path) in bins {
|
||||||
commands.insert(
|
commands.insert(
|
||||||
bin_name.clone(),
|
bin_name.clone(),
|
||||||
|
@ -356,7 +383,9 @@ fn resolve_custom_commands_from_deps(
|
||||||
snapshot: &NpmResolutionSnapshot,
|
snapshot: &NpmResolutionSnapshot,
|
||||||
get_package_path: impl Fn(&NpmResolutionPackage) -> PathBuf,
|
get_package_path: impl Fn(&NpmResolutionPackage) -> PathBuf,
|
||||||
) -> Result<crate::task_runner::TaskCustomCommands, AnyError> {
|
) -> Result<crate::task_runner::TaskCustomCommands, AnyError> {
|
||||||
|
let mut bin_entries = BinEntries::new();
|
||||||
resolve_custom_commands_from_packages(
|
resolve_custom_commands_from_packages(
|
||||||
|
&mut bin_entries,
|
||||||
baseline,
|
baseline,
|
||||||
snapshot,
|
snapshot,
|
||||||
package
|
package
|
||||||
|
|
|
@ -55,6 +55,7 @@ use crate::util::progress_bar::ProgressMessagePrompt;
|
||||||
use super::super::cache::NpmCache;
|
use super::super::cache::NpmCache;
|
||||||
use super::super::cache::TarballCache;
|
use super::super::cache::TarballCache;
|
||||||
use super::super::resolution::NpmResolution;
|
use super::super::resolution::NpmResolution;
|
||||||
|
use super::common::bin_entries;
|
||||||
use super::common::NpmPackageFsResolver;
|
use super::common::NpmPackageFsResolver;
|
||||||
use super::common::RegistryReadPermissionChecker;
|
use super::common::RegistryReadPermissionChecker;
|
||||||
|
|
||||||
|
@ -329,8 +330,7 @@ async fn sync_resolution_with_fs(
|
||||||
let mut cache_futures = FuturesUnordered::new();
|
let mut cache_futures = FuturesUnordered::new();
|
||||||
let mut newest_packages_by_name: HashMap<&String, &NpmResolutionPackage> =
|
let mut newest_packages_by_name: HashMap<&String, &NpmResolutionPackage> =
|
||||||
HashMap::with_capacity(package_partitions.packages.len());
|
HashMap::with_capacity(package_partitions.packages.len());
|
||||||
let bin_entries =
|
let bin_entries = Rc::new(RefCell::new(bin_entries::BinEntries::new()));
|
||||||
Rc::new(RefCell::new(super::common::bin_entries::BinEntries::new()));
|
|
||||||
let mut lifecycle_scripts =
|
let mut lifecycle_scripts =
|
||||||
super::common::lifecycle_scripts::LifecycleScripts::new(
|
super::common::lifecycle_scripts::LifecycleScripts::new(
|
||||||
lifecycle_scripts,
|
lifecycle_scripts,
|
||||||
|
@ -658,7 +658,28 @@ async fn sync_resolution_with_fs(
|
||||||
// 7. Set up `node_modules/.bin` entries for packages that need it.
|
// 7. Set up `node_modules/.bin` entries for packages that need it.
|
||||||
{
|
{
|
||||||
let bin_entries = std::mem::take(&mut *bin_entries.borrow_mut());
|
let bin_entries = std::mem::take(&mut *bin_entries.borrow_mut());
|
||||||
bin_entries.finish(snapshot, &bin_node_modules_dir_path)?;
|
bin_entries.finish(
|
||||||
|
snapshot,
|
||||||
|
&bin_node_modules_dir_path,
|
||||||
|
|setup_outcome| {
|
||||||
|
match setup_outcome {
|
||||||
|
bin_entries::EntrySetupOutcome::MissingEntrypoint {
|
||||||
|
package,
|
||||||
|
package_path,
|
||||||
|
..
|
||||||
|
} if super::common::lifecycle_scripts::has_lifecycle_scripts(
|
||||||
|
package,
|
||||||
|
package_path,
|
||||||
|
) && lifecycle_scripts.can_run_scripts(&package.id.nv)
|
||||||
|
&& !lifecycle_scripts.has_run_scripts(package) =>
|
||||||
|
{
|
||||||
|
// ignore, it might get fixed when the lifecycle scripts run.
|
||||||
|
// if not, we'll warn then
|
||||||
|
}
|
||||||
|
outcome => outcome.warn_if_failed(),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 8. Create symlinks for the workspace packages
|
// 8. Create symlinks for the workspace packages
|
||||||
|
@ -708,7 +729,7 @@ async fn sync_resolution_with_fs(
|
||||||
.finish(
|
.finish(
|
||||||
snapshot,
|
snapshot,
|
||||||
&package_partitions.packages,
|
&package_partitions.packages,
|
||||||
Some(root_node_modules_dir_path),
|
root_node_modules_dir_path,
|
||||||
progress_bar,
|
progress_bar,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
use std::sync::atomic::AtomicUsize;
|
use std::sync::atomic::AtomicUsize;
|
||||||
use std::sync::atomic::Ordering;
|
use std::sync::atomic::Ordering;
|
||||||
use std::time;
|
|
||||||
|
|
||||||
use deno_core::error::generic_error;
|
use deno_core::error::generic_error;
|
||||||
use deno_core::error::type_error;
|
use deno_core::error::type_error;
|
||||||
|
@ -13,6 +12,7 @@ use deno_core::ModuleSpecifier;
|
||||||
use deno_core::OpState;
|
use deno_core::OpState;
|
||||||
use deno_runtime::deno_permissions::ChildPermissionsArg;
|
use deno_runtime::deno_permissions::ChildPermissionsArg;
|
||||||
use deno_runtime::deno_permissions::PermissionsContainer;
|
use deno_runtime::deno_permissions::PermissionsContainer;
|
||||||
|
use deno_runtime::deno_web::StartTime;
|
||||||
use tokio::sync::mpsc::UnboundedSender;
|
use tokio::sync::mpsc::UnboundedSender;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
@ -148,7 +148,7 @@ fn op_dispatch_bench_event(state: &mut OpState, #[serde] event: BenchEvent) {
|
||||||
#[op2(fast)]
|
#[op2(fast)]
|
||||||
#[number]
|
#[number]
|
||||||
fn op_bench_now(state: &mut OpState) -> Result<u64, std::num::TryFromIntError> {
|
fn op_bench_now(state: &mut OpState) -> Result<u64, std::num::TryFromIntError> {
|
||||||
let ns = state.borrow::<time::Instant>().elapsed().as_nanos();
|
let ns = state.borrow::<StartTime>().elapsed().as_nanos();
|
||||||
let ns_u64 = u64::try_from(ns)?;
|
let ns_u64 = u64::try_from(ns)?;
|
||||||
Ok(ns_u64)
|
Ok(ns_u64)
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,11 @@ pub async fn cache_top_level_deps(
|
||||||
|
|
||||||
let mut seen_reqs = std::collections::HashSet::new();
|
let mut seen_reqs = std::collections::HashSet::new();
|
||||||
|
|
||||||
for entry in import_map.imports().entries() {
|
for entry in import_map.imports().entries().chain(
|
||||||
|
import_map
|
||||||
|
.scopes()
|
||||||
|
.flat_map(|scope| scope.imports.entries()),
|
||||||
|
) {
|
||||||
let Some(specifier) = entry.value else {
|
let Some(specifier) = entry.value else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "deno_broadcast_channel"
|
name = "deno_broadcast_channel"
|
||||||
version = "0.170.0"
|
version = "0.171.0"
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
|
2
ext/cache/Cargo.toml
vendored
2
ext/cache/Cargo.toml
vendored
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "deno_cache"
|
name = "deno_cache"
|
||||||
version = "0.108.0"
|
version = "0.109.0"
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
|
6
ext/cache/lib.rs
vendored
6
ext/cache/lib.rs
vendored
|
@ -33,7 +33,9 @@ pub enum CacheError {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct CreateCache<C: Cache + 'static>(pub Arc<dyn Fn() -> C>);
|
pub struct CreateCache<C: Cache + 'static>(
|
||||||
|
pub Arc<dyn Fn() -> Result<C, CacheError>>,
|
||||||
|
);
|
||||||
|
|
||||||
deno_core::extension!(deno_cache,
|
deno_core::extension!(deno_cache,
|
||||||
deps = [ deno_webidl, deno_web, deno_url, deno_fetch ],
|
deps = [ deno_webidl, deno_web, deno_url, deno_fetch ],
|
||||||
|
@ -231,7 +233,7 @@ where
|
||||||
if let Some(cache) = state.try_borrow::<CA>() {
|
if let Some(cache) = state.try_borrow::<CA>() {
|
||||||
Ok(cache.clone())
|
Ok(cache.clone())
|
||||||
} else if let Some(create_cache) = state.try_borrow::<CreateCache<CA>>() {
|
} else if let Some(create_cache) = state.try_borrow::<CreateCache<CA>>() {
|
||||||
let cache = create_cache.0();
|
let cache = create_cache.0()?;
|
||||||
state.put(cache);
|
state.put(cache);
|
||||||
Ok(state.borrow::<CA>().clone())
|
Ok(state.borrow::<CA>().clone())
|
||||||
} else {
|
} else {
|
||||||
|
|
19
ext/cache/sqlite.rs
vendored
19
ext/cache/sqlite.rs
vendored
|
@ -42,7 +42,7 @@ pub struct SqliteBackedCache {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SqliteBackedCache {
|
impl SqliteBackedCache {
|
||||||
pub fn new(cache_storage_dir: PathBuf) -> Self {
|
pub fn new(cache_storage_dir: PathBuf) -> Result<Self, CacheError> {
|
||||||
{
|
{
|
||||||
std::fs::create_dir_all(&cache_storage_dir)
|
std::fs::create_dir_all(&cache_storage_dir)
|
||||||
.expect("failed to create cache dir");
|
.expect("failed to create cache dir");
|
||||||
|
@ -57,18 +57,14 @@ impl SqliteBackedCache {
|
||||||
PRAGMA synchronous=NORMAL;
|
PRAGMA synchronous=NORMAL;
|
||||||
PRAGMA optimize;
|
PRAGMA optimize;
|
||||||
";
|
";
|
||||||
connection
|
connection.execute_batch(initial_pragmas)?;
|
||||||
.execute_batch(initial_pragmas)
|
connection.execute(
|
||||||
.expect("failed to execute pragmas");
|
|
||||||
connection
|
|
||||||
.execute(
|
|
||||||
"CREATE TABLE IF NOT EXISTS cache_storage (
|
"CREATE TABLE IF NOT EXISTS cache_storage (
|
||||||
id INTEGER PRIMARY KEY,
|
id INTEGER PRIMARY KEY,
|
||||||
cache_name TEXT NOT NULL UNIQUE
|
cache_name TEXT NOT NULL UNIQUE
|
||||||
)",
|
)",
|
||||||
(),
|
(),
|
||||||
)
|
)?;
|
||||||
.expect("failed to create cache_storage table");
|
|
||||||
connection
|
connection
|
||||||
.execute(
|
.execute(
|
||||||
"CREATE TABLE IF NOT EXISTS request_response_list (
|
"CREATE TABLE IF NOT EXISTS request_response_list (
|
||||||
|
@ -86,12 +82,11 @@ impl SqliteBackedCache {
|
||||||
UNIQUE (cache_id, request_url)
|
UNIQUE (cache_id, request_url)
|
||||||
)",
|
)",
|
||||||
(),
|
(),
|
||||||
)
|
)?;
|
||||||
.expect("failed to create request_response_list table");
|
Ok(SqliteBackedCache {
|
||||||
SqliteBackedCache {
|
|
||||||
connection: Arc::new(Mutex::new(connection)),
|
connection: Arc::new(Mutex::new(connection)),
|
||||||
cache_storage_dir,
|
cache_storage_dir,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "deno_canvas"
|
name = "deno_canvas"
|
||||||
version = "0.45.0"
|
version = "0.46.0"
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "deno_console"
|
name = "deno_console"
|
||||||
version = "0.176.0"
|
version = "0.177.0"
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "deno_cron"
|
name = "deno_cron"
|
||||||
version = "0.56.0"
|
version = "0.57.0"
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "deno_crypto"
|
name = "deno_crypto"
|
||||||
version = "0.190.0"
|
version = "0.191.0"
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
|
|
@ -281,11 +281,11 @@ class Request {
|
||||||
if (signal === undefined) {
|
if (signal === undefined) {
|
||||||
const signal = newSignal();
|
const signal = newSignal();
|
||||||
this[_signalCache] = signal;
|
this[_signalCache] = signal;
|
||||||
return signal;
|
this[_request].onCancel?.(() => {
|
||||||
}
|
|
||||||
|
|
||||||
if (!signal.aborted && this[_request].isCancelled) {
|
|
||||||
signal[signalAbort](signalAbortError);
|
signal[signalAbort](signalAbortError);
|
||||||
|
});
|
||||||
|
|
||||||
|
return signal;
|
||||||
}
|
}
|
||||||
|
|
||||||
return signal;
|
return signal;
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "deno_fetch"
|
name = "deno_fetch"
|
||||||
version = "0.200.0"
|
version = "0.201.0"
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "deno_ffi"
|
name = "deno_ffi"
|
||||||
version = "0.163.0"
|
version = "0.164.0"
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "deno_fs"
|
name = "deno_fs"
|
||||||
version = "0.86.0"
|
version = "0.87.0"
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
|
|
@ -11,10 +11,10 @@ import {
|
||||||
op_http_cancel,
|
op_http_cancel,
|
||||||
op_http_close,
|
op_http_close,
|
||||||
op_http_close_after_finish,
|
op_http_close_after_finish,
|
||||||
op_http_get_request_cancelled,
|
|
||||||
op_http_get_request_headers,
|
op_http_get_request_headers,
|
||||||
op_http_get_request_method_and_url,
|
op_http_get_request_method_and_url,
|
||||||
op_http_read_request_body,
|
op_http_read_request_body,
|
||||||
|
op_http_request_on_cancel,
|
||||||
op_http_serve,
|
op_http_serve,
|
||||||
op_http_serve_on,
|
op_http_serve_on,
|
||||||
op_http_set_promise_complete,
|
op_http_set_promise_complete,
|
||||||
|
@ -375,11 +375,16 @@ class InnerRequest {
|
||||||
return this.#external;
|
return this.#external;
|
||||||
}
|
}
|
||||||
|
|
||||||
get isCancelled() {
|
onCancel(callback) {
|
||||||
if (this.#external === null) {
|
if (this.#external === null) {
|
||||||
return true;
|
callback();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
return op_http_get_request_cancelled(this.#external);
|
|
||||||
|
PromisePrototypeThen(
|
||||||
|
op_http_request_on_cancel(this.#external),
|
||||||
|
callback,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "deno_http"
|
name = "deno_http"
|
||||||
version = "0.174.0"
|
version = "0.175.0"
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
|
|
@ -564,6 +564,7 @@ fn is_request_compressible(
|
||||||
match accept_encoding.to_str() {
|
match accept_encoding.to_str() {
|
||||||
// Firefox and Chrome send this -- no need to parse
|
// Firefox and Chrome send this -- no need to parse
|
||||||
Ok("gzip, deflate, br") => return Compression::Brotli,
|
Ok("gzip, deflate, br") => return Compression::Brotli,
|
||||||
|
Ok("gzip, deflate, br, zstd") => return Compression::Brotli,
|
||||||
Ok("gzip") => return Compression::GZip,
|
Ok("gzip") => return Compression::GZip,
|
||||||
Ok("br") => return Compression::Brotli,
|
Ok("br") => return Compression::Brotli,
|
||||||
_ => (),
|
_ => (),
|
||||||
|
@ -708,6 +709,19 @@ pub fn op_http_get_request_cancelled(external: *const c_void) -> bool {
|
||||||
http.cancelled()
|
http.cancelled()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[op2(async)]
|
||||||
|
pub async fn op_http_request_on_cancel(external: *const c_void) {
|
||||||
|
let http =
|
||||||
|
// SAFETY: op is called with external.
|
||||||
|
unsafe { clone_external!(external, "op_http_request_on_cancel") };
|
||||||
|
let (tx, rx) = tokio::sync::oneshot::channel();
|
||||||
|
|
||||||
|
http.on_cancel(tx);
|
||||||
|
drop(http);
|
||||||
|
|
||||||
|
rx.await.ok();
|
||||||
|
}
|
||||||
|
|
||||||
/// Returned promise resolves when body streaming finishes.
|
/// Returned promise resolves when body streaming finishes.
|
||||||
/// Call [`op_http_close_after_finish`] when done with the external.
|
/// Call [`op_http_close_after_finish`] when done with the external.
|
||||||
#[op2(async)]
|
#[op2(async)]
|
||||||
|
|
|
@ -112,6 +112,7 @@ deno_core::extension!(
|
||||||
http_next::op_http_close_after_finish,
|
http_next::op_http_close_after_finish,
|
||||||
http_next::op_http_get_request_header,
|
http_next::op_http_get_request_header,
|
||||||
http_next::op_http_get_request_headers,
|
http_next::op_http_get_request_headers,
|
||||||
|
http_next::op_http_request_on_cancel,
|
||||||
http_next::op_http_get_request_method_and_url<HTTP>,
|
http_next::op_http_get_request_method_and_url<HTTP>,
|
||||||
http_next::op_http_get_request_cancelled,
|
http_next::op_http_get_request_cancelled,
|
||||||
http_next::op_http_read_request_body,
|
http_next::op_http_read_request_body,
|
||||||
|
|
|
@ -27,6 +27,7 @@ use std::rc::Rc;
|
||||||
use std::task::Context;
|
use std::task::Context;
|
||||||
use std::task::Poll;
|
use std::task::Poll;
|
||||||
use std::task::Waker;
|
use std::task::Waker;
|
||||||
|
use tokio::sync::oneshot;
|
||||||
|
|
||||||
pub type Request = hyper::Request<Incoming>;
|
pub type Request = hyper::Request<Incoming>;
|
||||||
pub type Response = hyper::Response<HttpRecordResponse>;
|
pub type Response = hyper::Response<HttpRecordResponse>;
|
||||||
|
@ -211,6 +212,7 @@ pub struct UpgradeUnavailableError;
|
||||||
|
|
||||||
struct HttpRecordInner {
|
struct HttpRecordInner {
|
||||||
server_state: SignallingRc<HttpServerState>,
|
server_state: SignallingRc<HttpServerState>,
|
||||||
|
closed_channel: Option<oneshot::Sender<()>>,
|
||||||
request_info: HttpConnectionProperties,
|
request_info: HttpConnectionProperties,
|
||||||
request_parts: http::request::Parts,
|
request_parts: http::request::Parts,
|
||||||
request_body: Option<RequestBodyState>,
|
request_body: Option<RequestBodyState>,
|
||||||
|
@ -276,6 +278,7 @@ impl HttpRecord {
|
||||||
response_body_finished: false,
|
response_body_finished: false,
|
||||||
response_body_waker: None,
|
response_body_waker: None,
|
||||||
trailers: None,
|
trailers: None,
|
||||||
|
closed_channel: None,
|
||||||
been_dropped: false,
|
been_dropped: false,
|
||||||
finished: false,
|
finished: false,
|
||||||
needs_close_after_finish: false,
|
needs_close_after_finish: false,
|
||||||
|
@ -312,6 +315,10 @@ impl HttpRecord {
|
||||||
RefMut::map(self.self_mut(), |inner| &mut inner.needs_close_after_finish)
|
RefMut::map(self.self_mut(), |inner| &mut inner.needs_close_after_finish)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn on_cancel(&self, sender: oneshot::Sender<()>) {
|
||||||
|
self.self_mut().closed_channel = Some(sender);
|
||||||
|
}
|
||||||
|
|
||||||
fn recycle(self: Rc<Self>) {
|
fn recycle(self: Rc<Self>) {
|
||||||
assert!(
|
assert!(
|
||||||
Rc::strong_count(&self) == 1,
|
Rc::strong_count(&self) == 1,
|
||||||
|
@ -390,6 +397,9 @@ impl HttpRecord {
|
||||||
inner.been_dropped = true;
|
inner.been_dropped = true;
|
||||||
// The request body might include actual resources.
|
// The request body might include actual resources.
|
||||||
inner.request_body.take();
|
inner.request_body.take();
|
||||||
|
if let Some(closed_channel) = inner.closed_channel.take() {
|
||||||
|
let _ = closed_channel.send(());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Complete this record, potentially expunging it if it is fully complete (ie: cancelled as well).
|
/// Complete this record, potentially expunging it if it is fully complete (ie: cancelled as well).
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "deno_io"
|
name = "deno_io"
|
||||||
version = "0.86.0"
|
version = "0.87.0"
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "deno_kv"
|
name = "deno_kv"
|
||||||
version = "0.84.0"
|
version = "0.85.0"
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
|
|
@ -1,16 +1,17 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub struct KvConfig {
|
pub struct KvConfig {
|
||||||
pub(crate) max_write_key_size_bytes: usize,
|
pub max_write_key_size_bytes: usize,
|
||||||
pub(crate) max_read_key_size_bytes: usize,
|
pub max_read_key_size_bytes: usize,
|
||||||
pub(crate) max_value_size_bytes: usize,
|
pub max_value_size_bytes: usize,
|
||||||
pub(crate) max_read_ranges: usize,
|
pub max_read_ranges: usize,
|
||||||
pub(crate) max_read_entries: usize,
|
pub max_read_entries: usize,
|
||||||
pub(crate) max_checks: usize,
|
pub max_checks: usize,
|
||||||
pub(crate) max_mutations: usize,
|
pub max_mutations: usize,
|
||||||
pub(crate) max_watched_keys: usize,
|
pub max_watched_keys: usize,
|
||||||
pub(crate) max_total_mutation_size_bytes: usize,
|
pub max_total_mutation_size_bytes: usize,
|
||||||
pub(crate) max_total_key_size_bytes: usize,
|
pub max_total_key_size_bytes: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl KvConfig {
|
impl KvConfig {
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "deno_napi"
|
name = "deno_napi"
|
||||||
version = "0.107.0"
|
version = "0.108.0"
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "napi_sym"
|
name = "napi_sym"
|
||||||
version = "0.106.0"
|
version = "0.107.0"
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "deno_net"
|
name = "deno_net"
|
||||||
version = "0.168.0"
|
version = "0.169.0"
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "deno_node"
|
name = "deno_node"
|
||||||
version = "0.113.0"
|
version = "0.114.0"
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { primordials } from "ext:core/mod.js";
|
import { primordials } from "ext:core/mod.js";
|
||||||
const { JSONStringify, SymbolFor } = primordials;
|
const { JSONStringify, SafeArrayIterator, SymbolFor } = primordials;
|
||||||
import { format, inspect } from "ext:deno_node/internal/util/inspect.mjs";
|
import { format, inspect } from "ext:deno_node/internal/util/inspect.mjs";
|
||||||
import { codes } from "ext:deno_node/internal/error_codes.ts";
|
import { codes } from "ext:deno_node/internal/error_codes.ts";
|
||||||
import {
|
import {
|
||||||
|
@ -1874,6 +1874,11 @@ export class ERR_SOCKET_CLOSED extends NodeError {
|
||||||
super("ERR_SOCKET_CLOSED", `Socket is closed`);
|
super("ERR_SOCKET_CLOSED", `Socket is closed`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
export class ERR_SOCKET_CONNECTION_TIMEOUT extends NodeError {
|
||||||
|
constructor() {
|
||||||
|
super("ERR_SOCKET_CONNECTION_TIMEOUT", `Socket connection timeout`);
|
||||||
|
}
|
||||||
|
}
|
||||||
export class ERR_SOCKET_DGRAM_IS_CONNECTED extends NodeError {
|
export class ERR_SOCKET_DGRAM_IS_CONNECTED extends NodeError {
|
||||||
constructor() {
|
constructor() {
|
||||||
super("ERR_SOCKET_DGRAM_IS_CONNECTED", `Already connected`);
|
super("ERR_SOCKET_DGRAM_IS_CONNECTED", `Already connected`);
|
||||||
|
@ -2633,11 +2638,30 @@ export function aggregateTwoErrors(
|
||||||
}
|
}
|
||||||
return innerError || outerError;
|
return innerError || outerError;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class NodeAggregateError extends AggregateError {
|
||||||
|
code: string;
|
||||||
|
constructor(errors, message) {
|
||||||
|
super(new SafeArrayIterator(errors), message);
|
||||||
|
this.code = errors[0]?.code;
|
||||||
|
}
|
||||||
|
|
||||||
|
get [kIsNodeError]() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// deno-lint-ignore adjacent-overload-signatures
|
||||||
|
get ["constructor"]() {
|
||||||
|
return AggregateError;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
codes.ERR_IPC_CHANNEL_CLOSED = ERR_IPC_CHANNEL_CLOSED;
|
codes.ERR_IPC_CHANNEL_CLOSED = ERR_IPC_CHANNEL_CLOSED;
|
||||||
codes.ERR_INVALID_ARG_TYPE = ERR_INVALID_ARG_TYPE;
|
codes.ERR_INVALID_ARG_TYPE = ERR_INVALID_ARG_TYPE;
|
||||||
codes.ERR_INVALID_ARG_VALUE = ERR_INVALID_ARG_VALUE;
|
codes.ERR_INVALID_ARG_VALUE = ERR_INVALID_ARG_VALUE;
|
||||||
codes.ERR_OUT_OF_RANGE = ERR_OUT_OF_RANGE;
|
codes.ERR_OUT_OF_RANGE = ERR_OUT_OF_RANGE;
|
||||||
codes.ERR_SOCKET_BAD_PORT = ERR_SOCKET_BAD_PORT;
|
codes.ERR_SOCKET_BAD_PORT = ERR_SOCKET_BAD_PORT;
|
||||||
|
codes.ERR_SOCKET_CONNECTION_TIMEOUT = ERR_SOCKET_CONNECTION_TIMEOUT;
|
||||||
codes.ERR_BUFFER_OUT_OF_BOUNDS = ERR_BUFFER_OUT_OF_BOUNDS;
|
codes.ERR_BUFFER_OUT_OF_BOUNDS = ERR_BUFFER_OUT_OF_BOUNDS;
|
||||||
codes.ERR_UNKNOWN_ENCODING = ERR_UNKNOWN_ENCODING;
|
codes.ERR_UNKNOWN_ENCODING = ERR_UNKNOWN_ENCODING;
|
||||||
codes.ERR_PARSE_ARGS_INVALID_OPTION_VALUE = ERR_PARSE_ARGS_INVALID_OPTION_VALUE;
|
codes.ERR_PARSE_ARGS_INVALID_OPTION_VALUE = ERR_PARSE_ARGS_INVALID_OPTION_VALUE;
|
||||||
|
|
|
@ -95,4 +95,5 @@ export function makeSyncWrite(fd: number) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const kReinitializeHandle = Symbol("kReinitializeHandle");
|
||||||
export const normalizedArgsSymbol = Symbol("normalizedArgs");
|
export const normalizedArgsSymbol = Symbol("normalizedArgs");
|
||||||
|
|
|
@ -530,10 +530,12 @@ export function mapSysErrnoToUvErrno(sysErrno: number): number {
|
||||||
|
|
||||||
export const UV_EAI_MEMORY = codeMap.get("EAI_MEMORY")!;
|
export const UV_EAI_MEMORY = codeMap.get("EAI_MEMORY")!;
|
||||||
export const UV_EBADF = codeMap.get("EBADF")!;
|
export const UV_EBADF = codeMap.get("EBADF")!;
|
||||||
|
export const UV_ECANCELED = codeMap.get("ECANCELED")!;
|
||||||
export const UV_EEXIST = codeMap.get("EEXIST");
|
export const UV_EEXIST = codeMap.get("EEXIST");
|
||||||
export const UV_EINVAL = codeMap.get("EINVAL")!;
|
export const UV_EINVAL = codeMap.get("EINVAL")!;
|
||||||
export const UV_ENOENT = codeMap.get("ENOENT");
|
export const UV_ENOENT = codeMap.get("ENOENT");
|
||||||
export const UV_ENOTSOCK = codeMap.get("ENOTSOCK")!;
|
export const UV_ENOTSOCK = codeMap.get("ENOTSOCK")!;
|
||||||
|
export const UV_ETIMEDOUT = codeMap.get("ETIMEDOUT")!;
|
||||||
export const UV_UNKNOWN = codeMap.get("UNKNOWN")!;
|
export const UV_UNKNOWN = codeMap.get("UNKNOWN")!;
|
||||||
|
|
||||||
export function errname(errno: number): string {
|
export function errname(errno: number): string {
|
||||||
|
|
|
@ -31,6 +31,7 @@ import {
|
||||||
isIP,
|
isIP,
|
||||||
isIPv4,
|
isIPv4,
|
||||||
isIPv6,
|
isIPv6,
|
||||||
|
kReinitializeHandle,
|
||||||
normalizedArgsSymbol,
|
normalizedArgsSymbol,
|
||||||
} from "ext:deno_node/internal/net.ts";
|
} from "ext:deno_node/internal/net.ts";
|
||||||
import { Duplex } from "node:stream";
|
import { Duplex } from "node:stream";
|
||||||
|
@ -50,9 +51,11 @@ import {
|
||||||
ERR_SERVER_ALREADY_LISTEN,
|
ERR_SERVER_ALREADY_LISTEN,
|
||||||
ERR_SERVER_NOT_RUNNING,
|
ERR_SERVER_NOT_RUNNING,
|
||||||
ERR_SOCKET_CLOSED,
|
ERR_SOCKET_CLOSED,
|
||||||
|
ERR_SOCKET_CONNECTION_TIMEOUT,
|
||||||
errnoException,
|
errnoException,
|
||||||
exceptionWithHostPort,
|
exceptionWithHostPort,
|
||||||
genericNodeError,
|
genericNodeError,
|
||||||
|
NodeAggregateError,
|
||||||
uvExceptionWithHostPort,
|
uvExceptionWithHostPort,
|
||||||
} from "ext:deno_node/internal/errors.ts";
|
} from "ext:deno_node/internal/errors.ts";
|
||||||
import type { ErrnoException } from "ext:deno_node/internal/errors.ts";
|
import type { ErrnoException } from "ext:deno_node/internal/errors.ts";
|
||||||
|
@ -80,6 +83,7 @@ import { Buffer } from "node:buffer";
|
||||||
import type { LookupOneOptions } from "ext:deno_node/internal/dns/utils.ts";
|
import type { LookupOneOptions } from "ext:deno_node/internal/dns/utils.ts";
|
||||||
import {
|
import {
|
||||||
validateAbortSignal,
|
validateAbortSignal,
|
||||||
|
validateBoolean,
|
||||||
validateFunction,
|
validateFunction,
|
||||||
validateInt32,
|
validateInt32,
|
||||||
validateNumber,
|
validateNumber,
|
||||||
|
@ -100,13 +104,25 @@ import { ShutdownWrap } from "ext:deno_node/internal_binding/stream_wrap.ts";
|
||||||
import { assert } from "ext:deno_node/_util/asserts.ts";
|
import { assert } from "ext:deno_node/_util/asserts.ts";
|
||||||
import { isWindows } from "ext:deno_node/_util/os.ts";
|
import { isWindows } from "ext:deno_node/_util/os.ts";
|
||||||
import { ADDRCONFIG, lookup as dnsLookup } from "node:dns";
|
import { ADDRCONFIG, lookup as dnsLookup } from "node:dns";
|
||||||
import { codeMap } from "ext:deno_node/internal_binding/uv.ts";
|
import {
|
||||||
|
codeMap,
|
||||||
|
UV_ECANCELED,
|
||||||
|
UV_ETIMEDOUT,
|
||||||
|
} from "ext:deno_node/internal_binding/uv.ts";
|
||||||
import { guessHandleType } from "ext:deno_node/internal_binding/util.ts";
|
import { guessHandleType } from "ext:deno_node/internal_binding/util.ts";
|
||||||
import { debuglog } from "ext:deno_node/internal/util/debuglog.ts";
|
import { debuglog } from "ext:deno_node/internal/util/debuglog.ts";
|
||||||
import type { DuplexOptions } from "ext:deno_node/_stream.d.ts";
|
import type { DuplexOptions } from "ext:deno_node/_stream.d.ts";
|
||||||
import type { BufferEncoding } from "ext:deno_node/_global.d.ts";
|
import type { BufferEncoding } from "ext:deno_node/_global.d.ts";
|
||||||
import type { Abortable } from "ext:deno_node/_events.d.ts";
|
import type { Abortable } from "ext:deno_node/_events.d.ts";
|
||||||
import { channel } from "node:diagnostics_channel";
|
import { channel } from "node:diagnostics_channel";
|
||||||
|
import { primordials } from "ext:core/mod.js";
|
||||||
|
|
||||||
|
const {
|
||||||
|
ArrayPrototypeIncludes,
|
||||||
|
ArrayPrototypePush,
|
||||||
|
FunctionPrototypeBind,
|
||||||
|
MathMax,
|
||||||
|
} = primordials;
|
||||||
|
|
||||||
let debug = debuglog("net", (fn) => {
|
let debug = debuglog("net", (fn) => {
|
||||||
debug = fn;
|
debug = fn;
|
||||||
|
@ -120,6 +136,9 @@ const kBytesWritten = Symbol("kBytesWritten");
|
||||||
const DEFAULT_IPV4_ADDR = "0.0.0.0";
|
const DEFAULT_IPV4_ADDR = "0.0.0.0";
|
||||||
const DEFAULT_IPV6_ADDR = "::";
|
const DEFAULT_IPV6_ADDR = "::";
|
||||||
|
|
||||||
|
let autoSelectFamilyDefault = true;
|
||||||
|
let autoSelectFamilyAttemptTimeoutDefault = 250;
|
||||||
|
|
||||||
type Handle = TCP | Pipe;
|
type Handle = TCP | Pipe;
|
||||||
|
|
||||||
interface HandleOptions {
|
interface HandleOptions {
|
||||||
|
@ -214,6 +233,8 @@ interface TcpSocketConnectOptions extends ConnectOptions {
|
||||||
hints?: number;
|
hints?: number;
|
||||||
family?: number;
|
family?: number;
|
||||||
lookup?: LookupFunction;
|
lookup?: LookupFunction;
|
||||||
|
autoSelectFamily?: boolean | undefined;
|
||||||
|
autoSelectFamilyAttemptTimeout?: number | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IpcSocketConnectOptions extends ConnectOptions {
|
interface IpcSocketConnectOptions extends ConnectOptions {
|
||||||
|
@ -316,12 +337,6 @@ export function _normalizeArgs(args: unknown[]): NormalizedArgs {
|
||||||
return arr;
|
return arr;
|
||||||
}
|
}
|
||||||
|
|
||||||
function _isTCPConnectWrap(
|
|
||||||
req: TCPConnectWrap | PipeConnectWrap,
|
|
||||||
): req is TCPConnectWrap {
|
|
||||||
return "localAddress" in req && "localPort" in req;
|
|
||||||
}
|
|
||||||
|
|
||||||
function _afterConnect(
|
function _afterConnect(
|
||||||
status: number,
|
status: number,
|
||||||
// deno-lint-ignore no-explicit-any
|
// deno-lint-ignore no-explicit-any
|
||||||
|
@ -372,7 +387,7 @@ function _afterConnect(
|
||||||
socket.connecting = false;
|
socket.connecting = false;
|
||||||
let details;
|
let details;
|
||||||
|
|
||||||
if (_isTCPConnectWrap(req)) {
|
if (req.localAddress && req.localPort) {
|
||||||
details = req.localAddress + ":" + req.localPort;
|
details = req.localAddress + ":" + req.localPort;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -384,7 +399,7 @@ function _afterConnect(
|
||||||
details,
|
details,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (_isTCPConnectWrap(req)) {
|
if (details) {
|
||||||
ex.localAddress = req.localAddress;
|
ex.localAddress = req.localAddress;
|
||||||
ex.localPort = req.localPort;
|
ex.localPort = req.localPort;
|
||||||
}
|
}
|
||||||
|
@ -393,6 +408,107 @@ function _afterConnect(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function _createConnectionError(req, status) {
|
||||||
|
let details;
|
||||||
|
|
||||||
|
if (req.localAddress && req.localPort) {
|
||||||
|
details = req.localAddress + ":" + req.localPort;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ex = exceptionWithHostPort(
|
||||||
|
status,
|
||||||
|
"connect",
|
||||||
|
req.address,
|
||||||
|
req.port,
|
||||||
|
details,
|
||||||
|
);
|
||||||
|
if (details) {
|
||||||
|
ex.localAddress = req.localAddress;
|
||||||
|
ex.localPort = req.localPort;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
function _afterConnectMultiple(
|
||||||
|
context,
|
||||||
|
current,
|
||||||
|
status,
|
||||||
|
handle,
|
||||||
|
req,
|
||||||
|
readable,
|
||||||
|
writable,
|
||||||
|
) {
|
||||||
|
debug(
|
||||||
|
"connect/multiple: connection attempt to %s:%s completed with status %s",
|
||||||
|
req.address,
|
||||||
|
req.port,
|
||||||
|
status,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Make sure another connection is not spawned
|
||||||
|
clearTimeout(context[kTimeout]);
|
||||||
|
|
||||||
|
// One of the connection has completed and correctly dispatched but after timeout, ignore this one
|
||||||
|
if (status === 0 && current !== context.current - 1) {
|
||||||
|
debug(
|
||||||
|
"connect/multiple: ignoring successful but timedout connection to %s:%s",
|
||||||
|
req.address,
|
||||||
|
req.port,
|
||||||
|
);
|
||||||
|
handle.close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const self = context.socket;
|
||||||
|
|
||||||
|
// Some error occurred, add to the list of exceptions
|
||||||
|
if (status !== 0) {
|
||||||
|
const ex = _createConnectionError(req, status);
|
||||||
|
ArrayPrototypePush(context.errors, ex);
|
||||||
|
|
||||||
|
self.emit(
|
||||||
|
"connectionAttemptFailed",
|
||||||
|
req.address,
|
||||||
|
req.port,
|
||||||
|
req.addressType,
|
||||||
|
ex,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Try the next address, unless we were aborted
|
||||||
|
if (context.socket.connecting) {
|
||||||
|
_internalConnectMultiple(context, status === UV_ECANCELED);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_afterConnect(status, self._handle, req, readable, writable);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _internalConnectMultipleTimeout(context, req, handle) {
|
||||||
|
debug(
|
||||||
|
"connect/multiple: connection to %s:%s timed out",
|
||||||
|
req.address,
|
||||||
|
req.port,
|
||||||
|
);
|
||||||
|
context.socket.emit(
|
||||||
|
"connectionAttemptTimeout",
|
||||||
|
req.address,
|
||||||
|
req.port,
|
||||||
|
req.addressType,
|
||||||
|
);
|
||||||
|
|
||||||
|
req.oncomplete = undefined;
|
||||||
|
ArrayPrototypePush(context.errors, _createConnectionError(req, UV_ETIMEDOUT));
|
||||||
|
handle.close();
|
||||||
|
|
||||||
|
// Try the next address, unless we were aborted
|
||||||
|
if (context.socket.connecting) {
|
||||||
|
_internalConnectMultiple(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function _checkBindError(err: number, port: number, handle: TCP) {
|
function _checkBindError(err: number, port: number, handle: TCP) {
|
||||||
// EADDRINUSE may not be reported until we call `listen()` or `connect()`.
|
// EADDRINUSE may not be reported until we call `listen()` or `connect()`.
|
||||||
// To complicate matters, a failed `bind()` followed by `listen()` or `connect()`
|
// To complicate matters, a failed `bind()` followed by `listen()` or `connect()`
|
||||||
|
@ -495,6 +611,131 @@ function _internalConnect(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function _internalConnectMultiple(context, canceled?: boolean) {
|
||||||
|
clearTimeout(context[kTimeout]);
|
||||||
|
const self = context.socket;
|
||||||
|
|
||||||
|
// We were requested to abort. Stop all operations
|
||||||
|
if (self._aborted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// All connections have been tried without success, destroy with error
|
||||||
|
if (canceled || context.current === context.addresses.length) {
|
||||||
|
if (context.errors.length === 0) {
|
||||||
|
self.destroy(new ERR_SOCKET_CONNECTION_TIMEOUT());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.destroy(new NodeAggregateError(context.errors));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(self.connecting);
|
||||||
|
|
||||||
|
const current = context.current++;
|
||||||
|
|
||||||
|
if (current > 0) {
|
||||||
|
self[kReinitializeHandle](new TCP(TCPConstants.SOCKET));
|
||||||
|
}
|
||||||
|
|
||||||
|
const { localPort, port, flags } = context;
|
||||||
|
const { address, family: addressType } = context.addresses[current];
|
||||||
|
let localAddress;
|
||||||
|
let err;
|
||||||
|
|
||||||
|
if (localPort) {
|
||||||
|
if (addressType === 4) {
|
||||||
|
localAddress = DEFAULT_IPV4_ADDR;
|
||||||
|
err = self._handle.bind(localAddress, localPort);
|
||||||
|
} else { // addressType === 6
|
||||||
|
localAddress = DEFAULT_IPV6_ADDR;
|
||||||
|
err = self._handle.bind6(localAddress, localPort, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
debug(
|
||||||
|
"connect/multiple: binding to localAddress: %s and localPort: %d (addressType: %d)",
|
||||||
|
localAddress,
|
||||||
|
localPort,
|
||||||
|
addressType,
|
||||||
|
);
|
||||||
|
|
||||||
|
err = _checkBindError(err, localPort, self._handle);
|
||||||
|
if (err) {
|
||||||
|
ArrayPrototypePush(
|
||||||
|
context.errors,
|
||||||
|
exceptionWithHostPort(err, "bind", localAddress, localPort),
|
||||||
|
);
|
||||||
|
_internalConnectMultiple(context);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
debug(
|
||||||
|
"connect/multiple: attempting to connect to %s:%d (addressType: %d)",
|
||||||
|
address,
|
||||||
|
port,
|
||||||
|
addressType,
|
||||||
|
);
|
||||||
|
self.emit("connectionAttempt", address, port, addressType);
|
||||||
|
|
||||||
|
const req = new TCPConnectWrap();
|
||||||
|
req.oncomplete = FunctionPrototypeBind(
|
||||||
|
_afterConnectMultiple,
|
||||||
|
undefined,
|
||||||
|
context,
|
||||||
|
current,
|
||||||
|
);
|
||||||
|
req.address = address;
|
||||||
|
req.port = port;
|
||||||
|
req.localAddress = localAddress;
|
||||||
|
req.localPort = localPort;
|
||||||
|
req.addressType = addressType;
|
||||||
|
|
||||||
|
ArrayPrototypePush(
|
||||||
|
self.autoSelectFamilyAttemptedAddresses,
|
||||||
|
`${address}:${port}`,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (addressType === 4) {
|
||||||
|
err = self._handle.connect(req, address, port);
|
||||||
|
} else {
|
||||||
|
err = self._handle.connect6(req, address, port);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
const sockname = self._getsockname();
|
||||||
|
let details;
|
||||||
|
|
||||||
|
if (sockname) {
|
||||||
|
details = sockname.address + ":" + sockname.port;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ex = exceptionWithHostPort(err, "connect", address, port, details);
|
||||||
|
ArrayPrototypePush(context.errors, ex);
|
||||||
|
|
||||||
|
self.emit("connectionAttemptFailed", address, port, addressType, ex);
|
||||||
|
_internalConnectMultiple(context);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (current < context.addresses.length - 1) {
|
||||||
|
debug(
|
||||||
|
"connect/multiple: setting the attempt timeout to %d ms",
|
||||||
|
context.timeout,
|
||||||
|
);
|
||||||
|
|
||||||
|
// If the attempt has not returned an error, start the connection timer
|
||||||
|
context[kTimeout] = setTimeout(
|
||||||
|
_internalConnectMultipleTimeout,
|
||||||
|
context.timeout,
|
||||||
|
context,
|
||||||
|
req,
|
||||||
|
self._handle,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Provide a better error message when we call end() as a result
|
// Provide a better error message when we call end() as a result
|
||||||
// of the other side sending a FIN. The standard "write after end"
|
// of the other side sending a FIN. The standard "write after end"
|
||||||
// is overly vague, and makes it seem like the user's code is to blame.
|
// is overly vague, and makes it seem like the user's code is to blame.
|
||||||
|
@ -597,7 +838,7 @@ function _lookupAndConnect(
|
||||||
) {
|
) {
|
||||||
const { localAddress, localPort } = options;
|
const { localAddress, localPort } = options;
|
||||||
const host = options.host || "localhost";
|
const host = options.host || "localhost";
|
||||||
let { port } = options;
|
let { port, autoSelectFamilyAttemptTimeout, autoSelectFamily } = options;
|
||||||
|
|
||||||
if (localAddress && !isIP(localAddress)) {
|
if (localAddress && !isIP(localAddress)) {
|
||||||
throw new ERR_INVALID_IP_ADDRESS(localAddress);
|
throw new ERR_INVALID_IP_ADDRESS(localAddress);
|
||||||
|
@ -621,6 +862,22 @@ function _lookupAndConnect(
|
||||||
|
|
||||||
port |= 0;
|
port |= 0;
|
||||||
|
|
||||||
|
if (autoSelectFamily != null) {
|
||||||
|
validateBoolean(autoSelectFamily, "options.autoSelectFamily");
|
||||||
|
} else {
|
||||||
|
autoSelectFamily = autoSelectFamilyDefault;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (autoSelectFamilyAttemptTimeout !== undefined) {
|
||||||
|
validateInt32(autoSelectFamilyAttemptTimeout);
|
||||||
|
|
||||||
|
if (autoSelectFamilyAttemptTimeout < 10) {
|
||||||
|
autoSelectFamilyAttemptTimeout = 10;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
autoSelectFamilyAttemptTimeout = autoSelectFamilyAttemptTimeoutDefault;
|
||||||
|
}
|
||||||
|
|
||||||
// If host is an IP, skip performing a lookup
|
// If host is an IP, skip performing a lookup
|
||||||
const addressType = isIP(host);
|
const addressType = isIP(host);
|
||||||
if (addressType) {
|
if (addressType) {
|
||||||
|
@ -649,6 +906,7 @@ function _lookupAndConnect(
|
||||||
const dnsOpts = {
|
const dnsOpts = {
|
||||||
family: options.family,
|
family: options.family,
|
||||||
hints: options.hints || 0,
|
hints: options.hints || 0,
|
||||||
|
all: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (
|
if (
|
||||||
|
@ -665,6 +923,31 @@ function _lookupAndConnect(
|
||||||
self._host = host;
|
self._host = host;
|
||||||
const lookup = options.lookup || dnsLookup;
|
const lookup = options.lookup || dnsLookup;
|
||||||
|
|
||||||
|
if (
|
||||||
|
dnsOpts.family !== 4 && dnsOpts.family !== 6 && !localAddress &&
|
||||||
|
autoSelectFamily
|
||||||
|
) {
|
||||||
|
debug("connect: autodetecting");
|
||||||
|
|
||||||
|
dnsOpts.all = true;
|
||||||
|
defaultTriggerAsyncIdScope(self[asyncIdSymbol], function () {
|
||||||
|
_lookupAndConnectMultiple(
|
||||||
|
self,
|
||||||
|
asyncIdSymbol,
|
||||||
|
lookup,
|
||||||
|
host,
|
||||||
|
options,
|
||||||
|
dnsOpts,
|
||||||
|
port,
|
||||||
|
localAddress,
|
||||||
|
localPort,
|
||||||
|
autoSelectFamilyAttemptTimeout,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
defaultTriggerAsyncIdScope(self[asyncIdSymbol], function () {
|
defaultTriggerAsyncIdScope(self[asyncIdSymbol], function () {
|
||||||
lookup(
|
lookup(
|
||||||
host,
|
host,
|
||||||
|
@ -719,6 +1002,143 @@ function _lookupAndConnect(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function _lookupAndConnectMultiple(
|
||||||
|
self: Socket,
|
||||||
|
asyncIdSymbol: number,
|
||||||
|
// deno-lint-ignore no-explicit-any
|
||||||
|
lookup: any,
|
||||||
|
host: string,
|
||||||
|
options: TcpSocketConnectOptions,
|
||||||
|
dnsopts,
|
||||||
|
port: number,
|
||||||
|
localAddress: string,
|
||||||
|
localPort: number,
|
||||||
|
timeout: number | undefined,
|
||||||
|
) {
|
||||||
|
defaultTriggerAsyncIdScope(self[asyncIdSymbol], function emitLookup() {
|
||||||
|
lookup(host, dnsopts, function emitLookup(err, addresses) {
|
||||||
|
// It's possible we were destroyed while looking this up.
|
||||||
|
// XXX it would be great if we could cancel the promise returned by
|
||||||
|
// the look up.
|
||||||
|
if (!self.connecting) {
|
||||||
|
return;
|
||||||
|
} else if (err) {
|
||||||
|
self.emit("lookup", err, undefined, undefined, host);
|
||||||
|
|
||||||
|
// net.createConnection() creates a net.Socket object and immediately
|
||||||
|
// calls net.Socket.connect() on it (that's us). There are no event
|
||||||
|
// listeners registered yet so defer the error event to the next tick.
|
||||||
|
nextTick(_connectErrorNT, self, err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter addresses by only keeping the one which are either IPv4 or IPV6.
|
||||||
|
// The first valid address determines which group has preference on the
|
||||||
|
// alternate family sorting which happens later.
|
||||||
|
const validAddresses = [[], []];
|
||||||
|
const validIps = [[], []];
|
||||||
|
let destinations;
|
||||||
|
for (let i = 0, l = addresses.length; i < l; i++) {
|
||||||
|
const address = addresses[i];
|
||||||
|
const { address: ip, family: addressType } = address;
|
||||||
|
self.emit("lookup", err, ip, addressType, host);
|
||||||
|
// It's possible we were destroyed while looking this up.
|
||||||
|
if (!self.connecting) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (isIP(ip) && (addressType === 4 || addressType === 6)) {
|
||||||
|
destinations ||= addressType === 6 ? { 6: 0, 4: 1 } : { 4: 0, 6: 1 };
|
||||||
|
|
||||||
|
const destination = destinations[addressType];
|
||||||
|
|
||||||
|
// Only try an address once
|
||||||
|
if (!ArrayPrototypeIncludes(validIps[destination], ip)) {
|
||||||
|
ArrayPrototypePush(validAddresses[destination], address);
|
||||||
|
ArrayPrototypePush(validIps[destination], ip);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// When no AAAA or A records are available, fail on the first one
|
||||||
|
if (!validAddresses[0].length && !validAddresses[1].length) {
|
||||||
|
const { address: firstIp, family: firstAddressType } = addresses[0];
|
||||||
|
|
||||||
|
if (!isIP(firstIp)) {
|
||||||
|
err = new ERR_INVALID_IP_ADDRESS(firstIp);
|
||||||
|
nextTick(_connectErrorNT, self, err);
|
||||||
|
} else if (firstAddressType !== 4 && firstAddressType !== 6) {
|
||||||
|
err = new ERR_INVALID_ADDRESS_FAMILY(
|
||||||
|
firstAddressType,
|
||||||
|
options.host,
|
||||||
|
options.port,
|
||||||
|
);
|
||||||
|
nextTick(_connectErrorNT, self, err);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort addresses alternating families
|
||||||
|
const toAttempt = [];
|
||||||
|
for (
|
||||||
|
let i = 0,
|
||||||
|
l = MathMax(validAddresses[0].length, validAddresses[1].length);
|
||||||
|
i < l;
|
||||||
|
i++
|
||||||
|
) {
|
||||||
|
if (i in validAddresses[0]) {
|
||||||
|
ArrayPrototypePush(toAttempt, validAddresses[0][i]);
|
||||||
|
}
|
||||||
|
if (i in validAddresses[1]) {
|
||||||
|
ArrayPrototypePush(toAttempt, validAddresses[1][i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (toAttempt.length === 1) {
|
||||||
|
debug(
|
||||||
|
"connect/multiple: only one address found, switching back to single connection",
|
||||||
|
);
|
||||||
|
const { address: ip, family: addressType } = toAttempt[0];
|
||||||
|
|
||||||
|
self._unrefTimer();
|
||||||
|
defaultTriggerAsyncIdScope(
|
||||||
|
self[asyncIdSymbol],
|
||||||
|
_internalConnect,
|
||||||
|
self,
|
||||||
|
ip,
|
||||||
|
port,
|
||||||
|
addressType,
|
||||||
|
localAddress,
|
||||||
|
localPort,
|
||||||
|
);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.autoSelectFamilyAttemptedAddresses = [];
|
||||||
|
debug("connect/multiple: will try the following addresses", toAttempt);
|
||||||
|
|
||||||
|
const context = {
|
||||||
|
socket: self,
|
||||||
|
addresses: toAttempt,
|
||||||
|
current: 0,
|
||||||
|
port,
|
||||||
|
localPort,
|
||||||
|
timeout,
|
||||||
|
[kTimeout]: null,
|
||||||
|
errors: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
self._unrefTimer();
|
||||||
|
defaultTriggerAsyncIdScope(
|
||||||
|
self[asyncIdSymbol],
|
||||||
|
_internalConnectMultiple,
|
||||||
|
context,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function _afterShutdown(this: ShutdownWrap<TCP>) {
|
function _afterShutdown(this: ShutdownWrap<TCP>) {
|
||||||
// deno-lint-ignore no-explicit-any
|
// deno-lint-ignore no-explicit-any
|
||||||
const self: any = this.handle[ownerSymbol];
|
const self: any = this.handle[ownerSymbol];
|
||||||
|
@ -777,6 +1197,7 @@ export class Socket extends Duplex {
|
||||||
_host: string | null = null;
|
_host: string | null = null;
|
||||||
// deno-lint-ignore no-explicit-any
|
// deno-lint-ignore no-explicit-any
|
||||||
_parent: any = null;
|
_parent: any = null;
|
||||||
|
autoSelectFamilyAttemptedAddresses: AddressInfo[] | undefined = undefined;
|
||||||
|
|
||||||
constructor(options: SocketOptions | number) {
|
constructor(options: SocketOptions | number) {
|
||||||
if (typeof options === "number") {
|
if (typeof options === "number") {
|
||||||
|
@ -1546,6 +1967,16 @@ export class Socket extends Duplex {
|
||||||
set _handle(v: Handle | null) {
|
set _handle(v: Handle | null) {
|
||||||
this[kHandle] = v;
|
this[kHandle] = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// deno-lint-ignore no-explicit-any
|
||||||
|
[kReinitializeHandle](handle: any) {
|
||||||
|
this._handle?.close();
|
||||||
|
|
||||||
|
this._handle = handle;
|
||||||
|
this._handle[ownerSymbol] = this;
|
||||||
|
|
||||||
|
_initSocketHandle(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Stream = Socket;
|
export const Stream = Socket;
|
||||||
|
@ -1593,6 +2024,33 @@ export function connect(...args: unknown[]) {
|
||||||
|
|
||||||
export const createConnection = connect;
|
export const createConnection = connect;
|
||||||
|
|
||||||
|
/** https://docs.deno.com/api/node/net/#namespace_getdefaultautoselectfamily */
|
||||||
|
export function getDefaultAutoSelectFamily() {
|
||||||
|
return autoSelectFamilyDefault;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** https://docs.deno.com/api/node/net/#namespace_setdefaultautoselectfamily */
|
||||||
|
export function setDefaultAutoSelectFamily(value: boolean) {
|
||||||
|
validateBoolean(value, "value");
|
||||||
|
autoSelectFamilyDefault = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** https://docs.deno.com/api/node/net/#namespace_getdefaultautoselectfamilyattempttimeout */
|
||||||
|
export function getDefaultAutoSelectFamilyAttemptTimeout() {
|
||||||
|
return autoSelectFamilyAttemptTimeoutDefault;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** https://docs.deno.com/api/node/net/#namespace_setdefaultautoselectfamilyattempttimeout */
|
||||||
|
export function setDefaultAutoSelectFamilyAttemptTimeout(value: number) {
|
||||||
|
validateInt32(value, "value", 1);
|
||||||
|
|
||||||
|
if (value < 10) {
|
||||||
|
value = 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
autoSelectFamilyAttemptTimeoutDefault = value;
|
||||||
|
}
|
||||||
|
|
||||||
export interface ListenOptions extends Abortable {
|
export interface ListenOptions extends Abortable {
|
||||||
fd?: number;
|
fd?: number;
|
||||||
port?: number | undefined;
|
port?: number | undefined;
|
||||||
|
@ -2478,15 +2936,19 @@ export { BlockList, isIP, isIPv4, isIPv6, SocketAddress };
|
||||||
export default {
|
export default {
|
||||||
_createServerHandle,
|
_createServerHandle,
|
||||||
_normalizeArgs,
|
_normalizeArgs,
|
||||||
isIP,
|
|
||||||
isIPv4,
|
|
||||||
isIPv6,
|
|
||||||
BlockList,
|
BlockList,
|
||||||
SocketAddress,
|
|
||||||
connect,
|
connect,
|
||||||
createConnection,
|
createConnection,
|
||||||
createServer,
|
createServer,
|
||||||
|
getDefaultAutoSelectFamily,
|
||||||
|
getDefaultAutoSelectFamilyAttemptTimeout,
|
||||||
|
isIP,
|
||||||
|
isIPv4,
|
||||||
|
isIPv6,
|
||||||
Server,
|
Server,
|
||||||
|
setDefaultAutoSelectFamily,
|
||||||
|
setDefaultAutoSelectFamilyAttemptTimeout,
|
||||||
Socket,
|
Socket,
|
||||||
|
SocketAddress,
|
||||||
Stream,
|
Stream,
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "deno_tls"
|
name = "deno_tls"
|
||||||
version = "0.163.0"
|
version = "0.164.0"
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "deno_url"
|
name = "deno_url"
|
||||||
version = "0.176.0"
|
version = "0.177.0"
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
|
|
@ -1,12 +1,9 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
import { core, primordials } from "ext:core/mod.js";
|
import { core, primordials } from "ext:core/mod.js";
|
||||||
import { op_defer, op_now } from "ext:core/ops";
|
import { op_defer } from "ext:core/ops";
|
||||||
const {
|
const {
|
||||||
Uint8Array,
|
|
||||||
Uint32Array,
|
|
||||||
PromisePrototypeThen,
|
PromisePrototypeThen,
|
||||||
TypedArrayPrototypeGetBuffer,
|
|
||||||
TypeError,
|
TypeError,
|
||||||
indirectEval,
|
indirectEval,
|
||||||
ReflectApply,
|
ReflectApply,
|
||||||
|
@ -18,13 +15,6 @@ const {
|
||||||
|
|
||||||
import * as webidl from "ext:deno_webidl/00_webidl.js";
|
import * as webidl from "ext:deno_webidl/00_webidl.js";
|
||||||
|
|
||||||
const hrU8 = new Uint8Array(8);
|
|
||||||
const hr = new Uint32Array(TypedArrayPrototypeGetBuffer(hrU8));
|
|
||||||
function opNow() {
|
|
||||||
op_now(hrU8);
|
|
||||||
return (hr[0] * 1000 + hr[1] / 1e6);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
function checkThis(thisArg) {
|
function checkThis(thisArg) {
|
||||||
|
@ -151,7 +141,6 @@ export {
|
||||||
clearInterval,
|
clearInterval,
|
||||||
clearTimeout,
|
clearTimeout,
|
||||||
defer,
|
defer,
|
||||||
opNow,
|
|
||||||
refTimer,
|
refTimer,
|
||||||
setImmediate,
|
setImmediate,
|
||||||
setInterval,
|
setInterval,
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
import { primordials } from "ext:core/mod.js";
|
import { primordials } from "ext:core/mod.js";
|
||||||
|
import { op_now, op_time_origin } from "ext:core/ops";
|
||||||
const {
|
const {
|
||||||
ArrayPrototypeFilter,
|
ArrayPrototypeFilter,
|
||||||
ArrayPrototypePush,
|
ArrayPrototypePush,
|
||||||
|
@ -10,19 +11,34 @@ const {
|
||||||
Symbol,
|
Symbol,
|
||||||
SymbolFor,
|
SymbolFor,
|
||||||
TypeError,
|
TypeError,
|
||||||
|
TypedArrayPrototypeGetBuffer,
|
||||||
|
Uint8Array,
|
||||||
|
Uint32Array,
|
||||||
} = primordials;
|
} = primordials;
|
||||||
|
|
||||||
import * as webidl from "ext:deno_webidl/00_webidl.js";
|
import * as webidl from "ext:deno_webidl/00_webidl.js";
|
||||||
import { structuredClone } from "./02_structured_clone.js";
|
import { structuredClone } from "./02_structured_clone.js";
|
||||||
import { createFilteredInspectProxy } from "ext:deno_console/01_console.js";
|
import { createFilteredInspectProxy } from "ext:deno_console/01_console.js";
|
||||||
import { EventTarget } from "./02_event.js";
|
import { EventTarget } from "./02_event.js";
|
||||||
import { opNow } from "./02_timers.js";
|
|
||||||
import { DOMException } from "./01_dom_exception.js";
|
import { DOMException } from "./01_dom_exception.js";
|
||||||
|
|
||||||
const illegalConstructorKey = Symbol("illegalConstructorKey");
|
const illegalConstructorKey = Symbol("illegalConstructorKey");
|
||||||
let performanceEntries = [];
|
let performanceEntries = [];
|
||||||
let timeOrigin;
|
let timeOrigin;
|
||||||
|
|
||||||
|
const hrU8 = new Uint8Array(8);
|
||||||
|
const hr = new Uint32Array(TypedArrayPrototypeGetBuffer(hrU8));
|
||||||
|
|
||||||
|
function setTimeOrigin() {
|
||||||
|
op_time_origin(hrU8);
|
||||||
|
timeOrigin = hr[0] * 1000 + hr[1] / 1e6;
|
||||||
|
}
|
||||||
|
|
||||||
|
function now() {
|
||||||
|
op_now(hrU8);
|
||||||
|
return hr[0] * 1000 + hr[1] / 1e6;
|
||||||
|
}
|
||||||
|
|
||||||
webidl.converters["PerformanceMarkOptions"] = webidl
|
webidl.converters["PerformanceMarkOptions"] = webidl
|
||||||
.createDictionaryConverter(
|
.createDictionaryConverter(
|
||||||
"PerformanceMarkOptions",
|
"PerformanceMarkOptions",
|
||||||
|
@ -90,10 +106,6 @@ webidl.converters["DOMString or PerformanceMeasureOptions"] = (
|
||||||
return webidl.converters.DOMString(V, prefix, context, opts);
|
return webidl.converters.DOMString(V, prefix, context, opts);
|
||||||
};
|
};
|
||||||
|
|
||||||
function setTimeOrigin(origin) {
|
|
||||||
timeOrigin = origin;
|
|
||||||
}
|
|
||||||
|
|
||||||
function findMostRecent(
|
function findMostRecent(
|
||||||
name,
|
name,
|
||||||
type,
|
type,
|
||||||
|
@ -135,8 +147,6 @@ function filterByNameType(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const now = opNow;
|
|
||||||
|
|
||||||
const _name = Symbol("[[name]]");
|
const _name = Symbol("[[name]]");
|
||||||
const _entryType = Symbol("[[entryType]]");
|
const _entryType = Symbol("[[entryType]]");
|
||||||
const _startTime = Symbol("[[startTime]]");
|
const _startTime = Symbol("[[startTime]]");
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "deno_web"
|
name = "deno_web"
|
||||||
version = "0.207.0"
|
version = "0.208.0"
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
|
|
@ -52,7 +52,8 @@ pub use crate::message_port::Transferable;
|
||||||
|
|
||||||
use crate::timers::op_defer;
|
use crate::timers::op_defer;
|
||||||
use crate::timers::op_now;
|
use crate::timers::op_now;
|
||||||
use crate::timers::StartTime;
|
use crate::timers::op_time_origin;
|
||||||
|
pub use crate::timers::StartTime;
|
||||||
pub use crate::timers::TimersPermission;
|
pub use crate::timers::TimersPermission;
|
||||||
|
|
||||||
deno_core::extension!(deno_web,
|
deno_core::extension!(deno_web,
|
||||||
|
@ -84,6 +85,7 @@ deno_core::extension!(deno_web,
|
||||||
compression::op_compression_write,
|
compression::op_compression_write,
|
||||||
compression::op_compression_finish,
|
compression::op_compression_finish,
|
||||||
op_now<P>,
|
op_now<P>,
|
||||||
|
op_time_origin<P>,
|
||||||
op_defer,
|
op_defer,
|
||||||
stream_resource::op_readable_stream_resource_allocate,
|
stream_resource::op_readable_stream_resource_allocate,
|
||||||
stream_resource::op_readable_stream_resource_allocate_sized,
|
stream_resource::op_readable_stream_resource_allocate_sized,
|
||||||
|
@ -123,7 +125,7 @@ deno_core::extension!(deno_web,
|
||||||
if let Some(location) = options.maybe_location {
|
if let Some(location) = options.maybe_location {
|
||||||
state.put(Location(location));
|
state.put(Location(location));
|
||||||
}
|
}
|
||||||
state.put(StartTime::now());
|
state.put(StartTime::default());
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,10 @@
|
||||||
|
|
||||||
use deno_core::op2;
|
use deno_core::op2;
|
||||||
use deno_core::OpState;
|
use deno_core::OpState;
|
||||||
|
use std::time::Duration;
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
|
use std::time::SystemTime;
|
||||||
|
use std::time::UNIX_EPOCH;
|
||||||
|
|
||||||
pub trait TimersPermission {
|
pub trait TimersPermission {
|
||||||
fn allow_hrtime(&mut self) -> bool;
|
fn allow_hrtime(&mut self) -> bool;
|
||||||
|
@ -17,21 +20,28 @@ impl TimersPermission for deno_permissions::PermissionsContainer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type StartTime = Instant;
|
pub struct StartTime(Instant);
|
||||||
|
|
||||||
// Returns a milliseconds and nanoseconds subsec
|
impl Default for StartTime {
|
||||||
// since the start time of the deno runtime.
|
fn default() -> Self {
|
||||||
// If the High precision flag is not set, the
|
Self(Instant::now())
|
||||||
// nanoseconds are rounded on 2ms.
|
}
|
||||||
#[op2(fast)]
|
}
|
||||||
pub fn op_now<TP>(state: &mut OpState, #[buffer] buf: &mut [u8])
|
|
||||||
|
impl std::ops::Deref for StartTime {
|
||||||
|
type Target = Instant;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn expose_time<TP>(state: &mut OpState, duration: Duration, out: &mut [u8])
|
||||||
where
|
where
|
||||||
TP: TimersPermission + 'static,
|
TP: TimersPermission + 'static,
|
||||||
{
|
{
|
||||||
let start_time = state.borrow::<StartTime>();
|
let seconds = duration.as_secs() as u32;
|
||||||
let elapsed = start_time.elapsed();
|
let mut subsec_nanos = duration.subsec_nanos();
|
||||||
let seconds = elapsed.as_secs();
|
|
||||||
let mut subsec_nanos = elapsed.subsec_nanos();
|
|
||||||
|
|
||||||
// If the permission is not enabled
|
// If the permission is not enabled
|
||||||
// Round the nano result on 2 milliseconds
|
// Round the nano result on 2 milliseconds
|
||||||
|
@ -40,14 +50,33 @@ where
|
||||||
let reduced_time_precision = 2_000_000; // 2ms in nanoseconds
|
let reduced_time_precision = 2_000_000; // 2ms in nanoseconds
|
||||||
subsec_nanos -= subsec_nanos % reduced_time_precision;
|
subsec_nanos -= subsec_nanos % reduced_time_precision;
|
||||||
}
|
}
|
||||||
if buf.len() < 8 {
|
|
||||||
return;
|
if out.len() >= 8 {
|
||||||
|
out[0..4].copy_from_slice(&seconds.to_ne_bytes());
|
||||||
|
out[4..8].copy_from_slice(&subsec_nanos.to_ne_bytes());
|
||||||
}
|
}
|
||||||
let buf: &mut [u32] =
|
}
|
||||||
// SAFETY: buffer is at least 8 bytes long.
|
|
||||||
unsafe { std::slice::from_raw_parts_mut(buf.as_mut_ptr() as _, 2) };
|
#[op2(fast)]
|
||||||
buf[0] = seconds as u32;
|
pub fn op_now<TP>(state: &mut OpState, #[buffer] buf: &mut [u8])
|
||||||
buf[1] = subsec_nanos;
|
where
|
||||||
|
TP: TimersPermission + 'static,
|
||||||
|
{
|
||||||
|
let start_time = state.borrow::<StartTime>();
|
||||||
|
let elapsed = start_time.elapsed();
|
||||||
|
expose_time::<TP>(state, elapsed, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[op2(fast)]
|
||||||
|
pub fn op_time_origin<TP>(state: &mut OpState, #[buffer] buf: &mut [u8])
|
||||||
|
where
|
||||||
|
TP: TimersPermission + 'static,
|
||||||
|
{
|
||||||
|
// https://w3c.github.io/hr-time/#dfn-estimated-monotonic-time-of-the-unix-epoch
|
||||||
|
let wall_time = SystemTime::now();
|
||||||
|
let monotonic_time = state.borrow::<StartTime>().elapsed();
|
||||||
|
let epoch = wall_time.duration_since(UNIX_EPOCH).unwrap() - monotonic_time;
|
||||||
|
expose_time::<TP>(state, epoch, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::unused_async)]
|
#[allow(clippy::unused_async)]
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "deno_webgpu"
|
name = "deno_webgpu"
|
||||||
version = "0.143.0"
|
version = "0.144.0"
|
||||||
authors = ["the Deno authors"]
|
authors = ["the Deno authors"]
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "deno_webidl"
|
name = "deno_webidl"
|
||||||
version = "0.176.0"
|
version = "0.177.0"
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
|
|
@ -28,6 +28,7 @@ const {
|
||||||
ArrayPrototypePush,
|
ArrayPrototypePush,
|
||||||
ArrayPrototypeShift,
|
ArrayPrototypeShift,
|
||||||
ArrayPrototypeSome,
|
ArrayPrototypeSome,
|
||||||
|
Error,
|
||||||
ErrorPrototypeToString,
|
ErrorPrototypeToString,
|
||||||
ObjectDefineProperties,
|
ObjectDefineProperties,
|
||||||
ObjectPrototypeIsPrototypeOf,
|
ObjectPrototypeIsPrototypeOf,
|
||||||
|
@ -488,8 +489,11 @@ class WebSocket extends EventTarget {
|
||||||
/* error */
|
/* error */
|
||||||
this[_readyState] = CLOSED;
|
this[_readyState] = CLOSED;
|
||||||
|
|
||||||
|
const message = op_ws_get_error(rid);
|
||||||
|
const error = new Error(message);
|
||||||
const errorEv = new ErrorEvent("error", {
|
const errorEv = new ErrorEvent("error", {
|
||||||
message: op_ws_get_error(rid),
|
error,
|
||||||
|
message,
|
||||||
});
|
});
|
||||||
this.dispatchEvent(errorEv);
|
this.dispatchEvent(errorEv);
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "deno_websocket"
|
name = "deno_websocket"
|
||||||
version = "0.181.0"
|
version = "0.182.0"
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "deno_webstorage"
|
name = "deno_webstorage"
|
||||||
version = "0.171.0"
|
version = "0.172.0"
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "deno_resolver"
|
name = "deno_resolver"
|
||||||
version = "0.8.0"
|
version = "0.9.0"
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "node_resolver"
|
name = "node_resolver"
|
||||||
version = "0.15.0"
|
version = "0.16.0"
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "deno_runtime"
|
name = "deno_runtime"
|
||||||
version = "0.185.0"
|
version = "0.186.0"
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
|
|
@ -623,7 +623,7 @@ fn get_ffi_call_error_class(e: &CallError) -> &'static str {
|
||||||
fn get_webstorage_class_name(e: &WebStorageError) -> &'static str {
|
fn get_webstorage_class_name(e: &WebStorageError) -> &'static str {
|
||||||
match e {
|
match e {
|
||||||
WebStorageError::ContextNotSupported => "DOMExceptionNotSupportedError",
|
WebStorageError::ContextNotSupported => "DOMExceptionNotSupportedError",
|
||||||
WebStorageError::Sqlite(_) => todo!(),
|
WebStorageError::Sqlite(_) => "Error",
|
||||||
WebStorageError::Io(e) => get_io_error_class(e),
|
WebStorageError::Io(e) => get_io_error_class(e),
|
||||||
WebStorageError::StorageExceeded => "DOMExceptionQuotaExceededError",
|
WebStorageError::StorageExceeded => "DOMExceptionQuotaExceededError",
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,6 @@ const {
|
||||||
ArrayPrototypeForEach,
|
ArrayPrototypeForEach,
|
||||||
ArrayPrototypeIncludes,
|
ArrayPrototypeIncludes,
|
||||||
ArrayPrototypeMap,
|
ArrayPrototypeMap,
|
||||||
DateNow,
|
|
||||||
Error,
|
Error,
|
||||||
ErrorPrototype,
|
ErrorPrototype,
|
||||||
FunctionPrototypeBind,
|
FunctionPrototypeBind,
|
||||||
|
@ -642,7 +641,7 @@ function bootstrapMainRuntime(runtimeOptions, warmup = false) {
|
||||||
|
|
||||||
removeImportedOps();
|
removeImportedOps();
|
||||||
|
|
||||||
performance.setTimeOrigin(DateNow());
|
performance.setTimeOrigin();
|
||||||
globalThis_ = globalThis;
|
globalThis_ = globalThis;
|
||||||
|
|
||||||
// Remove bootstrapping data from the global scope
|
// Remove bootstrapping data from the global scope
|
||||||
|
@ -858,7 +857,7 @@ function bootstrapWorkerRuntime(
|
||||||
7: nodeDebug,
|
7: nodeDebug,
|
||||||
} = runtimeOptions;
|
} = runtimeOptions;
|
||||||
|
|
||||||
performance.setTimeOrigin(DateNow());
|
performance.setTimeOrigin();
|
||||||
globalThis_ = globalThis;
|
globalThis_ = globalThis;
|
||||||
|
|
||||||
// Remove bootstrapping data from the global scope
|
// Remove bootstrapping data from the global scope
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "deno_permissions"
|
name = "deno_permissions"
|
||||||
version = "0.36.0"
|
version = "0.37.0"
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
|
|
@ -40,8 +40,8 @@ pub use prompter::PromptResponse;
|
||||||
#[derive(Debug, thiserror::Error)]
|
#[derive(Debug, thiserror::Error)]
|
||||||
#[error("Requires {access}, {}", format_permission_error(.name))]
|
#[error("Requires {access}, {}", format_permission_error(.name))]
|
||||||
pub struct PermissionDeniedError {
|
pub struct PermissionDeniedError {
|
||||||
access: String,
|
pub access: String,
|
||||||
name: &'static str,
|
pub name: &'static str,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn format_permission_error(name: &'static str) -> String {
|
fn format_permission_error(name: &'static str) -> String {
|
||||||
|
@ -1461,7 +1461,7 @@ pub struct SysDescriptor(String);
|
||||||
impl SysDescriptor {
|
impl SysDescriptor {
|
||||||
pub fn parse(kind: String) -> Result<Self, SysDescriptorParseError> {
|
pub fn parse(kind: String) -> Result<Self, SysDescriptorParseError> {
|
||||||
match kind.as_str() {
|
match kind.as_str() {
|
||||||
"hostname" | "osRelease" | "osUptime" | "loadavg"
|
"hostname" | "inspector" | "osRelease" | "osUptime" | "loadavg"
|
||||||
| "networkInterfaces" | "systemMemoryInfo" | "uid" | "gid" | "cpus"
|
| "networkInterfaces" | "systemMemoryInfo" | "uid" | "gid" | "cpus"
|
||||||
| "homedir" | "getegid" | "statfs" | "getPriority" | "setPriority"
|
| "homedir" | "getegid" | "statfs" | "getPriority" | "setPriority"
|
||||||
| "userInfo" => Ok(Self(kind)),
|
| "userInfo" => Ok(Self(kind)),
|
||||||
|
|
|
@ -77,6 +77,7 @@
|
||||||
"test-fs-rmdir-recursive.js",
|
"test-fs-rmdir-recursive.js",
|
||||||
"test-fs-write-file.js",
|
"test-fs-write-file.js",
|
||||||
"test-http-url.parse-https.request.js",
|
"test-http-url.parse-https.request.js",
|
||||||
|
"test-net-autoselectfamily.js",
|
||||||
"test-net-better-error-messages-path.js",
|
"test-net-better-error-messages-path.js",
|
||||||
"test-net-connect-buffer.js",
|
"test-net-connect-buffer.js",
|
||||||
"test-net-connect-buffer2.js",
|
"test-net-connect-buffer2.js",
|
||||||
|
@ -404,6 +405,7 @@
|
||||||
"test-http-url.parse-only-support-http-https-protocol.js",
|
"test-http-url.parse-only-support-http-https-protocol.js",
|
||||||
"test-icu-transcode.js",
|
"test-icu-transcode.js",
|
||||||
"test-net-access-byteswritten.js",
|
"test-net-access-byteswritten.js",
|
||||||
|
"test-net-autoselectfamily.js",
|
||||||
"test-net-better-error-messages-listen-path.js",
|
"test-net-better-error-messages-listen-path.js",
|
||||||
"test-net-better-error-messages-path.js",
|
"test-net-better-error-messages-path.js",
|
||||||
"test-net-better-error-messages-port-hostname.js",
|
"test-net-better-error-messages-port-hostname.js",
|
||||||
|
|
|
@ -1767,7 +1767,6 @@ NOTE: This file should not be manually edited. Please edit `tests/node_compat/co
|
||||||
- [parallel/test-net-autoselectfamily-commandline-option.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-net-autoselectfamily-commandline-option.js)
|
- [parallel/test-net-autoselectfamily-commandline-option.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-net-autoselectfamily-commandline-option.js)
|
||||||
- [parallel/test-net-autoselectfamily-default.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-net-autoselectfamily-default.js)
|
- [parallel/test-net-autoselectfamily-default.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-net-autoselectfamily-default.js)
|
||||||
- [parallel/test-net-autoselectfamily-ipv4first.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-net-autoselectfamily-ipv4first.js)
|
- [parallel/test-net-autoselectfamily-ipv4first.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-net-autoselectfamily-ipv4first.js)
|
||||||
- [parallel/test-net-autoselectfamily.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-net-autoselectfamily.js)
|
|
||||||
- [parallel/test-net-better-error-messages-listen.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-net-better-error-messages-listen.js)
|
- [parallel/test-net-better-error-messages-listen.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-net-better-error-messages-listen.js)
|
||||||
- [parallel/test-net-binary.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-net-binary.js)
|
- [parallel/test-net-binary.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-net-binary.js)
|
||||||
- [parallel/test-net-bind-twice.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-net-bind-twice.js)
|
- [parallel/test-net-bind-twice.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-net-bind-twice.js)
|
||||||
|
|
|
@ -19,6 +19,7 @@ import { magenta } from "@std/fmt/colors";
|
||||||
import { pooledMap } from "@std/async/pool";
|
import { pooledMap } from "@std/async/pool";
|
||||||
import { dirname, fromFileUrl, join } from "@std/path";
|
import { dirname, fromFileUrl, join } from "@std/path";
|
||||||
import { assertEquals, fail } from "@std/assert";
|
import { assertEquals, fail } from "@std/assert";
|
||||||
|
import { distinct } from "@std/collections";
|
||||||
import {
|
import {
|
||||||
config,
|
config,
|
||||||
getPathsFromTestSuites,
|
getPathsFromTestSuites,
|
||||||
|
@ -36,6 +37,9 @@ const testPaths = partitionParallelTestPaths(
|
||||||
getPathsFromTestSuites(config.ignore),
|
getPathsFromTestSuites(config.ignore),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
testPaths.sequential = distinct(testPaths.sequential);
|
||||||
|
testPaths.parallel = distinct(testPaths.parallel);
|
||||||
|
|
||||||
const cwd = new URL(".", import.meta.url);
|
const cwd = new URL(".", import.meta.url);
|
||||||
const windowsIgnorePaths = new Set(
|
const windowsIgnorePaths = new Set(
|
||||||
getPathsFromTestSuites(config.windowsIgnore),
|
getPathsFromTestSuites(config.windowsIgnore),
|
||||||
|
|
|
@ -473,6 +473,7 @@ const pwdCommand = isWindows ?
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
allowGlobals,
|
allowGlobals,
|
||||||
|
defaultAutoSelectFamilyAttemptTimeout: 2500,
|
||||||
expectsError,
|
expectsError,
|
||||||
expectWarning,
|
expectWarning,
|
||||||
getArrayBufferViews,
|
getArrayBufferViews,
|
||||||
|
|
312
tests/node_compat/test/parallel/test-net-autoselectfamily.js
Normal file
312
tests/node_compat/test/parallel/test-net-autoselectfamily.js
Normal file
|
@ -0,0 +1,312 @@
|
||||||
|
// deno-fmt-ignore-file
|
||||||
|
// deno-lint-ignore-file
|
||||||
|
|
||||||
|
// Copyright Joyent and Node contributors. All rights reserved. MIT license.
|
||||||
|
// Taken from Node 18.12.1
|
||||||
|
// This file is automatically generated by `tests/node_compat/runner/setup.ts`. Do not modify this file manually.
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const common = require('../common');
|
||||||
|
const { parseDNSPacket, writeDNSPacket } = require('../common/dns');
|
||||||
|
|
||||||
|
const assert = require('assert');
|
||||||
|
const dgram = require('dgram');
|
||||||
|
const { Resolver } = require('dns');
|
||||||
|
const { createConnection, createServer } = require('net');
|
||||||
|
|
||||||
|
// Test that happy eyeballs algorithm is properly implemented.
|
||||||
|
|
||||||
|
// Purposely not using setDefaultAutoSelectFamilyAttemptTimeout here to test the
|
||||||
|
// parameter is correctly used in options.
|
||||||
|
//
|
||||||
|
// Some of the machines in the CI need more time to establish connection
|
||||||
|
const autoSelectFamilyAttemptTimeout = common.defaultAutoSelectFamilyAttemptTimeout;
|
||||||
|
|
||||||
|
function _lookup(resolver, hostname, options, cb) {
|
||||||
|
resolver.resolve(hostname, 'ANY', (err, replies) => {
|
||||||
|
assert.notStrictEqual(options.family, 4);
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
return cb(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
const hosts = replies
|
||||||
|
.map((r) => ({ address: r.address, family: r.type === 'AAAA' ? 6 : 4 }))
|
||||||
|
.sort((a, b) => b.family - a.family);
|
||||||
|
|
||||||
|
if (options.all === true) {
|
||||||
|
return cb(null, hosts);
|
||||||
|
}
|
||||||
|
|
||||||
|
return cb(null, hosts[0].address, hosts[0].family);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function createDnsServer(ipv6Addrs, ipv4Addrs, cb) {
|
||||||
|
if (!Array.isArray(ipv6Addrs)) {
|
||||||
|
ipv6Addrs = [ipv6Addrs];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Array.isArray(ipv4Addrs)) {
|
||||||
|
ipv4Addrs = [ipv4Addrs];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a DNS server which replies with a AAAA and a A record for the same host
|
||||||
|
const socket = dgram.createSocket('udp4');
|
||||||
|
|
||||||
|
// TODO(kt3k): We use common.mustCallAtLeast instead of common.mustCall
|
||||||
|
// because Deno sends multiple requests to the DNS server.
|
||||||
|
// This can be addressed if Deno.resolveDns supports ANY record type.
|
||||||
|
// See https://github.com/denoland/deno/issues/14492
|
||||||
|
socket.on('message', common.mustCallAtLeast((msg, { address, port }) => {
|
||||||
|
const parsed = parseDNSPacket(msg);
|
||||||
|
const domain = parsed.questions[0].domain;
|
||||||
|
assert.strictEqual(domain, 'example.org');
|
||||||
|
|
||||||
|
socket.send(writeDNSPacket({
|
||||||
|
id: parsed.id,
|
||||||
|
questions: parsed.questions,
|
||||||
|
answers: [
|
||||||
|
...ipv6Addrs.map((address) => ({ type: 'AAAA', address, ttl: 123, domain: 'example.org' })),
|
||||||
|
...ipv4Addrs.map((address) => ({ type: 'A', address, ttl: 123, domain: 'example.org' })),
|
||||||
|
]
|
||||||
|
}), port, address);
|
||||||
|
}));
|
||||||
|
|
||||||
|
socket.bind(0, () => {
|
||||||
|
const resolver = new Resolver();
|
||||||
|
resolver.setServers([`127.0.0.1:${socket.address().port}`]);
|
||||||
|
|
||||||
|
cb({ dnsServer: socket, lookup: _lookup.bind(null, resolver) });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that IPV4 is reached if IPV6 is not reachable
|
||||||
|
{
|
||||||
|
createDnsServer('::1', '127.0.0.1', common.mustCall(function({ dnsServer, lookup }) {
|
||||||
|
const ipv4Server = createServer((socket) => {
|
||||||
|
socket.on('data', common.mustCall(() => {
|
||||||
|
socket.write('response-ipv4');
|
||||||
|
socket.end();
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
ipv4Server.listen(0, '127.0.0.1', common.mustCall(() => {
|
||||||
|
const port = ipv4Server.address().port;
|
||||||
|
|
||||||
|
const connection = createConnection({
|
||||||
|
host: 'example.org',
|
||||||
|
port: port,
|
||||||
|
lookup,
|
||||||
|
autoSelectFamily: true,
|
||||||
|
autoSelectFamilyAttemptTimeout,
|
||||||
|
});
|
||||||
|
|
||||||
|
let response = '';
|
||||||
|
connection.setEncoding('utf-8');
|
||||||
|
|
||||||
|
connection.on('ready', common.mustCall(() => {
|
||||||
|
assert.deepStrictEqual(connection.autoSelectFamilyAttemptedAddresses, [`::1:${port}`, `127.0.0.1:${port}`]);
|
||||||
|
}));
|
||||||
|
|
||||||
|
connection.on('data', (chunk) => {
|
||||||
|
response += chunk;
|
||||||
|
});
|
||||||
|
|
||||||
|
connection.on('end', common.mustCall(() => {
|
||||||
|
assert.strictEqual(response, 'response-ipv4');
|
||||||
|
ipv4Server.close();
|
||||||
|
dnsServer.close();
|
||||||
|
}));
|
||||||
|
|
||||||
|
connection.write('request');
|
||||||
|
}));
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that only the last successful connection is established.
|
||||||
|
{
|
||||||
|
createDnsServer(
|
||||||
|
['2606:4700::6810:85e5', '2606:4700::6810:84e5', "::1"],
|
||||||
|
// TODO(kt3k): Comment out ipv4 addresses to make the test pass faster.
|
||||||
|
// Enable this when Deno.connect() call becomes cancellable.
|
||||||
|
// See https://github.com/denoland/deno/issues/26819
|
||||||
|
// ['104.20.22.46', '104.20.23.46', '127.0.0.1'],
|
||||||
|
['127.0.0.1'],
|
||||||
|
common.mustCall(function({ dnsServer, lookup }) {
|
||||||
|
const ipv4Server = createServer((socket) => {
|
||||||
|
socket.on('data', common.mustCall(() => {
|
||||||
|
socket.write('response-ipv4');
|
||||||
|
socket.end();
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
ipv4Server.listen(0, '127.0.0.1', common.mustCall(() => {
|
||||||
|
const port = ipv4Server.address().port;
|
||||||
|
|
||||||
|
const connection = createConnection({
|
||||||
|
host: 'example.org',
|
||||||
|
port: port,
|
||||||
|
lookup,
|
||||||
|
autoSelectFamily: true,
|
||||||
|
autoSelectFamilyAttemptTimeout,
|
||||||
|
});
|
||||||
|
|
||||||
|
let response = '';
|
||||||
|
connection.setEncoding('utf-8');
|
||||||
|
|
||||||
|
connection.on('ready', common.mustCall(() => {
|
||||||
|
assert.deepStrictEqual(
|
||||||
|
connection.autoSelectFamilyAttemptedAddresses,
|
||||||
|
[
|
||||||
|
`2606:4700::6810:85e5:${port}`,
|
||||||
|
`104.20.22.46:${port}`,
|
||||||
|
`2606:4700::6810:84e5:${port}`,
|
||||||
|
`104.20.23.46:${port}`,
|
||||||
|
`::1:${port}`,
|
||||||
|
`127.0.0.1:${port}`,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}));
|
||||||
|
|
||||||
|
connection.on('data', (chunk) => {
|
||||||
|
response += chunk;
|
||||||
|
});
|
||||||
|
|
||||||
|
connection.on('end', common.mustCall(() => {
|
||||||
|
assert.strictEqual(response, 'response-ipv4');
|
||||||
|
ipv4Server.close();
|
||||||
|
dnsServer.close();
|
||||||
|
}));
|
||||||
|
|
||||||
|
connection.write('request');
|
||||||
|
}));
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that IPV4 is NOT reached if IPV6 is reachable
|
||||||
|
if (common.hasIPv6) {
|
||||||
|
createDnsServer('::1', '127.0.0.1', common.mustCall(function({ dnsServer, lookup }) {
|
||||||
|
const ipv4Server = createServer((socket) => {
|
||||||
|
socket.on('data', common.mustNotCall(() => {
|
||||||
|
socket.write('response-ipv4');
|
||||||
|
socket.end();
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
const ipv6Server = createServer((socket) => {
|
||||||
|
socket.on('data', common.mustCall(() => {
|
||||||
|
socket.write('response-ipv6');
|
||||||
|
socket.end();
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
ipv4Server.listen(0, '127.0.0.1', common.mustCall(() => {
|
||||||
|
const port = ipv4Server.address().port;
|
||||||
|
|
||||||
|
ipv6Server.listen(port, '::1', common.mustCall(() => {
|
||||||
|
const connection = createConnection({
|
||||||
|
host: 'example.org',
|
||||||
|
port,
|
||||||
|
lookup,
|
||||||
|
autoSelectFamily: true,
|
||||||
|
autoSelectFamilyAttemptTimeout,
|
||||||
|
});
|
||||||
|
|
||||||
|
let response = '';
|
||||||
|
connection.setEncoding('utf-8');
|
||||||
|
|
||||||
|
connection.on('ready', common.mustCall(() => {
|
||||||
|
assert.deepStrictEqual(connection.autoSelectFamilyAttemptedAddresses, [`::1:${port}`]);
|
||||||
|
}));
|
||||||
|
|
||||||
|
connection.on('data', (chunk) => {
|
||||||
|
response += chunk;
|
||||||
|
});
|
||||||
|
|
||||||
|
connection.on('end', common.mustCall(() => {
|
||||||
|
assert.strictEqual(response, 'response-ipv6');
|
||||||
|
ipv4Server.close();
|
||||||
|
ipv6Server.close();
|
||||||
|
dnsServer.close();
|
||||||
|
}));
|
||||||
|
|
||||||
|
connection.write('request');
|
||||||
|
}));
|
||||||
|
}));
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that when all errors are returned when no connections succeeded
|
||||||
|
{
|
||||||
|
createDnsServer('::1', '127.0.0.1', common.mustCall(function({ dnsServer, lookup }) {
|
||||||
|
const connection = createConnection({
|
||||||
|
host: 'example.org',
|
||||||
|
port: 10,
|
||||||
|
lookup,
|
||||||
|
autoSelectFamily: true,
|
||||||
|
autoSelectFamilyAttemptTimeout,
|
||||||
|
});
|
||||||
|
|
||||||
|
connection.on('ready', common.mustNotCall());
|
||||||
|
connection.on('error', common.mustCall((error) => {
|
||||||
|
assert.deepStrictEqual(connection.autoSelectFamilyAttemptedAddresses, ['::1:10', '127.0.0.1:10']);
|
||||||
|
assert.strictEqual(error.constructor.name, 'AggregateError');
|
||||||
|
assert.strictEqual(error.errors.length, 2);
|
||||||
|
|
||||||
|
const errors = error.errors.map((e) => e.message);
|
||||||
|
assert.ok(errors.includes('connect ECONNREFUSED 127.0.0.1:10'));
|
||||||
|
|
||||||
|
if (common.hasIPv6) {
|
||||||
|
assert.ok(errors.includes('connect ECONNREFUSED ::1:10'));
|
||||||
|
}
|
||||||
|
|
||||||
|
dnsServer.close();
|
||||||
|
}));
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that the option can be disabled
|
||||||
|
{
|
||||||
|
createDnsServer('::1', '127.0.0.1', common.mustCall(function({ dnsServer, lookup }) {
|
||||||
|
const ipv4Server = createServer((socket) => {
|
||||||
|
socket.on('data', common.mustCall(() => {
|
||||||
|
socket.write('response-ipv4');
|
||||||
|
socket.end();
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
ipv4Server.listen(0, '127.0.0.1', common.mustCall(() => {
|
||||||
|
const port = ipv4Server.address().port;
|
||||||
|
|
||||||
|
const connection = createConnection({
|
||||||
|
host: 'example.org',
|
||||||
|
port,
|
||||||
|
lookup,
|
||||||
|
autoSelectFamily: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
connection.on('ready', common.mustNotCall());
|
||||||
|
connection.on('error', common.mustCall((error) => {
|
||||||
|
assert.strictEqual(connection.autoSelectFamilyAttemptedAddresses, undefined);
|
||||||
|
|
||||||
|
if (common.hasIPv6) {
|
||||||
|
assert.strictEqual(error.code, 'ECONNREFUSED');
|
||||||
|
assert.strictEqual(error.message, `connect ECONNREFUSED ::1:${port}`);
|
||||||
|
} else if (error.code === 'EAFNOSUPPORT') {
|
||||||
|
assert.strictEqual(error.message, `connect EAFNOSUPPORT ::1:${port} - Local (undefined:undefined)`);
|
||||||
|
} else if (error.code === 'EUNATCH') {
|
||||||
|
assert.strictEqual(error.message, `connect EUNATCH ::1:${port} - Local (:::0)`);
|
||||||
|
} else {
|
||||||
|
assert.strictEqual(error.code, 'EADDRNOTAVAIL');
|
||||||
|
assert.strictEqual(error.message, `connect EADDRNOTAVAIL ::1:${port} - Local (:::0)`);
|
||||||
|
}
|
||||||
|
|
||||||
|
ipv4Server.close();
|
||||||
|
dnsServer.close();
|
||||||
|
}));
|
||||||
|
}));
|
||||||
|
}));
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
import * as fs from "node:fs";
|
||||||
|
|
||||||
|
fs.writeFileSync("./testbin.js", "#!/usr/bin/env node\nconsole.log('run testbin');");
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"name": "@denotest/bin-created-by-lifecycle",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"scripts": {
|
||||||
|
"install": "node install.mjs"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"testbin": "testbin.js"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"tempDir": true,
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"args": "install",
|
||||||
|
"output": "install.out"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"workspace": ["packages/foo", "packages/bar"],
|
||||||
|
"imports": {
|
||||||
|
"@denotest/subtract": "jsr:@denotest/subtract@^1.0.0"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
[UNORDERED_START]
|
||||||
|
Download http://localhost:4260/@denotest%2fesm-basic
|
||||||
|
Download http://localhost:4260/@denotest/esm-basic/1.0.0.tgz
|
||||||
|
Download http://127.0.0.1:4250/@denotest/subtract/meta.json
|
||||||
|
Download http://127.0.0.1:4250/@denotest/add/meta.json
|
||||||
|
Download http://127.0.0.1:4250/@denotest/add/1.0.0_meta.json
|
||||||
|
Download http://127.0.0.1:4250/@denotest/subtract/1.0.0_meta.json
|
||||||
|
Download http://127.0.0.1:4250/@denotest/add/1.0.0/mod.ts
|
||||||
|
Download http://127.0.0.1:4250/@denotest/subtract/1.0.0/mod.ts
|
||||||
|
[UNORDERED_END]
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"imports": {
|
||||||
|
"@denotest/esm-basic": "npm:@denotest/esm-basic@^1.0.0"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"imports": {
|
||||||
|
"@denotest/add": "jsr:@denotest/add@^1.0.0"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
{
|
||||||
|
"tempDir": true,
|
||||||
|
"tests": {
|
||||||
|
"all_at_once": {
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"args": "install --allow-scripts",
|
||||||
|
"output": "all_at_once_install.out"
|
||||||
|
},
|
||||||
|
{ "args": "task run-testbin", "output": "run_testbin.out" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"separate_steps": {
|
||||||
|
"steps": [
|
||||||
|
{ "if": "unix", "args": "install", "output": "install_warn.out" },
|
||||||
|
{
|
||||||
|
"if": "windows",
|
||||||
|
"args": "install",
|
||||||
|
"output": "install_warn_windows.out"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"args": "install --allow-scripts",
|
||||||
|
"output": "Initialize @denotest/bin-created-by-lifecycle@1.0.0: running 'install' script\n"
|
||||||
|
},
|
||||||
|
{ "args": "task run-testbin", "output": "run_testbin.out" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
Download http://localhost:4260/@denotest%2fbin-created-by-lifecycle
|
||||||
|
Download http://localhost:4260/@denotest/bin-created-by-lifecycle/1.0.0.tgz
|
||||||
|
Initialize @denotest/bin-created-by-lifecycle@1.0.0
|
||||||
|
Initialize @denotest/bin-created-by-lifecycle@1.0.0: running 'install' script
|
|
@ -0,0 +1,10 @@
|
||||||
|
Download http://localhost:4260/@denotest%2fbin-created-by-lifecycle
|
||||||
|
Download http://localhost:4260/@denotest/bin-created-by-lifecycle/1.0.0.tgz
|
||||||
|
Initialize @denotest/bin-created-by-lifecycle@1.0.0
|
||||||
|
Warning Trying to set up 'testbin' bin for "[WILDCARD]bin-created-by-lifecycle", but the entry point "[WILDCARD]testbin.js" doesn't exist.
|
||||||
|
Warning The following packages contained npm lifecycle scripts (preinstall/install/postinstall) that were not executed:
|
||||||
|
┠─ npm:@denotest/bin-created-by-lifecycle@1.0.0
|
||||||
|
┃
|
||||||
|
┠─ This may cause the packages to not work correctly.
|
||||||
|
┖─ To run lifecycle scripts, use the `--allow-scripts` flag with `deno install`:
|
||||||
|
deno install --allow-scripts=npm:@denotest/bin-created-by-lifecycle@1.0.0
|
|
@ -0,0 +1,9 @@
|
||||||
|
Download http://localhost:4260/@denotest%2fbin-created-by-lifecycle
|
||||||
|
Download http://localhost:4260/@denotest/bin-created-by-lifecycle/1.0.0.tgz
|
||||||
|
Initialize @denotest/bin-created-by-lifecycle@1.0.0
|
||||||
|
Warning The following packages contained npm lifecycle scripts (preinstall/install/postinstall) that were not executed:
|
||||||
|
┠─ npm:@denotest/bin-created-by-lifecycle@1.0.0
|
||||||
|
┃
|
||||||
|
┠─ This may cause the packages to not work correctly.
|
||||||
|
┖─ To run lifecycle scripts, use the `--allow-scripts` flag with `deno install`:
|
||||||
|
deno install --allow-scripts=npm:@denotest/bin-created-by-lifecycle@1.0.0
|
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"dependencies": {
|
||||||
|
"@denotest/bin-created-by-lifecycle": "1.0.0"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"run-testbin": "testbin"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
Task run-testbin testbin
|
||||||
|
run testbin
|
|
@ -4299,3 +4299,31 @@ Deno.test({
|
||||||
|
|
||||||
assert(cancelled);
|
assert(cancelled);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Deno.test({
|
||||||
|
name: "AbortSignal event aborted when request is cancelled",
|
||||||
|
}, async () => {
|
||||||
|
const { promise, resolve } = Promise.withResolvers<void>();
|
||||||
|
|
||||||
|
const server = Deno.serve({
|
||||||
|
hostname: "0.0.0.0",
|
||||||
|
port: servePort,
|
||||||
|
onListen: () => resolve(),
|
||||||
|
}, async (request) => {
|
||||||
|
const { promise: promiseAbort, resolve: resolveAbort } = Promise
|
||||||
|
.withResolvers<void>();
|
||||||
|
request.signal.addEventListener("abort", () => resolveAbort());
|
||||||
|
assert(!request.signal.aborted);
|
||||||
|
|
||||||
|
await promiseAbort;
|
||||||
|
|
||||||
|
return new Response("Ok");
|
||||||
|
});
|
||||||
|
|
||||||
|
await promise;
|
||||||
|
await fetch(`http://localhost:${servePort}/`, {
|
||||||
|
signal: AbortSignal.timeout(100),
|
||||||
|
}).catch(() => {});
|
||||||
|
|
||||||
|
await server.shutdown();
|
||||||
|
});
|
||||||
|
|
|
@ -453,7 +453,8 @@ Deno.test("invalid server", async () => {
|
||||||
const { promise, resolve } = Promise.withResolvers<void>();
|
const { promise, resolve } = Promise.withResolvers<void>();
|
||||||
const ws = new WebSocket("ws://localhost:2121");
|
const ws = new WebSocket("ws://localhost:2121");
|
||||||
let err = false;
|
let err = false;
|
||||||
ws.onerror = () => {
|
ws.onerror = (e) => {
|
||||||
|
assert("error" in e);
|
||||||
err = true;
|
err = true;
|
||||||
};
|
};
|
||||||
ws.onclose = () => {
|
ws.onclose = () => {
|
||||||
|
|
|
@ -10,6 +10,11 @@ import * as net from "node:net";
|
||||||
import { assert, assertEquals } from "@std/assert";
|
import { assert, assertEquals } from "@std/assert";
|
||||||
import { curlRequest } from "../unit/test_util.ts";
|
import { curlRequest } from "../unit/test_util.ts";
|
||||||
|
|
||||||
|
// Increase the timeout for the auto select family to avoid flakiness
|
||||||
|
net.setDefaultAutoSelectFamilyAttemptTimeout(
|
||||||
|
net.getDefaultAutoSelectFamilyAttemptTimeout() * 30,
|
||||||
|
);
|
||||||
|
|
||||||
for (const url of ["http://localhost:4246", "https://localhost:4247"]) {
|
for (const url of ["http://localhost:4246", "https://localhost:4247"]) {
|
||||||
Deno.test(`[node/http2 client] ${url}`, {
|
Deno.test(`[node/http2 client] ${url}`, {
|
||||||
ignore: Deno.build.os === "windows",
|
ignore: Deno.build.os === "windows",
|
||||||
|
|
Loading…
Reference in a new issue