mirror of
https://github.com/denoland/deno.git
synced 2025-01-21 04:52:26 -05:00
Merge branch 'main' into sigwinch_stdio
This commit is contained in:
commit
1f04d843dd
1352 changed files with 43024 additions and 18529 deletions
|
@ -13,7 +13,7 @@
|
||||||
},
|
},
|
||||||
"exec": {
|
"exec": {
|
||||||
"commands": [{
|
"commands": [{
|
||||||
"command": "rustfmt --config imports_granularity=item",
|
"command": "rustfmt --config imports_granularity=item --config group_imports=StdExternalCrate",
|
||||||
"exts": ["rs"]
|
"exts": ["rs"]
|
||||||
}]
|
}]
|
||||||
},
|
},
|
||||||
|
|
2
.github/mtime_cache/action.js
vendored
2
.github/mtime_cache/action.js
vendored
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
// This file contains the implementation of a Github Action. Github uses
|
// This file contains the implementation of a Github Action. Github uses
|
||||||
// Node.js v20.x to run actions, so this is Node code and not Deno code.
|
// Node.js v20.x to run actions, so this is Node code and not Deno code.
|
||||||
|
|
||||||
|
|
44
.github/workflows/ci.generate.ts
vendored
44
.github/workflows/ci.generate.ts
vendored
|
@ -1,11 +1,11 @@
|
||||||
#!/usr/bin/env -S deno run --allow-write=. --lock=./tools/deno.lock.json
|
#!/usr/bin/env -S deno run --allow-write=. --lock=./tools/deno.lock.json
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
import { stringify } from "jsr:@std/yaml@^0.221/stringify";
|
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 = 30;
|
const cacheVersion = 33;
|
||||||
|
|
||||||
const ubuntuX86Runner = "ubuntu-24.04";
|
const ubuntuX86Runner = "ubuntu-24.04";
|
||||||
const ubuntuX86XlRunner = "ubuntu-24.04-xl";
|
const ubuntuX86XlRunner = "ubuntu-24.04-xl";
|
||||||
|
@ -360,7 +360,7 @@ const ci = {
|
||||||
needs: ["pre_build"],
|
needs: ["pre_build"],
|
||||||
if: "${{ needs.pre_build.outputs.skip_build != 'true' }}",
|
if: "${{ needs.pre_build.outputs.skip_build != 'true' }}",
|
||||||
"runs-on": "${{ matrix.runner }}",
|
"runs-on": "${{ matrix.runner }}",
|
||||||
"timeout-minutes": 180,
|
"timeout-minutes": 240,
|
||||||
defaults: {
|
defaults: {
|
||||||
run: {
|
run: {
|
||||||
// GH actions does not fail fast by default on
|
// GH actions does not fail fast by default on
|
||||||
|
@ -484,6 +484,27 @@ const ci = {
|
||||||
" -czvf target/release/deno_src.tar.gz -C .. deno",
|
" -czvf target/release/deno_src.tar.gz -C .. deno",
|
||||||
].join("\n"),
|
].join("\n"),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "Cache Cargo home",
|
||||||
|
uses: "actions/cache@v4",
|
||||||
|
with: {
|
||||||
|
// See https://doc.rust-lang.org/cargo/guide/cargo-home.html#caching-the-cargo-home-in-ci
|
||||||
|
// Note that with the new sparse registry format, we no longer have to cache a `.git` dir
|
||||||
|
path: [
|
||||||
|
"~/.cargo/.crates.toml",
|
||||||
|
"~/.cargo/.crates2.json",
|
||||||
|
"~/.cargo/bin",
|
||||||
|
"~/.cargo/registry/index",
|
||||||
|
"~/.cargo/registry/cache",
|
||||||
|
"~/.cargo/git/db",
|
||||||
|
].join("\n"),
|
||||||
|
key:
|
||||||
|
`${cacheVersion}-cargo-home-\${{ matrix.os }}-\${{ matrix.arch }}-\${{ hashFiles('Cargo.lock') }}`,
|
||||||
|
// We will try to restore from the closest cargo-home we can find
|
||||||
|
"restore-keys":
|
||||||
|
`${cacheVersion}-cargo-home-\${{ matrix.os }}-\${{ matrix.arch }}-`,
|
||||||
|
},
|
||||||
|
},
|
||||||
installRustStep,
|
installRustStep,
|
||||||
{
|
{
|
||||||
if:
|
if:
|
||||||
|
@ -607,23 +628,6 @@ const ci = {
|
||||||
installBenchTools,
|
installBenchTools,
|
||||||
].join("\n"),
|
].join("\n"),
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: "Cache Cargo home",
|
|
||||||
uses: "actions/cache@v4",
|
|
||||||
with: {
|
|
||||||
// See https://doc.rust-lang.org/cargo/guide/cargo-home.html#caching-the-cargo-home-in-ci
|
|
||||||
// Note that with the new sparse registry format, we no longer have to cache a `.git` dir
|
|
||||||
path: [
|
|
||||||
"~/.cargo/registry/index",
|
|
||||||
"~/.cargo/registry/cache",
|
|
||||||
].join("\n"),
|
|
||||||
key:
|
|
||||||
`${cacheVersion}-cargo-home-\${{ matrix.os }}-\${{ matrix.arch }}-\${{ hashFiles('Cargo.lock') }}`,
|
|
||||||
// We will try to restore from the closest cargo-home we can find
|
|
||||||
"restore-keys":
|
|
||||||
`${cacheVersion}-cargo-home-\${{ matrix.os }}-\${{ matrix.arch }}-`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
// Restore cache from the latest 'main' branch build.
|
// Restore cache from the latest 'main' branch build.
|
||||||
name: "Restore cache build output (PR)",
|
name: "Restore cache build output (PR)",
|
||||||
|
|
28
.github/workflows/ci.yml
vendored
28
.github/workflows/ci.yml
vendored
|
@ -48,7 +48,7 @@ jobs:
|
||||||
- pre_build
|
- pre_build
|
||||||
if: '${{ needs.pre_build.outputs.skip_build != ''true'' }}'
|
if: '${{ needs.pre_build.outputs.skip_build != ''true'' }}'
|
||||||
runs-on: '${{ matrix.runner }}'
|
runs-on: '${{ matrix.runner }}'
|
||||||
timeout-minutes: 180
|
timeout-minutes: 240
|
||||||
defaults:
|
defaults:
|
||||||
run:
|
run:
|
||||||
shell: bash
|
shell: bash
|
||||||
|
@ -174,6 +174,19 @@ jobs:
|
||||||
mkdir -p target/release
|
mkdir -p target/release
|
||||||
tar --exclude=".git*" --exclude=target --exclude=third_party/prebuilt \
|
tar --exclude=".git*" --exclude=target --exclude=third_party/prebuilt \
|
||||||
-czvf target/release/deno_src.tar.gz -C .. deno
|
-czvf target/release/deno_src.tar.gz -C .. deno
|
||||||
|
- name: Cache Cargo home
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: |-
|
||||||
|
~/.cargo/.crates.toml
|
||||||
|
~/.cargo/.crates2.json
|
||||||
|
~/.cargo/bin
|
||||||
|
~/.cargo/registry/index
|
||||||
|
~/.cargo/registry/cache
|
||||||
|
~/.cargo/git/db
|
||||||
|
key: '33-cargo-home-${{ matrix.os }}-${{ matrix.arch }}-${{ hashFiles(''Cargo.lock'') }}'
|
||||||
|
restore-keys: '33-cargo-home-${{ matrix.os }}-${{ matrix.arch }}-'
|
||||||
|
if: '!(matrix.skip)'
|
||||||
- uses: dsherret/rust-toolchain-file@v1
|
- uses: dsherret/rust-toolchain-file@v1
|
||||||
if: '!(matrix.skip)'
|
if: '!(matrix.skip)'
|
||||||
- if: '!(matrix.skip) && (matrix.job == ''lint'' || matrix.job == ''test'' || matrix.job == ''bench'')'
|
- if: '!(matrix.skip) && (matrix.job == ''lint'' || matrix.job == ''test'' || matrix.job == ''bench'')'
|
||||||
|
@ -355,15 +368,6 @@ jobs:
|
||||||
- name: Install benchmark tools
|
- name: Install benchmark tools
|
||||||
if: '!(matrix.skip) && (matrix.job == ''bench'')'
|
if: '!(matrix.skip) && (matrix.job == ''bench'')'
|
||||||
run: ./tools/install_prebuilt.js wrk hyperfine
|
run: ./tools/install_prebuilt.js wrk hyperfine
|
||||||
- name: Cache Cargo home
|
|
||||||
uses: actions/cache@v4
|
|
||||||
with:
|
|
||||||
path: |-
|
|
||||||
~/.cargo/registry/index
|
|
||||||
~/.cargo/registry/cache
|
|
||||||
key: '30-cargo-home-${{ matrix.os }}-${{ matrix.arch }}-${{ hashFiles(''Cargo.lock'') }}'
|
|
||||||
restore-keys: '30-cargo-home-${{ matrix.os }}-${{ matrix.arch }}-'
|
|
||||||
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
|
||||||
if: '!(matrix.skip) && (github.ref != ''refs/heads/main'' && !startsWith(github.ref, ''refs/tags/''))'
|
if: '!(matrix.skip) && (github.ref != ''refs/heads/main'' && !startsWith(github.ref, ''refs/tags/''))'
|
||||||
|
@ -375,7 +379,7 @@ jobs:
|
||||||
!./target/*/*.zip
|
!./target/*/*.zip
|
||||||
!./target/*/*.tar.gz
|
!./target/*/*.tar.gz
|
||||||
key: never_saved
|
key: never_saved
|
||||||
restore-keys: '30-cargo-target-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.profile }}-${{ matrix.job }}-'
|
restore-keys: '33-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 +689,7 @@ jobs:
|
||||||
!./target/*/gn_root
|
!./target/*/gn_root
|
||||||
!./target/*/*.zip
|
!./target/*/*.zip
|
||||||
!./target/*/*.tar.gz
|
!./target/*/*.tar.gz
|
||||||
key: '30-cargo-target-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.profile }}-${{ matrix.job }}-${{ github.sha }}'
|
key: '33-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
|
||||||
|
|
698
Cargo.lock
generated
698
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
103
Cargo.toml
103
Cargo.toml
|
@ -1,4 +1,4 @@
|
||||||
# Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
# Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
[workspace]
|
[workspace]
|
||||||
resolver = "2"
|
resolver = "2"
|
||||||
|
@ -48,55 +48,56 @@ repository = "https://github.com/denoland/deno"
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
deno_ast = { version = "=0.44.0", features = ["transpiling"] }
|
deno_ast = { version = "=0.44.0", features = ["transpiling"] }
|
||||||
deno_core = { version = "0.324.0" }
|
deno_core = { version = "0.330.0" }
|
||||||
|
|
||||||
deno_bench_util = { version = "0.176.0", path = "./bench_util" }
|
deno_bench_util = { version = "0.179.0", path = "./bench_util" }
|
||||||
deno_config = { version = "=0.39.3", features = ["workspace", "sync"] }
|
deno_config = { version = "=0.45.0", features = ["workspace", "sync"] }
|
||||||
deno_lockfile = "=0.23.2"
|
deno_lockfile = "=0.24.0"
|
||||||
deno_media_type = { version = "0.2.0", features = ["module_specifier"] }
|
deno_media_type = { version = "0.2.3", features = ["module_specifier"] }
|
||||||
deno_npm = "=0.26.0"
|
deno_npm = "=0.27.2"
|
||||||
deno_path_util = "=0.2.1"
|
deno_path_util = "=0.3.0"
|
||||||
deno_permissions = { version = "0.42.0", path = "./runtime/permissions" }
|
deno_permissions = { version = "0.44.0", path = "./runtime/permissions" }
|
||||||
deno_runtime = { version = "0.191.0", path = "./runtime" }
|
deno_runtime = { version = "0.193.0", path = "./runtime" }
|
||||||
deno_semver = "=0.6.1"
|
deno_semver = "=0.7.1"
|
||||||
deno_terminal = "0.2.0"
|
deno_terminal = "0.2.0"
|
||||||
napi_sym = { version = "0.112.0", path = "./ext/napi/sym" }
|
napi_sym = { version = "0.115.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.4"
|
denokv_proto = "0.9.0"
|
||||||
denokv_remote = "0.8.4"
|
denokv_remote = "0.9.0"
|
||||||
# denokv_sqlite brings in bundled sqlite if we don't disable the default features
|
# denokv_sqlite brings in bundled sqlite if we don't disable the default features
|
||||||
denokv_sqlite = { default-features = false, version = "0.8.4" }
|
denokv_sqlite = { default-features = false, version = "0.9.0" }
|
||||||
|
|
||||||
# exts
|
# exts
|
||||||
deno_broadcast_channel = { version = "0.176.0", path = "./ext/broadcast_channel" }
|
deno_broadcast_channel = { version = "0.179.0", path = "./ext/broadcast_channel" }
|
||||||
deno_cache = { version = "0.114.0", path = "./ext/cache" }
|
deno_cache = { version = "0.117.0", path = "./ext/cache" }
|
||||||
deno_canvas = { version = "0.51.0", path = "./ext/canvas" }
|
deno_canvas = { version = "0.54.0", path = "./ext/canvas" }
|
||||||
deno_console = { version = "0.182.0", path = "./ext/console" }
|
deno_console = { version = "0.185.0", path = "./ext/console" }
|
||||||
deno_cron = { version = "0.62.0", path = "./ext/cron" }
|
deno_cron = { version = "0.65.0", path = "./ext/cron" }
|
||||||
deno_crypto = { version = "0.196.0", path = "./ext/crypto" }
|
deno_crypto = { version = "0.199.0", path = "./ext/crypto" }
|
||||||
deno_fetch = { version = "0.206.0", path = "./ext/fetch" }
|
deno_fetch = { version = "0.209.0", path = "./ext/fetch" }
|
||||||
deno_ffi = { version = "0.169.0", path = "./ext/ffi" }
|
deno_ffi = { version = "0.172.0", path = "./ext/ffi" }
|
||||||
deno_fs = { version = "0.92.0", path = "./ext/fs" }
|
deno_fs = { version = "0.95.0", path = "./ext/fs" }
|
||||||
deno_http = { version = "0.180.0", path = "./ext/http" }
|
deno_http = { version = "0.183.0", path = "./ext/http" }
|
||||||
deno_io = { version = "0.92.0", path = "./ext/io" }
|
deno_io = { version = "0.95.0", path = "./ext/io" }
|
||||||
deno_kv = { version = "0.90.0", path = "./ext/kv" }
|
deno_kv = { version = "0.93.0", path = "./ext/kv" }
|
||||||
deno_napi = { version = "0.113.0", path = "./ext/napi" }
|
deno_napi = { version = "0.116.0", path = "./ext/napi" }
|
||||||
deno_net = { version = "0.174.0", path = "./ext/net" }
|
deno_net = { version = "0.177.0", path = "./ext/net" }
|
||||||
deno_node = { version = "0.119.0", path = "./ext/node" }
|
deno_node = { version = "0.123.0", path = "./ext/node" }
|
||||||
deno_telemetry = { version = "0.4.0", path = "./ext/telemetry" }
|
deno_os = { version = "0.1.0", path = "./ext/os" }
|
||||||
deno_tls = { version = "0.169.0", path = "./ext/tls" }
|
deno_telemetry = { version = "0.7.0", path = "./ext/telemetry" }
|
||||||
deno_url = { version = "0.182.0", path = "./ext/url" }
|
deno_tls = { version = "0.172.0", path = "./ext/tls" }
|
||||||
deno_web = { version = "0.213.0", path = "./ext/web" }
|
deno_url = { version = "0.185.0", path = "./ext/url" }
|
||||||
deno_webgpu = { version = "0.149.0", path = "./ext/webgpu" }
|
deno_web = { version = "0.216.0", path = "./ext/web" }
|
||||||
deno_webidl = { version = "0.182.0", path = "./ext/webidl" }
|
deno_webgpu = { version = "0.152.0", path = "./ext/webgpu" }
|
||||||
deno_websocket = { version = "0.187.0", path = "./ext/websocket" }
|
deno_webidl = { version = "0.185.0", path = "./ext/webidl" }
|
||||||
deno_webstorage = { version = "0.177.0", path = "./ext/webstorage" }
|
deno_websocket = { version = "0.190.0", path = "./ext/websocket" }
|
||||||
|
deno_webstorage = { version = "0.180.0", path = "./ext/webstorage" }
|
||||||
|
|
||||||
# resolvers
|
# resolvers
|
||||||
deno_npm_cache = { version = "0.2.0", path = "./resolvers/npm_cache" }
|
deno_npm_cache = { version = "0.4.0", path = "./resolvers/npm_cache" }
|
||||||
deno_resolver = { version = "0.14.0", path = "./resolvers/deno" }
|
deno_resolver = { version = "0.16.0", path = "./resolvers/deno" }
|
||||||
node_resolver = { version = "0.21.0", path = "./resolvers/node" }
|
node_resolver = { version = "0.23.0", path = "./resolvers/node" }
|
||||||
|
|
||||||
aes = "=0.8.3"
|
aes = "=0.8.3"
|
||||||
anyhow = "1.0.57"
|
anyhow = "1.0.57"
|
||||||
|
@ -104,11 +105,11 @@ async-trait = "0.1.73"
|
||||||
base32 = "=0.5.1"
|
base32 = "=0.5.1"
|
||||||
base64 = "0.21.7"
|
base64 = "0.21.7"
|
||||||
bencher = "0.1"
|
bencher = "0.1"
|
||||||
boxed_error = "0.2.2"
|
boxed_error = "0.2.3"
|
||||||
brotli = "6.0.0"
|
brotli = "6.0.0"
|
||||||
bytes = "1.4.0"
|
bytes = "1.4.0"
|
||||||
cache_control = "=0.2.0"
|
cache_control = "=0.2.0"
|
||||||
capacity_builder = "0.1.0"
|
capacity_builder = "0.5.0"
|
||||||
cbc = { version = "=0.1.2", features = ["alloc"] }
|
cbc = { version = "=0.1.2", features = ["alloc"] }
|
||||||
# Note: Do not use the "clock" feature of chrono, as it links us to CoreFoundation on macOS.
|
# Note: Do not use the "clock" feature of chrono, as it links us to CoreFoundation on macOS.
|
||||||
# Instead use util::time::utc_now()
|
# Instead use util::time::utc_now()
|
||||||
|
@ -117,9 +118,10 @@ color-print = "0.3.5"
|
||||||
console_static_text = "=0.8.1"
|
console_static_text = "=0.8.1"
|
||||||
dashmap = "5.5.3"
|
dashmap = "5.5.3"
|
||||||
data-encoding = "2.3.3"
|
data-encoding = "2.3.3"
|
||||||
data-url = "=0.3.0"
|
data-url = "=0.3.1"
|
||||||
deno_cache_dir = "=0.14.0"
|
deno_cache_dir = "=0.16.0"
|
||||||
deno_package_json = { version = "0.2.1", default-features = false }
|
deno_error = "=0.5.3"
|
||||||
|
deno_package_json = { version = "0.4.0", default-features = false }
|
||||||
deno_unsync = "0.4.2"
|
deno_unsync = "0.4.2"
|
||||||
dlopen2 = "0.6.1"
|
dlopen2 = "0.6.1"
|
||||||
ecb = "=0.1.2"
|
ecb = "=0.1.2"
|
||||||
|
@ -148,7 +150,7 @@ indexmap = { version = "2", features = ["serde"] }
|
||||||
ipnet = "2.3"
|
ipnet = "2.3"
|
||||||
jsonc-parser = { version = "=0.26.2", features = ["serde"] }
|
jsonc-parser = { version = "=0.26.2", features = ["serde"] }
|
||||||
lazy-regex = "3"
|
lazy-regex = "3"
|
||||||
libc = "0.2.126"
|
libc = "0.2.168"
|
||||||
libz-sys = { version = "1.1.20", default-features = false }
|
libz-sys = { version = "1.1.20", default-features = false }
|
||||||
log = { version = "0.4.20", features = ["kv"] }
|
log = { version = "0.4.20", features = ["kv"] }
|
||||||
lsp-types = "=0.97.0" # used by tower-lsp and "proposed" feature is unstable in patch releases
|
lsp-types = "=0.97.0" # used by tower-lsp and "proposed" feature is unstable in patch releases
|
||||||
|
@ -192,6 +194,7 @@ slab = "0.4"
|
||||||
smallvec = "1.8"
|
smallvec = "1.8"
|
||||||
socket2 = { version = "0.5.3", features = ["all"] }
|
socket2 = { version = "0.5.3", features = ["all"] }
|
||||||
spki = "0.7.2"
|
spki = "0.7.2"
|
||||||
|
sys_traits = "=0.1.7"
|
||||||
tar = "=0.4.40"
|
tar = "=0.4.40"
|
||||||
tempfile = "3.4.0"
|
tempfile = "3.4.0"
|
||||||
termcolor = "1.1.3"
|
termcolor = "1.1.3"
|
||||||
|
@ -201,7 +204,7 @@ tokio-metrics = { version = "0.3.0", features = ["rt"] }
|
||||||
tokio-rustls = { version = "0.26.0", default-features = false, features = ["ring", "tls12"] }
|
tokio-rustls = { version = "0.26.0", default-features = false, features = ["ring", "tls12"] }
|
||||||
tokio-socks = "0.5.1"
|
tokio-socks = "0.5.1"
|
||||||
tokio-util = "0.7.4"
|
tokio-util = "0.7.4"
|
||||||
tower = { version = "0.4.13", default-features = false, features = ["util"] }
|
tower = { version = "0.5.2", default-features = false, features = ["retry", "util"] }
|
||||||
tower-http = { version = "0.6.1", features = ["decompression-br", "decompression-gzip"] }
|
tower-http = { version = "0.6.1", features = ["decompression-br", "decompression-gzip"] }
|
||||||
tower-lsp = { package = "deno_tower_lsp", version = "0.1.0", features = ["proposed"] }
|
tower-lsp = { package = "deno_tower_lsp", version = "0.1.0", features = ["proposed"] }
|
||||||
tower-service = "0.3.2"
|
tower-service = "0.3.2"
|
||||||
|
@ -210,7 +213,7 @@ url = { version = "2.5", features = ["serde", "expose_internals"] }
|
||||||
uuid = { version = "1.3.0", features = ["v4"] }
|
uuid = { version = "1.3.0", features = ["v4"] }
|
||||||
webpki-root-certs = "0.26.5"
|
webpki-root-certs = "0.26.5"
|
||||||
webpki-roots = "0.26"
|
webpki-roots = "0.26"
|
||||||
which = "4.2.5"
|
which = "6"
|
||||||
yoke = { version = "0.7.4", features = ["derive"] }
|
yoke = { version = "0.7.4", features = ["derive"] }
|
||||||
zeromq = { version = "=0.4.1", default-features = false, features = ["tcp-transport", "tokio-runtime"] }
|
zeromq = { version = "=0.4.1", default-features = false, features = ["tcp-transport", "tokio-runtime"] }
|
||||||
zstd = "=0.12.4"
|
zstd = "=0.12.4"
|
||||||
|
@ -238,7 +241,7 @@ syn = { version = "2", features = ["full", "extra-traits"] }
|
||||||
nix = "=0.27.1"
|
nix = "=0.27.1"
|
||||||
|
|
||||||
# windows deps
|
# windows deps
|
||||||
junction = "=0.2.0"
|
junction = "=1.2.0"
|
||||||
winapi = "=0.3.9"
|
winapi = "=0.3.9"
|
||||||
windows-sys = { version = "0.59.0", features = ["Win32_Foundation", "Win32_Media", "Win32_Storage_FileSystem", "Win32_System_IO", "Win32_System_WindowsProgramming", "Wdk", "Wdk_System", "Wdk_System_SystemInformation", "Win32_Security", "Win32_System_Pipes", "Wdk_Storage_FileSystem", "Win32_System_Registry", "Win32_System_Kernel", "Win32_System_Threading", "Win32_UI", "Win32_UI_Shell"] }
|
windows-sys = { version = "0.59.0", features = ["Win32_Foundation", "Win32_Media", "Win32_Storage_FileSystem", "Win32_System_IO", "Win32_System_WindowsProgramming", "Wdk", "Wdk_System", "Wdk_System_SystemInformation", "Win32_Security", "Win32_System_Pipes", "Wdk_Storage_FileSystem", "Win32_System_Registry", "Win32_System_Kernel", "Win32_System_Threading", "Win32_UI", "Win32_UI_Shell"] }
|
||||||
winres = "=0.1.12"
|
winres = "=0.1.12"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright 2018-2024 the Deno authors
|
Copyright 2018-2025 the Deno authors
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
this software and associated documentation files (the "Software"), to deal in
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
|
79
Releases.md
79
Releases.md
|
@ -6,6 +6,85 @@ 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.1.5 / 2025.01.09
|
||||||
|
|
||||||
|
- feat(unstable): implement QUIC (#21942)
|
||||||
|
- feat(unstable): add JS linting plugin infrastructure (#27416)
|
||||||
|
- feat(unstable): add OTEL MeterProvider (#27240)
|
||||||
|
- feat(unstable): no config npm:@opentelemetry/api integration (#27541)
|
||||||
|
- feat(unstable): replace SpanExporter with TracerProvider (#27473)
|
||||||
|
- feat(unstable): support selectors in JS lint plugins (#27452)
|
||||||
|
- fix(check): line-break between diagnostic message chain entries (#27543)
|
||||||
|
- fix(check): move module not found errors to typescript diagnostics (#27533)
|
||||||
|
- fix(compile): analyze modules in directory specified in --include (#27296)
|
||||||
|
- fix(compile): be more deterministic when compiling the same code in different
|
||||||
|
directories (#27395)
|
||||||
|
- fix(compile): display embedded file sizes and total (#27360)
|
||||||
|
- fix(compile): output contents of embedded file system (#27302)
|
||||||
|
- fix(ext/fetch): better error message when body resource is unavailable
|
||||||
|
(#27429)
|
||||||
|
- fix(ext/fetch): retry some http/2 errors (#27417)
|
||||||
|
- fix(ext/fs): do not throw for bigint ctime/mtime/atime (#27453)
|
||||||
|
- fix(ext/http): improve error message when underlying resource of request body
|
||||||
|
unavailable (#27463)
|
||||||
|
- fix(ext/net): update moka cache to avoid potential panic in `Deno.resolveDns`
|
||||||
|
on some laptops with Ryzen CPU (#27572)
|
||||||
|
- fix(ext/node): fix `fs.access`/`fs.promises.access` with `X_OK` mode parameter
|
||||||
|
on Windows (#27407)
|
||||||
|
- fix(ext/node): fix `os.cpus()` on Linux (#27592)
|
||||||
|
- fix(ext/node): RangeError timingSafeEqual with different byteLength (#27470)
|
||||||
|
- fix(ext/node): add `truncate` method to the `FileHandle` class (#27389)
|
||||||
|
- fix(ext/node): add support of any length IV for aes-(128|256)-gcm ciphers
|
||||||
|
(#27476)
|
||||||
|
- fix(ext/node): convert brotli chunks with proper byte offset (#27455)
|
||||||
|
- fix(ext/node): do not exit worker thread when there is pending async op
|
||||||
|
(#27378)
|
||||||
|
- fix(ext/node): have `process` global available in Node context (#27562)
|
||||||
|
- fix(ext/node): make getCiphers return supported ciphers (#27466)
|
||||||
|
- fix(ext/node): sort list of built-in modules alphabetically (#27410)
|
||||||
|
- fix(ext/node): support createConnection option in node:http.request() (#25470)
|
||||||
|
- fix(ext/node): support private key export in JWK format (#27325)
|
||||||
|
- fix(ext/web): add `[[ErrorData]]` slot to `DOMException` (#27342)
|
||||||
|
- fix(ext/websocket): Fix close code without reason (#27578)
|
||||||
|
- fix(jsr): Wasm imports fail to load (#27594)
|
||||||
|
- fix(kv): improve backoff error message and inline documentation (#27537)
|
||||||
|
- fix(lint): fix single char selectors being ignored (#27576)
|
||||||
|
- fix(lockfile): include dependencies listed in external import map in lockfile
|
||||||
|
(#27337)
|
||||||
|
- fix(lsp): css preprocessor formatting (#27526)
|
||||||
|
- fix(lsp): don't skip dirs with enabled subdirs (#27580)
|
||||||
|
- fix(lsp): include "node:" prefix for node builtin auto-imports (#27404)
|
||||||
|
- fix(lsp): respect "typescript.suggestionActions.enabled" setting (#27373)
|
||||||
|
- fix(lsp): rewrite imports for 'Move to a new file' action (#27427)
|
||||||
|
- fix(lsp): sql and component file formatting (#27350)
|
||||||
|
- fix(lsp): use verbatim specifier for URL auto-imports (#27605)
|
||||||
|
- fix(no-slow-types): handle rest param with internal assignments (#27581)
|
||||||
|
- fix(node/fs): add a chmod method to the FileHandle class (#27522)
|
||||||
|
- fix(node): add missing `inspector/promises` (#27491)
|
||||||
|
- fix(node): handle cjs exports with escaped chars (#27438)
|
||||||
|
- fix(npm): deterministically output tags to initialized file (#27514)
|
||||||
|
- fix(npm): search node_modules folder for package matching npm specifier
|
||||||
|
(#27345)
|
||||||
|
- fix(outdated): ensure "Latest" version is greater than "Update" version
|
||||||
|
(#27390)
|
||||||
|
- fix(outdated): support updating dependencies in external import maps (#27339)
|
||||||
|
- fix(permissions): implicit `--allow-import` when using `--cached-only`
|
||||||
|
(#27530)
|
||||||
|
- fix(publish): infer literal types in const contexts (#27425)
|
||||||
|
- fix(task): properly handle task name wildcards with --recursive (#27396)
|
||||||
|
- fix(task): support tasks without commands (#27191)
|
||||||
|
- fix(unstable): don't error on non-existing attrs or type attr (#27456)
|
||||||
|
- fix: FastString v8_string() should error when cannot allocated (#27375)
|
||||||
|
- fix: deno_resolver crate without 'sync' feature (#27403)
|
||||||
|
- fix: incorrect memory info free/available bytes on mac (#27460)
|
||||||
|
- fix: upgrade deno_doc to 0.161.3 (#27377)
|
||||||
|
- perf(fs/windows): stat - only open file once (#27487)
|
||||||
|
- perf(node/fs/copy): reduce metadata lookups copying directory (#27495)
|
||||||
|
- perf: don't store duplicate info for ops in the snapshot (#27430)
|
||||||
|
- perf: remove now needless canonicalization getting closest package.json
|
||||||
|
(#27437)
|
||||||
|
- perf: upgrade to deno_semver 0.7 (#27426)
|
||||||
|
|
||||||
### 2.1.4 / 2024.12.11
|
### 2.1.4 / 2024.12.11
|
||||||
|
|
||||||
- feat(unstable): support caching npm dependencies only as they're needed
|
- feat(unstable): support caching npm dependencies only as they're needed
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
# Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
# Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "deno_bench_util"
|
name = "deno_bench_util"
|
||||||
version = "0.176.0"
|
version = "0.179.0"
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
|
|
@ -7,7 +7,6 @@ use deno_bench_util::bench_js_sync;
|
||||||
use deno_bench_util::bench_or_profile;
|
use deno_bench_util::bench_or_profile;
|
||||||
use deno_bench_util::bencher::benchmark_group;
|
use deno_bench_util::bencher::benchmark_group;
|
||||||
use deno_bench_util::bencher::Bencher;
|
use deno_bench_util::bencher::Bencher;
|
||||||
|
|
||||||
use deno_core::Extension;
|
use deno_core::Extension;
|
||||||
|
|
||||||
#[op2]
|
#[op2]
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
use deno_bench_util::bench_js_sync_with;
|
use deno_bench_util::bench_js_sync_with;
|
||||||
use deno_bench_util::bench_or_profile;
|
use deno_bench_util::bench_or_profile;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
use bencher::Bencher;
|
use bencher::Bencher;
|
||||||
use deno_core::v8;
|
use deno_core::v8;
|
||||||
use deno_core::Extension;
|
use deno_core::Extension;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
mod js_runtime;
|
mod js_runtime;
|
||||||
mod profiling;
|
mod profiling;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
use bencher::DynBenchFn;
|
use bencher::DynBenchFn;
|
||||||
use bencher::StaticBenchFn;
|
use bencher::StaticBenchFn;
|
||||||
use bencher::TestDescAndFn;
|
use bencher::TestDescAndFn;
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
# Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
# Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "deno"
|
name = "deno"
|
||||||
version = "2.1.4"
|
version = "2.1.5"
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
default-run = "deno"
|
default-run = "deno"
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
|
@ -62,6 +62,7 @@ serde_json.workspace = true
|
||||||
zstd.workspace = true
|
zstd.workspace = true
|
||||||
glibc_version = "0.1.2"
|
glibc_version = "0.1.2"
|
||||||
flate2 = { workspace = true, features = ["default"] }
|
flate2 = { workspace = true, features = ["default"] }
|
||||||
|
deno_error.workspace = true
|
||||||
|
|
||||||
[target.'cfg(windows)'.build-dependencies]
|
[target.'cfg(windows)'.build-dependencies]
|
||||||
winapi.workspace = true
|
winapi.workspace = true
|
||||||
|
@ -72,15 +73,16 @@ deno_ast = { workspace = true, features = ["bundler", "cjs", "codegen", "proposa
|
||||||
deno_cache_dir.workspace = true
|
deno_cache_dir.workspace = true
|
||||||
deno_config.workspace = true
|
deno_config.workspace = true
|
||||||
deno_core = { workspace = true, features = ["include_js_files_for_snapshotting"] }
|
deno_core = { workspace = true, features = ["include_js_files_for_snapshotting"] }
|
||||||
deno_doc = { version = "=0.161.2", features = ["rust", "comrak"] }
|
deno_doc = { version = "=0.164.0", features = ["rust", "comrak"] }
|
||||||
deno_graph = { version = "=0.86.3" }
|
deno_error.workspace = true
|
||||||
|
deno_graph = { version = "=0.87.0" }
|
||||||
deno_lint = { version = "=0.68.2", features = ["docs"] }
|
deno_lint = { version = "=0.68.2", features = ["docs"] }
|
||||||
deno_lockfile.workspace = true
|
deno_lockfile.workspace = true
|
||||||
deno_npm.workspace = true
|
deno_npm.workspace = true
|
||||||
deno_npm_cache.workspace = true
|
deno_npm_cache.workspace = true
|
||||||
deno_package_json.workspace = true
|
deno_package_json.workspace = true
|
||||||
deno_path_util.workspace = true
|
deno_path_util.workspace = true
|
||||||
deno_resolver.workspace = true
|
deno_resolver = { workspace = true, features = ["sync"] }
|
||||||
deno_runtime = { workspace = true, features = ["include_js_files_for_snapshotting"] }
|
deno_runtime = { workspace = true, features = ["include_js_files_for_snapshotting"] }
|
||||||
deno_semver.workspace = true
|
deno_semver.workspace = true
|
||||||
deno_task_shell = "=0.20.2"
|
deno_task_shell = "=0.20.2"
|
||||||
|
@ -93,8 +95,10 @@ anstream = "0.6.14"
|
||||||
async-trait.workspace = true
|
async-trait.workspace = true
|
||||||
base64.workspace = true
|
base64.workspace = true
|
||||||
bincode = "=1.3.3"
|
bincode = "=1.3.3"
|
||||||
|
boxed_error.workspace = true
|
||||||
bytes.workspace = true
|
bytes.workspace = true
|
||||||
cache_control.workspace = true
|
cache_control.workspace = true
|
||||||
|
capacity_builder.workspace = true
|
||||||
chrono = { workspace = true, features = ["now"] }
|
chrono = { workspace = true, features = ["now"] }
|
||||||
clap = { version = "=4.5.16", features = ["env", "string", "wrap_help", "error-context"] }
|
clap = { version = "=4.5.16", features = ["env", "string", "wrap_help", "error-context"] }
|
||||||
clap_complete = "=4.5.24"
|
clap_complete = "=4.5.24"
|
||||||
|
@ -121,7 +125,7 @@ http.workspace = true
|
||||||
http-body.workspace = true
|
http-body.workspace = true
|
||||||
http-body-util.workspace = true
|
http-body-util.workspace = true
|
||||||
hyper-util.workspace = true
|
hyper-util.workspace = true
|
||||||
import_map = { version = "=0.20.1", features = ["ext"] }
|
import_map = { version = "=0.21.0", features = ["ext"] }
|
||||||
indexmap.workspace = true
|
indexmap.workspace = true
|
||||||
jsonc-parser = { workspace = true, features = ["cst", "serde"] }
|
jsonc-parser = { workspace = true, features = ["cst", "serde"] }
|
||||||
jupyter_runtime = { package = "runtimelib", version = "=0.19.0", features = ["tokio-runtime"] }
|
jupyter_runtime = { package = "runtimelib", version = "=0.19.0", features = ["tokio-runtime"] }
|
||||||
|
@ -155,6 +159,7 @@ shell-escape = "=0.1.5"
|
||||||
spki = { version = "0.7", features = ["pem"] }
|
spki = { version = "0.7", features = ["pem"] }
|
||||||
sqlformat = "=0.3.2"
|
sqlformat = "=0.3.2"
|
||||||
strsim = "0.11.1"
|
strsim = "0.11.1"
|
||||||
|
sys_traits = { workspace = true, features = ["getrandom", "filetime", "libc", "real", "strip_unc", "winapi"] }
|
||||||
tar.workspace = true
|
tar.workspace = true
|
||||||
tempfile.workspace = true
|
tempfile.workspace = true
|
||||||
text-size = "=1.1.0"
|
text-size = "=1.1.0"
|
||||||
|
@ -183,6 +188,7 @@ nix.workspace = true
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
deno_bench_util.workspace = true
|
deno_bench_util.workspace = true
|
||||||
pretty_assertions.workspace = true
|
pretty_assertions.workspace = true
|
||||||
|
sys_traits = { workspace = true, features = ["memory"] }
|
||||||
test_util.workspace = true
|
test_util.workspace = true
|
||||||
|
|
||||||
[package.metadata.winres]
|
[package.metadata.winres]
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
|
||||||
|
@ -8,62 +8,6 @@ use deno_semver::jsr::JsrDepPackageReq;
|
||||||
use deno_semver::jsr::JsrPackageReqReference;
|
use deno_semver::jsr::JsrPackageReqReference;
|
||||||
use deno_semver::npm::NpmPackageReqReference;
|
use deno_semver::npm::NpmPackageReqReference;
|
||||||
|
|
||||||
#[cfg(test)] // happens to only be used by the tests at the moment
|
|
||||||
pub struct DenoConfigFsAdapter<'a>(
|
|
||||||
pub &'a dyn deno_runtime::deno_fs::FileSystem,
|
|
||||||
);
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
impl<'a> deno_config::fs::DenoConfigFs for DenoConfigFsAdapter<'a> {
|
|
||||||
fn read_to_string_lossy(
|
|
||||||
&self,
|
|
||||||
path: &std::path::Path,
|
|
||||||
) -> Result<std::borrow::Cow<'static, str>, std::io::Error> {
|
|
||||||
self
|
|
||||||
.0
|
|
||||||
.read_text_file_lossy_sync(path, None)
|
|
||||||
.map_err(|err| err.into_io_error())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn stat_sync(
|
|
||||||
&self,
|
|
||||||
path: &std::path::Path,
|
|
||||||
) -> Result<deno_config::fs::FsMetadata, std::io::Error> {
|
|
||||||
self
|
|
||||||
.0
|
|
||||||
.stat_sync(path)
|
|
||||||
.map(|stat| deno_config::fs::FsMetadata {
|
|
||||||
is_file: stat.is_file,
|
|
||||||
is_directory: stat.is_directory,
|
|
||||||
is_symlink: stat.is_symlink,
|
|
||||||
})
|
|
||||||
.map_err(|err| err.into_io_error())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn read_dir(
|
|
||||||
&self,
|
|
||||||
path: &std::path::Path,
|
|
||||||
) -> Result<Vec<deno_config::fs::FsDirEntry>, std::io::Error> {
|
|
||||||
self
|
|
||||||
.0
|
|
||||||
.read_dir_sync(path)
|
|
||||||
.map_err(|err| err.into_io_error())
|
|
||||||
.map(|entries| {
|
|
||||||
entries
|
|
||||||
.into_iter()
|
|
||||||
.map(|e| deno_config::fs::FsDirEntry {
|
|
||||||
path: path.join(e.name),
|
|
||||||
metadata: deno_config::fs::FsMetadata {
|
|
||||||
is_file: e.is_file,
|
|
||||||
is_directory: e.is_directory,
|
|
||||||
is_symlink: e.is_symlink,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.collect()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn import_map_deps(
|
pub fn import_map_deps(
|
||||||
import_map: &serde_json::Value,
|
import_map: &serde_json::Value,
|
||||||
) -> HashSet<JsrDepPackageReq> {
|
) -> HashSet<JsrDepPackageReq> {
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
use std::borrow::Cow;
|
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::ffi::OsString;
|
use std::ffi::OsString;
|
||||||
|
@ -34,7 +33,6 @@ use deno_core::url::Url;
|
||||||
use deno_graph::GraphKind;
|
use deno_graph::GraphKind;
|
||||||
use deno_path_util::normalize_path;
|
use deno_path_util::normalize_path;
|
||||||
use deno_path_util::url_to_file_path;
|
use deno_path_util::url_to_file_path;
|
||||||
use deno_runtime::deno_permissions::PermissionsOptions;
|
|
||||||
use deno_runtime::deno_permissions::SysDescriptor;
|
use deno_runtime::deno_permissions::SysDescriptor;
|
||||||
use deno_telemetry::OtelConfig;
|
use deno_telemetry::OtelConfig;
|
||||||
use deno_telemetry::OtelConsoleConfig;
|
use deno_telemetry::OtelConsoleConfig;
|
||||||
|
@ -43,11 +41,8 @@ use log::Level;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
use crate::args::resolve_no_prompt;
|
|
||||||
use crate::util::fs::canonicalize_path;
|
|
||||||
|
|
||||||
use super::flags_net;
|
use super::flags_net;
|
||||||
use super::jsr_url;
|
use crate::util::fs::canonicalize_path;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, Eq, PartialEq)]
|
#[derive(Clone, Debug, Default, Eq, PartialEq)]
|
||||||
pub enum ConfigFlag {
|
pub enum ConfigFlag {
|
||||||
|
@ -693,97 +688,6 @@ impl PermissionFlags {
|
||||||
|| self.deny_write.is_some()
|
|| self.deny_write.is_some()
|
||||||
|| self.allow_import.is_some()
|
|| self.allow_import.is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_options(&self, cli_arg_urls: &[Cow<Url>]) -> PermissionsOptions {
|
|
||||||
fn handle_allow<T: Default>(
|
|
||||||
allow_all: bool,
|
|
||||||
value: Option<T>,
|
|
||||||
) -> Option<T> {
|
|
||||||
if allow_all {
|
|
||||||
assert!(value.is_none());
|
|
||||||
Some(T::default())
|
|
||||||
} else {
|
|
||||||
value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn handle_imports(
|
|
||||||
cli_arg_urls: &[Cow<Url>],
|
|
||||||
imports: Option<Vec<String>>,
|
|
||||||
) -> Option<Vec<String>> {
|
|
||||||
if imports.is_some() {
|
|
||||||
return imports;
|
|
||||||
}
|
|
||||||
|
|
||||||
let builtin_allowed_import_hosts = [
|
|
||||||
"jsr.io:443",
|
|
||||||
"deno.land:443",
|
|
||||||
"esm.sh:443",
|
|
||||||
"cdn.jsdelivr.net:443",
|
|
||||||
"raw.githubusercontent.com:443",
|
|
||||||
"gist.githubusercontent.com:443",
|
|
||||||
];
|
|
||||||
|
|
||||||
let mut imports =
|
|
||||||
Vec::with_capacity(builtin_allowed_import_hosts.len() + 1);
|
|
||||||
imports
|
|
||||||
.extend(builtin_allowed_import_hosts.iter().map(|s| s.to_string()));
|
|
||||||
|
|
||||||
// also add the JSR_URL env var
|
|
||||||
if let Some(jsr_host) = allow_import_host_from_url(jsr_url()) {
|
|
||||||
imports.push(jsr_host);
|
|
||||||
}
|
|
||||||
// include the cli arg urls
|
|
||||||
for url in cli_arg_urls {
|
|
||||||
if let Some(host) = allow_import_host_from_url(url) {
|
|
||||||
imports.push(host);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Some(imports)
|
|
||||||
}
|
|
||||||
|
|
||||||
PermissionsOptions {
|
|
||||||
allow_all: self.allow_all,
|
|
||||||
allow_env: handle_allow(self.allow_all, self.allow_env.clone()),
|
|
||||||
deny_env: self.deny_env.clone(),
|
|
||||||
allow_net: handle_allow(self.allow_all, self.allow_net.clone()),
|
|
||||||
deny_net: self.deny_net.clone(),
|
|
||||||
allow_ffi: handle_allow(self.allow_all, self.allow_ffi.clone()),
|
|
||||||
deny_ffi: self.deny_ffi.clone(),
|
|
||||||
allow_read: handle_allow(self.allow_all, self.allow_read.clone()),
|
|
||||||
deny_read: self.deny_read.clone(),
|
|
||||||
allow_run: handle_allow(self.allow_all, self.allow_run.clone()),
|
|
||||||
deny_run: self.deny_run.clone(),
|
|
||||||
allow_sys: handle_allow(self.allow_all, self.allow_sys.clone()),
|
|
||||||
deny_sys: self.deny_sys.clone(),
|
|
||||||
allow_write: handle_allow(self.allow_all, self.allow_write.clone()),
|
|
||||||
deny_write: self.deny_write.clone(),
|
|
||||||
allow_import: handle_imports(
|
|
||||||
cli_arg_urls,
|
|
||||||
handle_allow(self.allow_all, self.allow_import.clone()),
|
|
||||||
),
|
|
||||||
prompt: !resolve_no_prompt(self),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Gets the --allow-import host from the provided url
|
|
||||||
fn allow_import_host_from_url(url: &Url) -> Option<String> {
|
|
||||||
let host = url.host()?;
|
|
||||||
if let Some(port) = url.port() {
|
|
||||||
Some(format!("{}:{}", host, port))
|
|
||||||
} else {
|
|
||||||
use deno_core::url::Host::*;
|
|
||||||
match host {
|
|
||||||
Domain(domain) if domain == "jsr.io" && url.scheme() == "https" => None,
|
|
||||||
_ => match url.scheme() {
|
|
||||||
"https" => Some(format!("{}:443", host)),
|
|
||||||
"http" => Some(format!("{}:80", host)),
|
|
||||||
_ => None,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn join_paths(allowlist: &[String], d: &str) -> String {
|
fn join_paths(allowlist: &[String], d: &str) -> String {
|
||||||
|
@ -1006,6 +910,8 @@ impl Flags {
|
||||||
OtelConfig {
|
OtelConfig {
|
||||||
tracing_enabled: !disabled
|
tracing_enabled: !disabled
|
||||||
&& otel_var("OTEL_DENO_TRACING").unwrap_or(default),
|
&& otel_var("OTEL_DENO_TRACING").unwrap_or(default),
|
||||||
|
metrics_enabled: !disabled
|
||||||
|
&& otel_var("OTEL_DENO_METRICS").unwrap_or(default),
|
||||||
console: match std::env::var("OTEL_DENO_CONSOLE").as_deref() {
|
console: match std::env::var("OTEL_DENO_CONSOLE").as_deref() {
|
||||||
Ok(_) if disabled => OtelConsoleConfig::Ignore,
|
Ok(_) if disabled => OtelConsoleConfig::Ignore,
|
||||||
Ok("ignore") => OtelConsoleConfig::Ignore,
|
Ok("ignore") => OtelConsoleConfig::Ignore,
|
||||||
|
@ -6057,9 +5963,10 @@ pub fn resolve_urls(urls: Vec<String>) -> Vec<String> {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
/// Creates vector of strings, Vec<String>
|
/// Creates vector of strings, Vec<String>
|
||||||
macro_rules! svec {
|
macro_rules! svec {
|
||||||
($($x:expr),* $(,)?) => (vec![$($x.to_string().into()),*]);
|
($($x:expr),* $(,)?) => (vec![$($x.to_string().into()),*]);
|
||||||
|
@ -11547,8 +11454,6 @@ mod tests {
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
// just make sure this doesn't panic
|
|
||||||
let _ = flags.permissions.to_options(&[]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -11624,29 +11529,6 @@ Usage: deno repl [OPTIONS] [-- [ARGS]...]\n"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_allow_import_host_from_url() {
|
|
||||||
fn parse(text: &str) -> Option<String> {
|
|
||||||
allow_import_host_from_url(&Url::parse(text).unwrap())
|
|
||||||
}
|
|
||||||
|
|
||||||
assert_eq!(parse("https://jsr.io"), None);
|
|
||||||
assert_eq!(
|
|
||||||
parse("http://127.0.0.1:4250"),
|
|
||||||
Some("127.0.0.1:4250".to_string())
|
|
||||||
);
|
|
||||||
assert_eq!(parse("http://jsr.io"), Some("jsr.io:80".to_string()));
|
|
||||||
assert_eq!(
|
|
||||||
parse("https://example.com"),
|
|
||||||
Some("example.com:443".to_string())
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
parse("http://example.com"),
|
|
||||||
Some("example.com:80".to_string())
|
|
||||||
);
|
|
||||||
assert_eq!(parse("file:///example.com"), None);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn allow_all_conflicts_allow_perms() {
|
fn allow_all_conflicts_allow_perms() {
|
||||||
let flags = [
|
let flags = [
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
|
use std::net::IpAddr;
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
use deno_core::url::Url;
|
use deno_core::url::Url;
|
||||||
use deno_runtime::deno_permissions::NetDescriptor;
|
use deno_runtime::deno_permissions::NetDescriptor;
|
||||||
use std::net::IpAddr;
|
|
||||||
use std::str::FromStr;
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
pub struct ParsePortError(String);
|
pub struct ParsePortError(String);
|
||||||
|
|
|
@ -1,24 +1,24 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
use deno_core::serde_json;
|
use deno_core::serde_json;
|
||||||
use deno_core::url::Url;
|
use deno_core::url::Url;
|
||||||
|
|
||||||
use crate::file_fetcher::FileFetcher;
|
use crate::file_fetcher::CliFileFetcher;
|
||||||
|
use crate::file_fetcher::TextDecodedFile;
|
||||||
|
|
||||||
pub async fn resolve_import_map_value_from_specifier(
|
pub async fn resolve_import_map_value_from_specifier(
|
||||||
specifier: &Url,
|
specifier: &Url,
|
||||||
file_fetcher: &FileFetcher,
|
file_fetcher: &CliFileFetcher,
|
||||||
) -> Result<serde_json::Value, AnyError> {
|
) -> Result<serde_json::Value, AnyError> {
|
||||||
if specifier.scheme() == "data" {
|
if specifier.scheme() == "data" {
|
||||||
let data_url_text =
|
let data_url_text =
|
||||||
deno_graph::source::RawDataUrl::parse(specifier)?.decode()?;
|
deno_graph::source::RawDataUrl::parse(specifier)?.decode()?;
|
||||||
Ok(serde_json::from_str(&data_url_text)?)
|
Ok(serde_json::from_str(&data_url_text)?)
|
||||||
} else {
|
} else {
|
||||||
let file = file_fetcher
|
let file = TextDecodedFile::decode(
|
||||||
.fetch_bypass_permissions(specifier)
|
file_fetcher.fetch_bypass_permissions(specifier).await?,
|
||||||
.await?
|
)?;
|
||||||
.into_text_decoded()?;
|
|
||||||
Ok(serde_json::from_str(&file.source)?)
|
Ok(serde_json::from_str(&file.source)?)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
@ -10,20 +10,20 @@ use deno_core::error::AnyError;
|
||||||
use deno_core::parking_lot::Mutex;
|
use deno_core::parking_lot::Mutex;
|
||||||
use deno_core::parking_lot::MutexGuard;
|
use deno_core::parking_lot::MutexGuard;
|
||||||
use deno_core::serde_json;
|
use deno_core::serde_json;
|
||||||
|
use deno_error::JsErrorBox;
|
||||||
|
use deno_lockfile::Lockfile;
|
||||||
use deno_lockfile::WorkspaceMemberConfig;
|
use deno_lockfile::WorkspaceMemberConfig;
|
||||||
use deno_package_json::PackageJsonDepValue;
|
use deno_package_json::PackageJsonDepValue;
|
||||||
|
use deno_path_util::fs::atomic_write_file_with_retries;
|
||||||
use deno_runtime::deno_node::PackageJson;
|
use deno_runtime::deno_node::PackageJson;
|
||||||
use deno_semver::jsr::JsrDepPackageReq;
|
use deno_semver::jsr::JsrDepPackageReq;
|
||||||
|
|
||||||
use crate::args::deno_json::import_map_deps;
|
use crate::args::deno_json::import_map_deps;
|
||||||
use crate::cache;
|
|
||||||
use crate::util::fs::atomic_write_file_with_retries;
|
|
||||||
use crate::Flags;
|
|
||||||
|
|
||||||
use crate::args::DenoSubcommand;
|
use crate::args::DenoSubcommand;
|
||||||
use crate::args::InstallFlags;
|
use crate::args::InstallFlags;
|
||||||
|
use crate::cache;
|
||||||
use deno_lockfile::Lockfile;
|
use crate::sys::CliSys;
|
||||||
|
use crate::Flags;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct CliLockfileReadFromPathOptions {
|
pub struct CliLockfileReadFromPathOptions {
|
||||||
|
@ -35,6 +35,7 @@ pub struct CliLockfileReadFromPathOptions {
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct CliLockfile {
|
pub struct CliLockfile {
|
||||||
|
sys: CliSys,
|
||||||
lockfile: Mutex<Lockfile>,
|
lockfile: Mutex<Lockfile>,
|
||||||
pub filename: PathBuf,
|
pub filename: PathBuf,
|
||||||
frozen: bool,
|
frozen: bool,
|
||||||
|
@ -59,6 +60,14 @@ impl<'a, T> std::ops::DerefMut for Guard<'a, T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, thiserror::Error, deno_error::JsError)]
|
||||||
|
#[error("Failed writing lockfile")]
|
||||||
|
#[class(inherit)]
|
||||||
|
struct AtomicWriteFileWithRetriesError {
|
||||||
|
#[source]
|
||||||
|
source: std::io::Error,
|
||||||
|
}
|
||||||
|
|
||||||
impl CliLockfile {
|
impl CliLockfile {
|
||||||
/// Get the inner deno_lockfile::Lockfile.
|
/// Get the inner deno_lockfile::Lockfile.
|
||||||
pub fn lock(&self) -> Guard<Lockfile> {
|
pub fn lock(&self) -> Guard<Lockfile> {
|
||||||
|
@ -78,7 +87,7 @@ impl CliLockfile {
|
||||||
self.lockfile.lock().overwrite
|
self.lockfile.lock().overwrite
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_if_changed(&self) -> Result<(), AnyError> {
|
pub fn write_if_changed(&self) -> Result<(), JsErrorBox> {
|
||||||
if self.skip_write {
|
if self.skip_write {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
@ -91,16 +100,20 @@ impl CliLockfile {
|
||||||
// do an atomic write to reduce the chance of multiple deno
|
// do an atomic write to reduce the chance of multiple deno
|
||||||
// processes corrupting the file
|
// processes corrupting the file
|
||||||
atomic_write_file_with_retries(
|
atomic_write_file_with_retries(
|
||||||
|
&self.sys,
|
||||||
&lockfile.filename,
|
&lockfile.filename,
|
||||||
bytes,
|
&bytes,
|
||||||
cache::CACHE_PERM,
|
cache::CACHE_PERM,
|
||||||
)
|
)
|
||||||
.context("Failed writing lockfile.")?;
|
.map_err(|source| {
|
||||||
|
JsErrorBox::from_err(AtomicWriteFileWithRetriesError { source })
|
||||||
|
})?;
|
||||||
lockfile.has_content_changed = false;
|
lockfile.has_content_changed = false;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn discover(
|
pub fn discover(
|
||||||
|
sys: &CliSys,
|
||||||
flags: &Flags,
|
flags: &Flags,
|
||||||
workspace: &Workspace,
|
workspace: &Workspace,
|
||||||
maybe_external_import_map: Option<&serde_json::Value>,
|
maybe_external_import_map: Option<&serde_json::Value>,
|
||||||
|
@ -163,11 +176,14 @@ impl CliLockfile {
|
||||||
.unwrap_or(false)
|
.unwrap_or(false)
|
||||||
});
|
});
|
||||||
|
|
||||||
let lockfile = Self::read_from_path(CliLockfileReadFromPathOptions {
|
let lockfile = Self::read_from_path(
|
||||||
|
sys,
|
||||||
|
CliLockfileReadFromPathOptions {
|
||||||
file_path,
|
file_path,
|
||||||
frozen,
|
frozen,
|
||||||
skip_write: flags.internal.lockfile_skip_write,
|
skip_write: flags.internal.lockfile_skip_write,
|
||||||
})?;
|
},
|
||||||
|
)?;
|
||||||
|
|
||||||
// initialize the lockfile with the workspace's configuration
|
// initialize the lockfile with the workspace's configuration
|
||||||
let root_url = workspace.root_dir();
|
let root_url = workspace.root_dir();
|
||||||
|
@ -223,6 +239,7 @@ impl CliLockfile {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_from_path(
|
pub fn read_from_path(
|
||||||
|
sys: &CliSys,
|
||||||
opts: CliLockfileReadFromPathOptions,
|
opts: CliLockfileReadFromPathOptions,
|
||||||
) -> Result<CliLockfile, AnyError> {
|
) -> Result<CliLockfile, AnyError> {
|
||||||
let lockfile = match std::fs::read_to_string(&opts.file_path) {
|
let lockfile = match std::fs::read_to_string(&opts.file_path) {
|
||||||
|
@ -241,6 +258,7 @@ impl CliLockfile {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Ok(CliLockfile {
|
Ok(CliLockfile {
|
||||||
|
sys: sys.clone(),
|
||||||
filename: lockfile.filename.clone(),
|
filename: lockfile.filename.clone(),
|
||||||
lockfile: Mutex::new(lockfile),
|
lockfile: Mutex::new(lockfile),
|
||||||
frozen: opts.frozen,
|
frozen: opts.frozen,
|
||||||
|
@ -248,7 +266,7 @@ impl CliLockfile {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn error_if_changed(&self) -> Result<(), AnyError> {
|
pub fn error_if_changed(&self) -> Result<(), JsErrorBox> {
|
||||||
if !self.frozen {
|
if !self.frozen {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
@ -260,9 +278,7 @@ impl CliLockfile {
|
||||||
let diff = crate::util::diff::diff(&contents, &new_contents);
|
let diff = crate::util::diff::diff(&contents, &new_contents);
|
||||||
// has an extra newline at the end
|
// has an extra newline at the end
|
||||||
let diff = diff.trim_end();
|
let diff = diff.trim_end();
|
||||||
Err(deno_core::anyhow::anyhow!(
|
Err(JsErrorBox::generic(format!("The lockfile is out of date. Run `deno install --frozen=false`, or rerun with `--frozen=false` to update it.\nchanges:\n{diff}")))
|
||||||
"The lockfile is out of date. Run `deno install --frozen=false`, or rerun with `--frozen=false` to update it.\nchanges:\n{diff}"
|
|
||||||
))
|
|
||||||
} else {
|
} else {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
428
cli/args/mod.rs
428
cli/args/mod.rs
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
pub mod deno_json;
|
pub mod deno_json;
|
||||||
mod flags;
|
mod flags;
|
||||||
|
@ -7,68 +7,6 @@ mod import_map;
|
||||||
mod lockfile;
|
mod lockfile;
|
||||||
mod package_json;
|
mod package_json;
|
||||||
|
|
||||||
use deno_ast::MediaType;
|
|
||||||
use deno_ast::SourceMapOption;
|
|
||||||
use deno_config::deno_json::NodeModulesDirMode;
|
|
||||||
use deno_config::workspace::CreateResolverOptions;
|
|
||||||
use deno_config::workspace::FolderConfigs;
|
|
||||||
use deno_config::workspace::PackageJsonDepResolution;
|
|
||||||
use deno_config::workspace::VendorEnablement;
|
|
||||||
use deno_config::workspace::Workspace;
|
|
||||||
use deno_config::workspace::WorkspaceDirectory;
|
|
||||||
use deno_config::workspace::WorkspaceDirectoryEmptyOptions;
|
|
||||||
use deno_config::workspace::WorkspaceDiscoverOptions;
|
|
||||||
use deno_config::workspace::WorkspaceDiscoverStart;
|
|
||||||
use deno_config::workspace::WorkspaceLintConfig;
|
|
||||||
use deno_config::workspace::WorkspaceResolver;
|
|
||||||
use deno_core::resolve_url_or_path;
|
|
||||||
use deno_graph::GraphKind;
|
|
||||||
use deno_npm::npm_rc::NpmRc;
|
|
||||||
use deno_npm::npm_rc::ResolvedNpmRc;
|
|
||||||
use deno_npm::resolution::ValidSerializedNpmResolutionSnapshot;
|
|
||||||
use deno_npm::NpmSystemInfo;
|
|
||||||
use deno_npm_cache::NpmCacheSetting;
|
|
||||||
use deno_path_util::normalize_path;
|
|
||||||
use deno_semver::npm::NpmPackageReqReference;
|
|
||||||
use deno_telemetry::OtelConfig;
|
|
||||||
use deno_telemetry::OtelRuntimeConfig;
|
|
||||||
use import_map::resolve_import_map_value_from_specifier;
|
|
||||||
|
|
||||||
pub use deno_config::deno_json::BenchConfig;
|
|
||||||
pub use deno_config::deno_json::ConfigFile;
|
|
||||||
pub use deno_config::deno_json::FmtOptionsConfig;
|
|
||||||
pub use deno_config::deno_json::LintRulesConfig;
|
|
||||||
pub use deno_config::deno_json::ProseWrap;
|
|
||||||
pub use deno_config::deno_json::TsConfig;
|
|
||||||
pub use deno_config::deno_json::TsConfigForEmit;
|
|
||||||
pub use deno_config::deno_json::TsConfigType;
|
|
||||||
pub use deno_config::deno_json::TsTypeLib;
|
|
||||||
pub use deno_config::glob::FilePatterns;
|
|
||||||
pub use deno_json::check_warn_tsconfig;
|
|
||||||
pub use flags::*;
|
|
||||||
pub use lockfile::CliLockfile;
|
|
||||||
pub use lockfile::CliLockfileReadFromPathOptions;
|
|
||||||
pub use package_json::NpmInstallDepsProvider;
|
|
||||||
pub use package_json::PackageJsonDepValueParseWithLocationError;
|
|
||||||
|
|
||||||
use deno_ast::ModuleSpecifier;
|
|
||||||
use deno_core::anyhow::bail;
|
|
||||||
use deno_core::anyhow::Context;
|
|
||||||
use deno_core::error::AnyError;
|
|
||||||
use deno_core::serde_json;
|
|
||||||
use deno_core::url::Url;
|
|
||||||
use deno_runtime::deno_permissions::PermissionsOptions;
|
|
||||||
use deno_runtime::deno_tls::deno_native_certs::load_native_certs;
|
|
||||||
use deno_runtime::deno_tls::rustls;
|
|
||||||
use deno_runtime::deno_tls::rustls::RootCertStore;
|
|
||||||
use deno_runtime::deno_tls::rustls_pemfile;
|
|
||||||
use deno_runtime::deno_tls::webpki_roots;
|
|
||||||
use deno_runtime::inspector_server::InspectorServer;
|
|
||||||
use deno_terminal::colors;
|
|
||||||
use dotenvy::from_filename;
|
|
||||||
use once_cell::sync::Lazy;
|
|
||||||
use serde::Deserialize;
|
|
||||||
use serde::Serialize;
|
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::env;
|
use std::env;
|
||||||
|
@ -81,18 +19,82 @@ use std::num::NonZeroUsize;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use deno_ast::MediaType;
|
||||||
|
use deno_ast::ModuleSpecifier;
|
||||||
|
use deno_ast::SourceMapOption;
|
||||||
|
use deno_cache_dir::file_fetcher::CacheSetting;
|
||||||
|
pub use deno_config::deno_json::BenchConfig;
|
||||||
|
pub use deno_config::deno_json::ConfigFile;
|
||||||
|
use deno_config::deno_json::ConfigFileError;
|
||||||
|
use deno_config::deno_json::FmtConfig;
|
||||||
|
pub use deno_config::deno_json::FmtOptionsConfig;
|
||||||
|
use deno_config::deno_json::LintConfig;
|
||||||
|
pub use deno_config::deno_json::LintRulesConfig;
|
||||||
|
use deno_config::deno_json::NodeModulesDirMode;
|
||||||
|
pub use deno_config::deno_json::ProseWrap;
|
||||||
|
use deno_config::deno_json::TestConfig;
|
||||||
|
pub use deno_config::deno_json::TsConfig;
|
||||||
|
pub use deno_config::deno_json::TsConfigForEmit;
|
||||||
|
pub use deno_config::deno_json::TsConfigType;
|
||||||
|
pub use deno_config::deno_json::TsTypeLib;
|
||||||
|
pub use deno_config::glob::FilePatterns;
|
||||||
|
use deno_config::workspace::CreateResolverOptions;
|
||||||
|
use deno_config::workspace::FolderConfigs;
|
||||||
|
use deno_config::workspace::PackageJsonDepResolution;
|
||||||
|
use deno_config::workspace::VendorEnablement;
|
||||||
|
use deno_config::workspace::Workspace;
|
||||||
|
use deno_config::workspace::WorkspaceDirectory;
|
||||||
|
use deno_config::workspace::WorkspaceDirectoryEmptyOptions;
|
||||||
|
use deno_config::workspace::WorkspaceDiscoverOptions;
|
||||||
|
use deno_config::workspace::WorkspaceDiscoverStart;
|
||||||
|
use deno_config::workspace::WorkspaceLintConfig;
|
||||||
|
use deno_config::workspace::WorkspaceResolver;
|
||||||
|
use deno_core::anyhow::bail;
|
||||||
|
use deno_core::anyhow::Context;
|
||||||
|
use deno_core::error::AnyError;
|
||||||
|
use deno_core::resolve_url_or_path;
|
||||||
|
use deno_core::serde_json;
|
||||||
|
use deno_core::url::Url;
|
||||||
|
use deno_graph::GraphKind;
|
||||||
|
pub use deno_json::check_warn_tsconfig;
|
||||||
|
use deno_lint::linter::LintConfig as DenoLintConfig;
|
||||||
|
use deno_npm::npm_rc::NpmRc;
|
||||||
|
use deno_npm::npm_rc::ResolvedNpmRc;
|
||||||
|
use deno_npm::resolution::ValidSerializedNpmResolutionSnapshot;
|
||||||
|
use deno_npm::NpmSystemInfo;
|
||||||
|
use deno_path_util::normalize_path;
|
||||||
|
use deno_runtime::deno_permissions::PermissionsOptions;
|
||||||
|
use deno_runtime::deno_tls::deno_native_certs::load_native_certs;
|
||||||
|
use deno_runtime::deno_tls::rustls;
|
||||||
|
use deno_runtime::deno_tls::rustls::RootCertStore;
|
||||||
|
use deno_runtime::deno_tls::rustls_pemfile;
|
||||||
|
use deno_runtime::deno_tls::webpki_roots;
|
||||||
|
use deno_runtime::inspector_server::InspectorServer;
|
||||||
|
use deno_semver::npm::NpmPackageReqReference;
|
||||||
|
use deno_semver::StackString;
|
||||||
|
use deno_telemetry::OtelConfig;
|
||||||
|
use deno_telemetry::OtelRuntimeConfig;
|
||||||
|
use deno_terminal::colors;
|
||||||
|
use dotenvy::from_filename;
|
||||||
|
pub use flags::*;
|
||||||
|
use import_map::resolve_import_map_value_from_specifier;
|
||||||
|
pub use lockfile::CliLockfile;
|
||||||
|
pub use lockfile::CliLockfileReadFromPathOptions;
|
||||||
|
use once_cell::sync::Lazy;
|
||||||
|
pub use package_json::NpmInstallDepsProvider;
|
||||||
|
pub use package_json::PackageJsonDepValueParseWithLocationError;
|
||||||
|
use serde::Deserialize;
|
||||||
|
use serde::Serialize;
|
||||||
|
use sys_traits::EnvHomeDir;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
use crate::cache;
|
|
||||||
use crate::cache::DenoDirProvider;
|
use crate::cache::DenoDirProvider;
|
||||||
use crate::file_fetcher::FileFetcher;
|
use crate::file_fetcher::CliFileFetcher;
|
||||||
|
use crate::sys::CliSys;
|
||||||
use crate::util::fs::canonicalize_path_maybe_not_exists;
|
use crate::util::fs::canonicalize_path_maybe_not_exists;
|
||||||
use crate::version;
|
use crate::version;
|
||||||
|
|
||||||
use deno_config::deno_json::FmtConfig;
|
|
||||||
use deno_config::deno_json::LintConfig;
|
|
||||||
use deno_config::deno_json::TestConfig;
|
|
||||||
|
|
||||||
pub fn npm_registry_url() -> &'static Url {
|
pub fn npm_registry_url() -> &'static Url {
|
||||||
static NPM_REGISTRY_DEFAULT_URL: Lazy<Url> = Lazy::new(|| {
|
static NPM_REGISTRY_DEFAULT_URL: Lazy<Url> = Lazy::new(|| {
|
||||||
let env_var_name = "NPM_CONFIG_REGISTRY";
|
let env_var_name = "NPM_CONFIG_REGISTRY";
|
||||||
|
@ -217,52 +219,6 @@ pub fn ts_config_to_transpile_and_emit_options(
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Indicates how cached source files should be handled.
|
|
||||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
|
||||||
pub enum CacheSetting {
|
|
||||||
/// Only the cached files should be used. Any files not in the cache will
|
|
||||||
/// error. This is the equivalent of `--cached-only` in the CLI.
|
|
||||||
Only,
|
|
||||||
/// No cached source files should be used, and all files should be reloaded.
|
|
||||||
/// This is the equivalent of `--reload` in the CLI.
|
|
||||||
ReloadAll,
|
|
||||||
/// Only some cached resources should be used. This is the equivalent of
|
|
||||||
/// `--reload=jsr:@std/http/file-server` or
|
|
||||||
/// `--reload=jsr:@std/http/file-server,jsr:@std/assert/assert-equals`.
|
|
||||||
ReloadSome(Vec<String>),
|
|
||||||
/// The usability of a cached value is determined by analyzing the cached
|
|
||||||
/// headers and other metadata associated with a cached response, reloading
|
|
||||||
/// any cached "non-fresh" cached responses.
|
|
||||||
RespectHeaders,
|
|
||||||
/// The cached source files should be used for local modules. This is the
|
|
||||||
/// default behavior of the CLI.
|
|
||||||
Use,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CacheSetting {
|
|
||||||
pub fn as_npm_cache_setting(&self) -> NpmCacheSetting {
|
|
||||||
match self {
|
|
||||||
CacheSetting::Only => NpmCacheSetting::Only,
|
|
||||||
CacheSetting::ReloadAll => NpmCacheSetting::ReloadAll,
|
|
||||||
CacheSetting::ReloadSome(values) => {
|
|
||||||
if values.iter().any(|v| v == "npm:") {
|
|
||||||
NpmCacheSetting::ReloadAll
|
|
||||||
} else {
|
|
||||||
NpmCacheSetting::ReloadSome {
|
|
||||||
npm_package_names: values
|
|
||||||
.iter()
|
|
||||||
.filter_map(|v| v.strip_prefix("npm:"))
|
|
||||||
.map(|n| n.to_string())
|
|
||||||
.collect(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CacheSetting::RespectHeaders => unreachable!(), // not supported
|
|
||||||
CacheSetting::Use => NpmCacheSetting::Use,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct WorkspaceBenchOptions {
|
pub struct WorkspaceBenchOptions {
|
||||||
pub filter: Option<String>,
|
pub filter: Option<String>,
|
||||||
pub json: bool,
|
pub json: bool,
|
||||||
|
@ -616,7 +572,7 @@ fn discover_npmrc(
|
||||||
// TODO(bartlomieju): update to read both files - one in the project root and one and
|
// TODO(bartlomieju): update to read both files - one in the project root and one and
|
||||||
// home dir and then merge them.
|
// home dir and then merge them.
|
||||||
// 3. Try `.npmrc` in the user's home directory
|
// 3. Try `.npmrc` in the user's home directory
|
||||||
if let Some(home_dir) = cache::home_dir() {
|
if let Some(home_dir) = crate::sys::CliSys::default().env_home_dir() {
|
||||||
match try_to_read_npmrc(&home_dir) {
|
match try_to_read_npmrc(&home_dir) {
|
||||||
Ok(Some((source, path))) => {
|
Ok(Some((source, path))) => {
|
||||||
return try_to_parse_npmrc(source, &path).map(|r| (r, Some(path)));
|
return try_to_parse_npmrc(source, &path).map(|r| (r, Some(path)));
|
||||||
|
@ -649,7 +605,8 @@ pub fn create_default_npmrc() -> Arc<ResolvedNpmRc> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Error, Debug, Clone)]
|
#[derive(Error, Debug, Clone, deno_error::JsError)]
|
||||||
|
#[class(generic)]
|
||||||
pub enum RootCertStoreLoadError {
|
pub enum RootCertStoreLoadError {
|
||||||
#[error(
|
#[error(
|
||||||
"Unknown certificate store \"{0}\" specified (allowed: \"system,mozilla\")"
|
"Unknown certificate store \"{0}\" specified (allowed: \"system,mozilla\")"
|
||||||
|
@ -815,7 +772,9 @@ pub struct CliOptions {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CliOptions {
|
impl CliOptions {
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn new(
|
pub fn new(
|
||||||
|
sys: &CliSys,
|
||||||
flags: Arc<Flags>,
|
flags: Arc<Flags>,
|
||||||
initial_cwd: PathBuf,
|
initial_cwd: PathBuf,
|
||||||
maybe_lockfile: Option<Arc<CliLockfile>>,
|
maybe_lockfile: Option<Arc<CliLockfile>>,
|
||||||
|
@ -840,8 +799,10 @@ impl CliOptions {
|
||||||
}
|
}
|
||||||
|
|
||||||
let maybe_lockfile = maybe_lockfile.filter(|_| !force_global_cache);
|
let maybe_lockfile = maybe_lockfile.filter(|_| !force_global_cache);
|
||||||
let deno_dir_provider =
|
let deno_dir_provider = Arc::new(DenoDirProvider::new(
|
||||||
Arc::new(DenoDirProvider::new(flags.internal.cache_path.clone()));
|
sys.clone(),
|
||||||
|
flags.internal.cache_path.clone(),
|
||||||
|
));
|
||||||
let maybe_node_modules_folder = resolve_node_modules_folder(
|
let maybe_node_modules_folder = resolve_node_modules_folder(
|
||||||
&initial_cwd,
|
&initial_cwd,
|
||||||
&flags,
|
&flags,
|
||||||
|
@ -866,7 +827,7 @@ impl CliOptions {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_flags(flags: Arc<Flags>) -> Result<Self, AnyError> {
|
pub fn from_flags(sys: &CliSys, flags: Arc<Flags>) -> Result<Self, AnyError> {
|
||||||
let initial_cwd =
|
let initial_cwd =
|
||||||
std::env::current_dir().with_context(|| "Failed getting cwd.")?;
|
std::env::current_dir().with_context(|| "Failed getting cwd.")?;
|
||||||
let maybe_vendor_override = flags.vendor.map(|v| match v {
|
let maybe_vendor_override = flags.vendor.map(|v| match v {
|
||||||
|
@ -880,8 +841,6 @@ impl CliOptions {
|
||||||
} else {
|
} else {
|
||||||
&[]
|
&[]
|
||||||
};
|
};
|
||||||
let config_parse_options =
|
|
||||||
deno_config::deno_json::ConfigParseOptions::default();
|
|
||||||
let discover_pkg_json = flags.config_flag != ConfigFlag::Disabled
|
let discover_pkg_json = flags.config_flag != ConfigFlag::Disabled
|
||||||
&& !flags.no_npm
|
&& !flags.no_npm
|
||||||
&& !has_flag_env_var("DENO_NO_PACKAGE_JSON");
|
&& !has_flag_env_var("DENO_NO_PACKAGE_JSON");
|
||||||
|
@ -889,11 +848,9 @@ impl CliOptions {
|
||||||
log::debug!("package.json auto-discovery is disabled");
|
log::debug!("package.json auto-discovery is disabled");
|
||||||
}
|
}
|
||||||
WorkspaceDiscoverOptions {
|
WorkspaceDiscoverOptions {
|
||||||
fs: Default::default(), // use real fs
|
|
||||||
deno_json_cache: None,
|
deno_json_cache: None,
|
||||||
pkg_json_cache: Some(&node_resolver::PackageJsonThreadLocalCache),
|
pkg_json_cache: Some(&node_resolver::PackageJsonThreadLocalCache),
|
||||||
workspace_cache: None,
|
workspace_cache: None,
|
||||||
config_parse_options,
|
|
||||||
additional_config_file_names,
|
additional_config_file_names,
|
||||||
discover_pkg_json,
|
discover_pkg_json,
|
||||||
maybe_vendor_override,
|
maybe_vendor_override,
|
||||||
|
@ -911,6 +868,7 @@ impl CliOptions {
|
||||||
ConfigFlag::Discover => {
|
ConfigFlag::Discover => {
|
||||||
if let Some(start_paths) = flags.config_path_args(&initial_cwd) {
|
if let Some(start_paths) = flags.config_path_args(&initial_cwd) {
|
||||||
WorkspaceDirectory::discover(
|
WorkspaceDirectory::discover(
|
||||||
|
sys,
|
||||||
WorkspaceDiscoverStart::Paths(&start_paths),
|
WorkspaceDiscoverStart::Paths(&start_paths),
|
||||||
&resolve_workspace_discover_options(),
|
&resolve_workspace_discover_options(),
|
||||||
)?
|
)?
|
||||||
|
@ -921,6 +879,7 @@ impl CliOptions {
|
||||||
ConfigFlag::Path(path) => {
|
ConfigFlag::Path(path) => {
|
||||||
let config_path = normalize_path(initial_cwd.join(path));
|
let config_path = normalize_path(initial_cwd.join(path));
|
||||||
WorkspaceDirectory::discover(
|
WorkspaceDirectory::discover(
|
||||||
|
sys,
|
||||||
WorkspaceDiscoverStart::ConfigFile(&config_path),
|
WorkspaceDiscoverStart::ConfigFile(&config_path),
|
||||||
&resolve_workspace_discover_options(),
|
&resolve_workspace_discover_options(),
|
||||||
)?
|
)?
|
||||||
|
@ -959,6 +918,7 @@ impl CliOptions {
|
||||||
};
|
};
|
||||||
|
|
||||||
let maybe_lock_file = CliLockfile::discover(
|
let maybe_lock_file = CliLockfile::discover(
|
||||||
|
sys,
|
||||||
&flags,
|
&flags,
|
||||||
&start_dir.workspace,
|
&start_dir.workspace,
|
||||||
external_import_map.as_ref().map(|(_, v)| v),
|
external_import_map.as_ref().map(|(_, v)| v),
|
||||||
|
@ -967,6 +927,7 @@ impl CliOptions {
|
||||||
log::debug!("Finished config loading.");
|
log::debug!("Finished config loading.");
|
||||||
|
|
||||||
Self::new(
|
Self::new(
|
||||||
|
sys,
|
||||||
flags,
|
flags,
|
||||||
initial_cwd,
|
initial_cwd,
|
||||||
maybe_lock_file.map(Arc::new),
|
maybe_lock_file.map(Arc::new),
|
||||||
|
@ -1037,24 +998,24 @@ impl CliOptions {
|
||||||
// https://nodejs.org/api/process.html
|
// https://nodejs.org/api/process.html
|
||||||
match target.as_str() {
|
match target.as_str() {
|
||||||
"aarch64-apple-darwin" => NpmSystemInfo {
|
"aarch64-apple-darwin" => NpmSystemInfo {
|
||||||
os: "darwin".to_string(),
|
os: "darwin".into(),
|
||||||
cpu: "arm64".to_string(),
|
cpu: "arm64".into(),
|
||||||
},
|
},
|
||||||
"aarch64-unknown-linux-gnu" => NpmSystemInfo {
|
"aarch64-unknown-linux-gnu" => NpmSystemInfo {
|
||||||
os: "linux".to_string(),
|
os: "linux".into(),
|
||||||
cpu: "arm64".to_string(),
|
cpu: "arm64".into(),
|
||||||
},
|
},
|
||||||
"x86_64-apple-darwin" => NpmSystemInfo {
|
"x86_64-apple-darwin" => NpmSystemInfo {
|
||||||
os: "darwin".to_string(),
|
os: "darwin".into(),
|
||||||
cpu: "x64".to_string(),
|
cpu: "x64".into(),
|
||||||
},
|
},
|
||||||
"x86_64-unknown-linux-gnu" => NpmSystemInfo {
|
"x86_64-unknown-linux-gnu" => NpmSystemInfo {
|
||||||
os: "linux".to_string(),
|
os: "linux".into(),
|
||||||
cpu: "x64".to_string(),
|
cpu: "x64".into(),
|
||||||
},
|
},
|
||||||
"x86_64-pc-windows-msvc" => NpmSystemInfo {
|
"x86_64-pc-windows-msvc" => NpmSystemInfo {
|
||||||
os: "win32".to_string(),
|
os: "win32".into(),
|
||||||
cpu: "x64".to_string(),
|
cpu: "x64".into(),
|
||||||
},
|
},
|
||||||
value => {
|
value => {
|
||||||
log::warn!(
|
log::warn!(
|
||||||
|
@ -1091,7 +1052,7 @@ impl CliOptions {
|
||||||
|
|
||||||
pub async fn create_workspace_resolver(
|
pub async fn create_workspace_resolver(
|
||||||
&self,
|
&self,
|
||||||
file_fetcher: &FileFetcher,
|
file_fetcher: &CliFileFetcher,
|
||||||
pkg_json_dep_resolution: PackageJsonDepResolution,
|
pkg_json_dep_resolution: PackageJsonDepResolution,
|
||||||
) -> Result<WorkspaceResolver, AnyError> {
|
) -> Result<WorkspaceResolver, AnyError> {
|
||||||
let overrode_no_import_map: bool = self
|
let overrode_no_import_map: bool = self
|
||||||
|
@ -1138,11 +1099,11 @@ impl CliOptions {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Ok(self.workspace().create_resolver(
|
Ok(self.workspace().create_resolver(
|
||||||
|
&CliSys::default(),
|
||||||
CreateResolverOptions {
|
CreateResolverOptions {
|
||||||
pkg_json_dep_resolution,
|
pkg_json_dep_resolution,
|
||||||
specified_import_map: cli_arg_specified_import_map,
|
specified_import_map: cli_arg_specified_import_map,
|
||||||
},
|
},
|
||||||
|path| Ok(std::fs::read_to_string(path)?),
|
|
||||||
)?)
|
)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1284,11 +1245,14 @@ impl CliOptions {
|
||||||
|
|
||||||
pub fn node_modules_dir(
|
pub fn node_modules_dir(
|
||||||
&self,
|
&self,
|
||||||
) -> Result<Option<NodeModulesDirMode>, AnyError> {
|
) -> Result<
|
||||||
|
Option<NodeModulesDirMode>,
|
||||||
|
deno_config::deno_json::NodeModulesDirParseError,
|
||||||
|
> {
|
||||||
if let Some(flag) = self.flags.node_modules_dir {
|
if let Some(flag) = self.flags.node_modules_dir {
|
||||||
return Ok(Some(flag));
|
return Ok(Some(flag));
|
||||||
}
|
}
|
||||||
self.workspace().node_modules_dir().map_err(Into::into)
|
self.workspace().node_modules_dir()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn vendor_dir_path(&self) -> Option<&PathBuf> {
|
pub fn vendor_dir_path(&self) -> Option<&PathBuf> {
|
||||||
|
@ -1298,7 +1262,7 @@ impl CliOptions {
|
||||||
pub fn resolve_ts_config_for_emit(
|
pub fn resolve_ts_config_for_emit(
|
||||||
&self,
|
&self,
|
||||||
config_type: TsConfigType,
|
config_type: TsConfigType,
|
||||||
) -> Result<TsConfigForEmit, AnyError> {
|
) -> Result<TsConfigForEmit, ConfigFileError> {
|
||||||
self.workspace().resolve_ts_config_for_emit(config_type)
|
self.workspace().resolve_ts_config_for_emit(config_type)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1327,7 +1291,7 @@ impl CliOptions {
|
||||||
|
|
||||||
pub fn to_compiler_option_types(
|
pub fn to_compiler_option_types(
|
||||||
&self,
|
&self,
|
||||||
) -> Result<Vec<deno_graph::ReferrerImports>, AnyError> {
|
) -> Result<Vec<deno_graph::ReferrerImports>, serde_json::Error> {
|
||||||
self
|
self
|
||||||
.workspace()
|
.workspace()
|
||||||
.to_compiler_option_types()
|
.to_compiler_option_types()
|
||||||
|
@ -1397,9 +1361,7 @@ impl CliOptions {
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn resolve_deno_lint_config(
|
pub fn resolve_deno_lint_config(&self) -> Result<DenoLintConfig, AnyError> {
|
||||||
&self,
|
|
||||||
) -> Result<deno_lint::linter::LintConfig, AnyError> {
|
|
||||||
let ts_config_result =
|
let ts_config_result =
|
||||||
self.resolve_ts_config_for_emit(TsConfigType::Emit)?;
|
self.resolve_ts_config_for_emit(TsConfigType::Emit)?;
|
||||||
|
|
||||||
|
@ -1408,11 +1370,11 @@ impl CliOptions {
|
||||||
ts_config_result.ts_config,
|
ts_config_result.ts_config,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
Ok(deno_lint::linter::LintConfig {
|
Ok(DenoLintConfig {
|
||||||
default_jsx_factory: (!transpile_options.jsx_automatic)
|
default_jsx_factory: (!transpile_options.jsx_automatic)
|
||||||
.then(|| transpile_options.jsx_factory.clone()),
|
.then_some(transpile_options.jsx_factory),
|
||||||
default_jsx_fragment_factory: (!transpile_options.jsx_automatic)
|
default_jsx_fragment_factory: (!transpile_options.jsx_automatic)
|
||||||
.then(|| transpile_options.jsx_fragment_factory.clone()),
|
.then_some(transpile_options.jsx_fragment_factory),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1566,20 +1528,100 @@ impl CliOptions {
|
||||||
self.flags.no_npm
|
self.flags.no_npm
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn permission_flags(&self) -> &PermissionFlags {
|
|
||||||
&self.flags.permissions
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn permissions_options(&self) -> PermissionsOptions {
|
pub fn permissions_options(&self) -> PermissionsOptions {
|
||||||
fn files_to_urls(files: &[String]) -> Vec<Cow<'_, Url>> {
|
// bury this in here to ensure people use cli_options.permissions_options()
|
||||||
files
|
fn flags_to_options(flags: &PermissionFlags) -> PermissionsOptions {
|
||||||
.iter()
|
fn handle_allow<T: Default>(
|
||||||
.filter_map(|f| Url::parse(f).ok().map(Cow::Owned))
|
allow_all: bool,
|
||||||
.collect()
|
value: Option<T>,
|
||||||
|
) -> Option<T> {
|
||||||
|
if allow_all {
|
||||||
|
assert!(value.is_none());
|
||||||
|
Some(T::default())
|
||||||
|
} else {
|
||||||
|
value
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// get a list of urls to imply for --allow-import
|
PermissionsOptions {
|
||||||
let cli_arg_urls = self
|
allow_all: flags.allow_all,
|
||||||
|
allow_env: handle_allow(flags.allow_all, flags.allow_env.clone()),
|
||||||
|
deny_env: flags.deny_env.clone(),
|
||||||
|
allow_net: handle_allow(flags.allow_all, flags.allow_net.clone()),
|
||||||
|
deny_net: flags.deny_net.clone(),
|
||||||
|
allow_ffi: handle_allow(flags.allow_all, flags.allow_ffi.clone()),
|
||||||
|
deny_ffi: flags.deny_ffi.clone(),
|
||||||
|
allow_read: handle_allow(flags.allow_all, flags.allow_read.clone()),
|
||||||
|
deny_read: flags.deny_read.clone(),
|
||||||
|
allow_run: handle_allow(flags.allow_all, flags.allow_run.clone()),
|
||||||
|
deny_run: flags.deny_run.clone(),
|
||||||
|
allow_sys: handle_allow(flags.allow_all, flags.allow_sys.clone()),
|
||||||
|
deny_sys: flags.deny_sys.clone(),
|
||||||
|
allow_write: handle_allow(flags.allow_all, flags.allow_write.clone()),
|
||||||
|
deny_write: flags.deny_write.clone(),
|
||||||
|
allow_import: handle_allow(flags.allow_all, flags.allow_import.clone()),
|
||||||
|
prompt: !resolve_no_prompt(flags),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut permissions_options = flags_to_options(&self.flags.permissions);
|
||||||
|
self.augment_import_permissions(&mut permissions_options);
|
||||||
|
permissions_options
|
||||||
|
}
|
||||||
|
|
||||||
|
fn augment_import_permissions(&self, options: &mut PermissionsOptions) {
|
||||||
|
// do not add if the user specified --allow-all or --allow-import
|
||||||
|
if !options.allow_all && options.allow_import.is_none() {
|
||||||
|
options.allow_import = Some(self.implicit_allow_import());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn implicit_allow_import(&self) -> Vec<String> {
|
||||||
|
// allow importing from anywhere when using cached only
|
||||||
|
if self.cache_setting() == CacheSetting::Only {
|
||||||
|
vec![] // allow all imports
|
||||||
|
} else {
|
||||||
|
// implicitly allow some trusted hosts and the CLI arg urls
|
||||||
|
let cli_arg_urls = self.get_cli_arg_urls();
|
||||||
|
let builtin_allowed_import_hosts = [
|
||||||
|
"jsr.io:443",
|
||||||
|
"deno.land:443",
|
||||||
|
"esm.sh:443",
|
||||||
|
"cdn.jsdelivr.net:443",
|
||||||
|
"raw.githubusercontent.com:443",
|
||||||
|
"gist.githubusercontent.com:443",
|
||||||
|
];
|
||||||
|
let mut imports = Vec::with_capacity(
|
||||||
|
builtin_allowed_import_hosts.len() + cli_arg_urls.len() + 1,
|
||||||
|
);
|
||||||
|
imports
|
||||||
|
.extend(builtin_allowed_import_hosts.iter().map(|s| s.to_string()));
|
||||||
|
// also add the JSR_URL env var
|
||||||
|
if let Some(jsr_host) = allow_import_host_from_url(jsr_url()) {
|
||||||
|
if jsr_host != "jsr.io:443" {
|
||||||
|
imports.push(jsr_host);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// include the cli arg urls
|
||||||
|
for url in cli_arg_urls {
|
||||||
|
if let Some(host) = allow_import_host_from_url(&url) {
|
||||||
|
imports.push(host);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
imports
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_cli_arg_urls(&self) -> Vec<Cow<'_, Url>> {
|
||||||
|
fn files_to_urls(files: &[String]) -> Vec<Cow<'_, Url>> {
|
||||||
|
files.iter().filter_map(|f| file_to_url(f)).collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn file_to_url(file: &str) -> Option<Cow<'_, Url>> {
|
||||||
|
Url::parse(file).ok().map(Cow::Owned)
|
||||||
|
}
|
||||||
|
|
||||||
|
self
|
||||||
.resolve_main_module()
|
.resolve_main_module()
|
||||||
.ok()
|
.ok()
|
||||||
.map(|url| vec![Cow::Borrowed(url)])
|
.map(|url| vec![Cow::Borrowed(url)])
|
||||||
|
@ -1591,18 +1633,18 @@ impl CliOptions {
|
||||||
Some(files_to_urls(&check_flags.files))
|
Some(files_to_urls(&check_flags.files))
|
||||||
}
|
}
|
||||||
DenoSubcommand::Install(InstallFlags::Global(flags)) => {
|
DenoSubcommand::Install(InstallFlags::Global(flags)) => {
|
||||||
Url::parse(&flags.module_url)
|
file_to_url(&flags.module_url).map(|url| vec![url])
|
||||||
.ok()
|
|
||||||
.map(|url| vec![Cow::Owned(url)])
|
|
||||||
}
|
}
|
||||||
DenoSubcommand::Doc(DocFlags {
|
DenoSubcommand::Doc(DocFlags {
|
||||||
source_files: DocSourceFileFlag::Paths(paths),
|
source_files: DocSourceFileFlag::Paths(paths),
|
||||||
..
|
..
|
||||||
}) => Some(files_to_urls(paths)),
|
}) => Some(files_to_urls(paths)),
|
||||||
|
DenoSubcommand::Info(InfoFlags {
|
||||||
|
file: Some(file), ..
|
||||||
|
}) => file_to_url(file).map(|url| vec![url]),
|
||||||
_ => None,
|
_ => None,
|
||||||
})
|
})
|
||||||
.unwrap_or_default();
|
.unwrap_or_default()
|
||||||
self.flags.permissions.to_options(&cli_arg_urls)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reload_flag(&self) -> bool {
|
pub fn reload_flag(&self) -> bool {
|
||||||
|
@ -1993,15 +2035,17 @@ pub fn has_flag_env_var(name: &str) -> bool {
|
||||||
pub fn npm_pkg_req_ref_to_binary_command(
|
pub fn npm_pkg_req_ref_to_binary_command(
|
||||||
req_ref: &NpmPackageReqReference,
|
req_ref: &NpmPackageReqReference,
|
||||||
) -> String {
|
) -> String {
|
||||||
let binary_name = req_ref.sub_path().unwrap_or(req_ref.req().name.as_str());
|
req_ref
|
||||||
binary_name.to_string()
|
.sub_path()
|
||||||
|
.map(|s| s.to_string())
|
||||||
|
.unwrap_or_else(|| req_ref.req().name.to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn config_to_deno_graph_workspace_member(
|
pub fn config_to_deno_graph_workspace_member(
|
||||||
config: &ConfigFile,
|
config: &ConfigFile,
|
||||||
) -> Result<deno_graph::WorkspaceMember, AnyError> {
|
) -> Result<deno_graph::WorkspaceMember, AnyError> {
|
||||||
let name = match &config.json.name {
|
let name: StackString = match &config.json.name {
|
||||||
Some(name) => name.clone(),
|
Some(name) => name.as_str().into(),
|
||||||
None => bail!("Missing 'name' field in config file."),
|
None => bail!("Missing 'name' field in config file."),
|
||||||
};
|
};
|
||||||
let version = match &config.json.version {
|
let version = match &config.json.version {
|
||||||
|
@ -2036,6 +2080,20 @@ fn load_env_variables_from_env_file(filename: Option<&Vec<String>>) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Gets the --allow-import host from the provided url
|
||||||
|
fn allow_import_host_from_url(url: &Url) -> Option<String> {
|
||||||
|
let host = url.host()?;
|
||||||
|
if let Some(port) = url.port() {
|
||||||
|
Some(format!("{}:{}", host, port))
|
||||||
|
} else {
|
||||||
|
match url.scheme() {
|
||||||
|
"https" => Some(format!("{}:443", host)),
|
||||||
|
"http" => Some(format!("{}:80", host)),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub enum NpmCachingStrategy {
|
pub enum NpmCachingStrategy {
|
||||||
Eager,
|
Eager,
|
||||||
|
@ -2043,7 +2101,7 @@ pub enum NpmCachingStrategy {
|
||||||
Manual,
|
Manual,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn otel_runtime_config() -> OtelRuntimeConfig {
|
pub fn otel_runtime_config() -> OtelRuntimeConfig {
|
||||||
OtelRuntimeConfig {
|
OtelRuntimeConfig {
|
||||||
runtime_name: Cow::Borrowed("deno"),
|
runtime_name: Cow::Borrowed("deno"),
|
||||||
runtime_version: Cow::Borrowed(crate::version::DENO_VERSION_INFO.deno),
|
runtime_version: Cow::Borrowed(crate::version::DENO_VERSION_INFO.deno),
|
||||||
|
@ -2064,12 +2122,7 @@ mod test {
|
||||||
let cwd = &std::env::current_dir().unwrap();
|
let cwd = &std::env::current_dir().unwrap();
|
||||||
let config_specifier =
|
let config_specifier =
|
||||||
ModuleSpecifier::parse("file:///deno/deno.jsonc").unwrap();
|
ModuleSpecifier::parse("file:///deno/deno.jsonc").unwrap();
|
||||||
let config_file = ConfigFile::new(
|
let config_file = ConfigFile::new(config_text, config_specifier).unwrap();
|
||||||
config_text,
|
|
||||||
config_specifier,
|
|
||||||
&deno_config::deno_json::ConfigParseOptions::default(),
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
let actual = resolve_import_map_specifier(
|
let actual = resolve_import_map_specifier(
|
||||||
Some("import-map.json"),
|
Some("import-map.json"),
|
||||||
Some(&config_file),
|
Some(&config_file),
|
||||||
|
@ -2088,12 +2141,7 @@ mod test {
|
||||||
let config_text = r#"{}"#;
|
let config_text = r#"{}"#;
|
||||||
let config_specifier =
|
let config_specifier =
|
||||||
ModuleSpecifier::parse("file:///deno/deno.jsonc").unwrap();
|
ModuleSpecifier::parse("file:///deno/deno.jsonc").unwrap();
|
||||||
let config_file = ConfigFile::new(
|
let config_file = ConfigFile::new(config_text, config_specifier).unwrap();
|
||||||
config_text,
|
|
||||||
config_specifier,
|
|
||||||
&deno_config::deno_json::ConfigParseOptions::default(),
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
let actual = resolve_import_map_specifier(
|
let actual = resolve_import_map_specifier(
|
||||||
None,
|
None,
|
||||||
Some(&config_file),
|
Some(&config_file),
|
||||||
|
@ -2140,4 +2188,26 @@ mod test {
|
||||||
let reg_api_url = jsr_api_url();
|
let reg_api_url = jsr_api_url();
|
||||||
assert!(reg_api_url.as_str().ends_with('/'));
|
assert!(reg_api_url.as_str().ends_with('/'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_allow_import_host_from_url() {
|
||||||
|
fn parse(text: &str) -> Option<String> {
|
||||||
|
allow_import_host_from_url(&Url::parse(text).unwrap())
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
parse("http://127.0.0.1:4250"),
|
||||||
|
Some("127.0.0.1:4250".to_string())
|
||||||
|
);
|
||||||
|
assert_eq!(parse("http://jsr.io"), Some("jsr.io:80".to_string()));
|
||||||
|
assert_eq!(
|
||||||
|
parse("https://example.com"),
|
||||||
|
Some("example.com:443".to_string())
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
parse("http://example.com"),
|
||||||
|
Some("example.com:80".to_string())
|
||||||
|
);
|
||||||
|
assert_eq!(parse("file:///example.com"), None);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
@ -11,19 +11,20 @@ use deno_package_json::PackageJsonDepValueParseError;
|
||||||
use deno_package_json::PackageJsonDepWorkspaceReq;
|
use deno_package_json::PackageJsonDepWorkspaceReq;
|
||||||
use deno_semver::npm::NpmPackageReqReference;
|
use deno_semver::npm::NpmPackageReqReference;
|
||||||
use deno_semver::package::PackageReq;
|
use deno_semver::package::PackageReq;
|
||||||
|
use deno_semver::StackString;
|
||||||
use deno_semver::VersionReq;
|
use deno_semver::VersionReq;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct InstallNpmRemotePkg {
|
pub struct InstallNpmRemotePkg {
|
||||||
pub alias: Option<String>,
|
pub alias: Option<StackString>,
|
||||||
pub base_dir: PathBuf,
|
pub base_dir: PathBuf,
|
||||||
pub req: PackageReq,
|
pub req: PackageReq,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct InstallNpmWorkspacePkg {
|
pub struct InstallNpmWorkspacePkg {
|
||||||
pub alias: Option<String>,
|
pub alias: Option<StackString>,
|
||||||
pub target_dir: PathBuf,
|
pub target_dir: PathBuf,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,7 +32,7 @@ pub struct InstallNpmWorkspacePkg {
|
||||||
#[error("Failed to install '{}'\n at {}", alias, location)]
|
#[error("Failed to install '{}'\n at {}", alias, location)]
|
||||||
pub struct PackageJsonDepValueParseWithLocationError {
|
pub struct PackageJsonDepValueParseWithLocationError {
|
||||||
pub location: Url,
|
pub location: Url,
|
||||||
pub alias: String,
|
pub alias: StackString,
|
||||||
#[source]
|
#[source]
|
||||||
pub source: PackageJsonDepValueParseError,
|
pub source: PackageJsonDepValueParseError,
|
||||||
}
|
}
|
||||||
|
@ -100,10 +101,8 @@ impl NpmInstallDepsProvider {
|
||||||
let mut pkg_pkgs = Vec::with_capacity(
|
let mut pkg_pkgs = Vec::with_capacity(
|
||||||
deps.dependencies.len() + deps.dev_dependencies.len(),
|
deps.dependencies.len() + deps.dev_dependencies.len(),
|
||||||
);
|
);
|
||||||
for (alias, dep) in deps
|
for (alias, dep) in
|
||||||
.dependencies
|
deps.dependencies.iter().chain(deps.dev_dependencies.iter())
|
||||||
.into_iter()
|
|
||||||
.chain(deps.dev_dependencies.into_iter())
|
|
||||||
{
|
{
|
||||||
let dep = match dep {
|
let dep = match dep {
|
||||||
Ok(dep) => dep,
|
Ok(dep) => dep,
|
||||||
|
@ -111,8 +110,8 @@ impl NpmInstallDepsProvider {
|
||||||
pkg_json_dep_errors.push(
|
pkg_json_dep_errors.push(
|
||||||
PackageJsonDepValueParseWithLocationError {
|
PackageJsonDepValueParseWithLocationError {
|
||||||
location: pkg_json.specifier(),
|
location: pkg_json.specifier(),
|
||||||
alias,
|
alias: alias.clone(),
|
||||||
source: err,
|
source: err.clone(),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
continue;
|
continue;
|
||||||
|
@ -121,28 +120,28 @@ impl NpmInstallDepsProvider {
|
||||||
match dep {
|
match dep {
|
||||||
PackageJsonDepValue::Req(pkg_req) => {
|
PackageJsonDepValue::Req(pkg_req) => {
|
||||||
let workspace_pkg = workspace_npm_pkgs.iter().find(|pkg| {
|
let workspace_pkg = workspace_npm_pkgs.iter().find(|pkg| {
|
||||||
pkg.matches_req(&pkg_req)
|
pkg.matches_req(pkg_req)
|
||||||
// do not resolve to the current package
|
// do not resolve to the current package
|
||||||
&& pkg.pkg_json.path != pkg_json.path
|
&& pkg.pkg_json.path != pkg_json.path
|
||||||
});
|
});
|
||||||
|
|
||||||
if let Some(pkg) = workspace_pkg {
|
if let Some(pkg) = workspace_pkg {
|
||||||
workspace_pkgs.push(InstallNpmWorkspacePkg {
|
workspace_pkgs.push(InstallNpmWorkspacePkg {
|
||||||
alias: Some(alias),
|
alias: Some(alias.clone()),
|
||||||
target_dir: pkg.pkg_json.dir_path().to_path_buf(),
|
target_dir: pkg.pkg_json.dir_path().to_path_buf(),
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
pkg_pkgs.push(InstallNpmRemotePkg {
|
pkg_pkgs.push(InstallNpmRemotePkg {
|
||||||
alias: Some(alias),
|
alias: Some(alias.clone()),
|
||||||
base_dir: pkg_json.dir_path().to_path_buf(),
|
base_dir: pkg_json.dir_path().to_path_buf(),
|
||||||
req: pkg_req,
|
req: pkg_req.clone(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PackageJsonDepValue::Workspace(workspace_version_req) => {
|
PackageJsonDepValue::Workspace(workspace_version_req) => {
|
||||||
let version_req = match workspace_version_req {
|
let version_req = match workspace_version_req {
|
||||||
PackageJsonDepWorkspaceReq::VersionReq(version_req) => {
|
PackageJsonDepWorkspaceReq::VersionReq(version_req) => {
|
||||||
version_req
|
version_req.clone()
|
||||||
}
|
}
|
||||||
PackageJsonDepWorkspaceReq::Tilde
|
PackageJsonDepWorkspaceReq::Tilde
|
||||||
| PackageJsonDepWorkspaceReq::Caret => {
|
| PackageJsonDepWorkspaceReq::Caret => {
|
||||||
|
@ -150,10 +149,10 @@ impl NpmInstallDepsProvider {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if let Some(pkg) = workspace_npm_pkgs.iter().find(|pkg| {
|
if let Some(pkg) = workspace_npm_pkgs.iter().find(|pkg| {
|
||||||
pkg.matches_name_and_version_req(&alias, &version_req)
|
pkg.matches_name_and_version_req(alias, &version_req)
|
||||||
}) {
|
}) {
|
||||||
workspace_pkgs.push(InstallNpmWorkspacePkg {
|
workspace_pkgs.push(InstallNpmWorkspacePkg {
|
||||||
alias: Some(alias),
|
alias: Some(alias.clone()),
|
||||||
target_dir: pkg.pkg_json.dir_path().to_path_buf(),
|
target_dir: pkg.pkg_json.dir_path().to_path_buf(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,369 +0,0 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
|
||||||
|
|
||||||
use base64::prelude::BASE64_STANDARD;
|
|
||||||
use base64::Engine;
|
|
||||||
use deno_core::ModuleSpecifier;
|
|
||||||
use log::debug;
|
|
||||||
use log::error;
|
|
||||||
use std::borrow::Cow;
|
|
||||||
use std::fmt;
|
|
||||||
use std::net::IpAddr;
|
|
||||||
use std::net::Ipv4Addr;
|
|
||||||
use std::net::Ipv6Addr;
|
|
||||||
use std::net::SocketAddr;
|
|
||||||
use std::str::FromStr;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
||||||
pub enum AuthTokenData {
|
|
||||||
Bearer(String),
|
|
||||||
Basic { username: String, password: String },
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
||||||
pub struct AuthToken {
|
|
||||||
host: AuthDomain,
|
|
||||||
token: AuthTokenData,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for AuthToken {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
match &self.token {
|
|
||||||
AuthTokenData::Bearer(token) => write!(f, "Bearer {token}"),
|
|
||||||
AuthTokenData::Basic { username, password } => {
|
|
||||||
let credentials = format!("{username}:{password}");
|
|
||||||
write!(f, "Basic {}", BASE64_STANDARD.encode(credentials))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A structure which contains bearer tokens that can be used when sending
|
|
||||||
/// requests to websites, intended to authorize access to private resources
|
|
||||||
/// such as remote modules.
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct AuthTokens(Vec<AuthToken>);
|
|
||||||
|
|
||||||
/// An authorization domain, either an exact or suffix match.
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
||||||
pub enum AuthDomain {
|
|
||||||
Ip(IpAddr),
|
|
||||||
IpPort(SocketAddr),
|
|
||||||
/// Suffix match, no dot. May include a port.
|
|
||||||
Suffix(Cow<'static, str>),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: ToString> From<T> for AuthDomain {
|
|
||||||
fn from(value: T) -> Self {
|
|
||||||
let s = value.to_string().to_lowercase();
|
|
||||||
if let Ok(ip) = SocketAddr::from_str(&s) {
|
|
||||||
return AuthDomain::IpPort(ip);
|
|
||||||
};
|
|
||||||
if s.starts_with('[') && s.ends_with(']') {
|
|
||||||
if let Ok(ip) = Ipv6Addr::from_str(&s[1..s.len() - 1]) {
|
|
||||||
return AuthDomain::Ip(ip.into());
|
|
||||||
}
|
|
||||||
} else if let Ok(ip) = Ipv4Addr::from_str(&s) {
|
|
||||||
return AuthDomain::Ip(ip.into());
|
|
||||||
}
|
|
||||||
if let Some(s) = s.strip_prefix('.') {
|
|
||||||
AuthDomain::Suffix(Cow::Owned(s.to_owned()))
|
|
||||||
} else {
|
|
||||||
AuthDomain::Suffix(Cow::Owned(s))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AuthDomain {
|
|
||||||
pub fn matches(&self, specifier: &ModuleSpecifier) -> bool {
|
|
||||||
let Some(host) = specifier.host_str() else {
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
match *self {
|
|
||||||
Self::Ip(ip) => {
|
|
||||||
let AuthDomain::Ip(parsed) = AuthDomain::from(host) else {
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
ip == parsed && specifier.port().is_none()
|
|
||||||
}
|
|
||||||
Self::IpPort(ip) => {
|
|
||||||
let AuthDomain::Ip(parsed) = AuthDomain::from(host) else {
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
ip.ip() == parsed && specifier.port() == Some(ip.port())
|
|
||||||
}
|
|
||||||
Self::Suffix(ref suffix) => {
|
|
||||||
let hostname = if let Some(port) = specifier.port() {
|
|
||||||
Cow::Owned(format!("{}:{}", host, port))
|
|
||||||
} else {
|
|
||||||
Cow::Borrowed(host)
|
|
||||||
};
|
|
||||||
|
|
||||||
if suffix.len() == hostname.len() {
|
|
||||||
return suffix == &hostname;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If it's a suffix match, ensure a dot
|
|
||||||
if hostname.ends_with(suffix.as_ref())
|
|
||||||
&& hostname.ends_with(&format!(".{suffix}"))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AuthTokens {
|
|
||||||
/// Create a new set of tokens based on the provided string. It is intended
|
|
||||||
/// that the string be the value of an environment variable and the string is
|
|
||||||
/// parsed for token values. The string is expected to be a semi-colon
|
|
||||||
/// separated string, where each value is `{token}@{hostname}`.
|
|
||||||
pub fn new(maybe_tokens_str: Option<String>) -> Self {
|
|
||||||
let mut tokens = Vec::new();
|
|
||||||
if let Some(tokens_str) = maybe_tokens_str {
|
|
||||||
for token_str in tokens_str.trim().split(';') {
|
|
||||||
if token_str.contains('@') {
|
|
||||||
let mut iter = token_str.rsplitn(2, '@');
|
|
||||||
let host = AuthDomain::from(iter.next().unwrap());
|
|
||||||
let token = iter.next().unwrap();
|
|
||||||
if token.contains(':') {
|
|
||||||
let mut iter = token.rsplitn(2, ':');
|
|
||||||
let password = iter.next().unwrap().to_owned();
|
|
||||||
let username = iter.next().unwrap().to_owned();
|
|
||||||
tokens.push(AuthToken {
|
|
||||||
host,
|
|
||||||
token: AuthTokenData::Basic { username, password },
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
tokens.push(AuthToken {
|
|
||||||
host,
|
|
||||||
token: AuthTokenData::Bearer(token.to_string()),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
error!("Badly formed auth token discarded.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
debug!("Parsed {} auth token(s).", tokens.len());
|
|
||||||
}
|
|
||||||
|
|
||||||
Self(tokens)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Attempt to match the provided specifier to the tokens in the set. The
|
|
||||||
/// matching occurs from the right of the hostname plus port, irrespective of
|
|
||||||
/// scheme. For example `https://www.deno.land:8080/` would match a token
|
|
||||||
/// with a host value of `deno.land:8080` but not match `www.deno.land`. The
|
|
||||||
/// matching is case insensitive.
|
|
||||||
pub fn get(&self, specifier: &ModuleSpecifier) -> Option<AuthToken> {
|
|
||||||
self.0.iter().find_map(|t| {
|
|
||||||
if t.host.matches(specifier) {
|
|
||||||
Some(t.clone())
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
use deno_core::resolve_url;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_auth_token() {
|
|
||||||
let auth_tokens = AuthTokens::new(Some("abc123@deno.land".to_string()));
|
|
||||||
let fixture = resolve_url("https://deno.land/x/mod.ts").unwrap();
|
|
||||||
assert_eq!(
|
|
||||||
auth_tokens.get(&fixture).unwrap().to_string(),
|
|
||||||
"Bearer abc123"
|
|
||||||
);
|
|
||||||
let fixture = resolve_url("https://www.deno.land/x/mod.ts").unwrap();
|
|
||||||
assert_eq!(
|
|
||||||
auth_tokens.get(&fixture).unwrap().to_string(),
|
|
||||||
"Bearer abc123".to_string()
|
|
||||||
);
|
|
||||||
let fixture = resolve_url("http://127.0.0.1:8080/x/mod.ts").unwrap();
|
|
||||||
assert_eq!(auth_tokens.get(&fixture), None);
|
|
||||||
let fixture =
|
|
||||||
resolve_url("https://deno.land.example.com/x/mod.ts").unwrap();
|
|
||||||
assert_eq!(auth_tokens.get(&fixture), None);
|
|
||||||
let fixture = resolve_url("https://deno.land:8080/x/mod.ts").unwrap();
|
|
||||||
assert_eq!(auth_tokens.get(&fixture), None);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_auth_tokens_multiple() {
|
|
||||||
let auth_tokens =
|
|
||||||
AuthTokens::new(Some("abc123@deno.land;def456@example.com".to_string()));
|
|
||||||
let fixture = resolve_url("https://deno.land/x/mod.ts").unwrap();
|
|
||||||
assert_eq!(
|
|
||||||
auth_tokens.get(&fixture).unwrap().to_string(),
|
|
||||||
"Bearer abc123".to_string()
|
|
||||||
);
|
|
||||||
let fixture = resolve_url("http://example.com/a/file.ts").unwrap();
|
|
||||||
assert_eq!(
|
|
||||||
auth_tokens.get(&fixture).unwrap().to_string(),
|
|
||||||
"Bearer def456".to_string()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_auth_tokens_space() {
|
|
||||||
let auth_tokens = AuthTokens::new(Some(
|
|
||||||
" abc123@deno.land;def456@example.com\t".to_string(),
|
|
||||||
));
|
|
||||||
let fixture = resolve_url("https://deno.land/x/mod.ts").unwrap();
|
|
||||||
assert_eq!(
|
|
||||||
auth_tokens.get(&fixture).unwrap().to_string(),
|
|
||||||
"Bearer abc123".to_string()
|
|
||||||
);
|
|
||||||
let fixture = resolve_url("http://example.com/a/file.ts").unwrap();
|
|
||||||
assert_eq!(
|
|
||||||
auth_tokens.get(&fixture).unwrap().to_string(),
|
|
||||||
"Bearer def456".to_string()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_auth_tokens_newline() {
|
|
||||||
let auth_tokens = AuthTokens::new(Some(
|
|
||||||
"\nabc123@deno.land;def456@example.com\n".to_string(),
|
|
||||||
));
|
|
||||||
let fixture = resolve_url("https://deno.land/x/mod.ts").unwrap();
|
|
||||||
assert_eq!(
|
|
||||||
auth_tokens.get(&fixture).unwrap().to_string(),
|
|
||||||
"Bearer abc123".to_string()
|
|
||||||
);
|
|
||||||
let fixture = resolve_url("http://example.com/a/file.ts").unwrap();
|
|
||||||
assert_eq!(
|
|
||||||
auth_tokens.get(&fixture).unwrap().to_string(),
|
|
||||||
"Bearer def456".to_string()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_auth_tokens_port() {
|
|
||||||
let auth_tokens =
|
|
||||||
AuthTokens::new(Some("abc123@deno.land:8080".to_string()));
|
|
||||||
let fixture = resolve_url("https://deno.land/x/mod.ts").unwrap();
|
|
||||||
assert_eq!(auth_tokens.get(&fixture), None);
|
|
||||||
let fixture = resolve_url("http://deno.land:8080/x/mod.ts").unwrap();
|
|
||||||
assert_eq!(
|
|
||||||
auth_tokens.get(&fixture).unwrap().to_string(),
|
|
||||||
"Bearer abc123".to_string()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_auth_tokens_contain_at() {
|
|
||||||
let auth_tokens = AuthTokens::new(Some("abc@123@deno.land".to_string()));
|
|
||||||
let fixture = resolve_url("https://deno.land/x/mod.ts").unwrap();
|
|
||||||
assert_eq!(
|
|
||||||
auth_tokens.get(&fixture).unwrap().to_string(),
|
|
||||||
"Bearer abc@123".to_string()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_auth_token_basic() {
|
|
||||||
let auth_tokens = AuthTokens::new(Some("abc:123@deno.land".to_string()));
|
|
||||||
let fixture = resolve_url("https://deno.land/x/mod.ts").unwrap();
|
|
||||||
assert_eq!(
|
|
||||||
auth_tokens.get(&fixture).unwrap().to_string(),
|
|
||||||
"Basic YWJjOjEyMw=="
|
|
||||||
);
|
|
||||||
let fixture = resolve_url("https://www.deno.land/x/mod.ts").unwrap();
|
|
||||||
assert_eq!(
|
|
||||||
auth_tokens.get(&fixture).unwrap().to_string(),
|
|
||||||
"Basic YWJjOjEyMw==".to_string()
|
|
||||||
);
|
|
||||||
let fixture = resolve_url("http://127.0.0.1:8080/x/mod.ts").unwrap();
|
|
||||||
assert_eq!(auth_tokens.get(&fixture), None);
|
|
||||||
let fixture =
|
|
||||||
resolve_url("https://deno.land.example.com/x/mod.ts").unwrap();
|
|
||||||
assert_eq!(auth_tokens.get(&fixture), None);
|
|
||||||
let fixture = resolve_url("https://deno.land:8080/x/mod.ts").unwrap();
|
|
||||||
assert_eq!(auth_tokens.get(&fixture), None);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_parse_ip() {
|
|
||||||
let ip = AuthDomain::from("[2001:db8:a::123]");
|
|
||||||
assert_eq!("Ip(2001:db8:a::123)", format!("{ip:?}"));
|
|
||||||
let ip = AuthDomain::from("[2001:db8:a::123]:8080");
|
|
||||||
assert_eq!("IpPort([2001:db8:a::123]:8080)", format!("{ip:?}"));
|
|
||||||
let ip = AuthDomain::from("1.1.1.1");
|
|
||||||
assert_eq!("Ip(1.1.1.1)", format!("{ip:?}"));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_case_insensitive() {
|
|
||||||
let domain = AuthDomain::from("EXAMPLE.com");
|
|
||||||
assert!(
|
|
||||||
domain.matches(&ModuleSpecifier::parse("http://example.com").unwrap())
|
|
||||||
);
|
|
||||||
assert!(
|
|
||||||
domain.matches(&ModuleSpecifier::parse("http://example.COM").unwrap())
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_matches() {
|
|
||||||
let candidates = [
|
|
||||||
"example.com",
|
|
||||||
"www.example.com",
|
|
||||||
"1.1.1.1",
|
|
||||||
"[2001:db8:a::123]",
|
|
||||||
// These will never match
|
|
||||||
"example.com.evil.com",
|
|
||||||
"1.1.1.1.evil.com",
|
|
||||||
"notexample.com",
|
|
||||||
"www.notexample.com",
|
|
||||||
];
|
|
||||||
let domains = [
|
|
||||||
("example.com", vec!["example.com", "www.example.com"]),
|
|
||||||
(".example.com", vec!["example.com", "www.example.com"]),
|
|
||||||
("www.example.com", vec!["www.example.com"]),
|
|
||||||
("1.1.1.1", vec!["1.1.1.1"]),
|
|
||||||
("[2001:db8:a::123]", vec!["[2001:db8:a::123]"]),
|
|
||||||
];
|
|
||||||
let url = |c: &str| ModuleSpecifier::parse(&format!("http://{c}")).unwrap();
|
|
||||||
let url_port =
|
|
||||||
|c: &str| ModuleSpecifier::parse(&format!("http://{c}:8080")).unwrap();
|
|
||||||
|
|
||||||
// Generate each candidate with and without a port
|
|
||||||
let candidates = candidates
|
|
||||||
.into_iter()
|
|
||||||
.flat_map(|c| [url(c), url_port(c)])
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
for (domain, expected_domain) in domains {
|
|
||||||
// Test without a port -- all candidates return without a port
|
|
||||||
let auth_domain = AuthDomain::from(domain);
|
|
||||||
let actual = candidates
|
|
||||||
.iter()
|
|
||||||
.filter(|c| auth_domain.matches(c))
|
|
||||||
.cloned()
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
let expected = expected_domain.iter().map(|u| url(u)).collect::<Vec<_>>();
|
|
||||||
assert_eq!(actual, expected);
|
|
||||||
|
|
||||||
// Test with a port, all candidates return with a port
|
|
||||||
let auth_domain = AuthDomain::from(&format!("{domain}:8080"));
|
|
||||||
let actual = candidates
|
|
||||||
.iter()
|
|
||||||
.filter(|c| auth_domain.matches(c))
|
|
||||||
.cloned()
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
let expected = expected_domain
|
|
||||||
.iter()
|
|
||||||
.map(|u| url_port(u))
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
assert_eq!(actual, expected);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
const cacheName = "cache-v1";
|
const cacheName = "cache-v1";
|
||||||
const cache = await caches.open(cacheName);
|
const cache = await caches.open(cacheName);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
Deno.bench("echo deno", async () => {
|
Deno.bench("echo deno", async () => {
|
||||||
await new Deno.Command("echo", { args: ["deno"] }).output();
|
await new Deno.Command("echo", { args: ["deno"] }).output();
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
// deno-lint-ignore-file no-console
|
// deno-lint-ignore-file no-console
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
// v8 builtin that's close to the upper bound non-NOPs
|
// v8 builtin that's close to the upper bound non-NOPs
|
||||||
Deno.bench("date_now", { n: 5e5 }, () => {
|
Deno.bench("date_now", { n: 5e5 }, () => {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
// deno-lint-ignore-file no-console no-process-globals
|
// deno-lint-ignore-file no-console no-process-globals
|
||||||
|
|
||||||
let [total, count] = typeof Deno !== "undefined"
|
let [total, count] = typeof Deno !== "undefined"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
let total = 5;
|
let total = 5;
|
||||||
let current = "";
|
let current = "";
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
/** @jsx h */
|
/** @jsx h */
|
||||||
import results from "./deno.json" assert { type: "json" };
|
import results from "./deno.json" assert { type: "json" };
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
// deno-lint-ignore-file no-console no-process-globals
|
// deno-lint-ignore-file no-console no-process-globals
|
||||||
|
|
||||||
let [total, count] = typeof Deno !== "undefined"
|
let [total, count] = typeof Deno !== "undefined"
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::path::Path;
|
||||||
|
use std::str::FromStr;
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
use deno_core::serde::Deserialize;
|
use deno_core::serde::Deserialize;
|
||||||
use deno_core::serde_json;
|
use deno_core::serde_json;
|
||||||
use deno_core::serde_json::json;
|
use deno_core::serde_json::json;
|
||||||
use deno_core::serde_json::Value;
|
use deno_core::serde_json::Value;
|
||||||
use lsp_types::Uri;
|
use lsp_types::Uri;
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::path::Path;
|
|
||||||
use std::str::FromStr;
|
|
||||||
use std::time::Duration;
|
|
||||||
use test_util::lsp::LspClientBuilder;
|
use test_util::lsp::LspClientBuilder;
|
||||||
use test_util::PathRef;
|
use test_util::PathRef;
|
||||||
use tower_lsp::lsp_types as lsp;
|
use tower_lsp::lsp_types as lsp;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
use deno_bench_util::bencher::benchmark_group;
|
use deno_bench_util::bencher::benchmark_group;
|
||||||
use deno_bench_util::bencher::benchmark_main;
|
use deno_bench_util::bencher::benchmark_main;
|
||||||
|
|
|
@ -1,11 +1,8 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
#![allow(clippy::print_stdout)]
|
#![allow(clippy::print_stdout)]
|
||||||
#![allow(clippy::print_stderr)]
|
#![allow(clippy::print_stderr)]
|
||||||
|
|
||||||
use deno_core::error::AnyError;
|
|
||||||
use deno_core::serde_json;
|
|
||||||
use deno_core::serde_json::Value;
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::convert::From;
|
use std::convert::From;
|
||||||
use std::env;
|
use std::env;
|
||||||
|
@ -15,6 +12,10 @@ use std::path::PathBuf;
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
use std::process::Stdio;
|
use std::process::Stdio;
|
||||||
use std::time::SystemTime;
|
use std::time::SystemTime;
|
||||||
|
|
||||||
|
use deno_core::error::AnyError;
|
||||||
|
use deno_core::serde_json;
|
||||||
|
use deno_core::serde_json::Value;
|
||||||
use test_util::PathRef;
|
use test_util::PathRef;
|
||||||
|
|
||||||
mod lsp;
|
mod lsp;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
import { loadTestLibrary } from "../../../tests/napi/common.js";
|
import { loadTestLibrary } from "../../../tests/napi/common.js";
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
import { bench, run } from "mitata";
|
import { bench, run } from "mitata";
|
||||||
import { createRequire } from "module";
|
import { createRequire } from "module";
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
// deno-lint-ignore-file no-console no-process-globals
|
// deno-lint-ignore-file no-console no-process-globals
|
||||||
|
|
||||||
const queueMicrotask = globalThis.queueMicrotask || process.nextTick;
|
const queueMicrotask = globalThis.queueMicrotask || process.nextTick;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
// deno-lint-ignore-file no-console no-process-globals
|
// deno-lint-ignore-file no-console no-process-globals
|
||||||
|
|
||||||
let [total, count] = typeof Deno !== "undefined"
|
let [total, count] = typeof Deno !== "undefined"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
// From https://github.com/just-js/benchmarks/tree/main/01-stdio
|
// From https://github.com/just-js/benchmarks/tree/main/01-stdio
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
//
|
//
|
||||||
// From https://github.com/just-js/benchmarks/tree/main/01-stdio
|
// From https://github.com/just-js/benchmarks/tree/main/01-stdio
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
const listener = Deno.listen({ port: 4500 });
|
const listener = Deno.listen({ port: 4500 });
|
||||||
const response = new TextEncoder().encode(
|
const response = new TextEncoder().encode(
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
// deno-lint-ignore-file no-console no-process-globals
|
// deno-lint-ignore-file no-console no-process-globals
|
||||||
|
|
||||||
const queueMicrotask = globalThis.queueMicrotask || process.nextTick;
|
const queueMicrotask = globalThis.queueMicrotask || process.nextTick;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
// deno-lint-ignore-file no-console no-process-globals
|
// deno-lint-ignore-file no-console no-process-globals
|
||||||
|
|
||||||
const queueMicrotask = globalThis.queueMicrotask || process.nextTick;
|
const queueMicrotask = globalThis.queueMicrotask || process.nextTick;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
// deno-lint-ignore-file no-console
|
// deno-lint-ignore-file no-console
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
// deno-lint-ignore-file no-console no-process-globals
|
// deno-lint-ignore-file no-console no-process-globals
|
||||||
|
|
||||||
const queueMicrotask = globalThis.queueMicrotask || process.nextTick;
|
const queueMicrotask = globalThis.queueMicrotask || process.nextTick;
|
||||||
|
|
30
cli/build.rs
30
cli/build.rs
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
@ -8,17 +8,18 @@ use deno_runtime::*;
|
||||||
mod shared;
|
mod shared;
|
||||||
|
|
||||||
mod ts {
|
mod ts {
|
||||||
use super::*;
|
|
||||||
use deno_core::error::custom_error;
|
|
||||||
use deno_core::error::AnyError;
|
|
||||||
use deno_core::op2;
|
|
||||||
use deno_core::OpState;
|
|
||||||
use serde::Serialize;
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use deno_core::op2;
|
||||||
|
use deno_core::OpState;
|
||||||
|
use deno_error::JsErrorBox;
|
||||||
|
use serde::Serialize;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
struct BuildInfoResponse {
|
struct BuildInfoResponse {
|
||||||
|
@ -51,7 +52,7 @@ mod ts {
|
||||||
fn op_script_version(
|
fn op_script_version(
|
||||||
_state: &mut OpState,
|
_state: &mut OpState,
|
||||||
#[string] _arg: &str,
|
#[string] _arg: &str,
|
||||||
) -> Result<Option<String>, AnyError> {
|
) -> Result<Option<String>, JsErrorBox> {
|
||||||
Ok(Some("1".to_string()))
|
Ok(Some("1".to_string()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,7 +71,7 @@ mod ts {
|
||||||
fn op_load(
|
fn op_load(
|
||||||
state: &mut OpState,
|
state: &mut OpState,
|
||||||
#[string] load_specifier: &str,
|
#[string] load_specifier: &str,
|
||||||
) -> Result<LoadResponse, AnyError> {
|
) -> Result<LoadResponse, JsErrorBox> {
|
||||||
let op_crate_libs = state.borrow::<HashMap<&str, PathBuf>>();
|
let op_crate_libs = state.borrow::<HashMap<&str, PathBuf>>();
|
||||||
let path_dts = state.borrow::<PathBuf>();
|
let path_dts = state.borrow::<PathBuf>();
|
||||||
let re_asset = lazy_regex::regex!(r"asset:/{3}lib\.(\S+)\.d\.ts");
|
let re_asset = lazy_regex::regex!(r"asset:/{3}lib\.(\S+)\.d\.ts");
|
||||||
|
@ -91,12 +92,15 @@ mod ts {
|
||||||
// if it comes from an op crate, we were supplied with the path to the
|
// if it comes from an op crate, we were supplied with the path to the
|
||||||
// file.
|
// file.
|
||||||
let path = if let Some(op_crate_lib) = op_crate_libs.get(lib) {
|
let path = if let Some(op_crate_lib) = op_crate_libs.get(lib) {
|
||||||
PathBuf::from(op_crate_lib).canonicalize()?
|
PathBuf::from(op_crate_lib)
|
||||||
|
.canonicalize()
|
||||||
|
.map_err(JsErrorBox::from_err)?
|
||||||
// otherwise we will generate the path ourself
|
// otherwise we will generate the path ourself
|
||||||
} else {
|
} else {
|
||||||
path_dts.join(format!("lib.{lib}.d.ts"))
|
path_dts.join(format!("lib.{lib}.d.ts"))
|
||||||
};
|
};
|
||||||
let data = std::fs::read_to_string(path)?;
|
let data =
|
||||||
|
std::fs::read_to_string(path).map_err(JsErrorBox::from_err)?;
|
||||||
Ok(LoadResponse {
|
Ok(LoadResponse {
|
||||||
data,
|
data,
|
||||||
version: "1".to_string(),
|
version: "1".to_string(),
|
||||||
|
@ -104,13 +108,13 @@ mod ts {
|
||||||
script_kind: 3,
|
script_kind: 3,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
Err(custom_error(
|
Err(JsErrorBox::new(
|
||||||
"InvalidSpecifier",
|
"InvalidSpecifier",
|
||||||
format!("An invalid specifier was requested: {}", load_specifier),
|
format!("An invalid specifier was requested: {}", load_specifier),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Err(custom_error(
|
Err(JsErrorBox::new(
|
||||||
"InvalidSpecifier",
|
"InvalidSpecifier",
|
||||||
format!("An invalid specifier was requested: {}", load_specifier),
|
format!("An invalid specifier was requested: {}", load_specifier),
|
||||||
))
|
))
|
||||||
|
|
15
cli/cache/cache_db.rs
vendored
15
cli/cache/cache_db.rs
vendored
|
@ -1,4 +1,9 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
|
use std::io::IsTerminal;
|
||||||
|
use std::path::Path;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
use deno_core::parking_lot::Mutex;
|
use deno_core::parking_lot::Mutex;
|
||||||
|
@ -9,10 +14,6 @@ use deno_runtime::deno_webstorage::rusqlite::Connection;
|
||||||
use deno_runtime::deno_webstorage::rusqlite::OptionalExtension;
|
use deno_runtime::deno_webstorage::rusqlite::OptionalExtension;
|
||||||
use deno_runtime::deno_webstorage::rusqlite::Params;
|
use deno_runtime::deno_webstorage::rusqlite::Params;
|
||||||
use once_cell::sync::OnceCell;
|
use once_cell::sync::OnceCell;
|
||||||
use std::io::IsTerminal;
|
|
||||||
use std::path::Path;
|
|
||||||
use std::path::PathBuf;
|
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
use super::FastInsecureHasher;
|
use super::FastInsecureHasher;
|
||||||
|
|
||||||
|
@ -24,12 +25,12 @@ impl CacheDBHash {
|
||||||
Self(hash)
|
Self(hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_source(source: impl std::hash::Hash) -> Self {
|
pub fn from_hashable(hashable: impl std::hash::Hash) -> Self {
|
||||||
Self::new(
|
Self::new(
|
||||||
// always write in the deno version just in case
|
// always write in the deno version just in case
|
||||||
// the clearing on deno version change doesn't work
|
// the clearing on deno version change doesn't work
|
||||||
FastInsecureHasher::new_deno_versioned()
|
FastInsecureHasher::new_deno_versioned()
|
||||||
.write_hashable(source)
|
.write_hashable(hashable)
|
||||||
.finish(),
|
.finish(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
2
cli/cache/caches.rs
vendored
2
cli/cache/caches.rs
vendored
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
9
cli/cache/check.rs
vendored
9
cli/cache/check.rs
vendored
|
@ -1,12 +1,13 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
|
use deno_ast::ModuleSpecifier;
|
||||||
|
use deno_core::error::AnyError;
|
||||||
|
use deno_runtime::deno_webstorage::rusqlite::params;
|
||||||
|
|
||||||
use super::cache_db::CacheDB;
|
use super::cache_db::CacheDB;
|
||||||
use super::cache_db::CacheDBConfiguration;
|
use super::cache_db::CacheDBConfiguration;
|
||||||
use super::cache_db::CacheDBHash;
|
use super::cache_db::CacheDBHash;
|
||||||
use super::cache_db::CacheFailure;
|
use super::cache_db::CacheFailure;
|
||||||
use deno_ast::ModuleSpecifier;
|
|
||||||
use deno_core::error::AnyError;
|
|
||||||
use deno_runtime::deno_webstorage::rusqlite::params;
|
|
||||||
|
|
||||||
pub static TYPE_CHECK_CACHE_DB: CacheDBConfiguration = CacheDBConfiguration {
|
pub static TYPE_CHECK_CACHE_DB: CacheDBConfiguration = CacheDBConfiguration {
|
||||||
table_initializer: concat!(
|
table_initializer: concat!(
|
||||||
|
|
5
cli/cache/code_cache.rs
vendored
5
cli/cache/code_cache.rs
vendored
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
@ -7,12 +7,11 @@ use deno_core::error::AnyError;
|
||||||
use deno_runtime::code_cache;
|
use deno_runtime::code_cache;
|
||||||
use deno_runtime::deno_webstorage::rusqlite::params;
|
use deno_runtime::deno_webstorage::rusqlite::params;
|
||||||
|
|
||||||
use crate::worker::CliCodeCache;
|
|
||||||
|
|
||||||
use super::cache_db::CacheDB;
|
use super::cache_db::CacheDB;
|
||||||
use super::cache_db::CacheDBConfiguration;
|
use super::cache_db::CacheDBConfiguration;
|
||||||
use super::cache_db::CacheDBHash;
|
use super::cache_db::CacheDBHash;
|
||||||
use super::cache_db::CacheFailure;
|
use super::cache_db::CacheFailure;
|
||||||
|
use crate::worker::CliCodeCache;
|
||||||
|
|
||||||
pub static CODE_CACHE_DB: CacheDBConfiguration = CacheDBConfiguration {
|
pub static CODE_CACHE_DB: CacheDBConfiguration = CacheDBConfiguration {
|
||||||
table_initializer: concat!(
|
table_initializer: concat!(
|
||||||
|
|
2
cli/cache/common.rs
vendored
2
cli/cache/common.rs
vendored
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
use std::hash::Hasher;
|
use std::hash::Hasher;
|
||||||
|
|
||||||
|
|
175
cli/cache/deno_dir.rs
vendored
175
cli/cache/deno_dir.rs
vendored
|
@ -1,33 +1,48 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
use once_cell::sync::OnceCell;
|
|
||||||
|
|
||||||
use super::DiskCache;
|
|
||||||
|
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use deno_cache_dir::DenoDirResolutionError;
|
||||||
|
use once_cell::sync::OnceCell;
|
||||||
|
|
||||||
|
use super::DiskCache;
|
||||||
|
use crate::sys::CliSys;
|
||||||
|
|
||||||
/// Lazily creates the deno dir which might be useful in scenarios
|
/// Lazily creates the deno dir which might be useful in scenarios
|
||||||
/// where functionality wants to continue if the DENO_DIR can't be created.
|
/// where functionality wants to continue if the DENO_DIR can't be created.
|
||||||
pub struct DenoDirProvider {
|
pub struct DenoDirProvider {
|
||||||
|
sys: CliSys,
|
||||||
maybe_custom_root: Option<PathBuf>,
|
maybe_custom_root: Option<PathBuf>,
|
||||||
deno_dir: OnceCell<std::io::Result<DenoDir>>,
|
deno_dir: OnceCell<Result<DenoDir, DenoDirResolutionError>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DenoDirProvider {
|
impl DenoDirProvider {
|
||||||
pub fn new(maybe_custom_root: Option<PathBuf>) -> Self {
|
pub fn new(sys: CliSys, maybe_custom_root: Option<PathBuf>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
sys,
|
||||||
maybe_custom_root,
|
maybe_custom_root,
|
||||||
deno_dir: Default::default(),
|
deno_dir: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_or_create(&self) -> Result<&DenoDir, std::io::Error> {
|
pub fn get_or_create(&self) -> Result<&DenoDir, DenoDirResolutionError> {
|
||||||
self
|
self
|
||||||
.deno_dir
|
.deno_dir
|
||||||
.get_or_init(|| DenoDir::new(self.maybe_custom_root.clone()))
|
.get_or_init(|| {
|
||||||
|
DenoDir::new(self.sys.clone(), self.maybe_custom_root.clone())
|
||||||
|
})
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map_err(|err| std::io::Error::new(err.kind(), err.to_string()))
|
.map_err(|err| match err {
|
||||||
|
DenoDirResolutionError::NoCacheOrHomeDir => {
|
||||||
|
DenoDirResolutionError::NoCacheOrHomeDir
|
||||||
|
}
|
||||||
|
DenoDirResolutionError::FailedCwd { source } => {
|
||||||
|
DenoDirResolutionError::FailedCwd {
|
||||||
|
source: std::io::Error::new(source.kind(), source.to_string()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,33 +57,20 @@ pub struct DenoDir {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DenoDir {
|
impl DenoDir {
|
||||||
pub fn new(maybe_custom_root: Option<PathBuf>) -> std::io::Result<Self> {
|
pub fn new(
|
||||||
let maybe_custom_root =
|
sys: CliSys,
|
||||||
maybe_custom_root.or_else(|| env::var("DENO_DIR").map(String::into).ok());
|
maybe_custom_root: Option<PathBuf>,
|
||||||
let root: PathBuf = if let Some(root) = maybe_custom_root {
|
) -> Result<Self, deno_cache_dir::DenoDirResolutionError> {
|
||||||
root
|
let root = deno_cache_dir::resolve_deno_dir(
|
||||||
} else if let Some(cache_dir) = dirs::cache_dir() {
|
&sys_traits::impls::RealSys,
|
||||||
// We use the OS cache dir because all files deno writes are cache files
|
maybe_custom_root,
|
||||||
// Once that changes we need to start using different roots if DENO_DIR
|
)?;
|
||||||
// is not set, and keep a single one if it is.
|
|
||||||
cache_dir.join("deno")
|
|
||||||
} else if let Some(home_dir) = dirs::home_dir() {
|
|
||||||
// fallback path
|
|
||||||
home_dir.join(".deno")
|
|
||||||
} else {
|
|
||||||
panic!("Could not set the Deno root directory")
|
|
||||||
};
|
|
||||||
let root = if root.is_absolute() {
|
|
||||||
root
|
|
||||||
} else {
|
|
||||||
std::env::current_dir()?.join(root)
|
|
||||||
};
|
|
||||||
assert!(root.is_absolute());
|
assert!(root.is_absolute());
|
||||||
let gen_path = root.join("gen");
|
let gen_path = root.join("gen");
|
||||||
|
|
||||||
let deno_dir = Self {
|
let deno_dir = Self {
|
||||||
root,
|
root,
|
||||||
gen_cache: DiskCache::new(&gen_path),
|
gen_cache: DiskCache::new(sys, &gen_path),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(deno_dir)
|
Ok(deno_dir)
|
||||||
|
@ -166,112 +168,3 @@ impl DenoDir {
|
||||||
self.root.join("dl")
|
self.root.join("dl")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// To avoid the poorly managed dirs crate
|
|
||||||
#[cfg(not(windows))]
|
|
||||||
pub mod dirs {
|
|
||||||
use std::path::PathBuf;
|
|
||||||
|
|
||||||
pub fn cache_dir() -> Option<PathBuf> {
|
|
||||||
if cfg!(target_os = "macos") {
|
|
||||||
home_dir().map(|h| h.join("Library/Caches"))
|
|
||||||
} else {
|
|
||||||
std::env::var_os("XDG_CACHE_HOME")
|
|
||||||
.map(PathBuf::from)
|
|
||||||
.or_else(|| home_dir().map(|h| h.join(".cache")))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn home_dir() -> Option<PathBuf> {
|
|
||||||
std::env::var_os("HOME")
|
|
||||||
.and_then(|h| if h.is_empty() { None } else { Some(h) })
|
|
||||||
.or_else(|| {
|
|
||||||
// TODO(bartlomieju):
|
|
||||||
#[allow(clippy::undocumented_unsafe_blocks)]
|
|
||||||
unsafe {
|
|
||||||
fallback()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.map(PathBuf::from)
|
|
||||||
}
|
|
||||||
|
|
||||||
// This piece of code is taken from the deprecated home_dir() function in Rust's standard library: https://github.com/rust-lang/rust/blob/master/src/libstd/sys/unix/os.rs#L579
|
|
||||||
// The same code is used by the dirs crate
|
|
||||||
unsafe fn fallback() -> Option<std::ffi::OsString> {
|
|
||||||
let amt = match libc::sysconf(libc::_SC_GETPW_R_SIZE_MAX) {
|
|
||||||
n if n < 0 => 512_usize,
|
|
||||||
n => n as usize,
|
|
||||||
};
|
|
||||||
let mut buf = Vec::with_capacity(amt);
|
|
||||||
let mut passwd: libc::passwd = std::mem::zeroed();
|
|
||||||
let mut result = std::ptr::null_mut();
|
|
||||||
match libc::getpwuid_r(
|
|
||||||
libc::getuid(),
|
|
||||||
&mut passwd,
|
|
||||||
buf.as_mut_ptr(),
|
|
||||||
buf.capacity(),
|
|
||||||
&mut result,
|
|
||||||
) {
|
|
||||||
0 if !result.is_null() => {
|
|
||||||
let ptr = passwd.pw_dir as *const _;
|
|
||||||
let bytes = std::ffi::CStr::from_ptr(ptr).to_bytes().to_vec();
|
|
||||||
Some(std::os::unix::ffi::OsStringExt::from_vec(bytes))
|
|
||||||
}
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// To avoid the poorly managed dirs crate
|
|
||||||
// Copied from
|
|
||||||
// https://github.com/dirs-dev/dirs-sys-rs/blob/ec7cee0b3e8685573d847f0a0f60aae3d9e07fa2/src/lib.rs#L140-L164
|
|
||||||
// MIT license. Copyright (c) 2018-2019 dirs-rs contributors
|
|
||||||
#[cfg(windows)]
|
|
||||||
pub mod dirs {
|
|
||||||
use std::ffi::OsString;
|
|
||||||
use std::os::windows::ffi::OsStringExt;
|
|
||||||
use std::path::PathBuf;
|
|
||||||
use winapi::shared::winerror;
|
|
||||||
use winapi::um::combaseapi;
|
|
||||||
use winapi::um::knownfolders;
|
|
||||||
use winapi::um::shlobj;
|
|
||||||
use winapi::um::shtypes;
|
|
||||||
use winapi::um::winbase;
|
|
||||||
use winapi::um::winnt;
|
|
||||||
|
|
||||||
fn known_folder(folder_id: shtypes::REFKNOWNFOLDERID) -> Option<PathBuf> {
|
|
||||||
// SAFETY: winapi calls
|
|
||||||
unsafe {
|
|
||||||
let mut path_ptr: winnt::PWSTR = std::ptr::null_mut();
|
|
||||||
let result = shlobj::SHGetKnownFolderPath(
|
|
||||||
folder_id,
|
|
||||||
0,
|
|
||||||
std::ptr::null_mut(),
|
|
||||||
&mut path_ptr,
|
|
||||||
);
|
|
||||||
if result == winerror::S_OK {
|
|
||||||
let len = winbase::lstrlenW(path_ptr) as usize;
|
|
||||||
let path = std::slice::from_raw_parts(path_ptr, len);
|
|
||||||
let ostr: OsString = OsStringExt::from_wide(path);
|
|
||||||
combaseapi::CoTaskMemFree(path_ptr as *mut winapi::ctypes::c_void);
|
|
||||||
Some(PathBuf::from(ostr))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn cache_dir() -> Option<PathBuf> {
|
|
||||||
known_folder(&knownfolders::FOLDERID_LocalAppData)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn home_dir() -> Option<PathBuf> {
|
|
||||||
if let Some(userprofile) = std::env::var_os("USERPROFILE") {
|
|
||||||
if !userprofile.is_empty() {
|
|
||||||
return Some(PathBuf::from(userprofile));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
known_folder(&knownfolders::FOLDERID_Profile)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
33
cli/cache/disk_cache.rs
vendored
33
cli/cache/disk_cache.rs
vendored
|
@ -1,11 +1,5 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
use super::CACHE_PERM;
|
|
||||||
use crate::util::fs::atomic_write_file_with_retries;
|
|
||||||
|
|
||||||
use deno_cache_dir::url_to_filename;
|
|
||||||
use deno_core::url::Host;
|
|
||||||
use deno_core::url::Url;
|
|
||||||
use std::ffi::OsStr;
|
use std::ffi::OsStr;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::path::Component;
|
use std::path::Component;
|
||||||
|
@ -14,16 +8,26 @@ use std::path::PathBuf;
|
||||||
use std::path::Prefix;
|
use std::path::Prefix;
|
||||||
use std::str;
|
use std::str;
|
||||||
|
|
||||||
|
use deno_cache_dir::url_to_filename;
|
||||||
|
use deno_core::url::Host;
|
||||||
|
use deno_core::url::Url;
|
||||||
|
use deno_path_util::fs::atomic_write_file_with_retries;
|
||||||
|
|
||||||
|
use super::CACHE_PERM;
|
||||||
|
use crate::sys::CliSys;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct DiskCache {
|
pub struct DiskCache {
|
||||||
|
sys: CliSys,
|
||||||
pub location: PathBuf,
|
pub location: PathBuf,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DiskCache {
|
impl DiskCache {
|
||||||
/// `location` must be an absolute path.
|
/// `location` must be an absolute path.
|
||||||
pub fn new(location: &Path) -> Self {
|
pub fn new(sys: CliSys, location: &Path) -> Self {
|
||||||
assert!(location.is_absolute());
|
assert!(location.is_absolute());
|
||||||
Self {
|
Self {
|
||||||
|
sys,
|
||||||
location: location.to_owned(),
|
location: location.to_owned(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -120,20 +124,21 @@ impl DiskCache {
|
||||||
|
|
||||||
pub fn set(&self, filename: &Path, data: &[u8]) -> std::io::Result<()> {
|
pub fn set(&self, filename: &Path, data: &[u8]) -> std::io::Result<()> {
|
||||||
let path = self.location.join(filename);
|
let path = self.location.join(filename);
|
||||||
atomic_write_file_with_retries(&path, data, CACHE_PERM)
|
atomic_write_file_with_retries(&self.sys, &path, data, CACHE_PERM)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
|
||||||
use test_util::TempDir;
|
use test_util::TempDir;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_set_get_cache_file() {
|
fn test_set_get_cache_file() {
|
||||||
let temp_dir = TempDir::new();
|
let temp_dir = TempDir::new();
|
||||||
let sub_dir = temp_dir.path().join("sub_dir");
|
let sub_dir = temp_dir.path().join("sub_dir");
|
||||||
let cache = DiskCache::new(&sub_dir.to_path_buf());
|
let cache = DiskCache::new(CliSys::default(), &sub_dir.to_path_buf());
|
||||||
let path = PathBuf::from("foo/bar.txt");
|
let path = PathBuf::from("foo/bar.txt");
|
||||||
cache.set(&path, b"hello").unwrap();
|
cache.set(&path, b"hello").unwrap();
|
||||||
assert_eq!(cache.get(&path).unwrap(), b"hello");
|
assert_eq!(cache.get(&path).unwrap(), b"hello");
|
||||||
|
@ -147,7 +152,7 @@ mod tests {
|
||||||
PathBuf::from("/deno_dir/")
|
PathBuf::from("/deno_dir/")
|
||||||
};
|
};
|
||||||
|
|
||||||
let cache = DiskCache::new(&cache_location);
|
let cache = DiskCache::new(CliSys::default(), &cache_location);
|
||||||
|
|
||||||
let mut test_cases = vec![
|
let mut test_cases = vec![
|
||||||
(
|
(
|
||||||
|
@ -203,7 +208,7 @@ mod tests {
|
||||||
} else {
|
} else {
|
||||||
"/foo"
|
"/foo"
|
||||||
};
|
};
|
||||||
let cache = DiskCache::new(&PathBuf::from(p));
|
let cache = DiskCache::new(CliSys::default(), &PathBuf::from(p));
|
||||||
|
|
||||||
let mut test_cases = vec![
|
let mut test_cases = vec![
|
||||||
(
|
(
|
||||||
|
@ -251,7 +256,7 @@ mod tests {
|
||||||
PathBuf::from("/deno_dir/")
|
PathBuf::from("/deno_dir/")
|
||||||
};
|
};
|
||||||
|
|
||||||
let cache = DiskCache::new(&cache_location);
|
let cache = DiskCache::new(CliSys::default(), &cache_location);
|
||||||
|
|
||||||
let mut test_cases = vec!["unknown://localhost/test.ts"];
|
let mut test_cases = vec!["unknown://localhost/test.ts"];
|
||||||
|
|
||||||
|
|
6
cli/cache/emit.rs
vendored
6
cli/cache/emit.rs
vendored
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
@ -160,11 +160,13 @@ mod test {
|
||||||
use test_util::TempDir;
|
use test_util::TempDir;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use crate::sys::CliSys;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn emit_cache_general_use() {
|
pub fn emit_cache_general_use() {
|
||||||
let temp_dir = TempDir::new();
|
let temp_dir = TempDir::new();
|
||||||
let disk_cache = DiskCache::new(temp_dir.path().as_path());
|
let disk_cache =
|
||||||
|
DiskCache::new(CliSys::default(), temp_dir.path().as_path());
|
||||||
let cache = EmitCache {
|
let cache = EmitCache {
|
||||||
disk_cache: disk_cache.clone(),
|
disk_cache: disk_cache.clone(),
|
||||||
file_serializer: EmitFileSerializer {
|
file_serializer: EmitFileSerializer {
|
||||||
|
|
2
cli/cache/fast_check.rs
vendored
2
cli/cache/fast_check.rs
vendored
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
use deno_graph::FastCheckCacheItem;
|
use deno_graph::FastCheckCacheItem;
|
||||||
|
|
23
cli/cache/incremental.rs
vendored
23
cli/cache/incremental.rs
vendored
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
@ -34,12 +34,16 @@ pub static INCREMENTAL_CACHE_DB: CacheDBConfiguration = CacheDBConfiguration {
|
||||||
pub struct IncrementalCache(IncrementalCacheInner);
|
pub struct IncrementalCache(IncrementalCacheInner);
|
||||||
|
|
||||||
impl IncrementalCache {
|
impl IncrementalCache {
|
||||||
pub fn new<TState: std::hash::Hash>(
|
pub fn new(
|
||||||
db: CacheDB,
|
db: CacheDB,
|
||||||
state: &TState,
|
state_hash: CacheDBHash,
|
||||||
initial_file_paths: &[PathBuf],
|
initial_file_paths: &[PathBuf],
|
||||||
) -> Self {
|
) -> Self {
|
||||||
IncrementalCache(IncrementalCacheInner::new(db, state, initial_file_paths))
|
IncrementalCache(IncrementalCacheInner::new(
|
||||||
|
db,
|
||||||
|
state_hash,
|
||||||
|
initial_file_paths,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_file_same(&self, file_path: &Path, file_text: &str) -> bool {
|
pub fn is_file_same(&self, file_path: &Path, file_text: &str) -> bool {
|
||||||
|
@ -67,12 +71,11 @@ struct IncrementalCacheInner {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IncrementalCacheInner {
|
impl IncrementalCacheInner {
|
||||||
pub fn new<TState: std::hash::Hash>(
|
pub fn new(
|
||||||
db: CacheDB,
|
db: CacheDB,
|
||||||
state: &TState,
|
state_hash: CacheDBHash,
|
||||||
initial_file_paths: &[PathBuf],
|
initial_file_paths: &[PathBuf],
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let state_hash = CacheDBHash::from_source(state);
|
|
||||||
let sql_cache = SqlIncrementalCache::new(db, state_hash);
|
let sql_cache = SqlIncrementalCache::new(db, state_hash);
|
||||||
Self::from_sql_incremental_cache(sql_cache, initial_file_paths)
|
Self::from_sql_incremental_cache(sql_cache, initial_file_paths)
|
||||||
}
|
}
|
||||||
|
@ -112,13 +115,13 @@ impl IncrementalCacheInner {
|
||||||
|
|
||||||
pub fn is_file_same(&self, file_path: &Path, file_text: &str) -> bool {
|
pub fn is_file_same(&self, file_path: &Path, file_text: &str) -> bool {
|
||||||
match self.previous_hashes.get(file_path) {
|
match self.previous_hashes.get(file_path) {
|
||||||
Some(hash) => *hash == CacheDBHash::from_source(file_text),
|
Some(hash) => *hash == CacheDBHash::from_hashable(file_text),
|
||||||
None => false,
|
None => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_file(&self, file_path: &Path, file_text: &str) {
|
pub fn update_file(&self, file_path: &Path, file_text: &str) {
|
||||||
let hash = CacheDBHash::from_source(file_text);
|
let hash = CacheDBHash::from_hashable(file_text);
|
||||||
if let Some(previous_hash) = self.previous_hashes.get(file_path) {
|
if let Some(previous_hash) = self.previous_hashes.get(file_path) {
|
||||||
if *previous_hash == hash {
|
if *previous_hash == hash {
|
||||||
return; // do not bother updating the db file because nothing has changed
|
return; // do not bother updating the db file because nothing has changed
|
||||||
|
@ -262,7 +265,7 @@ mod test {
|
||||||
let sql_cache = SqlIncrementalCache::new(conn, CacheDBHash::new(1));
|
let sql_cache = SqlIncrementalCache::new(conn, CacheDBHash::new(1));
|
||||||
let file_path = PathBuf::from("/mod.ts");
|
let file_path = PathBuf::from("/mod.ts");
|
||||||
let file_text = "test";
|
let file_text = "test";
|
||||||
let file_hash = CacheDBHash::from_source(file_text);
|
let file_hash = CacheDBHash::from_hashable(file_text);
|
||||||
sql_cache.set_source_hash(&file_path, file_hash).unwrap();
|
sql_cache.set_source_hash(&file_path, file_hash).unwrap();
|
||||||
let cache = IncrementalCacheInner::from_sql_incremental_cache(
|
let cache = IncrementalCacheInner::from_sql_incremental_cache(
|
||||||
sql_cache,
|
sql_cache,
|
||||||
|
|
245
cli/cache/mod.rs
vendored
245
cli/cache/mod.rs
vendored
|
@ -1,18 +1,13 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
use crate::args::jsr_url;
|
use std::collections::HashMap;
|
||||||
use crate::args::CacheSetting;
|
use std::path::PathBuf;
|
||||||
use crate::errors::get_error_class_name;
|
use std::sync::Arc;
|
||||||
use crate::file_fetcher::FetchNoFollowOptions;
|
|
||||||
use crate::file_fetcher::FetchOptions;
|
|
||||||
use crate::file_fetcher::FetchPermissionsOptionRef;
|
|
||||||
use crate::file_fetcher::FileFetcher;
|
|
||||||
use crate::file_fetcher::FileOrRedirect;
|
|
||||||
use crate::util::fs::atomic_write_file_with_retries;
|
|
||||||
use crate::util::fs::atomic_write_file_with_retries_and_fs;
|
|
||||||
use crate::util::fs::AtomicWriteFileFsAdapter;
|
|
||||||
|
|
||||||
use deno_ast::MediaType;
|
use deno_ast::MediaType;
|
||||||
|
use deno_cache_dir::file_fetcher::CacheSetting;
|
||||||
|
use deno_cache_dir::file_fetcher::FetchNoFollowErrorKind;
|
||||||
|
use deno_cache_dir::file_fetcher::FileOrRedirect;
|
||||||
use deno_core::futures;
|
use deno_core::futures;
|
||||||
use deno_core::futures::FutureExt;
|
use deno_core::futures::FutureExt;
|
||||||
use deno_core::ModuleSpecifier;
|
use deno_core::ModuleSpecifier;
|
||||||
|
@ -20,15 +15,16 @@ use deno_graph::source::CacheInfo;
|
||||||
use deno_graph::source::LoadFuture;
|
use deno_graph::source::LoadFuture;
|
||||||
use deno_graph::source::LoadResponse;
|
use deno_graph::source::LoadResponse;
|
||||||
use deno_graph::source::Loader;
|
use deno_graph::source::Loader;
|
||||||
use deno_runtime::deno_fs;
|
use deno_resolver::npm::DenoInNpmPackageChecker;
|
||||||
use deno_runtime::deno_permissions::PermissionsContainer;
|
use deno_runtime::deno_permissions::PermissionsContainer;
|
||||||
use node_resolver::InNpmPackageChecker;
|
use node_resolver::InNpmPackageChecker;
|
||||||
use std::borrow::Cow;
|
|
||||||
use std::collections::HashMap;
|
use crate::args::jsr_url;
|
||||||
use std::path::Path;
|
use crate::file_fetcher::CliFetchNoFollowErrorKind;
|
||||||
use std::path::PathBuf;
|
use crate::file_fetcher::CliFileFetcher;
|
||||||
use std::sync::Arc;
|
use crate::file_fetcher::FetchNoFollowOptions;
|
||||||
use std::time::SystemTime;
|
use crate::file_fetcher::FetchPermissionsOptionRef;
|
||||||
|
use crate::sys::CliSys;
|
||||||
|
|
||||||
mod cache_db;
|
mod cache_db;
|
||||||
mod caches;
|
mod caches;
|
||||||
|
@ -49,7 +45,8 @@ pub use caches::Caches;
|
||||||
pub use check::TypeCheckCache;
|
pub use check::TypeCheckCache;
|
||||||
pub use code_cache::CodeCache;
|
pub use code_cache::CodeCache;
|
||||||
pub use common::FastInsecureHasher;
|
pub use common::FastInsecureHasher;
|
||||||
pub use deno_dir::dirs::home_dir;
|
/// Permissions used to save a file in the disk caches.
|
||||||
|
pub use deno_cache_dir::CACHE_PERM;
|
||||||
pub use deno_dir::DenoDir;
|
pub use deno_dir::DenoDir;
|
||||||
pub use deno_dir::DenoDirProvider;
|
pub use deno_dir::DenoDirProvider;
|
||||||
pub use disk_cache::DiskCache;
|
pub use disk_cache::DiskCache;
|
||||||
|
@ -61,123 +58,11 @@ pub use node::NodeAnalysisCache;
|
||||||
pub use parsed_source::LazyGraphSourceParser;
|
pub use parsed_source::LazyGraphSourceParser;
|
||||||
pub use parsed_source::ParsedSourceCache;
|
pub use parsed_source::ParsedSourceCache;
|
||||||
|
|
||||||
/// Permissions used to save a file in the disk caches.
|
pub type GlobalHttpCache = deno_cache_dir::GlobalHttpCache<CliSys>;
|
||||||
pub const CACHE_PERM: u32 = 0o644;
|
pub type LocalHttpCache = deno_cache_dir::LocalHttpCache<CliSys>;
|
||||||
|
pub type LocalLspHttpCache = deno_cache_dir::LocalLspHttpCache<CliSys>;
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct RealDenoCacheEnv;
|
|
||||||
|
|
||||||
impl deno_cache_dir::DenoCacheEnv for RealDenoCacheEnv {
|
|
||||||
fn read_file_bytes(
|
|
||||||
&self,
|
|
||||||
path: &Path,
|
|
||||||
) -> std::io::Result<Cow<'static, [u8]>> {
|
|
||||||
std::fs::read(path).map(Cow::Owned)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn atomic_write_file(
|
|
||||||
&self,
|
|
||||||
path: &Path,
|
|
||||||
bytes: &[u8],
|
|
||||||
) -> std::io::Result<()> {
|
|
||||||
atomic_write_file_with_retries(path, bytes, CACHE_PERM)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn canonicalize_path(&self, path: &Path) -> std::io::Result<PathBuf> {
|
|
||||||
crate::util::fs::canonicalize_path(path)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn create_dir_all(&self, path: &Path) -> std::io::Result<()> {
|
|
||||||
std::fs::create_dir_all(path)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn modified(&self, path: &Path) -> std::io::Result<Option<SystemTime>> {
|
|
||||||
match std::fs::metadata(path) {
|
|
||||||
Ok(metadata) => Ok(Some(
|
|
||||||
metadata.modified().unwrap_or_else(|_| SystemTime::now()),
|
|
||||||
)),
|
|
||||||
Err(err) if err.kind() == std::io::ErrorKind::NotFound => Ok(None),
|
|
||||||
Err(err) => Err(err),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_file(&self, path: &Path) -> bool {
|
|
||||||
path.is_file()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn time_now(&self) -> SystemTime {
|
|
||||||
SystemTime::now()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct DenoCacheEnvFsAdapter<'a>(
|
|
||||||
pub &'a dyn deno_runtime::deno_fs::FileSystem,
|
|
||||||
);
|
|
||||||
|
|
||||||
impl<'a> deno_cache_dir::DenoCacheEnv for DenoCacheEnvFsAdapter<'a> {
|
|
||||||
fn read_file_bytes(
|
|
||||||
&self,
|
|
||||||
path: &Path,
|
|
||||||
) -> std::io::Result<Cow<'static, [u8]>> {
|
|
||||||
self
|
|
||||||
.0
|
|
||||||
.read_file_sync(path, None)
|
|
||||||
.map_err(|err| err.into_io_error())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn atomic_write_file(
|
|
||||||
&self,
|
|
||||||
path: &Path,
|
|
||||||
bytes: &[u8],
|
|
||||||
) -> std::io::Result<()> {
|
|
||||||
atomic_write_file_with_retries_and_fs(
|
|
||||||
&AtomicWriteFileFsAdapter {
|
|
||||||
fs: self.0,
|
|
||||||
write_mode: CACHE_PERM,
|
|
||||||
},
|
|
||||||
path,
|
|
||||||
bytes,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn canonicalize_path(&self, path: &Path) -> std::io::Result<PathBuf> {
|
|
||||||
self.0.realpath_sync(path).map_err(|e| e.into_io_error())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn create_dir_all(&self, path: &Path) -> std::io::Result<()> {
|
|
||||||
self
|
|
||||||
.0
|
|
||||||
.mkdir_sync(path, true, None)
|
|
||||||
.map_err(|e| e.into_io_error())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn modified(&self, path: &Path) -> std::io::Result<Option<SystemTime>> {
|
|
||||||
self
|
|
||||||
.0
|
|
||||||
.stat_sync(path)
|
|
||||||
.map(|stat| {
|
|
||||||
stat
|
|
||||||
.mtime
|
|
||||||
.map(|ts| SystemTime::UNIX_EPOCH + std::time::Duration::from_secs(ts))
|
|
||||||
})
|
|
||||||
.map_err(|e| e.into_io_error())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_file(&self, path: &Path) -> bool {
|
|
||||||
self.0.is_file_sync(path)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn time_now(&self) -> SystemTime {
|
|
||||||
SystemTime::now()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub type GlobalHttpCache = deno_cache_dir::GlobalHttpCache<RealDenoCacheEnv>;
|
|
||||||
pub type LocalHttpCache = deno_cache_dir::LocalHttpCache<RealDenoCacheEnv>;
|
|
||||||
pub type LocalLspHttpCache =
|
|
||||||
deno_cache_dir::LocalLspHttpCache<RealDenoCacheEnv>;
|
|
||||||
pub use deno_cache_dir::HttpCache;
|
pub use deno_cache_dir::HttpCache;
|
||||||
|
use deno_error::JsErrorBox;
|
||||||
|
|
||||||
pub struct FetchCacherOptions {
|
pub struct FetchCacherOptions {
|
||||||
pub file_header_overrides: HashMap<ModuleSpecifier, HashMap<String, String>>,
|
pub file_header_overrides: HashMap<ModuleSpecifier, HashMap<String, String>>,
|
||||||
|
@ -190,31 +75,31 @@ pub struct FetchCacherOptions {
|
||||||
/// a concise interface to the DENO_DIR when building module graphs.
|
/// a concise interface to the DENO_DIR when building module graphs.
|
||||||
pub struct FetchCacher {
|
pub struct FetchCacher {
|
||||||
pub file_header_overrides: HashMap<ModuleSpecifier, HashMap<String, String>>,
|
pub file_header_overrides: HashMap<ModuleSpecifier, HashMap<String, String>>,
|
||||||
file_fetcher: Arc<FileFetcher>,
|
file_fetcher: Arc<CliFileFetcher>,
|
||||||
fs: Arc<dyn deno_fs::FileSystem>,
|
|
||||||
global_http_cache: Arc<GlobalHttpCache>,
|
global_http_cache: Arc<GlobalHttpCache>,
|
||||||
in_npm_pkg_checker: Arc<dyn InNpmPackageChecker>,
|
in_npm_pkg_checker: DenoInNpmPackageChecker,
|
||||||
module_info_cache: Arc<ModuleInfoCache>,
|
module_info_cache: Arc<ModuleInfoCache>,
|
||||||
permissions: PermissionsContainer,
|
permissions: PermissionsContainer,
|
||||||
|
sys: CliSys,
|
||||||
is_deno_publish: bool,
|
is_deno_publish: bool,
|
||||||
cache_info_enabled: bool,
|
cache_info_enabled: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FetchCacher {
|
impl FetchCacher {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
file_fetcher: Arc<FileFetcher>,
|
file_fetcher: Arc<CliFileFetcher>,
|
||||||
fs: Arc<dyn deno_fs::FileSystem>,
|
|
||||||
global_http_cache: Arc<GlobalHttpCache>,
|
global_http_cache: Arc<GlobalHttpCache>,
|
||||||
in_npm_pkg_checker: Arc<dyn InNpmPackageChecker>,
|
in_npm_pkg_checker: DenoInNpmPackageChecker,
|
||||||
module_info_cache: Arc<ModuleInfoCache>,
|
module_info_cache: Arc<ModuleInfoCache>,
|
||||||
|
sys: CliSys,
|
||||||
options: FetchCacherOptions,
|
options: FetchCacherOptions,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
file_fetcher,
|
file_fetcher,
|
||||||
fs,
|
|
||||||
global_http_cache,
|
global_http_cache,
|
||||||
in_npm_pkg_checker,
|
in_npm_pkg_checker,
|
||||||
module_info_cache,
|
module_info_cache,
|
||||||
|
sys,
|
||||||
file_header_overrides: options.file_header_overrides,
|
file_header_overrides: options.file_header_overrides,
|
||||||
permissions: options.permissions,
|
permissions: options.permissions,
|
||||||
is_deno_publish: options.is_deno_publish,
|
is_deno_publish: options.is_deno_publish,
|
||||||
|
@ -276,9 +161,8 @@ impl Loader for FetchCacher {
|
||||||
// symlinked to `/my-project-2/node_modules`), so first we checked if the path
|
// symlinked to `/my-project-2/node_modules`), so first we checked if the path
|
||||||
// is in a node_modules dir to avoid needlessly canonicalizing, then now compare
|
// is in a node_modules dir to avoid needlessly canonicalizing, then now compare
|
||||||
// against the canonicalized specifier.
|
// against the canonicalized specifier.
|
||||||
let specifier = crate::node::resolve_specifier_into_node_modules(
|
let specifier = node_resolver::resolve_specifier_into_node_modules(
|
||||||
specifier,
|
&self.sys, specifier,
|
||||||
self.fs.as_ref(),
|
|
||||||
);
|
);
|
||||||
if self.in_npm_pkg_checker.in_npm_package(&specifier) {
|
if self.in_npm_pkg_checker.in_npm_package(&specifier) {
|
||||||
return Box::pin(futures::future::ready(Ok(Some(
|
return Box::pin(futures::future::ready(Ok(Some(
|
||||||
|
@ -311,27 +195,27 @@ impl Loader for FetchCacher {
|
||||||
LoaderCacheSetting::Use => None,
|
LoaderCacheSetting::Use => None,
|
||||||
LoaderCacheSetting::Reload => {
|
LoaderCacheSetting::Reload => {
|
||||||
if matches!(file_fetcher.cache_setting(), CacheSetting::Only) {
|
if matches!(file_fetcher.cache_setting(), CacheSetting::Only) {
|
||||||
return Err(deno_core::anyhow::anyhow!(
|
return Err(deno_graph::source::LoadError::Other(Arc::new(JsErrorBox::generic(
|
||||||
"Could not resolve version constraint using only cached data. Try running again without --cached-only"
|
"Could not resolve version constraint using only cached data. Try running again without --cached-only"
|
||||||
));
|
))));
|
||||||
}
|
}
|
||||||
Some(CacheSetting::ReloadAll)
|
Some(CacheSetting::ReloadAll)
|
||||||
}
|
}
|
||||||
LoaderCacheSetting::Only => Some(CacheSetting::Only),
|
LoaderCacheSetting::Only => Some(CacheSetting::Only),
|
||||||
};
|
};
|
||||||
file_fetcher
|
file_fetcher
|
||||||
.fetch_no_follow_with_options(FetchNoFollowOptions {
|
.fetch_no_follow(
|
||||||
fetch_options: FetchOptions {
|
&specifier,
|
||||||
specifier: &specifier,
|
FetchPermissionsOptionRef::Restricted(&permissions,
|
||||||
permissions: if is_statically_analyzable {
|
if is_statically_analyzable {
|
||||||
FetchPermissionsOptionRef::StaticContainer(&permissions)
|
deno_runtime::deno_permissions::CheckSpecifierKind::Static
|
||||||
} else {
|
} else {
|
||||||
FetchPermissionsOptionRef::DynamicContainer(&permissions)
|
deno_runtime::deno_permissions::CheckSpecifierKind::Dynamic
|
||||||
},
|
}),
|
||||||
|
FetchNoFollowOptions {
|
||||||
maybe_auth: None,
|
maybe_auth: None,
|
||||||
maybe_accept: None,
|
maybe_accept: None,
|
||||||
maybe_cache_setting: maybe_cache_setting.as_ref(),
|
maybe_cache_setting: maybe_cache_setting.as_ref(),
|
||||||
},
|
|
||||||
maybe_checksum: options.maybe_checksum.as_ref(),
|
maybe_checksum: options.maybe_checksum.as_ref(),
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
|
@ -348,7 +232,7 @@ impl Loader for FetchCacher {
|
||||||
(None, None) => None,
|
(None, None) => None,
|
||||||
};
|
};
|
||||||
Ok(Some(LoadResponse::Module {
|
Ok(Some(LoadResponse::Module {
|
||||||
specifier: file.specifier,
|
specifier: file.url,
|
||||||
maybe_headers,
|
maybe_headers,
|
||||||
content: file.source,
|
content: file.source,
|
||||||
}))
|
}))
|
||||||
|
@ -361,18 +245,45 @@ impl Loader for FetchCacher {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.unwrap_or_else(|err| {
|
.unwrap_or_else(|err| {
|
||||||
if let Some(io_err) = err.downcast_ref::<std::io::Error>() {
|
let err = err.into_kind();
|
||||||
if io_err.kind() == std::io::ErrorKind::NotFound {
|
match err {
|
||||||
return Ok(None);
|
CliFetchNoFollowErrorKind::FetchNoFollow(err) => {
|
||||||
|
let err = err.into_kind();
|
||||||
|
match err {
|
||||||
|
FetchNoFollowErrorKind::NotFound(_) => Ok(None),
|
||||||
|
FetchNoFollowErrorKind::UrlToFilePath { .. } |
|
||||||
|
FetchNoFollowErrorKind::ReadingBlobUrl { .. } |
|
||||||
|
FetchNoFollowErrorKind::ReadingFile { .. } |
|
||||||
|
FetchNoFollowErrorKind::FetchingRemote { .. } |
|
||||||
|
FetchNoFollowErrorKind::ClientError { .. } |
|
||||||
|
FetchNoFollowErrorKind::NoRemote { .. } |
|
||||||
|
FetchNoFollowErrorKind::DataUrlDecode { .. } |
|
||||||
|
FetchNoFollowErrorKind::RedirectResolution { .. } |
|
||||||
|
FetchNoFollowErrorKind::CacheRead { .. } |
|
||||||
|
FetchNoFollowErrorKind::CacheSave { .. } |
|
||||||
|
FetchNoFollowErrorKind::UnsupportedScheme { .. } |
|
||||||
|
FetchNoFollowErrorKind::RedirectHeaderParse { .. } |
|
||||||
|
FetchNoFollowErrorKind::InvalidHeader { .. } => Err(deno_graph::source::LoadError::Other(Arc::new(JsErrorBox::from_err(err)))),
|
||||||
|
FetchNoFollowErrorKind::NotCached { .. } => {
|
||||||
|
if options.cache_setting == LoaderCacheSetting::Only {
|
||||||
|
Ok(None)
|
||||||
} else {
|
} else {
|
||||||
return Err(err);
|
Err(deno_graph::source::LoadError::Other(Arc::new(JsErrorBox::from_err(err))))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
FetchNoFollowErrorKind::ChecksumIntegrity(err) => {
|
||||||
|
// convert to the equivalent deno_graph error so that it
|
||||||
|
// enhances it if this is passed to deno_graph
|
||||||
|
Err(
|
||||||
|
deno_graph::source::LoadError::ChecksumIntegrity(deno_graph::source::ChecksumIntegrityError {
|
||||||
|
actual: err.actual,
|
||||||
|
expected: err.expected,
|
||||||
|
}),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let error_class_name = get_error_class_name(&err);
|
},
|
||||||
match error_class_name {
|
CliFetchNoFollowErrorKind::PermissionCheck(permission_check_error) => Err(deno_graph::source::LoadError::Other(Arc::new(JsErrorBox::from_err(permission_check_error)))),
|
||||||
"NotFound" => Ok(None),
|
|
||||||
"NotCached" if options.cache_setting == LoaderCacheSetting::Only => Ok(None),
|
|
||||||
_ => Err(err),
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -387,7 +298,7 @@ impl Loader for FetchCacher {
|
||||||
module_info: &deno_graph::ModuleInfo,
|
module_info: &deno_graph::ModuleInfo,
|
||||||
) {
|
) {
|
||||||
log::debug!("Caching module info for {}", specifier);
|
log::debug!("Caching module info for {}", specifier);
|
||||||
let source_hash = CacheDBHash::from_source(source);
|
let source_hash = CacheDBHash::from_hashable(source);
|
||||||
let result = self.module_info_cache.set_module_info(
|
let result = self.module_info_cache.set_module_info(
|
||||||
specifier,
|
specifier,
|
||||||
media_type,
|
media_type,
|
||||||
|
|
6
cli/cache/module_info.rs
vendored
6
cli/cache/module_info.rs
vendored
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
@ -194,7 +194,7 @@ impl<'a> ModuleInfoCacheModuleAnalyzer<'a> {
|
||||||
source: &Arc<str>,
|
source: &Arc<str>,
|
||||||
) -> Result<ModuleInfo, deno_ast::ParseDiagnostic> {
|
) -> Result<ModuleInfo, deno_ast::ParseDiagnostic> {
|
||||||
// attempt to load from the cache
|
// attempt to load from the cache
|
||||||
let source_hash = CacheDBHash::from_source(source);
|
let source_hash = CacheDBHash::from_hashable(source);
|
||||||
if let Some(info) =
|
if let Some(info) =
|
||||||
self.load_cached_module_info(specifier, media_type, source_hash)
|
self.load_cached_module_info(specifier, media_type, source_hash)
|
||||||
{
|
{
|
||||||
|
@ -228,7 +228,7 @@ impl<'a> deno_graph::ModuleAnalyzer for ModuleInfoCacheModuleAnalyzer<'a> {
|
||||||
media_type: MediaType,
|
media_type: MediaType,
|
||||||
) -> Result<ModuleInfo, deno_ast::ParseDiagnostic> {
|
) -> Result<ModuleInfo, deno_ast::ParseDiagnostic> {
|
||||||
// attempt to load from the cache
|
// attempt to load from the cache
|
||||||
let source_hash = CacheDBHash::from_source(&source);
|
let source_hash = CacheDBHash::from_hashable(&source);
|
||||||
if let Some(info) =
|
if let Some(info) =
|
||||||
self.load_cached_module_info(specifier, media_type, source_hash)
|
self.load_cached_module_info(specifier, media_type, source_hash)
|
||||||
{
|
{
|
||||||
|
|
5
cli/cache/node.rs
vendored
5
cli/cache/node.rs
vendored
|
@ -1,15 +1,14 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
use deno_core::serde_json;
|
use deno_core::serde_json;
|
||||||
use deno_runtime::deno_webstorage::rusqlite::params;
|
use deno_runtime::deno_webstorage::rusqlite::params;
|
||||||
|
|
||||||
use crate::node::CliCjsAnalysis;
|
|
||||||
|
|
||||||
use super::cache_db::CacheDB;
|
use super::cache_db::CacheDB;
|
||||||
use super::cache_db::CacheDBConfiguration;
|
use super::cache_db::CacheDBConfiguration;
|
||||||
use super::cache_db::CacheFailure;
|
use super::cache_db::CacheFailure;
|
||||||
use super::CacheDBHash;
|
use super::CacheDBHash;
|
||||||
|
use crate::node::CliCjsAnalysis;
|
||||||
|
|
||||||
pub static NODE_ANALYSIS_CACHE_DB: CacheDBConfiguration =
|
pub static NODE_ANALYSIS_CACHE_DB: CacheDBConfiguration =
|
||||||
CacheDBConfiguration {
|
CacheDBConfiguration {
|
||||||
|
|
2
cli/cache/parsed_source.rs
vendored
2
cli/cache/parsed_source.rs
vendored
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
/// <https://chromedevtools.github.io/devtools-protocol/tot/>
|
/// <https://chromedevtools.github.io/devtools-protocol/tot/>
|
||||||
use deno_core::serde_json::Value;
|
use deno_core::serde_json::Value;
|
||||||
|
|
|
@ -4,6 +4,7 @@ disallowed-methods = [
|
||||||
]
|
]
|
||||||
disallowed-types = [
|
disallowed-types = [
|
||||||
{ path = "reqwest::Client", reason = "use crate::http_util::HttpClient instead" },
|
{ path = "reqwest::Client", reason = "use crate::http_util::HttpClient instead" },
|
||||||
|
{ path = "sys_traits::impls::RealSys", reason = "use crate::sys::CliSys instead" },
|
||||||
]
|
]
|
||||||
ignore-interior-mutability = [
|
ignore-interior-mutability = [
|
||||||
"lsp_types::Uri",
|
"lsp_types::Uri",
|
||||||
|
|
92
cli/emit.rs
92
cli/emit.rs
|
@ -1,10 +1,8 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
use crate::cache::EmitCache;
|
use std::sync::Arc;
|
||||||
use crate::cache::FastInsecureHasher;
|
|
||||||
use crate::cache::ParsedSourceCache;
|
|
||||||
use crate::resolver::CjsTracker;
|
|
||||||
|
|
||||||
|
use deno_ast::EmittedSourceText;
|
||||||
use deno_ast::ModuleKind;
|
use deno_ast::ModuleKind;
|
||||||
use deno_ast::SourceMapOption;
|
use deno_ast::SourceMapOption;
|
||||||
use deno_ast::SourceRange;
|
use deno_ast::SourceRange;
|
||||||
|
@ -13,18 +11,24 @@ use deno_ast::SourceRangedForSpanned;
|
||||||
use deno_ast::TranspileModuleOptions;
|
use deno_ast::TranspileModuleOptions;
|
||||||
use deno_ast::TranspileResult;
|
use deno_ast::TranspileResult;
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
|
use deno_core::error::CoreError;
|
||||||
use deno_core::futures::stream::FuturesUnordered;
|
use deno_core::futures::stream::FuturesUnordered;
|
||||||
use deno_core::futures::FutureExt;
|
use deno_core::futures::FutureExt;
|
||||||
use deno_core::futures::StreamExt;
|
use deno_core::futures::StreamExt;
|
||||||
use deno_core::ModuleSpecifier;
|
use deno_core::ModuleSpecifier;
|
||||||
|
use deno_error::JsErrorBox;
|
||||||
use deno_graph::MediaType;
|
use deno_graph::MediaType;
|
||||||
use deno_graph::Module;
|
use deno_graph::Module;
|
||||||
use deno_graph::ModuleGraph;
|
use deno_graph::ModuleGraph;
|
||||||
use std::sync::Arc;
|
|
||||||
|
use crate::cache::EmitCache;
|
||||||
|
use crate::cache::FastInsecureHasher;
|
||||||
|
use crate::cache::ParsedSourceCache;
|
||||||
|
use crate::resolver::CliCjsTracker;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Emitter {
|
pub struct Emitter {
|
||||||
cjs_tracker: Arc<CjsTracker>,
|
cjs_tracker: Arc<CliCjsTracker>,
|
||||||
emit_cache: Arc<EmitCache>,
|
emit_cache: Arc<EmitCache>,
|
||||||
parsed_source_cache: Arc<ParsedSourceCache>,
|
parsed_source_cache: Arc<ParsedSourceCache>,
|
||||||
transpile_and_emit_options:
|
transpile_and_emit_options:
|
||||||
|
@ -35,7 +39,7 @@ pub struct Emitter {
|
||||||
|
|
||||||
impl Emitter {
|
impl Emitter {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
cjs_tracker: Arc<CjsTracker>,
|
cjs_tracker: Arc<CliCjsTracker>,
|
||||||
emit_cache: Arc<EmitCache>,
|
emit_cache: Arc<EmitCache>,
|
||||||
parsed_source_cache: Arc<ParsedSourceCache>,
|
parsed_source_cache: Arc<ParsedSourceCache>,
|
||||||
transpile_options: deno_ast::TranspileOptions,
|
transpile_options: deno_ast::TranspileOptions,
|
||||||
|
@ -122,7 +126,7 @@ impl Emitter {
|
||||||
let transpiled_source = deno_core::unsync::spawn_blocking({
|
let transpiled_source = deno_core::unsync::spawn_blocking({
|
||||||
let specifier = specifier.clone();
|
let specifier = specifier.clone();
|
||||||
let source = source.clone();
|
let source = source.clone();
|
||||||
move || -> Result<_, AnyError> {
|
move || {
|
||||||
EmitParsedSourceHelper::transpile(
|
EmitParsedSourceHelper::transpile(
|
||||||
&parsed_source_cache,
|
&parsed_source_cache,
|
||||||
&specifier,
|
&specifier,
|
||||||
|
@ -132,6 +136,7 @@ impl Emitter {
|
||||||
&transpile_and_emit_options.0,
|
&transpile_and_emit_options.0,
|
||||||
&transpile_and_emit_options.1,
|
&transpile_and_emit_options.1,
|
||||||
)
|
)
|
||||||
|
.map(|r| r.text)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
|
@ -152,7 +157,7 @@ impl Emitter {
|
||||||
media_type: MediaType,
|
media_type: MediaType,
|
||||||
module_kind: deno_ast::ModuleKind,
|
module_kind: deno_ast::ModuleKind,
|
||||||
source: &Arc<str>,
|
source: &Arc<str>,
|
||||||
) -> Result<String, AnyError> {
|
) -> Result<String, EmitParsedSourceHelperError> {
|
||||||
// Note: keep this in sync with the async version above
|
// Note: keep this in sync with the async version above
|
||||||
let helper = EmitParsedSourceHelper(self);
|
let helper = EmitParsedSourceHelper(self);
|
||||||
match helper.pre_emit_parsed_source(specifier, module_kind, source) {
|
match helper.pre_emit_parsed_source(specifier, module_kind, source) {
|
||||||
|
@ -166,7 +171,8 @@ impl Emitter {
|
||||||
source.clone(),
|
source.clone(),
|
||||||
&self.transpile_and_emit_options.0,
|
&self.transpile_and_emit_options.0,
|
||||||
&self.transpile_and_emit_options.1,
|
&self.transpile_and_emit_options.1,
|
||||||
)?;
|
)?
|
||||||
|
.text;
|
||||||
helper.post_emit_parsed_source(
|
helper.post_emit_parsed_source(
|
||||||
specifier,
|
specifier,
|
||||||
&transpiled_source,
|
&transpiled_source,
|
||||||
|
@ -177,11 +183,36 @@ impl Emitter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn emit_parsed_source_for_deno_compile(
|
||||||
|
&self,
|
||||||
|
specifier: &ModuleSpecifier,
|
||||||
|
media_type: MediaType,
|
||||||
|
module_kind: deno_ast::ModuleKind,
|
||||||
|
source: &Arc<str>,
|
||||||
|
) -> Result<(String, String), AnyError> {
|
||||||
|
let mut emit_options = self.transpile_and_emit_options.1.clone();
|
||||||
|
emit_options.inline_sources = false;
|
||||||
|
emit_options.source_map = SourceMapOption::Separate;
|
||||||
|
// strip off the path to have more deterministic builds as we don't care
|
||||||
|
// about the source name because we manually provide the source map to v8
|
||||||
|
emit_options.source_map_base = Some(deno_path_util::url_parent(specifier));
|
||||||
|
let source = EmitParsedSourceHelper::transpile(
|
||||||
|
&self.parsed_source_cache,
|
||||||
|
specifier,
|
||||||
|
media_type,
|
||||||
|
module_kind,
|
||||||
|
source.clone(),
|
||||||
|
&self.transpile_and_emit_options.0,
|
||||||
|
&emit_options,
|
||||||
|
)?;
|
||||||
|
Ok((source.text, source.source_map.unwrap()))
|
||||||
|
}
|
||||||
|
|
||||||
/// Expects a file URL, panics otherwise.
|
/// Expects a file URL, panics otherwise.
|
||||||
pub async fn load_and_emit_for_hmr(
|
pub async fn load_and_emit_for_hmr(
|
||||||
&self,
|
&self,
|
||||||
specifier: &ModuleSpecifier,
|
specifier: &ModuleSpecifier,
|
||||||
) -> Result<String, AnyError> {
|
) -> Result<String, CoreError> {
|
||||||
let media_type = MediaType::from_specifier(specifier);
|
let media_type = MediaType::from_specifier(specifier);
|
||||||
let source_code = tokio::fs::read_to_string(
|
let source_code = tokio::fs::read_to_string(
|
||||||
ModuleSpecifier::to_file_path(specifier).unwrap(),
|
ModuleSpecifier::to_file_path(specifier).unwrap(),
|
||||||
|
@ -196,17 +227,21 @@ impl Emitter {
|
||||||
let source_arc: Arc<str> = source_code.into();
|
let source_arc: Arc<str> = source_code.into();
|
||||||
let parsed_source = self
|
let parsed_source = self
|
||||||
.parsed_source_cache
|
.parsed_source_cache
|
||||||
.remove_or_parse_module(specifier, source_arc, media_type)?;
|
.remove_or_parse_module(specifier, source_arc, media_type)
|
||||||
|
.map_err(JsErrorBox::from_err)?;
|
||||||
// HMR doesn't work with embedded source maps for some reason, so set
|
// HMR doesn't work with embedded source maps for some reason, so set
|
||||||
// the option to not use them (though you should test this out because
|
// the option to not use them (though you should test this out because
|
||||||
// this statement is probably wrong)
|
// this statement is probably wrong)
|
||||||
let mut options = self.transpile_and_emit_options.1.clone();
|
let mut options = self.transpile_and_emit_options.1.clone();
|
||||||
options.source_map = SourceMapOption::None;
|
options.source_map = SourceMapOption::None;
|
||||||
let is_cjs = self.cjs_tracker.is_cjs_with_known_is_script(
|
let is_cjs = self
|
||||||
|
.cjs_tracker
|
||||||
|
.is_cjs_with_known_is_script(
|
||||||
specifier,
|
specifier,
|
||||||
media_type,
|
media_type,
|
||||||
parsed_source.compute_is_script(),
|
parsed_source.compute_is_script(),
|
||||||
)?;
|
)
|
||||||
|
.map_err(JsErrorBox::from_err)?;
|
||||||
let transpiled_source = parsed_source
|
let transpiled_source = parsed_source
|
||||||
.transpile(
|
.transpile(
|
||||||
&self.transpile_and_emit_options.0,
|
&self.transpile_and_emit_options.0,
|
||||||
|
@ -214,7 +249,8 @@ impl Emitter {
|
||||||
module_kind: Some(ModuleKind::from_is_cjs(is_cjs)),
|
module_kind: Some(ModuleKind::from_is_cjs(is_cjs)),
|
||||||
},
|
},
|
||||||
&options,
|
&options,
|
||||||
)?
|
)
|
||||||
|
.map_err(JsErrorBox::from_err)?
|
||||||
.into_source();
|
.into_source();
|
||||||
Ok(transpiled_source.text)
|
Ok(transpiled_source.text)
|
||||||
}
|
}
|
||||||
|
@ -253,6 +289,19 @@ enum PreEmitResult {
|
||||||
NotCached { source_hash: u64 },
|
NotCached { source_hash: u64 },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, thiserror::Error, deno_error::JsError)]
|
||||||
|
pub enum EmitParsedSourceHelperError {
|
||||||
|
#[class(inherit)]
|
||||||
|
#[error(transparent)]
|
||||||
|
ParseDiagnostic(#[from] deno_ast::ParseDiagnostic),
|
||||||
|
#[class(inherit)]
|
||||||
|
#[error(transparent)]
|
||||||
|
Transpile(#[from] deno_ast::TranspileError),
|
||||||
|
#[class(inherit)]
|
||||||
|
#[error(transparent)]
|
||||||
|
Other(#[from] JsErrorBox),
|
||||||
|
}
|
||||||
|
|
||||||
/// Helper to share code between async and sync emit_parsed_source methods.
|
/// Helper to share code between async and sync emit_parsed_source methods.
|
||||||
struct EmitParsedSourceHelper<'a>(&'a Emitter);
|
struct EmitParsedSourceHelper<'a>(&'a Emitter);
|
||||||
|
|
||||||
|
@ -282,7 +331,7 @@ impl<'a> EmitParsedSourceHelper<'a> {
|
||||||
source: Arc<str>,
|
source: Arc<str>,
|
||||||
transpile_options: &deno_ast::TranspileOptions,
|
transpile_options: &deno_ast::TranspileOptions,
|
||||||
emit_options: &deno_ast::EmitOptions,
|
emit_options: &deno_ast::EmitOptions,
|
||||||
) -> Result<String, AnyError> {
|
) -> Result<EmittedSourceText, EmitParsedSourceHelperError> {
|
||||||
// nothing else needs the parsed source at this point, so remove from
|
// nothing else needs the parsed source at this point, so remove from
|
||||||
// the cache in order to not transpile owned
|
// the cache in order to not transpile owned
|
||||||
let parsed_source = parsed_source_cache
|
let parsed_source = parsed_source_cache
|
||||||
|
@ -302,8 +351,7 @@ impl<'a> EmitParsedSourceHelper<'a> {
|
||||||
source
|
source
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
debug_assert!(transpiled_source.source_map.is_none());
|
Ok(transpiled_source)
|
||||||
Ok(transpiled_source.text)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn post_emit_parsed_source(
|
pub fn post_emit_parsed_source(
|
||||||
|
@ -323,7 +371,7 @@ impl<'a> EmitParsedSourceHelper<'a> {
|
||||||
// todo(dsherret): this is a temporary measure until we have swc erroring for this
|
// todo(dsherret): this is a temporary measure until we have swc erroring for this
|
||||||
fn ensure_no_import_assertion(
|
fn ensure_no_import_assertion(
|
||||||
parsed_source: &deno_ast::ParsedSource,
|
parsed_source: &deno_ast::ParsedSource,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), JsErrorBox> {
|
||||||
fn has_import_assertion(text: &str) -> bool {
|
fn has_import_assertion(text: &str) -> bool {
|
||||||
// good enough
|
// good enough
|
||||||
text.contains(" assert ") && !text.contains(" with ")
|
text.contains(" assert ") && !text.contains(" with ")
|
||||||
|
@ -332,7 +380,7 @@ fn ensure_no_import_assertion(
|
||||||
fn create_err(
|
fn create_err(
|
||||||
parsed_source: &deno_ast::ParsedSource,
|
parsed_source: &deno_ast::ParsedSource,
|
||||||
range: SourceRange,
|
range: SourceRange,
|
||||||
) -> AnyError {
|
) -> JsErrorBox {
|
||||||
let text_info = parsed_source.text_info_lazy();
|
let text_info = parsed_source.text_info_lazy();
|
||||||
let loc = text_info.line_and_column_display(range.start);
|
let loc = text_info.line_and_column_display(range.start);
|
||||||
let mut msg = "Import assertions are deprecated. Use `with` keyword, instead of 'assert' keyword.".to_string();
|
let mut msg = "Import assertions are deprecated. Use `with` keyword, instead of 'assert' keyword.".to_string();
|
||||||
|
@ -345,7 +393,7 @@ fn ensure_no_import_assertion(
|
||||||
loc.line_number,
|
loc.line_number,
|
||||||
loc.column_number,
|
loc.column_number,
|
||||||
));
|
));
|
||||||
deno_core::anyhow::anyhow!("{}", msg)
|
JsErrorBox::generic(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
let deno_ast::ProgramRef::Module(module) = parsed_source.program_ref() else {
|
let deno_ast::ProgramRef::Module(module) = parsed_source.program_ref() else {
|
||||||
|
|
119
cli/errors.rs
119
cli/errors.rs
|
@ -1,119 +0,0 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
|
||||||
|
|
||||||
//! There are many types of errors in Deno:
|
|
||||||
//! - AnyError: a generic wrapper that can encapsulate any type of error.
|
|
||||||
//! - JsError: a container for the error message and stack trace for exceptions
|
|
||||||
//! thrown in JavaScript code. We use this to pretty-print stack traces.
|
|
||||||
//! - Diagnostic: these are errors that originate in TypeScript's compiler.
|
|
||||||
//! They're similar to JsError, in that they have line numbers. But
|
|
||||||
//! Diagnostics are compile-time type errors, whereas JsErrors are runtime
|
|
||||||
//! exceptions.
|
|
||||||
|
|
||||||
use deno_ast::ParseDiagnostic;
|
|
||||||
use deno_core::error::AnyError;
|
|
||||||
use deno_graph::source::ResolveError;
|
|
||||||
use deno_graph::ModuleError;
|
|
||||||
use deno_graph::ModuleGraphError;
|
|
||||||
use deno_graph::ModuleLoadError;
|
|
||||||
use deno_graph::ResolutionError;
|
|
||||||
use import_map::ImportMapError;
|
|
||||||
|
|
||||||
fn get_import_map_error_class(_: &ImportMapError) -> &'static str {
|
|
||||||
"URIError"
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_diagnostic_class(_: &ParseDiagnostic) -> &'static str {
|
|
||||||
"SyntaxError"
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_module_graph_error_class(err: &ModuleGraphError) -> &'static str {
|
|
||||||
use deno_graph::JsrLoadError;
|
|
||||||
use deno_graph::NpmLoadError;
|
|
||||||
|
|
||||||
match err {
|
|
||||||
ModuleGraphError::ResolutionError(err)
|
|
||||||
| ModuleGraphError::TypesResolutionError(err) => {
|
|
||||||
get_resolution_error_class(err)
|
|
||||||
}
|
|
||||||
ModuleGraphError::ModuleError(err) => match err {
|
|
||||||
ModuleError::InvalidTypeAssertion { .. } => "SyntaxError",
|
|
||||||
ModuleError::ParseErr(_, diagnostic) => get_diagnostic_class(diagnostic),
|
|
||||||
ModuleError::WasmParseErr(..) => "SyntaxError",
|
|
||||||
ModuleError::UnsupportedMediaType { .. }
|
|
||||||
| ModuleError::UnsupportedImportAttributeType { .. } => "TypeError",
|
|
||||||
ModuleError::Missing(_, _) | ModuleError::MissingDynamic(_, _) => {
|
|
||||||
"NotFound"
|
|
||||||
}
|
|
||||||
ModuleError::LoadingErr(_, _, err) => match err {
|
|
||||||
ModuleLoadError::Loader(err) => get_error_class_name(err.as_ref()),
|
|
||||||
ModuleLoadError::HttpsChecksumIntegrity(_)
|
|
||||||
| ModuleLoadError::TooManyRedirects => "Error",
|
|
||||||
ModuleLoadError::NodeUnknownBuiltinModule(_) => "NotFound",
|
|
||||||
ModuleLoadError::Decode(_) => "TypeError",
|
|
||||||
ModuleLoadError::Npm(err) => match err {
|
|
||||||
NpmLoadError::NotSupportedEnvironment
|
|
||||||
| NpmLoadError::PackageReqResolution(_)
|
|
||||||
| NpmLoadError::RegistryInfo(_) => "Error",
|
|
||||||
NpmLoadError::PackageReqReferenceParse(_) => "TypeError",
|
|
||||||
},
|
|
||||||
ModuleLoadError::Jsr(err) => match err {
|
|
||||||
JsrLoadError::UnsupportedManifestChecksum
|
|
||||||
| JsrLoadError::PackageFormat(_) => "TypeError",
|
|
||||||
JsrLoadError::ContentLoadExternalSpecifier
|
|
||||||
| JsrLoadError::ContentLoad(_)
|
|
||||||
| JsrLoadError::ContentChecksumIntegrity(_)
|
|
||||||
| JsrLoadError::PackageManifestLoad(_, _)
|
|
||||||
| JsrLoadError::PackageVersionManifestChecksumIntegrity(..)
|
|
||||||
| JsrLoadError::PackageVersionManifestLoad(_, _)
|
|
||||||
| JsrLoadError::RedirectInPackage(_) => "Error",
|
|
||||||
JsrLoadError::PackageNotFound(_)
|
|
||||||
| JsrLoadError::PackageReqNotFound(_)
|
|
||||||
| JsrLoadError::PackageVersionNotFound(_)
|
|
||||||
| JsrLoadError::UnknownExport { .. } => "NotFound",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_resolution_error_class(err: &ResolutionError) -> &'static str {
|
|
||||||
match err {
|
|
||||||
ResolutionError::ResolverError { error, .. } => {
|
|
||||||
use ResolveError::*;
|
|
||||||
match error.as_ref() {
|
|
||||||
Specifier(_) => "TypeError",
|
|
||||||
Other(e) => get_error_class_name(e),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => "TypeError",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_try_from_int_error_class(_: &std::num::TryFromIntError) -> &'static str {
|
|
||||||
"TypeError"
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_error_class_name(e: &AnyError) -> &'static str {
|
|
||||||
deno_runtime::errors::get_error_class_name(e)
|
|
||||||
.or_else(|| {
|
|
||||||
e.downcast_ref::<ImportMapError>()
|
|
||||||
.map(get_import_map_error_class)
|
|
||||||
})
|
|
||||||
.or_else(|| {
|
|
||||||
e.downcast_ref::<ParseDiagnostic>()
|
|
||||||
.map(get_diagnostic_class)
|
|
||||||
})
|
|
||||||
.or_else(|| {
|
|
||||||
e.downcast_ref::<ModuleGraphError>()
|
|
||||||
.map(get_module_graph_error_class)
|
|
||||||
})
|
|
||||||
.or_else(|| {
|
|
||||||
e.downcast_ref::<ResolutionError>()
|
|
||||||
.map(get_resolution_error_class)
|
|
||||||
})
|
|
||||||
.or_else(|| {
|
|
||||||
e.downcast_ref::<std::num::TryFromIntError>()
|
|
||||||
.map(get_try_from_int_error_class)
|
|
||||||
})
|
|
||||||
.unwrap_or("Error")
|
|
||||||
}
|
|
436
cli/factory.rs
436
cli/factory.rs
|
@ -1,4 +1,39 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
|
use std::future::Future;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use deno_cache_dir::npm::NpmCacheDir;
|
||||||
|
use deno_config::workspace::PackageJsonDepResolution;
|
||||||
|
use deno_config::workspace::WorkspaceResolver;
|
||||||
|
use deno_core::error::AnyError;
|
||||||
|
use deno_core::futures::FutureExt;
|
||||||
|
use deno_core::FeatureChecker;
|
||||||
|
use deno_error::JsErrorBox;
|
||||||
|
use deno_npm_cache::NpmCacheSetting;
|
||||||
|
use deno_resolver::cjs::IsCjsResolutionMode;
|
||||||
|
use deno_resolver::npm::managed::ManagedInNpmPkgCheckerCreateOptions;
|
||||||
|
use deno_resolver::npm::managed::NpmResolutionCell;
|
||||||
|
use deno_resolver::npm::CreateInNpmPkgCheckerOptions;
|
||||||
|
use deno_resolver::npm::DenoInNpmPackageChecker;
|
||||||
|
use deno_resolver::npm::NpmReqResolverOptions;
|
||||||
|
use deno_resolver::sloppy_imports::SloppyImportsCachedFs;
|
||||||
|
use deno_resolver::DenoResolverOptions;
|
||||||
|
use deno_resolver::NodeAndNpmReqResolver;
|
||||||
|
use deno_runtime::deno_fs;
|
||||||
|
use deno_runtime::deno_fs::RealFs;
|
||||||
|
use deno_runtime::deno_node::RealIsBuiltInNodeModuleChecker;
|
||||||
|
use deno_runtime::deno_permissions::Permissions;
|
||||||
|
use deno_runtime::deno_permissions::PermissionsContainer;
|
||||||
|
use deno_runtime::deno_tls::rustls::RootCertStore;
|
||||||
|
use deno_runtime::deno_tls::RootCertStoreProvider;
|
||||||
|
use deno_runtime::deno_web::BlobStore;
|
||||||
|
use deno_runtime::inspector_server::InspectorServer;
|
||||||
|
use deno_runtime::permissions::RuntimePermissionDescriptorParser;
|
||||||
|
use log::warn;
|
||||||
|
use node_resolver::analyze::NodeCodeTranslator;
|
||||||
|
use once_cell::sync::OnceCell;
|
||||||
|
|
||||||
use crate::args::check_warn_tsconfig;
|
use crate::args::check_warn_tsconfig;
|
||||||
use crate::args::get_root_cert_store;
|
use crate::args::get_root_cert_store;
|
||||||
|
@ -11,7 +46,6 @@ use crate::args::StorageKeyResolver;
|
||||||
use crate::args::TsConfigType;
|
use crate::args::TsConfigType;
|
||||||
use crate::cache::Caches;
|
use crate::cache::Caches;
|
||||||
use crate::cache::CodeCache;
|
use crate::cache::CodeCache;
|
||||||
use crate::cache::DenoCacheEnvFsAdapter;
|
|
||||||
use crate::cache::DenoDir;
|
use crate::cache::DenoDir;
|
||||||
use crate::cache::DenoDirProvider;
|
use crate::cache::DenoDirProvider;
|
||||||
use crate::cache::EmitCache;
|
use crate::cache::EmitCache;
|
||||||
|
@ -22,7 +56,7 @@ use crate::cache::ModuleInfoCache;
|
||||||
use crate::cache::NodeAnalysisCache;
|
use crate::cache::NodeAnalysisCache;
|
||||||
use crate::cache::ParsedSourceCache;
|
use crate::cache::ParsedSourceCache;
|
||||||
use crate::emit::Emitter;
|
use crate::emit::Emitter;
|
||||||
use crate::file_fetcher::FileFetcher;
|
use crate::file_fetcher::CliFileFetcher;
|
||||||
use crate::graph_container::MainModuleGraphContainer;
|
use crate::graph_container::MainModuleGraphContainer;
|
||||||
use crate::graph_util::FileWatcherReporter;
|
use crate::graph_util::FileWatcherReporter;
|
||||||
use crate::graph_util::ModuleGraphBuilder;
|
use crate::graph_util::ModuleGraphBuilder;
|
||||||
|
@ -32,25 +66,32 @@ use crate::module_loader::CliModuleLoaderFactory;
|
||||||
use crate::module_loader::ModuleLoadPreparer;
|
use crate::module_loader::ModuleLoadPreparer;
|
||||||
use crate::node::CliCjsCodeAnalyzer;
|
use crate::node::CliCjsCodeAnalyzer;
|
||||||
use crate::node::CliNodeCodeTranslator;
|
use crate::node::CliNodeCodeTranslator;
|
||||||
use crate::npm::create_cli_npm_resolver;
|
use crate::node::CliNodeResolver;
|
||||||
use crate::npm::create_in_npm_pkg_checker;
|
use crate::node::CliPackageJsonResolver;
|
||||||
|
use crate::npm::installer::NpmInstaller;
|
||||||
|
use crate::npm::installer::NpmResolutionInstaller;
|
||||||
use crate::npm::CliByonmNpmResolverCreateOptions;
|
use crate::npm::CliByonmNpmResolverCreateOptions;
|
||||||
use crate::npm::CliManagedInNpmPkgCheckerCreateOptions;
|
|
||||||
use crate::npm::CliManagedNpmResolverCreateOptions;
|
use crate::npm::CliManagedNpmResolverCreateOptions;
|
||||||
|
use crate::npm::CliNpmCache;
|
||||||
|
use crate::npm::CliNpmCacheHttpClient;
|
||||||
|
use crate::npm::CliNpmRegistryInfoProvider;
|
||||||
use crate::npm::CliNpmResolver;
|
use crate::npm::CliNpmResolver;
|
||||||
use crate::npm::CliNpmResolverCreateOptions;
|
use crate::npm::CliNpmResolverCreateOptions;
|
||||||
use crate::npm::CliNpmResolverManagedSnapshotOption;
|
use crate::npm::CliNpmResolverManagedSnapshotOption;
|
||||||
use crate::npm::CreateInNpmPkgCheckerOptions;
|
use crate::npm::CliNpmTarballCache;
|
||||||
use crate::resolver::CjsTracker;
|
use crate::npm::NpmRegistryReadPermissionChecker;
|
||||||
|
use crate::npm::NpmRegistryReadPermissionCheckerMode;
|
||||||
|
use crate::npm::NpmResolutionInitializer;
|
||||||
|
use crate::resolver::CliCjsTracker;
|
||||||
use crate::resolver::CliDenoResolver;
|
use crate::resolver::CliDenoResolver;
|
||||||
use crate::resolver::CliDenoResolverFs;
|
use crate::resolver::CliNpmGraphResolver;
|
||||||
use crate::resolver::CliNpmReqResolver;
|
use crate::resolver::CliNpmReqResolver;
|
||||||
use crate::resolver::CliResolver;
|
use crate::resolver::CliResolver;
|
||||||
use crate::resolver::CliResolverOptions;
|
|
||||||
use crate::resolver::CliSloppyImportsResolver;
|
use crate::resolver::CliSloppyImportsResolver;
|
||||||
|
use crate::resolver::FoundPackageJsonDepFlag;
|
||||||
use crate::resolver::NpmModuleLoader;
|
use crate::resolver::NpmModuleLoader;
|
||||||
use crate::resolver::SloppyImportsCachedFs;
|
use crate::standalone::binary::DenoCompileBinaryWriter;
|
||||||
use crate::standalone::DenoCompileBinaryWriter;
|
use crate::sys::CliSys;
|
||||||
use crate::tools::check::TypeChecker;
|
use crate::tools::check::TypeChecker;
|
||||||
use crate::tools::coverage::CoverageCollector;
|
use crate::tools::coverage::CoverageCollector;
|
||||||
use crate::tools::lint::LintRuleProvider;
|
use crate::tools::lint::LintRuleProvider;
|
||||||
|
@ -62,36 +103,6 @@ use crate::util::progress_bar::ProgressBar;
|
||||||
use crate::util::progress_bar::ProgressBarStyle;
|
use crate::util::progress_bar::ProgressBarStyle;
|
||||||
use crate::worker::CliMainWorkerFactory;
|
use crate::worker::CliMainWorkerFactory;
|
||||||
use crate::worker::CliMainWorkerOptions;
|
use crate::worker::CliMainWorkerOptions;
|
||||||
use std::path::PathBuf;
|
|
||||||
|
|
||||||
use deno_cache_dir::npm::NpmCacheDir;
|
|
||||||
use deno_config::workspace::PackageJsonDepResolution;
|
|
||||||
use deno_config::workspace::WorkspaceResolver;
|
|
||||||
use deno_core::error::AnyError;
|
|
||||||
use deno_core::futures::FutureExt;
|
|
||||||
use deno_core::FeatureChecker;
|
|
||||||
|
|
||||||
use deno_resolver::cjs::IsCjsResolutionMode;
|
|
||||||
use deno_resolver::npm::NpmReqResolverOptions;
|
|
||||||
use deno_resolver::DenoResolverOptions;
|
|
||||||
use deno_resolver::NodeAndNpmReqResolver;
|
|
||||||
use deno_runtime::deno_fs;
|
|
||||||
use deno_runtime::deno_node::DenoFsNodeResolverEnv;
|
|
||||||
use deno_runtime::deno_node::NodeResolver;
|
|
||||||
use deno_runtime::deno_node::PackageJsonResolver;
|
|
||||||
use deno_runtime::deno_permissions::Permissions;
|
|
||||||
use deno_runtime::deno_permissions::PermissionsContainer;
|
|
||||||
use deno_runtime::deno_tls::rustls::RootCertStore;
|
|
||||||
use deno_runtime::deno_tls::RootCertStoreProvider;
|
|
||||||
use deno_runtime::deno_web::BlobStore;
|
|
||||||
use deno_runtime::inspector_server::InspectorServer;
|
|
||||||
use deno_runtime::permissions::RuntimePermissionDescriptorParser;
|
|
||||||
use log::warn;
|
|
||||||
use node_resolver::analyze::NodeCodeTranslator;
|
|
||||||
use node_resolver::InNpmPackageChecker;
|
|
||||||
use once_cell::sync::OnceCell;
|
|
||||||
use std::future::Future;
|
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
struct CliRootCertStoreProvider {
|
struct CliRootCertStoreProvider {
|
||||||
cell: OnceCell<RootCertStore>,
|
cell: OnceCell<RootCertStore>,
|
||||||
|
@ -116,7 +127,7 @@ impl CliRootCertStoreProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RootCertStoreProvider for CliRootCertStoreProvider {
|
impl RootCertStoreProvider for CliRootCertStoreProvider {
|
||||||
fn get_or_try_init(&self) -> Result<&RootCertStore, AnyError> {
|
fn get_or_try_init(&self) -> Result<&RootCertStore, JsErrorBox> {
|
||||||
self
|
self
|
||||||
.cell
|
.cell
|
||||||
.get_or_try_init(|| {
|
.get_or_try_init(|| {
|
||||||
|
@ -126,7 +137,7 @@ impl RootCertStoreProvider for CliRootCertStoreProvider {
|
||||||
self.maybe_ca_data.clone(),
|
self.maybe_ca_data.clone(),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.map_err(|e| e.into())
|
.map_err(JsErrorBox::from_err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,19 +189,20 @@ impl<T> Deferred<T> {
|
||||||
struct CliFactoryServices {
|
struct CliFactoryServices {
|
||||||
blob_store: Deferred<Arc<BlobStore>>,
|
blob_store: Deferred<Arc<BlobStore>>,
|
||||||
caches: Deferred<Arc<Caches>>,
|
caches: Deferred<Arc<Caches>>,
|
||||||
cjs_tracker: Deferred<Arc<CjsTracker>>,
|
cjs_tracker: Deferred<Arc<CliCjsTracker>>,
|
||||||
cli_options: Deferred<Arc<CliOptions>>,
|
cli_options: Deferred<Arc<CliOptions>>,
|
||||||
code_cache: Deferred<Arc<CodeCache>>,
|
code_cache: Deferred<Arc<CodeCache>>,
|
||||||
deno_resolver: Deferred<Arc<CliDenoResolver>>,
|
deno_resolver: Deferred<Arc<CliDenoResolver>>,
|
||||||
emit_cache: Deferred<Arc<EmitCache>>,
|
emit_cache: Deferred<Arc<EmitCache>>,
|
||||||
emitter: Deferred<Arc<Emitter>>,
|
emitter: Deferred<Arc<Emitter>>,
|
||||||
feature_checker: Deferred<Arc<FeatureChecker>>,
|
feature_checker: Deferred<Arc<FeatureChecker>>,
|
||||||
file_fetcher: Deferred<Arc<FileFetcher>>,
|
file_fetcher: Deferred<Arc<CliFileFetcher>>,
|
||||||
|
found_pkg_json_dep_flag: Arc<FoundPackageJsonDepFlag>,
|
||||||
fs: Deferred<Arc<dyn deno_fs::FileSystem>>,
|
fs: Deferred<Arc<dyn deno_fs::FileSystem>>,
|
||||||
global_http_cache: Deferred<Arc<GlobalHttpCache>>,
|
global_http_cache: Deferred<Arc<GlobalHttpCache>>,
|
||||||
http_cache: Deferred<Arc<dyn HttpCache>>,
|
http_cache: Deferred<Arc<dyn HttpCache>>,
|
||||||
http_client_provider: Deferred<Arc<HttpClientProvider>>,
|
http_client_provider: Deferred<Arc<HttpClientProvider>>,
|
||||||
in_npm_pkg_checker: Deferred<Arc<dyn InNpmPackageChecker>>,
|
in_npm_pkg_checker: Deferred<DenoInNpmPackageChecker>,
|
||||||
main_graph_container: Deferred<Arc<MainModuleGraphContainer>>,
|
main_graph_container: Deferred<Arc<MainModuleGraphContainer>>,
|
||||||
maybe_file_watcher_reporter: Deferred<Option<FileWatcherReporter>>,
|
maybe_file_watcher_reporter: Deferred<Option<FileWatcherReporter>>,
|
||||||
maybe_inspector_server: Deferred<Option<Arc<InspectorServer>>>,
|
maybe_inspector_server: Deferred<Option<Arc<InspectorServer>>>,
|
||||||
|
@ -199,13 +211,23 @@ struct CliFactoryServices {
|
||||||
module_info_cache: Deferred<Arc<ModuleInfoCache>>,
|
module_info_cache: Deferred<Arc<ModuleInfoCache>>,
|
||||||
module_load_preparer: Deferred<Arc<ModuleLoadPreparer>>,
|
module_load_preparer: Deferred<Arc<ModuleLoadPreparer>>,
|
||||||
node_code_translator: Deferred<Arc<CliNodeCodeTranslator>>,
|
node_code_translator: Deferred<Arc<CliNodeCodeTranslator>>,
|
||||||
node_resolver: Deferred<Arc<NodeResolver>>,
|
node_resolver: Deferred<Arc<CliNodeResolver>>,
|
||||||
|
npm_cache: Deferred<Arc<CliNpmCache>>,
|
||||||
npm_cache_dir: Deferred<Arc<NpmCacheDir>>,
|
npm_cache_dir: Deferred<Arc<NpmCacheDir>>,
|
||||||
|
npm_cache_http_client: Deferred<Arc<CliNpmCacheHttpClient>>,
|
||||||
|
npm_graph_resolver: Deferred<Arc<CliNpmGraphResolver>>,
|
||||||
|
npm_installer: Deferred<Arc<NpmInstaller>>,
|
||||||
|
npm_registry_info_provider: Deferred<Arc<CliNpmRegistryInfoProvider>>,
|
||||||
npm_req_resolver: Deferred<Arc<CliNpmReqResolver>>,
|
npm_req_resolver: Deferred<Arc<CliNpmReqResolver>>,
|
||||||
npm_resolver: Deferred<Arc<dyn CliNpmResolver>>,
|
npm_resolution: Arc<NpmResolutionCell>,
|
||||||
|
npm_resolution_initializer: Deferred<Arc<NpmResolutionInitializer>>,
|
||||||
|
npm_resolution_installer: Deferred<Arc<NpmResolutionInstaller>>,
|
||||||
|
npm_resolver: Deferred<CliNpmResolver>,
|
||||||
|
npm_tarball_cache: Deferred<Arc<CliNpmTarballCache>>,
|
||||||
parsed_source_cache: Deferred<Arc<ParsedSourceCache>>,
|
parsed_source_cache: Deferred<Arc<ParsedSourceCache>>,
|
||||||
permission_desc_parser: Deferred<Arc<RuntimePermissionDescriptorParser>>,
|
permission_desc_parser:
|
||||||
pkg_json_resolver: Deferred<Arc<PackageJsonResolver>>,
|
Deferred<Arc<RuntimePermissionDescriptorParser<CliSys>>>,
|
||||||
|
pkg_json_resolver: Deferred<Arc<CliPackageJsonResolver>>,
|
||||||
resolver: Deferred<Arc<CliResolver>>,
|
resolver: Deferred<Arc<CliResolver>>,
|
||||||
root_cert_store_provider: Deferred<Arc<dyn RootCertStoreProvider>>,
|
root_cert_store_provider: Deferred<Arc<dyn RootCertStoreProvider>>,
|
||||||
root_permissions_container: Deferred<PermissionsContainer>,
|
root_permissions_container: Deferred<PermissionsContainer>,
|
||||||
|
@ -255,7 +277,7 @@ impl CliFactory {
|
||||||
|
|
||||||
pub fn cli_options(&self) -> Result<&Arc<CliOptions>, AnyError> {
|
pub fn cli_options(&self) -> Result<&Arc<CliOptions>, AnyError> {
|
||||||
self.services.cli_options.get_or_try_init(|| {
|
self.services.cli_options.get_or_try_init(|| {
|
||||||
CliOptions::from_flags(self.flags.clone()).map(Arc::new)
|
CliOptions::from_flags(&self.sys(), self.flags.clone()).map(Arc::new)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -318,8 +340,8 @@ impl CliFactory {
|
||||||
pub fn global_http_cache(&self) -> Result<&Arc<GlobalHttpCache>, AnyError> {
|
pub fn global_http_cache(&self) -> Result<&Arc<GlobalHttpCache>, AnyError> {
|
||||||
self.services.global_http_cache.get_or_try_init(|| {
|
self.services.global_http_cache.get_or_try_init(|| {
|
||||||
Ok(Arc::new(GlobalHttpCache::new(
|
Ok(Arc::new(GlobalHttpCache::new(
|
||||||
|
self.sys(),
|
||||||
self.deno_dir()?.remote_folder_path(),
|
self.deno_dir()?.remote_folder_path(),
|
||||||
crate::cache::RealDenoCacheEnv,
|
|
||||||
)))
|
)))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -350,34 +372,40 @@ impl CliFactory {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn file_fetcher(&self) -> Result<&Arc<FileFetcher>, AnyError> {
|
pub fn file_fetcher(&self) -> Result<&Arc<CliFileFetcher>, AnyError> {
|
||||||
self.services.file_fetcher.get_or_try_init(|| {
|
self.services.file_fetcher.get_or_try_init(|| {
|
||||||
let cli_options = self.cli_options()?;
|
let cli_options = self.cli_options()?;
|
||||||
Ok(Arc::new(FileFetcher::new(
|
Ok(Arc::new(CliFileFetcher::new(
|
||||||
self.http_cache()?.clone(),
|
self.http_cache()?.clone(),
|
||||||
cli_options.cache_setting(),
|
|
||||||
!cli_options.no_remote(),
|
|
||||||
self.http_client_provider().clone(),
|
self.http_client_provider().clone(),
|
||||||
|
self.sys(),
|
||||||
self.blob_store().clone(),
|
self.blob_store().clone(),
|
||||||
Some(self.text_only_progress_bar().clone()),
|
Some(self.text_only_progress_bar().clone()),
|
||||||
|
!cli_options.no_remote(),
|
||||||
|
cli_options.cache_setting(),
|
||||||
|
log::Level::Info,
|
||||||
)))
|
)))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fs(&self) -> &Arc<dyn deno_fs::FileSystem> {
|
pub fn fs(&self) -> &Arc<dyn deno_fs::FileSystem> {
|
||||||
self.services.fs.get_or_init(|| Arc::new(deno_fs::RealFs))
|
self.services.fs.get_or_init(|| Arc::new(RealFs))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn sys(&self) -> CliSys {
|
||||||
|
CliSys::default() // very cheap to make
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn in_npm_pkg_checker(
|
pub fn in_npm_pkg_checker(
|
||||||
&self,
|
&self,
|
||||||
) -> Result<&Arc<dyn InNpmPackageChecker>, AnyError> {
|
) -> Result<&DenoInNpmPackageChecker, AnyError> {
|
||||||
self.services.in_npm_pkg_checker.get_or_try_init(|| {
|
self.services.in_npm_pkg_checker.get_or_try_init(|| {
|
||||||
let cli_options = self.cli_options()?;
|
let cli_options = self.cli_options()?;
|
||||||
let options = if cli_options.use_byonm() {
|
let options = if cli_options.use_byonm() {
|
||||||
CreateInNpmPkgCheckerOptions::Byonm
|
CreateInNpmPkgCheckerOptions::Byonm
|
||||||
} else {
|
} else {
|
||||||
CreateInNpmPkgCheckerOptions::Managed(
|
CreateInNpmPkgCheckerOptions::Managed(
|
||||||
CliManagedInNpmPkgCheckerCreateOptions {
|
ManagedInNpmPkgCheckerCreateOptions {
|
||||||
root_cache_dir_url: self.npm_cache_dir()?.root_dir_url(),
|
root_cache_dir_url: self.npm_cache_dir()?.root_dir_url(),
|
||||||
maybe_node_modules_path: cli_options
|
maybe_node_modules_path: cli_options
|
||||||
.node_modules_dir_path()
|
.node_modules_dir_path()
|
||||||
|
@ -385,37 +413,162 @@ impl CliFactory {
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
Ok(create_in_npm_pkg_checker(options))
|
Ok(DenoInNpmPackageChecker::new(options))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn npm_cache(&self) -> Result<&Arc<CliNpmCache>, AnyError> {
|
||||||
|
self.services.npm_cache.get_or_try_init(|| {
|
||||||
|
let cli_options = self.cli_options()?;
|
||||||
|
Ok(Arc::new(CliNpmCache::new(
|
||||||
|
self.npm_cache_dir()?.clone(),
|
||||||
|
self.sys(),
|
||||||
|
NpmCacheSetting::from_cache_setting(&cli_options.cache_setting()),
|
||||||
|
cli_options.npmrc().clone(),
|
||||||
|
)))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn npm_cache_dir(&self) -> Result<&Arc<NpmCacheDir>, AnyError> {
|
pub fn npm_cache_dir(&self) -> Result<&Arc<NpmCacheDir>, AnyError> {
|
||||||
self.services.npm_cache_dir.get_or_try_init(|| {
|
self.services.npm_cache_dir.get_or_try_init(|| {
|
||||||
let fs = self.fs();
|
|
||||||
let global_path = self.deno_dir()?.npm_folder_path();
|
let global_path = self.deno_dir()?.npm_folder_path();
|
||||||
let cli_options = self.cli_options()?;
|
let cli_options = self.cli_options()?;
|
||||||
Ok(Arc::new(NpmCacheDir::new(
|
Ok(Arc::new(NpmCacheDir::new(
|
||||||
&DenoCacheEnvFsAdapter(fs.as_ref()),
|
&self.sys(),
|
||||||
global_path,
|
global_path,
|
||||||
cli_options.npmrc().get_all_known_registries_urls(),
|
cli_options.npmrc().get_all_known_registries_urls(),
|
||||||
)))
|
)))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn npm_resolver(
|
pub fn npm_cache_http_client(&self) -> &Arc<CliNpmCacheHttpClient> {
|
||||||
|
self.services.npm_cache_http_client.get_or_init(|| {
|
||||||
|
Arc::new(CliNpmCacheHttpClient::new(
|
||||||
|
self.http_client_provider().clone(),
|
||||||
|
self.text_only_progress_bar().clone(),
|
||||||
|
))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn npm_graph_resolver(
|
||||||
&self,
|
&self,
|
||||||
) -> Result<&Arc<dyn CliNpmResolver>, AnyError> {
|
) -> Result<&Arc<CliNpmGraphResolver>, AnyError> {
|
||||||
|
self.services.npm_graph_resolver.get_or_try_init(|| {
|
||||||
|
let cli_options = self.cli_options()?;
|
||||||
|
Ok(Arc::new(CliNpmGraphResolver::new(
|
||||||
|
self.npm_installer_if_managed()?.cloned(),
|
||||||
|
self.services.found_pkg_json_dep_flag.clone(),
|
||||||
|
cli_options.unstable_bare_node_builtins(),
|
||||||
|
cli_options.default_npm_caching_strategy(),
|
||||||
|
)))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn npm_installer_if_managed(
|
||||||
|
&self,
|
||||||
|
) -> Result<Option<&Arc<NpmInstaller>>, AnyError> {
|
||||||
|
let options = self.cli_options()?;
|
||||||
|
if options.use_byonm() || options.no_npm() {
|
||||||
|
Ok(None)
|
||||||
|
} else {
|
||||||
|
Ok(Some(self.npm_installer()?))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn npm_installer(&self) -> Result<&Arc<NpmInstaller>, AnyError> {
|
||||||
|
self.services.npm_installer.get_or_try_init(|| {
|
||||||
|
let cli_options = self.cli_options()?;
|
||||||
|
Ok(Arc::new(NpmInstaller::new(
|
||||||
|
self.npm_cache()?.clone(),
|
||||||
|
Arc::new(NpmInstallDepsProvider::from_workspace(
|
||||||
|
cli_options.workspace(),
|
||||||
|
)),
|
||||||
|
self.npm_resolution().clone(),
|
||||||
|
self.npm_resolution_initializer()?.clone(),
|
||||||
|
self.npm_resolution_installer()?.clone(),
|
||||||
|
self.text_only_progress_bar(),
|
||||||
|
self.sys(),
|
||||||
|
self.npm_tarball_cache()?.clone(),
|
||||||
|
cli_options.maybe_lockfile().cloned(),
|
||||||
|
cli_options.node_modules_dir_path().cloned(),
|
||||||
|
cli_options.lifecycle_scripts_config(),
|
||||||
|
cli_options.npm_system_info(),
|
||||||
|
)))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn npm_registry_info_provider(
|
||||||
|
&self,
|
||||||
|
) -> Result<&Arc<CliNpmRegistryInfoProvider>, AnyError> {
|
||||||
|
self
|
||||||
|
.services
|
||||||
|
.npm_registry_info_provider
|
||||||
|
.get_or_try_init(|| {
|
||||||
|
let cli_options = self.cli_options()?;
|
||||||
|
Ok(Arc::new(CliNpmRegistryInfoProvider::new(
|
||||||
|
self.npm_cache()?.clone(),
|
||||||
|
self.npm_cache_http_client().clone(),
|
||||||
|
cli_options.npmrc().clone(),
|
||||||
|
)))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn npm_resolution(&self) -> &Arc<NpmResolutionCell> {
|
||||||
|
&self.services.npm_resolution
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn npm_resolution_initializer(
|
||||||
|
&self,
|
||||||
|
) -> Result<&Arc<NpmResolutionInitializer>, AnyError> {
|
||||||
|
self
|
||||||
|
.services
|
||||||
|
.npm_resolution_initializer
|
||||||
|
.get_or_try_init(|| {
|
||||||
|
let cli_options = self.cli_options()?;
|
||||||
|
Ok(Arc::new(NpmResolutionInitializer::new(
|
||||||
|
self.npm_registry_info_provider()?.clone(),
|
||||||
|
self.npm_resolution().clone(),
|
||||||
|
match cli_options.resolve_npm_resolution_snapshot()? {
|
||||||
|
Some(snapshot) => {
|
||||||
|
CliNpmResolverManagedSnapshotOption::Specified(Some(snapshot))
|
||||||
|
}
|
||||||
|
None => match cli_options.maybe_lockfile() {
|
||||||
|
Some(lockfile) => {
|
||||||
|
CliNpmResolverManagedSnapshotOption::ResolveFromLockfile(
|
||||||
|
lockfile.clone(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
None => CliNpmResolverManagedSnapshotOption::Specified(None),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn npm_resolution_installer(
|
||||||
|
&self,
|
||||||
|
) -> Result<&Arc<NpmResolutionInstaller>, AnyError> {
|
||||||
|
self.services.npm_resolution_installer.get_or_try_init(|| {
|
||||||
|
let cli_options = self.cli_options()?;
|
||||||
|
Ok(Arc::new(NpmResolutionInstaller::new(
|
||||||
|
self.npm_registry_info_provider()?.clone(),
|
||||||
|
self.npm_resolution().clone(),
|
||||||
|
cli_options.maybe_lockfile().cloned(),
|
||||||
|
)))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn npm_resolver(&self) -> Result<&CliNpmResolver, AnyError> {
|
||||||
self
|
self
|
||||||
.services
|
.services
|
||||||
.npm_resolver
|
.npm_resolver
|
||||||
.get_or_try_init_async(
|
.get_or_try_init_async(
|
||||||
async {
|
async {
|
||||||
let fs = self.fs();
|
|
||||||
let cli_options = self.cli_options()?;
|
let cli_options = self.cli_options()?;
|
||||||
create_cli_npm_resolver(if cli_options.use_byonm() {
|
Ok(CliNpmResolver::new(if cli_options.use_byonm() {
|
||||||
CliNpmResolverCreateOptions::Byonm(
|
CliNpmResolverCreateOptions::Byonm(
|
||||||
CliByonmNpmResolverCreateOptions {
|
CliByonmNpmResolverCreateOptions {
|
||||||
fs: CliDenoResolverFs(fs.clone()),
|
sys: self.sys(),
|
||||||
pkg_json_resolver: self.pkg_json_resolver().clone(),
|
pkg_json_resolver: self.pkg_json_resolver().clone(),
|
||||||
root_node_modules_dir: Some(
|
root_node_modules_dir: Some(
|
||||||
match cli_options.node_modules_dir_path() {
|
match cli_options.node_modules_dir_path() {
|
||||||
|
@ -431,52 +584,43 @@ impl CliFactory {
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
self
|
||||||
|
.npm_resolution_initializer()?
|
||||||
|
.ensure_initialized()
|
||||||
|
.await?;
|
||||||
CliNpmResolverCreateOptions::Managed(
|
CliNpmResolverCreateOptions::Managed(
|
||||||
CliManagedNpmResolverCreateOptions {
|
CliManagedNpmResolverCreateOptions {
|
||||||
snapshot: match cli_options.resolve_npm_resolution_snapshot()? {
|
sys: self.sys(),
|
||||||
Some(snapshot) => {
|
npm_resolution: self.npm_resolution().clone(),
|
||||||
CliNpmResolverManagedSnapshotOption::Specified(Some(
|
|
||||||
snapshot,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
None => match cli_options.maybe_lockfile() {
|
|
||||||
Some(lockfile) => {
|
|
||||||
CliNpmResolverManagedSnapshotOption::ResolveFromLockfile(
|
|
||||||
lockfile.clone(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
CliNpmResolverManagedSnapshotOption::Specified(None)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
maybe_lockfile: cli_options.maybe_lockfile().cloned(),
|
|
||||||
fs: fs.clone(),
|
|
||||||
http_client_provider: self.http_client_provider().clone(),
|
|
||||||
npm_cache_dir: self.npm_cache_dir()?.clone(),
|
npm_cache_dir: self.npm_cache_dir()?.clone(),
|
||||||
cache_setting: cli_options.cache_setting(),
|
|
||||||
text_only_progress_bar: self.text_only_progress_bar().clone(),
|
|
||||||
maybe_node_modules_path: cli_options
|
maybe_node_modules_path: cli_options
|
||||||
.node_modules_dir_path()
|
.node_modules_dir_path()
|
||||||
.cloned(),
|
.cloned(),
|
||||||
npm_install_deps_provider: Arc::new(
|
|
||||||
NpmInstallDepsProvider::from_workspace(
|
|
||||||
cli_options.workspace(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
npm_system_info: cli_options.npm_system_info(),
|
npm_system_info: cli_options.npm_system_info(),
|
||||||
npmrc: cli_options.npmrc().clone(),
|
npmrc: cli_options.npmrc().clone(),
|
||||||
lifecycle_scripts: cli_options.lifecycle_scripts_config(),
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
})
|
}))
|
||||||
.await
|
|
||||||
}
|
}
|
||||||
.boxed_local(),
|
.boxed_local(),
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn npm_tarball_cache(
|
||||||
|
&self,
|
||||||
|
) -> Result<&Arc<CliNpmTarballCache>, AnyError> {
|
||||||
|
self.services.npm_tarball_cache.get_or_try_init(|| {
|
||||||
|
let cli_options = self.cli_options()?;
|
||||||
|
Ok(Arc::new(CliNpmTarballCache::new(
|
||||||
|
self.npm_cache()?.clone(),
|
||||||
|
self.npm_cache_http_client().clone(),
|
||||||
|
self.sys(),
|
||||||
|
cli_options.npmrc().clone(),
|
||||||
|
)))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
pub fn sloppy_imports_resolver(
|
pub fn sloppy_imports_resolver(
|
||||||
&self,
|
&self,
|
||||||
) -> Result<Option<&Arc<CliSloppyImportsResolver>>, AnyError> {
|
) -> Result<Option<&Arc<CliSloppyImportsResolver>>, AnyError> {
|
||||||
|
@ -486,7 +630,7 @@ impl CliFactory {
|
||||||
.get_or_try_init(|| {
|
.get_or_try_init(|| {
|
||||||
Ok(self.cli_options()?.unstable_sloppy_imports().then(|| {
|
Ok(self.cli_options()?.unstable_sloppy_imports().then(|| {
|
||||||
Arc::new(CliSloppyImportsResolver::new(SloppyImportsCachedFs::new(
|
Arc::new(CliSloppyImportsResolver::new(SloppyImportsCachedFs::new(
|
||||||
self.fs().clone(),
|
self.sys(),
|
||||||
)))
|
)))
|
||||||
}))
|
}))
|
||||||
})
|
})
|
||||||
|
@ -564,17 +708,10 @@ impl CliFactory {
|
||||||
.resolver
|
.resolver
|
||||||
.get_or_try_init_async(
|
.get_or_try_init_async(
|
||||||
async {
|
async {
|
||||||
let cli_options = self.cli_options()?;
|
Ok(Arc::new(CliResolver::new(
|
||||||
Ok(Arc::new(CliResolver::new(CliResolverOptions {
|
self.deno_resolver().await?.clone(),
|
||||||
npm_resolver: if cli_options.no_npm() {
|
self.services.found_pkg_json_dep_flag.clone(),
|
||||||
None
|
)))
|
||||||
} else {
|
|
||||||
Some(self.npm_resolver().await?.clone())
|
|
||||||
},
|
|
||||||
bare_node_builtins_enabled: cli_options
|
|
||||||
.unstable_bare_node_builtins(),
|
|
||||||
deno_resolver: self.deno_resolver().await?.clone(),
|
|
||||||
})))
|
|
||||||
}
|
}
|
||||||
.boxed_local(),
|
.boxed_local(),
|
||||||
)
|
)
|
||||||
|
@ -647,21 +784,19 @@ impl CliFactory {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn node_resolver(&self) -> Result<&Arc<NodeResolver>, AnyError> {
|
pub async fn node_resolver(&self) -> Result<&Arc<CliNodeResolver>, AnyError> {
|
||||||
self
|
self
|
||||||
.services
|
.services
|
||||||
.node_resolver
|
.node_resolver
|
||||||
.get_or_try_init_async(
|
.get_or_try_init_async(
|
||||||
async {
|
async {
|
||||||
Ok(Arc::new(NodeResolver::new(
|
Ok(Arc::new(CliNodeResolver::new(
|
||||||
DenoFsNodeResolverEnv::new(self.fs().clone()),
|
|
||||||
self.in_npm_pkg_checker()?.clone(),
|
self.in_npm_pkg_checker()?.clone(),
|
||||||
self
|
RealIsBuiltInNodeModuleChecker,
|
||||||
.npm_resolver()
|
self.npm_resolver().await?.clone(),
|
||||||
.await?
|
|
||||||
.clone()
|
|
||||||
.into_npm_pkg_folder_resolver(),
|
|
||||||
self.pkg_json_resolver().clone(),
|
self.pkg_json_resolver().clone(),
|
||||||
|
self.sys(),
|
||||||
|
node_resolver::ConditionsFromResolutionMode::default(),
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
.boxed_local(),
|
.boxed_local(),
|
||||||
|
@ -689,15 +824,11 @@ impl CliFactory {
|
||||||
|
|
||||||
Ok(Arc::new(NodeCodeTranslator::new(
|
Ok(Arc::new(NodeCodeTranslator::new(
|
||||||
cjs_esm_analyzer,
|
cjs_esm_analyzer,
|
||||||
DenoFsNodeResolverEnv::new(self.fs().clone()),
|
|
||||||
self.in_npm_pkg_checker()?.clone(),
|
self.in_npm_pkg_checker()?.clone(),
|
||||||
node_resolver,
|
node_resolver,
|
||||||
self
|
self.npm_resolver().await?.clone(),
|
||||||
.npm_resolver()
|
|
||||||
.await?
|
|
||||||
.clone()
|
|
||||||
.into_npm_pkg_folder_resolver(),
|
|
||||||
self.pkg_json_resolver().clone(),
|
self.pkg_json_resolver().clone(),
|
||||||
|
self.sys(),
|
||||||
)))
|
)))
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
|
@ -712,22 +843,20 @@ impl CliFactory {
|
||||||
.get_or_try_init_async(async {
|
.get_or_try_init_async(async {
|
||||||
let npm_resolver = self.npm_resolver().await?;
|
let npm_resolver = self.npm_resolver().await?;
|
||||||
Ok(Arc::new(CliNpmReqResolver::new(NpmReqResolverOptions {
|
Ok(Arc::new(CliNpmReqResolver::new(NpmReqResolverOptions {
|
||||||
byonm_resolver: (npm_resolver.clone()).into_maybe_byonm(),
|
sys: self.sys(),
|
||||||
fs: CliDenoResolverFs(self.fs().clone()),
|
|
||||||
in_npm_pkg_checker: self.in_npm_pkg_checker()?.clone(),
|
in_npm_pkg_checker: self.in_npm_pkg_checker()?.clone(),
|
||||||
node_resolver: self.node_resolver().await?.clone(),
|
node_resolver: self.node_resolver().await?.clone(),
|
||||||
npm_req_resolver: npm_resolver.clone().into_npm_req_resolver(),
|
npm_resolver: npm_resolver.clone(),
|
||||||
})))
|
})))
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pkg_json_resolver(&self) -> &Arc<PackageJsonResolver> {
|
pub fn pkg_json_resolver(&self) -> &Arc<CliPackageJsonResolver> {
|
||||||
self.services.pkg_json_resolver.get_or_init(|| {
|
self
|
||||||
Arc::new(PackageJsonResolver::new(DenoFsNodeResolverEnv::new(
|
.services
|
||||||
self.fs().clone(),
|
.pkg_json_resolver
|
||||||
)))
|
.get_or_init(|| Arc::new(CliPackageJsonResolver::new(self.sys())))
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn type_checker(&self) -> Result<&Arc<TypeChecker>, AnyError> {
|
pub async fn type_checker(&self) -> Result<&Arc<TypeChecker>, AnyError> {
|
||||||
|
@ -745,7 +874,9 @@ impl CliFactory {
|
||||||
cli_options.clone(),
|
cli_options.clone(),
|
||||||
self.module_graph_builder().await?.clone(),
|
self.module_graph_builder().await?.clone(),
|
||||||
self.node_resolver().await?.clone(),
|
self.node_resolver().await?.clone(),
|
||||||
|
self.npm_installer_if_managed()?.cloned(),
|
||||||
self.npm_resolver().await?.clone(),
|
self.npm_resolver().await?.clone(),
|
||||||
|
self.sys(),
|
||||||
)))
|
)))
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
|
@ -764,16 +895,18 @@ impl CliFactory {
|
||||||
self.cjs_tracker()?.clone(),
|
self.cjs_tracker()?.clone(),
|
||||||
cli_options.clone(),
|
cli_options.clone(),
|
||||||
self.file_fetcher()?.clone(),
|
self.file_fetcher()?.clone(),
|
||||||
self.fs().clone(),
|
|
||||||
self.global_http_cache()?.clone(),
|
self.global_http_cache()?.clone(),
|
||||||
self.in_npm_pkg_checker()?.clone(),
|
self.in_npm_pkg_checker()?.clone(),
|
||||||
cli_options.maybe_lockfile().cloned(),
|
cli_options.maybe_lockfile().cloned(),
|
||||||
self.maybe_file_watcher_reporter().clone(),
|
self.maybe_file_watcher_reporter().clone(),
|
||||||
self.module_info_cache()?.clone(),
|
self.module_info_cache()?.clone(),
|
||||||
|
self.npm_graph_resolver()?.clone(),
|
||||||
|
self.npm_installer_if_managed()?.cloned(),
|
||||||
self.npm_resolver().await?.clone(),
|
self.npm_resolver().await?.clone(),
|
||||||
self.parsed_source_cache().clone(),
|
self.parsed_source_cache().clone(),
|
||||||
self.resolver().await?.clone(),
|
self.resolver().await?.clone(),
|
||||||
self.root_permissions_container()?.clone(),
|
self.root_permissions_container()?.clone(),
|
||||||
|
self.sys(),
|
||||||
)))
|
)))
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
|
@ -789,7 +922,7 @@ impl CliFactory {
|
||||||
let cli_options = self.cli_options()?;
|
let cli_options = self.cli_options()?;
|
||||||
Ok(Arc::new(ModuleGraphCreator::new(
|
Ok(Arc::new(ModuleGraphCreator::new(
|
||||||
cli_options.clone(),
|
cli_options.clone(),
|
||||||
self.npm_resolver().await?.clone(),
|
self.npm_installer_if_managed()?.cloned(),
|
||||||
self.module_graph_builder().await?.clone(),
|
self.module_graph_builder().await?.clone(),
|
||||||
self.type_checker().await?.clone(),
|
self.type_checker().await?.clone(),
|
||||||
)))
|
)))
|
||||||
|
@ -844,10 +977,10 @@ impl CliFactory {
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cjs_tracker(&self) -> Result<&Arc<CjsTracker>, AnyError> {
|
pub fn cjs_tracker(&self) -> Result<&Arc<CliCjsTracker>, AnyError> {
|
||||||
self.services.cjs_tracker.get_or_try_init(|| {
|
self.services.cjs_tracker.get_or_try_init(|| {
|
||||||
let options = self.cli_options()?;
|
let options = self.cli_options()?;
|
||||||
Ok(Arc::new(CjsTracker::new(
|
Ok(Arc::new(CliCjsTracker::new(
|
||||||
self.in_npm_pkg_checker()?.clone(),
|
self.in_npm_pkg_checker()?.clone(),
|
||||||
self.pkg_json_resolver().clone(),
|
self.pkg_json_resolver().clone(),
|
||||||
if options.is_node_main() || options.unstable_detect_cjs() {
|
if options.is_node_main() || options.unstable_detect_cjs() {
|
||||||
|
@ -863,10 +996,9 @@ impl CliFactory {
|
||||||
|
|
||||||
pub fn permission_desc_parser(
|
pub fn permission_desc_parser(
|
||||||
&self,
|
&self,
|
||||||
) -> Result<&Arc<RuntimePermissionDescriptorParser>, AnyError> {
|
) -> Result<&Arc<RuntimePermissionDescriptorParser<CliSys>>, AnyError> {
|
||||||
self.services.permission_desc_parser.get_or_try_init(|| {
|
self.services.permission_desc_parser.get_or_try_init(|| {
|
||||||
let fs = self.fs().clone();
|
Ok(Arc::new(RuntimePermissionDescriptorParser::new(self.sys())))
|
||||||
Ok(Arc::new(RuntimePermissionDescriptorParser::new(fs)))
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -897,7 +1029,7 @@ impl CliFactory {
|
||||||
self.emitter()?,
|
self.emitter()?,
|
||||||
self.file_fetcher()?,
|
self.file_fetcher()?,
|
||||||
self.http_client_provider(),
|
self.http_client_provider(),
|
||||||
self.npm_resolver().await?.as_ref(),
|
self.npm_resolver().await?,
|
||||||
self.workspace_resolver().await?.as_ref(),
|
self.workspace_resolver().await?.as_ref(),
|
||||||
cli_options.npm_system_info(),
|
cli_options.npm_system_info(),
|
||||||
))
|
))
|
||||||
|
@ -937,6 +1069,19 @@ impl CliFactory {
|
||||||
let cjs_tracker = self.cjs_tracker()?.clone();
|
let cjs_tracker = self.cjs_tracker()?.clone();
|
||||||
let pkg_json_resolver = self.pkg_json_resolver().clone();
|
let pkg_json_resolver = self.pkg_json_resolver().clone();
|
||||||
let npm_req_resolver = self.npm_req_resolver().await?;
|
let npm_req_resolver = self.npm_req_resolver().await?;
|
||||||
|
let npm_registry_permission_checker = {
|
||||||
|
let mode = if cli_options.use_byonm() {
|
||||||
|
NpmRegistryReadPermissionCheckerMode::Byonm
|
||||||
|
} else if let Some(node_modules_dir) = cli_options.node_modules_dir_path()
|
||||||
|
{
|
||||||
|
NpmRegistryReadPermissionCheckerMode::Local(node_modules_dir.clone())
|
||||||
|
} else {
|
||||||
|
NpmRegistryReadPermissionCheckerMode::Global(
|
||||||
|
self.npm_cache_dir()?.root_dir().to_path_buf(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
Arc::new(NpmRegistryReadPermissionChecker::new(self.sys(), mode))
|
||||||
|
};
|
||||||
|
|
||||||
Ok(CliMainWorkerFactory::new(
|
Ok(CliMainWorkerFactory::new(
|
||||||
self.blob_store().clone(),
|
self.blob_store().clone(),
|
||||||
|
@ -959,28 +1104,31 @@ impl CliFactory {
|
||||||
None
|
None
|
||||||
},
|
},
|
||||||
self.emitter()?.clone(),
|
self.emitter()?.clone(),
|
||||||
fs.clone(),
|
|
||||||
in_npm_pkg_checker.clone(),
|
in_npm_pkg_checker.clone(),
|
||||||
self.main_module_graph_container().await?.clone(),
|
self.main_module_graph_container().await?.clone(),
|
||||||
self.module_load_preparer().await?.clone(),
|
self.module_load_preparer().await?.clone(),
|
||||||
node_code_translator.clone(),
|
node_code_translator.clone(),
|
||||||
node_resolver.clone(),
|
node_resolver.clone(),
|
||||||
npm_req_resolver.clone(),
|
|
||||||
cli_npm_resolver.clone(),
|
|
||||||
NpmModuleLoader::new(
|
NpmModuleLoader::new(
|
||||||
self.cjs_tracker()?.clone(),
|
self.cjs_tracker()?.clone(),
|
||||||
fs.clone(),
|
fs.clone(),
|
||||||
node_code_translator.clone(),
|
node_code_translator.clone(),
|
||||||
),
|
),
|
||||||
|
npm_registry_permission_checker,
|
||||||
|
npm_req_resolver.clone(),
|
||||||
|
cli_npm_resolver.clone(),
|
||||||
self.parsed_source_cache().clone(),
|
self.parsed_source_cache().clone(),
|
||||||
self.resolver().await?.clone(),
|
self.resolver().await?.clone(),
|
||||||
|
self.sys(),
|
||||||
)),
|
)),
|
||||||
node_resolver.clone(),
|
node_resolver.clone(),
|
||||||
|
self.npm_installer_if_managed()?.cloned(),
|
||||||
npm_resolver.clone(),
|
npm_resolver.clone(),
|
||||||
pkg_json_resolver,
|
pkg_json_resolver,
|
||||||
self.root_cert_store_provider().clone(),
|
self.root_cert_store_provider().clone(),
|
||||||
self.root_permissions_container()?.clone(),
|
self.root_permissions_container()?.clone(),
|
||||||
StorageKeyResolver::from_options(cli_options),
|
StorageKeyResolver::from_options(cli_options),
|
||||||
|
self.sys(),
|
||||||
cli_options.sub_command().clone(),
|
cli_options.sub_command().clone(),
|
||||||
self.create_cli_main_worker_options()?,
|
self.create_cli_main_worker_options()?,
|
||||||
self.cli_options()?.otel_config(),
|
self.cli_options()?.otel_config(),
|
||||||
|
|
1416
cli/file_fetcher.rs
1416
cli/file_fetcher.rs
File diff suppressed because it is too large
Load diff
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,43 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
|
use std::collections::HashSet;
|
||||||
|
use std::error::Error;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use deno_config::deno_json;
|
||||||
|
use deno_config::deno_json::JsxImportSourceConfig;
|
||||||
|
use deno_config::deno_json::NodeModulesDirMode;
|
||||||
|
use deno_config::workspace::JsrPackageConfig;
|
||||||
|
use deno_core::error::AnyError;
|
||||||
|
use deno_core::parking_lot::Mutex;
|
||||||
|
use deno_core::serde_json;
|
||||||
|
use deno_core::ModuleSpecifier;
|
||||||
|
use deno_error::JsErrorBox;
|
||||||
|
use deno_error::JsErrorClass;
|
||||||
|
use deno_graph::source::Loader;
|
||||||
|
use deno_graph::source::LoaderChecksum;
|
||||||
|
use deno_graph::source::ResolutionKind;
|
||||||
|
use deno_graph::source::ResolveError;
|
||||||
|
use deno_graph::FillFromLockfileOptions;
|
||||||
|
use deno_graph::GraphKind;
|
||||||
|
use deno_graph::JsrLoadError;
|
||||||
|
use deno_graph::ModuleError;
|
||||||
|
use deno_graph::ModuleGraph;
|
||||||
|
use deno_graph::ModuleGraphError;
|
||||||
|
use deno_graph::ModuleLoadError;
|
||||||
|
use deno_graph::ResolutionError;
|
||||||
|
use deno_graph::SpecifierError;
|
||||||
|
use deno_graph::WorkspaceFastCheckOption;
|
||||||
|
use deno_path_util::url_to_file_path;
|
||||||
|
use deno_resolver::npm::DenoInNpmPackageChecker;
|
||||||
|
use deno_resolver::sloppy_imports::SloppyImportsCachedFs;
|
||||||
|
use deno_resolver::sloppy_imports::SloppyImportsResolutionKind;
|
||||||
|
use deno_runtime::deno_node;
|
||||||
|
use deno_runtime::deno_permissions::PermissionsContainer;
|
||||||
|
use deno_semver::jsr::JsrDepPackageReq;
|
||||||
|
use deno_semver::package::PackageNv;
|
||||||
|
use deno_semver::SmallStackString;
|
||||||
|
|
||||||
use crate::args::config_to_deno_graph_workspace_member;
|
use crate::args::config_to_deno_graph_workspace_member;
|
||||||
use crate::args::jsr_url;
|
use crate::args::jsr_url;
|
||||||
|
@ -12,53 +51,20 @@ use crate::cache::GlobalHttpCache;
|
||||||
use crate::cache::ModuleInfoCache;
|
use crate::cache::ModuleInfoCache;
|
||||||
use crate::cache::ParsedSourceCache;
|
use crate::cache::ParsedSourceCache;
|
||||||
use crate::colors;
|
use crate::colors;
|
||||||
use crate::errors::get_error_class_name;
|
use crate::file_fetcher::CliFileFetcher;
|
||||||
use crate::file_fetcher::FileFetcher;
|
use crate::npm::installer::NpmInstaller;
|
||||||
|
use crate::npm::installer::PackageCaching;
|
||||||
use crate::npm::CliNpmResolver;
|
use crate::npm::CliNpmResolver;
|
||||||
use crate::resolver::CjsTracker;
|
use crate::resolver::CliCjsTracker;
|
||||||
|
use crate::resolver::CliNpmGraphResolver;
|
||||||
use crate::resolver::CliResolver;
|
use crate::resolver::CliResolver;
|
||||||
use crate::resolver::CliSloppyImportsResolver;
|
use crate::resolver::CliSloppyImportsResolver;
|
||||||
use crate::resolver::SloppyImportsCachedFs;
|
use crate::sys::CliSys;
|
||||||
use crate::tools::check;
|
use crate::tools::check;
|
||||||
|
use crate::tools::check::CheckError;
|
||||||
use crate::tools::check::TypeChecker;
|
use crate::tools::check::TypeChecker;
|
||||||
use crate::util::file_watcher::WatcherCommunicator;
|
use crate::util::file_watcher::WatcherCommunicator;
|
||||||
use crate::util::fs::canonicalize_path;
|
use crate::util::fs::canonicalize_path;
|
||||||
use deno_config::deno_json::JsxImportSourceConfig;
|
|
||||||
use deno_config::workspace::JsrPackageConfig;
|
|
||||||
use deno_core::anyhow::bail;
|
|
||||||
use deno_graph::source::LoaderChecksum;
|
|
||||||
use deno_graph::source::ResolutionKind;
|
|
||||||
use deno_graph::FillFromLockfileOptions;
|
|
||||||
use deno_graph::JsrLoadError;
|
|
||||||
use deno_graph::ModuleLoadError;
|
|
||||||
use deno_graph::WorkspaceFastCheckOption;
|
|
||||||
|
|
||||||
use deno_core::error::custom_error;
|
|
||||||
use deno_core::error::AnyError;
|
|
||||||
use deno_core::parking_lot::Mutex;
|
|
||||||
use deno_core::ModuleSpecifier;
|
|
||||||
use deno_graph::source::Loader;
|
|
||||||
use deno_graph::source::ResolveError;
|
|
||||||
use deno_graph::GraphKind;
|
|
||||||
use deno_graph::ModuleError;
|
|
||||||
use deno_graph::ModuleGraph;
|
|
||||||
use deno_graph::ModuleGraphError;
|
|
||||||
use deno_graph::ResolutionError;
|
|
||||||
use deno_graph::SpecifierError;
|
|
||||||
use deno_path_util::url_to_file_path;
|
|
||||||
use deno_resolver::sloppy_imports::SloppyImportsResolutionKind;
|
|
||||||
use deno_runtime::deno_fs::FileSystem;
|
|
||||||
use deno_runtime::deno_node;
|
|
||||||
use deno_runtime::deno_permissions::PermissionsContainer;
|
|
||||||
use deno_semver::jsr::JsrDepPackageReq;
|
|
||||||
use deno_semver::package::PackageNv;
|
|
||||||
use import_map::ImportMapError;
|
|
||||||
use node_resolver::InNpmPackageChecker;
|
|
||||||
use std::collections::HashSet;
|
|
||||||
use std::error::Error;
|
|
||||||
use std::ops::Deref;
|
|
||||||
use std::path::PathBuf;
|
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct GraphValidOptions {
|
pub struct GraphValidOptions {
|
||||||
|
@ -79,17 +85,17 @@ pub struct GraphValidOptions {
|
||||||
/// for the CLI.
|
/// for the CLI.
|
||||||
pub fn graph_valid(
|
pub fn graph_valid(
|
||||||
graph: &ModuleGraph,
|
graph: &ModuleGraph,
|
||||||
fs: &Arc<dyn FileSystem>,
|
sys: &CliSys,
|
||||||
roots: &[ModuleSpecifier],
|
roots: &[ModuleSpecifier],
|
||||||
options: GraphValidOptions,
|
options: GraphValidOptions,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), JsErrorBox> {
|
||||||
if options.exit_integrity_errors {
|
if options.exit_integrity_errors {
|
||||||
graph_exit_integrity_errors(graph);
|
graph_exit_integrity_errors(graph);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut errors = graph_walk_errors(
|
let mut errors = graph_walk_errors(
|
||||||
graph,
|
graph,
|
||||||
fs,
|
sys,
|
||||||
roots,
|
roots,
|
||||||
GraphWalkErrorsOptions {
|
GraphWalkErrorsOptions {
|
||||||
check_js: options.check_js,
|
check_js: options.check_js,
|
||||||
|
@ -101,9 +107,9 @@ pub fn graph_valid(
|
||||||
} else {
|
} else {
|
||||||
// finally surface the npm resolution result
|
// finally surface the npm resolution result
|
||||||
if let Err(err) = &graph.npm_dep_graph_result {
|
if let Err(err) = &graph.npm_dep_graph_result {
|
||||||
return Err(custom_error(
|
return Err(JsErrorBox::new(
|
||||||
get_error_class_name(err),
|
err.get_class(),
|
||||||
format_deno_graph_error(err.as_ref().deref()),
|
format_deno_graph_error(err),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -139,10 +145,10 @@ pub struct GraphWalkErrorsOptions {
|
||||||
/// and enhances them with CLI information.
|
/// and enhances them with CLI information.
|
||||||
pub fn graph_walk_errors<'a>(
|
pub fn graph_walk_errors<'a>(
|
||||||
graph: &'a ModuleGraph,
|
graph: &'a ModuleGraph,
|
||||||
fs: &'a Arc<dyn FileSystem>,
|
sys: &'a CliSys,
|
||||||
roots: &'a [ModuleSpecifier],
|
roots: &'a [ModuleSpecifier],
|
||||||
options: GraphWalkErrorsOptions,
|
options: GraphWalkErrorsOptions,
|
||||||
) -> impl Iterator<Item = AnyError> + 'a {
|
) -> impl Iterator<Item = JsErrorBox> + 'a {
|
||||||
graph
|
graph
|
||||||
.walk(
|
.walk(
|
||||||
roots.iter(),
|
roots.iter(),
|
||||||
|
@ -162,6 +168,53 @@ pub fn graph_walk_errors<'a>(
|
||||||
roots.contains(error.specifier())
|
roots.contains(error.specifier())
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
let message = enhance_graph_error(
|
||||||
|
sys,
|
||||||
|
&error,
|
||||||
|
if is_root {
|
||||||
|
EnhanceGraphErrorMode::HideRange
|
||||||
|
} else {
|
||||||
|
EnhanceGraphErrorMode::ShowRange
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
if graph.graph_kind() == GraphKind::TypesOnly
|
||||||
|
&& matches!(
|
||||||
|
error,
|
||||||
|
ModuleGraphError::ModuleError(ModuleError::UnsupportedMediaType(..))
|
||||||
|
)
|
||||||
|
{
|
||||||
|
log::debug!("Ignoring: {}", message);
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
if graph.graph_kind().include_types()
|
||||||
|
&& (message.contains(RUN_WITH_SLOPPY_IMPORTS_MSG)
|
||||||
|
|| matches!(
|
||||||
|
error,
|
||||||
|
ModuleGraphError::ModuleError(ModuleError::Missing(..))
|
||||||
|
))
|
||||||
|
{
|
||||||
|
// ignore and let typescript surface this as a diagnostic instead
|
||||||
|
log::debug!("Ignoring: {}", message);
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(JsErrorBox::new(error.get_class(), message))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
|
pub enum EnhanceGraphErrorMode {
|
||||||
|
ShowRange,
|
||||||
|
HideRange,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn enhance_graph_error(
|
||||||
|
sys: &CliSys,
|
||||||
|
error: &ModuleGraphError,
|
||||||
|
mode: EnhanceGraphErrorMode,
|
||||||
|
) -> String {
|
||||||
let mut message = match &error {
|
let mut message = match &error {
|
||||||
ModuleGraphError::ResolutionError(resolution_error) => {
|
ModuleGraphError::ResolutionError(resolution_error) => {
|
||||||
enhanced_resolution_error_message(resolution_error)
|
enhanced_resolution_error_message(resolution_error)
|
||||||
|
@ -174,30 +227,20 @@ pub fn graph_walk_errors<'a>(
|
||||||
}
|
}
|
||||||
ModuleGraphError::ModuleError(error) => {
|
ModuleGraphError::ModuleError(error) => {
|
||||||
enhanced_integrity_error_message(error)
|
enhanced_integrity_error_message(error)
|
||||||
.or_else(|| enhanced_sloppy_imports_error_message(fs, error))
|
.or_else(|| enhanced_sloppy_imports_error_message(sys, error))
|
||||||
.unwrap_or_else(|| format_deno_graph_error(error))
|
.unwrap_or_else(|| format_deno_graph_error(error))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(range) = error.maybe_range() {
|
if let Some(range) = error.maybe_range() {
|
||||||
if !is_root && !range.specifier.as_str().contains("/$deno$eval") {
|
if mode == EnhanceGraphErrorMode::ShowRange
|
||||||
|
&& !range.specifier.as_str().contains("/$deno$eval")
|
||||||
|
{
|
||||||
message.push_str("\n at ");
|
message.push_str("\n at ");
|
||||||
message.push_str(&format_range_with_colors(range));
|
message.push_str(&format_range_with_colors(range));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
message
|
||||||
if graph.graph_kind() == GraphKind::TypesOnly
|
|
||||||
&& matches!(
|
|
||||||
error,
|
|
||||||
ModuleGraphError::ModuleError(ModuleError::UnsupportedMediaType(..))
|
|
||||||
)
|
|
||||||
{
|
|
||||||
log::debug!("Ignoring: {}", message);
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
Some(custom_error(get_error_class_name(&error.into()), message))
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn graph_exit_integrity_errors(graph: &ModuleGraph) {
|
pub fn graph_exit_integrity_errors(graph: &ModuleGraph) {
|
||||||
|
@ -224,7 +267,7 @@ pub struct CreateGraphOptions<'a> {
|
||||||
|
|
||||||
pub struct ModuleGraphCreator {
|
pub struct ModuleGraphCreator {
|
||||||
options: Arc<CliOptions>,
|
options: Arc<CliOptions>,
|
||||||
npm_resolver: Arc<dyn CliNpmResolver>,
|
npm_installer: Option<Arc<NpmInstaller>>,
|
||||||
module_graph_builder: Arc<ModuleGraphBuilder>,
|
module_graph_builder: Arc<ModuleGraphBuilder>,
|
||||||
type_checker: Arc<TypeChecker>,
|
type_checker: Arc<TypeChecker>,
|
||||||
}
|
}
|
||||||
|
@ -232,13 +275,13 @@ pub struct ModuleGraphCreator {
|
||||||
impl ModuleGraphCreator {
|
impl ModuleGraphCreator {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
options: Arc<CliOptions>,
|
options: Arc<CliOptions>,
|
||||||
npm_resolver: Arc<dyn CliNpmResolver>,
|
npm_installer: Option<Arc<NpmInstaller>>,
|
||||||
module_graph_builder: Arc<ModuleGraphBuilder>,
|
module_graph_builder: Arc<ModuleGraphBuilder>,
|
||||||
type_checker: Arc<TypeChecker>,
|
type_checker: Arc<TypeChecker>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
options,
|
options,
|
||||||
npm_resolver,
|
npm_installer,
|
||||||
module_graph_builder,
|
module_graph_builder,
|
||||||
type_checker,
|
type_checker,
|
||||||
}
|
}
|
||||||
|
@ -361,9 +404,9 @@ impl ModuleGraphCreator {
|
||||||
.build_graph_with_npm_resolution(&mut graph, options)
|
.build_graph_with_npm_resolution(&mut graph, options)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
if let Some(npm_resolver) = self.npm_resolver.as_managed() {
|
if let Some(npm_installer) = &self.npm_installer {
|
||||||
if graph.has_node_specifier && self.options.type_check_mode().is_true() {
|
if graph.has_node_specifier && self.options.type_check_mode().is_true() {
|
||||||
npm_resolver.inject_synthetic_types_node_package().await?;
|
npm_installer.inject_synthetic_types_node_package().await?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -397,14 +440,14 @@ impl ModuleGraphCreator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn graph_valid(&self, graph: &ModuleGraph) -> Result<(), AnyError> {
|
pub fn graph_valid(&self, graph: &ModuleGraph) -> Result<(), JsErrorBox> {
|
||||||
self.module_graph_builder.graph_valid(graph)
|
self.module_graph_builder.graph_valid(graph)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn type_check_graph(
|
async fn type_check_graph(
|
||||||
&self,
|
&self,
|
||||||
graph: ModuleGraph,
|
graph: ModuleGraph,
|
||||||
) -> Result<Arc<ModuleGraph>, AnyError> {
|
) -> Result<Arc<ModuleGraph>, CheckError> {
|
||||||
self
|
self
|
||||||
.type_checker
|
.type_checker
|
||||||
.check(
|
.check(
|
||||||
|
@ -427,56 +470,83 @@ pub struct BuildFastCheckGraphOptions<'a> {
|
||||||
pub workspace_fast_check: deno_graph::WorkspaceFastCheckOption<'a>,
|
pub workspace_fast_check: deno_graph::WorkspaceFastCheckOption<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, thiserror::Error, deno_error::JsError)]
|
||||||
|
pub enum BuildGraphWithNpmResolutionError {
|
||||||
|
#[class(inherit)]
|
||||||
|
#[error(transparent)]
|
||||||
|
SerdeJson(#[from] serde_json::Error),
|
||||||
|
#[class(inherit)]
|
||||||
|
#[error(transparent)]
|
||||||
|
ToMaybeJsxImportSourceConfig(
|
||||||
|
#[from] deno_json::ToMaybeJsxImportSourceConfigError,
|
||||||
|
),
|
||||||
|
#[class(inherit)]
|
||||||
|
#[error(transparent)]
|
||||||
|
NodeModulesDirParse(#[from] deno_json::NodeModulesDirParseError),
|
||||||
|
#[class(inherit)]
|
||||||
|
#[error(transparent)]
|
||||||
|
Other(#[from] JsErrorBox),
|
||||||
|
#[class(generic)]
|
||||||
|
#[error("Resolving npm specifier entrypoints this way is currently not supported with \"nodeModules\": \"manual\". In the meantime, try with --node-modules-dir=auto instead")]
|
||||||
|
UnsupportedNpmSpecifierEntrypointResolutionWay,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct ModuleGraphBuilder {
|
pub struct ModuleGraphBuilder {
|
||||||
caches: Arc<cache::Caches>,
|
caches: Arc<cache::Caches>,
|
||||||
cjs_tracker: Arc<CjsTracker>,
|
cjs_tracker: Arc<CliCjsTracker>,
|
||||||
cli_options: Arc<CliOptions>,
|
cli_options: Arc<CliOptions>,
|
||||||
file_fetcher: Arc<FileFetcher>,
|
file_fetcher: Arc<CliFileFetcher>,
|
||||||
fs: Arc<dyn FileSystem>,
|
|
||||||
global_http_cache: Arc<GlobalHttpCache>,
|
global_http_cache: Arc<GlobalHttpCache>,
|
||||||
in_npm_pkg_checker: Arc<dyn InNpmPackageChecker>,
|
in_npm_pkg_checker: DenoInNpmPackageChecker,
|
||||||
lockfile: Option<Arc<CliLockfile>>,
|
lockfile: Option<Arc<CliLockfile>>,
|
||||||
maybe_file_watcher_reporter: Option<FileWatcherReporter>,
|
maybe_file_watcher_reporter: Option<FileWatcherReporter>,
|
||||||
module_info_cache: Arc<ModuleInfoCache>,
|
module_info_cache: Arc<ModuleInfoCache>,
|
||||||
npm_resolver: Arc<dyn CliNpmResolver>,
|
npm_graph_resolver: Arc<CliNpmGraphResolver>,
|
||||||
|
npm_installer: Option<Arc<NpmInstaller>>,
|
||||||
|
npm_resolver: CliNpmResolver,
|
||||||
parsed_source_cache: Arc<ParsedSourceCache>,
|
parsed_source_cache: Arc<ParsedSourceCache>,
|
||||||
resolver: Arc<CliResolver>,
|
resolver: Arc<CliResolver>,
|
||||||
root_permissions_container: PermissionsContainer,
|
root_permissions_container: PermissionsContainer,
|
||||||
|
sys: CliSys,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ModuleGraphBuilder {
|
impl ModuleGraphBuilder {
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn new(
|
pub fn new(
|
||||||
caches: Arc<cache::Caches>,
|
caches: Arc<cache::Caches>,
|
||||||
cjs_tracker: Arc<CjsTracker>,
|
cjs_tracker: Arc<CliCjsTracker>,
|
||||||
cli_options: Arc<CliOptions>,
|
cli_options: Arc<CliOptions>,
|
||||||
file_fetcher: Arc<FileFetcher>,
|
file_fetcher: Arc<CliFileFetcher>,
|
||||||
fs: Arc<dyn FileSystem>,
|
|
||||||
global_http_cache: Arc<GlobalHttpCache>,
|
global_http_cache: Arc<GlobalHttpCache>,
|
||||||
in_npm_pkg_checker: Arc<dyn InNpmPackageChecker>,
|
in_npm_pkg_checker: DenoInNpmPackageChecker,
|
||||||
lockfile: Option<Arc<CliLockfile>>,
|
lockfile: Option<Arc<CliLockfile>>,
|
||||||
maybe_file_watcher_reporter: Option<FileWatcherReporter>,
|
maybe_file_watcher_reporter: Option<FileWatcherReporter>,
|
||||||
module_info_cache: Arc<ModuleInfoCache>,
|
module_info_cache: Arc<ModuleInfoCache>,
|
||||||
npm_resolver: Arc<dyn CliNpmResolver>,
|
npm_graph_resolver: Arc<CliNpmGraphResolver>,
|
||||||
|
npm_installer: Option<Arc<NpmInstaller>>,
|
||||||
|
npm_resolver: CliNpmResolver,
|
||||||
parsed_source_cache: Arc<ParsedSourceCache>,
|
parsed_source_cache: Arc<ParsedSourceCache>,
|
||||||
resolver: Arc<CliResolver>,
|
resolver: Arc<CliResolver>,
|
||||||
root_permissions_container: PermissionsContainer,
|
root_permissions_container: PermissionsContainer,
|
||||||
|
sys: CliSys,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
caches,
|
caches,
|
||||||
cjs_tracker,
|
cjs_tracker,
|
||||||
cli_options,
|
cli_options,
|
||||||
file_fetcher,
|
file_fetcher,
|
||||||
fs,
|
|
||||||
global_http_cache,
|
global_http_cache,
|
||||||
in_npm_pkg_checker,
|
in_npm_pkg_checker,
|
||||||
lockfile,
|
lockfile,
|
||||||
maybe_file_watcher_reporter,
|
maybe_file_watcher_reporter,
|
||||||
module_info_cache,
|
module_info_cache,
|
||||||
|
npm_graph_resolver,
|
||||||
|
npm_installer,
|
||||||
npm_resolver,
|
npm_resolver,
|
||||||
parsed_source_cache,
|
parsed_source_cache,
|
||||||
resolver,
|
resolver,
|
||||||
root_permissions_container,
|
root_permissions_container,
|
||||||
|
sys,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -484,7 +554,7 @@ impl ModuleGraphBuilder {
|
||||||
&self,
|
&self,
|
||||||
graph: &mut ModuleGraph,
|
graph: &mut ModuleGraph,
|
||||||
options: CreateGraphOptions<'a>,
|
options: CreateGraphOptions<'a>,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), BuildGraphWithNpmResolutionError> {
|
||||||
enum MutLoaderRef<'a> {
|
enum MutLoaderRef<'a> {
|
||||||
Borrowed(&'a mut dyn Loader),
|
Borrowed(&'a mut dyn Loader),
|
||||||
Owned(cache::FetchCacher),
|
Owned(cache::FetchCacher),
|
||||||
|
@ -570,10 +640,7 @@ impl ModuleGraphBuilder {
|
||||||
Some(loader) => MutLoaderRef::Borrowed(loader),
|
Some(loader) => MutLoaderRef::Borrowed(loader),
|
||||||
None => MutLoaderRef::Owned(self.create_graph_loader()),
|
None => MutLoaderRef::Owned(self.create_graph_loader()),
|
||||||
};
|
};
|
||||||
let cli_resolver = &self.resolver;
|
|
||||||
let graph_resolver = self.create_graph_resolver()?;
|
let graph_resolver = self.create_graph_resolver()?;
|
||||||
let graph_npm_resolver =
|
|
||||||
cli_resolver.create_graph_npm_resolver(options.npm_caching);
|
|
||||||
let maybe_file_watcher_reporter = self
|
let maybe_file_watcher_reporter = self
|
||||||
.maybe_file_watcher_reporter
|
.maybe_file_watcher_reporter
|
||||||
.as_ref()
|
.as_ref()
|
||||||
|
@ -592,9 +659,9 @@ impl ModuleGraphBuilder {
|
||||||
is_dynamic: options.is_dynamic,
|
is_dynamic: options.is_dynamic,
|
||||||
passthrough_jsr_specifiers: false,
|
passthrough_jsr_specifiers: false,
|
||||||
executor: Default::default(),
|
executor: Default::default(),
|
||||||
file_system: &DenoGraphFsAdapter(self.fs.as_ref()),
|
file_system: &self.sys,
|
||||||
jsr_url_provider: &CliJsrUrlProvider,
|
jsr_url_provider: &CliJsrUrlProvider,
|
||||||
npm_resolver: Some(&graph_npm_resolver),
|
npm_resolver: Some(self.npm_graph_resolver.as_ref()),
|
||||||
module_analyzer: &analyzer,
|
module_analyzer: &analyzer,
|
||||||
reporter: maybe_file_watcher_reporter,
|
reporter: maybe_file_watcher_reporter,
|
||||||
resolver: Some(&graph_resolver),
|
resolver: Some(&graph_resolver),
|
||||||
|
@ -612,22 +679,21 @@ impl ModuleGraphBuilder {
|
||||||
loader: &'a mut dyn deno_graph::source::Loader,
|
loader: &'a mut dyn deno_graph::source::Loader,
|
||||||
options: deno_graph::BuildOptions<'a>,
|
options: deno_graph::BuildOptions<'a>,
|
||||||
npm_caching: NpmCachingStrategy,
|
npm_caching: NpmCachingStrategy,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), BuildGraphWithNpmResolutionError> {
|
||||||
// ensure an "npm install" is done if the user has explicitly
|
// ensure an "npm install" is done if the user has explicitly
|
||||||
// opted into using a node_modules directory
|
// opted into using a node_modules directory
|
||||||
if self
|
if self
|
||||||
.cli_options
|
.cli_options
|
||||||
.node_modules_dir()?
|
.node_modules_dir()?
|
||||||
.map(|m| m.uses_node_modules_dir())
|
.map(|m| m == NodeModulesDirMode::Auto)
|
||||||
.unwrap_or(false)
|
.unwrap_or(false)
|
||||||
{
|
{
|
||||||
if let Some(npm_resolver) = self.npm_resolver.as_managed() {
|
if let Some(npm_installer) = &self.npm_installer {
|
||||||
let already_done =
|
let already_done = npm_installer
|
||||||
npm_resolver.ensure_top_level_package_json_install().await?;
|
.ensure_top_level_package_json_install()
|
||||||
if !already_done && matches!(npm_caching, NpmCachingStrategy::Eager) {
|
|
||||||
npm_resolver
|
|
||||||
.cache_packages(crate::npm::PackageCaching::All)
|
|
||||||
.await?;
|
.await?;
|
||||||
|
if !already_done && matches!(npm_caching, NpmCachingStrategy::Eager) {
|
||||||
|
npm_installer.cache_packages(PackageCaching::All).await?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -646,10 +712,9 @@ impl ModuleGraphBuilder {
|
||||||
let initial_package_deps_len = graph.packages.package_deps_sum();
|
let initial_package_deps_len = graph.packages.package_deps_sum();
|
||||||
let initial_package_mappings_len = graph.packages.mappings().len();
|
let initial_package_mappings_len = graph.packages.mappings().len();
|
||||||
|
|
||||||
if roots.iter().any(|r| r.scheme() == "npm")
|
if roots.iter().any(|r| r.scheme() == "npm") && self.npm_resolver.is_byonm()
|
||||||
&& self.npm_resolver.as_byonm().is_some()
|
|
||||||
{
|
{
|
||||||
bail!("Resolving npm specifier entrypoints this way is currently not supported with \"nodeModules\": \"manual\". In the meantime, try with --node-modules-dir=auto instead");
|
return Err(BuildGraphWithNpmResolutionError::UnsupportedNpmSpecifierEntrypointResolutionWay);
|
||||||
}
|
}
|
||||||
|
|
||||||
graph.build(roots, loader, options).await;
|
graph.build(roots, loader, options).await;
|
||||||
|
@ -680,7 +745,7 @@ impl ModuleGraphBuilder {
|
||||||
for (from, to) in graph.packages.mappings() {
|
for (from, to) in graph.packages.mappings() {
|
||||||
lockfile.insert_package_specifier(
|
lockfile.insert_package_specifier(
|
||||||
JsrDepPackageReq::jsr(from.clone()),
|
JsrDepPackageReq::jsr(from.clone()),
|
||||||
to.version.to_string(),
|
to.version.to_custom_string::<SmallStackString>(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -700,7 +765,7 @@ impl ModuleGraphBuilder {
|
||||||
&self,
|
&self,
|
||||||
graph: &mut ModuleGraph,
|
graph: &mut ModuleGraph,
|
||||||
options: BuildFastCheckGraphOptions,
|
options: BuildFastCheckGraphOptions,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), deno_json::ToMaybeJsxImportSourceConfigError> {
|
||||||
if !graph.graph_kind().include_types() {
|
if !graph.graph_kind().include_types() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
@ -715,11 +780,7 @@ impl ModuleGraphBuilder {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
let parser = self.parsed_source_cache.as_capturing_parser();
|
let parser = self.parsed_source_cache.as_capturing_parser();
|
||||||
let cli_resolver = &self.resolver;
|
|
||||||
let graph_resolver = self.create_graph_resolver()?;
|
let graph_resolver = self.create_graph_resolver()?;
|
||||||
let graph_npm_resolver = cli_resolver.create_graph_npm_resolver(
|
|
||||||
self.cli_options.default_npm_caching_strategy(),
|
|
||||||
);
|
|
||||||
|
|
||||||
graph.build_fast_check_type_graph(
|
graph.build_fast_check_type_graph(
|
||||||
deno_graph::BuildFastCheckTypeGraphOptions {
|
deno_graph::BuildFastCheckTypeGraphOptions {
|
||||||
|
@ -728,7 +789,7 @@ impl ModuleGraphBuilder {
|
||||||
fast_check_dts: false,
|
fast_check_dts: false,
|
||||||
jsr_url_provider: &CliJsrUrlProvider,
|
jsr_url_provider: &CliJsrUrlProvider,
|
||||||
resolver: Some(&graph_resolver),
|
resolver: Some(&graph_resolver),
|
||||||
npm_resolver: Some(&graph_npm_resolver),
|
npm_resolver: Some(self.npm_graph_resolver.as_ref()),
|
||||||
workspace_fast_check: options.workspace_fast_check,
|
workspace_fast_check: options.workspace_fast_check,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -746,10 +807,10 @@ impl ModuleGraphBuilder {
|
||||||
) -> cache::FetchCacher {
|
) -> cache::FetchCacher {
|
||||||
cache::FetchCacher::new(
|
cache::FetchCacher::new(
|
||||||
self.file_fetcher.clone(),
|
self.file_fetcher.clone(),
|
||||||
self.fs.clone(),
|
|
||||||
self.global_http_cache.clone(),
|
self.global_http_cache.clone(),
|
||||||
self.in_npm_pkg_checker.clone(),
|
self.in_npm_pkg_checker.clone(),
|
||||||
self.module_info_cache.clone(),
|
self.module_info_cache.clone(),
|
||||||
|
self.sys.clone(),
|
||||||
cache::FetchCacherOptions {
|
cache::FetchCacherOptions {
|
||||||
file_header_overrides: self.cli_options.resolve_file_header_overrides(),
|
file_header_overrides: self.cli_options.resolve_file_header_overrides(),
|
||||||
permissions,
|
permissions,
|
||||||
|
@ -764,7 +825,7 @@ impl ModuleGraphBuilder {
|
||||||
/// Check if `roots` and their deps are available. Returns `Ok(())` if
|
/// Check if `roots` and their deps are available. Returns `Ok(())` if
|
||||||
/// so. Returns `Err(_)` if there is a known module graph or resolution
|
/// so. Returns `Err(_)` if there is a known module graph or resolution
|
||||||
/// error statically reachable from `roots` and not a dynamic import.
|
/// error statically reachable from `roots` and not a dynamic import.
|
||||||
pub fn graph_valid(&self, graph: &ModuleGraph) -> Result<(), AnyError> {
|
pub fn graph_valid(&self, graph: &ModuleGraph) -> Result<(), JsErrorBox> {
|
||||||
self.graph_roots_valid(
|
self.graph_roots_valid(
|
||||||
graph,
|
graph,
|
||||||
&graph.roots.iter().cloned().collect::<Vec<_>>(),
|
&graph.roots.iter().cloned().collect::<Vec<_>>(),
|
||||||
|
@ -775,10 +836,10 @@ impl ModuleGraphBuilder {
|
||||||
&self,
|
&self,
|
||||||
graph: &ModuleGraph,
|
graph: &ModuleGraph,
|
||||||
roots: &[ModuleSpecifier],
|
roots: &[ModuleSpecifier],
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), JsErrorBox> {
|
||||||
graph_valid(
|
graph_valid(
|
||||||
graph,
|
graph,
|
||||||
&self.fs,
|
&self.sys,
|
||||||
roots,
|
roots,
|
||||||
GraphValidOptions {
|
GraphValidOptions {
|
||||||
kind: if self.cli_options.type_check_mode().is_true() {
|
kind: if self.cli_options.type_check_mode().is_true() {
|
||||||
|
@ -792,7 +853,10 @@ impl ModuleGraphBuilder {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_graph_resolver(&self) -> Result<CliGraphResolver, AnyError> {
|
fn create_graph_resolver(
|
||||||
|
&self,
|
||||||
|
) -> Result<CliGraphResolver, deno_json::ToMaybeJsxImportSourceConfigError>
|
||||||
|
{
|
||||||
let jsx_import_source_config = self
|
let jsx_import_source_config = self
|
||||||
.cli_options
|
.cli_options
|
||||||
.workspace()
|
.workspace()
|
||||||
|
@ -833,18 +897,19 @@ pub fn enhanced_resolution_error_message(error: &ResolutionError) -> String {
|
||||||
message
|
message
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static RUN_WITH_SLOPPY_IMPORTS_MSG: &str =
|
||||||
|
"or run with --unstable-sloppy-imports";
|
||||||
|
|
||||||
fn enhanced_sloppy_imports_error_message(
|
fn enhanced_sloppy_imports_error_message(
|
||||||
fs: &Arc<dyn FileSystem>,
|
sys: &CliSys,
|
||||||
error: &ModuleError,
|
error: &ModuleError,
|
||||||
) -> Option<String> {
|
) -> Option<String> {
|
||||||
match error {
|
match error {
|
||||||
ModuleError::LoadingErr(specifier, _, ModuleLoadError::Loader(_)) // ex. "Is a directory" error
|
ModuleError::LoadingErr(specifier, _, ModuleLoadError::Loader(_)) // ex. "Is a directory" error
|
||||||
| ModuleError::Missing(specifier, _) => {
|
| ModuleError::Missing(specifier, _) => {
|
||||||
let additional_message = CliSloppyImportsResolver::new(SloppyImportsCachedFs::new(fs.clone()))
|
let additional_message = maybe_additional_sloppy_imports_message(sys, specifier)?;
|
||||||
.resolve(specifier, SloppyImportsResolutionKind::Execution)?
|
|
||||||
.as_suggestion_message();
|
|
||||||
Some(format!(
|
Some(format!(
|
||||||
"{} {} or run with --unstable-sloppy-imports",
|
"{} {}",
|
||||||
error,
|
error,
|
||||||
additional_message,
|
additional_message,
|
||||||
))
|
))
|
||||||
|
@ -853,6 +918,19 @@ fn enhanced_sloppy_imports_error_message(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn maybe_additional_sloppy_imports_message(
|
||||||
|
sys: &CliSys,
|
||||||
|
specifier: &ModuleSpecifier,
|
||||||
|
) -> Option<String> {
|
||||||
|
Some(format!(
|
||||||
|
"{} {}",
|
||||||
|
CliSloppyImportsResolver::new(SloppyImportsCachedFs::new(sys.clone()))
|
||||||
|
.resolve(specifier, SloppyImportsResolutionKind::Execution)?
|
||||||
|
.as_suggestion_message(),
|
||||||
|
RUN_WITH_SLOPPY_IMPORTS_MSG
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
fn enhanced_integrity_error_message(err: &ModuleError) -> Option<String> {
|
fn enhanced_integrity_error_message(err: &ModuleError) -> Option<String> {
|
||||||
match err {
|
match err {
|
||||||
ModuleError::LoadingErr(
|
ModuleError::LoadingErr(
|
||||||
|
@ -946,9 +1024,11 @@ fn get_resolution_error_bare_specifier(
|
||||||
{
|
{
|
||||||
Some(specifier.as_str())
|
Some(specifier.as_str())
|
||||||
} else if let ResolutionError::ResolverError { error, .. } = error {
|
} else if let ResolutionError::ResolverError { error, .. } = error {
|
||||||
if let ResolveError::Other(error) = (*error).as_ref() {
|
if let ResolveError::ImportMap(error) = (*error).as_ref() {
|
||||||
if let Some(ImportMapError::UnmappedBareSpecifier(specifier, _)) =
|
if let import_map::ImportMapErrorKind::UnmappedBareSpecifier(
|
||||||
error.downcast_ref::<ImportMapError>()
|
specifier,
|
||||||
|
_,
|
||||||
|
) = error.as_kind()
|
||||||
{
|
{
|
||||||
Some(specifier.as_str())
|
Some(specifier.as_str())
|
||||||
} else {
|
} else {
|
||||||
|
@ -985,11 +1065,12 @@ fn get_import_prefix_missing_error(error: &ResolutionError) -> Option<&str> {
|
||||||
ResolveError::Other(other_error) => {
|
ResolveError::Other(other_error) => {
|
||||||
if let Some(SpecifierError::ImportPrefixMissing {
|
if let Some(SpecifierError::ImportPrefixMissing {
|
||||||
specifier, ..
|
specifier, ..
|
||||||
}) = other_error.downcast_ref::<SpecifierError>()
|
}) = other_error.as_any().downcast_ref::<SpecifierError>()
|
||||||
{
|
{
|
||||||
maybe_specifier = Some(specifier);
|
maybe_specifier = Some(specifier);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ResolveError::ImportMap(_) => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1081,71 +1162,6 @@ impl deno_graph::source::Reporter for FileWatcherReporter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DenoGraphFsAdapter<'a>(
|
|
||||||
pub &'a dyn deno_runtime::deno_fs::FileSystem,
|
|
||||||
);
|
|
||||||
|
|
||||||
impl<'a> deno_graph::source::FileSystem for DenoGraphFsAdapter<'a> {
|
|
||||||
fn read_dir(
|
|
||||||
&self,
|
|
||||||
dir_url: &deno_graph::ModuleSpecifier,
|
|
||||||
) -> Vec<deno_graph::source::DirEntry> {
|
|
||||||
use deno_core::anyhow;
|
|
||||||
use deno_graph::source::DirEntry;
|
|
||||||
use deno_graph::source::DirEntryKind;
|
|
||||||
|
|
||||||
let dir_path = match dir_url.to_file_path() {
|
|
||||||
Ok(path) => path,
|
|
||||||
// ignore, treat as non-analyzable
|
|
||||||
Err(()) => return vec![],
|
|
||||||
};
|
|
||||||
let entries = match self.0.read_dir_sync(&dir_path) {
|
|
||||||
Ok(dir) => dir,
|
|
||||||
Err(err)
|
|
||||||
if matches!(
|
|
||||||
err.kind(),
|
|
||||||
std::io::ErrorKind::PermissionDenied | std::io::ErrorKind::NotFound
|
|
||||||
) =>
|
|
||||||
{
|
|
||||||
return vec![];
|
|
||||||
}
|
|
||||||
Err(err) => {
|
|
||||||
return vec![DirEntry {
|
|
||||||
kind: DirEntryKind::Error(
|
|
||||||
anyhow::Error::from(err)
|
|
||||||
.context("Failed to read directory.".to_string()),
|
|
||||||
),
|
|
||||||
url: dir_url.clone(),
|
|
||||||
}];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let mut dir_entries = Vec::with_capacity(entries.len());
|
|
||||||
for entry in entries {
|
|
||||||
let entry_path = dir_path.join(&entry.name);
|
|
||||||
dir_entries.push(if entry.is_directory {
|
|
||||||
DirEntry {
|
|
||||||
kind: DirEntryKind::Dir,
|
|
||||||
url: ModuleSpecifier::from_directory_path(&entry_path).unwrap(),
|
|
||||||
}
|
|
||||||
} else if entry.is_file {
|
|
||||||
DirEntry {
|
|
||||||
kind: DirEntryKind::File,
|
|
||||||
url: ModuleSpecifier::from_file_path(&entry_path).unwrap(),
|
|
||||||
}
|
|
||||||
} else if entry.is_symlink {
|
|
||||||
DirEntry {
|
|
||||||
kind: DirEntryKind::Symlink,
|
|
||||||
url: ModuleSpecifier::from_file_path(&entry_path).unwrap(),
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
continue;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
dir_entries
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn format_range_with_colors(referrer: &deno_graph::Range) -> String {
|
pub fn format_range_with_colors(referrer: &deno_graph::Range) -> String {
|
||||||
format!(
|
format!(
|
||||||
"{}:{}:{}",
|
"{}:{}:{}",
|
||||||
|
@ -1209,7 +1225,7 @@ fn format_deno_graph_error(err: &dyn Error) -> String {
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct CliGraphResolver<'a> {
|
struct CliGraphResolver<'a> {
|
||||||
cjs_tracker: &'a CjsTracker,
|
cjs_tracker: &'a CliCjsTracker,
|
||||||
resolver: &'a CliResolver,
|
resolver: &'a CliResolver,
|
||||||
jsx_import_source_config: Option<JsxImportSourceConfig>,
|
jsx_import_source_config: Option<JsxImportSourceConfig>,
|
||||||
}
|
}
|
||||||
|
@ -1305,7 +1321,7 @@ mod test {
|
||||||
let specifier = ModuleSpecifier::parse("file:///file.ts").unwrap();
|
let specifier = ModuleSpecifier::parse("file:///file.ts").unwrap();
|
||||||
let err = import_map.resolve(input, &specifier).err().unwrap();
|
let err = import_map.resolve(input, &specifier).err().unwrap();
|
||||||
let err = ResolutionError::ResolverError {
|
let err = ResolutionError::ResolverError {
|
||||||
error: Arc::new(ResolveError::Other(err.into())),
|
error: Arc::new(ResolveError::ImportMap(err)),
|
||||||
specifier: input.to_string(),
|
specifier: input.to_string(),
|
||||||
range: Range {
|
range: Range {
|
||||||
specifier,
|
specifier,
|
||||||
|
|
890
cli/http_util.rs
890
cli/http_util.rs
File diff suppressed because it is too large
Load diff
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
let mut args = vec!["cargo", "test", "-p", "cli_tests", "--features", "run"];
|
let mut args = vec!["cargo", "test", "-p", "cli_tests", "--features", "run"];
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
use log::debug;
|
use log::debug;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
// deno-lint-ignore-file
|
// deno-lint-ignore-file
|
||||||
|
|
||||||
import { core, primordials } from "ext:core/mod.js";
|
import { core, primordials } from "ext:core/mod.js";
|
||||||
|
@ -8,7 +8,7 @@ import {
|
||||||
restorePermissions,
|
restorePermissions,
|
||||||
} from "ext:cli/40_test_common.js";
|
} from "ext:cli/40_test_common.js";
|
||||||
import { Console } from "ext:deno_console/01_console.js";
|
import { Console } from "ext:deno_console/01_console.js";
|
||||||
import { setExitHandler } from "ext:runtime/30_os.js";
|
import { setExitHandler } from "ext:deno_os/30_os.js";
|
||||||
const {
|
const {
|
||||||
op_register_bench,
|
op_register_bench,
|
||||||
op_bench_get_origin,
|
op_bench_get_origin,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
// deno-lint-ignore-file
|
// deno-lint-ignore-file
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
1089
cli/js/40_lint.js
Normal file
1089
cli/js/40_lint.js
Normal file
File diff suppressed because it is too large
Load diff
1029
cli/js/40_lint_selector.js
Normal file
1029
cli/js/40_lint_selector.js
Normal file
File diff suppressed because it is too large
Load diff
139
cli/js/40_lint_types.d.ts
vendored
Normal file
139
cli/js/40_lint_types.d.ts
vendored
Normal file
|
@ -0,0 +1,139 @@
|
||||||
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
|
export interface NodeFacade {
|
||||||
|
type: string;
|
||||||
|
range: [number, number];
|
||||||
|
[key: string]: unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AstContext {
|
||||||
|
buf: Uint8Array;
|
||||||
|
strTable: Map<number, string>;
|
||||||
|
strTableOffset: number;
|
||||||
|
rootOffset: number;
|
||||||
|
nodes: Map<number, NodeFacade>;
|
||||||
|
spansOffset: number;
|
||||||
|
propsOffset: number;
|
||||||
|
strByType: number[];
|
||||||
|
strByProp: number[];
|
||||||
|
typeByStr: Map<string, number>;
|
||||||
|
propByStr: Map<string, number>;
|
||||||
|
matcher: MatchContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Node {
|
||||||
|
range: Range;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Range = [number, number];
|
||||||
|
|
||||||
|
// TODO(@marvinhagemeister) Remove once we land "official" types
|
||||||
|
export interface RuleContext {
|
||||||
|
id: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(@marvinhagemeister) Remove once we land "official" types
|
||||||
|
export interface LintRule {
|
||||||
|
create(ctx: RuleContext): Record<string, (node: unknown) => void>;
|
||||||
|
destroy?(ctx: RuleContext): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(@marvinhagemeister) Remove once we land "official" types
|
||||||
|
export interface LintPlugin {
|
||||||
|
name: string;
|
||||||
|
rules: Record<string, LintRule>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface LintState {
|
||||||
|
plugins: LintPlugin[];
|
||||||
|
installedPlugins: Set<string>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type VisitorFn = (node: unknown) => void;
|
||||||
|
|
||||||
|
export interface CompiledVisitor {
|
||||||
|
matcher: (ctx: MatchContext, offset: number) => boolean;
|
||||||
|
info: { enter: VisitorFn; exit: VisitorFn };
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AttrExists {
|
||||||
|
type: 3;
|
||||||
|
prop: number[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AttrBin {
|
||||||
|
type: 4;
|
||||||
|
prop: number[];
|
||||||
|
op: number;
|
||||||
|
// deno-lint-ignore no-explicit-any
|
||||||
|
value: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type AttrSelector = AttrExists | AttrBin;
|
||||||
|
|
||||||
|
export interface ElemSelector {
|
||||||
|
type: 1;
|
||||||
|
wildcard: boolean;
|
||||||
|
elem: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PseudoNthChild {
|
||||||
|
type: 5;
|
||||||
|
op: string | null;
|
||||||
|
step: number;
|
||||||
|
stepOffset: number;
|
||||||
|
of: Selector | null;
|
||||||
|
repeat: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PseudoHas {
|
||||||
|
type: 6;
|
||||||
|
selectors: Selector[];
|
||||||
|
}
|
||||||
|
export interface PseudoNot {
|
||||||
|
type: 7;
|
||||||
|
selectors: Selector[];
|
||||||
|
}
|
||||||
|
export interface PseudoFirstChild {
|
||||||
|
type: 8;
|
||||||
|
}
|
||||||
|
export interface PseudoLastChild {
|
||||||
|
type: 9;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Relation {
|
||||||
|
type: 2;
|
||||||
|
op: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Selector = Array<
|
||||||
|
| ElemSelector
|
||||||
|
| Relation
|
||||||
|
| AttrExists
|
||||||
|
| AttrBin
|
||||||
|
| PseudoNthChild
|
||||||
|
| PseudoNot
|
||||||
|
| PseudoHas
|
||||||
|
| PseudoFirstChild
|
||||||
|
| PseudoLastChild
|
||||||
|
>;
|
||||||
|
|
||||||
|
export interface SelectorParseCtx {
|
||||||
|
root: Selector;
|
||||||
|
current: Selector;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MatchContext {
|
||||||
|
getFirstChild(id: number): number;
|
||||||
|
getLastChild(id: number): number;
|
||||||
|
getSiblings(id: number): number[];
|
||||||
|
getParent(id: number): number;
|
||||||
|
getType(id: number): number;
|
||||||
|
getAttrPathValue(id: number, propIds: number[], idx: number): unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type NextFn = (ctx: MatchContext, id: number) => boolean;
|
||||||
|
export type MatcherFn = (ctx: MatchContext, id: number) => boolean;
|
||||||
|
export type TransformFn = (value: string) => number;
|
||||||
|
|
||||||
|
export {};
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
import { core, primordials } from "ext:core/mod.js";
|
import { core, primordials } from "ext:core/mod.js";
|
||||||
import { escapeName, withPermissions } from "ext:cli/40_test_common.js";
|
import { escapeName, withPermissions } from "ext:cli/40_test_common.js";
|
||||||
|
@ -26,7 +26,7 @@ const {
|
||||||
TypeError,
|
TypeError,
|
||||||
} = primordials;
|
} = primordials;
|
||||||
|
|
||||||
import { setExitHandler } from "ext:runtime/30_os.js";
|
import { setExitHandler } from "ext:deno_os/30_os.js";
|
||||||
|
|
||||||
// Capture `Deno` global so that users deleting or mangling it, won't
|
// Capture `Deno` global so that users deleting or mangling it, won't
|
||||||
// have impact on our sanitizers.
|
// have impact on our sanitizers.
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
import { core, primordials } from "ext:core/mod.js";
|
import { core, primordials } from "ext:core/mod.js";
|
||||||
import { serializePermissions } from "ext:runtime/10_permissions.js";
|
import { serializePermissions } from "ext:runtime/10_permissions.js";
|
||||||
const ops = core.ops;
|
const ops = core.ops;
|
||||||
|
|
14
cli/jsr.rs
14
cli/jsr.rs
|
@ -1,14 +1,16 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
use crate::args::jsr_url;
|
|
||||||
use crate::file_fetcher::FileFetcher;
|
|
||||||
use dashmap::DashMap;
|
use dashmap::DashMap;
|
||||||
use deno_core::serde_json;
|
use deno_core::serde_json;
|
||||||
use deno_graph::packages::JsrPackageInfo;
|
use deno_graph::packages::JsrPackageInfo;
|
||||||
use deno_graph::packages::JsrPackageVersionInfo;
|
use deno_graph::packages::JsrPackageVersionInfo;
|
||||||
use deno_semver::package::PackageNv;
|
use deno_semver::package::PackageNv;
|
||||||
use deno_semver::package::PackageReq;
|
use deno_semver::package::PackageReq;
|
||||||
use std::sync::Arc;
|
|
||||||
|
use crate::args::jsr_url;
|
||||||
|
use crate::file_fetcher::CliFileFetcher;
|
||||||
|
|
||||||
/// This is similar to a subset of `JsrCacheResolver` which fetches rather than
|
/// This is similar to a subset of `JsrCacheResolver` which fetches rather than
|
||||||
/// just reads the cache. Keep in sync!
|
/// just reads the cache. Keep in sync!
|
||||||
|
@ -19,11 +21,11 @@ pub struct JsrFetchResolver {
|
||||||
/// It can be large and we don't want to store it.
|
/// It can be large and we don't want to store it.
|
||||||
info_by_nv: DashMap<PackageNv, Option<Arc<JsrPackageVersionInfo>>>,
|
info_by_nv: DashMap<PackageNv, Option<Arc<JsrPackageVersionInfo>>>,
|
||||||
info_by_name: DashMap<String, Option<Arc<JsrPackageInfo>>>,
|
info_by_name: DashMap<String, Option<Arc<JsrPackageInfo>>>,
|
||||||
file_fetcher: Arc<FileFetcher>,
|
file_fetcher: Arc<CliFileFetcher>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl JsrFetchResolver {
|
impl JsrFetchResolver {
|
||||||
pub fn new(file_fetcher: Arc<FileFetcher>) -> Self {
|
pub fn new(file_fetcher: Arc<CliFileFetcher>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
nv_by_req: Default::default(),
|
nv_by_req: Default::default(),
|
||||||
info_by_nv: Default::default(),
|
info_by_nv: Default::default(),
|
||||||
|
|
|
@ -1,4 +1,46 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
|
use std::borrow::Cow;
|
||||||
|
use std::cmp::Ordering;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::collections::HashSet;
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
use deno_ast::SourceRange;
|
||||||
|
use deno_ast::SourceRangedForSpanned;
|
||||||
|
use deno_ast::SourceTextInfo;
|
||||||
|
use deno_config::workspace::MappedResolution;
|
||||||
|
use deno_core::error::AnyError;
|
||||||
|
use deno_core::serde::Deserialize;
|
||||||
|
use deno_core::serde::Serialize;
|
||||||
|
use deno_core::serde_json;
|
||||||
|
use deno_core::serde_json::json;
|
||||||
|
use deno_core::ModuleSpecifier;
|
||||||
|
use deno_error::JsErrorBox;
|
||||||
|
use deno_lint::diagnostic::LintDiagnosticRange;
|
||||||
|
use deno_path_util::url_to_file_path;
|
||||||
|
use deno_resolver::npm::managed::NpmResolutionCell;
|
||||||
|
use deno_runtime::deno_node::PathClean;
|
||||||
|
use deno_semver::jsr::JsrPackageNvReference;
|
||||||
|
use deno_semver::jsr::JsrPackageReqReference;
|
||||||
|
use deno_semver::npm::NpmPackageReqReference;
|
||||||
|
use deno_semver::package::PackageNv;
|
||||||
|
use deno_semver::package::PackageNvReference;
|
||||||
|
use deno_semver::package::PackageReq;
|
||||||
|
use deno_semver::package::PackageReqReference;
|
||||||
|
use deno_semver::SmallStackString;
|
||||||
|
use deno_semver::StackString;
|
||||||
|
use deno_semver::Version;
|
||||||
|
use import_map::ImportMap;
|
||||||
|
use node_resolver::InNpmPackageChecker;
|
||||||
|
use node_resolver::NodeResolutionKind;
|
||||||
|
use node_resolver::ResolutionMode;
|
||||||
|
use once_cell::sync::Lazy;
|
||||||
|
use regex::Regex;
|
||||||
|
use text_lines::LineAndColumnIndex;
|
||||||
|
use tower_lsp::lsp_types as lsp;
|
||||||
|
use tower_lsp::lsp_types::Position;
|
||||||
|
use tower_lsp::lsp_types::Range;
|
||||||
|
|
||||||
use super::diagnostics::DenoDiagnostic;
|
use super::diagnostics::DenoDiagnostic;
|
||||||
use super::diagnostics::DiagnosticSource;
|
use super::diagnostics::DiagnosticSource;
|
||||||
|
@ -8,49 +50,11 @@ use super::language_server;
|
||||||
use super::resolver::LspResolver;
|
use super::resolver::LspResolver;
|
||||||
use super::tsc;
|
use super::tsc;
|
||||||
use super::urls::url_to_uri;
|
use super::urls::url_to_uri;
|
||||||
|
|
||||||
use crate::args::jsr_url;
|
use crate::args::jsr_url;
|
||||||
use crate::lsp::logging::lsp_warn;
|
use crate::lsp::logging::lsp_warn;
|
||||||
use crate::lsp::search::PackageSearchApi;
|
use crate::lsp::search::PackageSearchApi;
|
||||||
use crate::tools::lint::CliLinter;
|
use crate::tools::lint::CliLinter;
|
||||||
use crate::util::path::relative_specifier;
|
use crate::util::path::relative_specifier;
|
||||||
use deno_config::workspace::MappedResolution;
|
|
||||||
use deno_lint::diagnostic::LintDiagnosticRange;
|
|
||||||
|
|
||||||
use deno_ast::SourceRange;
|
|
||||||
use deno_ast::SourceRangedForSpanned;
|
|
||||||
use deno_ast::SourceTextInfo;
|
|
||||||
use deno_core::error::custom_error;
|
|
||||||
use deno_core::error::AnyError;
|
|
||||||
use deno_core::serde::Deserialize;
|
|
||||||
use deno_core::serde::Serialize;
|
|
||||||
use deno_core::serde_json;
|
|
||||||
use deno_core::serde_json::json;
|
|
||||||
use deno_core::ModuleSpecifier;
|
|
||||||
use deno_path_util::url_to_file_path;
|
|
||||||
use deno_runtime::deno_node::PathClean;
|
|
||||||
use deno_semver::jsr::JsrPackageNvReference;
|
|
||||||
use deno_semver::jsr::JsrPackageReqReference;
|
|
||||||
use deno_semver::npm::NpmPackageReqReference;
|
|
||||||
use deno_semver::package::PackageNv;
|
|
||||||
use deno_semver::package::PackageNvReference;
|
|
||||||
use deno_semver::package::PackageReq;
|
|
||||||
use deno_semver::package::PackageReqReference;
|
|
||||||
use deno_semver::Version;
|
|
||||||
use import_map::ImportMap;
|
|
||||||
use node_resolver::NodeResolutionKind;
|
|
||||||
use node_resolver::ResolutionMode;
|
|
||||||
use once_cell::sync::Lazy;
|
|
||||||
use regex::Regex;
|
|
||||||
use std::borrow::Cow;
|
|
||||||
use std::cmp::Ordering;
|
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::collections::HashSet;
|
|
||||||
use std::path::Path;
|
|
||||||
use text_lines::LineAndColumnIndex;
|
|
||||||
use tower_lsp::lsp_types as lsp;
|
|
||||||
use tower_lsp::lsp_types::Position;
|
|
||||||
use tower_lsp::lsp_types::Range;
|
|
||||||
|
|
||||||
/// Diagnostic error codes which actually are the same, and so when grouping
|
/// Diagnostic error codes which actually are the same, and so when grouping
|
||||||
/// fixes we treat them the same.
|
/// fixes we treat them the same.
|
||||||
|
@ -270,13 +274,24 @@ impl<'a> TsResponseImportMapper<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if specifier.scheme() == "node" {
|
||||||
|
return Some(specifier.to_string());
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(jsr_path) = specifier.as_str().strip_prefix(jsr_url().as_str())
|
if let Some(jsr_path) = specifier.as_str().strip_prefix(jsr_url().as_str())
|
||||||
{
|
{
|
||||||
let mut segments = jsr_path.split('/');
|
let mut segments = jsr_path.split('/');
|
||||||
let name = if jsr_path.starts_with('@') {
|
let name = if jsr_path.starts_with('@') {
|
||||||
format!("{}/{}", segments.next()?, segments.next()?)
|
let scope = segments.next()?;
|
||||||
|
let name = segments.next()?;
|
||||||
|
capacity_builder::StringBuilder::<StackString>::build(|builder| {
|
||||||
|
builder.append(scope);
|
||||||
|
builder.append("/");
|
||||||
|
builder.append(name);
|
||||||
|
})
|
||||||
|
.unwrap()
|
||||||
} else {
|
} else {
|
||||||
segments.next()?.to_string()
|
StackString::from(segments.next()?)
|
||||||
};
|
};
|
||||||
let version = Version::parse_standard(segments.next()?).ok()?;
|
let version = Version::parse_standard(segments.next()?).ok()?;
|
||||||
let nv = PackageNv { name, version };
|
let nv = PackageNv { name, version };
|
||||||
|
@ -286,7 +301,9 @@ impl<'a> TsResponseImportMapper<'a> {
|
||||||
&path,
|
&path,
|
||||||
Some(&self.file_referrer),
|
Some(&self.file_referrer),
|
||||||
)?;
|
)?;
|
||||||
let sub_path = (export != ".").then_some(export);
|
let sub_path = (export != ".")
|
||||||
|
.then_some(export)
|
||||||
|
.map(SmallStackString::from_string);
|
||||||
let mut req = None;
|
let mut req = None;
|
||||||
req = req.or_else(|| {
|
req = req.or_else(|| {
|
||||||
let import_map = self.maybe_import_map?;
|
let import_map = self.maybe_import_map?;
|
||||||
|
@ -350,7 +367,9 @@ impl<'a> TsResponseImportMapper<'a> {
|
||||||
if let Ok(Some(pkg_id)) =
|
if let Ok(Some(pkg_id)) =
|
||||||
npm_resolver.resolve_pkg_id_from_specifier(specifier)
|
npm_resolver.resolve_pkg_id_from_specifier(specifier)
|
||||||
{
|
{
|
||||||
let pkg_reqs = npm_resolver.resolve_pkg_reqs_from_pkg_id(&pkg_id);
|
let pkg_reqs = npm_resolver
|
||||||
|
.resolution()
|
||||||
|
.resolve_pkg_reqs_from_pkg_id(&pkg_id);
|
||||||
// check if any pkg reqs match what is found in an import map
|
// check if any pkg reqs match what is found in an import map
|
||||||
if !pkg_reqs.is_empty() {
|
if !pkg_reqs.is_empty() {
|
||||||
let sub_path = npm_resolver
|
let sub_path = npm_resolver
|
||||||
|
@ -599,18 +618,24 @@ fn try_reverse_map_package_json_exports(
|
||||||
/// For a set of tsc changes, can them for any that contain something that looks
|
/// For a set of tsc changes, can them for any that contain something that looks
|
||||||
/// like an import and rewrite the import specifier to include the extension
|
/// like an import and rewrite the import specifier to include the extension
|
||||||
pub fn fix_ts_import_changes(
|
pub fn fix_ts_import_changes(
|
||||||
referrer: &ModuleSpecifier,
|
|
||||||
resolution_mode: ResolutionMode,
|
|
||||||
changes: &[tsc::FileTextChanges],
|
changes: &[tsc::FileTextChanges],
|
||||||
language_server: &language_server::Inner,
|
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 Ok(referrer) = ModuleSpecifier::parse(&change.file_name) else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
let referrer_doc = language_server.get_asset_or_document(&referrer).ok();
|
||||||
|
let resolution_mode = referrer_doc
|
||||||
|
.as_ref()
|
||||||
|
.map(|d| d.resolution_mode())
|
||||||
|
.unwrap_or(ResolutionMode::Import);
|
||||||
|
let import_mapper =
|
||||||
|
language_server.get_ts_response_import_mapper(&referrer);
|
||||||
let mut text_changes = Vec::new();
|
let mut text_changes = Vec::new();
|
||||||
for text_change in &change.text_changes {
|
for text_change in &change.text_changes {
|
||||||
let lines = text_change.new_text.split('\n');
|
let lines = text_change.new_text.split('\n');
|
||||||
|
|
||||||
let new_lines: Vec<String> = lines
|
let new_lines: Vec<String> = lines
|
||||||
.map(|line| {
|
.map(|line| {
|
||||||
// This assumes that there's only one import per line.
|
// This assumes that there's only one import per line.
|
||||||
|
@ -618,7 +643,7 @@ pub fn fix_ts_import_changes(
|
||||||
let specifier =
|
let specifier =
|
||||||
captures.iter().skip(1).find_map(|s| s).unwrap().as_str();
|
captures.iter().skip(1).find_map(|s| s).unwrap().as_str();
|
||||||
if let Some(new_specifier) = import_mapper
|
if let Some(new_specifier) = import_mapper
|
||||||
.check_unresolved_specifier(specifier, referrer, resolution_mode)
|
.check_unresolved_specifier(specifier, &referrer, resolution_mode)
|
||||||
{
|
{
|
||||||
line.replace(specifier, &new_specifier)
|
line.replace(specifier, &new_specifier)
|
||||||
} else {
|
} else {
|
||||||
|
@ -1049,10 +1074,13 @@ impl CodeActionCollection {
|
||||||
// we wrap tsc, we can't handle the asynchronous response, so it is
|
// we wrap tsc, we can't handle the asynchronous response, so it is
|
||||||
// actually easier to return errors if we ever encounter one of these,
|
// actually easier to return errors if we ever encounter one of these,
|
||||||
// which we really wouldn't expect from the Deno lsp.
|
// which we really wouldn't expect from the Deno lsp.
|
||||||
return Err(custom_error(
|
return Err(
|
||||||
|
JsErrorBox::new(
|
||||||
"UnsupportedFix",
|
"UnsupportedFix",
|
||||||
"The action returned from TypeScript is unsupported.",
|
"The action returned from TypeScript is unsupported.",
|
||||||
));
|
)
|
||||||
|
.into(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
let Some(action) =
|
let Some(action) =
|
||||||
fix_ts_import_action(specifier, resolution_mode, action, language_server)
|
fix_ts_import_action(specifier, resolution_mode, action, language_server)
|
||||||
|
@ -1271,6 +1299,19 @@ impl CodeActionCollection {
|
||||||
range: &lsp::Range,
|
range: &lsp::Range,
|
||||||
language_server: &language_server::Inner,
|
language_server: &language_server::Inner,
|
||||||
) -> Option<lsp::CodeAction> {
|
) -> Option<lsp::CodeAction> {
|
||||||
|
fn top_package_req_for_name(
|
||||||
|
resolution: &NpmResolutionCell,
|
||||||
|
name: &str,
|
||||||
|
) -> Option<PackageReq> {
|
||||||
|
let package_reqs = resolution.package_reqs();
|
||||||
|
let mut entries = package_reqs
|
||||||
|
.into_iter()
|
||||||
|
.filter(|(_, nv)| nv.name == name)
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
entries.sort_by(|a, b| a.1.version.cmp(&b.1.version));
|
||||||
|
Some(entries.pop()?.0)
|
||||||
|
}
|
||||||
|
|
||||||
let (dep_key, dependency, _) =
|
let (dep_key, dependency, _) =
|
||||||
document.get_maybe_dependency(&range.end)?;
|
document.get_maybe_dependency(&range.end)?;
|
||||||
if dependency.maybe_deno_types_specifier.is_some() {
|
if dependency.maybe_deno_types_specifier.is_some() {
|
||||||
|
@ -1358,9 +1399,10 @@ impl CodeActionCollection {
|
||||||
.and_then(|versions| versions.first().cloned())?;
|
.and_then(|versions| versions.first().cloned())?;
|
||||||
let types_specifier_text =
|
let types_specifier_text =
|
||||||
if let Some(npm_resolver) = managed_npm_resolver {
|
if let Some(npm_resolver) = managed_npm_resolver {
|
||||||
let mut specifier_text = if let Some(req) =
|
let mut specifier_text = if let Some(req) = top_package_req_for_name(
|
||||||
npm_resolver.top_package_req_for_name(&types_package_name)
|
npm_resolver.resolution(),
|
||||||
{
|
&types_package_name,
|
||||||
|
) {
|
||||||
format!("npm:{req}")
|
format!("npm:{req}")
|
||||||
} else {
|
} else {
|
||||||
format!("npm:{}@^{}", &types_package_name, types_package_version)
|
format!("npm:{}@^{}", &types_package_name, types_package_version)
|
||||||
|
|
|
@ -1,4 +1,14 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
|
use std::collections::BTreeMap;
|
||||||
|
use std::fs;
|
||||||
|
use std::path::Path;
|
||||||
|
use std::sync::Arc;
|
||||||
|
use std::time::SystemTime;
|
||||||
|
|
||||||
|
use deno_core::url::Url;
|
||||||
|
use deno_core::ModuleSpecifier;
|
||||||
|
use deno_path_util::url_to_file_path;
|
||||||
|
|
||||||
use crate::cache::DenoDir;
|
use crate::cache::DenoDir;
|
||||||
use crate::cache::GlobalHttpCache;
|
use crate::cache::GlobalHttpCache;
|
||||||
|
@ -7,15 +17,7 @@ use crate::cache::LocalLspHttpCache;
|
||||||
use crate::lsp::config::Config;
|
use crate::lsp::config::Config;
|
||||||
use crate::lsp::logging::lsp_log;
|
use crate::lsp::logging::lsp_log;
|
||||||
use crate::lsp::logging::lsp_warn;
|
use crate::lsp::logging::lsp_warn;
|
||||||
|
use crate::sys::CliSys;
|
||||||
use deno_core::url::Url;
|
|
||||||
use deno_core::ModuleSpecifier;
|
|
||||||
use deno_path_util::url_to_file_path;
|
|
||||||
use std::collections::BTreeMap;
|
|
||||||
use std::fs;
|
|
||||||
use std::path::Path;
|
|
||||||
use std::sync::Arc;
|
|
||||||
use std::time::SystemTime;
|
|
||||||
|
|
||||||
pub fn calculate_fs_version(
|
pub fn calculate_fs_version(
|
||||||
cache: &LspCache,
|
cache: &LspCache,
|
||||||
|
@ -91,12 +93,11 @@ impl LspCache {
|
||||||
})
|
})
|
||||||
.ok()
|
.ok()
|
||||||
});
|
});
|
||||||
let deno_dir = DenoDir::new(global_cache_path)
|
let sys = CliSys::default();
|
||||||
|
let deno_dir = DenoDir::new(sys.clone(), global_cache_path)
|
||||||
.expect("should be infallible with absolute custom root");
|
.expect("should be infallible with absolute custom root");
|
||||||
let global = Arc::new(GlobalHttpCache::new(
|
let global =
|
||||||
deno_dir.remote_folder_path(),
|
Arc::new(GlobalHttpCache::new(sys, deno_dir.remote_folder_path()));
|
||||||
crate::cache::RealDenoCacheEnv,
|
|
||||||
));
|
|
||||||
Self {
|
Self {
|
||||||
deno_dir,
|
deno_dir,
|
||||||
global,
|
global,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
//!
|
//!
|
||||||
//! Provides information about what capabilities that are supported by the
|
//! Provides information about what capabilities that are supported by the
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
@ -12,12 +12,11 @@ use lsp_types::Uri;
|
||||||
use tower_lsp::lsp_types as lsp;
|
use tower_lsp::lsp_types as lsp;
|
||||||
use tower_lsp::lsp_types::ConfigurationItem;
|
use tower_lsp::lsp_types::ConfigurationItem;
|
||||||
|
|
||||||
use crate::lsp::repl::get_repl_workspace_settings;
|
|
||||||
|
|
||||||
use super::config::WorkspaceSettings;
|
use super::config::WorkspaceSettings;
|
||||||
use super::config::SETTINGS_SECTION;
|
use super::config::SETTINGS_SECTION;
|
||||||
use super::lsp_custom;
|
use super::lsp_custom;
|
||||||
use super::testing::lsp_custom as testing_lsp_custom;
|
use super::testing::lsp_custom as testing_lsp_custom;
|
||||||
|
use crate::lsp::repl::get_repl_workspace_settings;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum TestingNotification {
|
pub enum TestingNotification {
|
||||||
|
|
|
@ -1,13 +1,9 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
use crate::lsp::logging::lsp_warn;
|
use std::cell::RefCell;
|
||||||
|
use std::collections::HashSet;
|
||||||
use super::analysis::source_range_to_lsp_range;
|
use std::rc::Rc;
|
||||||
use super::config::CodeLensSettings;
|
use std::sync::Arc;
|
||||||
use super::language_server;
|
|
||||||
use super::text::LineIndex;
|
|
||||||
use super::tsc;
|
|
||||||
use super::tsc::NavigationTree;
|
|
||||||
|
|
||||||
use deno_ast::swc::ast;
|
use deno_ast::swc::ast;
|
||||||
use deno_ast::swc::visit::Visit;
|
use deno_ast::swc::visit::Visit;
|
||||||
|
@ -25,13 +21,17 @@ use deno_core::ModuleSpecifier;
|
||||||
use lazy_regex::lazy_regex;
|
use lazy_regex::lazy_regex;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use std::cell::RefCell;
|
|
||||||
use std::collections::HashSet;
|
|
||||||
use std::rc::Rc;
|
|
||||||
use std::sync::Arc;
|
|
||||||
use tower_lsp::jsonrpc::Error as LspError;
|
use tower_lsp::jsonrpc::Error as LspError;
|
||||||
use tower_lsp::lsp_types as lsp;
|
use tower_lsp::lsp_types as lsp;
|
||||||
|
|
||||||
|
use super::analysis::source_range_to_lsp_range;
|
||||||
|
use super::config::CodeLensSettings;
|
||||||
|
use super::language_server;
|
||||||
|
use super::text::LineIndex;
|
||||||
|
use super::tsc;
|
||||||
|
use super::tsc::NavigationTree;
|
||||||
|
use crate::lsp::logging::lsp_warn;
|
||||||
|
|
||||||
static ABSTRACT_MODIFIER: Lazy<Regex> = lazy_regex!(r"\babstract\b");
|
static ABSTRACT_MODIFIER: Lazy<Regex> = lazy_regex!(r"\babstract\b");
|
||||||
|
|
||||||
static EXPORT_MODIFIER: Lazy<Regex> = lazy_regex!(r"\bexport\b");
|
static EXPORT_MODIFIER: Lazy<Regex> = lazy_regex!(r"\bexport\b");
|
||||||
|
|
|
@ -1,4 +1,26 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
|
use deno_ast::LineAndColumnIndex;
|
||||||
|
use deno_ast::SourceTextInfo;
|
||||||
|
use deno_core::resolve_path;
|
||||||
|
use deno_core::resolve_url;
|
||||||
|
use deno_core::serde::Deserialize;
|
||||||
|
use deno_core::serde::Serialize;
|
||||||
|
use deno_core::serde_json::json;
|
||||||
|
use deno_core::url::Position;
|
||||||
|
use deno_core::ModuleSpecifier;
|
||||||
|
use deno_path_util::url_to_file_path;
|
||||||
|
use deno_runtime::deno_node::SUPPORTED_BUILTIN_NODE_MODULES;
|
||||||
|
use deno_semver::jsr::JsrPackageReqReference;
|
||||||
|
use deno_semver::package::PackageNv;
|
||||||
|
use import_map::ImportMap;
|
||||||
|
use indexmap::IndexSet;
|
||||||
|
use lsp_types::CompletionList;
|
||||||
|
use node_resolver::NodeResolutionKind;
|
||||||
|
use node_resolver::ResolutionMode;
|
||||||
|
use once_cell::sync::Lazy;
|
||||||
|
use regex::Regex;
|
||||||
|
use tower_lsp::lsp_types as lsp;
|
||||||
|
|
||||||
use super::client::Client;
|
use super::client::Client;
|
||||||
use super::config::Config;
|
use super::config::Config;
|
||||||
|
@ -12,33 +34,10 @@ use super::registries::ModuleRegistry;
|
||||||
use super::resolver::LspResolver;
|
use super::resolver::LspResolver;
|
||||||
use super::search::PackageSearchApi;
|
use super::search::PackageSearchApi;
|
||||||
use super::tsc;
|
use super::tsc;
|
||||||
|
|
||||||
use crate::graph_util::to_node_resolution_mode;
|
use crate::graph_util::to_node_resolution_mode;
|
||||||
use crate::jsr::JsrFetchResolver;
|
use crate::jsr::JsrFetchResolver;
|
||||||
use crate::util::path::is_importable_ext;
|
use crate::util::path::is_importable_ext;
|
||||||
use crate::util::path::relative_specifier;
|
use crate::util::path::relative_specifier;
|
||||||
use deno_runtime::deno_node::SUPPORTED_BUILTIN_NODE_MODULES;
|
|
||||||
|
|
||||||
use deno_ast::LineAndColumnIndex;
|
|
||||||
use deno_ast::SourceTextInfo;
|
|
||||||
use deno_core::resolve_path;
|
|
||||||
use deno_core::resolve_url;
|
|
||||||
use deno_core::serde::Deserialize;
|
|
||||||
use deno_core::serde::Serialize;
|
|
||||||
use deno_core::serde_json::json;
|
|
||||||
use deno_core::url::Position;
|
|
||||||
use deno_core::ModuleSpecifier;
|
|
||||||
use deno_path_util::url_to_file_path;
|
|
||||||
use deno_semver::jsr::JsrPackageReqReference;
|
|
||||||
use deno_semver::package::PackageNv;
|
|
||||||
use import_map::ImportMap;
|
|
||||||
use indexmap::IndexSet;
|
|
||||||
use lsp_types::CompletionList;
|
|
||||||
use node_resolver::NodeResolutionKind;
|
|
||||||
use node_resolver::ResolutionMode;
|
|
||||||
use once_cell::sync::Lazy;
|
|
||||||
use regex::Regex;
|
|
||||||
use tower_lsp::lsp_types as lsp;
|
|
||||||
|
|
||||||
static FILE_PROTO_RE: Lazy<Regex> =
|
static FILE_PROTO_RE: Lazy<Regex> =
|
||||||
lazy_regex::lazy_regex!(r#"^file:/{2}(?:/[A-Za-z]:)?"#);
|
lazy_regex::lazy_regex!(r#"^file:/{2}(?:/[A-Za-z]:)?"#);
|
||||||
|
@ -822,16 +821,18 @@ fn get_workspace_completions(
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use deno_core::resolve_url;
|
||||||
|
use pretty_assertions::assert_eq;
|
||||||
|
use test_util::TempDir;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::cache::HttpCache;
|
use crate::cache::HttpCache;
|
||||||
use crate::lsp::cache::LspCache;
|
use crate::lsp::cache::LspCache;
|
||||||
use crate::lsp::documents::Documents;
|
use crate::lsp::documents::Documents;
|
||||||
use crate::lsp::documents::LanguageId;
|
use crate::lsp::documents::LanguageId;
|
||||||
use crate::lsp::search::tests::TestPackageSearchApi;
|
use crate::lsp::search::tests::TestPackageSearchApi;
|
||||||
use deno_core::resolve_url;
|
|
||||||
use pretty_assertions::assert_eq;
|
|
||||||
use std::collections::HashMap;
|
|
||||||
use test_util::TempDir;
|
|
||||||
|
|
||||||
fn setup(
|
fn setup(
|
||||||
open_sources: &[(&str, &str, i32, LanguageId)],
|
open_sources: &[(&str, &str, i32, LanguageId)],
|
||||||
|
|
|
@ -1,4 +1,13 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
|
use std::collections::BTreeMap;
|
||||||
|
use std::collections::BTreeSet;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::ops::Deref;
|
||||||
|
use std::ops::DerefMut;
|
||||||
|
use std::path::Path;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
use deno_ast::MediaType;
|
use deno_ast::MediaType;
|
||||||
use deno_config::deno_json::DenoJsonCache;
|
use deno_config::deno_json::DenoJsonCache;
|
||||||
|
@ -9,8 +18,6 @@ use deno_config::deno_json::LintConfig;
|
||||||
use deno_config::deno_json::NodeModulesDirMode;
|
use deno_config::deno_json::NodeModulesDirMode;
|
||||||
use deno_config::deno_json::TestConfig;
|
use deno_config::deno_json::TestConfig;
|
||||||
use deno_config::deno_json::TsConfig;
|
use deno_config::deno_json::TsConfig;
|
||||||
use deno_config::fs::DenoConfigFs;
|
|
||||||
use deno_config::fs::RealDenoConfigFs;
|
|
||||||
use deno_config::glob::FilePatterns;
|
use deno_config::glob::FilePatterns;
|
||||||
use deno_config::glob::PathOrPatternSet;
|
use deno_config::glob::PathOrPatternSet;
|
||||||
use deno_config::workspace::CreateResolverOptions;
|
use deno_config::workspace::CreateResolverOptions;
|
||||||
|
@ -38,18 +45,10 @@ use deno_lint::linter::LintConfig as DenoLintConfig;
|
||||||
use deno_npm::npm_rc::ResolvedNpmRc;
|
use deno_npm::npm_rc::ResolvedNpmRc;
|
||||||
use deno_package_json::PackageJsonCache;
|
use deno_package_json::PackageJsonCache;
|
||||||
use deno_path_util::url_to_file_path;
|
use deno_path_util::url_to_file_path;
|
||||||
|
use deno_resolver::sloppy_imports::SloppyImportsCachedFs;
|
||||||
use deno_runtime::deno_node::PackageJson;
|
use deno_runtime::deno_node::PackageJson;
|
||||||
use indexmap::IndexSet;
|
use indexmap::IndexSet;
|
||||||
use lsp_types::ClientCapabilities;
|
use lsp_types::ClientCapabilities;
|
||||||
use std::borrow::Cow;
|
|
||||||
use std::collections::BTreeMap;
|
|
||||||
use std::collections::BTreeSet;
|
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::ops::Deref;
|
|
||||||
use std::ops::DerefMut;
|
|
||||||
use std::path::Path;
|
|
||||||
use std::path::PathBuf;
|
|
||||||
use std::sync::Arc;
|
|
||||||
use tower_lsp::lsp_types as lsp;
|
use tower_lsp::lsp_types as lsp;
|
||||||
|
|
||||||
use super::logging::lsp_log;
|
use super::logging::lsp_log;
|
||||||
|
@ -63,10 +62,10 @@ use crate::args::ConfigFile;
|
||||||
use crate::args::LintFlags;
|
use crate::args::LintFlags;
|
||||||
use crate::args::LintOptions;
|
use crate::args::LintOptions;
|
||||||
use crate::cache::FastInsecureHasher;
|
use crate::cache::FastInsecureHasher;
|
||||||
use crate::file_fetcher::FileFetcher;
|
use crate::file_fetcher::CliFileFetcher;
|
||||||
use crate::lsp::logging::lsp_warn;
|
use crate::lsp::logging::lsp_warn;
|
||||||
use crate::resolver::CliSloppyImportsResolver;
|
use crate::resolver::CliSloppyImportsResolver;
|
||||||
use crate::resolver::SloppyImportsCachedFs;
|
use crate::sys::CliSys;
|
||||||
use crate::tools::lint::CliLinter;
|
use crate::tools::lint::CliLinter;
|
||||||
use crate::tools::lint::CliLinterOptions;
|
use crate::tools::lint::CliLinterOptions;
|
||||||
use crate::tools::lint::LintRuleProvider;
|
use crate::tools::lint::LintRuleProvider;
|
||||||
|
@ -459,6 +458,19 @@ impl Default for LanguagePreferences {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct SuggestionActionsSettings {
|
||||||
|
#[serde(default = "is_true")]
|
||||||
|
pub enabled: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for SuggestionActionsSettings {
|
||||||
|
fn default() -> Self {
|
||||||
|
SuggestionActionsSettings { enabled: true }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, Deserialize, Serialize, PartialEq, Eq)]
|
#[derive(Debug, Default, Clone, Deserialize, Serialize, PartialEq, Eq)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct UpdateImportsOnFileMoveOptions {
|
pub struct UpdateImportsOnFileMoveOptions {
|
||||||
|
@ -490,6 +502,8 @@ pub struct LanguageWorkspaceSettings {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub suggest: CompletionSettings,
|
pub suggest: CompletionSettings,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
|
pub suggestion_actions: SuggestionActionsSettings,
|
||||||
|
#[serde(default)]
|
||||||
pub update_imports_on_file_move: UpdateImportsOnFileMoveOptions,
|
pub update_imports_on_file_move: UpdateImportsOnFileMoveOptions,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -839,7 +853,8 @@ impl Settings {
|
||||||
Some(false)
|
Some(false)
|
||||||
} else if let Some(enable_paths) = &enable_paths {
|
} else if let Some(enable_paths) = &enable_paths {
|
||||||
for enable_path in enable_paths {
|
for enable_path in enable_paths {
|
||||||
if path.starts_with(enable_path) {
|
// Also enable if the checked path is a dir containing an enabled path.
|
||||||
|
if path.starts_with(enable_path) || enable_path.starts_with(&path) {
|
||||||
return Some(true);
|
return Some(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1203,9 +1218,8 @@ impl ConfigData {
|
||||||
specified_config: Option<&Path>,
|
specified_config: Option<&Path>,
|
||||||
scope: &ModuleSpecifier,
|
scope: &ModuleSpecifier,
|
||||||
settings: &Settings,
|
settings: &Settings,
|
||||||
file_fetcher: &Arc<FileFetcher>,
|
file_fetcher: &Arc<CliFileFetcher>,
|
||||||
// sync requirement is because the lsp requires sync
|
// sync requirement is because the lsp requires sync
|
||||||
cached_deno_config_fs: &(dyn DenoConfigFs + Sync),
|
|
||||||
deno_json_cache: &(dyn DenoJsonCache + Sync),
|
deno_json_cache: &(dyn DenoJsonCache + Sync),
|
||||||
pkg_json_cache: &(dyn PackageJsonCache + Sync),
|
pkg_json_cache: &(dyn PackageJsonCache + Sync),
|
||||||
workspace_cache: &(dyn WorkspaceCache + Sync),
|
workspace_cache: &(dyn WorkspaceCache + Sync),
|
||||||
|
@ -1215,6 +1229,7 @@ impl ConfigData {
|
||||||
Ok(scope_dir_path) => {
|
Ok(scope_dir_path) => {
|
||||||
let paths = [scope_dir_path];
|
let paths = [scope_dir_path];
|
||||||
WorkspaceDirectory::discover(
|
WorkspaceDirectory::discover(
|
||||||
|
&CliSys::default(),
|
||||||
match specified_config {
|
match specified_config {
|
||||||
Some(config_path) => {
|
Some(config_path) => {
|
||||||
deno_config::workspace::WorkspaceDiscoverStart::ConfigFile(
|
deno_config::workspace::WorkspaceDiscoverStart::ConfigFile(
|
||||||
|
@ -1226,13 +1241,11 @@ impl ConfigData {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
&WorkspaceDiscoverOptions {
|
&WorkspaceDiscoverOptions {
|
||||||
fs: cached_deno_config_fs,
|
|
||||||
additional_config_file_names: &[],
|
additional_config_file_names: &[],
|
||||||
deno_json_cache: Some(deno_json_cache),
|
deno_json_cache: Some(deno_json_cache),
|
||||||
pkg_json_cache: Some(pkg_json_cache),
|
pkg_json_cache: Some(pkg_json_cache),
|
||||||
workspace_cache: Some(workspace_cache),
|
workspace_cache: Some(workspace_cache),
|
||||||
discover_pkg_json: !has_flag_env_var("DENO_NO_PACKAGE_JSON"),
|
discover_pkg_json: !has_flag_env_var("DENO_NO_PACKAGE_JSON"),
|
||||||
config_parse_options: Default::default(),
|
|
||||||
maybe_vendor_override: None,
|
maybe_vendor_override: None,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
@ -1298,7 +1311,7 @@ impl ConfigData {
|
||||||
member_dir: Arc<WorkspaceDirectory>,
|
member_dir: Arc<WorkspaceDirectory>,
|
||||||
scope: Arc<ModuleSpecifier>,
|
scope: Arc<ModuleSpecifier>,
|
||||||
settings: &Settings,
|
settings: &Settings,
|
||||||
file_fetcher: Option<&Arc<FileFetcher>>,
|
file_fetcher: Option<&Arc<CliFileFetcher>>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let (settings, workspace_folder) = settings.get_for_specifier(&scope);
|
let (settings, workspace_folder) = settings.get_for_specifier(&scope);
|
||||||
let mut watched_files = HashMap::with_capacity(10);
|
let mut watched_files = HashMap::with_capacity(10);
|
||||||
|
@ -1557,11 +1570,11 @@ impl ConfigData {
|
||||||
let resolver = member_dir
|
let resolver = member_dir
|
||||||
.workspace
|
.workspace
|
||||||
.create_resolver(
|
.create_resolver(
|
||||||
|
&CliSys::default(),
|
||||||
CreateResolverOptions {
|
CreateResolverOptions {
|
||||||
pkg_json_dep_resolution,
|
pkg_json_dep_resolution,
|
||||||
specified_import_map,
|
specified_import_map,
|
||||||
},
|
},
|
||||||
|path| Ok(std::fs::read_to_string(path)?),
|
|
||||||
)
|
)
|
||||||
.inspect_err(|err| {
|
.inspect_err(|err| {
|
||||||
lsp_warn!(
|
lsp_warn!(
|
||||||
|
@ -1603,9 +1616,7 @@ impl ConfigData {
|
||||||
|| unstable.contains("sloppy-imports");
|
|| unstable.contains("sloppy-imports");
|
||||||
let sloppy_imports_resolver = unstable_sloppy_imports.then(|| {
|
let sloppy_imports_resolver = unstable_sloppy_imports.then(|| {
|
||||||
Arc::new(CliSloppyImportsResolver::new(
|
Arc::new(CliSloppyImportsResolver::new(
|
||||||
SloppyImportsCachedFs::new_without_stat_cache(Arc::new(
|
SloppyImportsCachedFs::new_without_stat_cache(CliSys::default()),
|
||||||
deno_runtime::deno_fs::RealFs,
|
|
||||||
)),
|
|
||||||
))
|
))
|
||||||
});
|
});
|
||||||
let resolver = Arc::new(resolver);
|
let resolver = Arc::new(resolver);
|
||||||
|
@ -1819,13 +1830,12 @@ impl ConfigTree {
|
||||||
&mut self,
|
&mut self,
|
||||||
settings: &Settings,
|
settings: &Settings,
|
||||||
workspace_files: &IndexSet<ModuleSpecifier>,
|
workspace_files: &IndexSet<ModuleSpecifier>,
|
||||||
file_fetcher: &Arc<FileFetcher>,
|
file_fetcher: &Arc<CliFileFetcher>,
|
||||||
) {
|
) {
|
||||||
lsp_log!("Refreshing configuration tree...");
|
lsp_log!("Refreshing configuration tree...");
|
||||||
// since we're resolving a workspace multiple times in different
|
// since we're resolving a workspace multiple times in different
|
||||||
// folders, we want to cache all the lookups and config files across
|
// folders, we want to cache all the lookups and config files across
|
||||||
// ConfigData::load calls
|
// ConfigData::load calls
|
||||||
let cached_fs = CachedDenoConfigFs::default();
|
|
||||||
let deno_json_cache = DenoJsonMemCache::default();
|
let deno_json_cache = DenoJsonMemCache::default();
|
||||||
let pkg_json_cache = PackageJsonMemCache::default();
|
let pkg_json_cache = PackageJsonMemCache::default();
|
||||||
let workspace_cache = WorkspaceMemCache::default();
|
let workspace_cache = WorkspaceMemCache::default();
|
||||||
|
@ -1850,7 +1860,6 @@ impl ConfigTree {
|
||||||
folder_uri,
|
folder_uri,
|
||||||
settings,
|
settings,
|
||||||
file_fetcher,
|
file_fetcher,
|
||||||
&cached_fs,
|
|
||||||
&deno_json_cache,
|
&deno_json_cache,
|
||||||
&pkg_json_cache,
|
&pkg_json_cache,
|
||||||
&workspace_cache,
|
&workspace_cache,
|
||||||
|
@ -1881,7 +1890,6 @@ impl ConfigTree {
|
||||||
&scope,
|
&scope,
|
||||||
settings,
|
settings,
|
||||||
file_fetcher,
|
file_fetcher,
|
||||||
&cached_fs,
|
|
||||||
&deno_json_cache,
|
&deno_json_cache,
|
||||||
&pkg_json_cache,
|
&pkg_json_cache,
|
||||||
&workspace_cache,
|
&workspace_cache,
|
||||||
|
@ -1898,7 +1906,6 @@ impl ConfigTree {
|
||||||
member_scope,
|
member_scope,
|
||||||
settings,
|
settings,
|
||||||
file_fetcher,
|
file_fetcher,
|
||||||
&cached_fs,
|
|
||||||
&deno_json_cache,
|
&deno_json_cache,
|
||||||
&pkg_json_cache,
|
&pkg_json_cache,
|
||||||
&workspace_cache,
|
&workspace_cache,
|
||||||
|
@ -1913,21 +1920,24 @@ impl ConfigTree {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub async fn inject_config_file(&mut self, config_file: ConfigFile) {
|
pub async fn inject_config_file(&mut self, config_file: ConfigFile) {
|
||||||
|
use sys_traits::FsCreateDirAll;
|
||||||
|
use sys_traits::FsWrite;
|
||||||
|
|
||||||
let scope = config_file.specifier.join(".").unwrap();
|
let scope = config_file.specifier.join(".").unwrap();
|
||||||
let json_text = serde_json::to_string(&config_file.json).unwrap();
|
let json_text = serde_json::to_string(&config_file.json).unwrap();
|
||||||
let test_fs = deno_runtime::deno_fs::InMemoryFs::default();
|
let memory_sys = sys_traits::impls::InMemorySys::default();
|
||||||
let config_path = url_to_file_path(&config_file.specifier).unwrap();
|
let config_path = url_to_file_path(&config_file.specifier).unwrap();
|
||||||
test_fs.setup_text_files(vec![(
|
memory_sys
|
||||||
config_path.to_string_lossy().to_string(),
|
.fs_create_dir_all(config_path.parent().unwrap())
|
||||||
json_text,
|
.unwrap();
|
||||||
)]);
|
memory_sys.fs_write(&config_path, json_text).unwrap();
|
||||||
let workspace_dir = Arc::new(
|
let workspace_dir = Arc::new(
|
||||||
WorkspaceDirectory::discover(
|
WorkspaceDirectory::discover(
|
||||||
|
&memory_sys,
|
||||||
deno_config::workspace::WorkspaceDiscoverStart::ConfigFile(
|
deno_config::workspace::WorkspaceDiscoverStart::ConfigFile(
|
||||||
&config_path,
|
&config_path,
|
||||||
),
|
),
|
||||||
&deno_config::workspace::WorkspaceDiscoverOptions {
|
&deno_config::workspace::WorkspaceDiscoverOptions {
|
||||||
fs: &crate::args::deno_json::DenoConfigFsAdapter(&test_fs),
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
@ -2000,11 +2010,14 @@ fn resolve_lockfile_from_path(
|
||||||
lockfile_path: PathBuf,
|
lockfile_path: PathBuf,
|
||||||
frozen: bool,
|
frozen: bool,
|
||||||
) -> Option<CliLockfile> {
|
) -> Option<CliLockfile> {
|
||||||
match CliLockfile::read_from_path(CliLockfileReadFromPathOptions {
|
match CliLockfile::read_from_path(
|
||||||
|
&CliSys::default(),
|
||||||
|
CliLockfileReadFromPathOptions {
|
||||||
file_path: lockfile_path,
|
file_path: lockfile_path,
|
||||||
frozen,
|
frozen,
|
||||||
skip_write: false,
|
skip_write: false,
|
||||||
}) {
|
},
|
||||||
|
) {
|
||||||
Ok(value) => {
|
Ok(value) => {
|
||||||
if value.filename.exists() {
|
if value.filename.exists() {
|
||||||
if let Ok(specifier) = ModuleSpecifier::from_file_path(&value.filename)
|
if let Ok(specifier) = ModuleSpecifier::from_file_path(&value.filename)
|
||||||
|
@ -2061,81 +2074,8 @@ impl deno_config::workspace::WorkspaceCache for WorkspaceMemCache {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
struct CachedFsItems<T: Clone> {
|
|
||||||
items: HashMap<PathBuf, Result<T, std::io::Error>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Clone> CachedFsItems<T> {
|
|
||||||
pub fn get(
|
|
||||||
&mut self,
|
|
||||||
path: &Path,
|
|
||||||
action: impl FnOnce(&Path) -> Result<T, std::io::Error>,
|
|
||||||
) -> Result<T, std::io::Error> {
|
|
||||||
let value = if let Some(value) = self.items.get(path) {
|
|
||||||
value
|
|
||||||
} else {
|
|
||||||
let value = action(path);
|
|
||||||
// just in case this gets really large for some reason
|
|
||||||
if self.items.len() == 16_384 {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
self.items.insert(path.to_owned(), value);
|
|
||||||
self.items.get(path).unwrap()
|
|
||||||
};
|
|
||||||
value
|
|
||||||
.as_ref()
|
|
||||||
.map(|v| (*v).clone())
|
|
||||||
.map_err(|e| std::io::Error::new(e.kind(), e.to_string()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
struct InnerData {
|
|
||||||
stat_calls: CachedFsItems<deno_config::fs::FsMetadata>,
|
|
||||||
read_to_string_calls: CachedFsItems<Cow<'static, str>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
struct CachedDenoConfigFs(Mutex<InnerData>);
|
|
||||||
|
|
||||||
impl DenoConfigFs for CachedDenoConfigFs {
|
|
||||||
fn stat_sync(
|
|
||||||
&self,
|
|
||||||
path: &Path,
|
|
||||||
) -> Result<deno_config::fs::FsMetadata, std::io::Error> {
|
|
||||||
self
|
|
||||||
.0
|
|
||||||
.lock()
|
|
||||||
.stat_calls
|
|
||||||
.get(path, |path| RealDenoConfigFs.stat_sync(path))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn read_to_string_lossy(
|
|
||||||
&self,
|
|
||||||
path: &Path,
|
|
||||||
) -> Result<Cow<'static, str>, std::io::Error> {
|
|
||||||
self
|
|
||||||
.0
|
|
||||||
.lock()
|
|
||||||
.read_to_string_calls
|
|
||||||
.get(path, |path| RealDenoConfigFs.read_to_string_lossy(path))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn read_dir(
|
|
||||||
&self,
|
|
||||||
path: &Path,
|
|
||||||
) -> Result<Vec<deno_config::fs::FsDirEntry>, std::io::Error> {
|
|
||||||
// no need to cache these because the workspace cache will ensure
|
|
||||||
// we only do read_dir calls once (read_dirs are only used for
|
|
||||||
// npm workspace resolution)
|
|
||||||
RealDenoConfigFs.read_dir(path)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use deno_config::deno_json::ConfigParseOptions;
|
|
||||||
use deno_core::resolve_url;
|
use deno_core::resolve_url;
|
||||||
use deno_core::serde_json;
|
use deno_core::serde_json;
|
||||||
use deno_core::serde_json::json;
|
use deno_core::serde_json::json;
|
||||||
|
@ -2292,6 +2232,7 @@ mod tests {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
suggestion_actions: SuggestionActionsSettings { enabled: true },
|
||||||
update_imports_on_file_move: UpdateImportsOnFileMoveOptions {
|
update_imports_on_file_move: UpdateImportsOnFileMoveOptions {
|
||||||
enabled: UpdateImportsOnFileMoveEnabled::Prompt
|
enabled: UpdateImportsOnFileMoveEnabled::Prompt
|
||||||
}
|
}
|
||||||
|
@ -2338,6 +2279,7 @@ mod tests {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
suggestion_actions: SuggestionActionsSettings { enabled: true },
|
||||||
update_imports_on_file_move: UpdateImportsOnFileMoveOptions {
|
update_imports_on_file_move: UpdateImportsOnFileMoveOptions {
|
||||||
enabled: UpdateImportsOnFileMoveEnabled::Prompt
|
enabled: UpdateImportsOnFileMoveEnabled::Prompt
|
||||||
}
|
}
|
||||||
|
@ -2407,12 +2349,7 @@ mod tests {
|
||||||
config
|
config
|
||||||
.tree
|
.tree
|
||||||
.inject_config_file(
|
.inject_config_file(
|
||||||
ConfigFile::new(
|
ConfigFile::new("{}", root_uri.join("deno.json").unwrap()).unwrap(),
|
||||||
"{}",
|
|
||||||
root_uri.join("deno.json").unwrap(),
|
|
||||||
&ConfigParseOptions::default(),
|
|
||||||
)
|
|
||||||
.unwrap(),
|
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert!(config.specifier_enabled(&root_uri));
|
assert!(config.specifier_enabled(&root_uri));
|
||||||
|
@ -2468,7 +2405,6 @@ mod tests {
|
||||||
})
|
})
|
||||||
.to_string(),
|
.to_string(),
|
||||||
root_uri.join("deno.json").unwrap(),
|
root_uri.join("deno.json").unwrap(),
|
||||||
&ConfigParseOptions::default(),
|
|
||||||
)
|
)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
)
|
)
|
||||||
|
@ -2494,7 +2430,6 @@ mod tests {
|
||||||
})
|
})
|
||||||
.to_string(),
|
.to_string(),
|
||||||
root_uri.join("deno.json").unwrap(),
|
root_uri.join("deno.json").unwrap(),
|
||||||
&ConfigParseOptions::default(),
|
|
||||||
)
|
)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
)
|
)
|
||||||
|
@ -2512,7 +2447,6 @@ mod tests {
|
||||||
})
|
})
|
||||||
.to_string(),
|
.to_string(),
|
||||||
root_uri.join("deno.json").unwrap(),
|
root_uri.join("deno.json").unwrap(),
|
||||||
&ConfigParseOptions::default(),
|
|
||||||
)
|
)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,30 +1,11 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
use super::analysis;
|
use std::collections::HashMap;
|
||||||
use super::client::Client;
|
use std::collections::HashSet;
|
||||||
use super::config::Config;
|
use std::path::PathBuf;
|
||||||
use super::documents;
|
use std::sync::atomic::AtomicUsize;
|
||||||
use super::documents::Document;
|
use std::sync::Arc;
|
||||||
use super::documents::Documents;
|
use std::thread;
|
||||||
use super::documents::DocumentsFilter;
|
|
||||||
use super::language_server;
|
|
||||||
use super::language_server::StateSnapshot;
|
|
||||||
use super::performance::Performance;
|
|
||||||
use super::tsc;
|
|
||||||
use super::tsc::TsServer;
|
|
||||||
use super::urls::uri_parse_unencoded;
|
|
||||||
use super::urls::url_to_uri;
|
|
||||||
use super::urls::LspUrlMap;
|
|
||||||
|
|
||||||
use crate::graph_util;
|
|
||||||
use crate::graph_util::enhanced_resolution_error_message;
|
|
||||||
use crate::lsp::lsp_custom::DiagnosticBatchNotificationParams;
|
|
||||||
use crate::resolver::CliSloppyImportsResolver;
|
|
||||||
use crate::resolver::SloppyImportsCachedFs;
|
|
||||||
use crate::tools::lint::CliLinter;
|
|
||||||
use crate::tools::lint::CliLinterOptions;
|
|
||||||
use crate::tools::lint::LintRuleProvider;
|
|
||||||
use crate::util::path::to_percent_decoded_str;
|
|
||||||
|
|
||||||
use deno_ast::MediaType;
|
use deno_ast::MediaType;
|
||||||
use deno_config::deno_json::LintConfig;
|
use deno_config::deno_json::LintConfig;
|
||||||
|
@ -44,29 +25,50 @@ use deno_graph::source::ResolveError;
|
||||||
use deno_graph::Resolution;
|
use deno_graph::Resolution;
|
||||||
use deno_graph::ResolutionError;
|
use deno_graph::ResolutionError;
|
||||||
use deno_graph::SpecifierError;
|
use deno_graph::SpecifierError;
|
||||||
|
use deno_lint::linter::LintConfig as DenoLintConfig;
|
||||||
|
use deno_resolver::sloppy_imports::SloppyImportsCachedFs;
|
||||||
use deno_resolver::sloppy_imports::SloppyImportsResolution;
|
use deno_resolver::sloppy_imports::SloppyImportsResolution;
|
||||||
use deno_resolver::sloppy_imports::SloppyImportsResolutionKind;
|
use deno_resolver::sloppy_imports::SloppyImportsResolutionKind;
|
||||||
use deno_runtime::deno_fs;
|
|
||||||
use deno_runtime::deno_node;
|
use deno_runtime::deno_node;
|
||||||
use deno_runtime::tokio_util::create_basic_runtime;
|
use deno_runtime::tokio_util::create_basic_runtime;
|
||||||
use deno_semver::jsr::JsrPackageReqReference;
|
use deno_semver::jsr::JsrPackageReqReference;
|
||||||
use deno_semver::npm::NpmPackageReqReference;
|
use deno_semver::npm::NpmPackageReqReference;
|
||||||
use deno_semver::package::PackageReq;
|
use deno_semver::package::PackageReq;
|
||||||
use import_map::ImportMap;
|
use import_map::ImportMap;
|
||||||
use import_map::ImportMapError;
|
use import_map::ImportMapErrorKind;
|
||||||
use log::error;
|
use log::error;
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::collections::HashSet;
|
|
||||||
use std::path::PathBuf;
|
|
||||||
use std::sync::atomic::AtomicUsize;
|
|
||||||
use std::sync::Arc;
|
|
||||||
use std::thread;
|
|
||||||
use tokio::sync::mpsc;
|
use tokio::sync::mpsc;
|
||||||
use tokio::sync::Mutex;
|
use tokio::sync::Mutex;
|
||||||
use tokio::time::Duration;
|
use tokio::time::Duration;
|
||||||
use tokio_util::sync::CancellationToken;
|
use tokio_util::sync::CancellationToken;
|
||||||
use tower_lsp::lsp_types as lsp;
|
use tower_lsp::lsp_types as lsp;
|
||||||
|
|
||||||
|
use super::analysis;
|
||||||
|
use super::client::Client;
|
||||||
|
use super::config::Config;
|
||||||
|
use super::documents;
|
||||||
|
use super::documents::Document;
|
||||||
|
use super::documents::Documents;
|
||||||
|
use super::documents::DocumentsFilter;
|
||||||
|
use super::language_server;
|
||||||
|
use super::language_server::StateSnapshot;
|
||||||
|
use super::performance::Performance;
|
||||||
|
use super::tsc;
|
||||||
|
use super::tsc::TsServer;
|
||||||
|
use super::urls::uri_parse_unencoded;
|
||||||
|
use super::urls::url_to_uri;
|
||||||
|
use super::urls::LspUrlMap;
|
||||||
|
use crate::graph_util;
|
||||||
|
use crate::graph_util::enhanced_resolution_error_message;
|
||||||
|
use crate::lsp::lsp_custom::DiagnosticBatchNotificationParams;
|
||||||
|
use crate::resolver::CliSloppyImportsResolver;
|
||||||
|
use crate::sys::CliSys;
|
||||||
|
use crate::tools::lint::CliLinter;
|
||||||
|
use crate::tools::lint::CliLinterOptions;
|
||||||
|
use crate::tools::lint::LintRuleProvider;
|
||||||
|
use crate::tsc::DiagnosticCategory;
|
||||||
|
use crate::util::path::to_percent_decoded_str;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct DiagnosticServerUpdateMessage {
|
pub struct DiagnosticServerUpdateMessage {
|
||||||
pub snapshot: Arc<StateSnapshot>,
|
pub snapshot: Arc<StateSnapshot>,
|
||||||
|
@ -833,7 +835,7 @@ fn generate_lint_diagnostics(
|
||||||
lint_rule_provider.resolve_lint_rules(Default::default(), None)
|
lint_rule_provider.resolve_lint_rules(Default::default(), None)
|
||||||
},
|
},
|
||||||
fix: false,
|
fix: false,
|
||||||
deno_lint_config: deno_lint::linter::LintConfig {
|
deno_lint_config: DenoLintConfig {
|
||||||
default_jsx_factory: None,
|
default_jsx_factory: None,
|
||||||
default_jsx_fragment_factory: None,
|
default_jsx_fragment_factory: None,
|
||||||
},
|
},
|
||||||
|
@ -906,8 +908,22 @@ async fn generate_ts_diagnostics(
|
||||||
} else {
|
} else {
|
||||||
Default::default()
|
Default::default()
|
||||||
};
|
};
|
||||||
for (specifier_str, ts_json_diagnostics) in ts_diagnostics_map {
|
for (specifier_str, mut ts_json_diagnostics) in ts_diagnostics_map {
|
||||||
let specifier = resolve_url(&specifier_str)?;
|
let specifier = resolve_url(&specifier_str)?;
|
||||||
|
let suggestion_actions_settings = snapshot
|
||||||
|
.config
|
||||||
|
.language_settings_for_specifier(&specifier)
|
||||||
|
.map(|s| s.suggestion_actions.clone())
|
||||||
|
.unwrap_or_default();
|
||||||
|
if !suggestion_actions_settings.enabled {
|
||||||
|
ts_json_diagnostics.retain(|d| {
|
||||||
|
d.category != DiagnosticCategory::Suggestion
|
||||||
|
// Still show deprecated and unused diagnostics.
|
||||||
|
// https://github.com/microsoft/vscode/blob/ce50bd4876af457f64d83cfd956bc916535285f4/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts#L113-L114
|
||||||
|
|| d.reports_deprecated == Some(true)
|
||||||
|
|| d.reports_unnecessary == Some(true)
|
||||||
|
});
|
||||||
|
}
|
||||||
let version = snapshot
|
let version = snapshot
|
||||||
.documents
|
.documents
|
||||||
.get(&specifier)
|
.get(&specifier)
|
||||||
|
@ -1265,7 +1281,7 @@ impl DenoDiagnostic {
|
||||||
Self::NotInstalledNpm(pkg_req, specifier) => (lsp::DiagnosticSeverity::ERROR, format!("npm package \"{pkg_req}\" is not installed or doesn't exist."), Some(json!({ "specifier": specifier }))),
|
Self::NotInstalledNpm(pkg_req, specifier) => (lsp::DiagnosticSeverity::ERROR, format!("npm package \"{pkg_req}\" is not installed or doesn't exist."), Some(json!({ "specifier": specifier }))),
|
||||||
Self::NoLocal(specifier) => {
|
Self::NoLocal(specifier) => {
|
||||||
let maybe_sloppy_resolution = CliSloppyImportsResolver::new(
|
let maybe_sloppy_resolution = CliSloppyImportsResolver::new(
|
||||||
SloppyImportsCachedFs::new(Arc::new(deno_fs::RealFs))
|
SloppyImportsCachedFs::new(CliSys::default())
|
||||||
).resolve(specifier, SloppyImportsResolutionKind::Execution);
|
).resolve(specifier, SloppyImportsResolutionKind::Execution);
|
||||||
let data = maybe_sloppy_resolution.as_ref().map(|res| {
|
let data = maybe_sloppy_resolution.as_ref().map(|res| {
|
||||||
json!({
|
json!({
|
||||||
|
@ -1281,8 +1297,8 @@ impl DenoDiagnostic {
|
||||||
let mut message;
|
let mut message;
|
||||||
message = enhanced_resolution_error_message(err);
|
message = enhanced_resolution_error_message(err);
|
||||||
if let deno_graph::ResolutionError::ResolverError {error, ..} = err{
|
if let deno_graph::ResolutionError::ResolverError {error, ..} = err{
|
||||||
if let ResolveError::Other(resolve_error, ..) = (*error).as_ref() {
|
if let ResolveError::ImportMap(importmap) = (*error).as_ref() {
|
||||||
if let Some(ImportMapError::UnmappedBareSpecifier(specifier, _)) = resolve_error.downcast_ref::<ImportMapError>() {
|
if let ImportMapErrorKind::UnmappedBareSpecifier(specifier, _) = &**importmap {
|
||||||
if specifier.chars().next().unwrap_or('\0') == '@'{
|
if specifier.chars().next().unwrap_or('\0') == '@'{
|
||||||
let hint = format!("\nHint: Use [deno add {}] to add the dependency.", specifier);
|
let hint = format!("\nHint: Use [deno add {}] to add the dependency.", specifier);
|
||||||
message.push_str(hint.as_str());
|
message.push_str(hint.as_str());
|
||||||
|
@ -1630,6 +1646,12 @@ fn generate_deno_diagnostics(
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use deno_config::deno_json::ConfigFile;
|
||||||
|
use pretty_assertions::assert_eq;
|
||||||
|
use test_util::TempDir;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::lsp::cache::LspCache;
|
use crate::lsp::cache::LspCache;
|
||||||
use crate::lsp::config::Config;
|
use crate::lsp::config::Config;
|
||||||
|
@ -1640,11 +1662,6 @@ mod tests {
|
||||||
use crate::lsp::language_server::StateSnapshot;
|
use crate::lsp::language_server::StateSnapshot;
|
||||||
use crate::lsp::resolver::LspResolver;
|
use crate::lsp::resolver::LspResolver;
|
||||||
|
|
||||||
use deno_config::deno_json::ConfigFile;
|
|
||||||
use pretty_assertions::assert_eq;
|
|
||||||
use std::sync::Arc;
|
|
||||||
use test_util::TempDir;
|
|
||||||
|
|
||||||
fn mock_config() -> Config {
|
fn mock_config() -> Config {
|
||||||
let root_url = resolve_url("file:///").unwrap();
|
let root_url = resolve_url("file:///").unwrap();
|
||||||
let root_uri = url_to_uri(&root_url).unwrap();
|
let root_uri = url_to_uri(&root_url).unwrap();
|
||||||
|
@ -1678,12 +1695,7 @@ mod tests {
|
||||||
let mut config = Config::new_with_roots([root_uri.clone()]);
|
let mut config = Config::new_with_roots([root_uri.clone()]);
|
||||||
if let Some((relative_path, json_string)) = maybe_import_map {
|
if let Some((relative_path, json_string)) = maybe_import_map {
|
||||||
let base_url = root_uri.join(relative_path).unwrap();
|
let base_url = root_uri.join(relative_path).unwrap();
|
||||||
let config_file = ConfigFile::new(
|
let config_file = ConfigFile::new(json_string, base_url).unwrap();
|
||||||
json_string,
|
|
||||||
base_url,
|
|
||||||
&deno_config::deno_json::ConfigParseOptions::default(),
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
config.tree.inject_config_file(config_file).await;
|
config.tree.inject_config_file(config_file).await;
|
||||||
}
|
}
|
||||||
let resolver =
|
let resolver =
|
||||||
|
|
|
@ -1,41 +1,5 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
use super::cache::calculate_fs_version;
|
|
||||||
use super::cache::LspCache;
|
|
||||||
use super::config::Config;
|
|
||||||
use super::resolver::LspResolver;
|
|
||||||
use super::resolver::ScopeDepInfo;
|
|
||||||
use super::resolver::SingleReferrerGraphResolver;
|
|
||||||
use super::testing::TestCollector;
|
|
||||||
use super::testing::TestModule;
|
|
||||||
use super::text::LineIndex;
|
|
||||||
use super::tsc;
|
|
||||||
use super::tsc::AssetDocument;
|
|
||||||
|
|
||||||
use crate::graph_util::CliJsrUrlProvider;
|
|
||||||
|
|
||||||
use dashmap::DashMap;
|
|
||||||
use deno_ast::swc::visit::VisitWith;
|
|
||||||
use deno_ast::MediaType;
|
|
||||||
use deno_ast::ParsedSource;
|
|
||||||
use deno_ast::SourceTextInfo;
|
|
||||||
use deno_core::error::custom_error;
|
|
||||||
use deno_core::error::AnyError;
|
|
||||||
use deno_core::futures::future;
|
|
||||||
use deno_core::futures::future::Shared;
|
|
||||||
use deno_core::futures::FutureExt;
|
|
||||||
use deno_core::parking_lot::Mutex;
|
|
||||||
use deno_core::ModuleSpecifier;
|
|
||||||
use deno_graph::Resolution;
|
|
||||||
use deno_path_util::url_to_file_path;
|
|
||||||
use deno_runtime::deno_node;
|
|
||||||
use deno_semver::jsr::JsrPackageReqReference;
|
|
||||||
use deno_semver::npm::NpmPackageReqReference;
|
|
||||||
use deno_semver::package::PackageReq;
|
|
||||||
use indexmap::IndexMap;
|
|
||||||
use indexmap::IndexSet;
|
|
||||||
use node_resolver::NodeResolutionKind;
|
|
||||||
use node_resolver::ResolutionMode;
|
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
@ -48,8 +12,44 @@ use std::str::FromStr;
|
||||||
use std::sync::atomic::AtomicBool;
|
use std::sync::atomic::AtomicBool;
|
||||||
use std::sync::atomic::Ordering;
|
use std::sync::atomic::Ordering;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use dashmap::DashMap;
|
||||||
|
use deno_ast::swc::visit::VisitWith;
|
||||||
|
use deno_ast::MediaType;
|
||||||
|
use deno_ast::ParsedSource;
|
||||||
|
use deno_ast::SourceTextInfo;
|
||||||
|
use deno_core::error::AnyError;
|
||||||
|
use deno_core::futures::future;
|
||||||
|
use deno_core::futures::future::Shared;
|
||||||
|
use deno_core::futures::FutureExt;
|
||||||
|
use deno_core::parking_lot::Mutex;
|
||||||
|
use deno_core::ModuleSpecifier;
|
||||||
|
use deno_error::JsErrorBox;
|
||||||
|
use deno_graph::Resolution;
|
||||||
|
use deno_path_util::url_to_file_path;
|
||||||
|
use deno_runtime::deno_node;
|
||||||
|
use deno_semver::jsr::JsrPackageReqReference;
|
||||||
|
use deno_semver::npm::NpmPackageReqReference;
|
||||||
|
use deno_semver::package::PackageReq;
|
||||||
|
use indexmap::IndexMap;
|
||||||
|
use indexmap::IndexSet;
|
||||||
|
use node_resolver::NodeResolutionKind;
|
||||||
|
use node_resolver::ResolutionMode;
|
||||||
use tower_lsp::lsp_types as lsp;
|
use tower_lsp::lsp_types as lsp;
|
||||||
|
|
||||||
|
use super::cache::calculate_fs_version;
|
||||||
|
use super::cache::LspCache;
|
||||||
|
use super::config::Config;
|
||||||
|
use super::resolver::LspResolver;
|
||||||
|
use super::resolver::ScopeDepInfo;
|
||||||
|
use super::resolver::SingleReferrerGraphResolver;
|
||||||
|
use super::testing::TestCollector;
|
||||||
|
use super::testing::TestModule;
|
||||||
|
use super::text::LineIndex;
|
||||||
|
use super::tsc;
|
||||||
|
use super::tsc::AssetDocument;
|
||||||
|
use crate::graph_util::CliJsrUrlProvider;
|
||||||
|
|
||||||
pub const DOCUMENT_SCHEMES: [&str; 5] =
|
pub const DOCUMENT_SCHEMES: [&str; 5] =
|
||||||
["data", "blob", "file", "http", "https"];
|
["data", "blob", "file", "http", "https"];
|
||||||
|
|
||||||
|
@ -64,6 +64,9 @@ pub enum LanguageId {
|
||||||
Markdown,
|
Markdown,
|
||||||
Html,
|
Html,
|
||||||
Css,
|
Css,
|
||||||
|
Scss,
|
||||||
|
Sass,
|
||||||
|
Less,
|
||||||
Yaml,
|
Yaml,
|
||||||
Sql,
|
Sql,
|
||||||
Svelte,
|
Svelte,
|
||||||
|
@ -86,6 +89,9 @@ impl LanguageId {
|
||||||
LanguageId::Markdown => Some("md"),
|
LanguageId::Markdown => Some("md"),
|
||||||
LanguageId::Html => Some("html"),
|
LanguageId::Html => Some("html"),
|
||||||
LanguageId::Css => Some("css"),
|
LanguageId::Css => Some("css"),
|
||||||
|
LanguageId::Scss => Some("scss"),
|
||||||
|
LanguageId::Sass => Some("sass"),
|
||||||
|
LanguageId::Less => Some("less"),
|
||||||
LanguageId::Yaml => Some("yaml"),
|
LanguageId::Yaml => Some("yaml"),
|
||||||
LanguageId::Sql => Some("sql"),
|
LanguageId::Sql => Some("sql"),
|
||||||
LanguageId::Svelte => Some("svelte"),
|
LanguageId::Svelte => Some("svelte"),
|
||||||
|
@ -107,6 +113,9 @@ impl LanguageId {
|
||||||
LanguageId::Markdown => Some("text/markdown"),
|
LanguageId::Markdown => Some("text/markdown"),
|
||||||
LanguageId::Html => Some("text/html"),
|
LanguageId::Html => Some("text/html"),
|
||||||
LanguageId::Css => Some("text/css"),
|
LanguageId::Css => Some("text/css"),
|
||||||
|
LanguageId::Scss => None,
|
||||||
|
LanguageId::Sass => None,
|
||||||
|
LanguageId::Less => None,
|
||||||
LanguageId::Yaml => Some("application/yaml"),
|
LanguageId::Yaml => Some("application/yaml"),
|
||||||
LanguageId::Sql => None,
|
LanguageId::Sql => None,
|
||||||
LanguageId::Svelte => None,
|
LanguageId::Svelte => None,
|
||||||
|
@ -140,6 +149,9 @@ impl FromStr for LanguageId {
|
||||||
"markdown" => Ok(Self::Markdown),
|
"markdown" => Ok(Self::Markdown),
|
||||||
"html" => Ok(Self::Html),
|
"html" => Ok(Self::Html),
|
||||||
"css" => Ok(Self::Css),
|
"css" => Ok(Self::Css),
|
||||||
|
"scss" => Ok(Self::Scss),
|
||||||
|
"sass" => Ok(Self::Sass),
|
||||||
|
"less" => Ok(Self::Less),
|
||||||
"yaml" => Ok(Self::Yaml),
|
"yaml" => Ok(Self::Yaml),
|
||||||
"sql" => Ok(Self::Sql),
|
"sql" => Ok(Self::Sql),
|
||||||
"svelte" => Ok(Self::Svelte),
|
"svelte" => Ok(Self::Svelte),
|
||||||
|
@ -251,6 +263,13 @@ impl AssetOrDocument {
|
||||||
pub fn document_lsp_version(&self) -> Option<i32> {
|
pub fn document_lsp_version(&self) -> Option<i32> {
|
||||||
self.document().and_then(|d| d.maybe_lsp_version())
|
self.document().and_then(|d| d.maybe_lsp_version())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn resolution_mode(&self) -> ResolutionMode {
|
||||||
|
match self {
|
||||||
|
AssetOrDocument::Asset(_) => ResolutionMode::Import,
|
||||||
|
AssetOrDocument::Document(d) => d.resolution_mode(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type ModuleResult = Result<deno_graph::JsModule, deno_graph::ModuleGraphError>;
|
type ModuleResult = Result<deno_graph::JsModule, deno_graph::ModuleGraphError>;
|
||||||
|
@ -461,7 +480,7 @@ impl Document {
|
||||||
let is_cjs_resolver =
|
let is_cjs_resolver =
|
||||||
resolver.as_is_cjs_resolver(self.file_referrer.as_ref());
|
resolver.as_is_cjs_resolver(self.file_referrer.as_ref());
|
||||||
let npm_resolver =
|
let npm_resolver =
|
||||||
resolver.create_graph_npm_resolver(self.file_referrer.as_ref());
|
resolver.as_graph_npm_resolver(self.file_referrer.as_ref());
|
||||||
let config_data = resolver.as_config_data(self.file_referrer.as_ref());
|
let config_data = resolver.as_config_data(self.file_referrer.as_ref());
|
||||||
let jsx_import_source_config =
|
let jsx_import_source_config =
|
||||||
config_data.and_then(|d| d.maybe_jsx_import_source_config());
|
config_data.and_then(|d| d.maybe_jsx_import_source_config());
|
||||||
|
@ -484,7 +503,7 @@ impl Document {
|
||||||
s,
|
s,
|
||||||
&CliJsrUrlProvider,
|
&CliJsrUrlProvider,
|
||||||
Some(&resolver),
|
Some(&resolver),
|
||||||
Some(&npm_resolver),
|
Some(npm_resolver.as_ref()),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
@ -494,7 +513,7 @@ impl Document {
|
||||||
Arc::new(d.with_new_resolver(
|
Arc::new(d.with_new_resolver(
|
||||||
&CliJsrUrlProvider,
|
&CliJsrUrlProvider,
|
||||||
Some(&resolver),
|
Some(&resolver),
|
||||||
Some(&npm_resolver),
|
Some(npm_resolver.as_ref()),
|
||||||
))
|
))
|
||||||
});
|
});
|
||||||
is_script = self.is_script;
|
is_script = self.is_script;
|
||||||
|
@ -1062,7 +1081,7 @@ impl Documents {
|
||||||
.or_else(|| self.file_system_docs.remove_document(specifier))
|
.or_else(|| self.file_system_docs.remove_document(specifier))
|
||||||
.map(Ok)
|
.map(Ok)
|
||||||
.unwrap_or_else(|| {
|
.unwrap_or_else(|| {
|
||||||
Err(custom_error(
|
Err(JsErrorBox::new(
|
||||||
"NotFound",
|
"NotFound",
|
||||||
format!("The specifier \"{specifier}\" was not found."),
|
format!("The specifier \"{specifier}\" was not found."),
|
||||||
))
|
))
|
||||||
|
@ -1683,7 +1702,7 @@ fn analyze_module(
|
||||||
) -> (ModuleResult, ResolutionMode) {
|
) -> (ModuleResult, ResolutionMode) {
|
||||||
match parsed_source_result {
|
match parsed_source_result {
|
||||||
Ok(parsed_source) => {
|
Ok(parsed_source) => {
|
||||||
let npm_resolver = resolver.create_graph_npm_resolver(file_referrer);
|
let npm_resolver = resolver.as_graph_npm_resolver(file_referrer);
|
||||||
let cli_resolver = resolver.as_cli_resolver(file_referrer);
|
let cli_resolver = resolver.as_cli_resolver(file_referrer);
|
||||||
let is_cjs_resolver = resolver.as_is_cjs_resolver(file_referrer);
|
let is_cjs_resolver = resolver.as_is_cjs_resolver(file_referrer);
|
||||||
let config_data = resolver.as_config_data(file_referrer);
|
let config_data = resolver.as_config_data(file_referrer);
|
||||||
|
@ -1712,7 +1731,7 @@ fn analyze_module(
|
||||||
file_system: &deno_graph::source::NullFileSystem,
|
file_system: &deno_graph::source::NullFileSystem,
|
||||||
jsr_url_provider: &CliJsrUrlProvider,
|
jsr_url_provider: &CliJsrUrlProvider,
|
||||||
maybe_resolver: Some(&resolver),
|
maybe_resolver: Some(&resolver),
|
||||||
maybe_npm_resolver: Some(&npm_resolver),
|
maybe_npm_resolver: Some(npm_resolver.as_ref()),
|
||||||
},
|
},
|
||||||
)),
|
)),
|
||||||
module_resolution_mode,
|
module_resolution_mode,
|
||||||
|
@ -1747,16 +1766,15 @@ fn bytes_to_content(
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
|
||||||
use crate::lsp::cache::LspCache;
|
|
||||||
|
|
||||||
use deno_config::deno_json::ConfigFile;
|
use deno_config::deno_json::ConfigFile;
|
||||||
use deno_config::deno_json::ConfigParseOptions;
|
|
||||||
use deno_core::serde_json;
|
use deno_core::serde_json;
|
||||||
use deno_core::serde_json::json;
|
use deno_core::serde_json::json;
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
use test_util::TempDir;
|
use test_util::TempDir;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
use crate::lsp::cache::LspCache;
|
||||||
|
|
||||||
async fn setup() -> (Documents, LspCache, TempDir) {
|
async fn setup() -> (Documents, LspCache, TempDir) {
|
||||||
let temp_dir = TempDir::new();
|
let temp_dir = TempDir::new();
|
||||||
temp_dir.create_dir_all(".deno_dir");
|
temp_dir.create_dir_all(".deno_dir");
|
||||||
|
@ -1905,7 +1923,6 @@ console.log(b, "hello deno");
|
||||||
})
|
})
|
||||||
.to_string(),
|
.to_string(),
|
||||||
config.root_uri().unwrap().join("deno.json").unwrap(),
|
config.root_uri().unwrap().join("deno.json").unwrap(),
|
||||||
&ConfigParseOptions::default(),
|
|
||||||
)
|
)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
)
|
)
|
||||||
|
@ -1949,7 +1966,6 @@ console.log(b, "hello deno");
|
||||||
})
|
})
|
||||||
.to_string(),
|
.to_string(),
|
||||||
config.root_uri().unwrap().join("deno.json").unwrap(),
|
config.root_uri().unwrap().join("deno.json").unwrap(),
|
||||||
&ConfigParseOptions::default(),
|
|
||||||
)
|
)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
use crate::args::jsr_api_url;
|
|
||||||
use crate::args::jsr_url;
|
|
||||||
use crate::file_fetcher::FileFetcher;
|
|
||||||
use crate::jsr::partial_jsr_package_version_info_from_slice;
|
|
||||||
use crate::jsr::JsrFetchResolver;
|
|
||||||
use dashmap::DashMap;
|
use dashmap::DashMap;
|
||||||
use deno_cache_dir::HttpCache;
|
use deno_cache_dir::HttpCache;
|
||||||
use deno_core::anyhow::anyhow;
|
use deno_core::anyhow::anyhow;
|
||||||
|
@ -17,13 +15,18 @@ use deno_graph::ModuleSpecifier;
|
||||||
use deno_semver::jsr::JsrPackageReqReference;
|
use deno_semver::jsr::JsrPackageReqReference;
|
||||||
use deno_semver::package::PackageNv;
|
use deno_semver::package::PackageNv;
|
||||||
use deno_semver::package::PackageReq;
|
use deno_semver::package::PackageReq;
|
||||||
|
use deno_semver::StackString;
|
||||||
use deno_semver::Version;
|
use deno_semver::Version;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
use super::config::ConfigData;
|
use super::config::ConfigData;
|
||||||
use super::search::PackageSearchApi;
|
use super::search::PackageSearchApi;
|
||||||
|
use crate::args::jsr_api_url;
|
||||||
|
use crate::args::jsr_url;
|
||||||
|
use crate::file_fetcher::CliFileFetcher;
|
||||||
|
use crate::file_fetcher::TextDecodedFile;
|
||||||
|
use crate::jsr::partial_jsr_package_version_info_from_slice;
|
||||||
|
use crate::jsr::JsrFetchResolver;
|
||||||
|
|
||||||
/// Keep in sync with `JsrFetchResolver`!
|
/// Keep in sync with `JsrFetchResolver`!
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -32,8 +35,8 @@ pub struct JsrCacheResolver {
|
||||||
/// The `module_graph` fields of the version infos should be forcibly absent.
|
/// The `module_graph` fields of the version infos should be forcibly absent.
|
||||||
/// It can be large and we don't want to store it.
|
/// It can be large and we don't want to store it.
|
||||||
info_by_nv: DashMap<PackageNv, Option<Arc<JsrPackageVersionInfo>>>,
|
info_by_nv: DashMap<PackageNv, Option<Arc<JsrPackageVersionInfo>>>,
|
||||||
info_by_name: DashMap<String, Option<Arc<JsrPackageInfo>>>,
|
info_by_name: DashMap<StackString, Option<Arc<JsrPackageInfo>>>,
|
||||||
workspace_scope_by_name: HashMap<String, ModuleSpecifier>,
|
workspace_scope_by_name: HashMap<StackString, ModuleSpecifier>,
|
||||||
cache: Arc<dyn HttpCache>,
|
cache: Arc<dyn HttpCache>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,7 +61,7 @@ impl JsrCacheResolver {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
let nv = PackageNv {
|
let nv = PackageNv {
|
||||||
name: jsr_pkg_config.name.clone(),
|
name: jsr_pkg_config.name.as_str().into(),
|
||||||
version: version.clone(),
|
version: version.clone(),
|
||||||
};
|
};
|
||||||
info_by_name.insert(
|
info_by_name.insert(
|
||||||
|
@ -124,8 +127,8 @@ impl JsrCacheResolver {
|
||||||
return nv.value().clone();
|
return nv.value().clone();
|
||||||
}
|
}
|
||||||
let maybe_get_nv = || {
|
let maybe_get_nv = || {
|
||||||
let name = req.name.clone();
|
let name = &req.name;
|
||||||
let package_info = self.package_info(&name)?;
|
let package_info = self.package_info(name)?;
|
||||||
// Find the first matching version of the package which is cached.
|
// Find the first matching version of the package which is cached.
|
||||||
let mut versions = package_info.versions.keys().collect::<Vec<_>>();
|
let mut versions = package_info.versions.keys().collect::<Vec<_>>();
|
||||||
versions.sort();
|
versions.sort();
|
||||||
|
@ -143,7 +146,10 @@ impl JsrCacheResolver {
|
||||||
self.package_version_info(&nv).is_some()
|
self.package_version_info(&nv).is_some()
|
||||||
})
|
})
|
||||||
.cloned()?;
|
.cloned()?;
|
||||||
Some(PackageNv { name, version })
|
Some(PackageNv {
|
||||||
|
name: name.clone(),
|
||||||
|
version,
|
||||||
|
})
|
||||||
};
|
};
|
||||||
let nv = maybe_get_nv();
|
let nv = maybe_get_nv();
|
||||||
self.nv_by_req.insert(req.clone(), nv.clone());
|
self.nv_by_req.insert(req.clone(), nv.clone());
|
||||||
|
@ -215,7 +221,10 @@ impl JsrCacheResolver {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn package_info(&self, name: &str) -> Option<Arc<JsrPackageInfo>> {
|
pub fn package_info(
|
||||||
|
&self,
|
||||||
|
name: &StackString,
|
||||||
|
) -> Option<Arc<JsrPackageInfo>> {
|
||||||
if let Some(info) = self.info_by_name.get(name) {
|
if let Some(info) = self.info_by_name.get(name) {
|
||||||
return info.value().clone();
|
return info.value().clone();
|
||||||
}
|
}
|
||||||
|
@ -225,7 +234,7 @@ impl JsrCacheResolver {
|
||||||
serde_json::from_slice::<JsrPackageInfo>(&meta_bytes).ok()
|
serde_json::from_slice::<JsrPackageInfo>(&meta_bytes).ok()
|
||||||
};
|
};
|
||||||
let info = read_cached_package_info().map(Arc::new);
|
let info = read_cached_package_info().map(Arc::new);
|
||||||
self.info_by_name.insert(name.to_string(), info.clone());
|
self.info_by_name.insert(name.clone(), info.clone());
|
||||||
info
|
info
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -267,7 +276,7 @@ fn read_cached_url(
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct CliJsrSearchApi {
|
pub struct CliJsrSearchApi {
|
||||||
file_fetcher: Arc<FileFetcher>,
|
file_fetcher: Arc<CliFileFetcher>,
|
||||||
resolver: JsrFetchResolver,
|
resolver: JsrFetchResolver,
|
||||||
search_cache: DashMap<String, Arc<Vec<String>>>,
|
search_cache: DashMap<String, Arc<Vec<String>>>,
|
||||||
versions_cache: DashMap<String, Arc<Vec<Version>>>,
|
versions_cache: DashMap<String, Arc<Vec<Version>>>,
|
||||||
|
@ -275,7 +284,7 @@ pub struct CliJsrSearchApi {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CliJsrSearchApi {
|
impl CliJsrSearchApi {
|
||||||
pub fn new(file_fetcher: Arc<FileFetcher>) -> Self {
|
pub fn new(file_fetcher: Arc<CliFileFetcher>) -> Self {
|
||||||
let resolver = JsrFetchResolver::new(file_fetcher.clone());
|
let resolver = JsrFetchResolver::new(file_fetcher.clone());
|
||||||
Self {
|
Self {
|
||||||
file_fetcher,
|
file_fetcher,
|
||||||
|
@ -309,10 +318,8 @@ impl PackageSearchApi for CliJsrSearchApi {
|
||||||
let file_fetcher = self.file_fetcher.clone();
|
let file_fetcher = self.file_fetcher.clone();
|
||||||
// spawn due to the lsp's `Send` requirement
|
// spawn due to the lsp's `Send` requirement
|
||||||
let file = deno_core::unsync::spawn(async move {
|
let file = deno_core::unsync::spawn(async move {
|
||||||
file_fetcher
|
let file = file_fetcher.fetch_bypass_permissions(&search_url).await?;
|
||||||
.fetch_bypass_permissions(&search_url)
|
TextDecodedFile::decode(file)
|
||||||
.await?
|
|
||||||
.into_text_decoded()
|
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
let names = Arc::new(parse_jsr_search_response(&file.source)?);
|
let names = Arc::new(parse_jsr_search_response(&file.source)?);
|
||||||
|
|
|
@ -1,6 +1,18 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
|
use std::collections::BTreeMap;
|
||||||
|
use std::collections::BTreeSet;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::collections::HashSet;
|
||||||
|
use std::collections::VecDeque;
|
||||||
|
use std::env;
|
||||||
|
use std::fmt::Write as _;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use std::str::FromStr;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
use deno_ast::MediaType;
|
use deno_ast::MediaType;
|
||||||
|
use deno_cache_dir::file_fetcher::CacheSetting;
|
||||||
use deno_config::workspace::WorkspaceDirectory;
|
use deno_config::workspace::WorkspaceDirectory;
|
||||||
use deno_config::workspace::WorkspaceDiscoverOptions;
|
use deno_config::workspace::WorkspaceDiscoverOptions;
|
||||||
use deno_core::anyhow::anyhow;
|
use deno_core::anyhow::anyhow;
|
||||||
|
@ -26,16 +38,6 @@ use node_resolver::NodeResolutionKind;
|
||||||
use node_resolver::ResolutionMode;
|
use node_resolver::ResolutionMode;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde_json::from_value;
|
use serde_json::from_value;
|
||||||
use std::collections::BTreeMap;
|
|
||||||
use std::collections::BTreeSet;
|
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::collections::HashSet;
|
|
||||||
use std::collections::VecDeque;
|
|
||||||
use std::env;
|
|
||||||
use std::fmt::Write as _;
|
|
||||||
use std::path::PathBuf;
|
|
||||||
use std::str::FromStr;
|
|
||||||
use std::sync::Arc;
|
|
||||||
use tokio::sync::mpsc::unbounded_channel;
|
use tokio::sync::mpsc::unbounded_channel;
|
||||||
use tokio::sync::mpsc::UnboundedReceiver;
|
use tokio::sync::mpsc::UnboundedReceiver;
|
||||||
use tokio::sync::mpsc::UnboundedSender;
|
use tokio::sync::mpsc::UnboundedSender;
|
||||||
|
@ -95,19 +97,19 @@ use crate::args::create_default_npmrc;
|
||||||
use crate::args::get_root_cert_store;
|
use crate::args::get_root_cert_store;
|
||||||
use crate::args::has_flag_env_var;
|
use crate::args::has_flag_env_var;
|
||||||
use crate::args::CaData;
|
use crate::args::CaData;
|
||||||
use crate::args::CacheSetting;
|
|
||||||
use crate::args::CliOptions;
|
use crate::args::CliOptions;
|
||||||
use crate::args::Flags;
|
use crate::args::Flags;
|
||||||
use crate::args::InternalFlags;
|
use crate::args::InternalFlags;
|
||||||
use crate::args::UnstableFmtOptions;
|
use crate::args::UnstableFmtOptions;
|
||||||
use crate::factory::CliFactory;
|
use crate::factory::CliFactory;
|
||||||
use crate::file_fetcher::FileFetcher;
|
use crate::file_fetcher::CliFileFetcher;
|
||||||
use crate::graph_util;
|
use crate::graph_util;
|
||||||
use crate::http_util::HttpClientProvider;
|
use crate::http_util::HttpClientProvider;
|
||||||
use crate::lsp::config::ConfigWatchedFileType;
|
use crate::lsp::config::ConfigWatchedFileType;
|
||||||
use crate::lsp::logging::init_log_file;
|
use crate::lsp::logging::init_log_file;
|
||||||
use crate::lsp::tsc::file_text_changes_to_workspace_edit;
|
use crate::lsp::tsc::file_text_changes_to_workspace_edit;
|
||||||
use crate::lsp::urls::LspUrlKind;
|
use crate::lsp::urls::LspUrlKind;
|
||||||
|
use crate::sys::CliSys;
|
||||||
use crate::tools::fmt::format_file;
|
use crate::tools::fmt::format_file;
|
||||||
use crate::tools::fmt::format_parsed_source;
|
use crate::tools::fmt::format_parsed_source;
|
||||||
use crate::tools::upgrade::check_for_upgrades_for_lsp;
|
use crate::tools::upgrade::check_for_upgrades_for_lsp;
|
||||||
|
@ -120,7 +122,7 @@ use crate::util::sync::AsyncFlag;
|
||||||
struct LspRootCertStoreProvider(RootCertStore);
|
struct LspRootCertStoreProvider(RootCertStore);
|
||||||
|
|
||||||
impl RootCertStoreProvider for LspRootCertStoreProvider {
|
impl RootCertStoreProvider for LspRootCertStoreProvider {
|
||||||
fn get_or_try_init(&self) -> Result<&RootCertStore, AnyError> {
|
fn get_or_try_init(&self) -> Result<&RootCertStore, deno_error::JsErrorBox> {
|
||||||
Ok(&self.0)
|
Ok(&self.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -279,7 +281,7 @@ impl LanguageServer {
|
||||||
.await?;
|
.await?;
|
||||||
graph_util::graph_valid(
|
graph_util::graph_valid(
|
||||||
&graph,
|
&graph,
|
||||||
factory.fs(),
|
&CliSys::default(),
|
||||||
&roots,
|
&roots,
|
||||||
graph_util::GraphValidOptions {
|
graph_util::GraphValidOptions {
|
||||||
kind: GraphKind::All,
|
kind: GraphKind::All,
|
||||||
|
@ -958,15 +960,16 @@ impl Inner {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn refresh_config_tree(&mut self) {
|
async fn refresh_config_tree(&mut self) {
|
||||||
let mut file_fetcher = FileFetcher::new(
|
let file_fetcher = CliFileFetcher::new(
|
||||||
self.cache.global().clone(),
|
self.cache.global().clone(),
|
||||||
CacheSetting::RespectHeaders,
|
|
||||||
true,
|
|
||||||
self.http_client_provider.clone(),
|
self.http_client_provider.clone(),
|
||||||
|
CliSys::default(),
|
||||||
Default::default(),
|
Default::default(),
|
||||||
None,
|
None,
|
||||||
|
true,
|
||||||
|
CacheSetting::RespectHeaders,
|
||||||
|
super::logging::lsp_log_level(),
|
||||||
);
|
);
|
||||||
file_fetcher.set_download_log_level(super::logging::lsp_log_level());
|
|
||||||
let file_fetcher = Arc::new(file_fetcher);
|
let file_fetcher = Arc::new(file_fetcher);
|
||||||
self
|
self
|
||||||
.config
|
.config
|
||||||
|
@ -1416,18 +1419,16 @@ impl Inner {
|
||||||
// the file path is only used to determine what formatter should
|
// the file path is only used to determine what formatter should
|
||||||
// be used to format the file, so give the filepath an extension
|
// be used to format the file, so give the filepath an extension
|
||||||
// that matches what the user selected as the language
|
// that matches what the user selected as the language
|
||||||
let file_path = document
|
let ext = document
|
||||||
.maybe_language_id()
|
.maybe_language_id()
|
||||||
.and_then(|id| id.as_extension())
|
.and_then(|id| id.as_extension().map(|s| s.to_string()));
|
||||||
.map(|ext| file_path.with_extension(ext))
|
|
||||||
.unwrap_or(file_path);
|
|
||||||
// it's not a js/ts file, so attempt to format its contents
|
// it's not a js/ts file, so attempt to format its contents
|
||||||
format_file(
|
format_file(
|
||||||
&file_path,
|
&file_path,
|
||||||
document.content(),
|
document.content(),
|
||||||
&fmt_options,
|
&fmt_options,
|
||||||
&unstable_options,
|
&unstable_options,
|
||||||
None,
|
ext,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1855,20 +1856,12 @@ impl Inner {
|
||||||
}
|
}
|
||||||
|
|
||||||
let changes = if code_action_data.fix_id == "fixMissingImport" {
|
let changes = if code_action_data.fix_id == "fixMissingImport" {
|
||||||
fix_ts_import_changes(
|
fix_ts_import_changes(&combined_code_actions.changes, self).map_err(
|
||||||
&code_action_data.specifier,
|
|err| {
|
||||||
maybe_asset_or_doc
|
|
||||||
.as_ref()
|
|
||||||
.and_then(|d| d.document())
|
|
||||||
.map(|d| d.resolution_mode())
|
|
||||||
.unwrap_or(ResolutionMode::Import),
|
|
||||||
&combined_code_actions.changes,
|
|
||||||
self,
|
|
||||||
)
|
|
||||||
.map_err(|err| {
|
|
||||||
error!("Unable to remap changes: {:#}", err);
|
error!("Unable to remap changes: {:#}", err);
|
||||||
LspError::internal_error()
|
LspError::internal_error()
|
||||||
})?
|
},
|
||||||
|
)?
|
||||||
} else {
|
} else {
|
||||||
combined_code_actions.changes
|
combined_code_actions.changes
|
||||||
};
|
};
|
||||||
|
@ -1912,20 +1905,16 @@ impl Inner {
|
||||||
asset_or_doc.scope().cloned(),
|
asset_or_doc.scope().cloned(),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
if kind_suffix == ".rewrite.function.returnType" {
|
if kind_suffix == ".rewrite.function.returnType"
|
||||||
refactor_edit_info.edits = fix_ts_import_changes(
|
|| kind_suffix == ".move.newFile"
|
||||||
&action_data.specifier,
|
{
|
||||||
asset_or_doc
|
refactor_edit_info.edits =
|
||||||
.document()
|
fix_ts_import_changes(&refactor_edit_info.edits, self).map_err(
|
||||||
.map(|d| d.resolution_mode())
|
|err| {
|
||||||
.unwrap_or(ResolutionMode::Import),
|
|
||||||
&refactor_edit_info.edits,
|
|
||||||
self,
|
|
||||||
)
|
|
||||||
.map_err(|err| {
|
|
||||||
error!("Unable to remap changes: {:#}", err);
|
error!("Unable to remap changes: {:#}", err);
|
||||||
LspError::internal_error()
|
LspError::internal_error()
|
||||||
})?
|
},
|
||||||
|
)?
|
||||||
}
|
}
|
||||||
code_action.edit = refactor_edit_info.to_workspace_edit(self)?;
|
code_action.edit = refactor_edit_info.to_workspace_edit(self)?;
|
||||||
code_action
|
code_action
|
||||||
|
@ -3624,16 +3613,14 @@ impl Inner {
|
||||||
let workspace = match config_data {
|
let workspace = match config_data {
|
||||||
Some(d) => d.member_dir.clone(),
|
Some(d) => d.member_dir.clone(),
|
||||||
None => Arc::new(WorkspaceDirectory::discover(
|
None => Arc::new(WorkspaceDirectory::discover(
|
||||||
|
&CliSys::default(),
|
||||||
deno_config::workspace::WorkspaceDiscoverStart::Paths(&[
|
deno_config::workspace::WorkspaceDiscoverStart::Paths(&[
|
||||||
initial_cwd.clone()
|
initial_cwd.clone()
|
||||||
]),
|
]),
|
||||||
&WorkspaceDiscoverOptions {
|
&WorkspaceDiscoverOptions {
|
||||||
fs: Default::default(), // use real fs,
|
|
||||||
deno_json_cache: None,
|
deno_json_cache: None,
|
||||||
pkg_json_cache: None,
|
pkg_json_cache: None,
|
||||||
workspace_cache: None,
|
workspace_cache: None,
|
||||||
config_parse_options:
|
|
||||||
deno_config::deno_json::ConfigParseOptions::default(),
|
|
||||||
additional_config_file_names: &[],
|
additional_config_file_names: &[],
|
||||||
discover_pkg_json: !has_flag_env_var("DENO_NO_PACKAGE_JSON"),
|
discover_pkg_json: !has_flag_env_var("DENO_NO_PACKAGE_JSON"),
|
||||||
maybe_vendor_override: if force_global_cache {
|
maybe_vendor_override: if force_global_cache {
|
||||||
|
@ -3645,6 +3632,7 @@ impl Inner {
|
||||||
)?),
|
)?),
|
||||||
};
|
};
|
||||||
let cli_options = CliOptions::new(
|
let cli_options = CliOptions::new(
|
||||||
|
&CliSys::default(),
|
||||||
Arc::new(Flags {
|
Arc::new(Flags {
|
||||||
internal: InternalFlags {
|
internal: InternalFlags {
|
||||||
cache_path: Some(self.cache.deno_dir().root.clone()),
|
cache_path: Some(self.cache.deno_dir().root.clone()),
|
||||||
|
@ -3793,7 +3781,7 @@ impl Inner {
|
||||||
for (name, command) in scripts {
|
for (name, command) in scripts {
|
||||||
result.push(TaskDefinition {
|
result.push(TaskDefinition {
|
||||||
name: name.clone(),
|
name: name.clone(),
|
||||||
command: command.clone(),
|
command: Some(command.clone()),
|
||||||
source_uri: url_to_uri(&package_json.specifier())
|
source_uri: url_to_uri(&package_json.specifier())
|
||||||
.map_err(|_| LspError::internal_error())?,
|
.map_err(|_| LspError::internal_error())?,
|
||||||
});
|
});
|
||||||
|
@ -3972,10 +3960,11 @@ impl Inner {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
use test_util::TempDir;
|
use test_util::TempDir;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_walk_workspace() {
|
fn test_walk_workspace() {
|
||||||
let temp_dir = TempDir::new();
|
let temp_dir = TempDir::new();
|
||||||
|
@ -4012,12 +4001,14 @@ mod tests {
|
||||||
temp_dir.write("root1/target/main.ts", ""); // no, because there is a Cargo.toml in the root directory
|
temp_dir.write("root1/target/main.ts", ""); // no, because there is a Cargo.toml in the root directory
|
||||||
|
|
||||||
temp_dir.create_dir_all("root2/folder");
|
temp_dir.create_dir_all("root2/folder");
|
||||||
|
temp_dir.create_dir_all("root2/folder2/inner_folder");
|
||||||
temp_dir.create_dir_all("root2/sub_folder");
|
temp_dir.create_dir_all("root2/sub_folder");
|
||||||
temp_dir.create_dir_all("root2/root2.1");
|
temp_dir.create_dir_all("root2/root2.1");
|
||||||
temp_dir.write("root2/file1.ts", ""); // yes, enabled
|
temp_dir.write("root2/file1.ts", ""); // yes, enabled
|
||||||
temp_dir.write("root2/file2.ts", ""); // no, not enabled
|
temp_dir.write("root2/file2.ts", ""); // no, not enabled
|
||||||
temp_dir.write("root2/folder/main.ts", ""); // yes, enabled
|
temp_dir.write("root2/folder/main.ts", ""); // yes, enabled
|
||||||
temp_dir.write("root2/folder/other.ts", ""); // no, disabled
|
temp_dir.write("root2/folder/other.ts", ""); // no, disabled
|
||||||
|
temp_dir.write("root2/folder2/inner_folder/main.ts", ""); // yes, enabled (regression test for https://github.com/denoland/vscode_deno/issues/1239)
|
||||||
temp_dir.write("root2/sub_folder/a.js", ""); // no, not enabled
|
temp_dir.write("root2/sub_folder/a.js", ""); // no, not enabled
|
||||||
temp_dir.write("root2/sub_folder/b.ts", ""); // no, not enabled
|
temp_dir.write("root2/sub_folder/b.ts", ""); // no, not enabled
|
||||||
temp_dir.write("root2/sub_folder/c.js", ""); // no, not enabled
|
temp_dir.write("root2/sub_folder/c.js", ""); // no, not enabled
|
||||||
|
@ -4058,6 +4049,7 @@ mod tests {
|
||||||
enable_paths: Some(vec![
|
enable_paths: Some(vec![
|
||||||
"file1.ts".to_string(),
|
"file1.ts".to_string(),
|
||||||
"folder".to_string(),
|
"folder".to_string(),
|
||||||
|
"folder2/inner_folder".to_string(),
|
||||||
]),
|
]),
|
||||||
disable_paths: vec!["folder/other.ts".to_string()],
|
disable_paths: vec!["folder/other.ts".to_string()],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
@ -4108,6 +4100,10 @@ mod tests {
|
||||||
temp_dir.url().join("root1/folder/mod.ts").unwrap(),
|
temp_dir.url().join("root1/folder/mod.ts").unwrap(),
|
||||||
temp_dir.url().join("root2/folder/main.ts").unwrap(),
|
temp_dir.url().join("root2/folder/main.ts").unwrap(),
|
||||||
temp_dir.url().join("root2/root2.1/main.ts").unwrap(),
|
temp_dir.url().join("root2/root2.1/main.ts").unwrap(),
|
||||||
|
temp_dir
|
||||||
|
.url()
|
||||||
|
.join("root2/folder2/inner_folder/main.ts")
|
||||||
|
.unwrap(),
|
||||||
])
|
])
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
use chrono::DateTime;
|
|
||||||
use chrono::Utc;
|
|
||||||
use deno_core::parking_lot::Mutex;
|
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
@ -12,6 +9,10 @@ use std::sync::atomic::Ordering;
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use std::time::SystemTime;
|
use std::time::SystemTime;
|
||||||
|
|
||||||
|
use chrono::DateTime;
|
||||||
|
use chrono::Utc;
|
||||||
|
use deno_core::parking_lot::Mutex;
|
||||||
|
|
||||||
static LSP_DEBUG_FLAG: AtomicBool = AtomicBool::new(false);
|
static LSP_DEBUG_FLAG: AtomicBool = AtomicBool::new(false);
|
||||||
static LSP_LOG_LEVEL: AtomicUsize = AtomicUsize::new(log::Level::Info as usize);
|
static LSP_LOG_LEVEL: AtomicUsize = AtomicUsize::new(log::Level::Info as usize);
|
||||||
static LSP_WARN_LEVEL: AtomicUsize =
|
static LSP_WARN_LEVEL: AtomicUsize =
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
use deno_core::serde::Deserialize;
|
use deno_core::serde::Deserialize;
|
||||||
use deno_core::serde::Serialize;
|
use deno_core::serde::Serialize;
|
||||||
|
@ -14,7 +14,7 @@ pub const LATEST_DIAGNOSTIC_BATCH_INDEX: &str =
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct TaskDefinition {
|
pub struct TaskDefinition {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub command: String,
|
pub command: Option<String>,
|
||||||
pub source_uri: lsp::Uri,
|
pub source_uri: lsp::Uri,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,16 +1,15 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
use deno_core::unsync::spawn;
|
use deno_core::unsync::spawn;
|
||||||
|
pub use repl::ReplCompletionItem;
|
||||||
|
pub use repl::ReplLanguageServer;
|
||||||
use tower_lsp::LspService;
|
use tower_lsp::LspService;
|
||||||
use tower_lsp::Server;
|
use tower_lsp::Server;
|
||||||
|
|
||||||
|
use self::diagnostics::should_send_diagnostic_batch_index_notifications;
|
||||||
use crate::lsp::language_server::LanguageServer;
|
use crate::lsp::language_server::LanguageServer;
|
||||||
use crate::util::sync::AsyncFlag;
|
use crate::util::sync::AsyncFlag;
|
||||||
pub use repl::ReplCompletionItem;
|
|
||||||
pub use repl::ReplLanguageServer;
|
|
||||||
|
|
||||||
use self::diagnostics::should_send_diagnostic_batch_index_notifications;
|
|
||||||
|
|
||||||
mod analysis;
|
mod analysis;
|
||||||
mod cache;
|
mod cache;
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
use dashmap::DashMap;
|
use dashmap::DashMap;
|
||||||
use deno_core::anyhow::anyhow;
|
use deno_core::anyhow::anyhow;
|
||||||
|
@ -8,24 +10,23 @@ use deno_npm::npm_rc::NpmRc;
|
||||||
use deno_semver::package::PackageNv;
|
use deno_semver::package::PackageNv;
|
||||||
use deno_semver::Version;
|
use deno_semver::Version;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
use crate::args::npm_registry_url;
|
|
||||||
use crate::file_fetcher::FileFetcher;
|
|
||||||
use crate::npm::NpmFetchResolver;
|
|
||||||
|
|
||||||
use super::search::PackageSearchApi;
|
use super::search::PackageSearchApi;
|
||||||
|
use crate::args::npm_registry_url;
|
||||||
|
use crate::file_fetcher::CliFileFetcher;
|
||||||
|
use crate::file_fetcher::TextDecodedFile;
|
||||||
|
use crate::npm::NpmFetchResolver;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct CliNpmSearchApi {
|
pub struct CliNpmSearchApi {
|
||||||
file_fetcher: Arc<FileFetcher>,
|
file_fetcher: Arc<CliFileFetcher>,
|
||||||
resolver: NpmFetchResolver,
|
resolver: NpmFetchResolver,
|
||||||
search_cache: DashMap<String, Arc<Vec<String>>>,
|
search_cache: DashMap<String, Arc<Vec<String>>>,
|
||||||
versions_cache: DashMap<String, Arc<Vec<Version>>>,
|
versions_cache: DashMap<String, Arc<Vec<Version>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CliNpmSearchApi {
|
impl CliNpmSearchApi {
|
||||||
pub fn new(file_fetcher: Arc<FileFetcher>) -> Self {
|
pub fn new(file_fetcher: Arc<CliFileFetcher>) -> Self {
|
||||||
let resolver = NpmFetchResolver::new(
|
let resolver = NpmFetchResolver::new(
|
||||||
file_fetcher.clone(),
|
file_fetcher.clone(),
|
||||||
Arc::new(NpmRc::default().as_resolved(npm_registry_url()).unwrap()),
|
Arc::new(NpmRc::default().as_resolved(npm_registry_url()).unwrap()),
|
||||||
|
@ -57,10 +58,8 @@ impl PackageSearchApi for CliNpmSearchApi {
|
||||||
.append_pair("text", &format!("{} boost-exact:false", query));
|
.append_pair("text", &format!("{} boost-exact:false", query));
|
||||||
let file_fetcher = self.file_fetcher.clone();
|
let file_fetcher = self.file_fetcher.clone();
|
||||||
let file = deno_core::unsync::spawn(async move {
|
let file = deno_core::unsync::spawn(async move {
|
||||||
file_fetcher
|
let file = file_fetcher.fetch_bypass_permissions(&search_url).await?;
|
||||||
.fetch_bypass_permissions(&search_url)
|
TextDecodedFile::decode(file)
|
||||||
.await?
|
|
||||||
.into_text_decoded()
|
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
let names = Arc::new(parse_npm_search_response(&file.source)?);
|
let names = Arc::new(parse_npm_search_response(&file.source)?);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
|
@ -52,10 +52,12 @@ fn is_process_active(process_id: u32) -> bool {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::is_process_active;
|
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
|
|
||||||
use test_util::deno_exe_path;
|
use test_util::deno_exe_path;
|
||||||
|
|
||||||
|
use super::is_process_active;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn process_active() {
|
fn process_active() {
|
||||||
// launch a long running process
|
// launch a long running process
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
// The logic of this module is heavily influenced by path-to-regexp at:
|
// The logic of this module is heavily influenced by path-to-regexp at:
|
||||||
// https://github.com/pillarjs/path-to-regexp/ which is licensed as follows:
|
// https://github.com/pillarjs/path-to-regexp/ which is licensed as follows:
|
||||||
|
@ -26,15 +26,16 @@
|
||||||
// THE SOFTWARE.
|
// THE SOFTWARE.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::fmt;
|
||||||
|
use std::fmt::Write as _;
|
||||||
|
use std::iter::Peekable;
|
||||||
|
|
||||||
use deno_core::anyhow::anyhow;
|
use deno_core::anyhow::anyhow;
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
use fancy_regex::Regex as FancyRegex;
|
use fancy_regex::Regex as FancyRegex;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::fmt;
|
|
||||||
use std::fmt::Write as _;
|
|
||||||
use std::iter::Peekable;
|
|
||||||
|
|
||||||
static ESCAPE_STRING_RE: Lazy<Regex> =
|
static ESCAPE_STRING_RE: Lazy<Regex> =
|
||||||
lazy_regex::lazy_regex!(r"([.+*?=^!:${}()\[\]|/\\])");
|
lazy_regex::lazy_regex!(r"([.+*?=^!:${}()\[\]|/\\])");
|
||||||
|
|
|
@ -1,9 +1,5 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
use deno_core::parking_lot::Mutex;
|
|
||||||
use deno_core::serde::Deserialize;
|
|
||||||
use deno_core::serde::Serialize;
|
|
||||||
use deno_core::serde_json::json;
|
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
|
@ -12,6 +8,11 @@ use std::sync::Arc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
|
|
||||||
|
use deno_core::parking_lot::Mutex;
|
||||||
|
use deno_core::serde::Deserialize;
|
||||||
|
use deno_core::serde::Serialize;
|
||||||
|
use deno_core::serde_json::json;
|
||||||
|
|
||||||
use super::logging::lsp_debug;
|
use super::logging::lsp_debug;
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize, PartialEq, Eq)]
|
#[derive(Debug, Deserialize, Serialize, PartialEq, Eq)]
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
// The logic of this module is heavily influenced by
|
// The logic of this module is heavily influenced by
|
||||||
// https://github.com/microsoft/vscode/blob/main/extensions/typescript-language-features/src/languageFeatures/refactor.ts
|
// https://github.com/microsoft/vscode/blob/main/extensions/typescript-language-features/src/languageFeatures/refactor.ts
|
||||||
|
|
|
@ -1,25 +1,11 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
use super::completions::IMPORT_COMMIT_CHARS;
|
use std::borrow::Cow;
|
||||||
use super::logging::lsp_log;
|
use std::collections::HashMap;
|
||||||
use super::path_to_regex::parse;
|
use std::path::PathBuf;
|
||||||
use super::path_to_regex::string_to_regex;
|
use std::sync::Arc;
|
||||||
use super::path_to_regex::Compiler;
|
|
||||||
use super::path_to_regex::Key;
|
|
||||||
use super::path_to_regex::MatchResult;
|
|
||||||
use super::path_to_regex::Matcher;
|
|
||||||
use super::path_to_regex::StringOrNumber;
|
|
||||||
use super::path_to_regex::StringOrVec;
|
|
||||||
use super::path_to_regex::Token;
|
|
||||||
|
|
||||||
use crate::args::CacheSetting;
|
|
||||||
use crate::cache::GlobalHttpCache;
|
|
||||||
use crate::cache::HttpCache;
|
|
||||||
use crate::file_fetcher::FetchOptions;
|
|
||||||
use crate::file_fetcher::FetchPermissionsOptionRef;
|
|
||||||
use crate::file_fetcher::FileFetcher;
|
|
||||||
use crate::http_util::HttpClientProvider;
|
|
||||||
|
|
||||||
|
use deno_cache_dir::file_fetcher::CacheSetting;
|
||||||
use deno_core::anyhow::anyhow;
|
use deno_core::anyhow::anyhow;
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
use deno_core::serde::Deserialize;
|
use deno_core::serde::Deserialize;
|
||||||
|
@ -33,12 +19,28 @@ use deno_core::ModuleSpecifier;
|
||||||
use deno_graph::Dependency;
|
use deno_graph::Dependency;
|
||||||
use log::error;
|
use log::error;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use std::borrow::Cow;
|
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::path::PathBuf;
|
|
||||||
use std::sync::Arc;
|
|
||||||
use tower_lsp::lsp_types as lsp;
|
use tower_lsp::lsp_types as lsp;
|
||||||
|
|
||||||
|
use super::completions::IMPORT_COMMIT_CHARS;
|
||||||
|
use super::logging::lsp_log;
|
||||||
|
use super::path_to_regex::parse;
|
||||||
|
use super::path_to_regex::string_to_regex;
|
||||||
|
use super::path_to_regex::Compiler;
|
||||||
|
use super::path_to_regex::Key;
|
||||||
|
use super::path_to_regex::MatchResult;
|
||||||
|
use super::path_to_regex::Matcher;
|
||||||
|
use super::path_to_regex::StringOrNumber;
|
||||||
|
use super::path_to_regex::StringOrVec;
|
||||||
|
use super::path_to_regex::Token;
|
||||||
|
use crate::cache::GlobalHttpCache;
|
||||||
|
use crate::cache::HttpCache;
|
||||||
|
use crate::file_fetcher::CliFileFetcher;
|
||||||
|
use crate::file_fetcher::FetchOptions;
|
||||||
|
use crate::file_fetcher::FetchPermissionsOptionRef;
|
||||||
|
use crate::file_fetcher::TextDecodedFile;
|
||||||
|
use crate::http_util::HttpClientProvider;
|
||||||
|
use crate::sys::CliSys;
|
||||||
|
|
||||||
const CONFIG_PATH: &str = "/.well-known/deno-import-intellisense.json";
|
const CONFIG_PATH: &str = "/.well-known/deno-import-intellisense.json";
|
||||||
const COMPONENT: &percent_encoding::AsciiSet = &percent_encoding::CONTROLS
|
const COMPONENT: &percent_encoding::AsciiSet = &percent_encoding::CONTROLS
|
||||||
.add(b' ')
|
.add(b' ')
|
||||||
|
@ -418,7 +420,7 @@ enum VariableItems {
|
||||||
pub struct ModuleRegistry {
|
pub struct ModuleRegistry {
|
||||||
origins: HashMap<String, Vec<RegistryConfiguration>>,
|
origins: HashMap<String, Vec<RegistryConfiguration>>,
|
||||||
pub location: PathBuf,
|
pub location: PathBuf,
|
||||||
pub file_fetcher: Arc<FileFetcher>,
|
pub file_fetcher: Arc<CliFileFetcher>,
|
||||||
http_cache: Arc<GlobalHttpCache>,
|
http_cache: Arc<GlobalHttpCache>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -428,19 +430,18 @@ impl ModuleRegistry {
|
||||||
http_client_provider: Arc<HttpClientProvider>,
|
http_client_provider: Arc<HttpClientProvider>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
// the http cache should always be the global one for registry completions
|
// the http cache should always be the global one for registry completions
|
||||||
let http_cache = Arc::new(GlobalHttpCache::new(
|
let http_cache =
|
||||||
location.clone(),
|
Arc::new(GlobalHttpCache::new(CliSys::default(), location.clone()));
|
||||||
crate::cache::RealDenoCacheEnv,
|
let file_fetcher = CliFileFetcher::new(
|
||||||
));
|
|
||||||
let mut file_fetcher = FileFetcher::new(
|
|
||||||
http_cache.clone(),
|
http_cache.clone(),
|
||||||
CacheSetting::RespectHeaders,
|
|
||||||
true,
|
|
||||||
http_client_provider,
|
http_client_provider,
|
||||||
|
CliSys::default(),
|
||||||
Default::default(),
|
Default::default(),
|
||||||
None,
|
None,
|
||||||
|
true,
|
||||||
|
CacheSetting::RespectHeaders,
|
||||||
|
super::logging::lsp_log_level(),
|
||||||
);
|
);
|
||||||
file_fetcher.set_download_log_level(super::logging::lsp_log_level());
|
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
origins: HashMap::new(),
|
origins: HashMap::new(),
|
||||||
|
@ -479,13 +480,15 @@ impl ModuleRegistry {
|
||||||
let specifier = specifier.clone();
|
let specifier = specifier.clone();
|
||||||
async move {
|
async move {
|
||||||
file_fetcher
|
file_fetcher
|
||||||
.fetch_with_options(FetchOptions {
|
.fetch_with_options(
|
||||||
specifier: &specifier,
|
&specifier,
|
||||||
permissions: FetchPermissionsOptionRef::AllowAll,
|
FetchPermissionsOptionRef::AllowAll,
|
||||||
|
FetchOptions {
|
||||||
maybe_auth: None,
|
maybe_auth: None,
|
||||||
maybe_accept: Some("application/vnd.deno.reg.v2+json, application/vnd.deno.reg.v1+json;q=0.9, application/json;q=0.8"),
|
maybe_accept: Some("application/vnd.deno.reg.v2+json, application/vnd.deno.reg.v1+json;q=0.9, application/json;q=0.8"),
|
||||||
maybe_cache_setting: None,
|
maybe_cache_setting: None,
|
||||||
})
|
}
|
||||||
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
}).await?;
|
}).await?;
|
||||||
|
@ -500,7 +503,7 @@ impl ModuleRegistry {
|
||||||
);
|
);
|
||||||
self.http_cache.set(specifier, headers_map, &[])?;
|
self.http_cache.set(specifier, headers_map, &[])?;
|
||||||
}
|
}
|
||||||
let file = fetch_result?.into_text_decoded()?;
|
let file = TextDecodedFile::decode(fetch_result?)?;
|
||||||
let config: RegistryConfigurationJson = serde_json::from_str(&file.source)?;
|
let config: RegistryConfigurationJson = serde_json::from_str(&file.source)?;
|
||||||
validate_config(&config)?;
|
validate_config(&config)?;
|
||||||
Ok(config.registries)
|
Ok(config.registries)
|
||||||
|
@ -584,12 +587,11 @@ impl ModuleRegistry {
|
||||||
// spawn due to the lsp's `Send` requirement
|
// spawn due to the lsp's `Send` requirement
|
||||||
let file = deno_core::unsync::spawn({
|
let file = deno_core::unsync::spawn({
|
||||||
async move {
|
async move {
|
||||||
file_fetcher
|
let file = file_fetcher
|
||||||
.fetch_bypass_permissions(&endpoint)
|
.fetch_bypass_permissions(&endpoint)
|
||||||
.await
|
.await
|
||||||
.ok()?
|
.ok()?;
|
||||||
.into_text_decoded()
|
TextDecodedFile::decode(file).ok()
|
||||||
.ok()
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
|
@ -983,12 +985,11 @@ impl ModuleRegistry {
|
||||||
let file_fetcher = self.file_fetcher.clone();
|
let file_fetcher = self.file_fetcher.clone();
|
||||||
// spawn due to the lsp's `Send` requirement
|
// spawn due to the lsp's `Send` requirement
|
||||||
let file = deno_core::unsync::spawn(async move {
|
let file = deno_core::unsync::spawn(async move {
|
||||||
file_fetcher
|
let file = file_fetcher
|
||||||
.fetch_bypass_permissions(&specifier)
|
.fetch_bypass_permissions(&specifier)
|
||||||
.await
|
.await
|
||||||
.ok()?
|
.ok()?;
|
||||||
.into_text_decoded()
|
TextDecodedFile::decode(file).ok()
|
||||||
.ok()
|
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.ok()??;
|
.ok()??;
|
||||||
|
@ -1049,7 +1050,7 @@ impl ModuleRegistry {
|
||||||
let file_fetcher = self.file_fetcher.clone();
|
let file_fetcher = self.file_fetcher.clone();
|
||||||
let specifier = specifier.clone();
|
let specifier = specifier.clone();
|
||||||
async move {
|
async move {
|
||||||
file_fetcher
|
let file = file_fetcher
|
||||||
.fetch_bypass_permissions(&specifier)
|
.fetch_bypass_permissions(&specifier)
|
||||||
.await
|
.await
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
|
@ -1058,9 +1059,8 @@ impl ModuleRegistry {
|
||||||
specifier, err
|
specifier, err
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
.ok()?
|
.ok()?;
|
||||||
.into_text_decoded()
|
TextDecodedFile::decode(file).ok()
|
||||||
.ok()
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
|
@ -1095,7 +1095,7 @@ impl ModuleRegistry {
|
||||||
let file_fetcher = self.file_fetcher.clone();
|
let file_fetcher = self.file_fetcher.clone();
|
||||||
let specifier = specifier.clone();
|
let specifier = specifier.clone();
|
||||||
async move {
|
async move {
|
||||||
file_fetcher
|
let file = file_fetcher
|
||||||
.fetch_bypass_permissions(&specifier)
|
.fetch_bypass_permissions(&specifier)
|
||||||
.await
|
.await
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
|
@ -1104,9 +1104,8 @@ impl ModuleRegistry {
|
||||||
specifier, err
|
specifier, err
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
.ok()?
|
.ok()?;
|
||||||
.into_text_decoded()
|
TextDecodedFile::decode(file).ok()
|
||||||
.ok()
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
|
@ -1129,9 +1128,10 @@ impl ModuleRegistry {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
|
||||||
use test_util::TempDir;
|
use test_util::TempDir;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_validate_registry_configuration() {
|
fn test_validate_registry_configuration() {
|
||||||
assert!(validate_config(&RegistryConfigurationJson {
|
assert!(validate_config(&RegistryConfigurationJson {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue