mirror of
https://github.com/denoland/deno.git
synced 2025-03-10 06:07:03 -04:00
Merge branch 'cjs_suggestions_for_mjs' of https://github.com/MohammadSu1/my_deno into cjs_suggestions_for_mjs
This commit is contained in:
commit
4db134d19e
1825 changed files with 11889 additions and 3998 deletions
|
@ -65,10 +65,14 @@
|
||||||
"tests/wpt/runner/expectation.json",
|
"tests/wpt/runner/expectation.json",
|
||||||
"tests/wpt/runner/manifest.json",
|
"tests/wpt/runner/manifest.json",
|
||||||
"tests/wpt/suite",
|
"tests/wpt/suite",
|
||||||
"third_party"
|
"third_party",
|
||||||
|
"tests/specs/run/shebang_with_json_imports_tsc",
|
||||||
|
"tests/specs/run/shebang_with_json_imports_swc",
|
||||||
|
"tests/specs/run/ext_flag_takes_precedence_over_extension",
|
||||||
|
"tests/specs/run/error_syntax_empty_trailing_line/error_syntax_empty_trailing_line.mjs"
|
||||||
],
|
],
|
||||||
"plugins": [
|
"plugins": [
|
||||||
"https://plugins.dprint.dev/typescript-0.93.1.wasm",
|
"https://plugins.dprint.dev/typescript-0.93.2.wasm",
|
||||||
"https://plugins.dprint.dev/json-0.19.4.wasm",
|
"https://plugins.dprint.dev/json-0.19.4.wasm",
|
||||||
"https://plugins.dprint.dev/markdown-0.17.8.wasm",
|
"https://plugins.dprint.dev/markdown-0.17.8.wasm",
|
||||||
"https://plugins.dprint.dev/toml-0.6.3.wasm",
|
"https://plugins.dprint.dev/toml-0.6.3.wasm",
|
||||||
|
|
2
.github/workflows/cargo_publish.yml
vendored
2
.github/workflows/cargo_publish.yml
vendored
|
@ -10,7 +10,7 @@ concurrency:
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
name: cargo publish
|
name: cargo publish
|
||||||
runs-on: ubuntu-20.04-xl
|
runs-on: ubuntu-24.04-xl
|
||||||
timeout-minutes: 90
|
timeout-minutes: 90
|
||||||
|
|
||||||
env:
|
env:
|
||||||
|
|
6
.github/workflows/ci.generate.ts
vendored
6
.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 = 23;
|
const cacheVersion = 24;
|
||||||
|
|
||||||
const ubuntuX86Runner = "ubuntu-24.04";
|
const ubuntuX86Runner = "ubuntu-24.04";
|
||||||
const ubuntuX86XlRunner = "ubuntu-24.04-xl";
|
const ubuntuX86XlRunner = "ubuntu-24.04-xl";
|
||||||
|
@ -14,6 +14,7 @@ const windowsX86Runner = "windows-2022";
|
||||||
const windowsX86XlRunner = "windows-2022-xl";
|
const windowsX86XlRunner = "windows-2022-xl";
|
||||||
const macosX86Runner = "macos-13";
|
const macosX86Runner = "macos-13";
|
||||||
const macosArmRunner = "macos-14";
|
const macosArmRunner = "macos-14";
|
||||||
|
const selfHostedMacosArmRunner = "self-hosted";
|
||||||
|
|
||||||
const Runners = {
|
const Runners = {
|
||||||
linuxX86: {
|
linuxX86: {
|
||||||
|
@ -40,7 +41,8 @@ const Runners = {
|
||||||
macosArm: {
|
macosArm: {
|
||||||
os: "macos",
|
os: "macos",
|
||||||
arch: "aarch64",
|
arch: "aarch64",
|
||||||
runner: macosArmRunner,
|
runner:
|
||||||
|
`\${{ github.repository == 'denoland/deno' && startsWith(github.ref, 'refs/tags/') && '${selfHostedMacosArmRunner}' || '${macosArmRunner}' }}`,
|
||||||
},
|
},
|
||||||
windowsX86: {
|
windowsX86: {
|
||||||
os: "windows",
|
os: "windows",
|
||||||
|
|
12
.github/workflows/ci.yml
vendored
12
.github/workflows/ci.yml
vendored
|
@ -68,12 +68,12 @@ jobs:
|
||||||
skip: '${{ !contains(github.event.pull_request.labels.*.name, ''ci-full'') && (github.event_name == ''pull_request'') }}'
|
skip: '${{ !contains(github.event.pull_request.labels.*.name, ''ci-full'') && (github.event_name == ''pull_request'') }}'
|
||||||
- os: macos
|
- os: macos
|
||||||
arch: aarch64
|
arch: aarch64
|
||||||
runner: macos-14
|
runner: '${{ github.repository == ''denoland/deno'' && startsWith(github.ref, ''refs/tags/'') && ''self-hosted'' || ''macos-14'' }}'
|
||||||
job: test
|
job: test
|
||||||
profile: debug
|
profile: debug
|
||||||
- os: macos
|
- os: macos
|
||||||
arch: aarch64
|
arch: aarch64
|
||||||
runner: '${{ (!contains(github.event.pull_request.labels.*.name, ''ci-full'') && (github.event_name == ''pull_request'')) && ''ubuntu-24.04'' || ''macos-14'' }}'
|
runner: '${{ (!contains(github.event.pull_request.labels.*.name, ''ci-full'') && (github.event_name == ''pull_request'')) && ''ubuntu-24.04'' || github.repository == ''denoland/deno'' && startsWith(github.ref, ''refs/tags/'') && ''self-hosted'' || ''macos-14'' }}'
|
||||||
job: test
|
job: test
|
||||||
profile: release
|
profile: release
|
||||||
skip: '${{ !contains(github.event.pull_request.labels.*.name, ''ci-full'') && (github.event_name == ''pull_request'') }}'
|
skip: '${{ !contains(github.event.pull_request.labels.*.name, ''ci-full'') && (github.event_name == ''pull_request'') }}'
|
||||||
|
@ -361,8 +361,8 @@ jobs:
|
||||||
path: |-
|
path: |-
|
||||||
~/.cargo/registry/index
|
~/.cargo/registry/index
|
||||||
~/.cargo/registry/cache
|
~/.cargo/registry/cache
|
||||||
key: '23-cargo-home-${{ matrix.os }}-${{ matrix.arch }}-${{ hashFiles(''Cargo.lock'') }}'
|
key: '24-cargo-home-${{ matrix.os }}-${{ matrix.arch }}-${{ hashFiles(''Cargo.lock'') }}'
|
||||||
restore-keys: '23-cargo-home-${{ matrix.os }}-${{ matrix.arch }}'
|
restore-keys: '24-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: '23-cargo-target-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.profile }}-${{ matrix.job }}-'
|
restore-keys: '24-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: '23-cargo-target-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.profile }}-${{ matrix.job }}-${{ github.sha }}'
|
key: '24-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
|
||||||
|
|
2
.github/workflows/post_publish.yml
vendored
2
.github/workflows/post_publish.yml
vendored
|
@ -7,7 +7,7 @@ on:
|
||||||
jobs:
|
jobs:
|
||||||
update-dl-version:
|
update-dl-version:
|
||||||
name: update dl.deno.land version
|
name: update dl.deno.land version
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-24.04
|
||||||
if: github.repository == 'denoland/deno'
|
if: github.repository == 'denoland/deno'
|
||||||
steps:
|
steps:
|
||||||
- name: Authenticate with Google Cloud
|
- name: Authenticate with Google Cloud
|
||||||
|
|
2
.github/workflows/start_release.yml
vendored
2
.github/workflows/start_release.yml
vendored
|
@ -16,7 +16,7 @@ on:
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
name: start release
|
name: start release
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-24.04
|
||||||
timeout-minutes: 30
|
timeout-minutes: 30
|
||||||
|
|
||||||
env:
|
env:
|
||||||
|
|
2
.github/workflows/version_bump.yml
vendored
2
.github/workflows/version_bump.yml
vendored
|
@ -16,7 +16,7 @@ on:
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
name: version bump
|
name: version bump
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-24.04
|
||||||
timeout-minutes: 90
|
timeout-minutes: 90
|
||||||
|
|
||||||
env:
|
env:
|
||||||
|
|
2
.github/workflows/wpt_epoch.yml
vendored
2
.github/workflows/wpt_epoch.yml
vendored
|
@ -20,7 +20,7 @@ jobs:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
deno-version: [v1.x, canary]
|
deno-version: [v1.x, canary]
|
||||||
os: [ubuntu-22.04-xl]
|
os: [ubuntu-24.04-xl]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Clone repository
|
- name: Clone repository
|
||||||
|
|
332
Cargo.lock
generated
332
Cargo.lock
generated
|
@ -765,6 +765,8 @@ dependencies = [
|
||||||
"fastwebsockets",
|
"fastwebsockets",
|
||||||
"file_test_runner",
|
"file_test_runner",
|
||||||
"flaky_test",
|
"flaky_test",
|
||||||
|
"hickory-client",
|
||||||
|
"hickory-server",
|
||||||
"http 1.1.0",
|
"http 1.1.0",
|
||||||
"http-body-util",
|
"http-body-util",
|
||||||
"hyper 1.4.1",
|
"hyper 1.4.1",
|
||||||
|
@ -778,8 +780,6 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
"test_server",
|
"test_server",
|
||||||
"tokio",
|
"tokio",
|
||||||
"trust-dns-client",
|
|
||||||
"trust-dns-server",
|
|
||||||
"url",
|
"url",
|
||||||
"uuid",
|
"uuid",
|
||||||
"zeromq",
|
"zeromq",
|
||||||
|
@ -1154,7 +1154,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno"
|
name = "deno"
|
||||||
version = "2.0.4"
|
version = "2.0.5"
|
||||||
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.169.0"
|
version = "0.170.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.169.0"
|
version = "0.170.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.107.0"
|
version = "0.108.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.44.0"
|
version = "0.45.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"deno_core",
|
"deno_core",
|
||||||
"deno_webgpu",
|
"deno_webgpu",
|
||||||
|
@ -1387,9 +1387,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_config"
|
name = "deno_config"
|
||||||
version = "0.37.2"
|
version = "0.38.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5900bfb37538d83b19ba0b157cdc785770e38422ee4632411e3bd3d90ac0f537"
|
checksum = "966825073480a6ac7e01977a3879d13edc8d6ea2d65ea164b37156a5fb206e9a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"deno_package_json",
|
"deno_package_json",
|
||||||
|
@ -1411,16 +1411,16 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_console"
|
name = "deno_console"
|
||||||
version = "0.175.0"
|
version = "0.176.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"deno_core",
|
"deno_core",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_core"
|
name = "deno_core"
|
||||||
version = "0.316.0"
|
version = "0.318.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "94f68061c88ced959c6b0417f0f0d0b3dbeaeb18013b55f86c505e9fba705cf8"
|
checksum = "10cae2393219ff9278123f7b24799cdfab37c7d6561b69ca06ced115cac92111"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bincode",
|
"bincode",
|
||||||
|
@ -1456,7 +1456,7 @@ checksum = "a13951ea98c0a4c372f162d669193b4c9d991512de9f2381dd161027f34b26b1"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_cron"
|
name = "deno_cron"
|
||||||
version = "0.55.0"
|
version = "0.56.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
|
@ -1469,7 +1469,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_crypto"
|
name = "deno_crypto"
|
||||||
version = "0.189.0"
|
version = "0.190.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aes",
|
"aes",
|
||||||
"aes-gcm",
|
"aes-gcm",
|
||||||
|
@ -1531,7 +1531,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_fetch"
|
name = "deno_fetch"
|
||||||
version = "0.199.0"
|
version = "0.200.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.162.0"
|
version = "0.163.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.85.0"
|
version = "0.86.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"base32",
|
"base32",
|
||||||
|
@ -1635,7 +1635,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_http"
|
name = "deno_http"
|
||||||
version = "0.173.0"
|
version = "0.174.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.85.0"
|
version = "0.86.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.83.0"
|
version = "0.84.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
|
@ -1767,7 +1767,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_napi"
|
name = "deno_napi"
|
||||||
version = "0.106.0"
|
version = "0.107.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"deno_core",
|
"deno_core",
|
||||||
"deno_permissions",
|
"deno_permissions",
|
||||||
|
@ -1795,24 +1795,24 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_net"
|
name = "deno_net"
|
||||||
version = "0.167.0"
|
version = "0.168.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"deno_core",
|
"deno_core",
|
||||||
"deno_permissions",
|
"deno_permissions",
|
||||||
"deno_tls",
|
"deno_tls",
|
||||||
|
"hickory-proto",
|
||||||
|
"hickory-resolver",
|
||||||
"pin-project",
|
"pin-project",
|
||||||
"rustls-tokio-stream",
|
"rustls-tokio-stream",
|
||||||
"serde",
|
"serde",
|
||||||
"socket2",
|
"socket2",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tokio",
|
"tokio",
|
||||||
"trust-dns-proto",
|
|
||||||
"trust-dns-resolver",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_node"
|
name = "deno_node"
|
||||||
version = "0.112.0"
|
version = "0.113.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aead-gcm-stream",
|
"aead-gcm-stream",
|
||||||
"aes",
|
"aes",
|
||||||
|
@ -1921,9 +1921,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_ops"
|
name = "deno_ops"
|
||||||
version = "0.192.0"
|
version = "0.194.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bdb7096887508456349d7e7e09e326d157d4dba46ef1f5849bc544592ea3042a"
|
checksum = "f760b492bd638c1dc3e992d11672c259fbe9a233162099a8347591c9e22d0391"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro-rules",
|
"proc-macro-rules",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
|
@ -1961,7 +1961,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_permissions"
|
name = "deno_permissions"
|
||||||
version = "0.35.0"
|
version = "0.36.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"deno_core",
|
"deno_core",
|
||||||
"deno_path_util",
|
"deno_path_util",
|
||||||
|
@ -1972,13 +1972,14 @@ dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
"serde",
|
"serde",
|
||||||
|
"thiserror",
|
||||||
"which 4.4.2",
|
"which 4.4.2",
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_resolver"
|
name = "deno_resolver"
|
||||||
version = "0.7.0"
|
version = "0.8.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"base32",
|
"base32",
|
||||||
|
@ -1994,7 +1995,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_runtime"
|
name = "deno_runtime"
|
||||||
version = "0.184.0"
|
version = "0.185.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"color-print",
|
"color-print",
|
||||||
"deno_ast",
|
"deno_ast",
|
||||||
|
@ -2112,7 +2113,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_tls"
|
name = "deno_tls"
|
||||||
version = "0.162.0"
|
version = "0.163.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"deno_core",
|
"deno_core",
|
||||||
"deno_native_certs",
|
"deno_native_certs",
|
||||||
|
@ -2161,7 +2162,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_url"
|
name = "deno_url"
|
||||||
version = "0.175.0"
|
version = "0.176.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"deno_bench_util",
|
"deno_bench_util",
|
||||||
"deno_console",
|
"deno_console",
|
||||||
|
@ -2173,7 +2174,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_web"
|
name = "deno_web"
|
||||||
version = "0.206.0"
|
version = "0.207.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"base64-simd 0.8.0",
|
"base64-simd 0.8.0",
|
||||||
|
@ -2195,7 +2196,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_webgpu"
|
name = "deno_webgpu"
|
||||||
version = "0.142.0"
|
version = "0.143.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"deno_core",
|
"deno_core",
|
||||||
"raw-window-handle",
|
"raw-window-handle",
|
||||||
|
@ -2208,7 +2209,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_webidl"
|
name = "deno_webidl"
|
||||||
version = "0.175.0"
|
version = "0.176.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"deno_bench_util",
|
"deno_bench_util",
|
||||||
"deno_core",
|
"deno_core",
|
||||||
|
@ -2216,7 +2217,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_websocket"
|
name = "deno_websocket"
|
||||||
version = "0.180.0"
|
version = "0.181.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"deno_core",
|
"deno_core",
|
||||||
|
@ -2238,7 +2239,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_webstorage"
|
name = "deno_webstorage"
|
||||||
version = "0.170.0"
|
version = "0.171.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"deno_core",
|
"deno_core",
|
||||||
"deno_web",
|
"deno_web",
|
||||||
|
@ -2608,9 +2609,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dprint-plugin-typescript"
|
name = "dprint-plugin-typescript"
|
||||||
version = "0.93.1"
|
version = "0.93.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5abfd78fe3cde4f5a6699d65f760c8d44da130cf446b6f80a7a9bc6580e156ab"
|
checksum = "3ff29fd136541e59d51946f0d2d353fefc886776f61a799ebfb5838b06cef13b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"deno_ast",
|
"deno_ast",
|
||||||
|
@ -2638,15 +2639,6 @@ dependencies = [
|
||||||
"text_lines",
|
"text_lines",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "drain"
|
|
||||||
version = "0.1.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9d105028bd2b5dfcb33318fd79a445001ead36004dd8dffef1bdd7e493d8bc1e"
|
|
||||||
dependencies = [
|
|
||||||
"tokio",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dsa"
|
name = "dsa"
|
||||||
version = "0.6.3"
|
version = "0.6.3"
|
||||||
|
@ -3544,6 +3536,92 @@ version = "0.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df"
|
checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hickory-client"
|
||||||
|
version = "0.24.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bab9683b08d8f8957a857b0236455d80e1886eaa8c6178af556aa7871fb61b55"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"data-encoding",
|
||||||
|
"futures-channel",
|
||||||
|
"futures-util",
|
||||||
|
"hickory-proto",
|
||||||
|
"once_cell",
|
||||||
|
"radix_trie",
|
||||||
|
"rand",
|
||||||
|
"thiserror",
|
||||||
|
"tokio",
|
||||||
|
"tracing",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hickory-proto"
|
||||||
|
version = "0.24.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "07698b8420e2f0d6447a436ba999ec85d8fbf2a398bbd737b82cac4a2e96e512"
|
||||||
|
dependencies = [
|
||||||
|
"async-trait",
|
||||||
|
"cfg-if",
|
||||||
|
"data-encoding",
|
||||||
|
"enum-as-inner",
|
||||||
|
"futures-channel",
|
||||||
|
"futures-io",
|
||||||
|
"futures-util",
|
||||||
|
"idna 0.4.0",
|
||||||
|
"ipnet",
|
||||||
|
"once_cell",
|
||||||
|
"rand",
|
||||||
|
"serde",
|
||||||
|
"thiserror",
|
||||||
|
"tinyvec",
|
||||||
|
"tokio",
|
||||||
|
"tracing",
|
||||||
|
"url",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hickory-resolver"
|
||||||
|
version = "0.24.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "28757f23aa75c98f254cf0405e6d8c25b831b32921b050a66692427679b1f243"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"futures-util",
|
||||||
|
"hickory-proto",
|
||||||
|
"ipconfig",
|
||||||
|
"lru-cache",
|
||||||
|
"once_cell",
|
||||||
|
"parking_lot",
|
||||||
|
"rand",
|
||||||
|
"resolv-conf",
|
||||||
|
"serde",
|
||||||
|
"smallvec",
|
||||||
|
"thiserror",
|
||||||
|
"tokio",
|
||||||
|
"tracing",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hickory-server"
|
||||||
|
version = "0.24.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9be0e43c556b9b3fdb6c7c71a9a32153a2275d02419e3de809e520bfcfe40c37"
|
||||||
|
dependencies = [
|
||||||
|
"async-trait",
|
||||||
|
"bytes",
|
||||||
|
"cfg-if",
|
||||||
|
"enum-as-inner",
|
||||||
|
"futures-util",
|
||||||
|
"hickory-proto",
|
||||||
|
"serde",
|
||||||
|
"thiserror",
|
||||||
|
"time",
|
||||||
|
"tokio",
|
||||||
|
"tokio-util",
|
||||||
|
"tracing",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hkdf"
|
name = "hkdf"
|
||||||
version = "0.12.4"
|
version = "0.12.4"
|
||||||
|
@ -4194,9 +4272,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libsui"
|
name = "libsui"
|
||||||
version = "0.4.0"
|
version = "0.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "205eca4e7beaad637dcd38fe41292065894ee7f498077cf3c135d5f7252b9f27"
|
checksum = "89795977654ad6250d6c0915411b622bac22f9efb4f852af94b2e00964cab832"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"editpe",
|
"editpe",
|
||||||
"libc",
|
"libc",
|
||||||
|
@ -4483,7 +4561,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "napi_sym"
|
name = "napi_sym"
|
||||||
version = "0.105.0"
|
version = "0.106.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"quote",
|
"quote",
|
||||||
"serde",
|
"serde",
|
||||||
|
@ -4538,7 +4616,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "node_resolver"
|
name = "node_resolver"
|
||||||
version = "0.14.0"
|
version = "0.15.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
|
@ -6146,15 +6224,6 @@ dependencies = [
|
||||||
"syn 2.0.72",
|
"syn 2.0.72",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "serde_spanned"
|
|
||||||
version = "0.6.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "79e674e01f999af37c49f70a6ede167a8a60b2503e56c5599532a65baa5969a0"
|
|
||||||
dependencies = [
|
|
||||||
"serde",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_urlencoded"
|
name = "serde_urlencoded"
|
||||||
version = "0.7.1"
|
version = "0.7.1"
|
||||||
|
@ -6169,9 +6238,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_v8"
|
name = "serde_v8"
|
||||||
version = "0.225.0"
|
version = "0.227.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ce4b71200ef49a9e629edaea3d13fc98c25ede07e1496558df7f09354e37976f"
|
checksum = "0a8294c2223c53bed343be8b80564ece4dc0d03b643b06fa86c4ccc0e064eda0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"num-bigint",
|
"num-bigint",
|
||||||
"serde",
|
"serde",
|
||||||
|
@ -7121,6 +7190,7 @@ dependencies = [
|
||||||
"console_static_text",
|
"console_static_text",
|
||||||
"deno_unsync",
|
"deno_unsync",
|
||||||
"denokv_proto",
|
"denokv_proto",
|
||||||
|
"faster-hex",
|
||||||
"fastwebsockets",
|
"fastwebsockets",
|
||||||
"flate2",
|
"flate2",
|
||||||
"futures",
|
"futures",
|
||||||
|
@ -7368,40 +7438,6 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "toml"
|
|
||||||
version = "0.7.8"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "dd79e69d3b627db300ff956027cc6c3798cef26d22526befdfcd12feeb6d2257"
|
|
||||||
dependencies = [
|
|
||||||
"serde",
|
|
||||||
"serde_spanned",
|
|
||||||
"toml_datetime",
|
|
||||||
"toml_edit",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "toml_datetime"
|
|
||||||
version = "0.6.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf"
|
|
||||||
dependencies = [
|
|
||||||
"serde",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "toml_edit"
|
|
||||||
version = "0.19.15"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421"
|
|
||||||
dependencies = [
|
|
||||||
"indexmap",
|
|
||||||
"serde",
|
|
||||||
"serde_spanned",
|
|
||||||
"toml_datetime",
|
|
||||||
"winnow 0.5.40",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tower"
|
name = "tower"
|
||||||
version = "0.4.13"
|
version = "0.4.13"
|
||||||
|
@ -7491,95 +7527,6 @@ dependencies = [
|
||||||
"stable_deref_trait",
|
"stable_deref_trait",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "trust-dns-client"
|
|
||||||
version = "0.23.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "14135e72c7e6d4c9b6902d4437881a8598f0145dbb2e3f86f92dbad845b61e63"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
"data-encoding",
|
|
||||||
"futures-channel",
|
|
||||||
"futures-util",
|
|
||||||
"once_cell",
|
|
||||||
"radix_trie",
|
|
||||||
"rand",
|
|
||||||
"thiserror",
|
|
||||||
"tokio",
|
|
||||||
"tracing",
|
|
||||||
"trust-dns-proto",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "trust-dns-proto"
|
|
||||||
version = "0.23.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "3119112651c157f4488931a01e586aa459736e9d6046d3bd9105ffb69352d374"
|
|
||||||
dependencies = [
|
|
||||||
"async-trait",
|
|
||||||
"cfg-if",
|
|
||||||
"data-encoding",
|
|
||||||
"enum-as-inner",
|
|
||||||
"futures-channel",
|
|
||||||
"futures-io",
|
|
||||||
"futures-util",
|
|
||||||
"idna 0.4.0",
|
|
||||||
"ipnet",
|
|
||||||
"once_cell",
|
|
||||||
"rand",
|
|
||||||
"serde",
|
|
||||||
"smallvec",
|
|
||||||
"thiserror",
|
|
||||||
"tinyvec",
|
|
||||||
"tokio",
|
|
||||||
"tracing",
|
|
||||||
"url",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "trust-dns-resolver"
|
|
||||||
version = "0.23.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "10a3e6c3aff1718b3c73e395d1f35202ba2ffa847c6a62eea0db8fb4cfe30be6"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
"futures-util",
|
|
||||||
"ipconfig",
|
|
||||||
"lru-cache",
|
|
||||||
"once_cell",
|
|
||||||
"parking_lot",
|
|
||||||
"rand",
|
|
||||||
"resolv-conf",
|
|
||||||
"serde",
|
|
||||||
"smallvec",
|
|
||||||
"thiserror",
|
|
||||||
"tokio",
|
|
||||||
"tracing",
|
|
||||||
"trust-dns-proto",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "trust-dns-server"
|
|
||||||
version = "0.23.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "c540f73c2b2ec2f6c54eabd0900e7aafb747a820224b742f556e8faabb461bc7"
|
|
||||||
dependencies = [
|
|
||||||
"async-trait",
|
|
||||||
"bytes",
|
|
||||||
"cfg-if",
|
|
||||||
"drain",
|
|
||||||
"enum-as-inner",
|
|
||||||
"futures-executor",
|
|
||||||
"futures-util",
|
|
||||||
"serde",
|
|
||||||
"thiserror",
|
|
||||||
"time",
|
|
||||||
"tokio",
|
|
||||||
"toml 0.7.8",
|
|
||||||
"tracing",
|
|
||||||
"trust-dns-proto",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "try-lock"
|
name = "try-lock"
|
||||||
version = "0.2.5"
|
version = "0.2.5"
|
||||||
|
@ -8329,15 +8276,6 @@ version = "0.52.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8"
|
checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "winnow"
|
|
||||||
version = "0.5.40"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876"
|
|
||||||
dependencies = [
|
|
||||||
"memchr",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winnow"
|
name = "winnow"
|
||||||
version = "0.6.15"
|
version = "0.6.15"
|
||||||
|
@ -8373,7 +8311,7 @@ version = "0.1.12"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b68db261ef59e9e52806f688020631e987592bd83619edccda9c47d42cde4f6c"
|
checksum = "b68db261ef59e9e52806f688020631e987592bd83619edccda9c47d42cde4f6c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"toml 0.5.11",
|
"toml",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -8450,7 +8388,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2a6a39b6b5ba0d02c910d05d7fbc366a4befb8901ea107dcde9c1c97acb8a366"
|
checksum = "2a6a39b6b5ba0d02c910d05d7fbc366a4befb8901ea107dcde9c1c97acb8a366"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"rowan",
|
"rowan",
|
||||||
"winnow 0.6.15",
|
"winnow",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
58
Cargo.toml
58
Cargo.toml
|
@ -46,18 +46,18 @@ repository = "https://github.com/denoland/deno"
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
deno_ast = { version = "=0.43.3", features = ["transpiling"] }
|
deno_ast = { version = "=0.43.3", features = ["transpiling"] }
|
||||||
deno_core = { version = "0.316.0" }
|
deno_core = { version = "0.318.0" }
|
||||||
|
|
||||||
deno_bench_util = { version = "0.169.0", path = "./bench_util" }
|
deno_bench_util = { version = "0.170.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.35.0", path = "./runtime/permissions" }
|
deno_permissions = { version = "0.36.0", path = "./runtime/permissions" }
|
||||||
deno_runtime = { version = "0.184.0", path = "./runtime" }
|
deno_runtime = { version = "0.185.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.105.0", path = "./ext/napi/sym" }
|
napi_sym = { version = "0.106.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.169.0", path = "./ext/broadcast_channel" }
|
deno_broadcast_channel = { version = "0.170.0", path = "./ext/broadcast_channel" }
|
||||||
deno_cache = { version = "0.107.0", path = "./ext/cache" }
|
deno_cache = { version = "0.108.0", path = "./ext/cache" }
|
||||||
deno_canvas = { version = "0.44.0", path = "./ext/canvas" }
|
deno_canvas = { version = "0.45.0", path = "./ext/canvas" }
|
||||||
deno_console = { version = "0.175.0", path = "./ext/console" }
|
deno_console = { version = "0.176.0", path = "./ext/console" }
|
||||||
deno_cron = { version = "0.55.0", path = "./ext/cron" }
|
deno_cron = { version = "0.56.0", path = "./ext/cron" }
|
||||||
deno_crypto = { version = "0.189.0", path = "./ext/crypto" }
|
deno_crypto = { version = "0.190.0", path = "./ext/crypto" }
|
||||||
deno_fetch = { version = "0.199.0", path = "./ext/fetch" }
|
deno_fetch = { version = "0.200.0", path = "./ext/fetch" }
|
||||||
deno_ffi = { version = "0.162.0", path = "./ext/ffi" }
|
deno_ffi = { version = "0.163.0", path = "./ext/ffi" }
|
||||||
deno_fs = { version = "0.85.0", path = "./ext/fs" }
|
deno_fs = { version = "0.86.0", path = "./ext/fs" }
|
||||||
deno_http = { version = "0.173.0", path = "./ext/http" }
|
deno_http = { version = "0.174.0", path = "./ext/http" }
|
||||||
deno_io = { version = "0.85.0", path = "./ext/io" }
|
deno_io = { version = "0.86.0", path = "./ext/io" }
|
||||||
deno_kv = { version = "0.83.0", path = "./ext/kv" }
|
deno_kv = { version = "0.84.0", path = "./ext/kv" }
|
||||||
deno_napi = { version = "0.106.0", path = "./ext/napi" }
|
deno_napi = { version = "0.107.0", path = "./ext/napi" }
|
||||||
deno_net = { version = "0.167.0", path = "./ext/net" }
|
deno_net = { version = "0.168.0", path = "./ext/net" }
|
||||||
deno_node = { version = "0.112.0", path = "./ext/node" }
|
deno_node = { version = "0.113.0", path = "./ext/node" }
|
||||||
deno_tls = { version = "0.162.0", path = "./ext/tls" }
|
deno_tls = { version = "0.163.0", path = "./ext/tls" }
|
||||||
deno_url = { version = "0.175.0", path = "./ext/url" }
|
deno_url = { version = "0.176.0", path = "./ext/url" }
|
||||||
deno_web = { version = "0.206.0", path = "./ext/web" }
|
deno_web = { version = "0.207.0", path = "./ext/web" }
|
||||||
deno_webgpu = { version = "0.142.0", path = "./ext/webgpu" }
|
deno_webgpu = { version = "0.143.0", path = "./ext/webgpu" }
|
||||||
deno_webidl = { version = "0.175.0", path = "./ext/webidl" }
|
deno_webidl = { version = "0.176.0", path = "./ext/webidl" }
|
||||||
deno_websocket = { version = "0.180.0", path = "./ext/websocket" }
|
deno_websocket = { version = "0.181.0", path = "./ext/websocket" }
|
||||||
deno_webstorage = { version = "0.170.0", path = "./ext/webstorage" }
|
deno_webstorage = { version = "0.171.0", path = "./ext/webstorage" }
|
||||||
|
|
||||||
# resolvers
|
# resolvers
|
||||||
deno_resolver = { version = "0.7.0", path = "./resolvers/deno" }
|
deno_resolver = { version = "0.8.0", path = "./resolvers/deno" }
|
||||||
node_resolver = { version = "0.14.0", path = "./resolvers/node" }
|
node_resolver = { version = "0.15.0", path = "./resolvers/node" }
|
||||||
|
|
||||||
aes = "=0.8.3"
|
aes = "=0.8.3"
|
||||||
anyhow = "1.0.57"
|
anyhow = "1.0.57"
|
||||||
|
|
36
Releases.md
36
Releases.md
|
@ -6,6 +6,42 @@ 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.5 / 2024.11.05
|
||||||
|
|
||||||
|
- fix(add): better error message when adding package that only has pre-release
|
||||||
|
versions (#26724)
|
||||||
|
- fix(add): only add npm deps to package.json if it's at least as close as
|
||||||
|
deno.json (#26683)
|
||||||
|
- fix(cli): set `npm_config_user_agent` when running npm packages or tasks
|
||||||
|
(#26639)
|
||||||
|
- fix(coverage): exclude comment lines from coverage reports (#25939)
|
||||||
|
- fix(ext/node): add `findSourceMap` to the default export of `node:module`
|
||||||
|
(#26720)
|
||||||
|
- fix(ext/node): convert errors from `fs.readFile/fs.readFileSync` to node
|
||||||
|
format (#26632)
|
||||||
|
- fix(ext/node): resolve exports even if parent module filename isn't present
|
||||||
|
(#26553)
|
||||||
|
- fix(ext/node): return `this` from `http.Server.ref/unref()` (#26647)
|
||||||
|
- fix(fmt): do not panic for jsx ignore container followed by jsx text (#26723)
|
||||||
|
- fix(fmt): fix several HTML and components issues (#26654)
|
||||||
|
- fix(fmt): ignore file directive for YAML files (#26717)
|
||||||
|
- fix(install): handle invalid function error, and fallback to junctions
|
||||||
|
regardless of the error (#26730)
|
||||||
|
- fix(lsp): include unstable features from editor settings (#26655)
|
||||||
|
- fix(lsp): scope attribution for lazily loaded assets (#26699)
|
||||||
|
- fix(node): Implement `os.userInfo` properly, add missing `toPrimitive`
|
||||||
|
(#24702)
|
||||||
|
- fix(serve): support serve hmr (#26078)
|
||||||
|
- fix(types): missing `import` permission on `PermissionOptionsObject` (#26627)
|
||||||
|
- fix(workspace): support wildcard packages (#26568)
|
||||||
|
- fix: clamp smi in fast calls by default (#26506)
|
||||||
|
- fix: improved support for cjs and cts modules (#26558)
|
||||||
|
- fix: op_run_microtasks crash (#26718)
|
||||||
|
- fix: panic_hook hangs without procfs (#26732)
|
||||||
|
- fix: remove permission check in op_require_node_module_paths (#26645)
|
||||||
|
- fix: surface package.json location on dep parse failure (#26665)
|
||||||
|
- perf(lsp): don't walk coverage directory (#26715)
|
||||||
|
|
||||||
### 2.0.4 / 2024.10.29
|
### 2.0.4 / 2024.10.29
|
||||||
|
|
||||||
- Revert "fix(ext/node): fix dns.lookup result ordering (#26264)" (#26621)
|
- Revert "fix(ext/node): fix dns.lookup result ordering (#26264)" (#26621)
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "deno_bench_util"
|
name = "deno_bench_util"
|
||||||
version = "0.169.0"
|
version = "0.170.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.4"
|
version = "2.0.5"
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
default-run = "deno"
|
default-run = "deno"
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
|
@ -70,7 +70,7 @@ winres.workspace = true
|
||||||
[dependencies]
|
[dependencies]
|
||||||
deno_ast = { workspace = true, features = ["bundler", "cjs", "codegen", "proposal", "react", "sourcemap", "transforms", "typescript", "view", "visit"] }
|
deno_ast = { workspace = true, features = ["bundler", "cjs", "codegen", "proposal", "react", "sourcemap", "transforms", "typescript", "view", "visit"] }
|
||||||
deno_cache_dir = { workspace = true }
|
deno_cache_dir = { workspace = true }
|
||||||
deno_config = { version = "=0.37.2", features = ["workspace", "sync"] }
|
deno_config = { version = "=0.38.2", features = ["workspace", "sync"] }
|
||||||
deno_core = { workspace = true, features = ["include_js_files_for_snapshotting"] }
|
deno_core = { workspace = true, features = ["include_js_files_for_snapshotting"] }
|
||||||
deno_doc = { version = "0.156.0", default-features = false, features = ["rust", "html", "syntect"] }
|
deno_doc = { version = "0.156.0", default-features = false, features = ["rust", "html", "syntect"] }
|
||||||
deno_graph = { version = "=0.84.1" }
|
deno_graph = { version = "=0.84.1" }
|
||||||
|
@ -84,7 +84,7 @@ deno_runtime = { workspace = true, features = ["include_js_files_for_snapshottin
|
||||||
deno_semver.workspace = true
|
deno_semver.workspace = true
|
||||||
deno_task_shell = "=0.18.1"
|
deno_task_shell = "=0.18.1"
|
||||||
deno_terminal.workspace = true
|
deno_terminal.workspace = true
|
||||||
libsui = "0.4.0"
|
libsui = "0.5.0"
|
||||||
node_resolver.workspace = true
|
node_resolver.workspace = true
|
||||||
|
|
||||||
anstream = "0.6.14"
|
anstream = "0.6.14"
|
||||||
|
@ -107,7 +107,7 @@ dotenvy = "0.15.7"
|
||||||
dprint-plugin-json = "=0.19.4"
|
dprint-plugin-json = "=0.19.4"
|
||||||
dprint-plugin-jupyter = "=0.1.5"
|
dprint-plugin-jupyter = "=0.1.5"
|
||||||
dprint-plugin-markdown = "=0.17.8"
|
dprint-plugin-markdown = "=0.17.8"
|
||||||
dprint-plugin-typescript = "=0.93.1"
|
dprint-plugin-typescript = "=0.93.2"
|
||||||
env_logger = "=0.10.0"
|
env_logger = "=0.10.0"
|
||||||
fancy-regex = "=0.10.0"
|
fancy-regex = "=0.10.0"
|
||||||
faster-hex.workspace = true
|
faster-hex.workspace = true
|
||||||
|
|
|
@ -3388,8 +3388,7 @@ fn permission_args(app: Command, requires: Option<&'static str>) -> Command {
|
||||||
.value_name("IP_OR_HOSTNAME")
|
.value_name("IP_OR_HOSTNAME")
|
||||||
.help("Allow network access. Optionally specify allowed IP addresses and host names, with ports as necessary")
|
.help("Allow network access. Optionally specify allowed IP addresses and host names, with ports as necessary")
|
||||||
.value_parser(flags_net::validator)
|
.value_parser(flags_net::validator)
|
||||||
.hide(true)
|
.hide(true);
|
||||||
;
|
|
||||||
if let Some(requires) = requires {
|
if let Some(requires) = requires {
|
||||||
arg = arg.requires(requires)
|
arg = arg.requires(requires)
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,7 +51,7 @@ pub fn parse(paths: Vec<String>) -> clap::error::Result<Vec<String>> {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
NetDescriptor::parse(&host_and_port).map_err(|e| {
|
NetDescriptor::parse(&host_and_port).map_err(|e| {
|
||||||
clap::Error::raw(clap::error::ErrorKind::InvalidValue, format!("{e:?}"))
|
clap::Error::raw(clap::error::ErrorKind::InvalidValue, e.to_string())
|
||||||
})?;
|
})?;
|
||||||
out.push(host_and_port)
|
out.push(host_and_port)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||||
|
// deno-lint-ignore-file no-console no-process-globals
|
||||||
// deno-lint-ignore-file no-console
|
|
||||||
|
|
||||||
let [total, count] = typeof Deno !== "undefined"
|
let [total, count] = typeof Deno !== "undefined"
|
||||||
? Deno.args
|
? Deno.args
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||||
|
// deno-lint-ignore-file no-console no-process-globals
|
||||||
// deno-lint-ignore-file no-console
|
|
||||||
|
|
||||||
let [total, count] = typeof Deno !== "undefined"
|
let [total, count] = typeof Deno !== "undefined"
|
||||||
? Deno.args
|
? Deno.args
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||||
|
// deno-lint-ignore-file no-console no-process-globals
|
||||||
// deno-lint-ignore-file no-console
|
|
||||||
|
|
||||||
const queueMicrotask = globalThis.queueMicrotask || process.nextTick;
|
const queueMicrotask = globalThis.queueMicrotask || process.nextTick;
|
||||||
let [total, count] = typeof Deno !== "undefined"
|
let [total, count] = typeof Deno !== "undefined"
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||||
|
// deno-lint-ignore-file no-console no-process-globals
|
||||||
// deno-lint-ignore-file no-console
|
|
||||||
|
|
||||||
let [total, count] = typeof Deno !== "undefined"
|
let [total, count] = typeof Deno !== "undefined"
|
||||||
? Deno.args
|
? Deno.args
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||||
|
// deno-lint-ignore-file no-console no-process-globals
|
||||||
// deno-lint-ignore-file no-console
|
|
||||||
|
|
||||||
const queueMicrotask = globalThis.queueMicrotask || process.nextTick;
|
const queueMicrotask = globalThis.queueMicrotask || process.nextTick;
|
||||||
let [total, count] = typeof Deno !== "undefined"
|
let [total, count] = typeof Deno !== "undefined"
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||||
|
// deno-lint-ignore-file no-console no-process-globals
|
||||||
// deno-lint-ignore-file no-console
|
|
||||||
|
|
||||||
const queueMicrotask = globalThis.queueMicrotask || process.nextTick;
|
const queueMicrotask = globalThis.queueMicrotask || process.nextTick;
|
||||||
let [total, count] = typeof Deno !== "undefined"
|
let [total, count] = typeof Deno !== "undefined"
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||||
|
// deno-lint-ignore-file no-console no-process-globals
|
||||||
// deno-lint-ignore-file no-console
|
|
||||||
|
|
||||||
const queueMicrotask = globalThis.queueMicrotask || process.nextTick;
|
const queueMicrotask = globalThis.queueMicrotask || process.nextTick;
|
||||||
let [total, count] = typeof Deno !== "undefined"
|
let [total, count] = typeof Deno !== "undefined"
|
||||||
|
|
|
@ -88,6 +88,10 @@ fn get_resolution_error_class(err: &ResolutionError) -> &'static str {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_try_from_int_error_class(_: &std::num::TryFromIntError) -> &'static str {
|
||||||
|
"TypeError"
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_error_class_name(e: &AnyError) -> &'static str {
|
pub fn get_error_class_name(e: &AnyError) -> &'static str {
|
||||||
deno_runtime::errors::get_error_class_name(e)
|
deno_runtime::errors::get_error_class_name(e)
|
||||||
.or_else(|| {
|
.or_else(|| {
|
||||||
|
@ -106,5 +110,9 @@ pub fn get_error_class_name(e: &AnyError) -> &'static str {
|
||||||
e.downcast_ref::<ResolutionError>()
|
e.downcast_ref::<ResolutionError>()
|
||||||
.map(get_resolution_error_class)
|
.map(get_resolution_error_class)
|
||||||
})
|
})
|
||||||
|
.or_else(|| {
|
||||||
|
e.downcast_ref::<std::num::TryFromIntError>()
|
||||||
|
.map(get_try_from_int_error_class)
|
||||||
|
})
|
||||||
.unwrap_or("Error")
|
.unwrap_or("Error")
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,9 @@ use super::urls::url_to_uri;
|
||||||
use crate::args::jsr_url;
|
use crate::args::jsr_url;
|
||||||
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 deno_config::workspace::MappedResolution;
|
use deno_config::workspace::MappedResolution;
|
||||||
|
use deno_graph::source::ResolutionMode;
|
||||||
use deno_lint::diagnostic::LintDiagnosticRange;
|
use deno_lint::diagnostic::LintDiagnosticRange;
|
||||||
|
|
||||||
use deno_ast::SourceRange;
|
use deno_ast::SourceRange;
|
||||||
|
@ -228,6 +230,7 @@ pub struct TsResponseImportMapper<'a> {
|
||||||
documents: &'a Documents,
|
documents: &'a Documents,
|
||||||
maybe_import_map: Option<&'a ImportMap>,
|
maybe_import_map: Option<&'a ImportMap>,
|
||||||
resolver: &'a LspResolver,
|
resolver: &'a LspResolver,
|
||||||
|
tsc_specifier_map: &'a tsc::TscSpecifierMap,
|
||||||
file_referrer: ModuleSpecifier,
|
file_referrer: ModuleSpecifier,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -236,12 +239,14 @@ impl<'a> TsResponseImportMapper<'a> {
|
||||||
documents: &'a Documents,
|
documents: &'a Documents,
|
||||||
maybe_import_map: Option<&'a ImportMap>,
|
maybe_import_map: Option<&'a ImportMap>,
|
||||||
resolver: &'a LspResolver,
|
resolver: &'a LspResolver,
|
||||||
|
tsc_specifier_map: &'a tsc::TscSpecifierMap,
|
||||||
file_referrer: &ModuleSpecifier,
|
file_referrer: &ModuleSpecifier,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
documents,
|
documents,
|
||||||
maybe_import_map,
|
maybe_import_map,
|
||||||
resolver,
|
resolver,
|
||||||
|
tsc_specifier_map,
|
||||||
file_referrer: file_referrer.clone(),
|
file_referrer: file_referrer.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -387,6 +392,11 @@ impl<'a> TsResponseImportMapper<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if let Some(dep_name) = self
|
||||||
|
.resolver
|
||||||
|
.file_url_to_package_json_dep(specifier, Some(&self.file_referrer))
|
||||||
|
{
|
||||||
|
return Some(dep_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if the import map has this specifier
|
// check if the import map has this specifier
|
||||||
|
@ -457,20 +467,37 @@ impl<'a> TsResponseImportMapper<'a> {
|
||||||
specifier: &str,
|
specifier: &str,
|
||||||
referrer: &ModuleSpecifier,
|
referrer: &ModuleSpecifier,
|
||||||
) -> Option<String> {
|
) -> Option<String> {
|
||||||
if let Ok(specifier) = referrer.join(specifier) {
|
let specifier_stem = specifier.strip_suffix(".js").unwrap_or(specifier);
|
||||||
if let Some(specifier) = self.check_specifier(&specifier, referrer) {
|
let specifiers = std::iter::once(Cow::Borrowed(specifier)).chain(
|
||||||
|
SUPPORTED_EXTENSIONS
|
||||||
|
.iter()
|
||||||
|
.map(|ext| Cow::Owned(format!("{specifier_stem}{ext}"))),
|
||||||
|
);
|
||||||
|
for specifier in specifiers {
|
||||||
|
if let Some(specifier) = self
|
||||||
|
.resolver
|
||||||
|
.as_graph_resolver(Some(&self.file_referrer))
|
||||||
|
.resolve(
|
||||||
|
&specifier,
|
||||||
|
&deno_graph::Range {
|
||||||
|
specifier: referrer.clone(),
|
||||||
|
start: deno_graph::Position::zeroed(),
|
||||||
|
end: deno_graph::Position::zeroed(),
|
||||||
|
},
|
||||||
|
ResolutionMode::Types,
|
||||||
|
)
|
||||||
|
.ok()
|
||||||
|
.and_then(|s| self.tsc_specifier_map.normalize(s.as_str()).ok())
|
||||||
|
.filter(|s| self.documents.exists(s, Some(&self.file_referrer)))
|
||||||
|
{
|
||||||
|
if let Some(specifier) = self
|
||||||
|
.check_specifier(&specifier, referrer)
|
||||||
|
.or_else(|| relative_specifier(referrer, &specifier))
|
||||||
|
.filter(|s| !s.contains("/node_modules/"))
|
||||||
|
{
|
||||||
return Some(specifier);
|
return Some(specifier);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let specifier = specifier.strip_suffix(".js").unwrap_or(specifier);
|
|
||||||
for ext in SUPPORTED_EXTENSIONS {
|
|
||||||
let specifier_with_ext = format!("{specifier}{ext}");
|
|
||||||
if self
|
|
||||||
.documents
|
|
||||||
.contains_import(&specifier_with_ext, referrer)
|
|
||||||
{
|
|
||||||
return Some(specifier_with_ext);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -559,8 +586,9 @@ fn try_reverse_map_package_json_exports(
|
||||||
pub fn fix_ts_import_changes(
|
pub fn fix_ts_import_changes(
|
||||||
referrer: &ModuleSpecifier,
|
referrer: &ModuleSpecifier,
|
||||||
changes: &[tsc::FileTextChanges],
|
changes: &[tsc::FileTextChanges],
|
||||||
import_mapper: &TsResponseImportMapper,
|
language_server: &language_server::Inner,
|
||||||
) -> Result<Vec<tsc::FileTextChanges>, AnyError> {
|
) -> Result<Vec<tsc::FileTextChanges>, AnyError> {
|
||||||
|
let import_mapper = language_server.get_ts_response_import_mapper(referrer);
|
||||||
let mut r = Vec::new();
|
let mut r = Vec::new();
|
||||||
for change in changes {
|
for change in changes {
|
||||||
let mut text_changes = Vec::new();
|
let mut text_changes = Vec::new();
|
||||||
|
@ -605,7 +633,7 @@ pub fn fix_ts_import_changes(
|
||||||
fn fix_ts_import_action<'a>(
|
fn fix_ts_import_action<'a>(
|
||||||
referrer: &ModuleSpecifier,
|
referrer: &ModuleSpecifier,
|
||||||
action: &'a tsc::CodeFixAction,
|
action: &'a tsc::CodeFixAction,
|
||||||
import_mapper: &TsResponseImportMapper,
|
language_server: &language_server::Inner,
|
||||||
) -> Option<Cow<'a, tsc::CodeFixAction>> {
|
) -> Option<Cow<'a, tsc::CodeFixAction>> {
|
||||||
if !matches!(
|
if !matches!(
|
||||||
action.fix_name.as_str(),
|
action.fix_name.as_str(),
|
||||||
|
@ -621,6 +649,7 @@ fn fix_ts_import_action<'a>(
|
||||||
let Some(specifier) = specifier else {
|
let Some(specifier) = specifier else {
|
||||||
return Some(Cow::Borrowed(action));
|
return Some(Cow::Borrowed(action));
|
||||||
};
|
};
|
||||||
|
let import_mapper = language_server.get_ts_response_import_mapper(referrer);
|
||||||
if let Some(new_specifier) =
|
if let Some(new_specifier) =
|
||||||
import_mapper.check_unresolved_specifier(specifier, referrer)
|
import_mapper.check_unresolved_specifier(specifier, referrer)
|
||||||
{
|
{
|
||||||
|
@ -728,7 +757,7 @@ pub fn ts_changes_to_edit(
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct CodeActionData {
|
pub struct CodeActionData {
|
||||||
pub specifier: ModuleSpecifier,
|
pub specifier: ModuleSpecifier,
|
||||||
|
@ -998,11 +1027,8 @@ impl CodeActionCollection {
|
||||||
"The action returned from TypeScript is unsupported.",
|
"The action returned from TypeScript is unsupported.",
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
let Some(action) = fix_ts_import_action(
|
let Some(action) = fix_ts_import_action(specifier, action, language_server)
|
||||||
specifier,
|
else {
|
||||||
action,
|
|
||||||
&language_server.get_ts_response_import_mapper(specifier),
|
|
||||||
) else {
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
};
|
};
|
||||||
let edit = ts_changes_to_edit(&action.changes, language_server)?;
|
let edit = ts_changes_to_edit(&action.changes, language_server)?;
|
||||||
|
@ -1051,10 +1077,12 @@ impl CodeActionCollection {
|
||||||
specifier: &ModuleSpecifier,
|
specifier: &ModuleSpecifier,
|
||||||
diagnostic: &lsp::Diagnostic,
|
diagnostic: &lsp::Diagnostic,
|
||||||
) {
|
) {
|
||||||
let data = Some(json!({
|
let data = action.fix_id.as_ref().map(|fix_id| {
|
||||||
"specifier": specifier,
|
json!(CodeActionData {
|
||||||
"fixId": action.fix_id,
|
specifier: specifier.clone(),
|
||||||
}));
|
fix_id: fix_id.clone(),
|
||||||
|
})
|
||||||
|
});
|
||||||
let title = if let Some(description) = &action.fix_all_description {
|
let title = if let Some(description) = &action.fix_all_description {
|
||||||
description.clone()
|
description.clone()
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1059,34 +1059,6 @@ impl Documents {
|
||||||
self.cache.is_valid_file_referrer(specifier)
|
self.cache.is_valid_file_referrer(specifier)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return `true` if the provided specifier can be resolved to a document,
|
|
||||||
/// otherwise `false`.
|
|
||||||
pub fn contains_import(
|
|
||||||
&self,
|
|
||||||
specifier: &str,
|
|
||||||
referrer: &ModuleSpecifier,
|
|
||||||
) -> bool {
|
|
||||||
let file_referrer = self.get_file_referrer(referrer);
|
|
||||||
let maybe_specifier = self
|
|
||||||
.resolver
|
|
||||||
.as_graph_resolver(file_referrer.as_deref())
|
|
||||||
.resolve(
|
|
||||||
specifier,
|
|
||||||
&deno_graph::Range {
|
|
||||||
specifier: referrer.clone(),
|
|
||||||
start: deno_graph::Position::zeroed(),
|
|
||||||
end: deno_graph::Position::zeroed(),
|
|
||||||
},
|
|
||||||
ResolutionMode::Types,
|
|
||||||
)
|
|
||||||
.ok();
|
|
||||||
if let Some(import_specifier) = maybe_specifier {
|
|
||||||
self.exists(&import_specifier, file_referrer.as_deref())
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn resolve_document_specifier(
|
pub fn resolve_document_specifier(
|
||||||
&self,
|
&self,
|
||||||
specifier: &ModuleSpecifier,
|
specifier: &ModuleSpecifier,
|
||||||
|
|
|
@ -863,7 +863,10 @@ impl Inner {
|
||||||
// We ignore these directories by default because there is a
|
// We ignore these directories by default because there is a
|
||||||
// high likelihood they aren't relevant. Someone can opt-into
|
// high likelihood they aren't relevant. Someone can opt-into
|
||||||
// them by specifying one of them as an enabled path.
|
// them by specifying one of them as an enabled path.
|
||||||
if matches!(dir_name.as_str(), "vendor" | "node_modules" | ".git") {
|
if matches!(
|
||||||
|
dir_name.as_str(),
|
||||||
|
"vendor" | "coverage" | "node_modules" | ".git"
|
||||||
|
) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// ignore cargo target directories for anyone using Deno with Rust
|
// ignore cargo target directories for anyone using Deno with Rust
|
||||||
|
@ -1834,7 +1837,7 @@ impl Inner {
|
||||||
fix_ts_import_changes(
|
fix_ts_import_changes(
|
||||||
&code_action_data.specifier,
|
&code_action_data.specifier,
|
||||||
&combined_code_actions.changes,
|
&combined_code_actions.changes,
|
||||||
&self.get_ts_response_import_mapper(&code_action_data.specifier),
|
self,
|
||||||
)
|
)
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
error!("Unable to remap changes: {:#}", err);
|
error!("Unable to remap changes: {:#}", err);
|
||||||
|
@ -1887,7 +1890,7 @@ impl Inner {
|
||||||
refactor_edit_info.edits = fix_ts_import_changes(
|
refactor_edit_info.edits = fix_ts_import_changes(
|
||||||
&action_data.specifier,
|
&action_data.specifier,
|
||||||
&refactor_edit_info.edits,
|
&refactor_edit_info.edits,
|
||||||
&self.get_ts_response_import_mapper(&action_data.specifier),
|
self,
|
||||||
)
|
)
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
error!("Unable to remap changes: {:#}", err);
|
error!("Unable to remap changes: {:#}", err);
|
||||||
|
@ -1918,7 +1921,8 @@ impl Inner {
|
||||||
// todo(dsherret): this should probably just take the resolver itself
|
// todo(dsherret): this should probably just take the resolver itself
|
||||||
// as the import map is an implementation detail
|
// as the import map is an implementation detail
|
||||||
.and_then(|d| d.resolver.maybe_import_map()),
|
.and_then(|d| d.resolver.maybe_import_map()),
|
||||||
self.resolver.as_ref(),
|
&self.resolver,
|
||||||
|
&self.ts_server.specifier_map,
|
||||||
file_referrer,
|
file_referrer,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -2281,7 +2285,11 @@ impl Inner {
|
||||||
.into(),
|
.into(),
|
||||||
scope.cloned(),
|
scope.cloned(),
|
||||||
)
|
)
|
||||||
.await;
|
.await
|
||||||
|
.unwrap_or_else(|err| {
|
||||||
|
error!("Unable to get completion info from TypeScript: {:#}", err);
|
||||||
|
None
|
||||||
|
});
|
||||||
|
|
||||||
if let Some(completions) = maybe_completion_info {
|
if let Some(completions) = maybe_completion_info {
|
||||||
response = Some(
|
response = Some(
|
||||||
|
@ -3944,7 +3952,9 @@ mod tests {
|
||||||
fn test_walk_workspace() {
|
fn test_walk_workspace() {
|
||||||
let temp_dir = TempDir::new();
|
let temp_dir = TempDir::new();
|
||||||
temp_dir.create_dir_all("root1/vendor/");
|
temp_dir.create_dir_all("root1/vendor/");
|
||||||
|
temp_dir.create_dir_all("root1/coverage/");
|
||||||
temp_dir.write("root1/vendor/mod.ts", ""); // no, vendor
|
temp_dir.write("root1/vendor/mod.ts", ""); // no, vendor
|
||||||
|
temp_dir.write("root1/coverage/mod.ts", ""); // no, coverage
|
||||||
|
|
||||||
temp_dir.create_dir_all("root1/node_modules/");
|
temp_dir.create_dir_all("root1/node_modules/");
|
||||||
temp_dir.write("root1/node_modules/mod.ts", ""); // no, node_modules
|
temp_dir.write("root1/node_modules/mod.ts", ""); // no, node_modules
|
||||||
|
|
|
@ -74,6 +74,7 @@ struct LspScopeResolver {
|
||||||
pkg_json_resolver: Option<Arc<PackageJsonResolver>>,
|
pkg_json_resolver: Option<Arc<PackageJsonResolver>>,
|
||||||
redirect_resolver: Option<Arc<RedirectResolver>>,
|
redirect_resolver: Option<Arc<RedirectResolver>>,
|
||||||
graph_imports: Arc<IndexMap<ModuleSpecifier, GraphImport>>,
|
graph_imports: Arc<IndexMap<ModuleSpecifier, GraphImport>>,
|
||||||
|
package_json_deps_by_resolution: Arc<IndexMap<ModuleSpecifier, String>>,
|
||||||
config_data: Option<Arc<ConfigData>>,
|
config_data: Option<Arc<ConfigData>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,6 +89,7 @@ impl Default for LspScopeResolver {
|
||||||
pkg_json_resolver: None,
|
pkg_json_resolver: None,
|
||||||
redirect_resolver: None,
|
redirect_resolver: None,
|
||||||
graph_imports: Default::default(),
|
graph_imports: Default::default(),
|
||||||
|
package_json_deps_by_resolution: Default::default(),
|
||||||
config_data: None,
|
config_data: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -165,6 +167,33 @@ impl LspScopeResolver {
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
let package_json_deps_by_resolution = (|| {
|
||||||
|
let node_resolver = node_resolver.as_ref()?;
|
||||||
|
let package_json = config_data?.maybe_pkg_json()?;
|
||||||
|
let referrer = package_json.specifier();
|
||||||
|
let dependencies = package_json.dependencies.as_ref()?;
|
||||||
|
let result = dependencies
|
||||||
|
.iter()
|
||||||
|
.flat_map(|(name, _)| {
|
||||||
|
let req_ref =
|
||||||
|
NpmPackageReqReference::from_str(&format!("npm:{name}")).ok()?;
|
||||||
|
let specifier = into_specifier_and_media_type(Some(
|
||||||
|
node_resolver
|
||||||
|
.resolve_req_reference(
|
||||||
|
&req_ref,
|
||||||
|
&referrer,
|
||||||
|
NodeResolutionMode::Types,
|
||||||
|
)
|
||||||
|
.ok()?,
|
||||||
|
))
|
||||||
|
.0;
|
||||||
|
Some((specifier, name.clone()))
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
Some(result)
|
||||||
|
})();
|
||||||
|
let package_json_deps_by_resolution =
|
||||||
|
Arc::new(package_json_deps_by_resolution.unwrap_or_default());
|
||||||
Self {
|
Self {
|
||||||
cjs_tracker: lsp_cjs_tracker,
|
cjs_tracker: lsp_cjs_tracker,
|
||||||
graph_resolver,
|
graph_resolver,
|
||||||
|
@ -174,6 +203,7 @@ impl LspScopeResolver {
|
||||||
pkg_json_resolver: Some(pkg_json_resolver),
|
pkg_json_resolver: Some(pkg_json_resolver),
|
||||||
redirect_resolver,
|
redirect_resolver,
|
||||||
graph_imports,
|
graph_imports,
|
||||||
|
package_json_deps_by_resolution,
|
||||||
config_data: config_data.cloned(),
|
config_data: config_data.cloned(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -216,6 +246,9 @@ impl LspScopeResolver {
|
||||||
redirect_resolver: self.redirect_resolver.clone(),
|
redirect_resolver: self.redirect_resolver.clone(),
|
||||||
pkg_json_resolver: Some(pkg_json_resolver),
|
pkg_json_resolver: Some(pkg_json_resolver),
|
||||||
graph_imports: self.graph_imports.clone(),
|
graph_imports: self.graph_imports.clone(),
|
||||||
|
package_json_deps_by_resolution: self
|
||||||
|
.package_json_deps_by_resolution
|
||||||
|
.clone(),
|
||||||
config_data: self.config_data.clone(),
|
config_data: self.config_data.clone(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -407,6 +440,18 @@ impl LspResolver {
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn file_url_to_package_json_dep(
|
||||||
|
&self,
|
||||||
|
specifier: &ModuleSpecifier,
|
||||||
|
file_referrer: Option<&ModuleSpecifier>,
|
||||||
|
) -> Option<String> {
|
||||||
|
let resolver = self.get_scope_resolver(file_referrer);
|
||||||
|
resolver
|
||||||
|
.package_json_deps_by_resolution
|
||||||
|
.get(specifier)
|
||||||
|
.cloned()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn in_node_modules(&self, specifier: &ModuleSpecifier) -> bool {
|
pub fn in_node_modules(&self, specifier: &ModuleSpecifier) -> bool {
|
||||||
fn has_node_modules_dir(specifier: &ModuleSpecifier) -> bool {
|
fn has_node_modules_dir(specifier: &ModuleSpecifier) -> bool {
|
||||||
// consider any /node_modules/ directory as being in the node_modules
|
// consider any /node_modules/ directory as being in the node_modules
|
||||||
|
|
|
@ -236,7 +236,7 @@ pub struct TsServer {
|
||||||
performance: Arc<Performance>,
|
performance: Arc<Performance>,
|
||||||
sender: mpsc::UnboundedSender<Request>,
|
sender: mpsc::UnboundedSender<Request>,
|
||||||
receiver: Mutex<Option<mpsc::UnboundedReceiver<Request>>>,
|
receiver: Mutex<Option<mpsc::UnboundedReceiver<Request>>>,
|
||||||
specifier_map: Arc<TscSpecifierMap>,
|
pub specifier_map: Arc<TscSpecifierMap>,
|
||||||
inspector_server: Mutex<Option<Arc<InspectorServer>>>,
|
inspector_server: Mutex<Option<Arc<InspectorServer>>>,
|
||||||
pending_change: Mutex<Option<PendingChange>>,
|
pending_change: Mutex<Option<PendingChange>>,
|
||||||
}
|
}
|
||||||
|
@ -882,20 +882,22 @@ impl TsServer {
|
||||||
options: GetCompletionsAtPositionOptions,
|
options: GetCompletionsAtPositionOptions,
|
||||||
format_code_settings: FormatCodeSettings,
|
format_code_settings: FormatCodeSettings,
|
||||||
scope: Option<ModuleSpecifier>,
|
scope: Option<ModuleSpecifier>,
|
||||||
) -> Option<CompletionInfo> {
|
) -> Result<Option<CompletionInfo>, AnyError> {
|
||||||
let req = TscRequest::GetCompletionsAtPosition(Box::new((
|
let req = TscRequest::GetCompletionsAtPosition(Box::new((
|
||||||
self.specifier_map.denormalize(&specifier),
|
self.specifier_map.denormalize(&specifier),
|
||||||
position,
|
position,
|
||||||
options,
|
options,
|
||||||
format_code_settings,
|
format_code_settings,
|
||||||
)));
|
)));
|
||||||
match self.request(snapshot, req, scope).await {
|
self
|
||||||
Ok(maybe_info) => maybe_info,
|
.request::<Option<CompletionInfo>>(snapshot, req, scope)
|
||||||
Err(err) => {
|
.await
|
||||||
log::error!("Unable to get completion info from TypeScript: {:#}", err);
|
.map(|mut info| {
|
||||||
None
|
if let Some(info) = &mut info {
|
||||||
}
|
info.normalize(&self.specifier_map);
|
||||||
}
|
}
|
||||||
|
info
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_completion_details(
|
pub async fn get_completion_details(
|
||||||
|
@ -3642,6 +3644,12 @@ pub struct CompletionInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CompletionInfo {
|
impl CompletionInfo {
|
||||||
|
fn normalize(&mut self, specifier_map: &TscSpecifierMap) {
|
||||||
|
for entry in &mut self.entries {
|
||||||
|
entry.normalize(specifier_map);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn as_completion_response(
|
pub fn as_completion_response(
|
||||||
&self,
|
&self,
|
||||||
line_index: Arc<LineIndex>,
|
line_index: Arc<LineIndex>,
|
||||||
|
@ -3703,11 +3711,17 @@ pub struct CompletionItemData {
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
struct CompletionEntryDataImport {
|
struct CompletionEntryDataAutoImport {
|
||||||
module_specifier: String,
|
module_specifier: String,
|
||||||
file_name: String,
|
file_name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct CompletionNormalizedAutoImportData {
|
||||||
|
raw: CompletionEntryDataAutoImport,
|
||||||
|
normalized: ModuleSpecifier,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Deserialize, Serialize)]
|
#[derive(Debug, Default, Deserialize, Serialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct CompletionEntry {
|
pub struct CompletionEntry {
|
||||||
|
@ -3740,9 +3754,28 @@ pub struct CompletionEntry {
|
||||||
is_import_statement_completion: Option<bool>,
|
is_import_statement_completion: Option<bool>,
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
data: Option<Value>,
|
data: Option<Value>,
|
||||||
|
/// This is not from tsc, we add it for convenience during normalization.
|
||||||
|
/// Represents `self.data.file_name`, but normalized.
|
||||||
|
#[serde(skip)]
|
||||||
|
auto_import_data: Option<CompletionNormalizedAutoImportData>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CompletionEntry {
|
impl CompletionEntry {
|
||||||
|
fn normalize(&mut self, specifier_map: &TscSpecifierMap) {
|
||||||
|
let Some(data) = &self.data else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let Ok(raw) =
|
||||||
|
serde_json::from_value::<CompletionEntryDataAutoImport>(data.clone())
|
||||||
|
else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
if let Ok(normalized) = specifier_map.normalize(&raw.file_name) {
|
||||||
|
self.auto_import_data =
|
||||||
|
Some(CompletionNormalizedAutoImportData { raw, normalized });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn get_commit_characters(
|
fn get_commit_characters(
|
||||||
&self,
|
&self,
|
||||||
info: &CompletionInfo,
|
info: &CompletionInfo,
|
||||||
|
@ -3891,27 +3924,26 @@ impl CompletionEntry {
|
||||||
|
|
||||||
if let Some(source) = &self.source {
|
if let Some(source) = &self.source {
|
||||||
let mut display_source = source.clone();
|
let mut display_source = source.clone();
|
||||||
if let Some(data) = &self.data {
|
if let Some(import_data) = &self.auto_import_data {
|
||||||
if let Ok(import_data) =
|
|
||||||
serde_json::from_value::<CompletionEntryDataImport>(data.clone())
|
|
||||||
{
|
|
||||||
if let Ok(import_specifier) = resolve_url(&import_data.file_name) {
|
|
||||||
if let Some(new_module_specifier) = language_server
|
if let Some(new_module_specifier) = language_server
|
||||||
.get_ts_response_import_mapper(specifier)
|
.get_ts_response_import_mapper(specifier)
|
||||||
.check_specifier(&import_specifier, specifier)
|
.check_specifier(&import_data.normalized, specifier)
|
||||||
.or_else(|| relative_specifier(specifier, &import_specifier))
|
.or_else(|| relative_specifier(specifier, &import_data.normalized))
|
||||||
{
|
{
|
||||||
|
if new_module_specifier.contains("/node_modules/") {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
display_source.clone_from(&new_module_specifier);
|
display_source.clone_from(&new_module_specifier);
|
||||||
if new_module_specifier != import_data.module_specifier {
|
if new_module_specifier != import_data.raw.module_specifier {
|
||||||
specifier_rewrite =
|
specifier_rewrite = Some((
|
||||||
Some((import_data.module_specifier, new_module_specifier));
|
import_data.raw.module_specifier.clone(),
|
||||||
|
new_module_specifier,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
} else if source.starts_with(jsr_url().as_str()) {
|
} else if source.starts_with(jsr_url().as_str()) {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
// We want relative or bare (import-mapped or otherwise) specifiers to
|
// We want relative or bare (import-mapped or otherwise) specifiers to
|
||||||
// appear at the top.
|
// appear at the top.
|
||||||
if resolve_url(&display_source).is_err() {
|
if resolve_url(&display_source).is_err() {
|
||||||
|
@ -4212,6 +4244,13 @@ impl TscSpecifierMap {
|
||||||
return specifier.to_string();
|
return specifier.to_string();
|
||||||
}
|
}
|
||||||
let mut specifier = original.to_string();
|
let mut specifier = original.to_string();
|
||||||
|
if specifier.contains("/node_modules/.deno/")
|
||||||
|
&& !specifier.contains("/node_modules/@types/node/")
|
||||||
|
{
|
||||||
|
// The ts server doesn't give completions from files in
|
||||||
|
// `node_modules/.deno/`. We work around it like this.
|
||||||
|
specifier = specifier.replace("/node_modules/", "/$node_modules/");
|
||||||
|
}
|
||||||
let media_type = MediaType::from_specifier(original);
|
let media_type = MediaType::from_specifier(original);
|
||||||
// If the URL-inferred media type doesn't correspond to tsc's path-inferred
|
// If the URL-inferred media type doesn't correspond to tsc's path-inferred
|
||||||
// media type, force it to be the same by appending an extension.
|
// media type, force it to be the same by appending an extension.
|
||||||
|
@ -4329,7 +4368,7 @@ fn op_is_cancelled(state: &mut OpState) -> bool {
|
||||||
fn op_is_node_file(state: &mut OpState, #[string] path: String) -> bool {
|
fn op_is_node_file(state: &mut OpState, #[string] path: String) -> bool {
|
||||||
let state = state.borrow::<State>();
|
let state = state.borrow::<State>();
|
||||||
let mark = state.performance.mark("tsc.op.op_is_node_file");
|
let mark = state.performance.mark("tsc.op.op_is_node_file");
|
||||||
let r = match ModuleSpecifier::parse(&path) {
|
let r = match state.specifier_map.normalize(path) {
|
||||||
Ok(specifier) => state.state_snapshot.resolver.in_node_modules(&specifier),
|
Ok(specifier) => state.state_snapshot.resolver.in_node_modules(&specifier),
|
||||||
Err(_) => false,
|
Err(_) => false,
|
||||||
};
|
};
|
||||||
|
@ -4609,7 +4648,10 @@ fn op_script_names(state: &mut OpState) -> ScriptNames {
|
||||||
for doc in &docs {
|
for doc in &docs {
|
||||||
let specifier = doc.specifier();
|
let specifier = doc.specifier();
|
||||||
let is_open = doc.is_open();
|
let is_open = doc.is_open();
|
||||||
if is_open || specifier.scheme() == "file" {
|
if is_open
|
||||||
|
|| (specifier.scheme() == "file"
|
||||||
|
&& !state.state_snapshot.resolver.in_node_modules(specifier))
|
||||||
|
{
|
||||||
let script_names = doc
|
let script_names = doc
|
||||||
.scope()
|
.scope()
|
||||||
.and_then(|s| result.by_scope.get_mut(s))
|
.and_then(|s| result.by_scope.get_mut(s))
|
||||||
|
@ -6035,6 +6077,7 @@ mod tests {
|
||||||
Some(temp_dir.url()),
|
Some(temp_dir.url()),
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
|
.unwrap()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(info.entries.len(), 22);
|
assert_eq!(info.entries.len(), 22);
|
||||||
let details = ts_server
|
let details = ts_server
|
||||||
|
@ -6194,6 +6237,7 @@ mod tests {
|
||||||
Some(temp_dir.url()),
|
Some(temp_dir.url()),
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
|
.unwrap()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let entry = info
|
let entry = info
|
||||||
.entries
|
.entries
|
||||||
|
|
|
@ -89,7 +89,7 @@ impl CliNpmResolver for CliByonmNpmResolver {
|
||||||
.components()
|
.components()
|
||||||
.any(|c| c.as_os_str().to_ascii_lowercase() == "node_modules")
|
.any(|c| c.as_os_str().to_ascii_lowercase() == "node_modules")
|
||||||
{
|
{
|
||||||
permissions.check_read_path(path)
|
permissions.check_read_path(path).map_err(Into::into)
|
||||||
} else {
|
} else {
|
||||||
Ok(Cow::Borrowed(path))
|
Ok(Cow::Borrowed(path))
|
||||||
}
|
}
|
||||||
|
|
|
@ -133,7 +133,7 @@ impl RegistryReadPermissionChecker {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
permissions.check_read_path(path)
|
permissions.check_read_path(path).map_err(Into::into)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1035,12 +1035,18 @@ fn junction_or_symlink_dir(
|
||||||
if symlink_err.kind() == std::io::ErrorKind::PermissionDenied =>
|
if symlink_err.kind() == std::io::ErrorKind::PermissionDenied =>
|
||||||
{
|
{
|
||||||
USE_JUNCTIONS.store(true, std::sync::atomic::Ordering::Relaxed);
|
USE_JUNCTIONS.store(true, std::sync::atomic::Ordering::Relaxed);
|
||||||
junction::create(old_path, new_path).map_err(Into::into)
|
junction::create(old_path, new_path)
|
||||||
|
.context("Failed creating junction in node_modules folder")
|
||||||
|
}
|
||||||
|
Err(symlink_err) => {
|
||||||
|
log::warn!(
|
||||||
|
"{} Unexpected error symlinking node_modules: {symlink_err}",
|
||||||
|
colors::yellow("Warning")
|
||||||
|
);
|
||||||
|
USE_JUNCTIONS.store(true, std::sync::atomic::Ordering::Relaxed);
|
||||||
|
junction::create(old_path, new_path)
|
||||||
|
.context("Failed creating junction in node_modules folder")
|
||||||
}
|
}
|
||||||
Err(symlink_err) => Err(
|
|
||||||
AnyError::from(symlink_err)
|
|
||||||
.context("Failed creating symlink in node_modules folder"),
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -56,7 +56,7 @@ struct PermissionsHolder(Uuid, PermissionsContainer);
|
||||||
pub fn op_pledge_test_permissions(
|
pub fn op_pledge_test_permissions(
|
||||||
state: &mut OpState,
|
state: &mut OpState,
|
||||||
#[serde] args: ChildPermissionsArg,
|
#[serde] args: ChildPermissionsArg,
|
||||||
) -> Result<Uuid, AnyError> {
|
) -> Result<Uuid, deno_runtime::deno_permissions::ChildPermissionError> {
|
||||||
let token = Uuid::new_v4();
|
let token = Uuid::new_v4();
|
||||||
let parent_permissions = state.borrow_mut::<PermissionsContainer>();
|
let parent_permissions = state.borrow_mut::<PermissionsContainer>();
|
||||||
let worker_permissions = parent_permissions.create_child_permissions(args)?;
|
let worker_permissions = parent_permissions.create_child_permissions(args)?;
|
||||||
|
@ -147,7 +147,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, AnyError> {
|
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::<time::Instant>().elapsed().as_nanos();
|
||||||
let ns_u64 = u64::try_from(ns)?;
|
let ns_u64 = u64::try_from(ns)?;
|
||||||
Ok(ns_u64)
|
Ok(ns_u64)
|
||||||
|
|
|
@ -46,7 +46,7 @@ pub fn op_jupyter_input(
|
||||||
state: &mut OpState,
|
state: &mut OpState,
|
||||||
#[string] prompt: String,
|
#[string] prompt: String,
|
||||||
is_password: bool,
|
is_password: bool,
|
||||||
) -> Result<Option<String>, AnyError> {
|
) -> Option<String> {
|
||||||
let (last_execution_request, stdin_connection_proxy) = {
|
let (last_execution_request, stdin_connection_proxy) = {
|
||||||
(
|
(
|
||||||
state.borrow::<Arc<Mutex<Option<JupyterMessage>>>>().clone(),
|
state.borrow::<Arc<Mutex<Option<JupyterMessage>>>>().clone(),
|
||||||
|
@ -58,11 +58,11 @@ pub fn op_jupyter_input(
|
||||||
if let Some(last_request) = maybe_last_request {
|
if let Some(last_request) = maybe_last_request {
|
||||||
let JupyterMessageContent::ExecuteRequest(msg) = &last_request.content
|
let JupyterMessageContent::ExecuteRequest(msg) = &last_request.content
|
||||||
else {
|
else {
|
||||||
return Ok(None);
|
return None;
|
||||||
};
|
};
|
||||||
|
|
||||||
if !msg.allow_stdin {
|
if !msg.allow_stdin {
|
||||||
return Ok(None);
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let content = InputRequest {
|
let content = InputRequest {
|
||||||
|
@ -73,7 +73,7 @@ pub fn op_jupyter_input(
|
||||||
let msg = JupyterMessage::new(content, Some(&last_request));
|
let msg = JupyterMessage::new(content, Some(&last_request));
|
||||||
|
|
||||||
let Ok(()) = stdin_connection_proxy.lock().tx.send(msg) else {
|
let Ok(()) = stdin_connection_proxy.lock().tx.send(msg) else {
|
||||||
return Ok(None);
|
return None;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Need to spawn a separate thread here, because `blocking_recv()` can't
|
// Need to spawn a separate thread here, because `blocking_recv()` can't
|
||||||
|
@ -82,17 +82,25 @@ pub fn op_jupyter_input(
|
||||||
stdin_connection_proxy.lock().rx.blocking_recv()
|
stdin_connection_proxy.lock().rx.blocking_recv()
|
||||||
});
|
});
|
||||||
let Ok(Some(response)) = join_handle.join() else {
|
let Ok(Some(response)) = join_handle.join() else {
|
||||||
return Ok(None);
|
return None;
|
||||||
};
|
};
|
||||||
|
|
||||||
let JupyterMessageContent::InputReply(msg) = response.content else {
|
let JupyterMessageContent::InputReply(msg) = response.content else {
|
||||||
return Ok(None);
|
return None;
|
||||||
};
|
};
|
||||||
|
|
||||||
return Ok(Some(msg.value));
|
return Some(msg.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(None)
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, thiserror::Error)]
|
||||||
|
pub enum JupyterBroadcastError {
|
||||||
|
#[error(transparent)]
|
||||||
|
SerdeJson(serde_json::Error),
|
||||||
|
#[error(transparent)]
|
||||||
|
ZeroMq(AnyError),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[op2(async)]
|
#[op2(async)]
|
||||||
|
@ -102,7 +110,7 @@ pub async fn op_jupyter_broadcast(
|
||||||
#[serde] content: serde_json::Value,
|
#[serde] content: serde_json::Value,
|
||||||
#[serde] metadata: serde_json::Value,
|
#[serde] metadata: serde_json::Value,
|
||||||
#[serde] buffers: Vec<deno_core::JsBuffer>,
|
#[serde] buffers: Vec<deno_core::JsBuffer>,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), JupyterBroadcastError> {
|
||||||
let (iopub_connection, last_execution_request) = {
|
let (iopub_connection, last_execution_request) = {
|
||||||
let s = state.borrow();
|
let s = state.borrow();
|
||||||
|
|
||||||
|
@ -125,36 +133,35 @@ pub async fn op_jupyter_broadcast(
|
||||||
content,
|
content,
|
||||||
err
|
err
|
||||||
);
|
);
|
||||||
err
|
JupyterBroadcastError::SerdeJson(err)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let jupyter_message = JupyterMessage::new(content, Some(&last_request))
|
let jupyter_message = JupyterMessage::new(content, Some(&last_request))
|
||||||
.with_metadata(metadata)
|
.with_metadata(metadata)
|
||||||
.with_buffers(buffers.into_iter().map(|b| b.to_vec().into()).collect());
|
.with_buffers(buffers.into_iter().map(|b| b.to_vec().into()).collect());
|
||||||
|
|
||||||
iopub_connection.lock().send(jupyter_message).await?;
|
iopub_connection
|
||||||
|
.lock()
|
||||||
|
.send(jupyter_message)
|
||||||
|
.await
|
||||||
|
.map_err(JupyterBroadcastError::ZeroMq)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[op2(fast)]
|
#[op2(fast)]
|
||||||
pub fn op_print(
|
pub fn op_print(state: &mut OpState, #[string] msg: &str, is_err: bool) {
|
||||||
state: &mut OpState,
|
|
||||||
#[string] msg: &str,
|
|
||||||
is_err: bool,
|
|
||||||
) -> Result<(), AnyError> {
|
|
||||||
let sender = state.borrow_mut::<mpsc::UnboundedSender<StreamContent>>();
|
let sender = state.borrow_mut::<mpsc::UnboundedSender<StreamContent>>();
|
||||||
|
|
||||||
if is_err {
|
if is_err {
|
||||||
if let Err(err) = sender.send(StreamContent::stderr(msg)) {
|
if let Err(err) = sender.send(StreamContent::stderr(msg)) {
|
||||||
log::error!("Failed to send stderr message: {}", err);
|
log::error!("Failed to send stderr message: {}", err);
|
||||||
}
|
}
|
||||||
return Ok(());
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Err(err) = sender.send(StreamContent::stdout(msg)) {
|
if let Err(err) = sender.send(StreamContent::stdout(msg)) {
|
||||||
log::error!("Failed to send stdout message: {}", err);
|
log::error!("Failed to send stdout message: {}", err);
|
||||||
}
|
}
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,7 +51,7 @@ struct PermissionsHolder(Uuid, PermissionsContainer);
|
||||||
pub fn op_pledge_test_permissions(
|
pub fn op_pledge_test_permissions(
|
||||||
state: &mut OpState,
|
state: &mut OpState,
|
||||||
#[serde] args: ChildPermissionsArg,
|
#[serde] args: ChildPermissionsArg,
|
||||||
) -> Result<Uuid, AnyError> {
|
) -> Result<Uuid, deno_runtime::deno_permissions::ChildPermissionError> {
|
||||||
let token = Uuid::new_v4();
|
let token = Uuid::new_v4();
|
||||||
let parent_permissions = state.borrow_mut::<PermissionsContainer>();
|
let parent_permissions = state.borrow_mut::<PermissionsContainer>();
|
||||||
let worker_permissions = parent_permissions.create_child_permissions(args)?;
|
let worker_permissions = parent_permissions.create_child_permissions(args)?;
|
||||||
|
@ -150,7 +150,7 @@ fn op_register_test_step(
|
||||||
#[smi] parent_id: usize,
|
#[smi] parent_id: usize,
|
||||||
#[smi] root_id: usize,
|
#[smi] root_id: usize,
|
||||||
#[string] root_name: String,
|
#[string] root_name: String,
|
||||||
) -> Result<usize, AnyError> {
|
) -> usize {
|
||||||
let id = NEXT_ID.fetch_add(1, Ordering::SeqCst);
|
let id = NEXT_ID.fetch_add(1, Ordering::SeqCst);
|
||||||
let origin = state.borrow::<ModuleSpecifier>().to_string();
|
let origin = state.borrow::<ModuleSpecifier>().to_string();
|
||||||
let description = TestStepDescription {
|
let description = TestStepDescription {
|
||||||
|
@ -169,7 +169,7 @@ fn op_register_test_step(
|
||||||
};
|
};
|
||||||
let sender = state.borrow_mut::<TestEventSender>();
|
let sender = state.borrow_mut::<TestEventSender>();
|
||||||
sender.send(TestEvent::StepRegister(description)).ok();
|
sender.send(TestEvent::StepRegister(description)).ok();
|
||||||
Ok(id)
|
id
|
||||||
}
|
}
|
||||||
|
|
||||||
#[op2(fast)]
|
#[op2(fast)]
|
||||||
|
|
|
@ -353,6 +353,21 @@ fn format_yaml(
|
||||||
file_text: &str,
|
file_text: &str,
|
||||||
fmt_options: &FmtOptionsConfig,
|
fmt_options: &FmtOptionsConfig,
|
||||||
) -> Result<Option<String>, AnyError> {
|
) -> Result<Option<String>, AnyError> {
|
||||||
|
let ignore_file = file_text
|
||||||
|
.lines()
|
||||||
|
.take_while(|line| line.starts_with('#'))
|
||||||
|
.any(|line| {
|
||||||
|
line
|
||||||
|
.strip_prefix('#')
|
||||||
|
.unwrap()
|
||||||
|
.trim()
|
||||||
|
.starts_with("deno-fmt-ignore-file")
|
||||||
|
});
|
||||||
|
|
||||||
|
if ignore_file {
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
|
||||||
let formatted_str =
|
let formatted_str =
|
||||||
pretty_yaml::format_text(file_text, &get_resolved_yaml_config(fmt_options))
|
pretty_yaml::format_text(file_text, &get_resolved_yaml_config(fmt_options))
|
||||||
.map_err(AnyError::from)?;
|
.map_err(AnyError::from)?;
|
||||||
|
@ -1017,7 +1032,7 @@ fn get_resolved_markup_fmt_config(
|
||||||
max_attrs_per_line: None,
|
max_attrs_per_line: None,
|
||||||
prefer_attrs_single_line: false,
|
prefer_attrs_single_line: false,
|
||||||
html_normal_self_closing: None,
|
html_normal_self_closing: None,
|
||||||
html_void_self_closing: Some(true),
|
html_void_self_closing: None,
|
||||||
component_self_closing: None,
|
component_self_closing: None,
|
||||||
svg_self_closing: None,
|
svg_self_closing: None,
|
||||||
mathml_self_closing: None,
|
mathml_self_closing: None,
|
||||||
|
|
|
@ -645,10 +645,12 @@ impl<'a> GraphDisplayContext<'a> {
|
||||||
let message = match err {
|
let message = match err {
|
||||||
HttpsChecksumIntegrity(_) => "(checksum integrity error)",
|
HttpsChecksumIntegrity(_) => "(checksum integrity error)",
|
||||||
Decode(_) => "(loading decode error)",
|
Decode(_) => "(loading decode error)",
|
||||||
Loader(err) => match deno_core::error::get_custom_error_class(err) {
|
Loader(err) => {
|
||||||
|
match deno_runtime::errors::get_error_class_name(err) {
|
||||||
Some("NotCapable") => "(not capable, requires --allow-import)",
|
Some("NotCapable") => "(not capable, requires --allow-import)",
|
||||||
_ => "(loading error)",
|
_ => "(loading error)",
|
||||||
},
|
}
|
||||||
|
}
|
||||||
Jsr(_) => "(loading error)",
|
Jsr(_) => "(loading error)",
|
||||||
NodeUnknownBuiltinModule(_) => "(unknown node built-in error)",
|
NodeUnknownBuiltinModule(_) => "(unknown node built-in error)",
|
||||||
Npm(_) => "(npm loading error)",
|
Npm(_) => "(npm loading error)",
|
||||||
|
|
|
@ -12,7 +12,9 @@ use deno_core::futures::StreamExt;
|
||||||
use deno_path_util::url_to_file_path;
|
use deno_path_util::url_to_file_path;
|
||||||
use deno_semver::jsr::JsrPackageReqReference;
|
use deno_semver::jsr::JsrPackageReqReference;
|
||||||
use deno_semver::npm::NpmPackageReqReference;
|
use deno_semver::npm::NpmPackageReqReference;
|
||||||
|
use deno_semver::package::PackageNv;
|
||||||
use deno_semver::package::PackageReq;
|
use deno_semver::package::PackageReq;
|
||||||
|
use deno_semver::Version;
|
||||||
use deno_semver::VersionReq;
|
use deno_semver::VersionReq;
|
||||||
use jsonc_parser::cst::CstObject;
|
use jsonc_parser::cst::CstObject;
|
||||||
use jsonc_parser::cst::CstObjectProp;
|
use jsonc_parser::cst::CstObjectProp;
|
||||||
|
@ -455,15 +457,32 @@ pub async fn add(
|
||||||
match package_and_version {
|
match package_and_version {
|
||||||
PackageAndVersion::NotFound {
|
PackageAndVersion::NotFound {
|
||||||
package: package_name,
|
package: package_name,
|
||||||
found_npm_package,
|
help,
|
||||||
package_req,
|
package_req,
|
||||||
} => {
|
} => match help {
|
||||||
if found_npm_package {
|
Some(NotFoundHelp::NpmPackage) => {
|
||||||
bail!("{} was not found, but a matching npm package exists. Did you mean `{}`?", crate::colors::red(package_name), crate::colors::yellow(format!("deno {cmd_name} npm:{package_req}")));
|
bail!(
|
||||||
} else {
|
"{} was not found, but a matching npm package exists. Did you mean `{}`?",
|
||||||
bail!("{} was not found.", crate::colors::red(package_name));
|
crate::colors::red(package_name),
|
||||||
|
crate::colors::yellow(format!("deno {cmd_name} npm:{package_req}"))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
Some(NotFoundHelp::JsrPackage) => {
|
||||||
|
bail!(
|
||||||
|
"{} was not found, but a matching jsr package exists. Did you mean `{}`?",
|
||||||
|
crate::colors::red(package_name),
|
||||||
|
crate::colors::yellow(format!("deno {cmd_name} jsr:{package_req}"))
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
Some(NotFoundHelp::PreReleaseVersion(version)) => {
|
||||||
|
bail!(
|
||||||
|
"{} has only pre-release versions available. Try specifying a version: `{}`",
|
||||||
|
crate::colors::red(&package_name),
|
||||||
|
crate::colors::yellow(format!("deno {cmd_name} {package_name}@^{version}"))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
None => bail!("{} was not found.", crate::colors::red(package_name)),
|
||||||
|
},
|
||||||
PackageAndVersion::Selected(selected) => {
|
PackageAndVersion::Selected(selected) => {
|
||||||
selected_packages.push(selected);
|
selected_packages.push(selected);
|
||||||
}
|
}
|
||||||
|
@ -511,36 +530,121 @@ struct SelectedPackage {
|
||||||
selected_version: String,
|
selected_version: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum NotFoundHelp {
|
||||||
|
NpmPackage,
|
||||||
|
JsrPackage,
|
||||||
|
PreReleaseVersion(Version),
|
||||||
|
}
|
||||||
|
|
||||||
enum PackageAndVersion {
|
enum PackageAndVersion {
|
||||||
NotFound {
|
NotFound {
|
||||||
package: String,
|
package: String,
|
||||||
found_npm_package: bool,
|
|
||||||
package_req: PackageReq,
|
package_req: PackageReq,
|
||||||
|
help: Option<NotFoundHelp>,
|
||||||
},
|
},
|
||||||
Selected(SelectedPackage),
|
Selected(SelectedPackage),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn best_version<'a>(
|
||||||
|
versions: impl Iterator<Item = &'a Version>,
|
||||||
|
) -> Option<&'a Version> {
|
||||||
|
let mut maybe_best_version: Option<&Version> = None;
|
||||||
|
for version in versions {
|
||||||
|
let is_best_version = maybe_best_version
|
||||||
|
.as_ref()
|
||||||
|
.map(|best_version| (*best_version).cmp(version).is_lt())
|
||||||
|
.unwrap_or(true);
|
||||||
|
if is_best_version {
|
||||||
|
maybe_best_version = Some(version);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
maybe_best_version
|
||||||
|
}
|
||||||
|
|
||||||
|
trait PackageInfoProvider {
|
||||||
|
const SPECIFIER_PREFIX: &str;
|
||||||
|
/// The help to return if a package is found by this provider
|
||||||
|
const HELP: NotFoundHelp;
|
||||||
|
async fn req_to_nv(&self, req: &PackageReq) -> Option<PackageNv>;
|
||||||
|
async fn latest_version<'a>(&self, req: &PackageReq) -> Option<Version>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PackageInfoProvider for Arc<JsrFetchResolver> {
|
||||||
|
const HELP: NotFoundHelp = NotFoundHelp::JsrPackage;
|
||||||
|
const SPECIFIER_PREFIX: &str = "jsr";
|
||||||
|
async fn req_to_nv(&self, req: &PackageReq) -> Option<PackageNv> {
|
||||||
|
(**self).req_to_nv(req).await
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn latest_version<'a>(&self, req: &PackageReq) -> Option<Version> {
|
||||||
|
let info = self.package_info(&req.name).await?;
|
||||||
|
best_version(
|
||||||
|
info
|
||||||
|
.versions
|
||||||
|
.iter()
|
||||||
|
.filter(|(_, version_info)| !version_info.yanked)
|
||||||
|
.map(|(version, _)| version),
|
||||||
|
)
|
||||||
|
.cloned()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PackageInfoProvider for Arc<NpmFetchResolver> {
|
||||||
|
const HELP: NotFoundHelp = NotFoundHelp::NpmPackage;
|
||||||
|
const SPECIFIER_PREFIX: &str = "npm";
|
||||||
|
async fn req_to_nv(&self, req: &PackageReq) -> Option<PackageNv> {
|
||||||
|
(**self).req_to_nv(req).await
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn latest_version<'a>(&self, req: &PackageReq) -> Option<Version> {
|
||||||
|
let info = self.package_info(&req.name).await?;
|
||||||
|
best_version(info.versions.keys()).cloned()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async fn find_package_and_select_version_for_req(
|
async fn find_package_and_select_version_for_req(
|
||||||
jsr_resolver: Arc<JsrFetchResolver>,
|
jsr_resolver: Arc<JsrFetchResolver>,
|
||||||
npm_resolver: Arc<NpmFetchResolver>,
|
npm_resolver: Arc<NpmFetchResolver>,
|
||||||
add_package_req: AddRmPackageReq,
|
add_package_req: AddRmPackageReq,
|
||||||
) -> Result<PackageAndVersion, AnyError> {
|
) -> Result<PackageAndVersion, AnyError> {
|
||||||
match add_package_req.value {
|
async fn select<T: PackageInfoProvider, S: PackageInfoProvider>(
|
||||||
AddRmPackageReqValue::Jsr(req) => {
|
main_resolver: T,
|
||||||
let jsr_prefixed_name = format!("jsr:{}", &req.name);
|
fallback_resolver: S,
|
||||||
let Some(nv) = jsr_resolver.req_to_nv(&req).await else {
|
add_package_req: AddRmPackageReq,
|
||||||
if npm_resolver.req_to_nv(&req).await.is_some() {
|
) -> Result<PackageAndVersion, AnyError> {
|
||||||
|
let req = match &add_package_req.value {
|
||||||
|
AddRmPackageReqValue::Jsr(req) => req,
|
||||||
|
AddRmPackageReqValue::Npm(req) => req,
|
||||||
|
};
|
||||||
|
let prefixed_name = format!("{}:{}", T::SPECIFIER_PREFIX, req.name);
|
||||||
|
let help_if_found_in_fallback = S::HELP;
|
||||||
|
let Some(nv) = main_resolver.req_to_nv(req).await else {
|
||||||
|
if fallback_resolver.req_to_nv(req).await.is_some() {
|
||||||
|
// it's in the other registry
|
||||||
return Ok(PackageAndVersion::NotFound {
|
return Ok(PackageAndVersion::NotFound {
|
||||||
package: jsr_prefixed_name,
|
package: prefixed_name,
|
||||||
found_npm_package: true,
|
help: Some(help_if_found_in_fallback),
|
||||||
package_req: req,
|
package_req: req.clone(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if req.version_req.version_text() == "*" {
|
||||||
|
if let Some(pre_release_version) =
|
||||||
|
main_resolver.latest_version(req).await
|
||||||
|
{
|
||||||
|
return Ok(PackageAndVersion::NotFound {
|
||||||
|
package: prefixed_name,
|
||||||
|
package_req: req.clone(),
|
||||||
|
help: Some(NotFoundHelp::PreReleaseVersion(
|
||||||
|
pre_release_version.clone(),
|
||||||
|
)),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return Ok(PackageAndVersion::NotFound {
|
return Ok(PackageAndVersion::NotFound {
|
||||||
package: jsr_prefixed_name,
|
package: prefixed_name,
|
||||||
found_npm_package: false,
|
help: None,
|
||||||
package_req: req,
|
package_req: req.clone(),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
let range_symbol = if req.version_req.version_text().starts_with('~') {
|
let range_symbol = if req.version_req.version_text().starts_with('~') {
|
||||||
|
@ -552,35 +656,18 @@ async fn find_package_and_select_version_for_req(
|
||||||
};
|
};
|
||||||
Ok(PackageAndVersion::Selected(SelectedPackage {
|
Ok(PackageAndVersion::Selected(SelectedPackage {
|
||||||
import_name: add_package_req.alias,
|
import_name: add_package_req.alias,
|
||||||
package_name: jsr_prefixed_name,
|
package_name: prefixed_name,
|
||||||
version_req: format!("{}{}", range_symbol, &nv.version),
|
version_req: format!("{}{}", range_symbol, &nv.version),
|
||||||
selected_version: nv.version.to_string(),
|
selected_version: nv.version.to_string(),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
AddRmPackageReqValue::Npm(req) => {
|
|
||||||
let npm_prefixed_name = format!("npm:{}", &req.name);
|
|
||||||
let Some(nv) = npm_resolver.req_to_nv(&req).await else {
|
|
||||||
return Ok(PackageAndVersion::NotFound {
|
|
||||||
package: npm_prefixed_name,
|
|
||||||
found_npm_package: false,
|
|
||||||
package_req: req,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
let range_symbol = if req.version_req.version_text().starts_with('~') {
|
match &add_package_req.value {
|
||||||
"~"
|
AddRmPackageReqValue::Jsr(_) => {
|
||||||
} else if req.version_req.version_text() == nv.version.to_string() {
|
select(jsr_resolver, npm_resolver, add_package_req).await
|
||||||
""
|
}
|
||||||
} else {
|
AddRmPackageReqValue::Npm(_) => {
|
||||||
"^"
|
select(npm_resolver, jsr_resolver, add_package_req).await
|
||||||
};
|
|
||||||
|
|
||||||
Ok(PackageAndVersion::Selected(SelectedPackage {
|
|
||||||
import_name: add_package_req.alias,
|
|
||||||
package_name: npm_prefixed_name,
|
|
||||||
version_req: format!("{}{}", range_symbol, &nv.version),
|
|
||||||
selected_version: nv.version.to_string(),
|
|
||||||
}))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -801,7 +801,11 @@ delete Object.prototype.__proto__;
|
||||||
if (logDebug) {
|
if (logDebug) {
|
||||||
debug(`host.getScriptSnapshot("${specifier}")`);
|
debug(`host.getScriptSnapshot("${specifier}")`);
|
||||||
}
|
}
|
||||||
const sourceFile = sourceFileCache.get(specifier);
|
if (specifier.startsWith(ASSETS_URL_PREFIX)) {
|
||||||
|
const sourceFile = this.getSourceFile(
|
||||||
|
specifier,
|
||||||
|
ts.ScriptTarget.ESNext,
|
||||||
|
);
|
||||||
if (sourceFile) {
|
if (sourceFile) {
|
||||||
if (!assetScopes.has(specifier)) {
|
if (!assetScopes.has(specifier)) {
|
||||||
assetScopes.set(specifier, lastRequestScope);
|
assetScopes.set(specifier, lastRequestScope);
|
||||||
|
@ -809,6 +813,7 @@ delete Object.prototype.__proto__;
|
||||||
// This case only occurs for assets.
|
// This case only occurs for assets.
|
||||||
return ts.ScriptSnapshot.fromString(sourceFile.text);
|
return ts.ScriptSnapshot.fromString(sourceFile.text);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
let sourceText = sourceTextCache.get(specifier);
|
let sourceText = sourceTextCache.get(specifier);
|
||||||
if (sourceText == undefined) {
|
if (sourceText == undefined) {
|
||||||
/** @type {{ data: string, version: string, isCjs: boolean }} */
|
/** @type {{ data: string, version: string, isCjs: boolean }} */
|
||||||
|
|
37
cli/tsc/dts/lib.deno.ns.d.ts
vendored
37
cli/tsc/dts/lib.deno.ns.d.ts
vendored
|
@ -556,14 +556,23 @@ declare namespace Deno {
|
||||||
*/
|
*/
|
||||||
env?: "inherit" | boolean | string[];
|
env?: "inherit" | boolean | string[];
|
||||||
|
|
||||||
/** Specifies if the `sys` permission should be requested or revoked.
|
/** Specifies if the `ffi` permission should be requested or revoked.
|
||||||
* If set to `"inherit"`, the current `sys` permission will be inherited.
|
* If set to `"inherit"`, the current `ffi` permission will be inherited.
|
||||||
* If set to `true`, the global `sys` permission will be requested.
|
* If set to `true`, the global `ffi` permission will be requested.
|
||||||
* If set to `false`, the global `sys` permission will be revoked.
|
* If set to `false`, the global `ffi` permission will be revoked.
|
||||||
*
|
*
|
||||||
* @default {false}
|
* @default {false}
|
||||||
*/
|
*/
|
||||||
sys?: "inherit" | boolean | string[];
|
ffi?: "inherit" | boolean | Array<string | URL>;
|
||||||
|
|
||||||
|
/** Specifies if the `import` permission should be requested or revoked.
|
||||||
|
* If set to `"inherit"` the current `import` permission will be inherited.
|
||||||
|
* If set to `true`, the global `import` permission will be requested.
|
||||||
|
* If set to `false`, the global `import` permission will be revoked.
|
||||||
|
* If set to `Array<string>`, the `import` permissions will be requested with the
|
||||||
|
* specified domains.
|
||||||
|
*/
|
||||||
|
import?: "inherit" | boolean | Array<string>;
|
||||||
|
|
||||||
/** Specifies if the `net` permission should be requested or revoked.
|
/** Specifies if the `net` permission should be requested or revoked.
|
||||||
* if set to `"inherit"`, the current `net` permission will be inherited.
|
* if set to `"inherit"`, the current `net` permission will be inherited.
|
||||||
|
@ -638,15 +647,6 @@ declare namespace Deno {
|
||||||
*/
|
*/
|
||||||
net?: "inherit" | boolean | string[];
|
net?: "inherit" | boolean | string[];
|
||||||
|
|
||||||
/** Specifies if the `ffi` permission should be requested or revoked.
|
|
||||||
* If set to `"inherit"`, the current `ffi` permission will be inherited.
|
|
||||||
* If set to `true`, the global `ffi` permission will be requested.
|
|
||||||
* If set to `false`, the global `ffi` permission will be revoked.
|
|
||||||
*
|
|
||||||
* @default {false}
|
|
||||||
*/
|
|
||||||
ffi?: "inherit" | boolean | Array<string | URL>;
|
|
||||||
|
|
||||||
/** Specifies if the `read` permission should be requested or revoked.
|
/** Specifies if the `read` permission should be requested or revoked.
|
||||||
* If set to `"inherit"`, the current `read` permission will be inherited.
|
* If set to `"inherit"`, the current `read` permission will be inherited.
|
||||||
* If set to `true`, the global `read` permission will be requested.
|
* If set to `true`, the global `read` permission will be requested.
|
||||||
|
@ -667,6 +667,15 @@ declare namespace Deno {
|
||||||
*/
|
*/
|
||||||
run?: "inherit" | boolean | Array<string | URL>;
|
run?: "inherit" | boolean | Array<string | URL>;
|
||||||
|
|
||||||
|
/** Specifies if the `sys` permission should be requested or revoked.
|
||||||
|
* If set to `"inherit"`, the current `sys` permission will be inherited.
|
||||||
|
* If set to `true`, the global `sys` permission will be requested.
|
||||||
|
* If set to `false`, the global `sys` permission will be revoked.
|
||||||
|
*
|
||||||
|
* @default {false}
|
||||||
|
*/
|
||||||
|
sys?: "inherit" | boolean | string[];
|
||||||
|
|
||||||
/** Specifies if the `write` permission should be requested or revoked.
|
/** Specifies if the `write` permission should be requested or revoked.
|
||||||
* If set to `"inherit"`, the current `write` permission will be inherited.
|
* If set to `"inherit"`, the current `write` permission will be inherited.
|
||||||
* If set to `true`, the global `write` permission will be requested.
|
* If set to `true`, the global `write` permission will be requested.
|
||||||
|
|
|
@ -565,7 +565,9 @@ pub fn symlink_dir(oldpath: &Path, newpath: &Path) -> Result<(), Error> {
|
||||||
use std::os::windows::fs::symlink_dir;
|
use std::os::windows::fs::symlink_dir;
|
||||||
symlink_dir(oldpath, newpath).map_err(|err| {
|
symlink_dir(oldpath, newpath).map_err(|err| {
|
||||||
if let Some(code) = err.raw_os_error() {
|
if let Some(code) = err.raw_os_error() {
|
||||||
if code as u32 == winapi::shared::winerror::ERROR_PRIVILEGE_NOT_HELD {
|
if code as u32 == winapi::shared::winerror::ERROR_PRIVILEGE_NOT_HELD
|
||||||
|
|| code as u32 == winapi::shared::winerror::ERROR_INVALID_FUNCTION
|
||||||
|
{
|
||||||
return err_mapper(err, Some(ErrorKind::PermissionDenied));
|
return err_mapper(err, Some(ErrorKind::PermissionDenied));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "deno_broadcast_channel"
|
name = "deno_broadcast_channel"
|
||||||
version = "0.169.0"
|
version = "0.170.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.107.0"
|
version = "0.108.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.44.0"
|
version = "0.45.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.175.0"
|
version = "0.176.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.55.0"
|
version = "0.56.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.189.0"
|
version = "0.190.0"
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
|
|
@ -269,12 +269,6 @@ class Request {
|
||||||
/** @type {AbortSignal} */
|
/** @type {AbortSignal} */
|
||||||
get [_signal]() {
|
get [_signal]() {
|
||||||
const signal = this[_signalCache];
|
const signal = this[_signalCache];
|
||||||
// This signal not been created yet, and the request is still in progress
|
|
||||||
if (signal === undefined) {
|
|
||||||
const signal = newSignal();
|
|
||||||
this[_signalCache] = signal;
|
|
||||||
return signal;
|
|
||||||
}
|
|
||||||
// This signal has not been created yet, but the request has already completed
|
// This signal has not been created yet, but the request has already completed
|
||||||
if (signal === false) {
|
if (signal === false) {
|
||||||
const signal = newSignal();
|
const signal = newSignal();
|
||||||
|
@ -282,6 +276,18 @@ class Request {
|
||||||
signal[signalAbort](signalAbortError);
|
signal[signalAbort](signalAbortError);
|
||||||
return signal;
|
return signal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This signal not been created yet, and the request is still in progress
|
||||||
|
if (signal === undefined) {
|
||||||
|
const signal = newSignal();
|
||||||
|
this[_signalCache] = signal;
|
||||||
|
this[_request].onCancel?.(() => {
|
||||||
|
signal[signalAbort](signalAbortError);
|
||||||
|
});
|
||||||
|
|
||||||
|
return signal;
|
||||||
|
}
|
||||||
|
|
||||||
return signal;
|
return signal;
|
||||||
}
|
}
|
||||||
get [_mimeType]() {
|
get [_mimeType]() {
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "deno_fetch"
|
name = "deno_fetch"
|
||||||
version = "0.199.0"
|
version = "0.200.0"
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
|
|
@ -39,6 +39,7 @@ use deno_core::OpState;
|
||||||
use deno_core::RcRef;
|
use deno_core::RcRef;
|
||||||
use deno_core::Resource;
|
use deno_core::Resource;
|
||||||
use deno_core::ResourceId;
|
use deno_core::ResourceId;
|
||||||
|
use deno_permissions::PermissionCheckError;
|
||||||
use deno_tls::rustls::RootCertStore;
|
use deno_tls::rustls::RootCertStore;
|
||||||
use deno_tls::Proxy;
|
use deno_tls::Proxy;
|
||||||
use deno_tls::RootCertStoreProvider;
|
use deno_tls::RootCertStoreProvider;
|
||||||
|
@ -149,7 +150,7 @@ pub enum FetchError {
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Resource(deno_core::error::AnyError),
|
Resource(deno_core::error::AnyError),
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Permission(deno_core::error::AnyError),
|
Permission(#[from] PermissionCheckError),
|
||||||
#[error("NetworkError when attempting to fetch resource")]
|
#[error("NetworkError when attempting to fetch resource")]
|
||||||
NetworkError,
|
NetworkError,
|
||||||
#[error("Fetching files only supports the GET method: received {0}")]
|
#[error("Fetching files only supports the GET method: received {0}")]
|
||||||
|
@ -346,13 +347,13 @@ pub trait FetchPermissions {
|
||||||
&mut self,
|
&mut self,
|
||||||
url: &Url,
|
url: &Url,
|
||||||
api_name: &str,
|
api_name: &str,
|
||||||
) -> Result<(), deno_core::error::AnyError>;
|
) -> Result<(), PermissionCheckError>;
|
||||||
#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
|
#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
|
||||||
fn check_read<'a>(
|
fn check_read<'a>(
|
||||||
&mut self,
|
&mut self,
|
||||||
p: &'a Path,
|
p: &'a Path,
|
||||||
api_name: &str,
|
api_name: &str,
|
||||||
) -> Result<Cow<'a, Path>, deno_core::error::AnyError>;
|
) -> Result<Cow<'a, Path>, PermissionCheckError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FetchPermissions for deno_permissions::PermissionsContainer {
|
impl FetchPermissions for deno_permissions::PermissionsContainer {
|
||||||
|
@ -361,7 +362,7 @@ impl FetchPermissions for deno_permissions::PermissionsContainer {
|
||||||
&mut self,
|
&mut self,
|
||||||
url: &Url,
|
url: &Url,
|
||||||
api_name: &str,
|
api_name: &str,
|
||||||
) -> Result<(), deno_core::error::AnyError> {
|
) -> Result<(), PermissionCheckError> {
|
||||||
deno_permissions::PermissionsContainer::check_net_url(self, url, api_name)
|
deno_permissions::PermissionsContainer::check_net_url(self, url, api_name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -370,7 +371,7 @@ impl FetchPermissions for deno_permissions::PermissionsContainer {
|
||||||
&mut self,
|
&mut self,
|
||||||
path: &'a Path,
|
path: &'a Path,
|
||||||
api_name: &str,
|
api_name: &str,
|
||||||
) -> Result<Cow<'a, Path>, deno_core::error::AnyError> {
|
) -> Result<Cow<'a, Path>, PermissionCheckError> {
|
||||||
deno_permissions::PermissionsContainer::check_read_path(
|
deno_permissions::PermissionsContainer::check_read_path(
|
||||||
self,
|
self,
|
||||||
path,
|
path,
|
||||||
|
@ -414,9 +415,7 @@ where
|
||||||
"file" => {
|
"file" => {
|
||||||
let path = url.to_file_path().map_err(|_| FetchError::NetworkError)?;
|
let path = url.to_file_path().map_err(|_| FetchError::NetworkError)?;
|
||||||
let permissions = state.borrow_mut::<FP>();
|
let permissions = state.borrow_mut::<FP>();
|
||||||
let path = permissions
|
let path = permissions.check_read(&path, "fetch()")?;
|
||||||
.check_read(&path, "fetch()")
|
|
||||||
.map_err(FetchError::Permission)?;
|
|
||||||
let url = match path {
|
let url = match path {
|
||||||
Cow::Owned(path) => Url::from_file_path(path).unwrap(),
|
Cow::Owned(path) => Url::from_file_path(path).unwrap(),
|
||||||
Cow::Borrowed(_) => url,
|
Cow::Borrowed(_) => url,
|
||||||
|
@ -442,9 +441,7 @@ where
|
||||||
}
|
}
|
||||||
"http" | "https" => {
|
"http" | "https" => {
|
||||||
let permissions = state.borrow_mut::<FP>();
|
let permissions = state.borrow_mut::<FP>();
|
||||||
permissions
|
permissions.check_net_url(&url, "fetch()")?;
|
||||||
.check_net_url(&url, "fetch()")
|
|
||||||
.map_err(FetchError::Resource)?;
|
|
||||||
|
|
||||||
let maybe_authority = extract_authority(&mut url);
|
let maybe_authority = extract_authority(&mut url);
|
||||||
let uri = url
|
let uri = url
|
||||||
|
@ -863,9 +860,7 @@ where
|
||||||
if let Some(proxy) = args.proxy.clone() {
|
if let Some(proxy) = args.proxy.clone() {
|
||||||
let permissions = state.borrow_mut::<FP>();
|
let permissions = state.borrow_mut::<FP>();
|
||||||
let url = Url::parse(&proxy.url)?;
|
let url = Url::parse(&proxy.url)?;
|
||||||
permissions
|
permissions.check_net_url(&url, "Deno.createHttpClient()")?;
|
||||||
.check_net_url(&url, "Deno.createHttpClient()")
|
|
||||||
.map_err(FetchError::Permission)?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let options = state.borrow::<Options>();
|
let options = state.borrow::<Options>();
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "deno_ffi"
|
name = "deno_ffi"
|
||||||
version = "0.162.0"
|
version = "0.163.0"
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
|
|
@ -32,7 +32,9 @@ pub enum CallError {
|
||||||
#[error("Invalid FFI symbol name: '{0}'")]
|
#[error("Invalid FFI symbol name: '{0}'")]
|
||||||
InvalidSymbol(String),
|
InvalidSymbol(String),
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Permission(deno_core::error::AnyError),
|
Permission(#[from] deno_permissions::PermissionCheckError),
|
||||||
|
#[error(transparent)]
|
||||||
|
Resource(deno_core::error::AnyError),
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Callback(#[from] super::CallbackError),
|
Callback(#[from] super::CallbackError),
|
||||||
}
|
}
|
||||||
|
@ -301,9 +303,7 @@ where
|
||||||
{
|
{
|
||||||
let mut state = state.borrow_mut();
|
let mut state = state.borrow_mut();
|
||||||
let permissions = state.borrow_mut::<FP>();
|
let permissions = state.borrow_mut::<FP>();
|
||||||
permissions
|
permissions.check_partial_no_path()?;
|
||||||
.check_partial_no_path()
|
|
||||||
.map_err(CallError::Permission)?;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let symbol = PtrSymbol::new(pointer, &def)?;
|
let symbol = PtrSymbol::new(pointer, &def)?;
|
||||||
|
@ -347,7 +347,7 @@ pub fn op_ffi_call_nonblocking(
|
||||||
let resource = state
|
let resource = state
|
||||||
.resource_table
|
.resource_table
|
||||||
.get::<DynamicLibraryResource>(rid)
|
.get::<DynamicLibraryResource>(rid)
|
||||||
.map_err(CallError::Permission)?;
|
.map_err(CallError::Resource)?;
|
||||||
let symbols = &resource.symbols;
|
let symbols = &resource.symbols;
|
||||||
*symbols
|
*symbols
|
||||||
.get(&symbol)
|
.get(&symbol)
|
||||||
|
@ -401,9 +401,7 @@ where
|
||||||
{
|
{
|
||||||
let mut state = state.borrow_mut();
|
let mut state = state.borrow_mut();
|
||||||
let permissions = state.borrow_mut::<FP>();
|
let permissions = state.borrow_mut::<FP>();
|
||||||
permissions
|
permissions.check_partial_no_path()?;
|
||||||
.check_partial_no_path()
|
|
||||||
.map_err(CallError::Permission)?;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let symbol = PtrSymbol::new(pointer, &def)?;
|
let symbol = PtrSymbol::new(pointer, &def)?;
|
||||||
|
|
|
@ -38,7 +38,7 @@ pub enum CallbackError {
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Resource(deno_core::error::AnyError),
|
Resource(deno_core::error::AnyError),
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Permission(deno_core::error::AnyError),
|
Permission(#[from] deno_permissions::PermissionCheckError),
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Other(deno_core::error::AnyError),
|
Other(deno_core::error::AnyError),
|
||||||
}
|
}
|
||||||
|
@ -572,9 +572,7 @@ where
|
||||||
FP: FfiPermissions + 'static,
|
FP: FfiPermissions + 'static,
|
||||||
{
|
{
|
||||||
let permissions = state.borrow_mut::<FP>();
|
let permissions = state.borrow_mut::<FP>();
|
||||||
permissions
|
permissions.check_partial_no_path()?;
|
||||||
.check_partial_no_path()
|
|
||||||
.map_err(CallbackError::Permission)?;
|
|
||||||
|
|
||||||
let thread_id: u32 = LOCAL_THREAD_ID.with(|s| {
|
let thread_id: u32 = LOCAL_THREAD_ID.with(|s| {
|
||||||
let value = *s.borrow();
|
let value = *s.borrow();
|
||||||
|
|
|
@ -30,7 +30,7 @@ pub enum DlfcnError {
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Dlopen(#[from] dlopen2::Error),
|
Dlopen(#[from] dlopen2::Error),
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Permission(deno_core::error::AnyError),
|
Permission(#[from] deno_permissions::PermissionCheckError),
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Other(deno_core::error::AnyError),
|
Other(deno_core::error::AnyError),
|
||||||
}
|
}
|
||||||
|
@ -133,9 +133,7 @@ where
|
||||||
FP: FfiPermissions + 'static,
|
FP: FfiPermissions + 'static,
|
||||||
{
|
{
|
||||||
let permissions = state.borrow_mut::<FP>();
|
let permissions = state.borrow_mut::<FP>();
|
||||||
let path = permissions
|
let path = permissions.check_partial_with_path(&args.path)?;
|
||||||
.check_partial_with_path(&args.path)
|
|
||||||
.map_err(DlfcnError::Permission)?;
|
|
||||||
|
|
||||||
let lib = Library::open(&path).map_err(|e| {
|
let lib = Library::open(&path).map_err(|e| {
|
||||||
dlopen2::Error::OpeningLibraryError(std::io::Error::new(
|
dlopen2::Error::OpeningLibraryError(std::io::Error::new(
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
use deno_core::error::AnyError;
|
|
||||||
|
|
||||||
use std::mem::size_of;
|
use std::mem::size_of;
|
||||||
use std::os::raw::c_char;
|
use std::os::raw::c_char;
|
||||||
use std::os::raw::c_short;
|
use std::os::raw::c_short;
|
||||||
|
@ -31,6 +29,7 @@ use symbol::Symbol;
|
||||||
|
|
||||||
pub use call::CallError;
|
pub use call::CallError;
|
||||||
pub use callback::CallbackError;
|
pub use callback::CallbackError;
|
||||||
|
use deno_permissions::PermissionCheckError;
|
||||||
pub use dlfcn::DlfcnError;
|
pub use dlfcn::DlfcnError;
|
||||||
pub use ir::IRError;
|
pub use ir::IRError;
|
||||||
pub use r#static::StaticError;
|
pub use r#static::StaticError;
|
||||||
|
@ -48,17 +47,17 @@ const _: () = {
|
||||||
pub const UNSTABLE_FEATURE_NAME: &str = "ffi";
|
pub const UNSTABLE_FEATURE_NAME: &str = "ffi";
|
||||||
|
|
||||||
pub trait FfiPermissions {
|
pub trait FfiPermissions {
|
||||||
fn check_partial_no_path(&mut self) -> Result<(), AnyError>;
|
fn check_partial_no_path(&mut self) -> Result<(), PermissionCheckError>;
|
||||||
#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
|
#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
|
||||||
fn check_partial_with_path(
|
fn check_partial_with_path(
|
||||||
&mut self,
|
&mut self,
|
||||||
path: &str,
|
path: &str,
|
||||||
) -> Result<PathBuf, AnyError>;
|
) -> Result<PathBuf, PermissionCheckError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FfiPermissions for deno_permissions::PermissionsContainer {
|
impl FfiPermissions for deno_permissions::PermissionsContainer {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn check_partial_no_path(&mut self) -> Result<(), AnyError> {
|
fn check_partial_no_path(&mut self) -> Result<(), PermissionCheckError> {
|
||||||
deno_permissions::PermissionsContainer::check_ffi_partial_no_path(self)
|
deno_permissions::PermissionsContainer::check_ffi_partial_no_path(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,7 +65,7 @@ impl FfiPermissions for deno_permissions::PermissionsContainer {
|
||||||
fn check_partial_with_path(
|
fn check_partial_with_path(
|
||||||
&mut self,
|
&mut self,
|
||||||
path: &str,
|
path: &str,
|
||||||
) -> Result<PathBuf, AnyError> {
|
) -> Result<PathBuf, PermissionCheckError> {
|
||||||
deno_permissions::PermissionsContainer::check_ffi_partial_with_path(
|
deno_permissions::PermissionsContainer::check_ffi_partial_with_path(
|
||||||
self, path,
|
self, path,
|
||||||
)
|
)
|
||||||
|
|
|
@ -46,7 +46,7 @@ pub enum ReprError {
|
||||||
#[error("Invalid pointer pointer, pointer is null")]
|
#[error("Invalid pointer pointer, pointer is null")]
|
||||||
InvalidPointer,
|
InvalidPointer,
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Permission(deno_core::error::AnyError),
|
Permission(#[from] deno_permissions::PermissionCheckError),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[op2(fast)]
|
#[op2(fast)]
|
||||||
|
@ -58,9 +58,7 @@ where
|
||||||
FP: FfiPermissions + 'static,
|
FP: FfiPermissions + 'static,
|
||||||
{
|
{
|
||||||
let permissions = state.borrow_mut::<FP>();
|
let permissions = state.borrow_mut::<FP>();
|
||||||
permissions
|
permissions.check_partial_no_path()?;
|
||||||
.check_partial_no_path()
|
|
||||||
.map_err(ReprError::Permission)?;
|
|
||||||
|
|
||||||
Ok(ptr_number as *mut c_void)
|
Ok(ptr_number as *mut c_void)
|
||||||
}
|
}
|
||||||
|
@ -75,9 +73,7 @@ where
|
||||||
FP: FfiPermissions + 'static,
|
FP: FfiPermissions + 'static,
|
||||||
{
|
{
|
||||||
let permissions = state.borrow_mut::<FP>();
|
let permissions = state.borrow_mut::<FP>();
|
||||||
permissions
|
permissions.check_partial_no_path()?;
|
||||||
.check_partial_no_path()
|
|
||||||
.map_err(ReprError::Permission)?;
|
|
||||||
|
|
||||||
Ok(a == b)
|
Ok(a == b)
|
||||||
}
|
}
|
||||||
|
@ -91,9 +87,7 @@ where
|
||||||
FP: FfiPermissions + 'static,
|
FP: FfiPermissions + 'static,
|
||||||
{
|
{
|
||||||
let permissions = state.borrow_mut::<FP>();
|
let permissions = state.borrow_mut::<FP>();
|
||||||
permissions
|
permissions.check_partial_no_path()?;
|
||||||
.check_partial_no_path()
|
|
||||||
.map_err(ReprError::Permission)?;
|
|
||||||
|
|
||||||
Ok(buf as *mut c_void)
|
Ok(buf as *mut c_void)
|
||||||
}
|
}
|
||||||
|
@ -107,9 +101,7 @@ where
|
||||||
FP: FfiPermissions + 'static,
|
FP: FfiPermissions + 'static,
|
||||||
{
|
{
|
||||||
let permissions = state.borrow_mut::<FP>();
|
let permissions = state.borrow_mut::<FP>();
|
||||||
permissions
|
permissions.check_partial_no_path()?;
|
||||||
.check_partial_no_path()
|
|
||||||
.map_err(ReprError::Permission)?;
|
|
||||||
|
|
||||||
let Some(buf) = buf.get_backing_store() else {
|
let Some(buf) = buf.get_backing_store() else {
|
||||||
return Ok(0 as _);
|
return Ok(0 as _);
|
||||||
|
@ -130,9 +122,7 @@ where
|
||||||
FP: FfiPermissions + 'static,
|
FP: FfiPermissions + 'static,
|
||||||
{
|
{
|
||||||
let permissions = state.borrow_mut::<FP>();
|
let permissions = state.borrow_mut::<FP>();
|
||||||
permissions
|
permissions.check_partial_no_path()?;
|
||||||
.check_partial_no_path()
|
|
||||||
.map_err(ReprError::Permission)?;
|
|
||||||
|
|
||||||
if ptr.is_null() {
|
if ptr.is_null() {
|
||||||
return Err(ReprError::InvalidOffset);
|
return Err(ReprError::InvalidOffset);
|
||||||
|
@ -162,9 +152,7 @@ where
|
||||||
FP: FfiPermissions + 'static,
|
FP: FfiPermissions + 'static,
|
||||||
{
|
{
|
||||||
let permissions = state.borrow_mut::<FP>();
|
let permissions = state.borrow_mut::<FP>();
|
||||||
permissions
|
permissions.check_partial_no_path()?;
|
||||||
.check_partial_no_path()
|
|
||||||
.map_err(ReprError::Permission)?;
|
|
||||||
|
|
||||||
Ok(ptr as usize)
|
Ok(ptr as usize)
|
||||||
}
|
}
|
||||||
|
@ -181,9 +169,7 @@ where
|
||||||
FP: FfiPermissions + 'static,
|
FP: FfiPermissions + 'static,
|
||||||
{
|
{
|
||||||
let permissions = state.borrow_mut::<FP>();
|
let permissions = state.borrow_mut::<FP>();
|
||||||
permissions
|
permissions.check_partial_no_path()?;
|
||||||
.check_partial_no_path()
|
|
||||||
.map_err(ReprError::Permission)?;
|
|
||||||
|
|
||||||
if ptr.is_null() {
|
if ptr.is_null() {
|
||||||
return Err(ReprError::InvalidArrayBuffer);
|
return Err(ReprError::InvalidArrayBuffer);
|
||||||
|
@ -215,9 +201,7 @@ where
|
||||||
FP: FfiPermissions + 'static,
|
FP: FfiPermissions + 'static,
|
||||||
{
|
{
|
||||||
let permissions = state.borrow_mut::<FP>();
|
let permissions = state.borrow_mut::<FP>();
|
||||||
permissions
|
permissions.check_partial_no_path()?;
|
||||||
.check_partial_no_path()
|
|
||||||
.map_err(ReprError::Permission)?;
|
|
||||||
|
|
||||||
if src.is_null() {
|
if src.is_null() {
|
||||||
Err(ReprError::InvalidArrayBuffer)
|
Err(ReprError::InvalidArrayBuffer)
|
||||||
|
@ -246,9 +230,7 @@ where
|
||||||
FP: FfiPermissions + 'static,
|
FP: FfiPermissions + 'static,
|
||||||
{
|
{
|
||||||
let permissions = state.borrow_mut::<FP>();
|
let permissions = state.borrow_mut::<FP>();
|
||||||
permissions
|
permissions.check_partial_no_path()?;
|
||||||
.check_partial_no_path()
|
|
||||||
.map_err(ReprError::Permission)?;
|
|
||||||
|
|
||||||
if ptr.is_null() {
|
if ptr.is_null() {
|
||||||
return Err(ReprError::InvalidCString);
|
return Err(ReprError::InvalidCString);
|
||||||
|
@ -272,9 +254,7 @@ where
|
||||||
FP: FfiPermissions + 'static,
|
FP: FfiPermissions + 'static,
|
||||||
{
|
{
|
||||||
let permissions = state.borrow_mut::<FP>();
|
let permissions = state.borrow_mut::<FP>();
|
||||||
permissions
|
permissions.check_partial_no_path()?;
|
||||||
.check_partial_no_path()
|
|
||||||
.map_err(ReprError::Permission)?;
|
|
||||||
|
|
||||||
if ptr.is_null() {
|
if ptr.is_null() {
|
||||||
return Err(ReprError::InvalidBool);
|
return Err(ReprError::InvalidBool);
|
||||||
|
@ -294,9 +274,7 @@ where
|
||||||
FP: FfiPermissions + 'static,
|
FP: FfiPermissions + 'static,
|
||||||
{
|
{
|
||||||
let permissions = state.borrow_mut::<FP>();
|
let permissions = state.borrow_mut::<FP>();
|
||||||
permissions
|
permissions.check_partial_no_path()?;
|
||||||
.check_partial_no_path()
|
|
||||||
.map_err(ReprError::Permission)?;
|
|
||||||
|
|
||||||
if ptr.is_null() {
|
if ptr.is_null() {
|
||||||
return Err(ReprError::InvalidU8);
|
return Err(ReprError::InvalidU8);
|
||||||
|
@ -318,9 +296,7 @@ where
|
||||||
FP: FfiPermissions + 'static,
|
FP: FfiPermissions + 'static,
|
||||||
{
|
{
|
||||||
let permissions = state.borrow_mut::<FP>();
|
let permissions = state.borrow_mut::<FP>();
|
||||||
permissions
|
permissions.check_partial_no_path()?;
|
||||||
.check_partial_no_path()
|
|
||||||
.map_err(ReprError::Permission)?;
|
|
||||||
|
|
||||||
if ptr.is_null() {
|
if ptr.is_null() {
|
||||||
return Err(ReprError::InvalidI8);
|
return Err(ReprError::InvalidI8);
|
||||||
|
@ -342,9 +318,7 @@ where
|
||||||
FP: FfiPermissions + 'static,
|
FP: FfiPermissions + 'static,
|
||||||
{
|
{
|
||||||
let permissions = state.borrow_mut::<FP>();
|
let permissions = state.borrow_mut::<FP>();
|
||||||
permissions
|
permissions.check_partial_no_path()?;
|
||||||
.check_partial_no_path()
|
|
||||||
.map_err(ReprError::Permission)?;
|
|
||||||
|
|
||||||
if ptr.is_null() {
|
if ptr.is_null() {
|
||||||
return Err(ReprError::InvalidU16);
|
return Err(ReprError::InvalidU16);
|
||||||
|
@ -366,9 +340,7 @@ where
|
||||||
FP: FfiPermissions + 'static,
|
FP: FfiPermissions + 'static,
|
||||||
{
|
{
|
||||||
let permissions = state.borrow_mut::<FP>();
|
let permissions = state.borrow_mut::<FP>();
|
||||||
permissions
|
permissions.check_partial_no_path()?;
|
||||||
.check_partial_no_path()
|
|
||||||
.map_err(ReprError::Permission)?;
|
|
||||||
|
|
||||||
if ptr.is_null() {
|
if ptr.is_null() {
|
||||||
return Err(ReprError::InvalidI16);
|
return Err(ReprError::InvalidI16);
|
||||||
|
@ -390,9 +362,7 @@ where
|
||||||
FP: FfiPermissions + 'static,
|
FP: FfiPermissions + 'static,
|
||||||
{
|
{
|
||||||
let permissions = state.borrow_mut::<FP>();
|
let permissions = state.borrow_mut::<FP>();
|
||||||
permissions
|
permissions.check_partial_no_path()?;
|
||||||
.check_partial_no_path()
|
|
||||||
.map_err(ReprError::Permission)?;
|
|
||||||
|
|
||||||
if ptr.is_null() {
|
if ptr.is_null() {
|
||||||
return Err(ReprError::InvalidU32);
|
return Err(ReprError::InvalidU32);
|
||||||
|
@ -412,9 +382,7 @@ where
|
||||||
FP: FfiPermissions + 'static,
|
FP: FfiPermissions + 'static,
|
||||||
{
|
{
|
||||||
let permissions = state.borrow_mut::<FP>();
|
let permissions = state.borrow_mut::<FP>();
|
||||||
permissions
|
permissions.check_partial_no_path()?;
|
||||||
.check_partial_no_path()
|
|
||||||
.map_err(ReprError::Permission)?;
|
|
||||||
|
|
||||||
if ptr.is_null() {
|
if ptr.is_null() {
|
||||||
return Err(ReprError::InvalidI32);
|
return Err(ReprError::InvalidI32);
|
||||||
|
@ -437,9 +405,7 @@ where
|
||||||
FP: FfiPermissions + 'static,
|
FP: FfiPermissions + 'static,
|
||||||
{
|
{
|
||||||
let permissions = state.borrow_mut::<FP>();
|
let permissions = state.borrow_mut::<FP>();
|
||||||
permissions
|
permissions.check_partial_no_path()?;
|
||||||
.check_partial_no_path()
|
|
||||||
.map_err(ReprError::Permission)?;
|
|
||||||
|
|
||||||
if ptr.is_null() {
|
if ptr.is_null() {
|
||||||
return Err(ReprError::InvalidU64);
|
return Err(ReprError::InvalidU64);
|
||||||
|
@ -465,9 +431,7 @@ where
|
||||||
FP: FfiPermissions + 'static,
|
FP: FfiPermissions + 'static,
|
||||||
{
|
{
|
||||||
let permissions = state.borrow_mut::<FP>();
|
let permissions = state.borrow_mut::<FP>();
|
||||||
permissions
|
permissions.check_partial_no_path()?;
|
||||||
.check_partial_no_path()
|
|
||||||
.map_err(ReprError::Permission)?;
|
|
||||||
|
|
||||||
if ptr.is_null() {
|
if ptr.is_null() {
|
||||||
return Err(ReprError::InvalidI64);
|
return Err(ReprError::InvalidI64);
|
||||||
|
@ -490,9 +454,7 @@ where
|
||||||
FP: FfiPermissions + 'static,
|
FP: FfiPermissions + 'static,
|
||||||
{
|
{
|
||||||
let permissions = state.borrow_mut::<FP>();
|
let permissions = state.borrow_mut::<FP>();
|
||||||
permissions
|
permissions.check_partial_no_path()?;
|
||||||
.check_partial_no_path()
|
|
||||||
.map_err(ReprError::Permission)?;
|
|
||||||
|
|
||||||
if ptr.is_null() {
|
if ptr.is_null() {
|
||||||
return Err(ReprError::InvalidF32);
|
return Err(ReprError::InvalidF32);
|
||||||
|
@ -512,9 +474,7 @@ where
|
||||||
FP: FfiPermissions + 'static,
|
FP: FfiPermissions + 'static,
|
||||||
{
|
{
|
||||||
let permissions = state.borrow_mut::<FP>();
|
let permissions = state.borrow_mut::<FP>();
|
||||||
permissions
|
permissions.check_partial_no_path()?;
|
||||||
.check_partial_no_path()
|
|
||||||
.map_err(ReprError::Permission)?;
|
|
||||||
|
|
||||||
if ptr.is_null() {
|
if ptr.is_null() {
|
||||||
return Err(ReprError::InvalidF64);
|
return Err(ReprError::InvalidF64);
|
||||||
|
@ -534,9 +494,7 @@ where
|
||||||
FP: FfiPermissions + 'static,
|
FP: FfiPermissions + 'static,
|
||||||
{
|
{
|
||||||
let permissions = state.borrow_mut::<FP>();
|
let permissions = state.borrow_mut::<FP>();
|
||||||
permissions
|
permissions.check_partial_no_path()?;
|
||||||
.check_partial_no_path()
|
|
||||||
.map_err(ReprError::Permission)?;
|
|
||||||
|
|
||||||
if ptr.is_null() {
|
if ptr.is_null() {
|
||||||
return Err(ReprError::InvalidPointer);
|
return Err(ReprError::InvalidPointer);
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "deno_fs"
|
name = "deno_fs"
|
||||||
version = "0.85.0"
|
version = "0.86.0"
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
|
|
@ -22,8 +22,8 @@ pub use crate::sync::MaybeSync;
|
||||||
|
|
||||||
use crate::ops::*;
|
use crate::ops::*;
|
||||||
|
|
||||||
use deno_core::error::AnyError;
|
|
||||||
use deno_io::fs::FsError;
|
use deno_io::fs::FsError;
|
||||||
|
use deno_permissions::PermissionCheckError;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
@ -42,45 +42,51 @@ pub trait FsPermissions {
|
||||||
&mut self,
|
&mut self,
|
||||||
path: &str,
|
path: &str,
|
||||||
api_name: &str,
|
api_name: &str,
|
||||||
) -> Result<PathBuf, AnyError>;
|
) -> Result<PathBuf, PermissionCheckError>;
|
||||||
#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
|
#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
|
||||||
fn check_read_path<'a>(
|
fn check_read_path<'a>(
|
||||||
&mut self,
|
&mut self,
|
||||||
path: &'a Path,
|
path: &'a Path,
|
||||||
api_name: &str,
|
api_name: &str,
|
||||||
) -> Result<Cow<'a, Path>, AnyError>;
|
) -> Result<Cow<'a, Path>, PermissionCheckError>;
|
||||||
fn check_read_all(&mut self, api_name: &str) -> Result<(), AnyError>;
|
fn check_read_all(
|
||||||
|
&mut self,
|
||||||
|
api_name: &str,
|
||||||
|
) -> Result<(), PermissionCheckError>;
|
||||||
fn check_read_blind(
|
fn check_read_blind(
|
||||||
&mut self,
|
&mut self,
|
||||||
p: &Path,
|
p: &Path,
|
||||||
display: &str,
|
display: &str,
|
||||||
api_name: &str,
|
api_name: &str,
|
||||||
) -> Result<(), AnyError>;
|
) -> Result<(), PermissionCheckError>;
|
||||||
#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
|
#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
|
||||||
fn check_write(
|
fn check_write(
|
||||||
&mut self,
|
&mut self,
|
||||||
path: &str,
|
path: &str,
|
||||||
api_name: &str,
|
api_name: &str,
|
||||||
) -> Result<PathBuf, AnyError>;
|
) -> Result<PathBuf, PermissionCheckError>;
|
||||||
#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
|
#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
|
||||||
fn check_write_path<'a>(
|
fn check_write_path<'a>(
|
||||||
&mut self,
|
&mut self,
|
||||||
path: &'a Path,
|
path: &'a Path,
|
||||||
api_name: &str,
|
api_name: &str,
|
||||||
) -> Result<Cow<'a, Path>, AnyError>;
|
) -> Result<Cow<'a, Path>, PermissionCheckError>;
|
||||||
#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
|
#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
|
||||||
fn check_write_partial(
|
fn check_write_partial(
|
||||||
&mut self,
|
&mut self,
|
||||||
path: &str,
|
path: &str,
|
||||||
api_name: &str,
|
api_name: &str,
|
||||||
) -> Result<PathBuf, AnyError>;
|
) -> Result<PathBuf, PermissionCheckError>;
|
||||||
fn check_write_all(&mut self, api_name: &str) -> Result<(), AnyError>;
|
fn check_write_all(
|
||||||
|
&mut self,
|
||||||
|
api_name: &str,
|
||||||
|
) -> Result<(), PermissionCheckError>;
|
||||||
fn check_write_blind(
|
fn check_write_blind(
|
||||||
&mut self,
|
&mut self,
|
||||||
p: &Path,
|
p: &Path,
|
||||||
display: &str,
|
display: &str,
|
||||||
api_name: &str,
|
api_name: &str,
|
||||||
) -> Result<(), AnyError>;
|
) -> Result<(), PermissionCheckError>;
|
||||||
|
|
||||||
fn check<'a>(
|
fn check<'a>(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
@ -140,7 +146,7 @@ impl FsPermissions for deno_permissions::PermissionsContainer {
|
||||||
&mut self,
|
&mut self,
|
||||||
path: &str,
|
path: &str,
|
||||||
api_name: &str,
|
api_name: &str,
|
||||||
) -> Result<PathBuf, AnyError> {
|
) -> Result<PathBuf, PermissionCheckError> {
|
||||||
deno_permissions::PermissionsContainer::check_read(self, path, api_name)
|
deno_permissions::PermissionsContainer::check_read(self, path, api_name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,7 +154,7 @@ impl FsPermissions for deno_permissions::PermissionsContainer {
|
||||||
&mut self,
|
&mut self,
|
||||||
path: &'a Path,
|
path: &'a Path,
|
||||||
api_name: &str,
|
api_name: &str,
|
||||||
) -> Result<Cow<'a, Path>, AnyError> {
|
) -> Result<Cow<'a, Path>, PermissionCheckError> {
|
||||||
deno_permissions::PermissionsContainer::check_read_path(
|
deno_permissions::PermissionsContainer::check_read_path(
|
||||||
self,
|
self,
|
||||||
path,
|
path,
|
||||||
|
@ -160,7 +166,7 @@ impl FsPermissions for deno_permissions::PermissionsContainer {
|
||||||
path: &Path,
|
path: &Path,
|
||||||
display: &str,
|
display: &str,
|
||||||
api_name: &str,
|
api_name: &str,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), PermissionCheckError> {
|
||||||
deno_permissions::PermissionsContainer::check_read_blind(
|
deno_permissions::PermissionsContainer::check_read_blind(
|
||||||
self, path, display, api_name,
|
self, path, display, api_name,
|
||||||
)
|
)
|
||||||
|
@ -170,7 +176,7 @@ impl FsPermissions for deno_permissions::PermissionsContainer {
|
||||||
&mut self,
|
&mut self,
|
||||||
path: &str,
|
path: &str,
|
||||||
api_name: &str,
|
api_name: &str,
|
||||||
) -> Result<PathBuf, AnyError> {
|
) -> Result<PathBuf, PermissionCheckError> {
|
||||||
deno_permissions::PermissionsContainer::check_write(self, path, api_name)
|
deno_permissions::PermissionsContainer::check_write(self, path, api_name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,7 +184,7 @@ impl FsPermissions for deno_permissions::PermissionsContainer {
|
||||||
&mut self,
|
&mut self,
|
||||||
path: &'a Path,
|
path: &'a Path,
|
||||||
api_name: &str,
|
api_name: &str,
|
||||||
) -> Result<Cow<'a, Path>, AnyError> {
|
) -> Result<Cow<'a, Path>, PermissionCheckError> {
|
||||||
deno_permissions::PermissionsContainer::check_write_path(
|
deno_permissions::PermissionsContainer::check_write_path(
|
||||||
self, path, api_name,
|
self, path, api_name,
|
||||||
)
|
)
|
||||||
|
@ -188,7 +194,7 @@ impl FsPermissions for deno_permissions::PermissionsContainer {
|
||||||
&mut self,
|
&mut self,
|
||||||
path: &str,
|
path: &str,
|
||||||
api_name: &str,
|
api_name: &str,
|
||||||
) -> Result<PathBuf, AnyError> {
|
) -> Result<PathBuf, PermissionCheckError> {
|
||||||
deno_permissions::PermissionsContainer::check_write_partial(
|
deno_permissions::PermissionsContainer::check_write_partial(
|
||||||
self, path, api_name,
|
self, path, api_name,
|
||||||
)
|
)
|
||||||
|
@ -199,17 +205,23 @@ impl FsPermissions for deno_permissions::PermissionsContainer {
|
||||||
p: &Path,
|
p: &Path,
|
||||||
display: &str,
|
display: &str,
|
||||||
api_name: &str,
|
api_name: &str,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), PermissionCheckError> {
|
||||||
deno_permissions::PermissionsContainer::check_write_blind(
|
deno_permissions::PermissionsContainer::check_write_blind(
|
||||||
self, p, display, api_name,
|
self, p, display, api_name,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_read_all(&mut self, api_name: &str) -> Result<(), AnyError> {
|
fn check_read_all(
|
||||||
|
&mut self,
|
||||||
|
api_name: &str,
|
||||||
|
) -> Result<(), PermissionCheckError> {
|
||||||
deno_permissions::PermissionsContainer::check_read_all(self, api_name)
|
deno_permissions::PermissionsContainer::check_read_all(self, api_name)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_write_all(&mut self, api_name: &str) -> Result<(), AnyError> {
|
fn check_write_all(
|
||||||
|
&mut self,
|
||||||
|
api_name: &str,
|
||||||
|
) -> Result<(), PermissionCheckError> {
|
||||||
deno_permissions::PermissionsContainer::check_write_all(self, api_name)
|
deno_permissions::PermissionsContainer::check_write_all(self, api_name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
217
ext/fs/ops.rs
217
ext/fs/ops.rs
|
@ -10,6 +10,12 @@ use std::path::PathBuf;
|
||||||
use std::path::StripPrefixError;
|
use std::path::StripPrefixError;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
use crate::interface::AccessCheckFn;
|
||||||
|
use crate::interface::FileSystemRc;
|
||||||
|
use crate::interface::FsDirEntry;
|
||||||
|
use crate::interface::FsFileType;
|
||||||
|
use crate::FsPermissions;
|
||||||
|
use crate::OpenOptions;
|
||||||
use deno_core::op2;
|
use deno_core::op2;
|
||||||
use deno_core::CancelFuture;
|
use deno_core::CancelFuture;
|
||||||
use deno_core::CancelHandle;
|
use deno_core::CancelHandle;
|
||||||
|
@ -20,18 +26,12 @@ use deno_core::ToJsBuffer;
|
||||||
use deno_io::fs::FileResource;
|
use deno_io::fs::FileResource;
|
||||||
use deno_io::fs::FsError;
|
use deno_io::fs::FsError;
|
||||||
use deno_io::fs::FsStat;
|
use deno_io::fs::FsStat;
|
||||||
|
use deno_permissions::PermissionCheckError;
|
||||||
use rand::rngs::ThreadRng;
|
use rand::rngs::ThreadRng;
|
||||||
use rand::thread_rng;
|
use rand::thread_rng;
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
use crate::interface::AccessCheckFn;
|
|
||||||
use crate::interface::FileSystemRc;
|
|
||||||
use crate::interface::FsDirEntry;
|
|
||||||
use crate::interface::FsFileType;
|
|
||||||
use crate::FsPermissions;
|
|
||||||
use crate::OpenOptions;
|
|
||||||
|
|
||||||
#[derive(Debug, thiserror::Error)]
|
#[derive(Debug, thiserror::Error)]
|
||||||
pub enum FsOpsError {
|
pub enum FsOpsError {
|
||||||
#[error("{0}")]
|
#[error("{0}")]
|
||||||
|
@ -39,7 +39,7 @@ pub enum FsOpsError {
|
||||||
#[error("{0}")]
|
#[error("{0}")]
|
||||||
OperationError(#[source] OperationError),
|
OperationError(#[source] OperationError),
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Permission(deno_core::error::AnyError),
|
Permission(#[from] PermissionCheckError),
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Resource(deno_core::error::AnyError),
|
Resource(deno_core::error::AnyError),
|
||||||
#[error("File name or path {0:?} is not valid UTF-8")]
|
#[error("File name or path {0:?} is not valid UTF-8")]
|
||||||
|
@ -150,8 +150,7 @@ where
|
||||||
let path = fs.cwd()?;
|
let path = fs.cwd()?;
|
||||||
state
|
state
|
||||||
.borrow_mut::<P>()
|
.borrow_mut::<P>()
|
||||||
.check_read_blind(&path, "CWD", "Deno.cwd()")
|
.check_read_blind(&path, "CWD", "Deno.cwd()")?;
|
||||||
.map_err(FsOpsError::Permission)?;
|
|
||||||
let path_str = path_into_string(path.into_os_string())?;
|
let path_str = path_into_string(path.into_os_string())?;
|
||||||
Ok(path_str)
|
Ok(path_str)
|
||||||
}
|
}
|
||||||
|
@ -166,8 +165,7 @@ where
|
||||||
{
|
{
|
||||||
let d = state
|
let d = state
|
||||||
.borrow_mut::<P>()
|
.borrow_mut::<P>()
|
||||||
.check_read(directory, "Deno.chdir()")
|
.check_read(directory, "Deno.chdir()")?;
|
||||||
.map_err(FsOpsError::Permission)?;
|
|
||||||
state
|
state
|
||||||
.borrow::<FileSystemRc>()
|
.borrow::<FileSystemRc>()
|
||||||
.chdir(&d)
|
.chdir(&d)
|
||||||
|
@ -253,8 +251,7 @@ where
|
||||||
|
|
||||||
let path = state
|
let path = state
|
||||||
.borrow_mut::<P>()
|
.borrow_mut::<P>()
|
||||||
.check_write(&path, "Deno.mkdirSync()")
|
.check_write(&path, "Deno.mkdirSync()")?;
|
||||||
.map_err(FsOpsError::Permission)?;
|
|
||||||
|
|
||||||
let fs = state.borrow::<FileSystemRc>();
|
let fs = state.borrow::<FileSystemRc>();
|
||||||
fs.mkdir_sync(&path, recursive, Some(mode))
|
fs.mkdir_sync(&path, recursive, Some(mode))
|
||||||
|
@ -277,10 +274,7 @@ where
|
||||||
|
|
||||||
let (fs, path) = {
|
let (fs, path) = {
|
||||||
let mut state = state.borrow_mut();
|
let mut state = state.borrow_mut();
|
||||||
let path = state
|
let path = state.borrow_mut::<P>().check_write(&path, "Deno.mkdir()")?;
|
||||||
.borrow_mut::<P>()
|
|
||||||
.check_write(&path, "Deno.mkdir()")
|
|
||||||
.map_err(FsOpsError::Permission)?;
|
|
||||||
(state.borrow::<FileSystemRc>().clone(), path)
|
(state.borrow::<FileSystemRc>().clone(), path)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -302,8 +296,7 @@ where
|
||||||
{
|
{
|
||||||
let path = state
|
let path = state
|
||||||
.borrow_mut::<P>()
|
.borrow_mut::<P>()
|
||||||
.check_write(&path, "Deno.chmodSync()")
|
.check_write(&path, "Deno.chmodSync()")?;
|
||||||
.map_err(FsOpsError::Permission)?;
|
|
||||||
let fs = state.borrow::<FileSystemRc>();
|
let fs = state.borrow::<FileSystemRc>();
|
||||||
fs.chmod_sync(&path, mode).context_path("chmod", &path)?;
|
fs.chmod_sync(&path, mode).context_path("chmod", &path)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -320,10 +313,7 @@ where
|
||||||
{
|
{
|
||||||
let (fs, path) = {
|
let (fs, path) = {
|
||||||
let mut state = state.borrow_mut();
|
let mut state = state.borrow_mut();
|
||||||
let path = state
|
let path = state.borrow_mut::<P>().check_write(&path, "Deno.chmod()")?;
|
||||||
.borrow_mut::<P>()
|
|
||||||
.check_write(&path, "Deno.chmod()")
|
|
||||||
.map_err(FsOpsError::Permission)?;
|
|
||||||
(state.borrow::<FileSystemRc>().clone(), path)
|
(state.borrow::<FileSystemRc>().clone(), path)
|
||||||
};
|
};
|
||||||
fs.chmod_async(path.clone(), mode)
|
fs.chmod_async(path.clone(), mode)
|
||||||
|
@ -344,8 +334,7 @@ where
|
||||||
{
|
{
|
||||||
let path = state
|
let path = state
|
||||||
.borrow_mut::<P>()
|
.borrow_mut::<P>()
|
||||||
.check_write(&path, "Deno.chownSync()")
|
.check_write(&path, "Deno.chownSync()")?;
|
||||||
.map_err(FsOpsError::Permission)?;
|
|
||||||
let fs = state.borrow::<FileSystemRc>();
|
let fs = state.borrow::<FileSystemRc>();
|
||||||
fs.chown_sync(&path, uid, gid)
|
fs.chown_sync(&path, uid, gid)
|
||||||
.context_path("chown", &path)?;
|
.context_path("chown", &path)?;
|
||||||
|
@ -364,10 +353,7 @@ where
|
||||||
{
|
{
|
||||||
let (fs, path) = {
|
let (fs, path) = {
|
||||||
let mut state = state.borrow_mut();
|
let mut state = state.borrow_mut();
|
||||||
let path = state
|
let path = state.borrow_mut::<P>().check_write(&path, "Deno.chown()")?;
|
||||||
.borrow_mut::<P>()
|
|
||||||
.check_write(&path, "Deno.chown()")
|
|
||||||
.map_err(FsOpsError::Permission)?;
|
|
||||||
(state.borrow::<FileSystemRc>().clone(), path)
|
(state.borrow::<FileSystemRc>().clone(), path)
|
||||||
};
|
};
|
||||||
fs.chown_async(path.clone(), uid, gid)
|
fs.chown_async(path.clone(), uid, gid)
|
||||||
|
@ -387,8 +373,7 @@ where
|
||||||
{
|
{
|
||||||
let path = state
|
let path = state
|
||||||
.borrow_mut::<P>()
|
.borrow_mut::<P>()
|
||||||
.check_write(path, "Deno.removeSync()")
|
.check_write(path, "Deno.removeSync()")?;
|
||||||
.map_err(FsOpsError::Permission)?;
|
|
||||||
|
|
||||||
let fs = state.borrow::<FileSystemRc>();
|
let fs = state.borrow::<FileSystemRc>();
|
||||||
fs.remove_sync(&path, recursive)
|
fs.remove_sync(&path, recursive)
|
||||||
|
@ -411,13 +396,11 @@ where
|
||||||
let path = if recursive {
|
let path = if recursive {
|
||||||
state
|
state
|
||||||
.borrow_mut::<P>()
|
.borrow_mut::<P>()
|
||||||
.check_write(&path, "Deno.remove()")
|
.check_write(&path, "Deno.remove()")?
|
||||||
.map_err(FsOpsError::Permission)?
|
|
||||||
} else {
|
} else {
|
||||||
state
|
state
|
||||||
.borrow_mut::<P>()
|
.borrow_mut::<P>()
|
||||||
.check_write_partial(&path, "Deno.remove()")
|
.check_write_partial(&path, "Deno.remove()")?
|
||||||
.map_err(FsOpsError::Permission)?
|
|
||||||
};
|
};
|
||||||
|
|
||||||
(state.borrow::<FileSystemRc>().clone(), path)
|
(state.borrow::<FileSystemRc>().clone(), path)
|
||||||
|
@ -440,12 +423,8 @@ where
|
||||||
P: FsPermissions + 'static,
|
P: FsPermissions + 'static,
|
||||||
{
|
{
|
||||||
let permissions = state.borrow_mut::<P>();
|
let permissions = state.borrow_mut::<P>();
|
||||||
let from = permissions
|
let from = permissions.check_read(from, "Deno.copyFileSync()")?;
|
||||||
.check_read(from, "Deno.copyFileSync()")
|
let to = permissions.check_write(to, "Deno.copyFileSync()")?;
|
||||||
.map_err(FsOpsError::Permission)?;
|
|
||||||
let to = permissions
|
|
||||||
.check_write(to, "Deno.copyFileSync()")
|
|
||||||
.map_err(FsOpsError::Permission)?;
|
|
||||||
|
|
||||||
let fs = state.borrow::<FileSystemRc>();
|
let fs = state.borrow::<FileSystemRc>();
|
||||||
fs.copy_file_sync(&from, &to)
|
fs.copy_file_sync(&from, &to)
|
||||||
|
@ -466,12 +445,8 @@ where
|
||||||
let (fs, from, to) = {
|
let (fs, from, to) = {
|
||||||
let mut state = state.borrow_mut();
|
let mut state = state.borrow_mut();
|
||||||
let permissions = state.borrow_mut::<P>();
|
let permissions = state.borrow_mut::<P>();
|
||||||
let from = permissions
|
let from = permissions.check_read(&from, "Deno.copyFile()")?;
|
||||||
.check_read(&from, "Deno.copyFile()")
|
let to = permissions.check_write(&to, "Deno.copyFile()")?;
|
||||||
.map_err(FsOpsError::Permission)?;
|
|
||||||
let to = permissions
|
|
||||||
.check_write(&to, "Deno.copyFile()")
|
|
||||||
.map_err(FsOpsError::Permission)?;
|
|
||||||
(state.borrow::<FileSystemRc>().clone(), from, to)
|
(state.borrow::<FileSystemRc>().clone(), from, to)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -493,8 +468,7 @@ where
|
||||||
{
|
{
|
||||||
let path = state
|
let path = state
|
||||||
.borrow_mut::<P>()
|
.borrow_mut::<P>()
|
||||||
.check_read(&path, "Deno.statSync()")
|
.check_read(&path, "Deno.statSync()")?;
|
||||||
.map_err(FsOpsError::Permission)?;
|
|
||||||
let fs = state.borrow::<FileSystemRc>();
|
let fs = state.borrow::<FileSystemRc>();
|
||||||
let stat = fs.stat_sync(&path).context_path("stat", &path)?;
|
let stat = fs.stat_sync(&path).context_path("stat", &path)?;
|
||||||
let serializable_stat = SerializableStat::from(stat);
|
let serializable_stat = SerializableStat::from(stat);
|
||||||
|
@ -514,9 +488,7 @@ where
|
||||||
let (fs, path) = {
|
let (fs, path) = {
|
||||||
let mut state = state.borrow_mut();
|
let mut state = state.borrow_mut();
|
||||||
let permissions = state.borrow_mut::<P>();
|
let permissions = state.borrow_mut::<P>();
|
||||||
let path = permissions
|
let path = permissions.check_read(&path, "Deno.stat()")?;
|
||||||
.check_read(&path, "Deno.stat()")
|
|
||||||
.map_err(FsOpsError::Permission)?;
|
|
||||||
(state.borrow::<FileSystemRc>().clone(), path)
|
(state.borrow::<FileSystemRc>().clone(), path)
|
||||||
};
|
};
|
||||||
let stat = fs
|
let stat = fs
|
||||||
|
@ -537,8 +509,7 @@ where
|
||||||
{
|
{
|
||||||
let path = state
|
let path = state
|
||||||
.borrow_mut::<P>()
|
.borrow_mut::<P>()
|
||||||
.check_read(&path, "Deno.lstatSync()")
|
.check_read(&path, "Deno.lstatSync()")?;
|
||||||
.map_err(FsOpsError::Permission)?;
|
|
||||||
let fs = state.borrow::<FileSystemRc>();
|
let fs = state.borrow::<FileSystemRc>();
|
||||||
let stat = fs.lstat_sync(&path).context_path("lstat", &path)?;
|
let stat = fs.lstat_sync(&path).context_path("lstat", &path)?;
|
||||||
let serializable_stat = SerializableStat::from(stat);
|
let serializable_stat = SerializableStat::from(stat);
|
||||||
|
@ -558,9 +529,7 @@ where
|
||||||
let (fs, path) = {
|
let (fs, path) = {
|
||||||
let mut state = state.borrow_mut();
|
let mut state = state.borrow_mut();
|
||||||
let permissions = state.borrow_mut::<P>();
|
let permissions = state.borrow_mut::<P>();
|
||||||
let path = permissions
|
let path = permissions.check_read(&path, "Deno.lstat()")?;
|
||||||
.check_read(&path, "Deno.lstat()")
|
|
||||||
.map_err(FsOpsError::Permission)?;
|
|
||||||
(state.borrow::<FileSystemRc>().clone(), path)
|
(state.borrow::<FileSystemRc>().clone(), path)
|
||||||
};
|
};
|
||||||
let stat = fs
|
let stat = fs
|
||||||
|
@ -581,13 +550,9 @@ where
|
||||||
{
|
{
|
||||||
let fs = state.borrow::<FileSystemRc>().clone();
|
let fs = state.borrow::<FileSystemRc>().clone();
|
||||||
let permissions = state.borrow_mut::<P>();
|
let permissions = state.borrow_mut::<P>();
|
||||||
let path = permissions
|
let path = permissions.check_read(&path, "Deno.realPathSync()")?;
|
||||||
.check_read(&path, "Deno.realPathSync()")
|
|
||||||
.map_err(FsOpsError::Permission)?;
|
|
||||||
if path.is_relative() {
|
if path.is_relative() {
|
||||||
permissions
|
permissions.check_read_blind(&fs.cwd()?, "CWD", "Deno.realPathSync()")?;
|
||||||
.check_read_blind(&fs.cwd()?, "CWD", "Deno.realPathSync()")
|
|
||||||
.map_err(FsOpsError::Permission)?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let resolved_path =
|
let resolved_path =
|
||||||
|
@ -610,13 +575,9 @@ where
|
||||||
let mut state = state.borrow_mut();
|
let mut state = state.borrow_mut();
|
||||||
let fs = state.borrow::<FileSystemRc>().clone();
|
let fs = state.borrow::<FileSystemRc>().clone();
|
||||||
let permissions = state.borrow_mut::<P>();
|
let permissions = state.borrow_mut::<P>();
|
||||||
let path = permissions
|
let path = permissions.check_read(&path, "Deno.realPath()")?;
|
||||||
.check_read(&path, "Deno.realPath()")
|
|
||||||
.map_err(FsOpsError::Permission)?;
|
|
||||||
if path.is_relative() {
|
if path.is_relative() {
|
||||||
permissions
|
permissions.check_read_blind(&fs.cwd()?, "CWD", "Deno.realPath()")?;
|
||||||
.check_read_blind(&fs.cwd()?, "CWD", "Deno.realPath()")
|
|
||||||
.map_err(FsOpsError::Permission)?;
|
|
||||||
}
|
}
|
||||||
(fs, path)
|
(fs, path)
|
||||||
};
|
};
|
||||||
|
@ -640,8 +601,7 @@ where
|
||||||
{
|
{
|
||||||
let path = state
|
let path = state
|
||||||
.borrow_mut::<P>()
|
.borrow_mut::<P>()
|
||||||
.check_read(&path, "Deno.readDirSync()")
|
.check_read(&path, "Deno.readDirSync()")?;
|
||||||
.map_err(FsOpsError::Permission)?;
|
|
||||||
|
|
||||||
let fs = state.borrow::<FileSystemRc>();
|
let fs = state.borrow::<FileSystemRc>();
|
||||||
let entries = fs.read_dir_sync(&path).context_path("readdir", &path)?;
|
let entries = fs.read_dir_sync(&path).context_path("readdir", &path)?;
|
||||||
|
@ -662,8 +622,7 @@ where
|
||||||
let mut state = state.borrow_mut();
|
let mut state = state.borrow_mut();
|
||||||
let path = state
|
let path = state
|
||||||
.borrow_mut::<P>()
|
.borrow_mut::<P>()
|
||||||
.check_read(&path, "Deno.readDir()")
|
.check_read(&path, "Deno.readDir()")?;
|
||||||
.map_err(FsOpsError::Permission)?;
|
|
||||||
(state.borrow::<FileSystemRc>().clone(), path)
|
(state.borrow::<FileSystemRc>().clone(), path)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -685,15 +644,9 @@ where
|
||||||
P: FsPermissions + 'static,
|
P: FsPermissions + 'static,
|
||||||
{
|
{
|
||||||
let permissions = state.borrow_mut::<P>();
|
let permissions = state.borrow_mut::<P>();
|
||||||
let _ = permissions
|
let _ = permissions.check_read(&oldpath, "Deno.renameSync()")?;
|
||||||
.check_read(&oldpath, "Deno.renameSync()")
|
let oldpath = permissions.check_write(&oldpath, "Deno.renameSync()")?;
|
||||||
.map_err(FsOpsError::Permission)?;
|
let newpath = permissions.check_write(&newpath, "Deno.renameSync()")?;
|
||||||
let oldpath = permissions
|
|
||||||
.check_write(&oldpath, "Deno.renameSync()")
|
|
||||||
.map_err(FsOpsError::Permission)?;
|
|
||||||
let newpath = permissions
|
|
||||||
.check_write(&newpath, "Deno.renameSync()")
|
|
||||||
.map_err(FsOpsError::Permission)?;
|
|
||||||
|
|
||||||
let fs = state.borrow::<FileSystemRc>();
|
let fs = state.borrow::<FileSystemRc>();
|
||||||
fs.rename_sync(&oldpath, &newpath)
|
fs.rename_sync(&oldpath, &newpath)
|
||||||
|
@ -714,15 +667,9 @@ where
|
||||||
let (fs, oldpath, newpath) = {
|
let (fs, oldpath, newpath) = {
|
||||||
let mut state = state.borrow_mut();
|
let mut state = state.borrow_mut();
|
||||||
let permissions = state.borrow_mut::<P>();
|
let permissions = state.borrow_mut::<P>();
|
||||||
_ = permissions
|
_ = permissions.check_read(&oldpath, "Deno.rename()")?;
|
||||||
.check_read(&oldpath, "Deno.rename()")
|
let oldpath = permissions.check_write(&oldpath, "Deno.rename()")?;
|
||||||
.map_err(FsOpsError::Permission)?;
|
let newpath = permissions.check_write(&newpath, "Deno.rename()")?;
|
||||||
let oldpath = permissions
|
|
||||||
.check_write(&oldpath, "Deno.rename()")
|
|
||||||
.map_err(FsOpsError::Permission)?;
|
|
||||||
let newpath = permissions
|
|
||||||
.check_write(&newpath, "Deno.rename()")
|
|
||||||
.map_err(FsOpsError::Permission)?;
|
|
||||||
(state.borrow::<FileSystemRc>().clone(), oldpath, newpath)
|
(state.borrow::<FileSystemRc>().clone(), oldpath, newpath)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -743,18 +690,10 @@ where
|
||||||
P: FsPermissions + 'static,
|
P: FsPermissions + 'static,
|
||||||
{
|
{
|
||||||
let permissions = state.borrow_mut::<P>();
|
let permissions = state.borrow_mut::<P>();
|
||||||
_ = permissions
|
_ = permissions.check_read(oldpath, "Deno.linkSync()")?;
|
||||||
.check_read(oldpath, "Deno.linkSync()")
|
let oldpath = permissions.check_write(oldpath, "Deno.linkSync()")?;
|
||||||
.map_err(FsOpsError::Permission)?;
|
_ = permissions.check_read(newpath, "Deno.linkSync()")?;
|
||||||
let oldpath = permissions
|
let newpath = permissions.check_write(newpath, "Deno.linkSync()")?;
|
||||||
.check_write(oldpath, "Deno.linkSync()")
|
|
||||||
.map_err(FsOpsError::Permission)?;
|
|
||||||
_ = permissions
|
|
||||||
.check_read(newpath, "Deno.linkSync()")
|
|
||||||
.map_err(FsOpsError::Permission)?;
|
|
||||||
let newpath = permissions
|
|
||||||
.check_write(newpath, "Deno.linkSync()")
|
|
||||||
.map_err(FsOpsError::Permission)?;
|
|
||||||
|
|
||||||
let fs = state.borrow::<FileSystemRc>();
|
let fs = state.borrow::<FileSystemRc>();
|
||||||
fs.link_sync(&oldpath, &newpath)
|
fs.link_sync(&oldpath, &newpath)
|
||||||
|
@ -775,18 +714,10 @@ where
|
||||||
let (fs, oldpath, newpath) = {
|
let (fs, oldpath, newpath) = {
|
||||||
let mut state = state.borrow_mut();
|
let mut state = state.borrow_mut();
|
||||||
let permissions = state.borrow_mut::<P>();
|
let permissions = state.borrow_mut::<P>();
|
||||||
_ = permissions
|
_ = permissions.check_read(&oldpath, "Deno.link()")?;
|
||||||
.check_read(&oldpath, "Deno.link()")
|
let oldpath = permissions.check_write(&oldpath, "Deno.link()")?;
|
||||||
.map_err(FsOpsError::Permission)?;
|
_ = permissions.check_read(&newpath, "Deno.link()")?;
|
||||||
let oldpath = permissions
|
let newpath = permissions.check_write(&newpath, "Deno.link()")?;
|
||||||
.check_write(&oldpath, "Deno.link()")
|
|
||||||
.map_err(FsOpsError::Permission)?;
|
|
||||||
_ = permissions
|
|
||||||
.check_read(&newpath, "Deno.link()")
|
|
||||||
.map_err(FsOpsError::Permission)?;
|
|
||||||
let newpath = permissions
|
|
||||||
.check_write(&newpath, "Deno.link()")
|
|
||||||
.map_err(FsOpsError::Permission)?;
|
|
||||||
(state.borrow::<FileSystemRc>().clone(), oldpath, newpath)
|
(state.borrow::<FileSystemRc>().clone(), oldpath, newpath)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -811,12 +742,8 @@ where
|
||||||
let newpath = PathBuf::from(newpath);
|
let newpath = PathBuf::from(newpath);
|
||||||
|
|
||||||
let permissions = state.borrow_mut::<P>();
|
let permissions = state.borrow_mut::<P>();
|
||||||
permissions
|
permissions.check_write_all("Deno.symlinkSync()")?;
|
||||||
.check_write_all("Deno.symlinkSync()")
|
permissions.check_read_all("Deno.symlinkSync()")?;
|
||||||
.map_err(FsOpsError::Permission)?;
|
|
||||||
permissions
|
|
||||||
.check_read_all("Deno.symlinkSync()")
|
|
||||||
.map_err(FsOpsError::Permission)?;
|
|
||||||
|
|
||||||
let fs = state.borrow::<FileSystemRc>();
|
let fs = state.borrow::<FileSystemRc>();
|
||||||
fs.symlink_sync(&oldpath, &newpath, file_type)
|
fs.symlink_sync(&oldpath, &newpath, file_type)
|
||||||
|
@ -841,12 +768,8 @@ where
|
||||||
let fs = {
|
let fs = {
|
||||||
let mut state = state.borrow_mut();
|
let mut state = state.borrow_mut();
|
||||||
let permissions = state.borrow_mut::<P>();
|
let permissions = state.borrow_mut::<P>();
|
||||||
permissions
|
permissions.check_write_all("Deno.symlink()")?;
|
||||||
.check_write_all("Deno.symlink()")
|
permissions.check_read_all("Deno.symlink()")?;
|
||||||
.map_err(FsOpsError::Permission)?;
|
|
||||||
permissions
|
|
||||||
.check_read_all("Deno.symlink()")
|
|
||||||
.map_err(FsOpsError::Permission)?;
|
|
||||||
state.borrow::<FileSystemRc>().clone()
|
state.borrow::<FileSystemRc>().clone()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -868,8 +791,7 @@ where
|
||||||
{
|
{
|
||||||
let path = state
|
let path = state
|
||||||
.borrow_mut::<P>()
|
.borrow_mut::<P>()
|
||||||
.check_read(&path, "Deno.readLink()")
|
.check_read(&path, "Deno.readLink()")?;
|
||||||
.map_err(FsOpsError::Permission)?;
|
|
||||||
|
|
||||||
let fs = state.borrow::<FileSystemRc>();
|
let fs = state.borrow::<FileSystemRc>();
|
||||||
|
|
||||||
|
@ -891,8 +813,7 @@ where
|
||||||
let mut state = state.borrow_mut();
|
let mut state = state.borrow_mut();
|
||||||
let path = state
|
let path = state
|
||||||
.borrow_mut::<P>()
|
.borrow_mut::<P>()
|
||||||
.check_read(&path, "Deno.readLink()")
|
.check_read(&path, "Deno.readLink()")?;
|
||||||
.map_err(FsOpsError::Permission)?;
|
|
||||||
(state.borrow::<FileSystemRc>().clone(), path)
|
(state.borrow::<FileSystemRc>().clone(), path)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -915,8 +836,7 @@ where
|
||||||
{
|
{
|
||||||
let path = state
|
let path = state
|
||||||
.borrow_mut::<P>()
|
.borrow_mut::<P>()
|
||||||
.check_write(path, "Deno.truncateSync()")
|
.check_write(path, "Deno.truncateSync()")?;
|
||||||
.map_err(FsOpsError::Permission)?;
|
|
||||||
|
|
||||||
let fs = state.borrow::<FileSystemRc>();
|
let fs = state.borrow::<FileSystemRc>();
|
||||||
fs.truncate_sync(&path, len)
|
fs.truncate_sync(&path, len)
|
||||||
|
@ -938,8 +858,7 @@ where
|
||||||
let mut state = state.borrow_mut();
|
let mut state = state.borrow_mut();
|
||||||
let path = state
|
let path = state
|
||||||
.borrow_mut::<P>()
|
.borrow_mut::<P>()
|
||||||
.check_write(&path, "Deno.truncate()")
|
.check_write(&path, "Deno.truncate()")?;
|
||||||
.map_err(FsOpsError::Permission)?;
|
|
||||||
(state.borrow::<FileSystemRc>().clone(), path)
|
(state.borrow::<FileSystemRc>().clone(), path)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -962,10 +881,7 @@ pub fn op_fs_utime_sync<P>(
|
||||||
where
|
where
|
||||||
P: FsPermissions + 'static,
|
P: FsPermissions + 'static,
|
||||||
{
|
{
|
||||||
let path = state
|
let path = state.borrow_mut::<P>().check_write(path, "Deno.utime()")?;
|
||||||
.borrow_mut::<P>()
|
|
||||||
.check_write(path, "Deno.utime()")
|
|
||||||
.map_err(FsOpsError::Permission)?;
|
|
||||||
|
|
||||||
let fs = state.borrow::<FileSystemRc>();
|
let fs = state.borrow::<FileSystemRc>();
|
||||||
fs.utime_sync(&path, atime_secs, atime_nanos, mtime_secs, mtime_nanos)
|
fs.utime_sync(&path, atime_secs, atime_nanos, mtime_secs, mtime_nanos)
|
||||||
|
@ -988,10 +904,7 @@ where
|
||||||
{
|
{
|
||||||
let (fs, path) = {
|
let (fs, path) = {
|
||||||
let mut state = state.borrow_mut();
|
let mut state = state.borrow_mut();
|
||||||
let path = state
|
let path = state.borrow_mut::<P>().check_write(&path, "Deno.utime()")?;
|
||||||
.borrow_mut::<P>()
|
|
||||||
.check_write(&path, "Deno.utime()")
|
|
||||||
.map_err(FsOpsError::Permission)?;
|
|
||||||
(state.borrow::<FileSystemRc>().clone(), path)
|
(state.borrow::<FileSystemRc>().clone(), path)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1219,16 +1132,12 @@ where
|
||||||
{
|
{
|
||||||
let fs = state.borrow::<FileSystemRc>().clone();
|
let fs = state.borrow::<FileSystemRc>().clone();
|
||||||
let dir = match dir {
|
let dir = match dir {
|
||||||
Some(dir) => state
|
Some(dir) => state.borrow_mut::<P>().check_write(dir, api_name)?,
|
||||||
.borrow_mut::<P>()
|
|
||||||
.check_write(dir, api_name)
|
|
||||||
.map_err(FsOpsError::Permission)?,
|
|
||||||
None => {
|
None => {
|
||||||
let dir = fs.tmp_dir().context("tmpdir")?;
|
let dir = fs.tmp_dir().context("tmpdir")?;
|
||||||
state
|
state
|
||||||
.borrow_mut::<P>()
|
.borrow_mut::<P>()
|
||||||
.check_write_blind(&dir, "TMP", api_name)
|
.check_write_blind(&dir, "TMP", api_name)?;
|
||||||
.map_err(FsOpsError::Permission)?;
|
|
||||||
dir
|
dir
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1246,16 +1155,12 @@ where
|
||||||
let mut state = state.borrow_mut();
|
let mut state = state.borrow_mut();
|
||||||
let fs = state.borrow::<FileSystemRc>().clone();
|
let fs = state.borrow::<FileSystemRc>().clone();
|
||||||
let dir = match dir {
|
let dir = match dir {
|
||||||
Some(dir) => state
|
Some(dir) => state.borrow_mut::<P>().check_write(dir, api_name)?,
|
||||||
.borrow_mut::<P>()
|
|
||||||
.check_write(dir, api_name)
|
|
||||||
.map_err(FsOpsError::Permission)?,
|
|
||||||
None => {
|
None => {
|
||||||
let dir = fs.tmp_dir().context("tmpdir")?;
|
let dir = fs.tmp_dir().context("tmpdir")?;
|
||||||
state
|
state
|
||||||
.borrow_mut::<P>()
|
.borrow_mut::<P>()
|
||||||
.check_write_blind(&dir, "TMP", api_name)
|
.check_write_blind(&dir, "TMP", api_name)?;
|
||||||
.map_err(FsOpsError::Permission)?;
|
|
||||||
dir
|
dir
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -14,6 +14,7 @@ import {
|
||||||
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,
|
||||||
|
@ -373,6 +374,18 @@ class InnerRequest {
|
||||||
get external() {
|
get external() {
|
||||||
return this.#external;
|
return this.#external;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onCancel(callback) {
|
||||||
|
if (this.#external === null) {
|
||||||
|
callback();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PromisePrototypeThen(
|
||||||
|
op_http_request_on_cancel(this.#external),
|
||||||
|
callback,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class CallbackContext {
|
class CallbackContext {
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "deno_http"
|
name = "deno_http"
|
||||||
version = "0.173.0"
|
version = "0.174.0"
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
|
|
@ -700,6 +700,27 @@ fn set_response(
|
||||||
http.complete();
|
http.complete();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[op2(fast)]
|
||||||
|
pub fn op_http_get_request_cancelled(external: *const c_void) -> bool {
|
||||||
|
let http =
|
||||||
|
// SAFETY: op is called with external.
|
||||||
|
unsafe { clone_external!(external, "op_http_get_request_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,7 +112,9 @@ 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_read_request_body,
|
http_next::op_http_read_request_body,
|
||||||
http_next::op_http_serve_on<HTTP>,
|
http_next::op_http_serve_on<HTTP>,
|
||||||
http_next::op_http_serve<HTTP>,
|
http_next::op_http_serve<HTTP>,
|
||||||
|
|
|
@ -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.85.0"
|
version = "0.86.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.83.0"
|
version = "0.84.0"
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
|
|
@ -15,6 +15,7 @@ use deno_core::futures::Stream;
|
||||||
use deno_core::OpState;
|
use deno_core::OpState;
|
||||||
use deno_fetch::create_http_client;
|
use deno_fetch::create_http_client;
|
||||||
use deno_fetch::CreateHttpClientOptions;
|
use deno_fetch::CreateHttpClientOptions;
|
||||||
|
use deno_permissions::PermissionCheckError;
|
||||||
use deno_tls::rustls::RootCertStore;
|
use deno_tls::rustls::RootCertStore;
|
||||||
use deno_tls::Proxy;
|
use deno_tls::Proxy;
|
||||||
use deno_tls::RootCertStoreProvider;
|
use deno_tls::RootCertStoreProvider;
|
||||||
|
@ -45,17 +46,17 @@ impl HttpOptions {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait RemoteDbHandlerPermissions {
|
pub trait RemoteDbHandlerPermissions {
|
||||||
fn check_env(&mut self, var: &str) -> Result<(), AnyError>;
|
fn check_env(&mut self, var: &str) -> Result<(), PermissionCheckError>;
|
||||||
fn check_net_url(
|
fn check_net_url(
|
||||||
&mut self,
|
&mut self,
|
||||||
url: &Url,
|
url: &Url,
|
||||||
api_name: &str,
|
api_name: &str,
|
||||||
) -> Result<(), AnyError>;
|
) -> Result<(), PermissionCheckError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RemoteDbHandlerPermissions for deno_permissions::PermissionsContainer {
|
impl RemoteDbHandlerPermissions for deno_permissions::PermissionsContainer {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn check_env(&mut self, var: &str) -> Result<(), AnyError> {
|
fn check_env(&mut self, var: &str) -> Result<(), PermissionCheckError> {
|
||||||
deno_permissions::PermissionsContainer::check_env(self, var)
|
deno_permissions::PermissionsContainer::check_env(self, var)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,7 +65,7 @@ impl RemoteDbHandlerPermissions for deno_permissions::PermissionsContainer {
|
||||||
&mut self,
|
&mut self,
|
||||||
url: &Url,
|
url: &Url,
|
||||||
api_name: &str,
|
api_name: &str,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), PermissionCheckError> {
|
||||||
deno_permissions::PermissionsContainer::check_net_url(self, url, api_name)
|
deno_permissions::PermissionsContainer::check_net_url(self, url, api_name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -103,7 +104,9 @@ impl<P: RemoteDbHandlerPermissions + 'static> denokv_remote::RemotePermissions
|
||||||
fn check_net_url(&self, url: &Url) -> Result<(), anyhow::Error> {
|
fn check_net_url(&self, url: &Url) -> Result<(), anyhow::Error> {
|
||||||
let mut state = self.state.borrow_mut();
|
let mut state = self.state.borrow_mut();
|
||||||
let permissions = state.borrow_mut::<P>();
|
let permissions = state.borrow_mut::<P>();
|
||||||
permissions.check_net_url(url, "Deno.openKv")
|
permissions
|
||||||
|
.check_net_url(url, "Deno.openKv")
|
||||||
|
.map_err(Into::into)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,20 +13,20 @@ use std::sync::Arc;
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
use std::sync::OnceLock;
|
use std::sync::OnceLock;
|
||||||
|
|
||||||
|
use crate::DatabaseHandler;
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use deno_core::error::type_error;
|
use deno_core::error::type_error;
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
use deno_core::unsync::spawn_blocking;
|
use deno_core::unsync::spawn_blocking;
|
||||||
use deno_core::OpState;
|
use deno_core::OpState;
|
||||||
use deno_path_util::normalize_path;
|
use deno_path_util::normalize_path;
|
||||||
|
use deno_permissions::PermissionCheckError;
|
||||||
pub use denokv_sqlite::SqliteBackendError;
|
pub use denokv_sqlite::SqliteBackendError;
|
||||||
use denokv_sqlite::SqliteConfig;
|
use denokv_sqlite::SqliteConfig;
|
||||||
use denokv_sqlite::SqliteNotifier;
|
use denokv_sqlite::SqliteNotifier;
|
||||||
use rand::SeedableRng;
|
use rand::SeedableRng;
|
||||||
use rusqlite::OpenFlags;
|
use rusqlite::OpenFlags;
|
||||||
|
|
||||||
use crate::DatabaseHandler;
|
|
||||||
|
|
||||||
static SQLITE_NOTIFIERS_MAP: OnceLock<Mutex<HashMap<PathBuf, SqliteNotifier>>> =
|
static SQLITE_NOTIFIERS_MAP: OnceLock<Mutex<HashMap<PathBuf, SqliteNotifier>>> =
|
||||||
OnceLock::new();
|
OnceLock::new();
|
||||||
|
|
||||||
|
@ -42,13 +42,13 @@ pub trait SqliteDbHandlerPermissions {
|
||||||
&mut self,
|
&mut self,
|
||||||
p: &str,
|
p: &str,
|
||||||
api_name: &str,
|
api_name: &str,
|
||||||
) -> Result<PathBuf, AnyError>;
|
) -> Result<PathBuf, PermissionCheckError>;
|
||||||
#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
|
#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
|
||||||
fn check_write<'a>(
|
fn check_write<'a>(
|
||||||
&mut self,
|
&mut self,
|
||||||
p: &'a Path,
|
p: &'a Path,
|
||||||
api_name: &str,
|
api_name: &str,
|
||||||
) -> Result<Cow<'a, Path>, AnyError>;
|
) -> Result<Cow<'a, Path>, PermissionCheckError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SqliteDbHandlerPermissions for deno_permissions::PermissionsContainer {
|
impl SqliteDbHandlerPermissions for deno_permissions::PermissionsContainer {
|
||||||
|
@ -57,7 +57,7 @@ impl SqliteDbHandlerPermissions for deno_permissions::PermissionsContainer {
|
||||||
&mut self,
|
&mut self,
|
||||||
p: &str,
|
p: &str,
|
||||||
api_name: &str,
|
api_name: &str,
|
||||||
) -> Result<PathBuf, AnyError> {
|
) -> Result<PathBuf, PermissionCheckError> {
|
||||||
deno_permissions::PermissionsContainer::check_read(self, p, api_name)
|
deno_permissions::PermissionsContainer::check_read(self, p, api_name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ impl SqliteDbHandlerPermissions for deno_permissions::PermissionsContainer {
|
||||||
&mut self,
|
&mut self,
|
||||||
p: &'a Path,
|
p: &'a Path,
|
||||||
api_name: &str,
|
api_name: &str,
|
||||||
) -> Result<Cow<'a, Path>, AnyError> {
|
) -> Result<Cow<'a, Path>, PermissionCheckError> {
|
||||||
deno_permissions::PermissionsContainer::check_write_path(self, p, api_name)
|
deno_permissions::PermissionsContainer::check_write_path(self, p, api_name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "deno_napi"
|
name = "deno_napi"
|
||||||
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
|
||||||
|
|
|
@ -43,7 +43,7 @@ pub enum NApiError {
|
||||||
#[error("Unable to find register Node-API module at {}", .0.display())]
|
#[error("Unable to find register Node-API module at {}", .0.display())]
|
||||||
ModuleNotFound(PathBuf),
|
ModuleNotFound(PathBuf),
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Permission(deno_core::error::AnyError),
|
Permission(#[from] PermissionCheckError),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
|
@ -55,6 +55,7 @@ use libloading::os::windows::*;
|
||||||
// Expose common stuff for ease of use.
|
// Expose common stuff for ease of use.
|
||||||
// `use deno_napi::*`
|
// `use deno_napi::*`
|
||||||
pub use deno_core::v8;
|
pub use deno_core::v8;
|
||||||
|
use deno_permissions::PermissionCheckError;
|
||||||
pub use std::ffi::CStr;
|
pub use std::ffi::CStr;
|
||||||
pub use std::os::raw::c_char;
|
pub use std::os::raw::c_char;
|
||||||
pub use std::os::raw::c_void;
|
pub use std::os::raw::c_void;
|
||||||
|
@ -508,20 +509,14 @@ deno_core::extension!(deno_napi,
|
||||||
|
|
||||||
pub trait NapiPermissions {
|
pub trait NapiPermissions {
|
||||||
#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
|
#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
|
||||||
fn check(
|
fn check(&mut self, path: &str) -> Result<PathBuf, PermissionCheckError>;
|
||||||
&mut self,
|
|
||||||
path: &str,
|
|
||||||
) -> Result<PathBuf, deno_core::error::AnyError>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE(bartlomieju): for now, NAPI uses `--allow-ffi` flag, but that might
|
// NOTE(bartlomieju): for now, NAPI uses `--allow-ffi` flag, but that might
|
||||||
// change in the future.
|
// change in the future.
|
||||||
impl NapiPermissions for deno_permissions::PermissionsContainer {
|
impl NapiPermissions for deno_permissions::PermissionsContainer {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn check(
|
fn check(&mut self, path: &str) -> Result<PathBuf, PermissionCheckError> {
|
||||||
&mut self,
|
|
||||||
path: &str,
|
|
||||||
) -> Result<PathBuf, deno_core::error::AnyError> {
|
|
||||||
deno_permissions::PermissionsContainer::check_ffi(self, path)
|
deno_permissions::PermissionsContainer::check_ffi(self, path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -553,7 +548,7 @@ where
|
||||||
let (async_work_sender, cleanup_hooks, external_ops_tracker, path) = {
|
let (async_work_sender, cleanup_hooks, external_ops_tracker, path) = {
|
||||||
let mut op_state = op_state.borrow_mut();
|
let mut op_state = op_state.borrow_mut();
|
||||||
let permissions = op_state.borrow_mut::<NP>();
|
let permissions = op_state.borrow_mut::<NP>();
|
||||||
let path = permissions.check(&path).map_err(NApiError::Permission)?;
|
let path = permissions.check(&path)?;
|
||||||
let napi_state = op_state.borrow::<NapiState>();
|
let napi_state = op_state.borrow::<NapiState>();
|
||||||
(
|
(
|
||||||
op_state.borrow::<V8CrossThreadTaskSpawner>().clone(),
|
op_state.borrow::<V8CrossThreadTaskSpawner>().clone(),
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "napi_sym"
|
name = "napi_sym"
|
||||||
version = "0.105.0"
|
version = "0.106.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.167.0"
|
version = "0.168.0"
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
@ -17,11 +17,11 @@ path = "lib.rs"
|
||||||
deno_core.workspace = true
|
deno_core.workspace = true
|
||||||
deno_permissions.workspace = true
|
deno_permissions.workspace = true
|
||||||
deno_tls.workspace = true
|
deno_tls.workspace = true
|
||||||
|
hickory-proto = "0.24"
|
||||||
|
hickory-resolver = { version = "0.24", features = ["tokio-runtime", "serde-config"] }
|
||||||
pin-project.workspace = true
|
pin-project.workspace = true
|
||||||
rustls-tokio-stream.workspace = true
|
rustls-tokio-stream.workspace = true
|
||||||
serde.workspace = true
|
serde.workspace = true
|
||||||
socket2.workspace = true
|
socket2.workspace = true
|
||||||
thiserror.workspace = true
|
thiserror.workspace = true
|
||||||
tokio.workspace = true
|
tokio.workspace = true
|
||||||
trust-dns-proto = "0.23"
|
|
||||||
trust-dns-resolver = { version = "0.23", features = ["tokio-runtime", "serde-config"] }
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ mod tcp;
|
||||||
|
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
use deno_core::OpState;
|
use deno_core::OpState;
|
||||||
|
use deno_permissions::PermissionCheckError;
|
||||||
use deno_tls::rustls::RootCertStore;
|
use deno_tls::rustls::RootCertStore;
|
||||||
use deno_tls::RootCertStoreProvider;
|
use deno_tls::RootCertStoreProvider;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
@ -25,25 +26,25 @@ pub trait NetPermissions {
|
||||||
&mut self,
|
&mut self,
|
||||||
host: &(T, Option<u16>),
|
host: &(T, Option<u16>),
|
||||||
api_name: &str,
|
api_name: &str,
|
||||||
) -> Result<(), AnyError>;
|
) -> Result<(), PermissionCheckError>;
|
||||||
#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
|
#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
|
||||||
fn check_read(
|
fn check_read(
|
||||||
&mut self,
|
&mut self,
|
||||||
p: &str,
|
p: &str,
|
||||||
api_name: &str,
|
api_name: &str,
|
||||||
) -> Result<PathBuf, AnyError>;
|
) -> Result<PathBuf, PermissionCheckError>;
|
||||||
#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
|
#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
|
||||||
fn check_write(
|
fn check_write(
|
||||||
&mut self,
|
&mut self,
|
||||||
p: &str,
|
p: &str,
|
||||||
api_name: &str,
|
api_name: &str,
|
||||||
) -> Result<PathBuf, AnyError>;
|
) -> Result<PathBuf, PermissionCheckError>;
|
||||||
#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
|
#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
|
||||||
fn check_write_path<'a>(
|
fn check_write_path<'a>(
|
||||||
&mut self,
|
&mut self,
|
||||||
p: &'a Path,
|
p: &'a Path,
|
||||||
api_name: &str,
|
api_name: &str,
|
||||||
) -> Result<Cow<'a, Path>, AnyError>;
|
) -> Result<Cow<'a, Path>, PermissionCheckError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NetPermissions for deno_permissions::PermissionsContainer {
|
impl NetPermissions for deno_permissions::PermissionsContainer {
|
||||||
|
@ -52,7 +53,7 @@ impl NetPermissions for deno_permissions::PermissionsContainer {
|
||||||
&mut self,
|
&mut self,
|
||||||
host: &(T, Option<u16>),
|
host: &(T, Option<u16>),
|
||||||
api_name: &str,
|
api_name: &str,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), PermissionCheckError> {
|
||||||
deno_permissions::PermissionsContainer::check_net(self, host, api_name)
|
deno_permissions::PermissionsContainer::check_net(self, host, api_name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,7 +62,7 @@ impl NetPermissions for deno_permissions::PermissionsContainer {
|
||||||
&mut self,
|
&mut self,
|
||||||
path: &str,
|
path: &str,
|
||||||
api_name: &str,
|
api_name: &str,
|
||||||
) -> Result<PathBuf, AnyError> {
|
) -> Result<PathBuf, PermissionCheckError> {
|
||||||
deno_permissions::PermissionsContainer::check_read(self, path, api_name)
|
deno_permissions::PermissionsContainer::check_read(self, path, api_name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,7 +71,7 @@ impl NetPermissions for deno_permissions::PermissionsContainer {
|
||||||
&mut self,
|
&mut self,
|
||||||
path: &str,
|
path: &str,
|
||||||
api_name: &str,
|
api_name: &str,
|
||||||
) -> Result<PathBuf, AnyError> {
|
) -> Result<PathBuf, PermissionCheckError> {
|
||||||
deno_permissions::PermissionsContainer::check_write(self, path, api_name)
|
deno_permissions::PermissionsContainer::check_write(self, path, api_name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,7 +80,7 @@ impl NetPermissions for deno_permissions::PermissionsContainer {
|
||||||
&mut self,
|
&mut self,
|
||||||
path: &'a Path,
|
path: &'a Path,
|
||||||
api_name: &str,
|
api_name: &str,
|
||||||
) -> Result<Cow<'a, Path>, AnyError> {
|
) -> Result<Cow<'a, Path>, PermissionCheckError> {
|
||||||
deno_permissions::PermissionsContainer::check_write_path(
|
deno_permissions::PermissionsContainer::check_write_path(
|
||||||
self, path, api_name,
|
self, path, api_name,
|
||||||
)
|
)
|
||||||
|
|
|
@ -18,6 +18,16 @@ use deno_core::OpState;
|
||||||
use deno_core::RcRef;
|
use deno_core::RcRef;
|
||||||
use deno_core::Resource;
|
use deno_core::Resource;
|
||||||
use deno_core::ResourceId;
|
use deno_core::ResourceId;
|
||||||
|
use hickory_proto::rr::rdata::caa::Value;
|
||||||
|
use hickory_proto::rr::record_data::RData;
|
||||||
|
use hickory_proto::rr::record_type::RecordType;
|
||||||
|
use hickory_resolver::config::NameServerConfigGroup;
|
||||||
|
use hickory_resolver::config::ResolverConfig;
|
||||||
|
use hickory_resolver::config::ResolverOpts;
|
||||||
|
use hickory_resolver::error::ResolveError;
|
||||||
|
use hickory_resolver::error::ResolveErrorKind;
|
||||||
|
use hickory_resolver::system_conf;
|
||||||
|
use hickory_resolver::AsyncResolver;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use socket2::Domain;
|
use socket2::Domain;
|
||||||
|
@ -33,16 +43,6 @@ use std::rc::Rc;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use tokio::net::TcpStream;
|
use tokio::net::TcpStream;
|
||||||
use tokio::net::UdpSocket;
|
use tokio::net::UdpSocket;
|
||||||
use trust_dns_proto::rr::rdata::caa::Value;
|
|
||||||
use trust_dns_proto::rr::record_data::RData;
|
|
||||||
use trust_dns_proto::rr::record_type::RecordType;
|
|
||||||
use trust_dns_resolver::config::NameServerConfigGroup;
|
|
||||||
use trust_dns_resolver::config::ResolverConfig;
|
|
||||||
use trust_dns_resolver::config::ResolverOpts;
|
|
||||||
use trust_dns_resolver::error::ResolveError;
|
|
||||||
use trust_dns_resolver::error::ResolveErrorKind;
|
|
||||||
use trust_dns_resolver::system_conf;
|
|
||||||
use trust_dns_resolver::AsyncResolver;
|
|
||||||
|
|
||||||
#[derive(Serialize, Clone, Debug)]
|
#[derive(Serialize, Clone, Debug)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
|
@ -81,8 +81,8 @@ pub enum NetError {
|
||||||
Io(#[from] std::io::Error),
|
Io(#[from] std::io::Error),
|
||||||
#[error("Another accept task is ongoing")]
|
#[error("Another accept task is ongoing")]
|
||||||
AcceptTaskOngoing,
|
AcceptTaskOngoing,
|
||||||
#[error("{0}")]
|
#[error(transparent)]
|
||||||
Permission(deno_core::error::AnyError),
|
Permission(#[from] deno_permissions::PermissionCheckError),
|
||||||
#[error("{0}")]
|
#[error("{0}")]
|
||||||
Resource(deno_core::error::AnyError),
|
Resource(deno_core::error::AnyError),
|
||||||
#[error("No resolved address found")]
|
#[error("No resolved address found")]
|
||||||
|
@ -195,12 +195,10 @@ where
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
let mut s = state.borrow_mut();
|
let mut s = state.borrow_mut();
|
||||||
s.borrow_mut::<NP>()
|
s.borrow_mut::<NP>().check_net(
|
||||||
.check_net(
|
|
||||||
&(&addr.hostname, Some(addr.port)),
|
&(&addr.hostname, Some(addr.port)),
|
||||||
"Deno.DatagramConn.send()",
|
"Deno.DatagramConn.send()",
|
||||||
)
|
)?;
|
||||||
.map_err(NetError::Permission)?;
|
|
||||||
}
|
}
|
||||||
let addr = resolve_addr(&addr.hostname, addr.port)
|
let addr = resolve_addr(&addr.hostname, addr.port)
|
||||||
.await?
|
.await?
|
||||||
|
@ -369,8 +367,7 @@ where
|
||||||
let mut state_ = state.borrow_mut();
|
let mut state_ = state.borrow_mut();
|
||||||
state_
|
state_
|
||||||
.borrow_mut::<NP>()
|
.borrow_mut::<NP>()
|
||||||
.check_net(&(&addr.hostname, Some(addr.port)), "Deno.connect()")
|
.check_net(&(&addr.hostname, Some(addr.port)), "Deno.connect()")?;
|
||||||
.map_err(NetError::Permission)?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let addr = resolve_addr(&addr.hostname, addr.port)
|
let addr = resolve_addr(&addr.hostname, addr.port)
|
||||||
|
@ -420,8 +417,7 @@ where
|
||||||
}
|
}
|
||||||
state
|
state
|
||||||
.borrow_mut::<NP>()
|
.borrow_mut::<NP>()
|
||||||
.check_net(&(&addr.hostname, Some(addr.port)), "Deno.listen()")
|
.check_net(&(&addr.hostname, Some(addr.port)), "Deno.listen()")?;
|
||||||
.map_err(NetError::Permission)?;
|
|
||||||
let addr = resolve_addr_sync(&addr.hostname, addr.port)?
|
let addr = resolve_addr_sync(&addr.hostname, addr.port)?
|
||||||
.next()
|
.next()
|
||||||
.ok_or_else(|| NetError::NoResolvedAddress)?;
|
.ok_or_else(|| NetError::NoResolvedAddress)?;
|
||||||
|
@ -449,8 +445,7 @@ where
|
||||||
{
|
{
|
||||||
state
|
state
|
||||||
.borrow_mut::<NP>()
|
.borrow_mut::<NP>()
|
||||||
.check_net(&(&addr.hostname, Some(addr.port)), "Deno.listenDatagram()")
|
.check_net(&(&addr.hostname, Some(addr.port)), "Deno.listenDatagram()")?;
|
||||||
.map_err(NetError::Permission)?;
|
|
||||||
let addr = resolve_addr_sync(&addr.hostname, addr.port)?
|
let addr = resolve_addr_sync(&addr.hostname, addr.port)?
|
||||||
.next()
|
.next()
|
||||||
.ok_or_else(|| NetError::NoResolvedAddress)?;
|
.ok_or_else(|| NetError::NoResolvedAddress)?;
|
||||||
|
@ -647,9 +642,7 @@ where
|
||||||
let socker_addr = &ns.socket_addr;
|
let socker_addr = &ns.socket_addr;
|
||||||
let ip = socker_addr.ip().to_string();
|
let ip = socker_addr.ip().to_string();
|
||||||
let port = socker_addr.port();
|
let port = socker_addr.port();
|
||||||
perm
|
perm.check_net(&(ip, Some(port)), "Deno.resolveDns()")?;
|
||||||
.check_net(&(ip, Some(port)), "Deno.resolveDns()")
|
|
||||||
.map_err(NetError::Permission)?;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -834,6 +827,22 @@ mod tests {
|
||||||
use deno_core::futures::FutureExt;
|
use deno_core::futures::FutureExt;
|
||||||
use deno_core::JsRuntime;
|
use deno_core::JsRuntime;
|
||||||
use deno_core::RuntimeOptions;
|
use deno_core::RuntimeOptions;
|
||||||
|
use deno_permissions::PermissionCheckError;
|
||||||
|
use hickory_proto::rr::rdata::a::A;
|
||||||
|
use hickory_proto::rr::rdata::aaaa::AAAA;
|
||||||
|
use hickory_proto::rr::rdata::caa::KeyValue;
|
||||||
|
use hickory_proto::rr::rdata::caa::CAA;
|
||||||
|
use hickory_proto::rr::rdata::mx::MX;
|
||||||
|
use hickory_proto::rr::rdata::name::ANAME;
|
||||||
|
use hickory_proto::rr::rdata::name::CNAME;
|
||||||
|
use hickory_proto::rr::rdata::name::NS;
|
||||||
|
use hickory_proto::rr::rdata::name::PTR;
|
||||||
|
use hickory_proto::rr::rdata::naptr::NAPTR;
|
||||||
|
use hickory_proto::rr::rdata::srv::SRV;
|
||||||
|
use hickory_proto::rr::rdata::txt::TXT;
|
||||||
|
use hickory_proto::rr::rdata::SOA;
|
||||||
|
use hickory_proto::rr::record_data::RData;
|
||||||
|
use hickory_proto::rr::Name;
|
||||||
use socket2::SockRef;
|
use socket2::SockRef;
|
||||||
use std::net::Ipv4Addr;
|
use std::net::Ipv4Addr;
|
||||||
use std::net::Ipv6Addr;
|
use std::net::Ipv6Addr;
|
||||||
|
@ -842,21 +851,6 @@ mod tests {
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
use trust_dns_proto::rr::rdata::a::A;
|
|
||||||
use trust_dns_proto::rr::rdata::aaaa::AAAA;
|
|
||||||
use trust_dns_proto::rr::rdata::caa::KeyValue;
|
|
||||||
use trust_dns_proto::rr::rdata::caa::CAA;
|
|
||||||
use trust_dns_proto::rr::rdata::mx::MX;
|
|
||||||
use trust_dns_proto::rr::rdata::name::ANAME;
|
|
||||||
use trust_dns_proto::rr::rdata::name::CNAME;
|
|
||||||
use trust_dns_proto::rr::rdata::name::NS;
|
|
||||||
use trust_dns_proto::rr::rdata::name::PTR;
|
|
||||||
use trust_dns_proto::rr::rdata::naptr::NAPTR;
|
|
||||||
use trust_dns_proto::rr::rdata::srv::SRV;
|
|
||||||
use trust_dns_proto::rr::rdata::txt::TXT;
|
|
||||||
use trust_dns_proto::rr::rdata::SOA;
|
|
||||||
use trust_dns_proto::rr::record_data::RData;
|
|
||||||
use trust_dns_proto::rr::Name;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn rdata_to_return_record_a() {
|
fn rdata_to_return_record_a() {
|
||||||
|
@ -1041,7 +1035,7 @@ mod tests {
|
||||||
&mut self,
|
&mut self,
|
||||||
_host: &(T, Option<u16>),
|
_host: &(T, Option<u16>),
|
||||||
_api_name: &str,
|
_api_name: &str,
|
||||||
) -> Result<(), deno_core::error::AnyError> {
|
) -> Result<(), PermissionCheckError> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1049,7 +1043,7 @@ mod tests {
|
||||||
&mut self,
|
&mut self,
|
||||||
p: &str,
|
p: &str,
|
||||||
_api_name: &str,
|
_api_name: &str,
|
||||||
) -> Result<PathBuf, deno_core::error::AnyError> {
|
) -> Result<PathBuf, PermissionCheckError> {
|
||||||
Ok(PathBuf::from(p))
|
Ok(PathBuf::from(p))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1057,7 +1051,7 @@ mod tests {
|
||||||
&mut self,
|
&mut self,
|
||||||
p: &str,
|
p: &str,
|
||||||
_api_name: &str,
|
_api_name: &str,
|
||||||
) -> Result<PathBuf, deno_core::error::AnyError> {
|
) -> Result<PathBuf, PermissionCheckError> {
|
||||||
Ok(PathBuf::from(p))
|
Ok(PathBuf::from(p))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1065,7 +1059,7 @@ mod tests {
|
||||||
&mut self,
|
&mut self,
|
||||||
p: &'a Path,
|
p: &'a Path,
|
||||||
_api_name: &str,
|
_api_name: &str,
|
||||||
) -> Result<Cow<'a, Path>, deno_core::error::AnyError> {
|
) -> Result<Cow<'a, Path>, PermissionCheckError> {
|
||||||
Ok(Cow::Borrowed(p))
|
Ok(Cow::Borrowed(p))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "deno_node"
|
name = "deno_node"
|
||||||
version = "0.112.0"
|
version = "0.113.0"
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
|
|
@ -24,6 +24,7 @@ pub mod ops;
|
||||||
mod polyfill;
|
mod polyfill;
|
||||||
|
|
||||||
pub use deno_package_json::PackageJson;
|
pub use deno_package_json::PackageJson;
|
||||||
|
use deno_permissions::PermissionCheckError;
|
||||||
pub use node_resolver::PathClean;
|
pub use node_resolver::PathClean;
|
||||||
pub use ops::ipc::ChildPipeFd;
|
pub use ops::ipc::ChildPipeFd;
|
||||||
pub use ops::ipc::IpcJsonStreamResource;
|
pub use ops::ipc::IpcJsonStreamResource;
|
||||||
|
@ -45,10 +46,18 @@ pub trait NodePermissions {
|
||||||
&mut self,
|
&mut self,
|
||||||
url: &Url,
|
url: &Url,
|
||||||
api_name: &str,
|
api_name: &str,
|
||||||
) -> Result<(), AnyError>;
|
) -> Result<(), PermissionCheckError>;
|
||||||
|
fn check_net(
|
||||||
|
&mut self,
|
||||||
|
host: (&str, Option<u16>),
|
||||||
|
api_name: &str,
|
||||||
|
) -> Result<(), PermissionCheckError>;
|
||||||
#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
|
#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn check_read(&mut self, path: &str) -> Result<PathBuf, AnyError> {
|
fn check_read(
|
||||||
|
&mut self,
|
||||||
|
path: &str,
|
||||||
|
) -> Result<PathBuf, PermissionCheckError> {
|
||||||
self.check_read_with_api_name(path, None)
|
self.check_read_with_api_name(path, None)
|
||||||
}
|
}
|
||||||
#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
|
#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
|
||||||
|
@ -56,20 +65,24 @@ pub trait NodePermissions {
|
||||||
&mut self,
|
&mut self,
|
||||||
path: &str,
|
path: &str,
|
||||||
api_name: Option<&str>,
|
api_name: Option<&str>,
|
||||||
) -> Result<PathBuf, AnyError>;
|
) -> Result<PathBuf, PermissionCheckError>;
|
||||||
#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
|
#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
|
||||||
fn check_read_path<'a>(
|
fn check_read_path<'a>(
|
||||||
&mut self,
|
&mut self,
|
||||||
path: &'a Path,
|
path: &'a Path,
|
||||||
) -> Result<Cow<'a, Path>, AnyError>;
|
) -> Result<Cow<'a, Path>, PermissionCheckError>;
|
||||||
fn query_read_all(&mut self) -> bool;
|
fn query_read_all(&mut self) -> bool;
|
||||||
fn check_sys(&mut self, kind: &str, api_name: &str) -> Result<(), AnyError>;
|
fn check_sys(
|
||||||
|
&mut self,
|
||||||
|
kind: &str,
|
||||||
|
api_name: &str,
|
||||||
|
) -> Result<(), PermissionCheckError>;
|
||||||
#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
|
#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
|
||||||
fn check_write_with_api_name(
|
fn check_write_with_api_name(
|
||||||
&mut self,
|
&mut self,
|
||||||
path: &str,
|
path: &str,
|
||||||
api_name: Option<&str>,
|
api_name: Option<&str>,
|
||||||
) -> Result<PathBuf, AnyError>;
|
) -> Result<PathBuf, PermissionCheckError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NodePermissions for deno_permissions::PermissionsContainer {
|
impl NodePermissions for deno_permissions::PermissionsContainer {
|
||||||
|
@ -78,16 +91,24 @@ impl NodePermissions for deno_permissions::PermissionsContainer {
|
||||||
&mut self,
|
&mut self,
|
||||||
url: &Url,
|
url: &Url,
|
||||||
api_name: &str,
|
api_name: &str,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), PermissionCheckError> {
|
||||||
deno_permissions::PermissionsContainer::check_net_url(self, url, api_name)
|
deno_permissions::PermissionsContainer::check_net_url(self, url, api_name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn check_net(
|
||||||
|
&mut self,
|
||||||
|
host: (&str, Option<u16>),
|
||||||
|
api_name: &str,
|
||||||
|
) -> Result<(), PermissionCheckError> {
|
||||||
|
deno_permissions::PermissionsContainer::check_net(self, &host, api_name)
|
||||||
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn check_read_with_api_name(
|
fn check_read_with_api_name(
|
||||||
&mut self,
|
&mut self,
|
||||||
path: &str,
|
path: &str,
|
||||||
api_name: Option<&str>,
|
api_name: Option<&str>,
|
||||||
) -> Result<PathBuf, AnyError> {
|
) -> Result<PathBuf, PermissionCheckError> {
|
||||||
deno_permissions::PermissionsContainer::check_read_with_api_name(
|
deno_permissions::PermissionsContainer::check_read_with_api_name(
|
||||||
self, path, api_name,
|
self, path, api_name,
|
||||||
)
|
)
|
||||||
|
@ -96,7 +117,7 @@ impl NodePermissions for deno_permissions::PermissionsContainer {
|
||||||
fn check_read_path<'a>(
|
fn check_read_path<'a>(
|
||||||
&mut self,
|
&mut self,
|
||||||
path: &'a Path,
|
path: &'a Path,
|
||||||
) -> Result<Cow<'a, Path>, AnyError> {
|
) -> Result<Cow<'a, Path>, PermissionCheckError> {
|
||||||
deno_permissions::PermissionsContainer::check_read_path(self, path, None)
|
deno_permissions::PermissionsContainer::check_read_path(self, path, None)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,13 +130,17 @@ impl NodePermissions for deno_permissions::PermissionsContainer {
|
||||||
&mut self,
|
&mut self,
|
||||||
path: &str,
|
path: &str,
|
||||||
api_name: Option<&str>,
|
api_name: Option<&str>,
|
||||||
) -> Result<PathBuf, AnyError> {
|
) -> Result<PathBuf, PermissionCheckError> {
|
||||||
deno_permissions::PermissionsContainer::check_write_with_api_name(
|
deno_permissions::PermissionsContainer::check_write_with_api_name(
|
||||||
self, path, api_name,
|
self, path, api_name,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_sys(&mut self, kind: &str, api_name: &str) -> Result<(), AnyError> {
|
fn check_sys(
|
||||||
|
&mut self,
|
||||||
|
kind: &str,
|
||||||
|
api_name: &str,
|
||||||
|
) -> Result<(), PermissionCheckError> {
|
||||||
deno_permissions::PermissionsContainer::check_sys(self, kind, api_name)
|
deno_permissions::PermissionsContainer::check_sys(self, kind, api_name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -386,6 +411,15 @@ deno_core::extension!(deno_node,
|
||||||
ops::process::op_node_process_kill,
|
ops::process::op_node_process_kill,
|
||||||
ops::process::op_process_abort,
|
ops::process::op_process_abort,
|
||||||
ops::tls::op_get_root_certificates,
|
ops::tls::op_get_root_certificates,
|
||||||
|
ops::inspector::op_inspector_open<P>,
|
||||||
|
ops::inspector::op_inspector_close,
|
||||||
|
ops::inspector::op_inspector_url,
|
||||||
|
ops::inspector::op_inspector_wait,
|
||||||
|
ops::inspector::op_inspector_connect<P>,
|
||||||
|
ops::inspector::op_inspector_dispatch,
|
||||||
|
ops::inspector::op_inspector_disconnect,
|
||||||
|
ops::inspector::op_inspector_emit_protocol_event,
|
||||||
|
ops::inspector::op_inspector_enabled,
|
||||||
],
|
],
|
||||||
esm_entry_point = "ext:deno_node/02_init.js",
|
esm_entry_point = "ext:deno_node/02_init.js",
|
||||||
esm = [
|
esm = [
|
||||||
|
@ -594,8 +628,8 @@ deno_core::extension!(deno_node,
|
||||||
"node:http" = "http.ts",
|
"node:http" = "http.ts",
|
||||||
"node:http2" = "http2.ts",
|
"node:http2" = "http2.ts",
|
||||||
"node:https" = "https.ts",
|
"node:https" = "https.ts",
|
||||||
"node:inspector" = "inspector.ts",
|
"node:inspector" = "inspector.js",
|
||||||
"node:inspector/promises" = "inspector.ts",
|
"node:inspector/promises" = "inspector/promises.js",
|
||||||
"node:module" = "01_require.js",
|
"node:module" = "01_require.js",
|
||||||
"node:net" = "net.ts",
|
"node:net" = "net.ts",
|
||||||
"node:os" = "os.ts",
|
"node:os" = "os.ts",
|
||||||
|
|
|
@ -4,9 +4,6 @@ use aes::cipher::block_padding::Pkcs7;
|
||||||
use aes::cipher::BlockDecryptMut;
|
use aes::cipher::BlockDecryptMut;
|
||||||
use aes::cipher::BlockEncryptMut;
|
use aes::cipher::BlockEncryptMut;
|
||||||
use aes::cipher::KeyIvInit;
|
use aes::cipher::KeyIvInit;
|
||||||
use deno_core::error::range_error;
|
|
||||||
use deno_core::error::type_error;
|
|
||||||
use deno_core::error::AnyError;
|
|
||||||
use deno_core::Resource;
|
use deno_core::Resource;
|
||||||
use digest::generic_array::GenericArray;
|
use digest::generic_array::GenericArray;
|
||||||
use digest::KeyInit;
|
use digest::KeyInit;
|
||||||
|
@ -50,8 +47,22 @@ pub struct DecipherContext {
|
||||||
decipher: Rc<RefCell<Decipher>>,
|
decipher: Rc<RefCell<Decipher>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, thiserror::Error)]
|
||||||
|
pub enum CipherContextError {
|
||||||
|
#[error("Cipher context is already in use")]
|
||||||
|
ContextInUse,
|
||||||
|
#[error("{0}")]
|
||||||
|
Resource(deno_core::error::AnyError),
|
||||||
|
#[error(transparent)]
|
||||||
|
Cipher(#[from] CipherError),
|
||||||
|
}
|
||||||
|
|
||||||
impl CipherContext {
|
impl CipherContext {
|
||||||
pub fn new(algorithm: &str, key: &[u8], iv: &[u8]) -> Result<Self, AnyError> {
|
pub fn new(
|
||||||
|
algorithm: &str,
|
||||||
|
key: &[u8],
|
||||||
|
iv: &[u8],
|
||||||
|
) -> Result<Self, CipherContextError> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
cipher: Rc::new(RefCell::new(Cipher::new(algorithm, key, iv)?)),
|
cipher: Rc::new(RefCell::new(Cipher::new(algorithm, key, iv)?)),
|
||||||
})
|
})
|
||||||
|
@ -74,16 +85,31 @@ impl CipherContext {
|
||||||
auto_pad: bool,
|
auto_pad: bool,
|
||||||
input: &[u8],
|
input: &[u8],
|
||||||
output: &mut [u8],
|
output: &mut [u8],
|
||||||
) -> Result<Tag, AnyError> {
|
) -> Result<Tag, CipherContextError> {
|
||||||
Rc::try_unwrap(self.cipher)
|
Rc::try_unwrap(self.cipher)
|
||||||
.map_err(|_| type_error("Cipher context is already in use"))?
|
.map_err(|_| CipherContextError::ContextInUse)?
|
||||||
.into_inner()
|
.into_inner()
|
||||||
.r#final(auto_pad, input, output)
|
.r#final(auto_pad, input, output)
|
||||||
|
.map_err(Into::into)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, thiserror::Error)]
|
||||||
|
pub enum DecipherContextError {
|
||||||
|
#[error("Decipher context is already in use")]
|
||||||
|
ContextInUse,
|
||||||
|
#[error("{0}")]
|
||||||
|
Resource(deno_core::error::AnyError),
|
||||||
|
#[error(transparent)]
|
||||||
|
Decipher(#[from] DecipherError),
|
||||||
|
}
|
||||||
|
|
||||||
impl DecipherContext {
|
impl DecipherContext {
|
||||||
pub fn new(algorithm: &str, key: &[u8], iv: &[u8]) -> Result<Self, AnyError> {
|
pub fn new(
|
||||||
|
algorithm: &str,
|
||||||
|
key: &[u8],
|
||||||
|
iv: &[u8],
|
||||||
|
) -> Result<Self, DecipherContextError> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
decipher: Rc::new(RefCell::new(Decipher::new(algorithm, key, iv)?)),
|
decipher: Rc::new(RefCell::new(Decipher::new(algorithm, key, iv)?)),
|
||||||
})
|
})
|
||||||
|
@ -103,11 +129,12 @@ impl DecipherContext {
|
||||||
input: &[u8],
|
input: &[u8],
|
||||||
output: &mut [u8],
|
output: &mut [u8],
|
||||||
auth_tag: &[u8],
|
auth_tag: &[u8],
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), DecipherContextError> {
|
||||||
Rc::try_unwrap(self.decipher)
|
Rc::try_unwrap(self.decipher)
|
||||||
.map_err(|_| type_error("Decipher context is already in use"))?
|
.map_err(|_| DecipherContextError::ContextInUse)?
|
||||||
.into_inner()
|
.into_inner()
|
||||||
.r#final(auto_pad, input, output, auth_tag)
|
.r#final(auto_pad, input, output, auth_tag)
|
||||||
|
.map_err(Into::into)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,12 +150,26 @@ impl Resource for DecipherContext {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, thiserror::Error)]
|
||||||
|
pub enum CipherError {
|
||||||
|
#[error("IV length must be 12 bytes")]
|
||||||
|
InvalidIvLength,
|
||||||
|
#[error("Invalid key length")]
|
||||||
|
InvalidKeyLength,
|
||||||
|
#[error("Invalid initialization vector")]
|
||||||
|
InvalidInitializationVector,
|
||||||
|
#[error("Cannot pad the input data")]
|
||||||
|
CannotPadInputData,
|
||||||
|
#[error("Unknown cipher {0}")]
|
||||||
|
UnknownCipher(String),
|
||||||
|
}
|
||||||
|
|
||||||
impl Cipher {
|
impl Cipher {
|
||||||
fn new(
|
fn new(
|
||||||
algorithm_name: &str,
|
algorithm_name: &str,
|
||||||
key: &[u8],
|
key: &[u8],
|
||||||
iv: &[u8],
|
iv: &[u8],
|
||||||
) -> Result<Self, AnyError> {
|
) -> Result<Self, CipherError> {
|
||||||
use Cipher::*;
|
use Cipher::*;
|
||||||
Ok(match algorithm_name {
|
Ok(match algorithm_name {
|
||||||
"aes-128-cbc" => {
|
"aes-128-cbc" => {
|
||||||
|
@ -139,7 +180,7 @@ impl Cipher {
|
||||||
"aes-256-ecb" => Aes256Ecb(Box::new(ecb::Encryptor::new(key.into()))),
|
"aes-256-ecb" => Aes256Ecb(Box::new(ecb::Encryptor::new(key.into()))),
|
||||||
"aes-128-gcm" => {
|
"aes-128-gcm" => {
|
||||||
if iv.len() != 12 {
|
if iv.len() != 12 {
|
||||||
return Err(type_error("IV length must be 12 bytes"));
|
return Err(CipherError::InvalidIvLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
let cipher =
|
let cipher =
|
||||||
|
@ -149,7 +190,7 @@ impl Cipher {
|
||||||
}
|
}
|
||||||
"aes-256-gcm" => {
|
"aes-256-gcm" => {
|
||||||
if iv.len() != 12 {
|
if iv.len() != 12 {
|
||||||
return Err(type_error("IV length must be 12 bytes"));
|
return Err(CipherError::InvalidIvLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
let cipher =
|
let cipher =
|
||||||
|
@ -159,15 +200,15 @@ impl Cipher {
|
||||||
}
|
}
|
||||||
"aes256" | "aes-256-cbc" => {
|
"aes256" | "aes-256-cbc" => {
|
||||||
if key.len() != 32 {
|
if key.len() != 32 {
|
||||||
return Err(range_error("Invalid key length"));
|
return Err(CipherError::InvalidKeyLength);
|
||||||
}
|
}
|
||||||
if iv.len() != 16 {
|
if iv.len() != 16 {
|
||||||
return Err(type_error("Invalid initialization vector"));
|
return Err(CipherError::InvalidInitializationVector);
|
||||||
}
|
}
|
||||||
|
|
||||||
Aes256Cbc(Box::new(cbc::Encryptor::new(key.into(), iv.into())))
|
Aes256Cbc(Box::new(cbc::Encryptor::new(key.into(), iv.into())))
|
||||||
}
|
}
|
||||||
_ => return Err(type_error(format!("Unknown cipher {algorithm_name}"))),
|
_ => return Err(CipherError::UnknownCipher(algorithm_name.to_string())),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -235,14 +276,14 @@ impl Cipher {
|
||||||
auto_pad: bool,
|
auto_pad: bool,
|
||||||
input: &[u8],
|
input: &[u8],
|
||||||
output: &mut [u8],
|
output: &mut [u8],
|
||||||
) -> Result<Tag, AnyError> {
|
) -> Result<Tag, CipherError> {
|
||||||
assert!(input.len() < 16);
|
assert!(input.len() < 16);
|
||||||
use Cipher::*;
|
use Cipher::*;
|
||||||
match (self, auto_pad) {
|
match (self, auto_pad) {
|
||||||
(Aes128Cbc(encryptor), true) => {
|
(Aes128Cbc(encryptor), true) => {
|
||||||
let _ = (*encryptor)
|
let _ = (*encryptor)
|
||||||
.encrypt_padded_b2b_mut::<Pkcs7>(input, output)
|
.encrypt_padded_b2b_mut::<Pkcs7>(input, output)
|
||||||
.map_err(|_| type_error("Cannot pad the input data"))?;
|
.map_err(|_| CipherError::CannotPadInputData)?;
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
(Aes128Cbc(mut encryptor), false) => {
|
(Aes128Cbc(mut encryptor), false) => {
|
||||||
|
@ -255,7 +296,7 @@ impl Cipher {
|
||||||
(Aes128Ecb(encryptor), true) => {
|
(Aes128Ecb(encryptor), true) => {
|
||||||
let _ = (*encryptor)
|
let _ = (*encryptor)
|
||||||
.encrypt_padded_b2b_mut::<Pkcs7>(input, output)
|
.encrypt_padded_b2b_mut::<Pkcs7>(input, output)
|
||||||
.map_err(|_| type_error("Cannot pad the input data"))?;
|
.map_err(|_| CipherError::CannotPadInputData)?;
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
(Aes128Ecb(mut encryptor), false) => {
|
(Aes128Ecb(mut encryptor), false) => {
|
||||||
|
@ -268,7 +309,7 @@ impl Cipher {
|
||||||
(Aes192Ecb(encryptor), true) => {
|
(Aes192Ecb(encryptor), true) => {
|
||||||
let _ = (*encryptor)
|
let _ = (*encryptor)
|
||||||
.encrypt_padded_b2b_mut::<Pkcs7>(input, output)
|
.encrypt_padded_b2b_mut::<Pkcs7>(input, output)
|
||||||
.map_err(|_| type_error("Cannot pad the input data"))?;
|
.map_err(|_| CipherError::CannotPadInputData)?;
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
(Aes192Ecb(mut encryptor), false) => {
|
(Aes192Ecb(mut encryptor), false) => {
|
||||||
|
@ -281,7 +322,7 @@ impl Cipher {
|
||||||
(Aes256Ecb(encryptor), true) => {
|
(Aes256Ecb(encryptor), true) => {
|
||||||
let _ = (*encryptor)
|
let _ = (*encryptor)
|
||||||
.encrypt_padded_b2b_mut::<Pkcs7>(input, output)
|
.encrypt_padded_b2b_mut::<Pkcs7>(input, output)
|
||||||
.map_err(|_| type_error("Cannot pad the input data"))?;
|
.map_err(|_| CipherError::CannotPadInputData)?;
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
(Aes256Ecb(mut encryptor), false) => {
|
(Aes256Ecb(mut encryptor), false) => {
|
||||||
|
@ -296,7 +337,7 @@ impl Cipher {
|
||||||
(Aes256Cbc(encryptor), true) => {
|
(Aes256Cbc(encryptor), true) => {
|
||||||
let _ = (*encryptor)
|
let _ = (*encryptor)
|
||||||
.encrypt_padded_b2b_mut::<Pkcs7>(input, output)
|
.encrypt_padded_b2b_mut::<Pkcs7>(input, output)
|
||||||
.map_err(|_| type_error("Cannot pad the input data"))?;
|
.map_err(|_| CipherError::CannotPadInputData)?;
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
(Aes256Cbc(mut encryptor), false) => {
|
(Aes256Cbc(mut encryptor), false) => {
|
||||||
|
@ -319,12 +360,32 @@ impl Cipher {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, thiserror::Error)]
|
||||||
|
pub enum DecipherError {
|
||||||
|
#[error("IV length must be 12 bytes")]
|
||||||
|
InvalidIvLength,
|
||||||
|
#[error("Invalid key length")]
|
||||||
|
InvalidKeyLength,
|
||||||
|
#[error("Invalid initialization vector")]
|
||||||
|
InvalidInitializationVector,
|
||||||
|
#[error("Cannot unpad the input data")]
|
||||||
|
CannotUnpadInputData,
|
||||||
|
#[error("Failed to authenticate data")]
|
||||||
|
DataAuthenticationFailed,
|
||||||
|
#[error("setAutoPadding(false) not supported for Aes128Gcm yet")]
|
||||||
|
SetAutoPaddingFalseAes128GcmUnsupported,
|
||||||
|
#[error("setAutoPadding(false) not supported for Aes256Gcm yet")]
|
||||||
|
SetAutoPaddingFalseAes256GcmUnsupported,
|
||||||
|
#[error("Unknown cipher {0}")]
|
||||||
|
UnknownCipher(String),
|
||||||
|
}
|
||||||
|
|
||||||
impl Decipher {
|
impl Decipher {
|
||||||
fn new(
|
fn new(
|
||||||
algorithm_name: &str,
|
algorithm_name: &str,
|
||||||
key: &[u8],
|
key: &[u8],
|
||||||
iv: &[u8],
|
iv: &[u8],
|
||||||
) -> Result<Self, AnyError> {
|
) -> Result<Self, DecipherError> {
|
||||||
use Decipher::*;
|
use Decipher::*;
|
||||||
Ok(match algorithm_name {
|
Ok(match algorithm_name {
|
||||||
"aes-128-cbc" => {
|
"aes-128-cbc" => {
|
||||||
|
@ -335,7 +396,7 @@ impl Decipher {
|
||||||
"aes-256-ecb" => Aes256Ecb(Box::new(ecb::Decryptor::new(key.into()))),
|
"aes-256-ecb" => Aes256Ecb(Box::new(ecb::Decryptor::new(key.into()))),
|
||||||
"aes-128-gcm" => {
|
"aes-128-gcm" => {
|
||||||
if iv.len() != 12 {
|
if iv.len() != 12 {
|
||||||
return Err(type_error("IV length must be 12 bytes"));
|
return Err(DecipherError::InvalidIvLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
let decipher =
|
let decipher =
|
||||||
|
@ -345,7 +406,7 @@ impl Decipher {
|
||||||
}
|
}
|
||||||
"aes-256-gcm" => {
|
"aes-256-gcm" => {
|
||||||
if iv.len() != 12 {
|
if iv.len() != 12 {
|
||||||
return Err(type_error("IV length must be 12 bytes"));
|
return Err(DecipherError::InvalidIvLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
let decipher =
|
let decipher =
|
||||||
|
@ -355,15 +416,17 @@ impl Decipher {
|
||||||
}
|
}
|
||||||
"aes256" | "aes-256-cbc" => {
|
"aes256" | "aes-256-cbc" => {
|
||||||
if key.len() != 32 {
|
if key.len() != 32 {
|
||||||
return Err(range_error("Invalid key length"));
|
return Err(DecipherError::InvalidKeyLength);
|
||||||
}
|
}
|
||||||
if iv.len() != 16 {
|
if iv.len() != 16 {
|
||||||
return Err(type_error("Invalid initialization vector"));
|
return Err(DecipherError::InvalidInitializationVector);
|
||||||
}
|
}
|
||||||
|
|
||||||
Aes256Cbc(Box::new(cbc::Decryptor::new(key.into(), iv.into())))
|
Aes256Cbc(Box::new(cbc::Decryptor::new(key.into(), iv.into())))
|
||||||
}
|
}
|
||||||
_ => return Err(type_error(format!("Unknown cipher {algorithm_name}"))),
|
_ => {
|
||||||
|
return Err(DecipherError::UnknownCipher(algorithm_name.to_string()))
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -432,14 +495,14 @@ impl Decipher {
|
||||||
input: &[u8],
|
input: &[u8],
|
||||||
output: &mut [u8],
|
output: &mut [u8],
|
||||||
auth_tag: &[u8],
|
auth_tag: &[u8],
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), DecipherError> {
|
||||||
use Decipher::*;
|
use Decipher::*;
|
||||||
match (self, auto_pad) {
|
match (self, auto_pad) {
|
||||||
(Aes128Cbc(decryptor), true) => {
|
(Aes128Cbc(decryptor), true) => {
|
||||||
assert!(input.len() == 16);
|
assert!(input.len() == 16);
|
||||||
let _ = (*decryptor)
|
let _ = (*decryptor)
|
||||||
.decrypt_padded_b2b_mut::<Pkcs7>(input, output)
|
.decrypt_padded_b2b_mut::<Pkcs7>(input, output)
|
||||||
.map_err(|_| type_error("Cannot unpad the input data"))?;
|
.map_err(|_| DecipherError::CannotUnpadInputData)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
(Aes128Cbc(mut decryptor), false) => {
|
(Aes128Cbc(mut decryptor), false) => {
|
||||||
|
@ -453,7 +516,7 @@ impl Decipher {
|
||||||
assert!(input.len() == 16);
|
assert!(input.len() == 16);
|
||||||
let _ = (*decryptor)
|
let _ = (*decryptor)
|
||||||
.decrypt_padded_b2b_mut::<Pkcs7>(input, output)
|
.decrypt_padded_b2b_mut::<Pkcs7>(input, output)
|
||||||
.map_err(|_| type_error("Cannot unpad the input data"))?;
|
.map_err(|_| DecipherError::CannotUnpadInputData)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
(Aes128Ecb(mut decryptor), false) => {
|
(Aes128Ecb(mut decryptor), false) => {
|
||||||
|
@ -467,7 +530,7 @@ impl Decipher {
|
||||||
assert!(input.len() == 16);
|
assert!(input.len() == 16);
|
||||||
let _ = (*decryptor)
|
let _ = (*decryptor)
|
||||||
.decrypt_padded_b2b_mut::<Pkcs7>(input, output)
|
.decrypt_padded_b2b_mut::<Pkcs7>(input, output)
|
||||||
.map_err(|_| type_error("Cannot unpad the input data"))?;
|
.map_err(|_| DecipherError::CannotUnpadInputData)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
(Aes192Ecb(mut decryptor), false) => {
|
(Aes192Ecb(mut decryptor), false) => {
|
||||||
|
@ -481,7 +544,7 @@ impl Decipher {
|
||||||
assert!(input.len() == 16);
|
assert!(input.len() == 16);
|
||||||
let _ = (*decryptor)
|
let _ = (*decryptor)
|
||||||
.decrypt_padded_b2b_mut::<Pkcs7>(input, output)
|
.decrypt_padded_b2b_mut::<Pkcs7>(input, output)
|
||||||
.map_err(|_| type_error("Cannot unpad the input data"))?;
|
.map_err(|_| DecipherError::CannotUnpadInputData)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
(Aes256Ecb(mut decryptor), false) => {
|
(Aes256Ecb(mut decryptor), false) => {
|
||||||
|
@ -496,28 +559,28 @@ impl Decipher {
|
||||||
if tag.as_slice() == auth_tag {
|
if tag.as_slice() == auth_tag {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(type_error("Failed to authenticate data"))
|
Err(DecipherError::DataAuthenticationFailed)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(Aes128Gcm(_), false) => Err(type_error(
|
(Aes128Gcm(_), false) => {
|
||||||
"setAutoPadding(false) not supported for Aes256Gcm yet",
|
Err(DecipherError::SetAutoPaddingFalseAes128GcmUnsupported)
|
||||||
)),
|
}
|
||||||
(Aes256Gcm(decipher), true) => {
|
(Aes256Gcm(decipher), true) => {
|
||||||
let tag = decipher.finish();
|
let tag = decipher.finish();
|
||||||
if tag.as_slice() == auth_tag {
|
if tag.as_slice() == auth_tag {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(type_error("Failed to authenticate data"))
|
Err(DecipherError::DataAuthenticationFailed)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(Aes256Gcm(_), false) => Err(type_error(
|
(Aes256Gcm(_), false) => {
|
||||||
"setAutoPadding(false) not supported for Aes256Gcm yet",
|
Err(DecipherError::SetAutoPaddingFalseAes256GcmUnsupported)
|
||||||
)),
|
}
|
||||||
(Aes256Cbc(decryptor), true) => {
|
(Aes256Cbc(decryptor), true) => {
|
||||||
assert!(input.len() == 16);
|
assert!(input.len() == 16);
|
||||||
let _ = (*decryptor)
|
let _ = (*decryptor)
|
||||||
.decrypt_padded_b2b_mut::<Pkcs7>(input, output)
|
.decrypt_padded_b2b_mut::<Pkcs7>(input, output)
|
||||||
.map_err(|_| type_error("Cannot unpad the input data"))?;
|
.map_err(|_| DecipherError::CannotUnpadInputData)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
(Aes256Cbc(mut decryptor), false) => {
|
(Aes256Cbc(mut decryptor), false) => {
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||||
use deno_core::error::generic_error;
|
|
||||||
use deno_core::error::AnyError;
|
|
||||||
use deno_core::GarbageCollected;
|
use deno_core::GarbageCollected;
|
||||||
use digest::Digest;
|
use digest::Digest;
|
||||||
use digest::DynDigest;
|
use digest::DynDigest;
|
||||||
|
@ -19,7 +17,7 @@ impl Hasher {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
algorithm: &str,
|
algorithm: &str,
|
||||||
output_length: Option<usize>,
|
output_length: Option<usize>,
|
||||||
) -> Result<Self, AnyError> {
|
) -> Result<Self, HashError> {
|
||||||
let hash = Hash::new(algorithm, output_length)?;
|
let hash = Hash::new(algorithm, output_length)?;
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
|
@ -44,7 +42,7 @@ impl Hasher {
|
||||||
pub fn clone_inner(
|
pub fn clone_inner(
|
||||||
&self,
|
&self,
|
||||||
output_length: Option<usize>,
|
output_length: Option<usize>,
|
||||||
) -> Result<Option<Self>, AnyError> {
|
) -> Result<Option<Self>, HashError> {
|
||||||
let hash = self.hash.borrow();
|
let hash = self.hash.borrow();
|
||||||
let Some(hash) = hash.as_ref() else {
|
let Some(hash) = hash.as_ref() else {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
|
@ -184,11 +182,19 @@ pub enum Hash {
|
||||||
|
|
||||||
use Hash::*;
|
use Hash::*;
|
||||||
|
|
||||||
|
#[derive(Debug, thiserror::Error)]
|
||||||
|
pub enum HashError {
|
||||||
|
#[error("Output length mismatch for non-extendable algorithm")]
|
||||||
|
OutputLengthMismatch,
|
||||||
|
#[error("Digest method not supported: {0}")]
|
||||||
|
DigestMethodUnsupported(String),
|
||||||
|
}
|
||||||
|
|
||||||
impl Hash {
|
impl Hash {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
algorithm_name: &str,
|
algorithm_name: &str,
|
||||||
output_length: Option<usize>,
|
output_length: Option<usize>,
|
||||||
) -> Result<Self, AnyError> {
|
) -> Result<Self, HashError> {
|
||||||
match algorithm_name {
|
match algorithm_name {
|
||||||
"shake128" => return Ok(Shake128(Default::default(), output_length)),
|
"shake128" => return Ok(Shake128(Default::default(), output_length)),
|
||||||
"shake256" => return Ok(Shake256(Default::default(), output_length)),
|
"shake256" => return Ok(Shake256(Default::default(), output_length)),
|
||||||
|
@ -201,17 +207,13 @@ impl Hash {
|
||||||
let digest: D = Digest::new();
|
let digest: D = Digest::new();
|
||||||
if let Some(length) = output_length {
|
if let Some(length) = output_length {
|
||||||
if length != digest.output_size() {
|
if length != digest.output_size() {
|
||||||
return Err(generic_error(
|
return Err(HashError::OutputLengthMismatch);
|
||||||
"Output length mismatch for non-extendable algorithm",
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FixedSize(Box::new(digest))
|
FixedSize(Box::new(digest))
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
return Err(generic_error(format!(
|
return Err(HashError::DigestMethodUnsupported(algorithm_name.to_string()))
|
||||||
"Digest method not supported: {algorithm_name}"
|
|
||||||
)))
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -243,14 +245,12 @@ impl Hash {
|
||||||
pub fn clone_hash(
|
pub fn clone_hash(
|
||||||
&self,
|
&self,
|
||||||
output_length: Option<usize>,
|
output_length: Option<usize>,
|
||||||
) -> Result<Self, AnyError> {
|
) -> Result<Self, HashError> {
|
||||||
let hash = match self {
|
let hash = match self {
|
||||||
FixedSize(context) => {
|
FixedSize(context) => {
|
||||||
if let Some(length) = output_length {
|
if let Some(length) = output_length {
|
||||||
if length != context.output_size() {
|
if length != context.output_size() {
|
||||||
return Err(generic_error(
|
return Err(HashError::OutputLengthMismatch);
|
||||||
"Output length mismatch for non-extendable algorithm",
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FixedSize(context.box_clone())
|
FixedSize(context.box_clone())
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,7 +1,6 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||||
use deno_core::error::generic_error;
|
use deno_core::error::generic_error;
|
||||||
use deno_core::error::type_error;
|
use deno_core::error::type_error;
|
||||||
use deno_core::error::AnyError;
|
|
||||||
use deno_core::op2;
|
use deno_core::op2;
|
||||||
use deno_core::unsync::spawn_blocking;
|
use deno_core::unsync::spawn_blocking;
|
||||||
use deno_core::JsBuffer;
|
use deno_core::JsBuffer;
|
||||||
|
@ -34,14 +33,14 @@ use rsa::Pkcs1v15Encrypt;
|
||||||
use rsa::RsaPrivateKey;
|
use rsa::RsaPrivateKey;
|
||||||
use rsa::RsaPublicKey;
|
use rsa::RsaPublicKey;
|
||||||
|
|
||||||
mod cipher;
|
pub mod cipher;
|
||||||
mod dh;
|
mod dh;
|
||||||
mod digest;
|
pub mod digest;
|
||||||
pub mod keys;
|
pub mod keys;
|
||||||
mod md5_sha1;
|
mod md5_sha1;
|
||||||
mod pkcs3;
|
mod pkcs3;
|
||||||
mod primes;
|
mod primes;
|
||||||
mod sign;
|
pub mod sign;
|
||||||
pub mod x509;
|
pub mod x509;
|
||||||
|
|
||||||
use self::digest::match_fixed_digest_with_eager_block_buffer;
|
use self::digest::match_fixed_digest_with_eager_block_buffer;
|
||||||
|
@ -58,38 +57,31 @@ pub fn op_node_check_prime(
|
||||||
pub fn op_node_check_prime_bytes(
|
pub fn op_node_check_prime_bytes(
|
||||||
#[anybuffer] bytes: &[u8],
|
#[anybuffer] bytes: &[u8],
|
||||||
#[number] checks: usize,
|
#[number] checks: usize,
|
||||||
) -> Result<bool, AnyError> {
|
) -> bool {
|
||||||
let candidate = BigInt::from_bytes_be(num_bigint::Sign::Plus, bytes);
|
let candidate = BigInt::from_bytes_be(num_bigint::Sign::Plus, bytes);
|
||||||
Ok(primes::is_probably_prime(&candidate, checks))
|
primes::is_probably_prime(&candidate, checks)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[op2(async)]
|
#[op2(async)]
|
||||||
pub async fn op_node_check_prime_async(
|
pub async fn op_node_check_prime_async(
|
||||||
#[bigint] num: i64,
|
#[bigint] num: i64,
|
||||||
#[number] checks: usize,
|
#[number] checks: usize,
|
||||||
) -> Result<bool, AnyError> {
|
) -> Result<bool, tokio::task::JoinError> {
|
||||||
// TODO(@littledivy): use rayon for CPU-bound tasks
|
// TODO(@littledivy): use rayon for CPU-bound tasks
|
||||||
Ok(
|
spawn_blocking(move || primes::is_probably_prime(&BigInt::from(num), checks))
|
||||||
spawn_blocking(move || {
|
.await
|
||||||
primes::is_probably_prime(&BigInt::from(num), checks)
|
|
||||||
})
|
|
||||||
.await?,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[op2(async)]
|
#[op2(async)]
|
||||||
pub fn op_node_check_prime_bytes_async(
|
pub fn op_node_check_prime_bytes_async(
|
||||||
#[anybuffer] bytes: &[u8],
|
#[anybuffer] bytes: &[u8],
|
||||||
#[number] checks: usize,
|
#[number] checks: usize,
|
||||||
) -> Result<impl Future<Output = Result<bool, AnyError>>, AnyError> {
|
) -> impl Future<Output = Result<bool, tokio::task::JoinError>> {
|
||||||
let candidate = BigInt::from_bytes_be(num_bigint::Sign::Plus, bytes);
|
let candidate = BigInt::from_bytes_be(num_bigint::Sign::Plus, bytes);
|
||||||
// TODO(@littledivy): use rayon for CPU-bound tasks
|
// TODO(@littledivy): use rayon for CPU-bound tasks
|
||||||
Ok(async move {
|
async move {
|
||||||
Ok(
|
spawn_blocking(move || primes::is_probably_prime(&candidate, checks)).await
|
||||||
spawn_blocking(move || primes::is_probably_prime(&candidate, checks))
|
}
|
||||||
.await?,
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[op2]
|
#[op2]
|
||||||
|
@ -97,7 +89,7 @@ pub fn op_node_check_prime_bytes_async(
|
||||||
pub fn op_node_create_hash(
|
pub fn op_node_create_hash(
|
||||||
#[string] algorithm: &str,
|
#[string] algorithm: &str,
|
||||||
output_length: Option<u32>,
|
output_length: Option<u32>,
|
||||||
) -> Result<digest::Hasher, AnyError> {
|
) -> Result<digest::Hasher, digest::HashError> {
|
||||||
digest::Hasher::new(algorithm, output_length.map(|l| l as usize))
|
digest::Hasher::new(algorithm, output_length.map(|l| l as usize))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,17 +137,31 @@ pub fn op_node_hash_digest_hex(
|
||||||
pub fn op_node_hash_clone(
|
pub fn op_node_hash_clone(
|
||||||
#[cppgc] hasher: &digest::Hasher,
|
#[cppgc] hasher: &digest::Hasher,
|
||||||
output_length: Option<u32>,
|
output_length: Option<u32>,
|
||||||
) -> Result<Option<digest::Hasher>, AnyError> {
|
) -> Result<Option<digest::Hasher>, digest::HashError> {
|
||||||
hasher.clone_inner(output_length.map(|l| l as usize))
|
hasher.clone_inner(output_length.map(|l| l as usize))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, thiserror::Error)]
|
||||||
|
pub enum PrivateEncryptDecryptError {
|
||||||
|
#[error(transparent)]
|
||||||
|
Pkcs8(#[from] pkcs8::Error),
|
||||||
|
#[error(transparent)]
|
||||||
|
Spki(#[from] spki::Error),
|
||||||
|
#[error(transparent)]
|
||||||
|
Utf8(#[from] std::str::Utf8Error),
|
||||||
|
#[error(transparent)]
|
||||||
|
Rsa(#[from] rsa::Error),
|
||||||
|
#[error("Unknown padding")]
|
||||||
|
UnknownPadding,
|
||||||
|
}
|
||||||
|
|
||||||
#[op2]
|
#[op2]
|
||||||
#[serde]
|
#[serde]
|
||||||
pub fn op_node_private_encrypt(
|
pub fn op_node_private_encrypt(
|
||||||
#[serde] key: StringOrBuffer,
|
#[serde] key: StringOrBuffer,
|
||||||
#[serde] msg: StringOrBuffer,
|
#[serde] msg: StringOrBuffer,
|
||||||
#[smi] padding: u32,
|
#[smi] padding: u32,
|
||||||
) -> Result<ToJsBuffer, AnyError> {
|
) -> Result<ToJsBuffer, PrivateEncryptDecryptError> {
|
||||||
let key = RsaPrivateKey::from_pkcs8_pem((&key).try_into()?)?;
|
let key = RsaPrivateKey::from_pkcs8_pem((&key).try_into()?)?;
|
||||||
|
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
|
@ -172,7 +178,7 @@ pub fn op_node_private_encrypt(
|
||||||
.encrypt(&mut rng, Oaep::new::<sha1::Sha1>(), &msg)?
|
.encrypt(&mut rng, Oaep::new::<sha1::Sha1>(), &msg)?
|
||||||
.into(),
|
.into(),
|
||||||
),
|
),
|
||||||
_ => Err(type_error("Unknown padding")),
|
_ => Err(PrivateEncryptDecryptError::UnknownPadding),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,13 +188,13 @@ pub fn op_node_private_decrypt(
|
||||||
#[serde] key: StringOrBuffer,
|
#[serde] key: StringOrBuffer,
|
||||||
#[serde] msg: StringOrBuffer,
|
#[serde] msg: StringOrBuffer,
|
||||||
#[smi] padding: u32,
|
#[smi] padding: u32,
|
||||||
) -> Result<ToJsBuffer, AnyError> {
|
) -> Result<ToJsBuffer, PrivateEncryptDecryptError> {
|
||||||
let key = RsaPrivateKey::from_pkcs8_pem((&key).try_into()?)?;
|
let key = RsaPrivateKey::from_pkcs8_pem((&key).try_into()?)?;
|
||||||
|
|
||||||
match padding {
|
match padding {
|
||||||
1 => Ok(key.decrypt(Pkcs1v15Encrypt, &msg)?.into()),
|
1 => Ok(key.decrypt(Pkcs1v15Encrypt, &msg)?.into()),
|
||||||
4 => Ok(key.decrypt(Oaep::new::<sha1::Sha1>(), &msg)?.into()),
|
4 => Ok(key.decrypt(Oaep::new::<sha1::Sha1>(), &msg)?.into()),
|
||||||
_ => Err(type_error("Unknown padding")),
|
_ => Err(PrivateEncryptDecryptError::UnknownPadding),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,7 +204,7 @@ pub fn op_node_public_encrypt(
|
||||||
#[serde] key: StringOrBuffer,
|
#[serde] key: StringOrBuffer,
|
||||||
#[serde] msg: StringOrBuffer,
|
#[serde] msg: StringOrBuffer,
|
||||||
#[smi] padding: u32,
|
#[smi] padding: u32,
|
||||||
) -> Result<ToJsBuffer, AnyError> {
|
) -> Result<ToJsBuffer, PrivateEncryptDecryptError> {
|
||||||
let key = RsaPublicKey::from_public_key_pem((&key).try_into()?)?;
|
let key = RsaPublicKey::from_public_key_pem((&key).try_into()?)?;
|
||||||
|
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
|
@ -209,7 +215,7 @@ pub fn op_node_public_encrypt(
|
||||||
.encrypt(&mut rng, Oaep::new::<sha1::Sha1>(), &msg)?
|
.encrypt(&mut rng, Oaep::new::<sha1::Sha1>(), &msg)?
|
||||||
.into(),
|
.into(),
|
||||||
),
|
),
|
||||||
_ => Err(type_error("Unknown padding")),
|
_ => Err(PrivateEncryptDecryptError::UnknownPadding),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,7 +226,7 @@ pub fn op_node_create_cipheriv(
|
||||||
#[string] algorithm: &str,
|
#[string] algorithm: &str,
|
||||||
#[buffer] key: &[u8],
|
#[buffer] key: &[u8],
|
||||||
#[buffer] iv: &[u8],
|
#[buffer] iv: &[u8],
|
||||||
) -> Result<u32, AnyError> {
|
) -> Result<u32, cipher::CipherContextError> {
|
||||||
let context = cipher::CipherContext::new(algorithm, key, iv)?;
|
let context = cipher::CipherContext::new(algorithm, key, iv)?;
|
||||||
Ok(state.resource_table.add(context))
|
Ok(state.resource_table.add(context))
|
||||||
}
|
}
|
||||||
|
@ -262,11 +268,14 @@ pub fn op_node_cipheriv_final(
|
||||||
auto_pad: bool,
|
auto_pad: bool,
|
||||||
#[buffer] input: &[u8],
|
#[buffer] input: &[u8],
|
||||||
#[anybuffer] output: &mut [u8],
|
#[anybuffer] output: &mut [u8],
|
||||||
) -> Result<Option<Vec<u8>>, AnyError> {
|
) -> Result<Option<Vec<u8>>, cipher::CipherContextError> {
|
||||||
let context = state.resource_table.take::<cipher::CipherContext>(rid)?;
|
let context = state
|
||||||
|
.resource_table
|
||||||
|
.take::<cipher::CipherContext>(rid)
|
||||||
|
.map_err(cipher::CipherContextError::Resource)?;
|
||||||
let context = Rc::try_unwrap(context)
|
let context = Rc::try_unwrap(context)
|
||||||
.map_err(|_| type_error("Cipher context is already in use"))?;
|
.map_err(|_| cipher::CipherContextError::ContextInUse)?;
|
||||||
context.r#final(auto_pad, input, output)
|
context.r#final(auto_pad, input, output).map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[op2]
|
#[op2]
|
||||||
|
@ -274,10 +283,13 @@ pub fn op_node_cipheriv_final(
|
||||||
pub fn op_node_cipheriv_take(
|
pub fn op_node_cipheriv_take(
|
||||||
state: &mut OpState,
|
state: &mut OpState,
|
||||||
#[smi] rid: u32,
|
#[smi] rid: u32,
|
||||||
) -> Result<Option<Vec<u8>>, AnyError> {
|
) -> Result<Option<Vec<u8>>, cipher::CipherContextError> {
|
||||||
let context = state.resource_table.take::<cipher::CipherContext>(rid)?;
|
let context = state
|
||||||
|
.resource_table
|
||||||
|
.take::<cipher::CipherContext>(rid)
|
||||||
|
.map_err(cipher::CipherContextError::Resource)?;
|
||||||
let context = Rc::try_unwrap(context)
|
let context = Rc::try_unwrap(context)
|
||||||
.map_err(|_| type_error("Cipher context is already in use"))?;
|
.map_err(|_| cipher::CipherContextError::ContextInUse)?;
|
||||||
Ok(context.take_tag())
|
Ok(context.take_tag())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -288,7 +300,7 @@ pub fn op_node_create_decipheriv(
|
||||||
#[string] algorithm: &str,
|
#[string] algorithm: &str,
|
||||||
#[buffer] key: &[u8],
|
#[buffer] key: &[u8],
|
||||||
#[buffer] iv: &[u8],
|
#[buffer] iv: &[u8],
|
||||||
) -> Result<u32, AnyError> {
|
) -> Result<u32, cipher::DecipherContextError> {
|
||||||
let context = cipher::DecipherContext::new(algorithm, key, iv)?;
|
let context = cipher::DecipherContext::new(algorithm, key, iv)?;
|
||||||
Ok(state.resource_table.add(context))
|
Ok(state.resource_table.add(context))
|
||||||
}
|
}
|
||||||
|
@ -326,10 +338,13 @@ pub fn op_node_decipheriv_decrypt(
|
||||||
pub fn op_node_decipheriv_take(
|
pub fn op_node_decipheriv_take(
|
||||||
state: &mut OpState,
|
state: &mut OpState,
|
||||||
#[smi] rid: u32,
|
#[smi] rid: u32,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), cipher::DecipherContextError> {
|
||||||
let context = state.resource_table.take::<cipher::DecipherContext>(rid)?;
|
let context = state
|
||||||
|
.resource_table
|
||||||
|
.take::<cipher::DecipherContext>(rid)
|
||||||
|
.map_err(cipher::DecipherContextError::Resource)?;
|
||||||
Rc::try_unwrap(context)
|
Rc::try_unwrap(context)
|
||||||
.map_err(|_| type_error("Cipher context is already in use"))?;
|
.map_err(|_| cipher::DecipherContextError::ContextInUse)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -341,11 +356,16 @@ pub fn op_node_decipheriv_final(
|
||||||
#[buffer] input: &[u8],
|
#[buffer] input: &[u8],
|
||||||
#[anybuffer] output: &mut [u8],
|
#[anybuffer] output: &mut [u8],
|
||||||
#[buffer] auth_tag: &[u8],
|
#[buffer] auth_tag: &[u8],
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), cipher::DecipherContextError> {
|
||||||
let context = state.resource_table.take::<cipher::DecipherContext>(rid)?;
|
let context = state
|
||||||
|
.resource_table
|
||||||
|
.take::<cipher::DecipherContext>(rid)
|
||||||
|
.map_err(cipher::DecipherContextError::Resource)?;
|
||||||
let context = Rc::try_unwrap(context)
|
let context = Rc::try_unwrap(context)
|
||||||
.map_err(|_| type_error("Cipher context is already in use"))?;
|
.map_err(|_| cipher::DecipherContextError::ContextInUse)?;
|
||||||
context.r#final(auto_pad, input, output, auth_tag)
|
context
|
||||||
|
.r#final(auto_pad, input, output, auth_tag)
|
||||||
|
.map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[op2]
|
#[op2]
|
||||||
|
@ -356,7 +376,7 @@ pub fn op_node_sign(
|
||||||
#[string] digest_type: &str,
|
#[string] digest_type: &str,
|
||||||
#[smi] pss_salt_length: Option<u32>,
|
#[smi] pss_salt_length: Option<u32>,
|
||||||
#[smi] dsa_signature_encoding: u32,
|
#[smi] dsa_signature_encoding: u32,
|
||||||
) -> Result<Box<[u8]>, AnyError> {
|
) -> Result<Box<[u8]>, sign::KeyObjectHandlePrehashedSignAndVerifyError> {
|
||||||
handle.sign_prehashed(
|
handle.sign_prehashed(
|
||||||
digest_type,
|
digest_type,
|
||||||
digest,
|
digest,
|
||||||
|
@ -373,7 +393,7 @@ pub fn op_node_verify(
|
||||||
#[buffer] signature: &[u8],
|
#[buffer] signature: &[u8],
|
||||||
#[smi] pss_salt_length: Option<u32>,
|
#[smi] pss_salt_length: Option<u32>,
|
||||||
#[smi] dsa_signature_encoding: u32,
|
#[smi] dsa_signature_encoding: u32,
|
||||||
) -> Result<bool, AnyError> {
|
) -> Result<bool, sign::KeyObjectHandlePrehashedSignAndVerifyError> {
|
||||||
handle.verify_prehashed(
|
handle.verify_prehashed(
|
||||||
digest_type,
|
digest_type,
|
||||||
digest,
|
digest,
|
||||||
|
@ -383,13 +403,21 @@ pub fn op_node_verify(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, thiserror::Error)]
|
||||||
|
pub enum Pbkdf2Error {
|
||||||
|
#[error("unsupported digest: {0}")]
|
||||||
|
UnsupportedDigest(String),
|
||||||
|
#[error(transparent)]
|
||||||
|
Join(#[from] tokio::task::JoinError),
|
||||||
|
}
|
||||||
|
|
||||||
fn pbkdf2_sync(
|
fn pbkdf2_sync(
|
||||||
password: &[u8],
|
password: &[u8],
|
||||||
salt: &[u8],
|
salt: &[u8],
|
||||||
iterations: u32,
|
iterations: u32,
|
||||||
algorithm_name: &str,
|
algorithm_name: &str,
|
||||||
derived_key: &mut [u8],
|
derived_key: &mut [u8],
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), Pbkdf2Error> {
|
||||||
match_fixed_digest_with_eager_block_buffer!(
|
match_fixed_digest_with_eager_block_buffer!(
|
||||||
algorithm_name,
|
algorithm_name,
|
||||||
fn <D>() {
|
fn <D>() {
|
||||||
|
@ -397,10 +425,7 @@ fn pbkdf2_sync(
|
||||||
Ok(())
|
Ok(())
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
Err(type_error(format!(
|
Err(Pbkdf2Error::UnsupportedDigest(algorithm_name.to_string()))
|
||||||
"unsupported digest: {}",
|
|
||||||
algorithm_name
|
|
||||||
)))
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -424,7 +449,7 @@ pub async fn op_node_pbkdf2_async(
|
||||||
#[smi] iterations: u32,
|
#[smi] iterations: u32,
|
||||||
#[string] digest: String,
|
#[string] digest: String,
|
||||||
#[number] keylen: usize,
|
#[number] keylen: usize,
|
||||||
) -> Result<ToJsBuffer, AnyError> {
|
) -> Result<ToJsBuffer, Pbkdf2Error> {
|
||||||
spawn_blocking(move || {
|
spawn_blocking(move || {
|
||||||
let mut derived_key = vec![0; keylen];
|
let mut derived_key = vec![0; keylen];
|
||||||
pbkdf2_sync(&password, &salt, iterations, &digest, &mut derived_key)
|
pbkdf2_sync(&password, &salt, iterations, &digest, &mut derived_key)
|
||||||
|
@ -450,15 +475,27 @@ pub async fn op_node_fill_random_async(#[smi] len: i32) -> ToJsBuffer {
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, thiserror::Error)]
|
||||||
|
pub enum HkdfError {
|
||||||
|
#[error("expected secret key")]
|
||||||
|
ExpectedSecretKey,
|
||||||
|
#[error("HKDF-Expand failed")]
|
||||||
|
HkdfExpandFailed,
|
||||||
|
#[error("Unsupported digest: {0}")]
|
||||||
|
UnsupportedDigest(String),
|
||||||
|
#[error(transparent)]
|
||||||
|
Join(#[from] tokio::task::JoinError),
|
||||||
|
}
|
||||||
|
|
||||||
fn hkdf_sync(
|
fn hkdf_sync(
|
||||||
digest_algorithm: &str,
|
digest_algorithm: &str,
|
||||||
handle: &KeyObjectHandle,
|
handle: &KeyObjectHandle,
|
||||||
salt: &[u8],
|
salt: &[u8],
|
||||||
info: &[u8],
|
info: &[u8],
|
||||||
okm: &mut [u8],
|
okm: &mut [u8],
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), HkdfError> {
|
||||||
let Some(ikm) = handle.as_secret_key() else {
|
let Some(ikm) = handle.as_secret_key() else {
|
||||||
return Err(type_error("expected secret key"));
|
return Err(HkdfError::ExpectedSecretKey);
|
||||||
};
|
};
|
||||||
|
|
||||||
match_fixed_digest_with_eager_block_buffer!(
|
match_fixed_digest_with_eager_block_buffer!(
|
||||||
|
@ -466,10 +503,10 @@ fn hkdf_sync(
|
||||||
fn <D>() {
|
fn <D>() {
|
||||||
let hk = Hkdf::<D>::new(Some(salt), ikm);
|
let hk = Hkdf::<D>::new(Some(salt), ikm);
|
||||||
hk.expand(info, okm)
|
hk.expand(info, okm)
|
||||||
.map_err(|_| type_error("HKDF-Expand failed"))
|
.map_err(|_| HkdfError::HkdfExpandFailed)
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
Err(type_error(format!("Unsupported digest: {}", digest_algorithm)))
|
Err(HkdfError::UnsupportedDigest(digest_algorithm.to_string()))
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -481,7 +518,7 @@ pub fn op_node_hkdf(
|
||||||
#[buffer] salt: &[u8],
|
#[buffer] salt: &[u8],
|
||||||
#[buffer] info: &[u8],
|
#[buffer] info: &[u8],
|
||||||
#[buffer] okm: &mut [u8],
|
#[buffer] okm: &mut [u8],
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), HkdfError> {
|
||||||
hkdf_sync(digest_algorithm, handle, salt, info, okm)
|
hkdf_sync(digest_algorithm, handle, salt, info, okm)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -493,7 +530,7 @@ pub async fn op_node_hkdf_async(
|
||||||
#[buffer] salt: JsBuffer,
|
#[buffer] salt: JsBuffer,
|
||||||
#[buffer] info: JsBuffer,
|
#[buffer] info: JsBuffer,
|
||||||
#[number] okm_len: usize,
|
#[number] okm_len: usize,
|
||||||
) -> Result<ToJsBuffer, AnyError> {
|
) -> Result<ToJsBuffer, HkdfError> {
|
||||||
let handle = handle.clone();
|
let handle = handle.clone();
|
||||||
spawn_blocking(move || {
|
spawn_blocking(move || {
|
||||||
let mut okm = vec![0u8; okm_len];
|
let mut okm = vec![0u8; okm_len];
|
||||||
|
@ -509,27 +546,24 @@ pub fn op_node_dh_compute_secret(
|
||||||
#[buffer] prime: JsBuffer,
|
#[buffer] prime: JsBuffer,
|
||||||
#[buffer] private_key: JsBuffer,
|
#[buffer] private_key: JsBuffer,
|
||||||
#[buffer] their_public_key: JsBuffer,
|
#[buffer] their_public_key: JsBuffer,
|
||||||
) -> Result<ToJsBuffer, AnyError> {
|
) -> ToJsBuffer {
|
||||||
let pubkey: BigUint = BigUint::from_bytes_be(their_public_key.as_ref());
|
let pubkey: BigUint = BigUint::from_bytes_be(their_public_key.as_ref());
|
||||||
let privkey: BigUint = BigUint::from_bytes_be(private_key.as_ref());
|
let privkey: BigUint = BigUint::from_bytes_be(private_key.as_ref());
|
||||||
let primei: BigUint = BigUint::from_bytes_be(prime.as_ref());
|
let primei: BigUint = BigUint::from_bytes_be(prime.as_ref());
|
||||||
let shared_secret: BigUint = pubkey.modpow(&privkey, &primei);
|
let shared_secret: BigUint = pubkey.modpow(&privkey, &primei);
|
||||||
|
|
||||||
Ok(shared_secret.to_bytes_be().into())
|
shared_secret.to_bytes_be().into()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[op2(fast)]
|
#[op2(fast)]
|
||||||
#[number]
|
#[number]
|
||||||
pub fn op_node_random_int(
|
pub fn op_node_random_int(#[number] min: i64, #[number] max: i64) -> i64 {
|
||||||
#[number] min: i64,
|
|
||||||
#[number] max: i64,
|
|
||||||
) -> Result<i64, AnyError> {
|
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
// Uniform distribution is required to avoid Modulo Bias
|
// Uniform distribution is required to avoid Modulo Bias
|
||||||
// https://en.wikipedia.org/wiki/Fisher–Yates_shuffle#Modulo_bias
|
// https://en.wikipedia.org/wiki/Fisher–Yates_shuffle#Modulo_bias
|
||||||
let dist = Uniform::from(min..max);
|
let dist = Uniform::from(min..max);
|
||||||
|
|
||||||
Ok(dist.sample(&mut rng))
|
dist.sample(&mut rng)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
|
@ -542,7 +576,7 @@ fn scrypt(
|
||||||
parallelization: u32,
|
parallelization: u32,
|
||||||
_maxmem: u32,
|
_maxmem: u32,
|
||||||
output_buffer: &mut [u8],
|
output_buffer: &mut [u8],
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), deno_core::error::AnyError> {
|
||||||
// Construct Params
|
// Construct Params
|
||||||
let params = scrypt::Params::new(
|
let params = scrypt::Params::new(
|
||||||
cost as u8,
|
cost as u8,
|
||||||
|
@ -573,7 +607,7 @@ pub fn op_node_scrypt_sync(
|
||||||
#[smi] parallelization: u32,
|
#[smi] parallelization: u32,
|
||||||
#[smi] maxmem: u32,
|
#[smi] maxmem: u32,
|
||||||
#[anybuffer] output_buffer: &mut [u8],
|
#[anybuffer] output_buffer: &mut [u8],
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), deno_core::error::AnyError> {
|
||||||
scrypt(
|
scrypt(
|
||||||
password,
|
password,
|
||||||
salt,
|
salt,
|
||||||
|
@ -586,6 +620,14 @@ pub fn op_node_scrypt_sync(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, thiserror::Error)]
|
||||||
|
pub enum ScryptAsyncError {
|
||||||
|
#[error(transparent)]
|
||||||
|
Join(#[from] tokio::task::JoinError),
|
||||||
|
#[error(transparent)]
|
||||||
|
Other(deno_core::error::AnyError),
|
||||||
|
}
|
||||||
|
|
||||||
#[op2(async)]
|
#[op2(async)]
|
||||||
#[serde]
|
#[serde]
|
||||||
pub async fn op_node_scrypt_async(
|
pub async fn op_node_scrypt_async(
|
||||||
|
@ -596,10 +638,11 @@ pub async fn op_node_scrypt_async(
|
||||||
#[smi] block_size: u32,
|
#[smi] block_size: u32,
|
||||||
#[smi] parallelization: u32,
|
#[smi] parallelization: u32,
|
||||||
#[smi] maxmem: u32,
|
#[smi] maxmem: u32,
|
||||||
) -> Result<ToJsBuffer, AnyError> {
|
) -> Result<ToJsBuffer, ScryptAsyncError> {
|
||||||
spawn_blocking(move || {
|
spawn_blocking(move || {
|
||||||
let mut output_buffer = vec![0u8; keylen as usize];
|
let mut output_buffer = vec![0u8; keylen as usize];
|
||||||
let res = scrypt(
|
|
||||||
|
scrypt(
|
||||||
password,
|
password,
|
||||||
salt,
|
salt,
|
||||||
keylen,
|
keylen,
|
||||||
|
@ -608,25 +651,30 @@ pub async fn op_node_scrypt_async(
|
||||||
parallelization,
|
parallelization,
|
||||||
maxmem,
|
maxmem,
|
||||||
&mut output_buffer,
|
&mut output_buffer,
|
||||||
);
|
)
|
||||||
|
.map(|_| output_buffer.into())
|
||||||
if res.is_ok() {
|
.map_err(ScryptAsyncError::Other)
|
||||||
Ok(output_buffer.into())
|
|
||||||
} else {
|
|
||||||
// TODO(lev): rethrow the error?
|
|
||||||
Err(generic_error("scrypt failure"))
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.await?
|
.await?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, thiserror::Error)]
|
||||||
|
pub enum EcdhEncodePubKey {
|
||||||
|
#[error("Invalid public key")]
|
||||||
|
InvalidPublicKey,
|
||||||
|
#[error("Unsupported curve")]
|
||||||
|
UnsupportedCurve,
|
||||||
|
#[error(transparent)]
|
||||||
|
Sec1(#[from] sec1::Error),
|
||||||
|
}
|
||||||
|
|
||||||
#[op2]
|
#[op2]
|
||||||
#[buffer]
|
#[buffer]
|
||||||
pub fn op_node_ecdh_encode_pubkey(
|
pub fn op_node_ecdh_encode_pubkey(
|
||||||
#[string] curve: &str,
|
#[string] curve: &str,
|
||||||
#[buffer] pubkey: &[u8],
|
#[buffer] pubkey: &[u8],
|
||||||
compress: bool,
|
compress: bool,
|
||||||
) -> Result<Vec<u8>, AnyError> {
|
) -> Result<Vec<u8>, EcdhEncodePubKey> {
|
||||||
use elliptic_curve::sec1::FromEncodedPoint;
|
use elliptic_curve::sec1::FromEncodedPoint;
|
||||||
|
|
||||||
match curve {
|
match curve {
|
||||||
|
@ -639,7 +687,7 @@ pub fn op_node_ecdh_encode_pubkey(
|
||||||
);
|
);
|
||||||
// CtOption does not expose its variants.
|
// CtOption does not expose its variants.
|
||||||
if pubkey.is_none().into() {
|
if pubkey.is_none().into() {
|
||||||
return Err(type_error("Invalid public key"));
|
return Err(EcdhEncodePubKey::InvalidPublicKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
let pubkey = pubkey.unwrap();
|
let pubkey = pubkey.unwrap();
|
||||||
|
@ -652,7 +700,7 @@ pub fn op_node_ecdh_encode_pubkey(
|
||||||
);
|
);
|
||||||
// CtOption does not expose its variants.
|
// CtOption does not expose its variants.
|
||||||
if pubkey.is_none().into() {
|
if pubkey.is_none().into() {
|
||||||
return Err(type_error("Invalid public key"));
|
return Err(EcdhEncodePubKey::InvalidPublicKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
let pubkey = pubkey.unwrap();
|
let pubkey = pubkey.unwrap();
|
||||||
|
@ -665,7 +713,7 @@ pub fn op_node_ecdh_encode_pubkey(
|
||||||
);
|
);
|
||||||
// CtOption does not expose its variants.
|
// CtOption does not expose its variants.
|
||||||
if pubkey.is_none().into() {
|
if pubkey.is_none().into() {
|
||||||
return Err(type_error("Invalid public key"));
|
return Err(EcdhEncodePubKey::InvalidPublicKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
let pubkey = pubkey.unwrap();
|
let pubkey = pubkey.unwrap();
|
||||||
|
@ -678,14 +726,14 @@ pub fn op_node_ecdh_encode_pubkey(
|
||||||
);
|
);
|
||||||
// CtOption does not expose its variants.
|
// CtOption does not expose its variants.
|
||||||
if pubkey.is_none().into() {
|
if pubkey.is_none().into() {
|
||||||
return Err(type_error("Invalid public key"));
|
return Err(EcdhEncodePubKey::InvalidPublicKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
let pubkey = pubkey.unwrap();
|
let pubkey = pubkey.unwrap();
|
||||||
|
|
||||||
Ok(pubkey.to_encoded_point(compress).as_ref().to_vec())
|
Ok(pubkey.to_encoded_point(compress).as_ref().to_vec())
|
||||||
}
|
}
|
||||||
&_ => Err(type_error("Unsupported curve")),
|
&_ => Err(EcdhEncodePubKey::UnsupportedCurve),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -695,7 +743,7 @@ pub fn op_node_ecdh_generate_keys(
|
||||||
#[buffer] pubbuf: &mut [u8],
|
#[buffer] pubbuf: &mut [u8],
|
||||||
#[buffer] privbuf: &mut [u8],
|
#[buffer] privbuf: &mut [u8],
|
||||||
#[string] format: &str,
|
#[string] format: &str,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), deno_core::error::AnyError> {
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
let compress = format == "compressed";
|
let compress = format == "compressed";
|
||||||
match curve {
|
match curve {
|
||||||
|
@ -742,7 +790,7 @@ pub fn op_node_ecdh_compute_secret(
|
||||||
#[buffer] this_priv: Option<JsBuffer>,
|
#[buffer] this_priv: Option<JsBuffer>,
|
||||||
#[buffer] their_pub: &mut [u8],
|
#[buffer] their_pub: &mut [u8],
|
||||||
#[buffer] secret: &mut [u8],
|
#[buffer] secret: &mut [u8],
|
||||||
) -> Result<(), AnyError> {
|
) {
|
||||||
match curve {
|
match curve {
|
||||||
"secp256k1" => {
|
"secp256k1" => {
|
||||||
let their_public_key =
|
let their_public_key =
|
||||||
|
@ -760,8 +808,6 @@ pub fn op_node_ecdh_compute_secret(
|
||||||
their_public_key.as_affine(),
|
their_public_key.as_affine(),
|
||||||
);
|
);
|
||||||
secret.copy_from_slice(shared_secret.raw_secret_bytes());
|
secret.copy_from_slice(shared_secret.raw_secret_bytes());
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
"prime256v1" | "secp256r1" => {
|
"prime256v1" | "secp256r1" => {
|
||||||
let their_public_key =
|
let their_public_key =
|
||||||
|
@ -776,8 +822,6 @@ pub fn op_node_ecdh_compute_secret(
|
||||||
their_public_key.as_affine(),
|
their_public_key.as_affine(),
|
||||||
);
|
);
|
||||||
secret.copy_from_slice(shared_secret.raw_secret_bytes());
|
secret.copy_from_slice(shared_secret.raw_secret_bytes());
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
"secp384r1" => {
|
"secp384r1" => {
|
||||||
let their_public_key =
|
let their_public_key =
|
||||||
|
@ -792,8 +836,6 @@ pub fn op_node_ecdh_compute_secret(
|
||||||
their_public_key.as_affine(),
|
their_public_key.as_affine(),
|
||||||
);
|
);
|
||||||
secret.copy_from_slice(shared_secret.raw_secret_bytes());
|
secret.copy_from_slice(shared_secret.raw_secret_bytes());
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
"secp224r1" => {
|
"secp224r1" => {
|
||||||
let their_public_key =
|
let their_public_key =
|
||||||
|
@ -808,8 +850,6 @@ pub fn op_node_ecdh_compute_secret(
|
||||||
their_public_key.as_affine(),
|
their_public_key.as_affine(),
|
||||||
);
|
);
|
||||||
secret.copy_from_slice(shared_secret.raw_secret_bytes());
|
secret.copy_from_slice(shared_secret.raw_secret_bytes());
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
&_ => todo!(),
|
&_ => todo!(),
|
||||||
}
|
}
|
||||||
|
@ -820,7 +860,7 @@ pub fn op_node_ecdh_compute_public_key(
|
||||||
#[string] curve: &str,
|
#[string] curve: &str,
|
||||||
#[buffer] privkey: &[u8],
|
#[buffer] privkey: &[u8],
|
||||||
#[buffer] pubkey: &mut [u8],
|
#[buffer] pubkey: &mut [u8],
|
||||||
) -> Result<(), AnyError> {
|
) {
|
||||||
match curve {
|
match curve {
|
||||||
"secp256k1" => {
|
"secp256k1" => {
|
||||||
let this_private_key =
|
let this_private_key =
|
||||||
|
@ -828,8 +868,6 @@ pub fn op_node_ecdh_compute_public_key(
|
||||||
.expect("bad private key");
|
.expect("bad private key");
|
||||||
let public_key = this_private_key.public_key();
|
let public_key = this_private_key.public_key();
|
||||||
pubkey.copy_from_slice(public_key.to_sec1_bytes().as_ref());
|
pubkey.copy_from_slice(public_key.to_sec1_bytes().as_ref());
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
"prime256v1" | "secp256r1" => {
|
"prime256v1" | "secp256r1" => {
|
||||||
let this_private_key =
|
let this_private_key =
|
||||||
|
@ -837,7 +875,6 @@ pub fn op_node_ecdh_compute_public_key(
|
||||||
.expect("bad private key");
|
.expect("bad private key");
|
||||||
let public_key = this_private_key.public_key();
|
let public_key = this_private_key.public_key();
|
||||||
pubkey.copy_from_slice(public_key.to_sec1_bytes().as_ref());
|
pubkey.copy_from_slice(public_key.to_sec1_bytes().as_ref());
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
"secp384r1" => {
|
"secp384r1" => {
|
||||||
let this_private_key =
|
let this_private_key =
|
||||||
|
@ -845,7 +882,6 @@ pub fn op_node_ecdh_compute_public_key(
|
||||||
.expect("bad private key");
|
.expect("bad private key");
|
||||||
let public_key = this_private_key.public_key();
|
let public_key = this_private_key.public_key();
|
||||||
pubkey.copy_from_slice(public_key.to_sec1_bytes().as_ref());
|
pubkey.copy_from_slice(public_key.to_sec1_bytes().as_ref());
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
"secp224r1" => {
|
"secp224r1" => {
|
||||||
let this_private_key =
|
let this_private_key =
|
||||||
|
@ -853,7 +889,6 @@ pub fn op_node_ecdh_compute_public_key(
|
||||||
.expect("bad private key");
|
.expect("bad private key");
|
||||||
let public_key = this_private_key.public_key();
|
let public_key = this_private_key.public_key();
|
||||||
pubkey.copy_from_slice(public_key.to_sec1_bytes().as_ref());
|
pubkey.copy_from_slice(public_key.to_sec1_bytes().as_ref());
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
&_ => todo!(),
|
&_ => todo!(),
|
||||||
}
|
}
|
||||||
|
@ -874,8 +909,20 @@ pub fn op_node_gen_prime(#[number] size: usize) -> ToJsBuffer {
|
||||||
#[serde]
|
#[serde]
|
||||||
pub async fn op_node_gen_prime_async(
|
pub async fn op_node_gen_prime_async(
|
||||||
#[number] size: usize,
|
#[number] size: usize,
|
||||||
) -> Result<ToJsBuffer, AnyError> {
|
) -> Result<ToJsBuffer, tokio::task::JoinError> {
|
||||||
Ok(spawn_blocking(move || gen_prime(size)).await?)
|
spawn_blocking(move || gen_prime(size)).await
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, thiserror::Error)]
|
||||||
|
pub enum DiffieHellmanError {
|
||||||
|
#[error("Expected private key")]
|
||||||
|
ExpectedPrivateKey,
|
||||||
|
#[error("Expected public key")]
|
||||||
|
ExpectedPublicKey,
|
||||||
|
#[error("DH parameters mismatch")]
|
||||||
|
DhParametersMismatch,
|
||||||
|
#[error("Unsupported key type for diffie hellman, or key type mismatch")]
|
||||||
|
UnsupportedKeyTypeForDiffieHellmanOrKeyTypeMismatch,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[op2]
|
#[op2]
|
||||||
|
@ -883,15 +930,16 @@ pub async fn op_node_gen_prime_async(
|
||||||
pub fn op_node_diffie_hellman(
|
pub fn op_node_diffie_hellman(
|
||||||
#[cppgc] private: &KeyObjectHandle,
|
#[cppgc] private: &KeyObjectHandle,
|
||||||
#[cppgc] public: &KeyObjectHandle,
|
#[cppgc] public: &KeyObjectHandle,
|
||||||
) -> Result<Box<[u8]>, AnyError> {
|
) -> Result<Box<[u8]>, DiffieHellmanError> {
|
||||||
let private = private
|
let private = private
|
||||||
.as_private_key()
|
.as_private_key()
|
||||||
.ok_or_else(|| type_error("Expected private key"))?;
|
.ok_or(DiffieHellmanError::ExpectedPrivateKey)?;
|
||||||
let public = public
|
let public = public
|
||||||
.as_public_key()
|
.as_public_key()
|
||||||
.ok_or_else(|| type_error("Expected public key"))?;
|
.ok_or(DiffieHellmanError::ExpectedPublicKey)?;
|
||||||
|
|
||||||
let res = match (private, &*public) {
|
let res =
|
||||||
|
match (private, &*public) {
|
||||||
(
|
(
|
||||||
AsymmetricPrivateKey::Ec(EcPrivateKey::P224(private)),
|
AsymmetricPrivateKey::Ec(EcPrivateKey::P224(private)),
|
||||||
AsymmetricPublicKey::Ec(EcPublicKey::P224(public)),
|
AsymmetricPublicKey::Ec(EcPublicKey::P224(public)),
|
||||||
|
@ -934,7 +982,7 @@ pub fn op_node_diffie_hellman(
|
||||||
if private.params.prime != public.params.prime
|
if private.params.prime != public.params.prime
|
||||||
|| private.params.base != public.params.base
|
|| private.params.base != public.params.base
|
||||||
{
|
{
|
||||||
return Err(type_error("DH parameters mismatch"));
|
return Err(DiffieHellmanError::DhParametersMismatch);
|
||||||
}
|
}
|
||||||
|
|
||||||
// OSIP - Octet-String-to-Integer primitive
|
// OSIP - Octet-String-to-Integer primitive
|
||||||
|
@ -949,51 +997,67 @@ pub fn op_node_diffie_hellman(
|
||||||
|
|
||||||
shared_secret.to_bytes_be().into()
|
shared_secret.to_bytes_be().into()
|
||||||
}
|
}
|
||||||
_ => {
|
_ => return Err(
|
||||||
return Err(type_error(
|
DiffieHellmanError::UnsupportedKeyTypeForDiffieHellmanOrKeyTypeMismatch,
|
||||||
"Unsupported key type for diffie hellman, or key type mismatch",
|
),
|
||||||
))
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(res)
|
Ok(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, thiserror::Error)]
|
||||||
|
pub enum SignEd25519Error {
|
||||||
|
#[error("Expected private key")]
|
||||||
|
ExpectedPrivateKey,
|
||||||
|
#[error("Expected Ed25519 private key")]
|
||||||
|
ExpectedEd25519PrivateKey,
|
||||||
|
#[error("Invalid Ed25519 private key")]
|
||||||
|
InvalidEd25519PrivateKey,
|
||||||
|
}
|
||||||
|
|
||||||
#[op2(fast)]
|
#[op2(fast)]
|
||||||
pub fn op_node_sign_ed25519(
|
pub fn op_node_sign_ed25519(
|
||||||
#[cppgc] key: &KeyObjectHandle,
|
#[cppgc] key: &KeyObjectHandle,
|
||||||
#[buffer] data: &[u8],
|
#[buffer] data: &[u8],
|
||||||
#[buffer] signature: &mut [u8],
|
#[buffer] signature: &mut [u8],
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), SignEd25519Error> {
|
||||||
let private = key
|
let private = key
|
||||||
.as_private_key()
|
.as_private_key()
|
||||||
.ok_or_else(|| type_error("Expected private key"))?;
|
.ok_or(SignEd25519Error::ExpectedPrivateKey)?;
|
||||||
|
|
||||||
let ed25519 = match private {
|
let ed25519 = match private {
|
||||||
AsymmetricPrivateKey::Ed25519(private) => private,
|
AsymmetricPrivateKey::Ed25519(private) => private,
|
||||||
_ => return Err(type_error("Expected Ed25519 private key")),
|
_ => return Err(SignEd25519Error::ExpectedEd25519PrivateKey),
|
||||||
};
|
};
|
||||||
|
|
||||||
let pair = Ed25519KeyPair::from_seed_unchecked(ed25519.as_bytes().as_slice())
|
let pair = Ed25519KeyPair::from_seed_unchecked(ed25519.as_bytes().as_slice())
|
||||||
.map_err(|_| type_error("Invalid Ed25519 private key"))?;
|
.map_err(|_| SignEd25519Error::InvalidEd25519PrivateKey)?;
|
||||||
signature.copy_from_slice(pair.sign(data).as_ref());
|
signature.copy_from_slice(pair.sign(data).as_ref());
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, thiserror::Error)]
|
||||||
|
pub enum VerifyEd25519Error {
|
||||||
|
#[error("Expected public key")]
|
||||||
|
ExpectedPublicKey,
|
||||||
|
#[error("Expected Ed25519 public key")]
|
||||||
|
ExpectedEd25519PublicKey,
|
||||||
|
}
|
||||||
|
|
||||||
#[op2(fast)]
|
#[op2(fast)]
|
||||||
pub fn op_node_verify_ed25519(
|
pub fn op_node_verify_ed25519(
|
||||||
#[cppgc] key: &KeyObjectHandle,
|
#[cppgc] key: &KeyObjectHandle,
|
||||||
#[buffer] data: &[u8],
|
#[buffer] data: &[u8],
|
||||||
#[buffer] signature: &[u8],
|
#[buffer] signature: &[u8],
|
||||||
) -> Result<bool, AnyError> {
|
) -> Result<bool, VerifyEd25519Error> {
|
||||||
let public = key
|
let public = key
|
||||||
.as_public_key()
|
.as_public_key()
|
||||||
.ok_or_else(|| type_error("Expected public key"))?;
|
.ok_or(VerifyEd25519Error::ExpectedPublicKey)?;
|
||||||
|
|
||||||
let ed25519 = match &*public {
|
let ed25519 = match &*public {
|
||||||
AsymmetricPublicKey::Ed25519(public) => public,
|
AsymmetricPublicKey::Ed25519(public) => public,
|
||||||
_ => return Err(type_error("Expected Ed25519 public key")),
|
_ => return Err(VerifyEd25519Error::ExpectedEd25519PublicKey),
|
||||||
};
|
};
|
||||||
|
|
||||||
let verified = ring::signature::UnparsedPublicKey::new(
|
let verified = ring::signature::UnparsedPublicKey::new(
|
||||||
|
|
|
@ -1,7 +1,4 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||||
use deno_core::error::generic_error;
|
|
||||||
use deno_core::error::type_error;
|
|
||||||
use deno_core::error::AnyError;
|
|
||||||
use rand::rngs::OsRng;
|
use rand::rngs::OsRng;
|
||||||
use rsa::signature::hazmat::PrehashSigner as _;
|
use rsa::signature::hazmat::PrehashSigner as _;
|
||||||
use rsa::signature::hazmat::PrehashVerifier as _;
|
use rsa::signature::hazmat::PrehashVerifier as _;
|
||||||
|
@ -26,7 +23,7 @@ use elliptic_curve::FieldBytesSize;
|
||||||
fn dsa_signature<C: elliptic_curve::PrimeCurve>(
|
fn dsa_signature<C: elliptic_curve::PrimeCurve>(
|
||||||
encoding: u32,
|
encoding: u32,
|
||||||
signature: ecdsa::Signature<C>,
|
signature: ecdsa::Signature<C>,
|
||||||
) -> Result<Box<[u8]>, AnyError>
|
) -> Result<Box<[u8]>, KeyObjectHandlePrehashedSignAndVerifyError>
|
||||||
where
|
where
|
||||||
MaxSize<C>: ArrayLength<u8>,
|
MaxSize<C>: ArrayLength<u8>,
|
||||||
<FieldBytesSize<C> as Add>::Output: Add<MaxOverhead> + ArrayLength<u8>,
|
<FieldBytesSize<C> as Add>::Output: Add<MaxOverhead> + ArrayLength<u8>,
|
||||||
|
@ -36,10 +33,54 @@ where
|
||||||
0 => Ok(signature.to_der().to_bytes().to_vec().into_boxed_slice()),
|
0 => Ok(signature.to_der().to_bytes().to_vec().into_boxed_slice()),
|
||||||
// IEEE P1363
|
// IEEE P1363
|
||||||
1 => Ok(signature.to_bytes().to_vec().into_boxed_slice()),
|
1 => Ok(signature.to_bytes().to_vec().into_boxed_slice()),
|
||||||
_ => Err(type_error("invalid DSA signature encoding")),
|
_ => Err(
|
||||||
|
KeyObjectHandlePrehashedSignAndVerifyError::InvalidDsaSignatureEncoding,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, thiserror::Error)]
|
||||||
|
pub enum KeyObjectHandlePrehashedSignAndVerifyError {
|
||||||
|
#[error("invalid DSA signature encoding")]
|
||||||
|
InvalidDsaSignatureEncoding,
|
||||||
|
#[error("key is not a private key")]
|
||||||
|
KeyIsNotPrivate,
|
||||||
|
#[error("digest not allowed for RSA signature: {0}")]
|
||||||
|
DigestNotAllowedForRsaSignature(String),
|
||||||
|
#[error("failed to sign digest with RSA")]
|
||||||
|
FailedToSignDigestWithRsa,
|
||||||
|
#[error("digest not allowed for RSA-PSS signature: {0}")]
|
||||||
|
DigestNotAllowedForRsaPssSignature(String),
|
||||||
|
#[error("failed to sign digest with RSA-PSS")]
|
||||||
|
FailedToSignDigestWithRsaPss,
|
||||||
|
#[error("failed to sign digest with DSA")]
|
||||||
|
FailedToSignDigestWithDsa,
|
||||||
|
#[error("rsa-pss with different mf1 hash algorithm and hash algorithm is not supported")]
|
||||||
|
RsaPssHashAlgorithmUnsupported,
|
||||||
|
#[error(
|
||||||
|
"private key does not allow {actual} to be used, expected {expected}"
|
||||||
|
)]
|
||||||
|
PrivateKeyDisallowsUsage { actual: String, expected: String },
|
||||||
|
#[error("failed to sign digest")]
|
||||||
|
FailedToSignDigest,
|
||||||
|
#[error("x25519 key cannot be used for signing")]
|
||||||
|
X25519KeyCannotBeUsedForSigning,
|
||||||
|
#[error("Ed25519 key cannot be used for prehashed signing")]
|
||||||
|
Ed25519KeyCannotBeUsedForPrehashedSigning,
|
||||||
|
#[error("DH key cannot be used for signing")]
|
||||||
|
DhKeyCannotBeUsedForSigning,
|
||||||
|
#[error("key is not a public or private key")]
|
||||||
|
KeyIsNotPublicOrPrivate,
|
||||||
|
#[error("Invalid DSA signature")]
|
||||||
|
InvalidDsaSignature,
|
||||||
|
#[error("x25519 key cannot be used for verification")]
|
||||||
|
X25519KeyCannotBeUsedForVerification,
|
||||||
|
#[error("Ed25519 key cannot be used for prehashed verification")]
|
||||||
|
Ed25519KeyCannotBeUsedForPrehashedVerification,
|
||||||
|
#[error("DH key cannot be used for verification")]
|
||||||
|
DhKeyCannotBeUsedForVerification,
|
||||||
|
}
|
||||||
|
|
||||||
impl KeyObjectHandle {
|
impl KeyObjectHandle {
|
||||||
pub fn sign_prehashed(
|
pub fn sign_prehashed(
|
||||||
&self,
|
&self,
|
||||||
|
@ -47,10 +88,10 @@ impl KeyObjectHandle {
|
||||||
digest: &[u8],
|
digest: &[u8],
|
||||||
pss_salt_length: Option<u32>,
|
pss_salt_length: Option<u32>,
|
||||||
dsa_signature_encoding: u32,
|
dsa_signature_encoding: u32,
|
||||||
) -> Result<Box<[u8]>, AnyError> {
|
) -> Result<Box<[u8]>, KeyObjectHandlePrehashedSignAndVerifyError> {
|
||||||
let private_key = self
|
let private_key = self
|
||||||
.as_private_key()
|
.as_private_key()
|
||||||
.ok_or_else(|| type_error("key is not a private key"))?;
|
.ok_or(KeyObjectHandlePrehashedSignAndVerifyError::KeyIsNotPrivate)?;
|
||||||
|
|
||||||
match private_key {
|
match private_key {
|
||||||
AsymmetricPrivateKey::Rsa(key) => {
|
AsymmetricPrivateKey::Rsa(key) => {
|
||||||
|
@ -63,17 +104,14 @@ impl KeyObjectHandle {
|
||||||
rsa::pkcs1v15::Pkcs1v15Sign::new::<D>()
|
rsa::pkcs1v15::Pkcs1v15Sign::new::<D>()
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
return Err(type_error(format!(
|
return Err(KeyObjectHandlePrehashedSignAndVerifyError::DigestNotAllowedForRsaSignature(digest_type.to_string()))
|
||||||
"digest not allowed for RSA signature: {}",
|
|
||||||
digest_type
|
|
||||||
)))
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
let signature = signer
|
let signature = signer
|
||||||
.sign(Some(&mut OsRng), key, digest)
|
.sign(Some(&mut OsRng), key, digest)
|
||||||
.map_err(|_| generic_error("failed to sign digest with RSA"))?;
|
.map_err(|_| KeyObjectHandlePrehashedSignAndVerifyError::FailedToSignDigestWithRsa)?;
|
||||||
Ok(signature.into())
|
Ok(signature.into())
|
||||||
}
|
}
|
||||||
AsymmetricPrivateKey::RsaPss(key) => {
|
AsymmetricPrivateKey::RsaPss(key) => {
|
||||||
|
@ -81,9 +119,7 @@ impl KeyObjectHandle {
|
||||||
let mut salt_length = None;
|
let mut salt_length = None;
|
||||||
if let Some(details) = &key.details {
|
if let Some(details) = &key.details {
|
||||||
if details.hash_algorithm != details.mf1_hash_algorithm {
|
if details.hash_algorithm != details.mf1_hash_algorithm {
|
||||||
return Err(type_error(
|
return Err(KeyObjectHandlePrehashedSignAndVerifyError::RsaPssHashAlgorithmUnsupported);
|
||||||
"rsa-pss with different mf1 hash algorithm and hash algorithm is not supported",
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
hash_algorithm = Some(details.hash_algorithm);
|
hash_algorithm = Some(details.hash_algorithm);
|
||||||
salt_length = Some(details.salt_length as usize);
|
salt_length = Some(details.salt_length as usize);
|
||||||
|
@ -96,10 +132,10 @@ impl KeyObjectHandle {
|
||||||
fn <D>(algorithm: Option<RsaPssHashAlgorithm>) {
|
fn <D>(algorithm: Option<RsaPssHashAlgorithm>) {
|
||||||
if let Some(hash_algorithm) = hash_algorithm.take() {
|
if let Some(hash_algorithm) = hash_algorithm.take() {
|
||||||
if Some(hash_algorithm) != algorithm {
|
if Some(hash_algorithm) != algorithm {
|
||||||
return Err(type_error(format!(
|
return Err(KeyObjectHandlePrehashedSignAndVerifyError::PrivateKeyDisallowsUsage {
|
||||||
"private key does not allow {} to be used, expected {}",
|
actual: digest_type.to_string(),
|
||||||
digest_type, hash_algorithm.as_str()
|
expected: hash_algorithm.as_str().to_string(),
|
||||||
)));
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(salt_length) = salt_length {
|
if let Some(salt_length) = salt_length {
|
||||||
|
@ -109,15 +145,12 @@ impl KeyObjectHandle {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
return Err(type_error(format!(
|
return Err(KeyObjectHandlePrehashedSignAndVerifyError::DigestNotAllowedForRsaPssSignature(digest_type.to_string()));
|
||||||
"digest not allowed for RSA-PSS signature: {}",
|
|
||||||
digest_type
|
|
||||||
)))
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
let signature = pss
|
let signature = pss
|
||||||
.sign(Some(&mut OsRng), &key.key, digest)
|
.sign(Some(&mut OsRng), &key.key, digest)
|
||||||
.map_err(|_| generic_error("failed to sign digest with RSA-PSS"))?;
|
.map_err(|_| KeyObjectHandlePrehashedSignAndVerifyError::FailedToSignDigestWithRsaPss)?;
|
||||||
Ok(signature.into())
|
Ok(signature.into())
|
||||||
}
|
}
|
||||||
AsymmetricPrivateKey::Dsa(key) => {
|
AsymmetricPrivateKey::Dsa(key) => {
|
||||||
|
@ -127,15 +160,12 @@ impl KeyObjectHandle {
|
||||||
key.sign_prehashed_rfc6979::<D>(digest)
|
key.sign_prehashed_rfc6979::<D>(digest)
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
return Err(type_error(format!(
|
return Err(KeyObjectHandlePrehashedSignAndVerifyError::DigestNotAllowedForRsaSignature(digest_type.to_string()))
|
||||||
"digest not allowed for RSA signature: {}",
|
|
||||||
digest_type
|
|
||||||
)))
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
let signature =
|
let signature =
|
||||||
res.map_err(|_| generic_error("failed to sign digest with DSA"))?;
|
res.map_err(|_| KeyObjectHandlePrehashedSignAndVerifyError::FailedToSignDigestWithDsa)?;
|
||||||
Ok(signature.into())
|
Ok(signature.into())
|
||||||
}
|
}
|
||||||
AsymmetricPrivateKey::Ec(key) => match key {
|
AsymmetricPrivateKey::Ec(key) => match key {
|
||||||
|
@ -143,7 +173,7 @@ impl KeyObjectHandle {
|
||||||
let signing_key = p224::ecdsa::SigningKey::from(key);
|
let signing_key = p224::ecdsa::SigningKey::from(key);
|
||||||
let signature: p224::ecdsa::Signature = signing_key
|
let signature: p224::ecdsa::Signature = signing_key
|
||||||
.sign_prehash(digest)
|
.sign_prehash(digest)
|
||||||
.map_err(|_| type_error("failed to sign digest"))?;
|
.map_err(|_| KeyObjectHandlePrehashedSignAndVerifyError::FailedToSignDigest)?;
|
||||||
|
|
||||||
dsa_signature(dsa_signature_encoding, signature)
|
dsa_signature(dsa_signature_encoding, signature)
|
||||||
}
|
}
|
||||||
|
@ -151,7 +181,7 @@ impl KeyObjectHandle {
|
||||||
let signing_key = p256::ecdsa::SigningKey::from(key);
|
let signing_key = p256::ecdsa::SigningKey::from(key);
|
||||||
let signature: p256::ecdsa::Signature = signing_key
|
let signature: p256::ecdsa::Signature = signing_key
|
||||||
.sign_prehash(digest)
|
.sign_prehash(digest)
|
||||||
.map_err(|_| type_error("failed to sign digest"))?;
|
.map_err(|_| KeyObjectHandlePrehashedSignAndVerifyError::FailedToSignDigest)?;
|
||||||
|
|
||||||
dsa_signature(dsa_signature_encoding, signature)
|
dsa_signature(dsa_signature_encoding, signature)
|
||||||
}
|
}
|
||||||
|
@ -159,19 +189,17 @@ impl KeyObjectHandle {
|
||||||
let signing_key = p384::ecdsa::SigningKey::from(key);
|
let signing_key = p384::ecdsa::SigningKey::from(key);
|
||||||
let signature: p384::ecdsa::Signature = signing_key
|
let signature: p384::ecdsa::Signature = signing_key
|
||||||
.sign_prehash(digest)
|
.sign_prehash(digest)
|
||||||
.map_err(|_| type_error("failed to sign digest"))?;
|
.map_err(|_| KeyObjectHandlePrehashedSignAndVerifyError::FailedToSignDigest)?;
|
||||||
|
|
||||||
dsa_signature(dsa_signature_encoding, signature)
|
dsa_signature(dsa_signature_encoding, signature)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
AsymmetricPrivateKey::X25519(_) => {
|
AsymmetricPrivateKey::X25519(_) => {
|
||||||
Err(type_error("x25519 key cannot be used for signing"))
|
Err(KeyObjectHandlePrehashedSignAndVerifyError::X25519KeyCannotBeUsedForSigning)
|
||||||
}
|
}
|
||||||
AsymmetricPrivateKey::Ed25519(_) => Err(type_error(
|
AsymmetricPrivateKey::Ed25519(_) => Err(KeyObjectHandlePrehashedSignAndVerifyError::Ed25519KeyCannotBeUsedForPrehashedSigning),
|
||||||
"Ed25519 key cannot be used for prehashed signing",
|
|
||||||
)),
|
|
||||||
AsymmetricPrivateKey::Dh(_) => {
|
AsymmetricPrivateKey::Dh(_) => {
|
||||||
Err(type_error("DH key cannot be used for signing"))
|
Err(KeyObjectHandlePrehashedSignAndVerifyError::DhKeyCannotBeUsedForSigning)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -183,10 +211,10 @@ impl KeyObjectHandle {
|
||||||
signature: &[u8],
|
signature: &[u8],
|
||||||
pss_salt_length: Option<u32>,
|
pss_salt_length: Option<u32>,
|
||||||
dsa_signature_encoding: u32,
|
dsa_signature_encoding: u32,
|
||||||
) -> Result<bool, AnyError> {
|
) -> Result<bool, KeyObjectHandlePrehashedSignAndVerifyError> {
|
||||||
let public_key = self
|
let public_key = self.as_public_key().ok_or(
|
||||||
.as_public_key()
|
KeyObjectHandlePrehashedSignAndVerifyError::KeyIsNotPublicOrPrivate,
|
||||||
.ok_or_else(|| type_error("key is not a public or private key"))?;
|
)?;
|
||||||
|
|
||||||
match &*public_key {
|
match &*public_key {
|
||||||
AsymmetricPublicKey::Rsa(key) => {
|
AsymmetricPublicKey::Rsa(key) => {
|
||||||
|
@ -199,10 +227,7 @@ impl KeyObjectHandle {
|
||||||
rsa::pkcs1v15::Pkcs1v15Sign::new::<D>()
|
rsa::pkcs1v15::Pkcs1v15Sign::new::<D>()
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
return Err(type_error(format!(
|
return Err(KeyObjectHandlePrehashedSignAndVerifyError::DigestNotAllowedForRsaSignature(digest_type.to_string()))
|
||||||
"digest not allowed for RSA signature: {}",
|
|
||||||
digest_type
|
|
||||||
)))
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
@ -214,9 +239,7 @@ impl KeyObjectHandle {
|
||||||
let mut salt_length = None;
|
let mut salt_length = None;
|
||||||
if let Some(details) = &key.details {
|
if let Some(details) = &key.details {
|
||||||
if details.hash_algorithm != details.mf1_hash_algorithm {
|
if details.hash_algorithm != details.mf1_hash_algorithm {
|
||||||
return Err(type_error(
|
return Err(KeyObjectHandlePrehashedSignAndVerifyError::RsaPssHashAlgorithmUnsupported);
|
||||||
"rsa-pss with different mf1 hash algorithm and hash algorithm is not supported",
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
hash_algorithm = Some(details.hash_algorithm);
|
hash_algorithm = Some(details.hash_algorithm);
|
||||||
salt_length = Some(details.salt_length as usize);
|
salt_length = Some(details.salt_length as usize);
|
||||||
|
@ -229,10 +252,10 @@ impl KeyObjectHandle {
|
||||||
fn <D>(algorithm: Option<RsaPssHashAlgorithm>) {
|
fn <D>(algorithm: Option<RsaPssHashAlgorithm>) {
|
||||||
if let Some(hash_algorithm) = hash_algorithm.take() {
|
if let Some(hash_algorithm) = hash_algorithm.take() {
|
||||||
if Some(hash_algorithm) != algorithm {
|
if Some(hash_algorithm) != algorithm {
|
||||||
return Err(type_error(format!(
|
return Err(KeyObjectHandlePrehashedSignAndVerifyError::PrivateKeyDisallowsUsage {
|
||||||
"private key does not allow {} to be used, expected {}",
|
actual: digest_type.to_string(),
|
||||||
digest_type, hash_algorithm.as_str()
|
expected: hash_algorithm.as_str().to_string(),
|
||||||
)));
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(salt_length) = salt_length {
|
if let Some(salt_length) = salt_length {
|
||||||
|
@ -242,17 +265,14 @@ impl KeyObjectHandle {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
return Err(type_error(format!(
|
return Err(KeyObjectHandlePrehashedSignAndVerifyError::DigestNotAllowedForRsaPssSignature(digest_type.to_string()));
|
||||||
"digest not allowed for RSA-PSS signature: {}",
|
|
||||||
digest_type
|
|
||||||
)))
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
Ok(pss.verify(&key.key, digest, signature).is_ok())
|
Ok(pss.verify(&key.key, digest, signature).is_ok())
|
||||||
}
|
}
|
||||||
AsymmetricPublicKey::Dsa(key) => {
|
AsymmetricPublicKey::Dsa(key) => {
|
||||||
let signature = dsa::Signature::from_der(signature)
|
let signature = dsa::Signature::from_der(signature)
|
||||||
.map_err(|_| type_error("Invalid DSA signature"))?;
|
.map_err(|_| KeyObjectHandlePrehashedSignAndVerifyError::InvalidDsaSignature)?;
|
||||||
Ok(key.verify_prehash(digest, &signature).is_ok())
|
Ok(key.verify_prehash(digest, &signature).is_ok())
|
||||||
}
|
}
|
||||||
AsymmetricPublicKey::Ec(key) => match key {
|
AsymmetricPublicKey::Ec(key) => match key {
|
||||||
|
@ -294,13 +314,11 @@ impl KeyObjectHandle {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
AsymmetricPublicKey::X25519(_) => {
|
AsymmetricPublicKey::X25519(_) => {
|
||||||
Err(type_error("x25519 key cannot be used for verification"))
|
Err(KeyObjectHandlePrehashedSignAndVerifyError::X25519KeyCannotBeUsedForVerification)
|
||||||
}
|
}
|
||||||
AsymmetricPublicKey::Ed25519(_) => Err(type_error(
|
AsymmetricPublicKey::Ed25519(_) => Err(KeyObjectHandlePrehashedSignAndVerifyError::Ed25519KeyCannotBeUsedForPrehashedVerification),
|
||||||
"Ed25519 key cannot be used for prehashed verification",
|
|
||||||
)),
|
|
||||||
AsymmetricPublicKey::Dh(_) => {
|
AsymmetricPublicKey::Dh(_) => {
|
||||||
Err(type_error("DH key cannot be used for verification"))
|
Err(KeyObjectHandlePrehashedSignAndVerifyError::DhKeyCannotBeUsedForVerification)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
use deno_core::error::AnyError;
|
|
||||||
use deno_core::op2;
|
use deno_core::op2;
|
||||||
|
|
||||||
use x509_parser::der_parser::asn1_rs::Any;
|
use x509_parser::der_parser::asn1_rs::Any;
|
||||||
use x509_parser::der_parser::asn1_rs::Tag;
|
use x509_parser::der_parser::asn1_rs::Tag;
|
||||||
use x509_parser::der_parser::oid::Oid;
|
use x509_parser::der_parser::oid::Oid;
|
||||||
|
pub use x509_parser::error::X509Error;
|
||||||
use x509_parser::extensions;
|
use x509_parser::extensions;
|
||||||
use x509_parser::pem;
|
use x509_parser::pem;
|
||||||
use x509_parser::prelude::*;
|
use x509_parser::prelude::*;
|
||||||
|
@ -65,7 +65,7 @@ impl<'a> Deref for CertificateView<'a> {
|
||||||
#[cppgc]
|
#[cppgc]
|
||||||
pub fn op_node_x509_parse(
|
pub fn op_node_x509_parse(
|
||||||
#[buffer] buf: &[u8],
|
#[buffer] buf: &[u8],
|
||||||
) -> Result<Certificate, AnyError> {
|
) -> Result<Certificate, X509Error> {
|
||||||
let source = match pem::parse_x509_pem(buf) {
|
let source = match pem::parse_x509_pem(buf) {
|
||||||
Ok((_, pem)) => CertificateSources::Pem(pem),
|
Ok((_, pem)) => CertificateSources::Pem(pem),
|
||||||
Err(_) => CertificateSources::Der(buf.to_vec().into_boxed_slice()),
|
Err(_) => CertificateSources::Der(buf.to_vec().into_boxed_slice()),
|
||||||
|
@ -81,7 +81,7 @@ pub fn op_node_x509_parse(
|
||||||
X509Certificate::from_der(buf).map(|(_, cert)| cert)?
|
X509Certificate::from_der(buf).map(|(_, cert)| cert)?
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Ok::<_, AnyError>(CertificateView { cert })
|
Ok::<_, X509Error>(CertificateView { cert })
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
@ -89,23 +89,23 @@ pub fn op_node_x509_parse(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[op2(fast)]
|
#[op2(fast)]
|
||||||
pub fn op_node_x509_ca(#[cppgc] cert: &Certificate) -> Result<bool, AnyError> {
|
pub fn op_node_x509_ca(#[cppgc] cert: &Certificate) -> bool {
|
||||||
let cert = cert.inner.get().deref();
|
let cert = cert.inner.get().deref();
|
||||||
Ok(cert.is_ca())
|
cert.is_ca()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[op2(fast)]
|
#[op2(fast)]
|
||||||
pub fn op_node_x509_check_email(
|
pub fn op_node_x509_check_email(
|
||||||
#[cppgc] cert: &Certificate,
|
#[cppgc] cert: &Certificate,
|
||||||
#[string] email: &str,
|
#[string] email: &str,
|
||||||
) -> Result<bool, AnyError> {
|
) -> bool {
|
||||||
let cert = cert.inner.get().deref();
|
let cert = cert.inner.get().deref();
|
||||||
let subject = cert.subject();
|
let subject = cert.subject();
|
||||||
if subject
|
if subject
|
||||||
.iter_email()
|
.iter_email()
|
||||||
.any(|e| e.as_str().unwrap_or("") == email)
|
.any(|e| e.as_str().unwrap_or("") == email)
|
||||||
{
|
{
|
||||||
return Ok(true);
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
let subject_alt = cert
|
let subject_alt = cert
|
||||||
|
@ -121,62 +121,60 @@ pub fn op_node_x509_check_email(
|
||||||
for name in &subject_alt.general_names {
|
for name in &subject_alt.general_names {
|
||||||
if let extensions::GeneralName::RFC822Name(n) = name {
|
if let extensions::GeneralName::RFC822Name(n) = name {
|
||||||
if *n == email {
|
if *n == email {
|
||||||
return Ok(true);
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(false)
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
#[op2]
|
#[op2]
|
||||||
#[string]
|
#[string]
|
||||||
pub fn op_node_x509_fingerprint(
|
pub fn op_node_x509_fingerprint(#[cppgc] cert: &Certificate) -> Option<String> {
|
||||||
#[cppgc] cert: &Certificate,
|
cert.fingerprint::<sha1::Sha1>()
|
||||||
) -> Result<Option<String>, AnyError> {
|
|
||||||
Ok(cert.fingerprint::<sha1::Sha1>())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[op2]
|
#[op2]
|
||||||
#[string]
|
#[string]
|
||||||
pub fn op_node_x509_fingerprint256(
|
pub fn op_node_x509_fingerprint256(
|
||||||
#[cppgc] cert: &Certificate,
|
#[cppgc] cert: &Certificate,
|
||||||
) -> Result<Option<String>, AnyError> {
|
) -> Option<String> {
|
||||||
Ok(cert.fingerprint::<sha2::Sha256>())
|
cert.fingerprint::<sha2::Sha256>()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[op2]
|
#[op2]
|
||||||
#[string]
|
#[string]
|
||||||
pub fn op_node_x509_fingerprint512(
|
pub fn op_node_x509_fingerprint512(
|
||||||
#[cppgc] cert: &Certificate,
|
#[cppgc] cert: &Certificate,
|
||||||
) -> Result<Option<String>, AnyError> {
|
) -> Option<String> {
|
||||||
Ok(cert.fingerprint::<sha2::Sha512>())
|
cert.fingerprint::<sha2::Sha512>()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[op2]
|
#[op2]
|
||||||
#[string]
|
#[string]
|
||||||
pub fn op_node_x509_get_issuer(
|
pub fn op_node_x509_get_issuer(
|
||||||
#[cppgc] cert: &Certificate,
|
#[cppgc] cert: &Certificate,
|
||||||
) -> Result<String, AnyError> {
|
) -> Result<String, X509Error> {
|
||||||
let cert = cert.inner.get().deref();
|
let cert = cert.inner.get().deref();
|
||||||
Ok(x509name_to_string(cert.issuer(), oid_registry())?)
|
x509name_to_string(cert.issuer(), oid_registry())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[op2]
|
#[op2]
|
||||||
#[string]
|
#[string]
|
||||||
pub fn op_node_x509_get_subject(
|
pub fn op_node_x509_get_subject(
|
||||||
#[cppgc] cert: &Certificate,
|
#[cppgc] cert: &Certificate,
|
||||||
) -> Result<String, AnyError> {
|
) -> Result<String, X509Error> {
|
||||||
let cert = cert.inner.get().deref();
|
let cert = cert.inner.get().deref();
|
||||||
Ok(x509name_to_string(cert.subject(), oid_registry())?)
|
x509name_to_string(cert.subject(), oid_registry())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[op2]
|
#[op2]
|
||||||
#[cppgc]
|
#[cppgc]
|
||||||
pub fn op_node_x509_public_key(
|
pub fn op_node_x509_public_key(
|
||||||
#[cppgc] cert: &Certificate,
|
#[cppgc] cert: &Certificate,
|
||||||
) -> Result<KeyObjectHandle, AnyError> {
|
) -> Result<KeyObjectHandle, super::keys::X509PublicKeyError> {
|
||||||
let cert = cert.inner.get().deref();
|
let cert = cert.inner.get().deref();
|
||||||
let public_key = &cert.tbs_certificate.subject_pki;
|
let public_key = &cert.tbs_certificate.subject_pki;
|
||||||
|
|
||||||
|
@ -245,37 +243,29 @@ fn x509name_to_string(
|
||||||
|
|
||||||
#[op2]
|
#[op2]
|
||||||
#[string]
|
#[string]
|
||||||
pub fn op_node_x509_get_valid_from(
|
pub fn op_node_x509_get_valid_from(#[cppgc] cert: &Certificate) -> String {
|
||||||
#[cppgc] cert: &Certificate,
|
|
||||||
) -> Result<String, AnyError> {
|
|
||||||
let cert = cert.inner.get().deref();
|
let cert = cert.inner.get().deref();
|
||||||
Ok(cert.validity().not_before.to_string())
|
cert.validity().not_before.to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[op2]
|
#[op2]
|
||||||
#[string]
|
#[string]
|
||||||
pub fn op_node_x509_get_valid_to(
|
pub fn op_node_x509_get_valid_to(#[cppgc] cert: &Certificate) -> String {
|
||||||
#[cppgc] cert: &Certificate,
|
|
||||||
) -> Result<String, AnyError> {
|
|
||||||
let cert = cert.inner.get().deref();
|
let cert = cert.inner.get().deref();
|
||||||
Ok(cert.validity().not_after.to_string())
|
cert.validity().not_after.to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[op2]
|
#[op2]
|
||||||
#[string]
|
#[string]
|
||||||
pub fn op_node_x509_get_serial_number(
|
pub fn op_node_x509_get_serial_number(#[cppgc] cert: &Certificate) -> String {
|
||||||
#[cppgc] cert: &Certificate,
|
|
||||||
) -> Result<String, AnyError> {
|
|
||||||
let cert = cert.inner.get().deref();
|
let cert = cert.inner.get().deref();
|
||||||
let mut s = cert.serial.to_str_radix(16);
|
let mut s = cert.serial.to_str_radix(16);
|
||||||
s.make_ascii_uppercase();
|
s.make_ascii_uppercase();
|
||||||
Ok(s)
|
s
|
||||||
}
|
}
|
||||||
|
|
||||||
#[op2(fast)]
|
#[op2(fast)]
|
||||||
pub fn op_node_x509_key_usage(
|
pub fn op_node_x509_key_usage(#[cppgc] cert: &Certificate) -> u16 {
|
||||||
#[cppgc] cert: &Certificate,
|
|
||||||
) -> Result<u16, AnyError> {
|
|
||||||
let cert = cert.inner.get().deref();
|
let cert = cert.inner.get().deref();
|
||||||
let key_usage = cert
|
let key_usage = cert
|
||||||
.extensions()
|
.extensions()
|
||||||
|
@ -286,5 +276,5 @@ pub fn op_node_x509_key_usage(
|
||||||
_ => None,
|
_ => None,
|
||||||
});
|
});
|
||||||
|
|
||||||
Ok(key_usage.map(|k| k.flags).unwrap_or(0))
|
key_usage.map(|k| k.flags).unwrap_or(0)
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ use crate::NodePermissions;
|
||||||
#[derive(Debug, thiserror::Error)]
|
#[derive(Debug, thiserror::Error)]
|
||||||
pub enum FsError {
|
pub enum FsError {
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Permission(deno_core::error::AnyError),
|
Permission(#[from] deno_permissions::PermissionCheckError),
|
||||||
#[error("{0}")]
|
#[error("{0}")]
|
||||||
Io(#[from] std::io::Error),
|
Io(#[from] std::io::Error),
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
|
@ -53,8 +53,7 @@ where
|
||||||
let mut state = state.borrow_mut();
|
let mut state = state.borrow_mut();
|
||||||
let path = state
|
let path = state
|
||||||
.borrow_mut::<P>()
|
.borrow_mut::<P>()
|
||||||
.check_read_with_api_name(&path, Some("node:fs.exists()"))
|
.check_read_with_api_name(&path, Some("node:fs.exists()"))?;
|
||||||
.map_err(FsError::Permission)?;
|
|
||||||
(state.borrow::<FileSystemRc>().clone(), path)
|
(state.borrow::<FileSystemRc>().clone(), path)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -72,12 +71,10 @@ where
|
||||||
{
|
{
|
||||||
let path = state
|
let path = state
|
||||||
.borrow_mut::<P>()
|
.borrow_mut::<P>()
|
||||||
.check_read_with_api_name(path, Some("node:fs.cpSync"))
|
.check_read_with_api_name(path, Some("node:fs.cpSync"))?;
|
||||||
.map_err(FsError::Permission)?;
|
|
||||||
let new_path = state
|
let new_path = state
|
||||||
.borrow_mut::<P>()
|
.borrow_mut::<P>()
|
||||||
.check_write_with_api_name(new_path, Some("node:fs.cpSync"))
|
.check_write_with_api_name(new_path, Some("node:fs.cpSync"))?;
|
||||||
.map_err(FsError::Permission)?;
|
|
||||||
|
|
||||||
let fs = state.borrow::<FileSystemRc>();
|
let fs = state.borrow::<FileSystemRc>();
|
||||||
fs.cp_sync(&path, &new_path)?;
|
fs.cp_sync(&path, &new_path)?;
|
||||||
|
@ -97,12 +94,10 @@ where
|
||||||
let mut state = state.borrow_mut();
|
let mut state = state.borrow_mut();
|
||||||
let path = state
|
let path = state
|
||||||
.borrow_mut::<P>()
|
.borrow_mut::<P>()
|
||||||
.check_read_with_api_name(&path, Some("node:fs.cpSync"))
|
.check_read_with_api_name(&path, Some("node:fs.cpSync"))?;
|
||||||
.map_err(FsError::Permission)?;
|
|
||||||
let new_path = state
|
let new_path = state
|
||||||
.borrow_mut::<P>()
|
.borrow_mut::<P>()
|
||||||
.check_write_with_api_name(&new_path, Some("node:fs.cpSync"))
|
.check_write_with_api_name(&new_path, Some("node:fs.cpSync"))?;
|
||||||
.map_err(FsError::Permission)?;
|
|
||||||
(state.borrow::<FileSystemRc>().clone(), path, new_path)
|
(state.borrow::<FileSystemRc>().clone(), path, new_path)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -136,12 +131,10 @@ where
|
||||||
let mut state = state.borrow_mut();
|
let mut state = state.borrow_mut();
|
||||||
let path = state
|
let path = state
|
||||||
.borrow_mut::<P>()
|
.borrow_mut::<P>()
|
||||||
.check_read_with_api_name(&path, Some("node:fs.statfs"))
|
.check_read_with_api_name(&path, Some("node:fs.statfs"))?;
|
||||||
.map_err(FsError::Permission)?;
|
|
||||||
state
|
state
|
||||||
.borrow_mut::<P>()
|
.borrow_mut::<P>()
|
||||||
.check_sys("statfs", "node:fs.statfs")
|
.check_sys("statfs", "node:fs.statfs")?;
|
||||||
.map_err(FsError::Permission)?;
|
|
||||||
path
|
path
|
||||||
};
|
};
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
|
@ -279,8 +272,7 @@ where
|
||||||
{
|
{
|
||||||
let path = state
|
let path = state
|
||||||
.borrow_mut::<P>()
|
.borrow_mut::<P>()
|
||||||
.check_write_with_api_name(path, Some("node:fs.lutimes"))
|
.check_write_with_api_name(path, Some("node:fs.lutimes"))?;
|
||||||
.map_err(FsError::Permission)?;
|
|
||||||
|
|
||||||
let fs = state.borrow::<FileSystemRc>();
|
let fs = state.borrow::<FileSystemRc>();
|
||||||
fs.lutime_sync(&path, atime_secs, atime_nanos, mtime_secs, mtime_nanos)?;
|
fs.lutime_sync(&path, atime_secs, atime_nanos, mtime_secs, mtime_nanos)?;
|
||||||
|
@ -303,8 +295,7 @@ where
|
||||||
let mut state = state.borrow_mut();
|
let mut state = state.borrow_mut();
|
||||||
let path = state
|
let path = state
|
||||||
.borrow_mut::<P>()
|
.borrow_mut::<P>()
|
||||||
.check_write_with_api_name(&path, Some("node:fs.lutimesSync"))
|
.check_write_with_api_name(&path, Some("node:fs.lutimesSync"))?;
|
||||||
.map_err(FsError::Permission)?;
|
|
||||||
(state.borrow::<FileSystemRc>().clone(), path)
|
(state.borrow::<FileSystemRc>().clone(), path)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -326,8 +317,7 @@ where
|
||||||
{
|
{
|
||||||
let path = state
|
let path = state
|
||||||
.borrow_mut::<P>()
|
.borrow_mut::<P>()
|
||||||
.check_write_with_api_name(&path, Some("node:fs.lchownSync"))
|
.check_write_with_api_name(&path, Some("node:fs.lchownSync"))?;
|
||||||
.map_err(FsError::Permission)?;
|
|
||||||
let fs = state.borrow::<FileSystemRc>();
|
let fs = state.borrow::<FileSystemRc>();
|
||||||
fs.lchown_sync(&path, uid, gid)?;
|
fs.lchown_sync(&path, uid, gid)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -347,8 +337,7 @@ where
|
||||||
let mut state = state.borrow_mut();
|
let mut state = state.borrow_mut();
|
||||||
let path = state
|
let path = state
|
||||||
.borrow_mut::<P>()
|
.borrow_mut::<P>()
|
||||||
.check_write_with_api_name(&path, Some("node:fs.lchown"))
|
.check_write_with_api_name(&path, Some("node:fs.lchown"))?;
|
||||||
.map_err(FsError::Permission)?;
|
|
||||||
(state.borrow::<FileSystemRc>().clone(), path)
|
(state.borrow::<FileSystemRc>().clone(), path)
|
||||||
};
|
};
|
||||||
fs.lchown_async(path, uid, gid).await?;
|
fs.lchown_async(path, uid, gid).await?;
|
||||||
|
|
|
@ -78,9 +78,7 @@ where
|
||||||
|
|
||||||
{
|
{
|
||||||
let permissions = state.borrow_mut::<P>();
|
let permissions = state.borrow_mut::<P>();
|
||||||
permissions
|
permissions.check_net_url(&url, "ClientRequest")?;
|
||||||
.check_net_url(&url, "ClientRequest")
|
|
||||||
.map_err(FetchError::Permission)?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut header_map = HeaderMap::new();
|
let mut header_map = HeaderMap::new();
|
||||||
|
|
161
ext/node/ops/inspector.rs
Normal file
161
ext/node/ops/inspector.rs
Normal file
|
@ -0,0 +1,161 @@
|
||||||
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
|
use crate::NodePermissions;
|
||||||
|
use deno_core::anyhow::Error;
|
||||||
|
use deno_core::error::generic_error;
|
||||||
|
use deno_core::futures::channel::mpsc;
|
||||||
|
use deno_core::op2;
|
||||||
|
use deno_core::v8;
|
||||||
|
use deno_core::GarbageCollected;
|
||||||
|
use deno_core::InspectorSessionKind;
|
||||||
|
use deno_core::InspectorSessionOptions;
|
||||||
|
use deno_core::JsRuntimeInspector;
|
||||||
|
use deno_core::OpState;
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
#[op2(fast)]
|
||||||
|
pub fn op_inspector_enabled() -> bool {
|
||||||
|
// TODO: hook up to InspectorServer
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
#[op2]
|
||||||
|
pub fn op_inspector_open<P>(
|
||||||
|
_state: &mut OpState,
|
||||||
|
_port: Option<u16>,
|
||||||
|
#[string] _host: Option<String>,
|
||||||
|
) -> Result<(), Error>
|
||||||
|
where
|
||||||
|
P: NodePermissions + 'static,
|
||||||
|
{
|
||||||
|
// TODO: hook up to InspectorServer
|
||||||
|
/*
|
||||||
|
let server = state.borrow_mut::<InspectorServer>();
|
||||||
|
if let Some(host) = host {
|
||||||
|
server.set_host(host);
|
||||||
|
}
|
||||||
|
if let Some(port) = port {
|
||||||
|
server.set_port(port);
|
||||||
|
}
|
||||||
|
state
|
||||||
|
.borrow_mut::<P>()
|
||||||
|
.check_net((server.host(), Some(server.port())), "inspector.open")?;
|
||||||
|
*/
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[op2(fast)]
|
||||||
|
pub fn op_inspector_close() {
|
||||||
|
// TODO: hook up to InspectorServer
|
||||||
|
}
|
||||||
|
|
||||||
|
#[op2]
|
||||||
|
#[string]
|
||||||
|
pub fn op_inspector_url() -> Option<String> {
|
||||||
|
// TODO: hook up to InspectorServer
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
#[op2(fast)]
|
||||||
|
pub fn op_inspector_wait(state: &OpState) -> bool {
|
||||||
|
match state.try_borrow::<Rc<RefCell<JsRuntimeInspector>>>() {
|
||||||
|
Some(inspector) => {
|
||||||
|
inspector
|
||||||
|
.borrow_mut()
|
||||||
|
.wait_for_session_and_break_on_next_statement();
|
||||||
|
true
|
||||||
|
}
|
||||||
|
None => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[op2(fast)]
|
||||||
|
pub fn op_inspector_emit_protocol_event(
|
||||||
|
#[string] _event_name: String,
|
||||||
|
#[string] _params: String,
|
||||||
|
) {
|
||||||
|
// TODO: inspector channel & protocol notifications
|
||||||
|
}
|
||||||
|
|
||||||
|
struct JSInspectorSession {
|
||||||
|
tx: RefCell<Option<mpsc::UnboundedSender<String>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GarbageCollected for JSInspectorSession {}
|
||||||
|
|
||||||
|
#[op2]
|
||||||
|
#[cppgc]
|
||||||
|
pub fn op_inspector_connect<'s, P>(
|
||||||
|
isolate: *mut v8::Isolate,
|
||||||
|
scope: &mut v8::HandleScope<'s>,
|
||||||
|
state: &mut OpState,
|
||||||
|
connect_to_main_thread: bool,
|
||||||
|
callback: v8::Local<'s, v8::Function>,
|
||||||
|
) -> Result<JSInspectorSession, Error>
|
||||||
|
where
|
||||||
|
P: NodePermissions + 'static,
|
||||||
|
{
|
||||||
|
state
|
||||||
|
.borrow_mut::<P>()
|
||||||
|
.check_sys("inspector", "inspector.Session.connect")?;
|
||||||
|
|
||||||
|
if connect_to_main_thread {
|
||||||
|
return Err(generic_error("connectToMainThread not supported"));
|
||||||
|
}
|
||||||
|
|
||||||
|
let context = scope.get_current_context();
|
||||||
|
let context = v8::Global::new(scope, context);
|
||||||
|
let callback = v8::Global::new(scope, callback);
|
||||||
|
|
||||||
|
let inspector = state
|
||||||
|
.borrow::<Rc<RefCell<JsRuntimeInspector>>>()
|
||||||
|
.borrow_mut();
|
||||||
|
|
||||||
|
let tx = inspector.create_raw_session(
|
||||||
|
InspectorSessionOptions {
|
||||||
|
kind: InspectorSessionKind::NonBlocking {
|
||||||
|
wait_for_disconnect: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// The inspector connection does not keep the event loop alive but
|
||||||
|
// when the inspector sends a message to the frontend, the JS that
|
||||||
|
// that runs may keep the event loop alive so we have to call back
|
||||||
|
// synchronously, instead of using the usual LocalInspectorSession
|
||||||
|
// UnboundedReceiver<InspectorMsg> API.
|
||||||
|
Box::new(move |message| {
|
||||||
|
// SAFETY: This function is called directly by the inspector, so
|
||||||
|
// 1) The isolate is still valid
|
||||||
|
// 2) We are on the same thread as the Isolate
|
||||||
|
let scope = unsafe { &mut v8::CallbackScope::new(&mut *isolate) };
|
||||||
|
let context = v8::Local::new(scope, context.clone());
|
||||||
|
let scope = &mut v8::ContextScope::new(scope, context);
|
||||||
|
let scope = &mut v8::TryCatch::new(scope);
|
||||||
|
let recv = v8::undefined(scope);
|
||||||
|
if let Some(message) = v8::String::new(scope, &message.content) {
|
||||||
|
let callback = v8::Local::new(scope, callback.clone());
|
||||||
|
callback.call(scope, recv.into(), &[message.into()]);
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(JSInspectorSession {
|
||||||
|
tx: RefCell::new(Some(tx)),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[op2(fast)]
|
||||||
|
pub fn op_inspector_dispatch(
|
||||||
|
#[cppgc] session: &JSInspectorSession,
|
||||||
|
#[string] message: String,
|
||||||
|
) {
|
||||||
|
if let Some(tx) = &*session.tx.borrow() {
|
||||||
|
let _ = tx.unbounded_send(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[op2(fast)]
|
||||||
|
pub fn op_inspector_disconnect(#[cppgc] session: &JSInspectorSession) {
|
||||||
|
drop(session.tx.borrow_mut().take());
|
||||||
|
}
|
|
@ -7,6 +7,7 @@ pub mod fs;
|
||||||
pub mod http;
|
pub mod http;
|
||||||
pub mod http2;
|
pub mod http2;
|
||||||
pub mod idna;
|
pub mod idna;
|
||||||
|
pub mod inspector;
|
||||||
pub mod ipc;
|
pub mod ipc;
|
||||||
pub mod os;
|
pub mod os;
|
||||||
pub mod process;
|
pub mod process;
|
||||||
|
|
|
@ -14,7 +14,7 @@ pub enum OsError {
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Priority(priority::PriorityError),
|
Priority(priority::PriorityError),
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Permission(deno_core::error::AnyError),
|
Permission(#[from] deno_permissions::PermissionCheckError),
|
||||||
#[error("Failed to get cpu info")]
|
#[error("Failed to get cpu info")]
|
||||||
FailedToGetCpuInfo,
|
FailedToGetCpuInfo,
|
||||||
#[error("Failed to get user info")]
|
#[error("Failed to get user info")]
|
||||||
|
@ -31,9 +31,7 @@ where
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
let permissions = state.borrow_mut::<P>();
|
let permissions = state.borrow_mut::<P>();
|
||||||
permissions
|
permissions.check_sys("getPriority", "node:os.getPriority()")?;
|
||||||
.check_sys("getPriority", "node:os.getPriority()")
|
|
||||||
.map_err(OsError::Permission)?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
priority::get_priority(pid).map_err(OsError::Priority)
|
priority::get_priority(pid).map_err(OsError::Priority)
|
||||||
|
@ -50,9 +48,7 @@ where
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
let permissions = state.borrow_mut::<P>();
|
let permissions = state.borrow_mut::<P>();
|
||||||
permissions
|
permissions.check_sys("setPriority", "node:os.setPriority()")?;
|
||||||
.check_sys("setPriority", "node:os.setPriority()")
|
|
||||||
.map_err(OsError::Permission)?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
priority::set_priority(pid, priority).map_err(OsError::Priority)
|
priority::set_priority(pid, priority).map_err(OsError::Priority)
|
||||||
|
@ -266,9 +262,7 @@ where
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
let permissions = state.borrow_mut::<P>();
|
let permissions = state.borrow_mut::<P>();
|
||||||
permissions
|
permissions.check_sys("cpus", "node:os.cpus()")?;
|
||||||
.check_sys("cpus", "node:os.cpus()")
|
|
||||||
.map_err(OsError::Permission)?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cpus::cpu_info().ok_or(OsError::FailedToGetCpuInfo)
|
cpus::cpu_info().ok_or(OsError::FailedToGetCpuInfo)
|
||||||
|
|
|
@ -1312,6 +1312,8 @@ export function findSourceMap(_path) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Module.findSourceMap = findSourceMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string | URL} _specifier
|
* @param {string | URL} _specifier
|
||||||
* @param {string | URL} _parentUrl
|
* @param {string | URL} _parentUrl
|
||||||
|
|
|
@ -20,6 +20,7 @@ import {
|
||||||
notImplemented,
|
notImplemented,
|
||||||
TextEncodings,
|
TextEncodings,
|
||||||
} from "ext:deno_node/_utils.ts";
|
} from "ext:deno_node/_utils.ts";
|
||||||
|
import { type Buffer } from "node:buffer";
|
||||||
|
|
||||||
export type CallbackWithError = (err: ErrnoException | null) => void;
|
export type CallbackWithError = (err: ErrnoException | null) => void;
|
||||||
|
|
||||||
|
|
|
@ -147,8 +147,8 @@ export function open(
|
||||||
|
|
||||||
export function openPromise(
|
export function openPromise(
|
||||||
path: string | Buffer | URL,
|
path: string | Buffer | URL,
|
||||||
flags?: openFlags = "r",
|
flags: openFlags = "r",
|
||||||
mode? = 0o666,
|
mode = 0o666,
|
||||||
): Promise<FileHandle> {
|
): Promise<FileHandle> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
open(path, flags, mode, (err, fd) => {
|
open(path, flags, mode, (err, fd) => {
|
||||||
|
|
|
@ -15,6 +15,7 @@ import { maybeCallback } from "ext:deno_node/_fs/_fs_common.ts";
|
||||||
import { validateInteger } from "ext:deno_node/internal/validators.mjs";
|
import { validateInteger } from "ext:deno_node/internal/validators.mjs";
|
||||||
import * as io from "ext:deno_io/12_io.js";
|
import * as io from "ext:deno_io/12_io.js";
|
||||||
import { op_fs_seek_async, op_fs_seek_sync } from "ext:core/ops";
|
import { op_fs_seek_async, op_fs_seek_sync } from "ext:core/ops";
|
||||||
|
import process from "node:process";
|
||||||
|
|
||||||
type Callback = (
|
type Callback = (
|
||||||
err: ErrnoException | null,
|
err: ErrnoException | null,
|
||||||
|
|
|
@ -14,6 +14,7 @@ import { nextTick } from "ext:deno_node/_next_tick.ts";
|
||||||
import {
|
import {
|
||||||
isAnyArrayBuffer,
|
isAnyArrayBuffer,
|
||||||
isArrayBufferView,
|
isArrayBufferView,
|
||||||
|
isUint8Array,
|
||||||
} from "ext:deno_node/internal/util/types.ts";
|
} from "ext:deno_node/internal/util/types.ts";
|
||||||
|
|
||||||
var kRangeErrorMessage = "Cannot create final Buffer. It would be larger " +
|
var kRangeErrorMessage = "Cannot create final Buffer. It would be larger " +
|
||||||
|
@ -158,6 +159,12 @@ export const inflateRawSync = function (buffer, opts) {
|
||||||
function sanitizeInput(input) {
|
function sanitizeInput(input) {
|
||||||
if (typeof input === "string") input = Buffer.from(input);
|
if (typeof input === "string") input = Buffer.from(input);
|
||||||
|
|
||||||
|
if (isArrayBufferView(input) && !isUint8Array(input)) {
|
||||||
|
input = Buffer.from(input.buffer, input.byteOffset, input.byteLength);
|
||||||
|
} else if (isAnyArrayBuffer(input)) {
|
||||||
|
input = Buffer.from(input);
|
||||||
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
!Buffer.isBuffer(input) &&
|
!Buffer.isBuffer(input) &&
|
||||||
(input.buffer && !input.buffer.constructor === ArrayBuffer)
|
(input.buffer && !input.buffer.constructor === ArrayBuffer)
|
||||||
|
|
210
ext/node/polyfills/inspector.js
Normal file
210
ext/node/polyfills/inspector.js
Normal file
|
@ -0,0 +1,210 @@
|
||||||
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||||
|
// Copyright Joyent and Node contributors. All rights reserved. MIT license.
|
||||||
|
|
||||||
|
import process from "node:process";
|
||||||
|
import { EventEmitter } from "node:events";
|
||||||
|
import { primordials } from "ext:core/mod.js";
|
||||||
|
import {
|
||||||
|
op_get_extras_binding_object,
|
||||||
|
op_inspector_close,
|
||||||
|
op_inspector_connect,
|
||||||
|
op_inspector_disconnect,
|
||||||
|
op_inspector_dispatch,
|
||||||
|
op_inspector_emit_protocol_event,
|
||||||
|
op_inspector_enabled,
|
||||||
|
op_inspector_open,
|
||||||
|
op_inspector_url,
|
||||||
|
op_inspector_wait,
|
||||||
|
} from "ext:core/ops";
|
||||||
|
import {
|
||||||
|
isUint32,
|
||||||
|
validateFunction,
|
||||||
|
validateInt32,
|
||||||
|
validateObject,
|
||||||
|
validateString,
|
||||||
|
} from "ext:deno_node/internal/validators.mjs";
|
||||||
|
import {
|
||||||
|
ERR_INSPECTOR_ALREADY_ACTIVATED,
|
||||||
|
ERR_INSPECTOR_ALREADY_CONNECTED,
|
||||||
|
ERR_INSPECTOR_CLOSED,
|
||||||
|
ERR_INSPECTOR_COMMAND,
|
||||||
|
ERR_INSPECTOR_NOT_ACTIVE,
|
||||||
|
ERR_INSPECTOR_NOT_CONNECTED,
|
||||||
|
ERR_INSPECTOR_NOT_WORKER,
|
||||||
|
} from "ext:deno_node/internal/errors.ts";
|
||||||
|
|
||||||
|
const {
|
||||||
|
SymbolDispose,
|
||||||
|
JSONParse,
|
||||||
|
JSONStringify,
|
||||||
|
SafeMap,
|
||||||
|
} = primordials;
|
||||||
|
|
||||||
|
class Session extends EventEmitter {
|
||||||
|
#connection = null;
|
||||||
|
#nextId = 1;
|
||||||
|
#messageCallbacks = new SafeMap();
|
||||||
|
|
||||||
|
connect() {
|
||||||
|
if (this.#connection) {
|
||||||
|
throw new ERR_INSPECTOR_ALREADY_CONNECTED("The inspector session");
|
||||||
|
}
|
||||||
|
this.#connection = op_inspector_connect(false, (m) => this.#onMessage(m));
|
||||||
|
}
|
||||||
|
|
||||||
|
connectToMainThread() {
|
||||||
|
if (isMainThread) {
|
||||||
|
throw new ERR_INSPECTOR_NOT_WORKER();
|
||||||
|
}
|
||||||
|
if (this.#connection) {
|
||||||
|
throw new ERR_INSPECTOR_ALREADY_CONNECTED("The inspector session");
|
||||||
|
}
|
||||||
|
this.#connection = op_inspector_connect(true, (m) => this.#onMessage(m));
|
||||||
|
}
|
||||||
|
|
||||||
|
#onMessage(message) {
|
||||||
|
const parsed = JSONParse(message);
|
||||||
|
try {
|
||||||
|
if (parsed.id) {
|
||||||
|
const callback = this.#messageCallbacks.get(parsed.id);
|
||||||
|
this.#messageCallbacks.delete(parsed.id);
|
||||||
|
if (callback) {
|
||||||
|
if (parsed.error) {
|
||||||
|
return callback(
|
||||||
|
new ERR_INSPECTOR_COMMAND(
|
||||||
|
parsed.error.code,
|
||||||
|
parsed.error.message,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
callback(null, parsed.result);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.emit(parsed.method, parsed);
|
||||||
|
this.emit("inspectorNotification", parsed);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
process.emitWarning(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
post(method, params, callback) {
|
||||||
|
validateString(method, "method");
|
||||||
|
if (!callback && typeof params === "function") {
|
||||||
|
callback = params;
|
||||||
|
params = null;
|
||||||
|
}
|
||||||
|
if (params) {
|
||||||
|
validateObject(params, "params");
|
||||||
|
}
|
||||||
|
if (callback) {
|
||||||
|
validateFunction(callback, "callback");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.#connection) {
|
||||||
|
throw new ERR_INSPECTOR_NOT_CONNECTED();
|
||||||
|
}
|
||||||
|
const id = this.#nextId++;
|
||||||
|
const message = { id, method };
|
||||||
|
if (params) {
|
||||||
|
message.params = params;
|
||||||
|
}
|
||||||
|
if (callback) {
|
||||||
|
this.#messageCallbacks.set(id, callback);
|
||||||
|
}
|
||||||
|
op_inspector_dispatch(this.#connection, JSONStringify(message));
|
||||||
|
}
|
||||||
|
|
||||||
|
disconnect() {
|
||||||
|
if (!this.#connection) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
op_inspector_disconnect(this.#connection);
|
||||||
|
this.#connection = null;
|
||||||
|
// deno-lint-ignore prefer-primordials
|
||||||
|
for (const callback of this.#messageCallbacks.values()) {
|
||||||
|
process.nextTick(callback, new ERR_INSPECTOR_CLOSED());
|
||||||
|
}
|
||||||
|
this.#messageCallbacks.clear();
|
||||||
|
this.#nextId = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function open(port, host, wait) {
|
||||||
|
if (op_inspector_enabled()) {
|
||||||
|
throw new ERR_INSPECTOR_ALREADY_ACTIVATED();
|
||||||
|
}
|
||||||
|
// inspectorOpen() currently does not typecheck its arguments and adding
|
||||||
|
// such checks would be a potentially breaking change. However, the native
|
||||||
|
// open() function requires the port to fit into a 16-bit unsigned integer,
|
||||||
|
// causing an integer overflow otherwise, so we at least need to prevent that.
|
||||||
|
if (isUint32(port)) {
|
||||||
|
validateInt32(port, "port", 0, 65535);
|
||||||
|
} else {
|
||||||
|
// equiv of handling args[0]->IsUint32()
|
||||||
|
port = undefined;
|
||||||
|
}
|
||||||
|
if (typeof host !== "string") {
|
||||||
|
// equiv of handling args[1]->IsString()
|
||||||
|
host = undefined;
|
||||||
|
}
|
||||||
|
op_inspector_open(port, host);
|
||||||
|
if (wait) {
|
||||||
|
op_inspector_wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
__proto__: null,
|
||||||
|
[SymbolDispose]() {
|
||||||
|
_debugEnd();
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function close() {
|
||||||
|
op_inspector_close();
|
||||||
|
}
|
||||||
|
|
||||||
|
function url() {
|
||||||
|
return op_inspector_url();
|
||||||
|
}
|
||||||
|
|
||||||
|
function waitForDebugger() {
|
||||||
|
if (!op_inspector_wait()) {
|
||||||
|
throw new ERR_INSPECTOR_NOT_ACTIVE();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function broadcastToFrontend(eventName, params) {
|
||||||
|
validateString(eventName, "eventName");
|
||||||
|
if (params) {
|
||||||
|
validateObject(params, "params");
|
||||||
|
}
|
||||||
|
op_inspector_emit_protocol_event(eventName, JSONStringify(params ?? {}));
|
||||||
|
}
|
||||||
|
|
||||||
|
const Network = {
|
||||||
|
requestWillBeSent: (params) =>
|
||||||
|
broadcastToFrontend("Network.requestWillBeSent", params),
|
||||||
|
responseReceived: (params) =>
|
||||||
|
broadcastToFrontend("Network.responseReceived", params),
|
||||||
|
loadingFinished: (params) =>
|
||||||
|
broadcastToFrontend("Network.loadingFinished", params),
|
||||||
|
loadingFailed: (params) =>
|
||||||
|
broadcastToFrontend("Network.loadingFailed", params),
|
||||||
|
};
|
||||||
|
|
||||||
|
const console = op_get_extras_binding_object().console;
|
||||||
|
|
||||||
|
export { close, console, Network, open, Session, url, waitForDebugger };
|
||||||
|
|
||||||
|
export default {
|
||||||
|
open,
|
||||||
|
close,
|
||||||
|
url,
|
||||||
|
waitForDebugger,
|
||||||
|
console,
|
||||||
|
Session,
|
||||||
|
Network,
|
||||||
|
};
|
|
@ -1,82 +0,0 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
|
||||||
// Copyright Joyent and Node contributors. All rights reserved. MIT license.
|
|
||||||
|
|
||||||
import { EventEmitter } from "node:events";
|
|
||||||
import { notImplemented } from "ext:deno_node/_utils.ts";
|
|
||||||
import { primordials } from "ext:core/mod.js";
|
|
||||||
|
|
||||||
const {
|
|
||||||
SafeMap,
|
|
||||||
} = primordials;
|
|
||||||
|
|
||||||
class Session extends EventEmitter {
|
|
||||||
#connection = null;
|
|
||||||
#nextId = 1;
|
|
||||||
#messageCallbacks = new SafeMap();
|
|
||||||
|
|
||||||
/** Connects the session to the inspector back-end. */
|
|
||||||
connect() {
|
|
||||||
notImplemented("inspector.Session.prototype.connect");
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Connects the session to the main thread
|
|
||||||
* inspector back-end. */
|
|
||||||
connectToMainThread() {
|
|
||||||
notImplemented("inspector.Session.prototype.connectToMainThread");
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Posts a message to the inspector back-end. */
|
|
||||||
post(
|
|
||||||
_method: string,
|
|
||||||
_params?: Record<string, unknown>,
|
|
||||||
_callback?: (...args: unknown[]) => void,
|
|
||||||
) {
|
|
||||||
notImplemented("inspector.Session.prototype.post");
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Immediately closes the session, all pending
|
|
||||||
* message callbacks will be called with an
|
|
||||||
* error.
|
|
||||||
*/
|
|
||||||
disconnect() {
|
|
||||||
notImplemented("inspector.Session.prototype.disconnect");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Activates inspector on host and port.
|
|
||||||
* See https://nodejs.org/api/inspector.html#inspectoropenport-host-wait */
|
|
||||||
function open(_port?: number, _host?: string, _wait?: boolean) {
|
|
||||||
notImplemented("inspector.Session.prototype.open");
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Deactivate the inspector. Blocks until there are no active connections.
|
|
||||||
* See https://nodejs.org/api/inspector.html#inspectorclose */
|
|
||||||
function close() {
|
|
||||||
notImplemented("inspector.Session.prototype.close");
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Return the URL of the active inspector, or undefined if there is none.
|
|
||||||
* See https://nodejs.org/api/inspector.html#inspectorurl */
|
|
||||||
function url() {
|
|
||||||
// TODO(kt3k): returns undefined for now, which means the inspector is not activated.
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Blocks until a client (existing or connected later) has sent Runtime.runIfWaitingForDebugger command.
|
|
||||||
* See https://nodejs.org/api/inspector.html#inspectorwaitfordebugger */
|
|
||||||
function waitForDebugger() {
|
|
||||||
notImplemented("inspector.wairForDebugger");
|
|
||||||
}
|
|
||||||
|
|
||||||
const console = globalThis.console;
|
|
||||||
|
|
||||||
export { close, console, open, Session, url, waitForDebugger };
|
|
||||||
|
|
||||||
export default {
|
|
||||||
close,
|
|
||||||
console,
|
|
||||||
open,
|
|
||||||
Session,
|
|
||||||
url,
|
|
||||||
waitForDebugger,
|
|
||||||
};
|
|
20
ext/node/polyfills/inspector/promises.js
Normal file
20
ext/node/polyfills/inspector/promises.js
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||||
|
// Copyright Joyent and Node contributors. All rights reserved. MIT license.
|
||||||
|
|
||||||
|
import inspector from "node:inspector";
|
||||||
|
import { promisify } from "ext:deno_node/internal/util.mjs";
|
||||||
|
|
||||||
|
class Session extends inspector.Session {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Session.prototype.post = promisify(inspector.Session.prototype.post);
|
||||||
|
|
||||||
|
export * from "node:inspector";
|
||||||
|
export { Session };
|
||||||
|
|
||||||
|
export default {
|
||||||
|
...inspector,
|
||||||
|
Session,
|
||||||
|
};
|
|
@ -29,6 +29,7 @@ import {
|
||||||
} from "ext:deno_node/internal/validators.mjs";
|
} from "ext:deno_node/internal/validators.mjs";
|
||||||
import { Buffer } from "node:buffer";
|
import { Buffer } from "node:buffer";
|
||||||
import { KeyFormat, KeyType } from "ext:deno_node/internal/crypto/types.ts";
|
import { KeyFormat, KeyType } from "ext:deno_node/internal/crypto/types.ts";
|
||||||
|
import process from "node:process";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
op_node_generate_dh_group_key,
|
op_node_generate_dh_group_key,
|
||||||
|
|
|
@ -38,6 +38,7 @@ import {
|
||||||
ERR_INVALID_ARG_TYPE,
|
ERR_INVALID_ARG_TYPE,
|
||||||
ERR_OUT_OF_RANGE,
|
ERR_OUT_OF_RANGE,
|
||||||
} from "ext:deno_node/internal/errors.ts";
|
} from "ext:deno_node/internal/errors.ts";
|
||||||
|
import { Buffer } from "node:buffer";
|
||||||
|
|
||||||
export { default as randomBytes } from "ext:deno_node/internal/crypto/_randomBytes.ts";
|
export { default as randomBytes } from "ext:deno_node/internal/crypto/_randomBytes.ts";
|
||||||
export {
|
export {
|
||||||
|
|
|
@ -126,6 +126,7 @@ ObjectSetPrototypeOf(HTTPParser.prototype, AsyncWrap.prototype);
|
||||||
function defineProps(obj: object, props: Record<string, unknown>) {
|
function defineProps(obj: object, props: Record<string, unknown>) {
|
||||||
for (const entry of new SafeArrayIterator(ObjectEntries(props))) {
|
for (const entry of new SafeArrayIterator(ObjectEntries(props))) {
|
||||||
ObjectDefineProperty(obj, entry[0], {
|
ObjectDefineProperty(obj, entry[0], {
|
||||||
|
__proto__: null,
|
||||||
value: entry[1],
|
value: entry[1],
|
||||||
enumerable: true,
|
enumerable: true,
|
||||||
writable: true,
|
writable: true,
|
||||||
|
|
|
@ -182,6 +182,7 @@ function getContextOptions(options) {
|
||||||
|
|
||||||
let defaultContextNameIndex = 1;
|
let defaultContextNameIndex = 1;
|
||||||
export function createContext(
|
export function createContext(
|
||||||
|
// deno-lint-ignore prefer-primordials
|
||||||
contextObject = {},
|
contextObject = {},
|
||||||
options = { __proto__: null },
|
options = { __proto__: null },
|
||||||
) {
|
) {
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue