mirror of
https://github.com/denoland/deno.git
synced 2024-11-28 16:20:57 -05:00
Merge branch 'main' into lint_skip_minified_files
This commit is contained in:
commit
dec220a239
1972 changed files with 13320 additions and 4962 deletions
|
@ -66,10 +66,14 @@
|
|||
"tests/wpt/runner/expectation.json",
|
||||
"tests/wpt/runner/manifest.json",
|
||||
"tests/wpt/suite",
|
||||
"third_party"
|
||||
"third_party",
|
||||
"tests/specs/run/shebang_with_json_imports_tsc",
|
||||
"tests/specs/run/shebang_with_json_imports_swc",
|
||||
"tests/specs/run/ext_flag_takes_precedence_over_extension",
|
||||
"tests/specs/run/error_syntax_empty_trailing_line/error_syntax_empty_trailing_line.mjs"
|
||||
],
|
||||
"plugins": [
|
||||
"https://plugins.dprint.dev/typescript-0.93.0.wasm",
|
||||
"https://plugins.dprint.dev/typescript-0.93.2.wasm",
|
||||
"https://plugins.dprint.dev/json-0.19.4.wasm",
|
||||
"https://plugins.dprint.dev/markdown-0.17.8.wasm",
|
||||
"https://plugins.dprint.dev/toml-0.6.3.wasm",
|
||||
|
|
2
.github/workflows/cargo_publish.yml
vendored
2
.github/workflows/cargo_publish.yml
vendored
|
@ -10,7 +10,7 @@ concurrency:
|
|||
jobs:
|
||||
build:
|
||||
name: cargo publish
|
||||
runs-on: ubuntu-20.04-xl
|
||||
runs-on: ubuntu-24.04-xl
|
||||
timeout-minutes: 90
|
||||
|
||||
env:
|
||||
|
|
16
.github/workflows/ci.generate.ts
vendored
16
.github/workflows/ci.generate.ts
vendored
|
@ -5,15 +5,16 @@ import { stringify } from "jsr:@std/yaml@^0.221/stringify";
|
|||
// Bump this number when you want to purge the cache.
|
||||
// Note: the tools/release/01_bump_crate_versions.ts script will update this version
|
||||
// automatically via regex, so ensure that this line maintains this format.
|
||||
const cacheVersion = 22;
|
||||
const cacheVersion = 24;
|
||||
|
||||
const ubuntuX86Runner = "ubuntu-22.04";
|
||||
const ubuntuX86XlRunner = "ubuntu-22.04-xl";
|
||||
const ubuntuX86Runner = "ubuntu-24.04";
|
||||
const ubuntuX86XlRunner = "ubuntu-24.04-xl";
|
||||
const ubuntuARMRunner = "ubicloud-standard-16-arm";
|
||||
const windowsX86Runner = "windows-2022";
|
||||
const windowsX86XlRunner = "windows-2022-xl";
|
||||
const macosX86Runner = "macos-13";
|
||||
const macosArmRunner = "macos-14";
|
||||
const selfHostedMacosArmRunner = "self-hosted";
|
||||
|
||||
const Runners = {
|
||||
linuxX86: {
|
||||
|
@ -40,7 +41,8 @@ const Runners = {
|
|||
macosArm: {
|
||||
os: "macos",
|
||||
arch: "aarch64",
|
||||
runner: macosArmRunner,
|
||||
runner:
|
||||
`\${{ github.repository == 'denoland/deno' && startsWith(github.ref, 'refs/tags/') && '${selfHostedMacosArmRunner}' || '${macosArmRunner}' }}`,
|
||||
},
|
||||
windowsX86: {
|
||||
os: "windows",
|
||||
|
@ -59,7 +61,7 @@ const prCacheKeyPrefix =
|
|||
`${cacheVersion}-cargo-target-\${{ matrix.os }}-\${{ matrix.arch }}-\${{ matrix.profile }}-\${{ matrix.job }}-`;
|
||||
|
||||
// Note that you may need to add more version to the `apt-get remove` line below if you change this
|
||||
const llvmVersion = 18;
|
||||
const llvmVersion = 19;
|
||||
const installPkgsCommand =
|
||||
`sudo apt-get install --no-install-recommends clang-${llvmVersion} lld-${llvmVersion} clang-tools-${llvmVersion} clang-format-${llvmVersion} clang-tidy-${llvmVersion}`;
|
||||
const sysRootStep = {
|
||||
|
@ -71,7 +73,7 @@ export DEBIAN_FRONTEND=noninteractive
|
|||
sudo apt-get -qq remove --purge -y man-db > /dev/null 2> /dev/null
|
||||
# Remove older clang before we install
|
||||
sudo apt-get -qq remove \
|
||||
'clang-12*' 'clang-13*' 'clang-14*' 'clang-15*' 'clang-16*' 'llvm-12*' 'llvm-13*' 'llvm-14*' 'llvm-15*' 'llvm-16*' 'lld-12*' 'lld-13*' 'lld-14*' 'lld-15*' 'lld-16*' > /dev/null 2> /dev/null
|
||||
'clang-12*' 'clang-13*' 'clang-14*' 'clang-15*' 'clang-16*' 'clang-17*' 'clang-18*' 'llvm-12*' 'llvm-13*' 'llvm-14*' 'llvm-15*' 'llvm-16*' 'lld-12*' 'lld-13*' 'lld-14*' 'lld-15*' 'lld-16*' 'lld-17*' 'lld-18*' > /dev/null 2> /dev/null
|
||||
|
||||
# Install clang-XXX, lld-XXX, and debootstrap.
|
||||
echo "deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-${llvmVersion} main" |
|
||||
|
@ -86,7 +88,7 @@ ${installPkgsCommand} || echo 'Failed. Trying again.' && sudo apt-get clean && s
|
|||
(yes '' | sudo update-alternatives --force --all) > /dev/null 2> /dev/null || true
|
||||
|
||||
echo "Decompressing sysroot..."
|
||||
wget -q https://github.com/denoland/deno_sysroot_build/releases/download/sysroot-20240528/sysroot-\`uname -m\`.tar.xz -O /tmp/sysroot.tar.xz
|
||||
wget -q https://github.com/denoland/deno_sysroot_build/releases/download/sysroot-20241030/sysroot-\`uname -m\`.tar.xz -O /tmp/sysroot.tar.xz
|
||||
cd /
|
||||
xzcat /tmp/sysroot.tar.xz | sudo tar -x
|
||||
sudo mount --rbind /dev /sysroot/dev
|
||||
|
|
46
.github/workflows/ci.yml
vendored
46
.github/workflows/ci.yml
vendored
|
@ -62,18 +62,18 @@ jobs:
|
|||
profile: debug
|
||||
- os: macos
|
||||
arch: x86_64
|
||||
runner: '${{ (!contains(github.event.pull_request.labels.*.name, ''ci-full'') && (github.event_name == ''pull_request'')) && ''ubuntu-22.04'' || ''macos-13'' }}'
|
||||
runner: '${{ (!contains(github.event.pull_request.labels.*.name, ''ci-full'') && (github.event_name == ''pull_request'')) && ''ubuntu-24.04'' || ''macos-13'' }}'
|
||||
job: test
|
||||
profile: release
|
||||
skip: '${{ !contains(github.event.pull_request.labels.*.name, ''ci-full'') && (github.event_name == ''pull_request'') }}'
|
||||
- os: macos
|
||||
arch: aarch64
|
||||
runner: macos-14
|
||||
runner: '${{ github.repository == ''denoland/deno'' && startsWith(github.ref, ''refs/tags/'') && ''self-hosted'' || ''macos-14'' }}'
|
||||
job: test
|
||||
profile: debug
|
||||
- os: macos
|
||||
arch: aarch64
|
||||
runner: '${{ (!contains(github.event.pull_request.labels.*.name, ''ci-full'') && (github.event_name == ''pull_request'')) && ''ubuntu-22.04'' || ''macos-14'' }}'
|
||||
runner: '${{ (!contains(github.event.pull_request.labels.*.name, ''ci-full'') && (github.event_name == ''pull_request'')) && ''ubuntu-24.04'' || github.repository == ''denoland/deno'' && startsWith(github.ref, ''refs/tags/'') && ''self-hosted'' || ''macos-14'' }}'
|
||||
job: test
|
||||
profile: release
|
||||
skip: '${{ !contains(github.event.pull_request.labels.*.name, ''ci-full'') && (github.event_name == ''pull_request'') }}'
|
||||
|
@ -84,33 +84,33 @@ jobs:
|
|||
profile: debug
|
||||
- os: windows
|
||||
arch: x86_64
|
||||
runner: '${{ (!contains(github.event.pull_request.labels.*.name, ''ci-full'') && (github.event_name == ''pull_request'')) && ''ubuntu-22.04'' || github.repository == ''denoland/deno'' && ''windows-2022-xl'' || ''windows-2022'' }}'
|
||||
runner: '${{ (!contains(github.event.pull_request.labels.*.name, ''ci-full'') && (github.event_name == ''pull_request'')) && ''ubuntu-24.04'' || github.repository == ''denoland/deno'' && ''windows-2022-xl'' || ''windows-2022'' }}'
|
||||
job: test
|
||||
profile: release
|
||||
skip: '${{ !contains(github.event.pull_request.labels.*.name, ''ci-full'') && (github.event_name == ''pull_request'') }}'
|
||||
- os: linux
|
||||
arch: x86_64
|
||||
runner: '${{ github.repository == ''denoland/deno'' && ''ubuntu-22.04-xl'' || ''ubuntu-22.04'' }}'
|
||||
runner: '${{ github.repository == ''denoland/deno'' && ''ubuntu-24.04-xl'' || ''ubuntu-24.04'' }}'
|
||||
job: test
|
||||
profile: release
|
||||
use_sysroot: true
|
||||
wpt: '${{ !startsWith(github.ref, ''refs/tags/'') }}'
|
||||
- os: linux
|
||||
arch: x86_64
|
||||
runner: '${{ (!contains(github.event.pull_request.labels.*.name, ''ci-full'') && (github.event_name == ''pull_request'' && !contains(github.event.pull_request.labels.*.name, ''ci-bench''))) && ''ubuntu-22.04'' || github.repository == ''denoland/deno'' && ''ubuntu-22.04-xl'' || ''ubuntu-22.04'' }}'
|
||||
runner: '${{ (!contains(github.event.pull_request.labels.*.name, ''ci-full'') && (github.event_name == ''pull_request'' && !contains(github.event.pull_request.labels.*.name, ''ci-bench''))) && ''ubuntu-24.04'' || github.repository == ''denoland/deno'' && ''ubuntu-24.04-xl'' || ''ubuntu-24.04'' }}'
|
||||
job: bench
|
||||
profile: release
|
||||
use_sysroot: true
|
||||
skip: '${{ !contains(github.event.pull_request.labels.*.name, ''ci-full'') && (github.event_name == ''pull_request'' && !contains(github.event.pull_request.labels.*.name, ''ci-bench'')) }}'
|
||||
- os: linux
|
||||
arch: x86_64
|
||||
runner: ubuntu-22.04
|
||||
runner: ubuntu-24.04
|
||||
job: test
|
||||
profile: debug
|
||||
use_sysroot: true
|
||||
- os: linux
|
||||
arch: x86_64
|
||||
runner: ubuntu-22.04
|
||||
runner: ubuntu-24.04
|
||||
job: lint
|
||||
profile: debug
|
||||
- os: linux
|
||||
|
@ -252,22 +252,22 @@ jobs:
|
|||
# to complete.
|
||||
sudo apt-get -qq remove --purge -y man-db > /dev/null 2> /dev/null
|
||||
# Remove older clang before we install
|
||||
sudo apt-get -qq remove 'clang-12*' 'clang-13*' 'clang-14*' 'clang-15*' 'clang-16*' 'llvm-12*' 'llvm-13*' 'llvm-14*' 'llvm-15*' 'llvm-16*' 'lld-12*' 'lld-13*' 'lld-14*' 'lld-15*' 'lld-16*' > /dev/null 2> /dev/null
|
||||
sudo apt-get -qq remove 'clang-12*' 'clang-13*' 'clang-14*' 'clang-15*' 'clang-16*' 'clang-17*' 'clang-18*' 'llvm-12*' 'llvm-13*' 'llvm-14*' 'llvm-15*' 'llvm-16*' 'lld-12*' 'lld-13*' 'lld-14*' 'lld-15*' 'lld-16*' 'lld-17*' 'lld-18*' > /dev/null 2> /dev/null
|
||||
|
||||
# Install clang-XXX, lld-XXX, and debootstrap.
|
||||
echo "deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-18 main" |
|
||||
sudo dd of=/etc/apt/sources.list.d/llvm-toolchain-jammy-18.list
|
||||
echo "deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-19 main" |
|
||||
sudo dd of=/etc/apt/sources.list.d/llvm-toolchain-jammy-19.list
|
||||
curl https://apt.llvm.org/llvm-snapshot.gpg.key |
|
||||
gpg --dearmor |
|
||||
sudo dd of=/etc/apt/trusted.gpg.d/llvm-snapshot.gpg
|
||||
sudo apt-get update
|
||||
# this was unreliable sometimes, so try again if it fails
|
||||
sudo apt-get install --no-install-recommends clang-18 lld-18 clang-tools-18 clang-format-18 clang-tidy-18 || echo 'Failed. Trying again.' && sudo apt-get clean && sudo apt-get update && sudo apt-get install --no-install-recommends clang-18 lld-18 clang-tools-18 clang-format-18 clang-tidy-18
|
||||
sudo apt-get install --no-install-recommends clang-19 lld-19 clang-tools-19 clang-format-19 clang-tidy-19 || echo 'Failed. Trying again.' && sudo apt-get clean && sudo apt-get update && sudo apt-get install --no-install-recommends clang-19 lld-19 clang-tools-19 clang-format-19 clang-tidy-19
|
||||
# Fix alternatives
|
||||
(yes '' | sudo update-alternatives --force --all) > /dev/null 2> /dev/null || true
|
||||
|
||||
echo "Decompressing sysroot..."
|
||||
wget -q https://github.com/denoland/deno_sysroot_build/releases/download/sysroot-20240528/sysroot-`uname -m`.tar.xz -O /tmp/sysroot.tar.xz
|
||||
wget -q https://github.com/denoland/deno_sysroot_build/releases/download/sysroot-20241030/sysroot-`uname -m`.tar.xz -O /tmp/sysroot.tar.xz
|
||||
cd /
|
||||
xzcat /tmp/sysroot.tar.xz | sudo tar -x
|
||||
sudo mount --rbind /dev /sysroot/dev
|
||||
|
@ -299,8 +299,8 @@ jobs:
|
|||
CARGO_PROFILE_RELEASE_LTO=false
|
||||
RUSTFLAGS<<__1
|
||||
-C linker-plugin-lto=true
|
||||
-C linker=clang-18
|
||||
-C link-arg=-fuse-ld=lld-18
|
||||
-C linker=clang-19
|
||||
-C link-arg=-fuse-ld=lld-19
|
||||
-C link-arg=-ldl
|
||||
-C link-arg=-Wl,--allow-shlib-undefined
|
||||
-C link-arg=-Wl,--thinlto-cache-dir=$(pwd)/target/release/lto-cache
|
||||
|
@ -310,8 +310,8 @@ jobs:
|
|||
__1
|
||||
RUSTDOCFLAGS<<__1
|
||||
-C linker-plugin-lto=true
|
||||
-C linker=clang-18
|
||||
-C link-arg=-fuse-ld=lld-18
|
||||
-C linker=clang-19
|
||||
-C link-arg=-fuse-ld=lld-19
|
||||
-C link-arg=-ldl
|
||||
-C link-arg=-Wl,--allow-shlib-undefined
|
||||
-C link-arg=-Wl,--thinlto-cache-dir=$(pwd)/target/release/lto-cache
|
||||
|
@ -319,7 +319,7 @@ jobs:
|
|||
--cfg tokio_unstable
|
||||
$RUSTFLAGS
|
||||
__1
|
||||
CC=/usr/bin/clang-18
|
||||
CC=/usr/bin/clang-19
|
||||
CFLAGS=-flto=thin $CFLAGS
|
||||
" > $GITHUB_ENV
|
||||
- name: Remove macOS cURL --ipv4 flag
|
||||
|
@ -361,8 +361,8 @@ jobs:
|
|||
path: |-
|
||||
~/.cargo/registry/index
|
||||
~/.cargo/registry/cache
|
||||
key: '22-cargo-home-${{ matrix.os }}-${{ matrix.arch }}-${{ hashFiles(''Cargo.lock'') }}'
|
||||
restore-keys: '22-cargo-home-${{ matrix.os }}-${{ matrix.arch }}'
|
||||
key: '24-cargo-home-${{ matrix.os }}-${{ matrix.arch }}-${{ hashFiles(''Cargo.lock'') }}'
|
||||
restore-keys: '24-cargo-home-${{ matrix.os }}-${{ matrix.arch }}'
|
||||
if: '!(matrix.skip)'
|
||||
- name: Restore cache build output (PR)
|
||||
uses: actions/cache/restore@v4
|
||||
|
@ -375,7 +375,7 @@ jobs:
|
|||
!./target/*/*.zip
|
||||
!./target/*/*.tar.gz
|
||||
key: never_saved
|
||||
restore-keys: '22-cargo-target-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.profile }}-${{ matrix.job }}-'
|
||||
restore-keys: '24-cargo-target-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.profile }}-${{ matrix.job }}-'
|
||||
- name: Apply and update mtime cache
|
||||
if: '!(matrix.skip) && (!startsWith(github.ref, ''refs/tags/''))'
|
||||
uses: ./.github/mtime_cache
|
||||
|
@ -685,10 +685,10 @@ jobs:
|
|||
!./target/*/*.zip
|
||||
!./target/*/*.sha256sum
|
||||
!./target/*/*.tar.gz
|
||||
key: '22-cargo-target-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.profile }}-${{ matrix.job }}-${{ github.sha }}'
|
||||
key: '24-cargo-target-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.profile }}-${{ matrix.job }}-${{ github.sha }}'
|
||||
publish-canary:
|
||||
name: publish canary
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-24.04
|
||||
needs:
|
||||
- build
|
||||
if: github.repository == 'denoland/deno' && github.ref == 'refs/heads/main'
|
||||
|
|
2
.github/workflows/post_publish.yml
vendored
2
.github/workflows/post_publish.yml
vendored
|
@ -7,7 +7,7 @@ on:
|
|||
jobs:
|
||||
update-dl-version:
|
||||
name: update dl.deno.land version
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-24.04
|
||||
if: github.repository == 'denoland/deno'
|
||||
steps:
|
||||
- name: Authenticate with Google Cloud
|
||||
|
|
2
.github/workflows/start_release.yml
vendored
2
.github/workflows/start_release.yml
vendored
|
@ -16,7 +16,7 @@ on:
|
|||
jobs:
|
||||
build:
|
||||
name: start release
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 30
|
||||
|
||||
env:
|
||||
|
|
2
.github/workflows/version_bump.yml
vendored
2
.github/workflows/version_bump.yml
vendored
|
@ -16,7 +16,7 @@ on:
|
|||
jobs:
|
||||
build:
|
||||
name: version bump
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 90
|
||||
|
||||
env:
|
||||
|
|
2
.github/workflows/wpt_epoch.yml
vendored
2
.github/workflows/wpt_epoch.yml
vendored
|
@ -20,7 +20,7 @@ jobs:
|
|||
fail-fast: false
|
||||
matrix:
|
||||
deno-version: [v1.x, canary]
|
||||
os: [ubuntu-22.04-xl]
|
||||
os: [ubuntu-24.04-xl]
|
||||
|
||||
steps:
|
||||
- name: Clone repository
|
||||
|
|
111
Cargo.lock
generated
111
Cargo.lock
generated
|
@ -1154,7 +1154,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno"
|
||||
version = "2.0.3"
|
||||
version = "2.0.5"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"async-trait",
|
||||
|
@ -1279,9 +1279,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_ast"
|
||||
version = "0.42.2"
|
||||
version = "0.43.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2b9d03b1bbeeecdac54367f075d572131736d06c5be3bc49037855bc5ab1bbb"
|
||||
checksum = "48d00b724e06d2081a141ec1155756a0b465d413d8e2a7515221f61d482eb2ee"
|
||||
dependencies = [
|
||||
"base64 0.21.7",
|
||||
"deno_media_type",
|
||||
|
@ -1323,7 +1323,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_bench_util"
|
||||
version = "0.168.0"
|
||||
version = "0.170.0"
|
||||
dependencies = [
|
||||
"bencher",
|
||||
"deno_core",
|
||||
|
@ -1332,7 +1332,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_broadcast_channel"
|
||||
version = "0.168.0"
|
||||
version = "0.170.0"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"deno_core",
|
||||
|
@ -1343,7 +1343,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_cache"
|
||||
version = "0.106.0"
|
||||
version = "0.108.0"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"deno_core",
|
||||
|
@ -1356,9 +1356,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_cache_dir"
|
||||
version = "0.13.1"
|
||||
version = "0.13.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "693ca429aebf945de5fef30df232044f9f80be4cc5a5e7c8d767226c43880f5a"
|
||||
checksum = "08c1f52170cd7715f8006da54cde1444863a0d6fbd9c11d037a737db2dec8e22"
|
||||
dependencies = [
|
||||
"base32",
|
||||
"deno_media_type",
|
||||
|
@ -1376,7 +1376,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_canvas"
|
||||
version = "0.43.0"
|
||||
version = "0.45.0"
|
||||
dependencies = [
|
||||
"deno_core",
|
||||
"deno_webgpu",
|
||||
|
@ -1387,9 +1387,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_config"
|
||||
version = "0.37.2"
|
||||
version = "0.38.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5900bfb37538d83b19ba0b157cdc785770e38422ee4632411e3bd3d90ac0f537"
|
||||
checksum = "966825073480a6ac7e01977a3879d13edc8d6ea2d65ea164b37156a5fb206e9a"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"deno_package_json",
|
||||
|
@ -1411,16 +1411,16 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_console"
|
||||
version = "0.174.0"
|
||||
version = "0.176.0"
|
||||
dependencies = [
|
||||
"deno_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "deno_core"
|
||||
version = "0.314.2"
|
||||
version = "0.318.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "83138917579676069b423c3eb9be3c1e579f60dc022d85f6ded4c792456255ff"
|
||||
checksum = "10cae2393219ff9278123f7b24799cdfab37c7d6561b69ca06ced115cac92111"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bincode",
|
||||
|
@ -1456,7 +1456,7 @@ checksum = "a13951ea98c0a4c372f162d669193b4c9d991512de9f2381dd161027f34b26b1"
|
|||
|
||||
[[package]]
|
||||
name = "deno_cron"
|
||||
version = "0.54.0"
|
||||
version = "0.56.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
|
@ -1469,7 +1469,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_crypto"
|
||||
version = "0.188.0"
|
||||
version = "0.190.0"
|
||||
dependencies = [
|
||||
"aes",
|
||||
"aes-gcm",
|
||||
|
@ -1506,9 +1506,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_doc"
|
||||
version = "0.154.0"
|
||||
version = "0.156.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "17e204e45b0d79750880114e37b34abe19ad0710d8435a8da8f23a528fe98de4"
|
||||
checksum = "2585b98d6ad76dae30bf2d7b6d71b8363cae041158b8780d14a2f4fe17590a61"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cfg-if",
|
||||
|
@ -1531,7 +1531,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_fetch"
|
||||
version = "0.198.0"
|
||||
version = "0.200.0"
|
||||
dependencies = [
|
||||
"base64 0.21.7",
|
||||
"bytes",
|
||||
|
@ -1564,7 +1564,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_ffi"
|
||||
version = "0.161.0"
|
||||
version = "0.163.0"
|
||||
dependencies = [
|
||||
"deno_core",
|
||||
"deno_permissions",
|
||||
|
@ -1584,7 +1584,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_fs"
|
||||
version = "0.84.0"
|
||||
version = "0.86.0"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"base32",
|
||||
|
@ -1606,9 +1606,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_graph"
|
||||
version = "0.83.4"
|
||||
version = "0.84.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5bd20bc0780071989c622cbfd5d4fb2e4fd05a247ccd7f791f13c8d2c3792228"
|
||||
checksum = "cd4f4a14aa069087be41c2998077b0453f0191747898f96e6343f700abfc2c18"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
|
@ -1635,7 +1635,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_http"
|
||||
version = "0.172.0"
|
||||
version = "0.174.0"
|
||||
dependencies = [
|
||||
"async-compression",
|
||||
"async-trait",
|
||||
|
@ -1674,7 +1674,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_io"
|
||||
version = "0.84.0"
|
||||
version = "0.86.0"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"deno_core",
|
||||
|
@ -1695,7 +1695,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_kv"
|
||||
version = "0.82.0"
|
||||
version = "0.84.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
|
@ -1726,9 +1726,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_lint"
|
||||
version = "0.67.0"
|
||||
version = "0.68.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "871b60e32bfb6c110cbb9b0688dbf048f81e5d347fe4ce5a42239263de9dd938"
|
||||
checksum = "bb994e6d1b18223df0a756c7948143b35682941d615edffef60d5b38822f38ac"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"deno_ast",
|
||||
|
@ -1756,9 +1756,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_media_type"
|
||||
version = "0.1.4"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a8978229b82552bf8457a0125aa20863f023619cfc21ebb007b1e571d68fd85b"
|
||||
checksum = "7fcf552fbdedbe81c89705349d7d2485c7051382b000dfddbdbf7fc25931cf83"
|
||||
dependencies = [
|
||||
"data-url",
|
||||
"serde",
|
||||
|
@ -1767,7 +1767,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_napi"
|
||||
version = "0.105.0"
|
||||
version = "0.107.0"
|
||||
dependencies = [
|
||||
"deno_core",
|
||||
"deno_permissions",
|
||||
|
@ -1795,7 +1795,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_net"
|
||||
version = "0.166.0"
|
||||
version = "0.168.0"
|
||||
dependencies = [
|
||||
"deno_core",
|
||||
"deno_permissions",
|
||||
|
@ -1812,7 +1812,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_node"
|
||||
version = "0.111.0"
|
||||
version = "0.113.0"
|
||||
dependencies = [
|
||||
"aead-gcm-stream",
|
||||
"aes",
|
||||
|
@ -1921,9 +1921,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_ops"
|
||||
version = "0.190.1"
|
||||
version = "0.194.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26f46d4e4f52f26c882b74a9b58810ea75252b807cf0966166ec333077cdfd85"
|
||||
checksum = "f760b492bd638c1dc3e992d11672c259fbe9a233162099a8347591c9e22d0391"
|
||||
dependencies = [
|
||||
"proc-macro-rules",
|
||||
"proc-macro2",
|
||||
|
@ -1961,7 +1961,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_permissions"
|
||||
version = "0.34.0"
|
||||
version = "0.36.0"
|
||||
dependencies = [
|
||||
"deno_core",
|
||||
"deno_path_util",
|
||||
|
@ -1972,13 +1972,14 @@ dependencies = [
|
|||
"once_cell",
|
||||
"percent-encoding",
|
||||
"serde",
|
||||
"thiserror",
|
||||
"which 4.4.2",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "deno_resolver"
|
||||
version = "0.6.0"
|
||||
version = "0.8.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"base32",
|
||||
|
@ -1994,7 +1995,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_runtime"
|
||||
version = "0.183.0"
|
||||
version = "0.185.0"
|
||||
dependencies = [
|
||||
"color-print",
|
||||
"deno_ast",
|
||||
|
@ -2112,7 +2113,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_tls"
|
||||
version = "0.161.0"
|
||||
version = "0.163.0"
|
||||
dependencies = [
|
||||
"deno_core",
|
||||
"deno_native_certs",
|
||||
|
@ -2161,7 +2162,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_url"
|
||||
version = "0.174.0"
|
||||
version = "0.176.0"
|
||||
dependencies = [
|
||||
"deno_bench_util",
|
||||
"deno_console",
|
||||
|
@ -2173,7 +2174,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_web"
|
||||
version = "0.205.0"
|
||||
version = "0.207.0"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"base64-simd 0.8.0",
|
||||
|
@ -2195,7 +2196,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_webgpu"
|
||||
version = "0.141.0"
|
||||
version = "0.143.0"
|
||||
dependencies = [
|
||||
"deno_core",
|
||||
"raw-window-handle",
|
||||
|
@ -2208,7 +2209,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_webidl"
|
||||
version = "0.174.0"
|
||||
version = "0.176.0"
|
||||
dependencies = [
|
||||
"deno_bench_util",
|
||||
"deno_core",
|
||||
|
@ -2216,7 +2217,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_websocket"
|
||||
version = "0.179.0"
|
||||
version = "0.181.0"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"deno_core",
|
||||
|
@ -2238,7 +2239,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "deno_webstorage"
|
||||
version = "0.169.0"
|
||||
version = "0.171.0"
|
||||
dependencies = [
|
||||
"deno_core",
|
||||
"deno_web",
|
||||
|
@ -2608,9 +2609,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "dprint-plugin-typescript"
|
||||
version = "0.93.0"
|
||||
version = "0.93.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e9308d98b923b7c0335c2ee1560199e3f2321b1be82803107b4ba4ed5dac46cc"
|
||||
checksum = "3ff29fd136541e59d51946f0d2d353fefc886776f61a799ebfb5838b06cef13b"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"deno_ast",
|
||||
|
@ -4194,9 +4195,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "libsui"
|
||||
version = "0.4.0"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "205eca4e7beaad637dcd38fe41292065894ee7f498077cf3c135d5f7252b9f27"
|
||||
checksum = "89795977654ad6250d6c0915411b622bac22f9efb4f852af94b2e00964cab832"
|
||||
dependencies = [
|
||||
"editpe",
|
||||
"libc",
|
||||
|
@ -4311,9 +4312,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "markup_fmt"
|
||||
version = "0.14.0"
|
||||
version = "0.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f15d7b24ae4ea9b87279bc0696462a4fb6c2168847f2cc162a2da05fe1a0f61"
|
||||
checksum = "ebae65c91eab3d42231232bf48107f351e5a8d511454927218c53aeb68bbdb6f"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"css_dataset",
|
||||
|
@ -4483,7 +4484,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "napi_sym"
|
||||
version = "0.104.0"
|
||||
version = "0.106.0"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"serde",
|
||||
|
@ -4538,7 +4539,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "node_resolver"
|
||||
version = "0.13.0"
|
||||
version = "0.15.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
|
@ -6169,9 +6170,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "serde_v8"
|
||||
version = "0.223.1"
|
||||
version = "0.227.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9cf3d859dda87ee96423c01244f10af864fa6d6a9fcdc2b77e0595078ea0ea11"
|
||||
checksum = "0a8294c2223c53bed343be8b80564ece4dc0d03b643b06fa86c4ccc0e064eda0"
|
||||
dependencies = [
|
||||
"num-bigint",
|
||||
"serde",
|
||||
|
|
64
Cargo.toml
64
Cargo.toml
|
@ -45,19 +45,19 @@ license = "MIT"
|
|||
repository = "https://github.com/denoland/deno"
|
||||
|
||||
[workspace.dependencies]
|
||||
deno_ast = { version = "=0.42.2", features = ["transpiling"] }
|
||||
deno_core = { version = "0.314.2" }
|
||||
deno_ast = { version = "=0.43.3", features = ["transpiling"] }
|
||||
deno_core = { version = "0.318.0" }
|
||||
|
||||
deno_bench_util = { version = "0.168.0", path = "./bench_util" }
|
||||
deno_bench_util = { version = "0.170.0", path = "./bench_util" }
|
||||
deno_lockfile = "=0.23.1"
|
||||
deno_media_type = { version = "0.1.4", features = ["module_specifier"] }
|
||||
deno_media_type = { version = "0.2.0", features = ["module_specifier"] }
|
||||
deno_npm = "=0.25.4"
|
||||
deno_path_util = "=0.2.1"
|
||||
deno_permissions = { version = "0.34.0", path = "./runtime/permissions" }
|
||||
deno_runtime = { version = "0.183.0", path = "./runtime" }
|
||||
deno_permissions = { version = "0.36.0", path = "./runtime/permissions" }
|
||||
deno_runtime = { version = "0.185.0", path = "./runtime" }
|
||||
deno_semver = "=0.5.16"
|
||||
deno_terminal = "0.2.0"
|
||||
napi_sym = { version = "0.104.0", path = "./ext/napi/sym" }
|
||||
napi_sym = { version = "0.106.0", path = "./ext/napi/sym" }
|
||||
test_util = { package = "test_server", path = "./tests/util/server" }
|
||||
|
||||
denokv_proto = "0.8.1"
|
||||
|
@ -66,32 +66,32 @@ denokv_remote = "0.8.1"
|
|||
denokv_sqlite = { default-features = false, version = "0.8.2" }
|
||||
|
||||
# exts
|
||||
deno_broadcast_channel = { version = "0.168.0", path = "./ext/broadcast_channel" }
|
||||
deno_cache = { version = "0.106.0", path = "./ext/cache" }
|
||||
deno_canvas = { version = "0.43.0", path = "./ext/canvas" }
|
||||
deno_console = { version = "0.174.0", path = "./ext/console" }
|
||||
deno_cron = { version = "0.54.0", path = "./ext/cron" }
|
||||
deno_crypto = { version = "0.188.0", path = "./ext/crypto" }
|
||||
deno_fetch = { version = "0.198.0", path = "./ext/fetch" }
|
||||
deno_ffi = { version = "0.161.0", path = "./ext/ffi" }
|
||||
deno_fs = { version = "0.84.0", path = "./ext/fs" }
|
||||
deno_http = { version = "0.172.0", path = "./ext/http" }
|
||||
deno_io = { version = "0.84.0", path = "./ext/io" }
|
||||
deno_kv = { version = "0.82.0", path = "./ext/kv" }
|
||||
deno_napi = { version = "0.105.0", path = "./ext/napi" }
|
||||
deno_net = { version = "0.166.0", path = "./ext/net" }
|
||||
deno_node = { version = "0.111.0", path = "./ext/node" }
|
||||
deno_tls = { version = "0.161.0", path = "./ext/tls" }
|
||||
deno_url = { version = "0.174.0", path = "./ext/url" }
|
||||
deno_web = { version = "0.205.0", path = "./ext/web" }
|
||||
deno_webgpu = { version = "0.141.0", path = "./ext/webgpu" }
|
||||
deno_webidl = { version = "0.174.0", path = "./ext/webidl" }
|
||||
deno_websocket = { version = "0.179.0", path = "./ext/websocket" }
|
||||
deno_webstorage = { version = "0.169.0", path = "./ext/webstorage" }
|
||||
deno_broadcast_channel = { version = "0.170.0", path = "./ext/broadcast_channel" }
|
||||
deno_cache = { version = "0.108.0", path = "./ext/cache" }
|
||||
deno_canvas = { version = "0.45.0", path = "./ext/canvas" }
|
||||
deno_console = { version = "0.176.0", path = "./ext/console" }
|
||||
deno_cron = { version = "0.56.0", path = "./ext/cron" }
|
||||
deno_crypto = { version = "0.190.0", path = "./ext/crypto" }
|
||||
deno_fetch = { version = "0.200.0", path = "./ext/fetch" }
|
||||
deno_ffi = { version = "0.163.0", path = "./ext/ffi" }
|
||||
deno_fs = { version = "0.86.0", path = "./ext/fs" }
|
||||
deno_http = { version = "0.174.0", path = "./ext/http" }
|
||||
deno_io = { version = "0.86.0", path = "./ext/io" }
|
||||
deno_kv = { version = "0.84.0", path = "./ext/kv" }
|
||||
deno_napi = { version = "0.107.0", path = "./ext/napi" }
|
||||
deno_net = { version = "0.168.0", path = "./ext/net" }
|
||||
deno_node = { version = "0.113.0", path = "./ext/node" }
|
||||
deno_tls = { version = "0.163.0", path = "./ext/tls" }
|
||||
deno_url = { version = "0.176.0", path = "./ext/url" }
|
||||
deno_web = { version = "0.207.0", path = "./ext/web" }
|
||||
deno_webgpu = { version = "0.143.0", path = "./ext/webgpu" }
|
||||
deno_webidl = { version = "0.176.0", path = "./ext/webidl" }
|
||||
deno_websocket = { version = "0.181.0", path = "./ext/websocket" }
|
||||
deno_webstorage = { version = "0.171.0", path = "./ext/webstorage" }
|
||||
|
||||
# resolvers
|
||||
deno_resolver = { version = "0.6.0", path = "./resolvers/deno" }
|
||||
node_resolver = { version = "0.13.0", path = "./resolvers/node" }
|
||||
deno_resolver = { version = "0.8.0", path = "./resolvers/deno" }
|
||||
node_resolver = { version = "0.15.0", path = "./resolvers/node" }
|
||||
|
||||
aes = "=0.8.3"
|
||||
anyhow = "1.0.57"
|
||||
|
@ -111,7 +111,7 @@ console_static_text = "=0.8.1"
|
|||
dashmap = "5.5.3"
|
||||
data-encoding = "2.3.3"
|
||||
data-url = "=0.3.0"
|
||||
deno_cache_dir = "=0.13.1"
|
||||
deno_cache_dir = "=0.13.2"
|
||||
deno_package_json = { version = "0.1.2", default-features = false }
|
||||
dlopen2 = "0.6.1"
|
||||
ecb = "=0.1.2"
|
||||
|
|
68
Releases.md
68
Releases.md
|
@ -6,6 +6,74 @@ https://github.com/denoland/deno/releases
|
|||
We also have one-line install commands at:
|
||||
https://github.com/denoland/deno_install
|
||||
|
||||
### 2.0.5 / 2024.11.05
|
||||
|
||||
- fix(add): better error message when adding package that only has pre-release
|
||||
versions (#26724)
|
||||
- fix(add): only add npm deps to package.json if it's at least as close as
|
||||
deno.json (#26683)
|
||||
- fix(cli): set `npm_config_user_agent` when running npm packages or tasks
|
||||
(#26639)
|
||||
- fix(coverage): exclude comment lines from coverage reports (#25939)
|
||||
- fix(ext/node): add `findSourceMap` to the default export of `node:module`
|
||||
(#26720)
|
||||
- fix(ext/node): convert errors from `fs.readFile/fs.readFileSync` to node
|
||||
format (#26632)
|
||||
- fix(ext/node): resolve exports even if parent module filename isn't present
|
||||
(#26553)
|
||||
- fix(ext/node): return `this` from `http.Server.ref/unref()` (#26647)
|
||||
- fix(fmt): do not panic for jsx ignore container followed by jsx text (#26723)
|
||||
- fix(fmt): fix several HTML and components issues (#26654)
|
||||
- fix(fmt): ignore file directive for YAML files (#26717)
|
||||
- fix(install): handle invalid function error, and fallback to junctions
|
||||
regardless of the error (#26730)
|
||||
- fix(lsp): include unstable features from editor settings (#26655)
|
||||
- fix(lsp): scope attribution for lazily loaded assets (#26699)
|
||||
- fix(node): Implement `os.userInfo` properly, add missing `toPrimitive`
|
||||
(#24702)
|
||||
- fix(serve): support serve hmr (#26078)
|
||||
- fix(types): missing `import` permission on `PermissionOptionsObject` (#26627)
|
||||
- fix(workspace): support wildcard packages (#26568)
|
||||
- fix: clamp smi in fast calls by default (#26506)
|
||||
- fix: improved support for cjs and cts modules (#26558)
|
||||
- fix: op_run_microtasks crash (#26718)
|
||||
- fix: panic_hook hangs without procfs (#26732)
|
||||
- fix: remove permission check in op_require_node_module_paths (#26645)
|
||||
- fix: surface package.json location on dep parse failure (#26665)
|
||||
- perf(lsp): don't walk coverage directory (#26715)
|
||||
|
||||
### 2.0.4 / 2024.10.29
|
||||
|
||||
- Revert "fix(ext/node): fix dns.lookup result ordering (#26264)" (#26621)
|
||||
- Revert "fix(ext/node): use primordials in `ext/node/polyfills/https.ts`
|
||||
(#26323)" (#26613)
|
||||
- feat(lsp): "typescript.preferences.preferTypeOnlyAutoImports" setting (#26546)
|
||||
- fix(check): expose more globals from @types/node (#26603)
|
||||
- fix(check): ignore resolving `jsxImportSource` when jsx is not used in graph
|
||||
(#26548)
|
||||
- fix(cli): Make --watcher CLEAR_SCREEN clear scrollback buffer as well as
|
||||
visible screen (#25997)
|
||||
- fix(compile): regression handling redirects (#26586)
|
||||
- fix(ext/napi): export dynamic symbols list for {Free,Open}BSD (#26605)
|
||||
- fix(ext/node): add path to `fs.stat` and `fs.statSync` error (#26037)
|
||||
- fix(ext/node): compatibility with {Free,Open}BSD (#26604)
|
||||
- fix(ext/node): use primordials in
|
||||
ext\node\polyfills\internal\crypto\_randomInt.ts (#26534)
|
||||
- fix(install): cache json exports of JSR packages (#26552)
|
||||
- fix(install): regression - do not panic when config file contains \r\n
|
||||
newlines (#26547)
|
||||
- fix(lsp): make missing import action fix infallible (#26539)
|
||||
- fix(npm): match npm bearer token generation (#26544)
|
||||
- fix(upgrade): stop running `deno lsp` processes on windows before attempting
|
||||
to replace executable (#26542)
|
||||
- fix(watch): don't panic on invalid file specifiers (#26577)
|
||||
- fix: do not panic when failing to write to http cache (#26591)
|
||||
- fix: provide hints in terminal errors for Node.js globals (#26610)
|
||||
- fix: report exceptions from nextTick (#26579)
|
||||
- fix: support watch flag to enable watching other files than the main module on
|
||||
serve subcommand (#26622)
|
||||
- perf: pass transpiled module to deno_core as known string (#26555)
|
||||
|
||||
### 2.0.3 / 2024.10.25
|
||||
|
||||
- feat(lsp): interactive inlay hints (#26382)
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
[package]
|
||||
name = "deno_bench_util"
|
||||
version = "0.168.0"
|
||||
version = "0.170.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
[package]
|
||||
name = "deno"
|
||||
version = "2.0.3"
|
||||
version = "2.0.5"
|
||||
authors.workspace = true
|
||||
default-run = "deno"
|
||||
edition.workspace = true
|
||||
|
@ -70,11 +70,11 @@ winres.workspace = true
|
|||
[dependencies]
|
||||
deno_ast = { workspace = true, features = ["bundler", "cjs", "codegen", "proposal", "react", "sourcemap", "transforms", "typescript", "view", "visit"] }
|
||||
deno_cache_dir = { workspace = true }
|
||||
deno_config = { version = "=0.37.2", features = ["workspace", "sync"] }
|
||||
deno_config = { version = "=0.38.2", features = ["workspace", "sync"] }
|
||||
deno_core = { workspace = true, features = ["include_js_files_for_snapshotting"] }
|
||||
deno_doc = { version = "0.154.0", default-features = false, features = ["rust", "html", "syntect"] }
|
||||
deno_graph = { version = "=0.83.4" }
|
||||
deno_lint = { version = "=0.67.0", features = ["docs"] }
|
||||
deno_doc = { version = "0.156.0", default-features = false, features = ["rust", "html", "syntect"] }
|
||||
deno_graph = { version = "=0.84.1" }
|
||||
deno_lint = { version = "=0.68.0", features = ["docs"] }
|
||||
deno_lockfile.workspace = true
|
||||
deno_npm.workspace = true
|
||||
deno_package_json.workspace = true
|
||||
|
@ -84,7 +84,7 @@ deno_runtime = { workspace = true, features = ["include_js_files_for_snapshottin
|
|||
deno_semver.workspace = true
|
||||
deno_task_shell = "=0.18.1"
|
||||
deno_terminal.workspace = true
|
||||
libsui = "0.4.0"
|
||||
libsui = "0.5.0"
|
||||
node_resolver.workspace = true
|
||||
|
||||
anstream = "0.6.14"
|
||||
|
@ -107,7 +107,7 @@ dotenvy = "0.15.7"
|
|||
dprint-plugin-json = "=0.19.4"
|
||||
dprint-plugin-jupyter = "=0.1.5"
|
||||
dprint-plugin-markdown = "=0.17.8"
|
||||
dprint-plugin-typescript = "=0.93.0"
|
||||
dprint-plugin-typescript = "=0.93.2"
|
||||
env_logger = "=0.10.0"
|
||||
fancy-regex = "=0.10.0"
|
||||
faster-hex.workspace = true
|
||||
|
@ -129,7 +129,7 @@ libz-sys.workspace = true
|
|||
log = { workspace = true, features = ["serde"] }
|
||||
lsp-types.workspace = true
|
||||
malva = "=0.11.0"
|
||||
markup_fmt = "=0.14.0"
|
||||
markup_fmt = "=0.15.0"
|
||||
memmem.workspace = true
|
||||
monch.workspace = true
|
||||
notify.workspace = true
|
||||
|
|
|
@ -1179,8 +1179,8 @@ static DENO_HELP: &str = cstr!(
|
|||
<y>Dependency management:</>
|
||||
<g>add</> Add dependencies
|
||||
<p(245)>deno add jsr:@std/assert | deno add npm:express</>
|
||||
<g>install</> Install script as an executable
|
||||
<g>uninstall</> Uninstall a script previously installed with deno install
|
||||
<g>install</> Installs dependencies either in the local project or globally to a bin directory
|
||||
<g>uninstall</> Uninstalls a dependency or an executable script in the installation root's bin directory
|
||||
<g>remove</> Remove dependencies from the configuration file
|
||||
|
||||
<y>Tooling:</>
|
||||
|
@ -3388,8 +3388,7 @@ fn permission_args(app: Command, requires: Option<&'static str>) -> Command {
|
|||
.value_name("IP_OR_HOSTNAME")
|
||||
.help("Allow network access. Optionally specify allowed IP addresses and host names, with ports as necessary")
|
||||
.value_parser(flags_net::validator)
|
||||
.hide(true)
|
||||
;
|
||||
.hide(true);
|
||||
if let Some(requires) = requires {
|
||||
arg = arg.requires(requires)
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ pub fn parse(paths: Vec<String>) -> clap::error::Result<Vec<String>> {
|
|||
}
|
||||
} else {
|
||||
NetDescriptor::parse(&host_and_port).map_err(|e| {
|
||||
clap::Error::raw(clap::error::ErrorKind::InvalidValue, format!("{e:?}"))
|
||||
clap::Error::raw(clap::error::ErrorKind::InvalidValue, e.to_string())
|
||||
})?;
|
||||
out.push(host_and_port)
|
||||
}
|
||||
|
|
|
@ -46,6 +46,7 @@ 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;
|
||||
|
@ -200,6 +201,8 @@ pub fn ts_config_to_transpile_and_emit_options(
|
|||
precompile_jsx_dynamic_props: None,
|
||||
transform_jsx,
|
||||
var_decl_imports: false,
|
||||
// todo(dsherret): support verbatim_module_syntax here properly
|
||||
verbatim_module_syntax: false,
|
||||
},
|
||||
deno_ast::EmitOptions {
|
||||
inline_sources: options.inline_sources,
|
||||
|
@ -1452,6 +1455,12 @@ impl CliOptions {
|
|||
watch: Some(WatchFlagsWithPaths { hmr, .. }),
|
||||
..
|
||||
}) = &self.flags.subcommand
|
||||
{
|
||||
*hmr
|
||||
} else if let DenoSubcommand::Serve(ServeFlags {
|
||||
watch: Some(WatchFlagsWithPaths { hmr, .. }),
|
||||
..
|
||||
}) = &self.flags.subcommand
|
||||
{
|
||||
*hmr
|
||||
} else {
|
||||
|
@ -1595,6 +1604,15 @@ impl CliOptions {
|
|||
}
|
||||
|
||||
pub fn use_byonm(&self) -> bool {
|
||||
if matches!(
|
||||
self.sub_command(),
|
||||
DenoSubcommand::Install(_)
|
||||
| DenoSubcommand::Add(_)
|
||||
| DenoSubcommand::Remove(_)
|
||||
) {
|
||||
// For `deno install/add/remove` we want to force the managed resolver so it can set up `node_modules/` directory.
|
||||
return false;
|
||||
}
|
||||
if self.node_modules_dir().ok().flatten().is_none()
|
||||
&& self.maybe_node_modules_folder.is_some()
|
||||
&& self
|
||||
|
|
|
@ -5,10 +5,12 @@ use std::sync::Arc;
|
|||
|
||||
use deno_config::workspace::Workspace;
|
||||
use deno_core::serde_json;
|
||||
use deno_core::url::Url;
|
||||
use deno_package_json::PackageJsonDepValue;
|
||||
use deno_package_json::PackageJsonDepValueParseError;
|
||||
use deno_semver::npm::NpmPackageReqReference;
|
||||
use deno_semver::package::PackageReq;
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct InstallNpmRemotePkg {
|
||||
|
@ -23,11 +25,20 @@ pub struct InstallNpmWorkspacePkg {
|
|||
pub target_dir: PathBuf,
|
||||
}
|
||||
|
||||
#[derive(Debug, Error, Clone)]
|
||||
#[error("Failed to install '{}'\n at {}", alias, location)]
|
||||
pub struct PackageJsonDepValueParseWithLocationError {
|
||||
pub location: Url,
|
||||
pub alias: String,
|
||||
#[source]
|
||||
pub source: PackageJsonDepValueParseError,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct NpmInstallDepsProvider {
|
||||
remote_pkgs: Vec<InstallNpmRemotePkg>,
|
||||
workspace_pkgs: Vec<InstallNpmWorkspacePkg>,
|
||||
pkg_json_dep_errors: Vec<PackageJsonDepValueParseError>,
|
||||
pkg_json_dep_errors: Vec<PackageJsonDepValueParseWithLocationError>,
|
||||
}
|
||||
|
||||
impl NpmInstallDepsProvider {
|
||||
|
@ -89,7 +100,13 @@ impl NpmInstallDepsProvider {
|
|||
let dep = match dep {
|
||||
Ok(dep) => dep,
|
||||
Err(err) => {
|
||||
pkg_json_dep_errors.push(err);
|
||||
pkg_json_dep_errors.push(
|
||||
PackageJsonDepValueParseWithLocationError {
|
||||
location: pkg_json.specifier(),
|
||||
alias,
|
||||
source: err,
|
||||
},
|
||||
);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
@ -150,7 +167,9 @@ impl NpmInstallDepsProvider {
|
|||
&self.workspace_pkgs
|
||||
}
|
||||
|
||||
pub fn pkg_json_dep_errors(&self) -> &[PackageJsonDepValueParseError] {
|
||||
pub fn pkg_json_dep_errors(
|
||||
&self,
|
||||
) -> &[PackageJsonDepValueParseWithLocationError] {
|
||||
&self.pkg_json_dep_errors
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
// deno-lint-ignore-file no-console
|
||||
// deno-lint-ignore-file no-console no-process-globals
|
||||
|
||||
let [total, count] = typeof Deno !== "undefined"
|
||||
? Deno.args
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
// deno-lint-ignore-file no-console
|
||||
// deno-lint-ignore-file no-console no-process-globals
|
||||
|
||||
let [total, count] = typeof Deno !== "undefined"
|
||||
? Deno.args
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
// deno-lint-ignore-file no-console
|
||||
// deno-lint-ignore-file no-console no-process-globals
|
||||
|
||||
const queueMicrotask = globalThis.queueMicrotask || process.nextTick;
|
||||
let [total, count] = typeof Deno !== "undefined"
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
// deno-lint-ignore-file no-console
|
||||
// deno-lint-ignore-file no-console no-process-globals
|
||||
|
||||
let [total, count] = typeof Deno !== "undefined"
|
||||
? Deno.args
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
// deno-lint-ignore-file no-console
|
||||
// deno-lint-ignore-file no-console no-process-globals
|
||||
|
||||
const queueMicrotask = globalThis.queueMicrotask || process.nextTick;
|
||||
let [total, count] = typeof Deno !== "undefined"
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
// deno-lint-ignore-file no-console
|
||||
// deno-lint-ignore-file no-console no-process-globals
|
||||
|
||||
const queueMicrotask = globalThis.queueMicrotask || process.nextTick;
|
||||
let [total, count] = typeof Deno !== "undefined"
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
// deno-lint-ignore-file no-console
|
||||
// deno-lint-ignore-file no-console no-process-globals
|
||||
|
||||
const queueMicrotask = globalThis.queueMicrotask || process.nextTick;
|
||||
let [total, count] = typeof Deno !== "undefined"
|
||||
|
|
6
cli/cache/cache_db.rs
vendored
6
cli/cache/cache_db.rs
vendored
|
@ -57,7 +57,7 @@ impl rusqlite::types::FromSql for CacheDBHash {
|
|||
}
|
||||
|
||||
/// What should the cache should do on failure?
|
||||
#[derive(Default)]
|
||||
#[derive(Debug, Default)]
|
||||
pub enum CacheFailure {
|
||||
/// Return errors if failure mode otherwise unspecified.
|
||||
#[default]
|
||||
|
@ -69,6 +69,7 @@ pub enum CacheFailure {
|
|||
}
|
||||
|
||||
/// Configuration SQL and other parameters for a [`CacheDB`].
|
||||
#[derive(Debug)]
|
||||
pub struct CacheDBConfiguration {
|
||||
/// SQL to run for a new database.
|
||||
pub table_initializer: &'static str,
|
||||
|
@ -98,6 +99,7 @@ impl CacheDBConfiguration {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum ConnectionState {
|
||||
Connected(Connection),
|
||||
Blackhole,
|
||||
|
@ -106,7 +108,7 @@ enum ConnectionState {
|
|||
|
||||
/// A cache database that eagerly initializes itself off-thread, preventing initialization operations
|
||||
/// from blocking the main thread.
|
||||
#[derive(Clone)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct CacheDB {
|
||||
// TODO(mmastrac): We can probably simplify our thread-safe implementation here
|
||||
conn: Arc<Mutex<OnceCell<ConnectionState>>>,
|
||||
|
|
2
cli/cache/emit.rs
vendored
2
cli/cache/emit.rs
vendored
|
@ -10,6 +10,7 @@ use deno_core::unsync::sync::AtomicFlag;
|
|||
use super::DiskCache;
|
||||
|
||||
/// The cache that stores previously emitted files.
|
||||
#[derive(Debug)]
|
||||
pub struct EmitCache {
|
||||
disk_cache: DiskCache,
|
||||
emit_failed_flag: AtomicFlag,
|
||||
|
@ -91,6 +92,7 @@ impl EmitCache {
|
|||
|
||||
const LAST_LINE_PREFIX: &str = "\n// denoCacheMetadata=";
|
||||
|
||||
#[derive(Debug)]
|
||||
struct EmitFileSerializer {
|
||||
cli_version: &'static str,
|
||||
}
|
||||
|
|
101
cli/cache/mod.rs
vendored
101
cli/cache/mod.rs
vendored
|
@ -8,14 +8,9 @@ use crate::file_fetcher::FetchOptions;
|
|||
use crate::file_fetcher::FetchPermissionsOptionRef;
|
||||
use crate::file_fetcher::FileFetcher;
|
||||
use crate::file_fetcher::FileOrRedirect;
|
||||
use crate::npm::CliNpmResolver;
|
||||
use crate::resolver::CliNodeResolver;
|
||||
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 crate::util::path::specifier_has_extension;
|
||||
use crate::util::text_encoding::arc_str_to_bytes;
|
||||
use crate::util::text_encoding::from_utf8_lossy_owned;
|
||||
|
||||
use deno_ast::MediaType;
|
||||
use deno_core::futures;
|
||||
|
@ -25,7 +20,9 @@ use deno_graph::source::CacheInfo;
|
|||
use deno_graph::source::LoadFuture;
|
||||
use deno_graph::source::LoadResponse;
|
||||
use deno_graph::source::Loader;
|
||||
use deno_runtime::deno_fs;
|
||||
use deno_runtime::deno_permissions::PermissionsContainer;
|
||||
use node_resolver::InNpmPackageChecker;
|
||||
use std::collections::HashMap;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
|
@ -60,7 +57,6 @@ pub use fast_check::FastCheckCache;
|
|||
pub use incremental::IncrementalCache;
|
||||
pub use module_info::ModuleInfoCache;
|
||||
pub use node::NodeAnalysisCache;
|
||||
pub use parsed_source::EsmOrCjsChecker;
|
||||
pub use parsed_source::LazyGraphSourceParser;
|
||||
pub use parsed_source::ParsedSourceCache;
|
||||
|
||||
|
@ -181,46 +177,40 @@ pub struct FetchCacherOptions {
|
|||
pub permissions: PermissionsContainer,
|
||||
/// If we're publishing for `deno publish`.
|
||||
pub is_deno_publish: bool,
|
||||
pub unstable_detect_cjs: bool,
|
||||
}
|
||||
|
||||
/// A "wrapper" for the FileFetcher and DiskCache for the Deno CLI that provides
|
||||
/// a concise interface to the DENO_DIR when building module graphs.
|
||||
pub struct FetchCacher {
|
||||
pub file_header_overrides: HashMap<ModuleSpecifier, HashMap<String, String>>,
|
||||
esm_or_cjs_checker: Arc<EsmOrCjsChecker>,
|
||||
file_fetcher: Arc<FileFetcher>,
|
||||
fs: Arc<dyn deno_fs::FileSystem>,
|
||||
global_http_cache: Arc<GlobalHttpCache>,
|
||||
node_resolver: Arc<CliNodeResolver>,
|
||||
npm_resolver: Arc<dyn CliNpmResolver>,
|
||||
in_npm_pkg_checker: Arc<dyn InNpmPackageChecker>,
|
||||
module_info_cache: Arc<ModuleInfoCache>,
|
||||
permissions: PermissionsContainer,
|
||||
is_deno_publish: bool,
|
||||
unstable_detect_cjs: bool,
|
||||
cache_info_enabled: bool,
|
||||
}
|
||||
|
||||
impl FetchCacher {
|
||||
pub fn new(
|
||||
esm_or_cjs_checker: Arc<EsmOrCjsChecker>,
|
||||
file_fetcher: Arc<FileFetcher>,
|
||||
fs: Arc<dyn deno_fs::FileSystem>,
|
||||
global_http_cache: Arc<GlobalHttpCache>,
|
||||
node_resolver: Arc<CliNodeResolver>,
|
||||
npm_resolver: Arc<dyn CliNpmResolver>,
|
||||
in_npm_pkg_checker: Arc<dyn InNpmPackageChecker>,
|
||||
module_info_cache: Arc<ModuleInfoCache>,
|
||||
options: FetchCacherOptions,
|
||||
) -> Self {
|
||||
Self {
|
||||
file_fetcher,
|
||||
esm_or_cjs_checker,
|
||||
fs,
|
||||
global_http_cache,
|
||||
node_resolver,
|
||||
npm_resolver,
|
||||
in_npm_pkg_checker,
|
||||
module_info_cache,
|
||||
file_header_overrides: options.file_header_overrides,
|
||||
permissions: options.permissions,
|
||||
is_deno_publish: options.is_deno_publish,
|
||||
unstable_detect_cjs: options.unstable_detect_cjs,
|
||||
cache_info_enabled: false,
|
||||
}
|
||||
}
|
||||
|
@ -271,70 +261,23 @@ impl Loader for FetchCacher {
|
|||
) -> LoadFuture {
|
||||
use deno_graph::source::CacheSetting as LoaderCacheSetting;
|
||||
|
||||
if specifier.scheme() == "file" {
|
||||
if specifier.path().contains("/node_modules/") {
|
||||
// The specifier might be in a completely different symlinked tree than
|
||||
// what the node_modules url is in (ex. `/my-project-1/node_modules`
|
||||
// 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
|
||||
// against the canonicalized specifier.
|
||||
let specifier =
|
||||
crate::node::resolve_specifier_into_node_modules(specifier);
|
||||
if self.npm_resolver.in_npm_package(&specifier) {
|
||||
return Box::pin(futures::future::ready(Ok(Some(
|
||||
LoadResponse::External { specifier },
|
||||
))));
|
||||
}
|
||||
}
|
||||
|
||||
// make local CJS modules external to the graph
|
||||
if specifier_has_extension(specifier, "cjs") {
|
||||
if specifier.scheme() == "file"
|
||||
&& specifier.path().contains("/node_modules/")
|
||||
{
|
||||
// The specifier might be in a completely different symlinked tree than
|
||||
// what the node_modules url is in (ex. `/my-project-1/node_modules`
|
||||
// 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
|
||||
// against the canonicalized specifier.
|
||||
let specifier = crate::node::resolve_specifier_into_node_modules(
|
||||
specifier,
|
||||
self.fs.as_ref(),
|
||||
);
|
||||
if self.in_npm_pkg_checker.in_npm_package(&specifier) {
|
||||
return Box::pin(futures::future::ready(Ok(Some(
|
||||
LoadResponse::External {
|
||||
specifier: specifier.clone(),
|
||||
},
|
||||
LoadResponse::External { specifier },
|
||||
))));
|
||||
}
|
||||
|
||||
if self.unstable_detect_cjs && specifier_has_extension(specifier, "js") {
|
||||
if let Ok(Some(pkg_json)) =
|
||||
self.node_resolver.get_closest_package_json(specifier)
|
||||
{
|
||||
if pkg_json.typ == "commonjs" {
|
||||
if let Ok(path) = specifier.to_file_path() {
|
||||
if let Ok(bytes) = std::fs::read(&path) {
|
||||
let text: Arc<str> = from_utf8_lossy_owned(bytes).into();
|
||||
let is_es_module = match self.esm_or_cjs_checker.is_esm(
|
||||
specifier,
|
||||
text.clone(),
|
||||
MediaType::JavaScript,
|
||||
) {
|
||||
Ok(value) => value,
|
||||
Err(err) => {
|
||||
return Box::pin(futures::future::ready(Err(err.into())));
|
||||
}
|
||||
};
|
||||
if !is_es_module {
|
||||
self.node_resolver.mark_cjs_resolution(specifier.clone());
|
||||
return Box::pin(futures::future::ready(Ok(Some(
|
||||
LoadResponse::External {
|
||||
specifier: specifier.clone(),
|
||||
},
|
||||
))));
|
||||
} else {
|
||||
return Box::pin(futures::future::ready(Ok(Some(
|
||||
LoadResponse::Module {
|
||||
specifier: specifier.clone(),
|
||||
content: arc_str_to_bytes(text),
|
||||
maybe_headers: None,
|
||||
},
|
||||
))));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if self.is_deno_publish
|
||||
|
|
140
cli/cache/module_info.rs
vendored
140
cli/cache/module_info.rs
vendored
|
@ -44,18 +44,32 @@ pub static MODULE_INFO_CACHE_DB: CacheDBConfiguration = CacheDBConfiguration {
|
|||
/// A cache of `deno_graph::ModuleInfo` objects. Using this leads to a considerable
|
||||
/// performance improvement because when it exists we can skip parsing a module for
|
||||
/// deno_graph.
|
||||
#[derive(Debug)]
|
||||
pub struct ModuleInfoCache {
|
||||
conn: CacheDB,
|
||||
parsed_source_cache: Arc<ParsedSourceCache>,
|
||||
}
|
||||
|
||||
impl ModuleInfoCache {
|
||||
#[cfg(test)]
|
||||
pub fn new_in_memory(version: &'static str) -> Self {
|
||||
Self::new(CacheDB::in_memory(&MODULE_INFO_CACHE_DB, version))
|
||||
pub fn new_in_memory(
|
||||
version: &'static str,
|
||||
parsed_source_cache: Arc<ParsedSourceCache>,
|
||||
) -> Self {
|
||||
Self::new(
|
||||
CacheDB::in_memory(&MODULE_INFO_CACHE_DB, version),
|
||||
parsed_source_cache,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn new(conn: CacheDB) -> Self {
|
||||
Self { conn }
|
||||
pub fn new(
|
||||
conn: CacheDB,
|
||||
parsed_source_cache: Arc<ParsedSourceCache>,
|
||||
) -> Self {
|
||||
Self {
|
||||
conn,
|
||||
parsed_source_cache,
|
||||
}
|
||||
}
|
||||
|
||||
/// Useful for testing: re-create this cache DB with a different current version.
|
||||
|
@ -63,6 +77,7 @@ impl ModuleInfoCache {
|
|||
pub(crate) fn recreate_with_version(self, version: &'static str) -> Self {
|
||||
Self {
|
||||
conn: self.conn.recreate_with_version(version),
|
||||
parsed_source_cache: self.parsed_source_cache,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -113,13 +128,10 @@ impl ModuleInfoCache {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn as_module_analyzer<'a>(
|
||||
&'a self,
|
||||
parsed_source_cache: &'a Arc<ParsedSourceCache>,
|
||||
) -> ModuleInfoCacheModuleAnalyzer<'a> {
|
||||
pub fn as_module_analyzer(&self) -> ModuleInfoCacheModuleAnalyzer {
|
||||
ModuleInfoCacheModuleAnalyzer {
|
||||
module_info_cache: self,
|
||||
parsed_source_cache,
|
||||
parsed_source_cache: &self.parsed_source_cache,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -129,6 +141,84 @@ pub struct ModuleInfoCacheModuleAnalyzer<'a> {
|
|||
parsed_source_cache: &'a Arc<ParsedSourceCache>,
|
||||
}
|
||||
|
||||
impl<'a> ModuleInfoCacheModuleAnalyzer<'a> {
|
||||
fn load_cached_module_info(
|
||||
&self,
|
||||
specifier: &ModuleSpecifier,
|
||||
media_type: MediaType,
|
||||
source_hash: CacheDBHash,
|
||||
) -> Option<ModuleInfo> {
|
||||
match self.module_info_cache.get_module_info(
|
||||
specifier,
|
||||
media_type,
|
||||
source_hash,
|
||||
) {
|
||||
Ok(Some(info)) => Some(info),
|
||||
Ok(None) => None,
|
||||
Err(err) => {
|
||||
log::debug!(
|
||||
"Error loading module cache info for {}. {:#}",
|
||||
specifier,
|
||||
err
|
||||
);
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn save_module_info_to_cache(
|
||||
&self,
|
||||
specifier: &ModuleSpecifier,
|
||||
media_type: MediaType,
|
||||
source_hash: CacheDBHash,
|
||||
module_info: &ModuleInfo,
|
||||
) {
|
||||
if let Err(err) = self.module_info_cache.set_module_info(
|
||||
specifier,
|
||||
media_type,
|
||||
source_hash,
|
||||
module_info,
|
||||
) {
|
||||
log::debug!(
|
||||
"Error saving module cache info for {}. {:#}",
|
||||
specifier,
|
||||
err
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn analyze_sync(
|
||||
&self,
|
||||
specifier: &ModuleSpecifier,
|
||||
media_type: MediaType,
|
||||
source: &Arc<str>,
|
||||
) -> Result<ModuleInfo, deno_ast::ParseDiagnostic> {
|
||||
// attempt to load from the cache
|
||||
let source_hash = CacheDBHash::from_source(source);
|
||||
if let Some(info) =
|
||||
self.load_cached_module_info(specifier, media_type, source_hash)
|
||||
{
|
||||
return Ok(info);
|
||||
}
|
||||
|
||||
// otherwise, get the module info from the parsed source cache
|
||||
let parser = self.parsed_source_cache.as_capturing_parser();
|
||||
let analyzer = ParserModuleAnalyzer::new(&parser);
|
||||
let module_info =
|
||||
analyzer.analyze_sync(specifier, source.clone(), media_type)?;
|
||||
|
||||
// then attempt to cache it
|
||||
self.save_module_info_to_cache(
|
||||
specifier,
|
||||
media_type,
|
||||
source_hash,
|
||||
&module_info,
|
||||
);
|
||||
|
||||
Ok(module_info)
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl<'a> deno_graph::ModuleAnalyzer for ModuleInfoCacheModuleAnalyzer<'a> {
|
||||
async fn analyze(
|
||||
|
@ -139,20 +229,10 @@ impl<'a> deno_graph::ModuleAnalyzer for ModuleInfoCacheModuleAnalyzer<'a> {
|
|||
) -> Result<ModuleInfo, deno_ast::ParseDiagnostic> {
|
||||
// attempt to load from the cache
|
||||
let source_hash = CacheDBHash::from_source(&source);
|
||||
match self.module_info_cache.get_module_info(
|
||||
specifier,
|
||||
media_type,
|
||||
source_hash,
|
||||
) {
|
||||
Ok(Some(info)) => return Ok(info),
|
||||
Ok(None) => {}
|
||||
Err(err) => {
|
||||
log::debug!(
|
||||
"Error loading module cache info for {}. {:#}",
|
||||
specifier,
|
||||
err
|
||||
);
|
||||
}
|
||||
if let Some(info) =
|
||||
self.load_cached_module_info(specifier, media_type, source_hash)
|
||||
{
|
||||
return Ok(info);
|
||||
}
|
||||
|
||||
// otherwise, get the module info from the parsed source cache
|
||||
|
@ -169,18 +249,12 @@ impl<'a> deno_graph::ModuleAnalyzer for ModuleInfoCacheModuleAnalyzer<'a> {
|
|||
.unwrap()?;
|
||||
|
||||
// then attempt to cache it
|
||||
if let Err(err) = self.module_info_cache.set_module_info(
|
||||
self.save_module_info_to_cache(
|
||||
specifier,
|
||||
media_type,
|
||||
source_hash,
|
||||
&module_info,
|
||||
) {
|
||||
log::debug!(
|
||||
"Error saving module cache info for {}. {:#}",
|
||||
specifier,
|
||||
err
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
Ok(module_info)
|
||||
}
|
||||
|
@ -202,7 +276,7 @@ fn serialize_media_type(media_type: MediaType) -> i64 {
|
|||
Tsx => 11,
|
||||
Json => 12,
|
||||
Wasm => 13,
|
||||
TsBuildInfo => 14,
|
||||
Css => 14,
|
||||
SourceMap => 15,
|
||||
Unknown => 16,
|
||||
}
|
||||
|
@ -217,7 +291,7 @@ mod test {
|
|||
|
||||
#[test]
|
||||
pub fn module_info_cache_general_use() {
|
||||
let cache = ModuleInfoCache::new_in_memory("1.0.0");
|
||||
let cache = ModuleInfoCache::new_in_memory("1.0.0", Default::default());
|
||||
let specifier1 =
|
||||
ModuleSpecifier::parse("https://localhost/mod.ts").unwrap();
|
||||
let specifier2 =
|
||||
|
|
60
cli/cache/parsed_source.rs
vendored
60
cli/cache/parsed_source.rs
vendored
|
@ -5,12 +5,11 @@ use std::sync::Arc;
|
|||
|
||||
use deno_ast::MediaType;
|
||||
use deno_ast::ModuleSpecifier;
|
||||
use deno_ast::ParseDiagnostic;
|
||||
use deno_ast::ParsedSource;
|
||||
use deno_core::parking_lot::Mutex;
|
||||
use deno_graph::CapturingModuleParser;
|
||||
use deno_graph::DefaultModuleParser;
|
||||
use deno_graph::ModuleParser;
|
||||
use deno_graph::CapturingEsParser;
|
||||
use deno_graph::DefaultEsParser;
|
||||
use deno_graph::EsParser;
|
||||
use deno_graph::ParseOptions;
|
||||
use deno_graph::ParsedSourceStore;
|
||||
|
||||
|
@ -47,7 +46,7 @@ impl<'a> LazyGraphSourceParser<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
#[derive(Debug, Default)]
|
||||
pub struct ParsedSourceCache {
|
||||
sources: Mutex<HashMap<ModuleSpecifier, ParsedSource>>,
|
||||
}
|
||||
|
@ -58,12 +57,11 @@ impl ParsedSourceCache {
|
|||
module: &deno_graph::JsModule,
|
||||
) -> Result<ParsedSource, deno_ast::ParseDiagnostic> {
|
||||
let parser = self.as_capturing_parser();
|
||||
// this will conditionally parse because it's using a CapturingModuleParser
|
||||
parser.parse_module(ParseOptions {
|
||||
// this will conditionally parse because it's using a CapturingEsParser
|
||||
parser.parse_program(ParseOptions {
|
||||
specifier: &module.specifier,
|
||||
source: module.source.clone(),
|
||||
media_type: module.media_type,
|
||||
// don't bother enabling because this method is currently only used for vendoring
|
||||
scope_analysis: false,
|
||||
})
|
||||
}
|
||||
|
@ -87,10 +85,9 @@ impl ParsedSourceCache {
|
|||
specifier,
|
||||
source,
|
||||
media_type,
|
||||
// don't bother enabling because this method is currently only used for emitting
|
||||
scope_analysis: false,
|
||||
};
|
||||
DefaultModuleParser.parse_module(options)
|
||||
DefaultEsParser.parse_program(options)
|
||||
}
|
||||
|
||||
/// Frees the parsed source from memory.
|
||||
|
@ -100,8 +97,8 @@ impl ParsedSourceCache {
|
|||
|
||||
/// Creates a parser that will reuse a ParsedSource from the store
|
||||
/// if it exists, or else parse.
|
||||
pub fn as_capturing_parser(&self) -> CapturingModuleParser {
|
||||
CapturingModuleParser::new(None, self)
|
||||
pub fn as_capturing_parser(&self) -> CapturingEsParser {
|
||||
CapturingEsParser::new(None, self)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -150,42 +147,3 @@ impl deno_graph::ParsedSourceStore for ParsedSourceCache {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct EsmOrCjsChecker {
|
||||
parsed_source_cache: Arc<ParsedSourceCache>,
|
||||
}
|
||||
|
||||
impl EsmOrCjsChecker {
|
||||
pub fn new(parsed_source_cache: Arc<ParsedSourceCache>) -> Self {
|
||||
Self {
|
||||
parsed_source_cache,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_esm(
|
||||
&self,
|
||||
specifier: &ModuleSpecifier,
|
||||
source: Arc<str>,
|
||||
media_type: MediaType,
|
||||
) -> Result<bool, ParseDiagnostic> {
|
||||
// todo(dsherret): add a file cache here to avoid parsing with swc on each run
|
||||
let source = match self.parsed_source_cache.get_parsed_source(specifier) {
|
||||
Some(source) => source.clone(),
|
||||
None => {
|
||||
let source = deno_ast::parse_program(deno_ast::ParseParams {
|
||||
specifier: specifier.clone(),
|
||||
text: source,
|
||||
media_type,
|
||||
capture_tokens: true, // capture because it's used for cjs export analysis
|
||||
scope_analysis: false,
|
||||
maybe_syntax: None,
|
||||
})?;
|
||||
self
|
||||
.parsed_source_cache
|
||||
.set_parsed_source(specifier.clone(), source.clone());
|
||||
source
|
||||
}
|
||||
};
|
||||
Ok(source.is_module())
|
||||
}
|
||||
}
|
||||
|
|
77
cli/emit.rs
77
cli/emit.rs
|
@ -3,11 +3,14 @@
|
|||
use crate::cache::EmitCache;
|
||||
use crate::cache::FastInsecureHasher;
|
||||
use crate::cache::ParsedSourceCache;
|
||||
use crate::resolver::CjsTracker;
|
||||
|
||||
use deno_ast::ModuleKind;
|
||||
use deno_ast::SourceMapOption;
|
||||
use deno_ast::SourceRange;
|
||||
use deno_ast::SourceRanged;
|
||||
use deno_ast::SourceRangedForSpanned;
|
||||
use deno_ast::TranspileModuleOptions;
|
||||
use deno_ast::TranspileResult;
|
||||
use deno_core::error::AnyError;
|
||||
use deno_core::futures::stream::FuturesUnordered;
|
||||
|
@ -19,7 +22,9 @@ use deno_graph::Module;
|
|||
use deno_graph::ModuleGraph;
|
||||
use std::sync::Arc;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Emitter {
|
||||
cjs_tracker: Arc<CjsTracker>,
|
||||
emit_cache: Arc<EmitCache>,
|
||||
parsed_source_cache: Arc<ParsedSourceCache>,
|
||||
transpile_and_emit_options:
|
||||
|
@ -30,6 +35,7 @@ pub struct Emitter {
|
|||
|
||||
impl Emitter {
|
||||
pub fn new(
|
||||
cjs_tracker: Arc<CjsTracker>,
|
||||
emit_cache: Arc<EmitCache>,
|
||||
parsed_source_cache: Arc<ParsedSourceCache>,
|
||||
transpile_options: deno_ast::TranspileOptions,
|
||||
|
@ -42,6 +48,7 @@ impl Emitter {
|
|||
hasher.finish()
|
||||
};
|
||||
Self {
|
||||
cjs_tracker,
|
||||
emit_cache,
|
||||
parsed_source_cache,
|
||||
transpile_and_emit_options: Arc::new((transpile_options, emit_options)),
|
||||
|
@ -59,21 +66,19 @@ impl Emitter {
|
|||
continue;
|
||||
};
|
||||
|
||||
// todo(https://github.com/denoland/deno_media_type/pull/12): use is_emittable()
|
||||
let is_emittable = matches!(
|
||||
module.media_type,
|
||||
MediaType::TypeScript
|
||||
| MediaType::Mts
|
||||
| MediaType::Cts
|
||||
| MediaType::Jsx
|
||||
| MediaType::Tsx
|
||||
);
|
||||
if is_emittable {
|
||||
if module.media_type.is_emittable() {
|
||||
futures.push(
|
||||
self
|
||||
.emit_parsed_source(
|
||||
&module.specifier,
|
||||
module.media_type,
|
||||
ModuleKind::from_is_cjs(
|
||||
self.cjs_tracker.is_cjs_with_known_is_script(
|
||||
&module.specifier,
|
||||
module.media_type,
|
||||
module.is_script,
|
||||
)?,
|
||||
),
|
||||
&module.source,
|
||||
)
|
||||
.boxed_local(),
|
||||
|
@ -92,9 +97,10 @@ impl Emitter {
|
|||
pub fn maybe_cached_emit(
|
||||
&self,
|
||||
specifier: &ModuleSpecifier,
|
||||
module_kind: deno_ast::ModuleKind,
|
||||
source: &str,
|
||||
) -> Option<String> {
|
||||
let source_hash = self.get_source_hash(source);
|
||||
let source_hash = self.get_source_hash(module_kind, source);
|
||||
self.emit_cache.get_emit_code(specifier, source_hash)
|
||||
}
|
||||
|
||||
|
@ -102,11 +108,12 @@ impl Emitter {
|
|||
&self,
|
||||
specifier: &ModuleSpecifier,
|
||||
media_type: MediaType,
|
||||
module_kind: deno_ast::ModuleKind,
|
||||
source: &Arc<str>,
|
||||
) -> Result<String, AnyError> {
|
||||
// Note: keep this in sync with the sync version below
|
||||
let helper = EmitParsedSourceHelper(self);
|
||||
match helper.pre_emit_parsed_source(specifier, source) {
|
||||
match helper.pre_emit_parsed_source(specifier, module_kind, source) {
|
||||
PreEmitResult::Cached(emitted_text) => Ok(emitted_text),
|
||||
PreEmitResult::NotCached { source_hash } => {
|
||||
let parsed_source_cache = self.parsed_source_cache.clone();
|
||||
|
@ -119,8 +126,9 @@ impl Emitter {
|
|||
EmitParsedSourceHelper::transpile(
|
||||
&parsed_source_cache,
|
||||
&specifier,
|
||||
source.clone(),
|
||||
media_type,
|
||||
module_kind,
|
||||
source.clone(),
|
||||
&transpile_and_emit_options.0,
|
||||
&transpile_and_emit_options.1,
|
||||
)
|
||||
|
@ -142,18 +150,20 @@ impl Emitter {
|
|||
&self,
|
||||
specifier: &ModuleSpecifier,
|
||||
media_type: MediaType,
|
||||
module_kind: deno_ast::ModuleKind,
|
||||
source: &Arc<str>,
|
||||
) -> Result<String, AnyError> {
|
||||
// Note: keep this in sync with the async version above
|
||||
let helper = EmitParsedSourceHelper(self);
|
||||
match helper.pre_emit_parsed_source(specifier, source) {
|
||||
match helper.pre_emit_parsed_source(specifier, module_kind, source) {
|
||||
PreEmitResult::Cached(emitted_text) => Ok(emitted_text),
|
||||
PreEmitResult::NotCached { source_hash } => {
|
||||
let transpiled_source = EmitParsedSourceHelper::transpile(
|
||||
&self.parsed_source_cache,
|
||||
specifier,
|
||||
source.clone(),
|
||||
media_type,
|
||||
module_kind,
|
||||
source.clone(),
|
||||
&self.transpile_and_emit_options.0,
|
||||
&self.transpile_and_emit_options.1,
|
||||
)?;
|
||||
|
@ -171,6 +181,7 @@ impl Emitter {
|
|||
pub async fn load_and_emit_for_hmr(
|
||||
&self,
|
||||
specifier: &ModuleSpecifier,
|
||||
module_kind: deno_ast::ModuleKind,
|
||||
) -> Result<String, AnyError> {
|
||||
let media_type = MediaType::from_specifier(specifier);
|
||||
let source_code = tokio::fs::read_to_string(
|
||||
|
@ -193,9 +204,14 @@ impl Emitter {
|
|||
let mut options = self.transpile_and_emit_options.1.clone();
|
||||
options.source_map = SourceMapOption::None;
|
||||
let transpiled_source = parsed_source
|
||||
.transpile(&self.transpile_and_emit_options.0, &options)?
|
||||
.into_source()
|
||||
.into_string()?;
|
||||
.transpile(
|
||||
&self.transpile_and_emit_options.0,
|
||||
&deno_ast::TranspileModuleOptions {
|
||||
module_kind: Some(module_kind),
|
||||
},
|
||||
&options,
|
||||
)?
|
||||
.into_source();
|
||||
Ok(transpiled_source.text)
|
||||
}
|
||||
MediaType::JavaScript
|
||||
|
@ -206,7 +222,7 @@ impl Emitter {
|
|||
| MediaType::Dcts
|
||||
| MediaType::Json
|
||||
| MediaType::Wasm
|
||||
| MediaType::TsBuildInfo
|
||||
| MediaType::Css
|
||||
| MediaType::SourceMap
|
||||
| MediaType::Unknown => {
|
||||
// clear this specifier from the parsed source cache as it's now out of date
|
||||
|
@ -219,10 +235,11 @@ impl Emitter {
|
|||
/// A hashing function that takes the source code and uses the global emit
|
||||
/// options then generates a string hash which can be stored to
|
||||
/// determine if the cached emit is valid or not.
|
||||
fn get_source_hash(&self, source_text: &str) -> u64 {
|
||||
fn get_source_hash(&self, module_kind: ModuleKind, source_text: &str) -> u64 {
|
||||
FastInsecureHasher::new_without_deno_version() // stored in the transpile_and_emit_options_hash
|
||||
.write_str(source_text)
|
||||
.write_u64(self.transpile_and_emit_options_hash)
|
||||
.write_hashable(module_kind)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
@ -239,9 +256,10 @@ impl<'a> EmitParsedSourceHelper<'a> {
|
|||
pub fn pre_emit_parsed_source(
|
||||
&self,
|
||||
specifier: &ModuleSpecifier,
|
||||
module_kind: deno_ast::ModuleKind,
|
||||
source: &Arc<str>,
|
||||
) -> PreEmitResult {
|
||||
let source_hash = self.0.get_source_hash(source);
|
||||
let source_hash = self.0.get_source_hash(module_kind, source);
|
||||
|
||||
if let Some(emit_code) =
|
||||
self.0.emit_cache.get_emit_code(specifier, source_hash)
|
||||
|
@ -255,8 +273,9 @@ impl<'a> EmitParsedSourceHelper<'a> {
|
|||
pub fn transpile(
|
||||
parsed_source_cache: &ParsedSourceCache,
|
||||
specifier: &ModuleSpecifier,
|
||||
source: Arc<str>,
|
||||
media_type: MediaType,
|
||||
module_kind: deno_ast::ModuleKind,
|
||||
source: Arc<str>,
|
||||
transpile_options: &deno_ast::TranspileOptions,
|
||||
emit_options: &deno_ast::EmitOptions,
|
||||
) -> Result<String, AnyError> {
|
||||
|
@ -265,8 +284,13 @@ impl<'a> EmitParsedSourceHelper<'a> {
|
|||
let parsed_source = parsed_source_cache
|
||||
.remove_or_parse_module(specifier, source, media_type)?;
|
||||
ensure_no_import_assertion(&parsed_source)?;
|
||||
let transpile_result =
|
||||
parsed_source.transpile(transpile_options, emit_options)?;
|
||||
let transpile_result = parsed_source.transpile(
|
||||
transpile_options,
|
||||
&TranspileModuleOptions {
|
||||
module_kind: Some(module_kind),
|
||||
},
|
||||
emit_options,
|
||||
)?;
|
||||
let transpiled_source = match transpile_result {
|
||||
TranspileResult::Owned(source) => source,
|
||||
TranspileResult::Cloned(source) => {
|
||||
|
@ -275,8 +299,7 @@ impl<'a> EmitParsedSourceHelper<'a> {
|
|||
}
|
||||
};
|
||||
debug_assert!(transpiled_source.source_map.is_none());
|
||||
let text = String::from_utf8(transpiled_source.source)?;
|
||||
Ok(text)
|
||||
Ok(transpiled_source.text)
|
||||
}
|
||||
|
||||
pub fn post_emit_parsed_source(
|
||||
|
@ -321,7 +344,7 @@ fn ensure_no_import_assertion(
|
|||
deno_core::anyhow::anyhow!("{}", msg)
|
||||
}
|
||||
|
||||
let Some(module) = parsed_source.program_ref().as_module() else {
|
||||
let deno_ast::ProgramRef::Module(module) = parsed_source.program_ref() else {
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
|
|
274
cli/factory.rs
274
cli/factory.rs
|
@ -11,10 +11,10 @@ use crate::args::StorageKeyResolver;
|
|||
use crate::args::TsConfigType;
|
||||
use crate::cache::Caches;
|
||||
use crate::cache::CodeCache;
|
||||
use crate::cache::DenoCacheEnvFsAdapter;
|
||||
use crate::cache::DenoDir;
|
||||
use crate::cache::DenoDirProvider;
|
||||
use crate::cache::EmitCache;
|
||||
use crate::cache::EsmOrCjsChecker;
|
||||
use crate::cache::GlobalHttpCache;
|
||||
use crate::cache::HttpCache;
|
||||
use crate::cache::LocalHttpCache;
|
||||
|
@ -33,12 +33,16 @@ use crate::module_loader::ModuleLoadPreparer;
|
|||
use crate::node::CliCjsCodeAnalyzer;
|
||||
use crate::node::CliNodeCodeTranslator;
|
||||
use crate::npm::create_cli_npm_resolver;
|
||||
use crate::npm::create_in_npm_pkg_checker;
|
||||
use crate::npm::CliByonmNpmResolverCreateOptions;
|
||||
use crate::npm::CliManagedInNpmPkgCheckerCreateOptions;
|
||||
use crate::npm::CliManagedNpmResolverCreateOptions;
|
||||
use crate::npm::CliNpmResolver;
|
||||
use crate::npm::CliNpmResolverCreateOptions;
|
||||
use crate::npm::CliNpmResolverManagedCreateOptions;
|
||||
use crate::npm::CliNpmResolverManagedSnapshotOption;
|
||||
use crate::resolver::CjsResolutionStore;
|
||||
use crate::npm::CreateInNpmPkgCheckerOptions;
|
||||
use crate::resolver::CjsTracker;
|
||||
use crate::resolver::CjsTrackerOptions;
|
||||
use crate::resolver::CliDenoResolverFs;
|
||||
use crate::resolver::CliGraphResolver;
|
||||
use crate::resolver::CliGraphResolverOptions;
|
||||
|
@ -51,6 +55,7 @@ use crate::tools::check::TypeChecker;
|
|||
use crate::tools::coverage::CoverageCollector;
|
||||
use crate::tools::lint::LintRuleProvider;
|
||||
use crate::tools::run::hmr::HmrRunner;
|
||||
use crate::tsc::TypeCheckingCjsTracker;
|
||||
use crate::util::file_watcher::WatcherCommunicator;
|
||||
use crate::util::fs::canonicalize_path_maybe_not_exists;
|
||||
use crate::util::progress_bar::ProgressBar;
|
||||
|
@ -59,6 +64,7 @@ use crate::worker::CliMainWorkerFactory;
|
|||
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;
|
||||
|
@ -68,6 +74,7 @@ use deno_core::FeatureChecker;
|
|||
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;
|
||||
|
@ -77,6 +84,7 @@ 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;
|
||||
|
@ -164,39 +172,41 @@ impl<T> Deferred<T> {
|
|||
|
||||
#[derive(Default)]
|
||||
struct CliFactoryServices {
|
||||
cli_options: Deferred<Arc<CliOptions>>,
|
||||
blob_store: Deferred<Arc<BlobStore>>,
|
||||
caches: Deferred<Arc<Caches>>,
|
||||
cjs_tracker: Deferred<Arc<CjsTracker>>,
|
||||
cli_node_resolver: Deferred<Arc<CliNodeResolver>>,
|
||||
cli_options: Deferred<Arc<CliOptions>>,
|
||||
code_cache: Deferred<Arc<CodeCache>>,
|
||||
emit_cache: Deferred<Arc<EmitCache>>,
|
||||
emitter: Deferred<Arc<Emitter>>,
|
||||
feature_checker: Deferred<Arc<FeatureChecker>>,
|
||||
file_fetcher: Deferred<Arc<FileFetcher>>,
|
||||
fs: Deferred<Arc<dyn deno_fs::FileSystem>>,
|
||||
global_http_cache: Deferred<Arc<GlobalHttpCache>>,
|
||||
http_cache: Deferred<Arc<dyn HttpCache>>,
|
||||
http_client_provider: Deferred<Arc<HttpClientProvider>>,
|
||||
emit_cache: Deferred<Arc<EmitCache>>,
|
||||
emitter: Deferred<Arc<Emitter>>,
|
||||
esm_or_cjs_checker: Deferred<Arc<EsmOrCjsChecker>>,
|
||||
fs: Deferred<Arc<dyn deno_fs::FileSystem>>,
|
||||
in_npm_pkg_checker: Deferred<Arc<dyn InNpmPackageChecker>>,
|
||||
main_graph_container: Deferred<Arc<MainModuleGraphContainer>>,
|
||||
maybe_inspector_server: Deferred<Option<Arc<InspectorServer>>>,
|
||||
root_cert_store_provider: Deferred<Arc<dyn RootCertStoreProvider>>,
|
||||
blob_store: Deferred<Arc<BlobStore>>,
|
||||
module_info_cache: Deferred<Arc<ModuleInfoCache>>,
|
||||
parsed_source_cache: Deferred<Arc<ParsedSourceCache>>,
|
||||
resolver: Deferred<Arc<CliGraphResolver>>,
|
||||
maybe_file_watcher_reporter: Deferred<Option<FileWatcherReporter>>,
|
||||
maybe_inspector_server: Deferred<Option<Arc<InspectorServer>>>,
|
||||
module_graph_builder: Deferred<Arc<ModuleGraphBuilder>>,
|
||||
module_graph_creator: Deferred<Arc<ModuleGraphCreator>>,
|
||||
module_info_cache: Deferred<Arc<ModuleInfoCache>>,
|
||||
module_load_preparer: Deferred<Arc<ModuleLoadPreparer>>,
|
||||
node_code_translator: Deferred<Arc<CliNodeCodeTranslator>>,
|
||||
node_resolver: Deferred<Arc<NodeResolver>>,
|
||||
npm_cache_dir: Deferred<Arc<NpmCacheDir>>,
|
||||
npm_resolver: Deferred<Arc<dyn CliNpmResolver>>,
|
||||
parsed_source_cache: Deferred<Arc<ParsedSourceCache>>,
|
||||
permission_desc_parser: Deferred<Arc<RuntimePermissionDescriptorParser>>,
|
||||
pkg_json_resolver: Deferred<Arc<PackageJsonResolver>>,
|
||||
resolver: Deferred<Arc<CliGraphResolver>>,
|
||||
root_cert_store_provider: Deferred<Arc<dyn RootCertStoreProvider>>,
|
||||
root_permissions_container: Deferred<PermissionsContainer>,
|
||||
sloppy_imports_resolver: Deferred<Option<Arc<CliSloppyImportsResolver>>>,
|
||||
text_only_progress_bar: Deferred<ProgressBar>,
|
||||
type_checker: Deferred<Arc<TypeChecker>>,
|
||||
cjs_resolutions: Deferred<Arc<CjsResolutionStore>>,
|
||||
cli_node_resolver: Deferred<Arc<CliNodeResolver>>,
|
||||
feature_checker: Deferred<Arc<FeatureChecker>>,
|
||||
code_cache: Deferred<Arc<CodeCache>>,
|
||||
workspace_resolver: Deferred<Arc<WorkspaceResolver>>,
|
||||
}
|
||||
|
||||
|
@ -300,12 +310,6 @@ impl CliFactory {
|
|||
.get_or_init(|| ProgressBar::new(ProgressBarStyle::TextOnly))
|
||||
}
|
||||
|
||||
pub fn esm_or_cjs_checker(&self) -> &Arc<EsmOrCjsChecker> {
|
||||
self.services.esm_or_cjs_checker.get_or_init(|| {
|
||||
Arc::new(EsmOrCjsChecker::new(self.parsed_source_cache().clone()))
|
||||
})
|
||||
}
|
||||
|
||||
pub fn global_http_cache(&self) -> Result<&Arc<GlobalHttpCache>, AnyError> {
|
||||
self.services.global_http_cache.get_or_try_init(|| {
|
||||
Ok(Arc::new(GlobalHttpCache::new(
|
||||
|
@ -359,56 +363,112 @@ impl CliFactory {
|
|||
self.services.fs.get_or_init(|| Arc::new(deno_fs::RealFs))
|
||||
}
|
||||
|
||||
pub fn in_npm_pkg_checker(
|
||||
&self,
|
||||
) -> Result<&Arc<dyn InNpmPackageChecker>, AnyError> {
|
||||
self.services.in_npm_pkg_checker.get_or_try_init(|| {
|
||||
let cli_options = self.cli_options()?;
|
||||
let options = if cli_options.use_byonm() {
|
||||
CreateInNpmPkgCheckerOptions::Byonm
|
||||
} else {
|
||||
CreateInNpmPkgCheckerOptions::Managed(
|
||||
CliManagedInNpmPkgCheckerCreateOptions {
|
||||
root_cache_dir_url: self.npm_cache_dir()?.root_dir_url(),
|
||||
maybe_node_modules_path: cli_options
|
||||
.node_modules_dir_path()
|
||||
.map(|p| p.as_path()),
|
||||
},
|
||||
)
|
||||
};
|
||||
Ok(create_in_npm_pkg_checker(options))
|
||||
})
|
||||
}
|
||||
|
||||
pub fn npm_cache_dir(&self) -> Result<&Arc<NpmCacheDir>, AnyError> {
|
||||
self.services.npm_cache_dir.get_or_try_init(|| {
|
||||
let fs = self.fs();
|
||||
let global_path = self.deno_dir()?.npm_folder_path();
|
||||
let cli_options = self.cli_options()?;
|
||||
Ok(Arc::new(NpmCacheDir::new(
|
||||
&DenoCacheEnvFsAdapter(fs.as_ref()),
|
||||
global_path,
|
||||
cli_options.npmrc().get_all_known_registries_urls(),
|
||||
)))
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn npm_resolver(
|
||||
&self,
|
||||
) -> Result<&Arc<dyn CliNpmResolver>, AnyError> {
|
||||
self
|
||||
.services
|
||||
.npm_resolver
|
||||
.get_or_try_init_async(async {
|
||||
let fs = self.fs();
|
||||
let cli_options = self.cli_options()?;
|
||||
// For `deno install` we want to force the managed resolver so it can set up `node_modules/` directory.
|
||||
create_cli_npm_resolver(if cli_options.use_byonm() && !matches!(cli_options.sub_command(), DenoSubcommand::Install(_) | DenoSubcommand::Add(_) | DenoSubcommand::Remove(_)) {
|
||||
CliNpmResolverCreateOptions::Byonm(CliByonmNpmResolverCreateOptions {
|
||||
fs: CliDenoResolverFs(fs.clone()),
|
||||
root_node_modules_dir: Some(match cli_options.node_modules_dir_path() {
|
||||
Some(node_modules_path) => node_modules_path.to_path_buf(),
|
||||
// path needs to be canonicalized for node resolution
|
||||
// (node_modules_dir_path above is already canonicalized)
|
||||
None => canonicalize_path_maybe_not_exists(cli_options.initial_cwd())?
|
||||
.join("node_modules"),
|
||||
}),
|
||||
})
|
||||
} else {
|
||||
CliNpmResolverCreateOptions::Managed(CliNpmResolverManagedCreateOptions {
|
||||
snapshot: 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),
|
||||
.get_or_try_init_async(
|
||||
async {
|
||||
let fs = self.fs();
|
||||
let cli_options = self.cli_options()?;
|
||||
create_cli_npm_resolver(if cli_options.use_byonm() {
|
||||
CliNpmResolverCreateOptions::Byonm(
|
||||
CliByonmNpmResolverCreateOptions {
|
||||
fs: CliDenoResolverFs(fs.clone()),
|
||||
pkg_json_resolver: self.pkg_json_resolver().clone(),
|
||||
root_node_modules_dir: Some(
|
||||
match cli_options.node_modules_dir_path() {
|
||||
Some(node_modules_path) => node_modules_path.to_path_buf(),
|
||||
// path needs to be canonicalized for node resolution
|
||||
// (node_modules_dir_path above is already canonicalized)
|
||||
None => canonicalize_path_maybe_not_exists(
|
||||
cli_options.initial_cwd(),
|
||||
)?
|
||||
.join("node_modules"),
|
||||
},
|
||||
),
|
||||
},
|
||||
},
|
||||
maybe_lockfile: cli_options.maybe_lockfile().cloned(),
|
||||
fs: fs.clone(),
|
||||
http_client_provider: self.http_client_provider().clone(),
|
||||
npm_global_cache_dir: self.deno_dir()?.npm_folder_path(),
|
||||
cache_setting: cli_options.cache_setting(),
|
||||
text_only_progress_bar: self.text_only_progress_bar().clone(),
|
||||
maybe_node_modules_path: cli_options.node_modules_dir_path().cloned(),
|
||||
npm_install_deps_provider: Arc::new(NpmInstallDepsProvider::from_workspace(cli_options.workspace())),
|
||||
npm_system_info: cli_options.npm_system_info(),
|
||||
npmrc: cli_options.npmrc().clone(),
|
||||
lifecycle_scripts: cli_options.lifecycle_scripts_config(),
|
||||
)
|
||||
} else {
|
||||
CliNpmResolverCreateOptions::Managed(
|
||||
CliManagedNpmResolverCreateOptions {
|
||||
snapshot: 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)
|
||||
}
|
||||
},
|
||||
},
|
||||
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(),
|
||||
cache_setting: cli_options.cache_setting(),
|
||||
text_only_progress_bar: self.text_only_progress_bar().clone(),
|
||||
maybe_node_modules_path: cli_options
|
||||
.node_modules_dir_path()
|
||||
.cloned(),
|
||||
npm_install_deps_provider: Arc::new(
|
||||
NpmInstallDepsProvider::from_workspace(
|
||||
cli_options.workspace(),
|
||||
),
|
||||
),
|
||||
npm_system_info: cli_options.npm_system_info(),
|
||||
npmrc: cli_options.npmrc().clone(),
|
||||
lifecycle_scripts: cli_options.lifecycle_scripts_config(),
|
||||
},
|
||||
)
|
||||
})
|
||||
}).await
|
||||
}.boxed_local())
|
||||
.await
|
||||
}
|
||||
.boxed_local(),
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
|
@ -513,6 +573,7 @@ impl CliFactory {
|
|||
self.services.module_info_cache.get_or_try_init(|| {
|
||||
Ok(Arc::new(ModuleInfoCache::new(
|
||||
self.caches()?.dep_analysis_db(),
|
||||
self.parsed_source_cache().clone(),
|
||||
)))
|
||||
})
|
||||
}
|
||||
|
@ -541,6 +602,7 @@ impl CliFactory {
|
|||
ts_config_result.ts_config,
|
||||
)?;
|
||||
Ok(Arc::new(Emitter::new(
|
||||
self.cjs_tracker()?.clone(),
|
||||
self.emit_cache()?.clone(),
|
||||
self.parsed_source_cache().clone(),
|
||||
transpile_options,
|
||||
|
@ -564,7 +626,9 @@ impl CliFactory {
|
|||
async {
|
||||
Ok(Arc::new(NodeResolver::new(
|
||||
DenoFsNodeResolverEnv::new(self.fs().clone()),
|
||||
self.in_npm_pkg_checker()?.clone(),
|
||||
self.npm_resolver().await?.clone().into_npm_resolver(),
|
||||
self.pkg_json_resolver().clone(),
|
||||
)))
|
||||
}
|
||||
.boxed_local(),
|
||||
|
@ -582,24 +646,35 @@ impl CliFactory {
|
|||
let caches = self.caches()?;
|
||||
let node_analysis_cache =
|
||||
NodeAnalysisCache::new(caches.node_analysis_db());
|
||||
let node_resolver = self.cli_node_resolver().await?.clone();
|
||||
let node_resolver = self.node_resolver().await?.clone();
|
||||
let cjs_esm_analyzer = CliCjsCodeAnalyzer::new(
|
||||
node_analysis_cache,
|
||||
self.cjs_tracker()?.clone(),
|
||||
self.fs().clone(),
|
||||
node_resolver,
|
||||
Some(self.parsed_source_cache().clone()),
|
||||
self.cli_options()?.is_npm_main(),
|
||||
);
|
||||
|
||||
Ok(Arc::new(NodeCodeTranslator::new(
|
||||
cjs_esm_analyzer,
|
||||
DenoFsNodeResolverEnv::new(self.fs().clone()),
|
||||
self.node_resolver().await?.clone(),
|
||||
self.in_npm_pkg_checker()?.clone(),
|
||||
node_resolver,
|
||||
self.npm_resolver().await?.clone().into_npm_resolver(),
|
||||
self.pkg_json_resolver().clone(),
|
||||
)))
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
pub fn pkg_json_resolver(&self) -> &Arc<PackageJsonResolver> {
|
||||
self.services.pkg_json_resolver.get_or_init(|| {
|
||||
Arc::new(PackageJsonResolver::new(DenoFsNodeResolverEnv::new(
|
||||
self.fs().clone(),
|
||||
)))
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn type_checker(&self) -> Result<&Arc<TypeChecker>, AnyError> {
|
||||
self
|
||||
.services
|
||||
|
@ -608,6 +683,10 @@ impl CliFactory {
|
|||
let cli_options = self.cli_options()?;
|
||||
Ok(Arc::new(TypeChecker::new(
|
||||
self.caches()?.clone(),
|
||||
Arc::new(TypeCheckingCjsTracker::new(
|
||||
self.cjs_tracker()?.clone(),
|
||||
self.module_info_cache()?.clone(),
|
||||
)),
|
||||
cli_options.clone(),
|
||||
self.module_graph_builder().await?.clone(),
|
||||
self.node_resolver().await?.clone(),
|
||||
|
@ -626,19 +705,18 @@ impl CliFactory {
|
|||
.get_or_try_init_async(async {
|
||||
let cli_options = self.cli_options()?;
|
||||
Ok(Arc::new(ModuleGraphBuilder::new(
|
||||
cli_options.clone(),
|
||||
self.caches()?.clone(),
|
||||
self.esm_or_cjs_checker().clone(),
|
||||
cli_options.clone(),
|
||||
self.file_fetcher()?.clone(),
|
||||
self.fs().clone(),
|
||||
self.resolver().await?.clone(),
|
||||
self.cli_node_resolver().await?.clone(),
|
||||
self.npm_resolver().await?.clone(),
|
||||
self.module_info_cache()?.clone(),
|
||||
self.parsed_source_cache().clone(),
|
||||
self.global_http_cache()?.clone(),
|
||||
self.in_npm_pkg_checker()?.clone(),
|
||||
cli_options.maybe_lockfile().cloned(),
|
||||
self.maybe_file_watcher_reporter().clone(),
|
||||
self.file_fetcher()?.clone(),
|
||||
self.global_http_cache()?.clone(),
|
||||
self.module_info_cache()?.clone(),
|
||||
self.npm_resolver().await?.clone(),
|
||||
self.parsed_source_cache().clone(),
|
||||
self.resolver().await?.clone(),
|
||||
self.root_permissions_container()?.clone(),
|
||||
)))
|
||||
})
|
||||
|
@ -710,8 +788,17 @@ impl CliFactory {
|
|||
.await
|
||||
}
|
||||
|
||||
pub fn cjs_resolutions(&self) -> &Arc<CjsResolutionStore> {
|
||||
self.services.cjs_resolutions.get_or_init(Default::default)
|
||||
pub fn cjs_tracker(&self) -> Result<&Arc<CjsTracker>, AnyError> {
|
||||
self.services.cjs_tracker.get_or_try_init(|| {
|
||||
let options = self.cli_options()?;
|
||||
Ok(Arc::new(CjsTracker::new(
|
||||
self.in_npm_pkg_checker()?.clone(),
|
||||
self.pkg_json_resolver().clone(),
|
||||
CjsTrackerOptions {
|
||||
unstable_detect_cjs: options.unstable_detect_cjs(),
|
||||
},
|
||||
)))
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn cli_node_resolver(
|
||||
|
@ -722,8 +809,9 @@ impl CliFactory {
|
|||
.cli_node_resolver
|
||||
.get_or_try_init_async(async {
|
||||
Ok(Arc::new(CliNodeResolver::new(
|
||||
self.cjs_resolutions().clone(),
|
||||
self.cjs_tracker()?.clone(),
|
||||
self.fs().clone(),
|
||||
self.in_npm_pkg_checker()?.clone(),
|
||||
self.node_resolver().await?.clone(),
|
||||
self.npm_resolver().await?.clone(),
|
||||
)))
|
||||
|
@ -761,6 +849,7 @@ impl CliFactory {
|
|||
) -> Result<DenoCompileBinaryWriter, AnyError> {
|
||||
let cli_options = self.cli_options()?;
|
||||
Ok(DenoCompileBinaryWriter::new(
|
||||
self.cjs_tracker()?,
|
||||
self.deno_dir()?,
|
||||
self.emitter()?,
|
||||
self.file_fetcher()?,
|
||||
|
@ -791,53 +880,60 @@ impl CliFactory {
|
|||
&self,
|
||||
) -> Result<CliMainWorkerFactory, AnyError> {
|
||||
let cli_options = self.cli_options()?;
|
||||
let fs = self.fs();
|
||||
let node_resolver = self.node_resolver().await?;
|
||||
let npm_resolver = self.npm_resolver().await?;
|
||||
let fs = self.fs();
|
||||
let cli_node_resolver = self.cli_node_resolver().await?;
|
||||
let cli_npm_resolver = self.npm_resolver().await?.clone();
|
||||
let in_npm_pkg_checker = self.in_npm_pkg_checker()?;
|
||||
let maybe_file_watcher_communicator = if cli_options.has_hmr() {
|
||||
Some(self.watcher_communicator.clone().unwrap())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let node_code_translator = self.node_code_translator().await?;
|
||||
let cjs_tracker = self.cjs_tracker()?.clone();
|
||||
let pkg_json_resolver = self.pkg_json_resolver().clone();
|
||||
|
||||
Ok(CliMainWorkerFactory::new(
|
||||
self.blob_store().clone(),
|
||||
self.cjs_resolutions().clone(),
|
||||
if cli_options.code_cache_enabled() {
|
||||
Some(self.code_cache()?.clone())
|
||||
} else {
|
||||
None
|
||||
},
|
||||
self.feature_checker()?.clone(),
|
||||
self.fs().clone(),
|
||||
fs.clone(),
|
||||
maybe_file_watcher_communicator,
|
||||
self.maybe_inspector_server()?.clone(),
|
||||
cli_options.maybe_lockfile().cloned(),
|
||||
Box::new(CliModuleLoaderFactory::new(
|
||||
cli_options,
|
||||
cjs_tracker,
|
||||
if cli_options.code_cache_enabled() {
|
||||
Some(self.code_cache()?.clone())
|
||||
} else {
|
||||
None
|
||||
},
|
||||
self.emitter()?.clone(),
|
||||
fs.clone(),
|
||||
in_npm_pkg_checker.clone(),
|
||||
self.main_module_graph_container().await?.clone(),
|
||||
self.module_load_preparer().await?.clone(),
|
||||
node_code_translator.clone(),
|
||||
cli_node_resolver.clone(),
|
||||
cli_npm_resolver.clone(),
|
||||
NpmModuleLoader::new(
|
||||
self.cjs_resolutions().clone(),
|
||||
self.node_code_translator().await?.clone(),
|
||||
self.cjs_tracker()?.clone(),
|
||||
fs.clone(),
|
||||
cli_node_resolver.clone(),
|
||||
node_code_translator.clone(),
|
||||
),
|
||||
self.parsed_source_cache().clone(),
|
||||
self.resolver().await?.clone(),
|
||||
)),
|
||||
node_resolver.clone(),
|
||||
npm_resolver.clone(),
|
||||
pkg_json_resolver,
|
||||
self.root_cert_store_provider().clone(),
|
||||
self.root_permissions_container()?.clone(),
|
||||
StorageKeyResolver::from_options(cli_options),
|
||||
|
@ -853,8 +949,10 @@ impl CliFactory {
|
|||
let create_hmr_runner = if cli_options.has_hmr() {
|
||||
let watcher_communicator = self.watcher_communicator.clone().unwrap();
|
||||
let emitter = self.emitter()?.clone();
|
||||
let cjs_tracker = self.cjs_tracker()?.clone();
|
||||
let fn_: crate::worker::CreateHmrRunnerCb = Box::new(move |session| {
|
||||
Box::new(HmrRunner::new(
|
||||
cjs_tracker.clone(),
|
||||
emitter.clone(),
|
||||
session,
|
||||
watcher_communicator.clone(),
|
||||
|
@ -891,7 +989,6 @@ impl CliFactory {
|
|||
inspect_wait: cli_options.inspect_wait().is_some(),
|
||||
strace_ops: cli_options.strace_ops().clone(),
|
||||
is_inspecting: cli_options.is_inspecting(),
|
||||
is_npm_main: cli_options.is_npm_main(),
|
||||
location: cli_options.location_flag().clone(),
|
||||
// if the user ran a binary command, we'll need to set process.argv[0]
|
||||
// to be the name of the binary command instead of deno
|
||||
|
@ -909,7 +1006,6 @@ impl CliFactory {
|
|||
node_ipc: cli_options.node_ipc_fd(),
|
||||
serve_port: cli_options.serve_port(),
|
||||
serve_host: cli_options.serve_host(),
|
||||
unstable_detect_cjs: cli_options.unstable_detect_cjs(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@ use crate::args::CliLockfile;
|
|||
use crate::args::CliOptions;
|
||||
use crate::args::DENO_DISABLE_PEDANTIC_NODE_WARNINGS;
|
||||
use crate::cache;
|
||||
use crate::cache::EsmOrCjsChecker;
|
||||
use crate::cache::GlobalHttpCache;
|
||||
use crate::cache::ModuleInfoCache;
|
||||
use crate::cache::ParsedSourceCache;
|
||||
|
@ -15,7 +14,6 @@ use crate::errors::get_error_class_name;
|
|||
use crate::file_fetcher::FileFetcher;
|
||||
use crate::npm::CliNpmResolver;
|
||||
use crate::resolver::CliGraphResolver;
|
||||
use crate::resolver::CliNodeResolver;
|
||||
use crate::resolver::CliSloppyImportsResolver;
|
||||
use crate::resolver::SloppyImportsCachedFs;
|
||||
use crate::tools::check;
|
||||
|
@ -50,6 +48,7 @@ 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;
|
||||
|
@ -379,54 +378,51 @@ pub struct BuildFastCheckGraphOptions<'a> {
|
|||
}
|
||||
|
||||
pub struct ModuleGraphBuilder {
|
||||
options: Arc<CliOptions>,
|
||||
caches: Arc<cache::Caches>,
|
||||
esm_or_cjs_checker: Arc<EsmOrCjsChecker>,
|
||||
cli_options: Arc<CliOptions>,
|
||||
file_fetcher: Arc<FileFetcher>,
|
||||
fs: Arc<dyn FileSystem>,
|
||||
resolver: Arc<CliGraphResolver>,
|
||||
node_resolver: Arc<CliNodeResolver>,
|
||||
npm_resolver: Arc<dyn CliNpmResolver>,
|
||||
module_info_cache: Arc<ModuleInfoCache>,
|
||||
parsed_source_cache: Arc<ParsedSourceCache>,
|
||||
global_http_cache: Arc<GlobalHttpCache>,
|
||||
in_npm_pkg_checker: Arc<dyn InNpmPackageChecker>,
|
||||
lockfile: Option<Arc<CliLockfile>>,
|
||||
maybe_file_watcher_reporter: Option<FileWatcherReporter>,
|
||||
file_fetcher: Arc<FileFetcher>,
|
||||
global_http_cache: Arc<GlobalHttpCache>,
|
||||
module_info_cache: Arc<ModuleInfoCache>,
|
||||
npm_resolver: Arc<dyn CliNpmResolver>,
|
||||
parsed_source_cache: Arc<ParsedSourceCache>,
|
||||
resolver: Arc<CliGraphResolver>,
|
||||
root_permissions_container: PermissionsContainer,
|
||||
}
|
||||
|
||||
impl ModuleGraphBuilder {
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn new(
|
||||
options: Arc<CliOptions>,
|
||||
caches: Arc<cache::Caches>,
|
||||
esm_or_cjs_checker: Arc<EsmOrCjsChecker>,
|
||||
cli_options: Arc<CliOptions>,
|
||||
file_fetcher: Arc<FileFetcher>,
|
||||
fs: Arc<dyn FileSystem>,
|
||||
resolver: Arc<CliGraphResolver>,
|
||||
node_resolver: Arc<CliNodeResolver>,
|
||||
npm_resolver: Arc<dyn CliNpmResolver>,
|
||||
module_info_cache: Arc<ModuleInfoCache>,
|
||||
parsed_source_cache: Arc<ParsedSourceCache>,
|
||||
global_http_cache: Arc<GlobalHttpCache>,
|
||||
in_npm_pkg_checker: Arc<dyn InNpmPackageChecker>,
|
||||
lockfile: Option<Arc<CliLockfile>>,
|
||||
maybe_file_watcher_reporter: Option<FileWatcherReporter>,
|
||||
file_fetcher: Arc<FileFetcher>,
|
||||
global_http_cache: Arc<GlobalHttpCache>,
|
||||
module_info_cache: Arc<ModuleInfoCache>,
|
||||
npm_resolver: Arc<dyn CliNpmResolver>,
|
||||
parsed_source_cache: Arc<ParsedSourceCache>,
|
||||
resolver: Arc<CliGraphResolver>,
|
||||
root_permissions_container: PermissionsContainer,
|
||||
) -> Self {
|
||||
Self {
|
||||
options,
|
||||
caches,
|
||||
esm_or_cjs_checker,
|
||||
cli_options,
|
||||
file_fetcher,
|
||||
fs,
|
||||
resolver,
|
||||
node_resolver,
|
||||
npm_resolver,
|
||||
module_info_cache,
|
||||
parsed_source_cache,
|
||||
global_http_cache,
|
||||
in_npm_pkg_checker,
|
||||
lockfile,
|
||||
maybe_file_watcher_reporter,
|
||||
file_fetcher,
|
||||
global_http_cache,
|
||||
module_info_cache,
|
||||
npm_resolver,
|
||||
parsed_source_cache,
|
||||
resolver,
|
||||
root_permissions_container,
|
||||
}
|
||||
}
|
||||
|
@ -512,13 +508,11 @@ impl ModuleGraphBuilder {
|
|||
}
|
||||
|
||||
let maybe_imports = if options.graph_kind.include_types() {
|
||||
self.options.to_compiler_option_types()?
|
||||
self.cli_options.to_compiler_option_types()?
|
||||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
let analyzer = self
|
||||
.module_info_cache
|
||||
.as_module_analyzer(&self.parsed_source_cache);
|
||||
let analyzer = self.module_info_cache.as_module_analyzer();
|
||||
let mut loader = match options.loader {
|
||||
Some(loader) => MutLoaderRef::Borrowed(loader),
|
||||
None => MutLoaderRef::Owned(self.create_graph_loader()),
|
||||
|
@ -566,7 +560,7 @@ impl ModuleGraphBuilder {
|
|||
// ensure an "npm install" is done if the user has explicitly
|
||||
// opted into using a node_modules directory
|
||||
if self
|
||||
.options
|
||||
.cli_options
|
||||
.node_modules_dir()?
|
||||
.map(|m| m.uses_node_modules_dir())
|
||||
.unwrap_or(false)
|
||||
|
@ -677,10 +671,10 @@ impl ModuleGraphBuilder {
|
|||
|
||||
graph.build_fast_check_type_graph(
|
||||
deno_graph::BuildFastCheckTypeGraphOptions {
|
||||
jsr_url_provider: &CliJsrUrlProvider,
|
||||
es_parser: Some(&parser),
|
||||
fast_check_cache: fast_check_cache.as_ref().map(|c| c as _),
|
||||
fast_check_dts: false,
|
||||
module_parser: Some(&parser),
|
||||
jsr_url_provider: &CliJsrUrlProvider,
|
||||
resolver: Some(graph_resolver),
|
||||
npm_resolver: Some(&graph_npm_resolver),
|
||||
workspace_fast_check: options.workspace_fast_check,
|
||||
|
@ -699,20 +693,18 @@ impl ModuleGraphBuilder {
|
|||
permissions: PermissionsContainer,
|
||||
) -> cache::FetchCacher {
|
||||
cache::FetchCacher::new(
|
||||
self.esm_or_cjs_checker.clone(),
|
||||
self.file_fetcher.clone(),
|
||||
self.fs.clone(),
|
||||
self.global_http_cache.clone(),
|
||||
self.node_resolver.clone(),
|
||||
self.npm_resolver.clone(),
|
||||
self.in_npm_pkg_checker.clone(),
|
||||
self.module_info_cache.clone(),
|
||||
cache::FetchCacherOptions {
|
||||
file_header_overrides: self.options.resolve_file_header_overrides(),
|
||||
file_header_overrides: self.cli_options.resolve_file_header_overrides(),
|
||||
permissions,
|
||||
is_deno_publish: matches!(
|
||||
self.options.sub_command(),
|
||||
self.cli_options.sub_command(),
|
||||
crate::args::DenoSubcommand::Publish { .. }
|
||||
),
|
||||
unstable_detect_cjs: self.options.unstable_detect_cjs(),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
@ -737,12 +729,12 @@ impl ModuleGraphBuilder {
|
|||
&self.fs,
|
||||
roots,
|
||||
GraphValidOptions {
|
||||
kind: if self.options.type_check_mode().is_true() {
|
||||
kind: if self.cli_options.type_check_mode().is_true() {
|
||||
GraphKind::All
|
||||
} else {
|
||||
GraphKind::CodeOnly
|
||||
},
|
||||
check_js: self.options.check_js(),
|
||||
check_js: self.cli_options.check_js(),
|
||||
exit_integrity_errors: true,
|
||||
},
|
||||
)
|
||||
|
|
|
@ -12,7 +12,9 @@ use super::urls::url_to_uri;
|
|||
use crate::args::jsr_url;
|
||||
use crate::lsp::search::PackageSearchApi;
|
||||
use crate::tools::lint::CliLinter;
|
||||
use crate::util::path::relative_specifier;
|
||||
use deno_config::workspace::MappedResolution;
|
||||
use deno_graph::source::ResolutionMode;
|
||||
use deno_lint::diagnostic::LintDiagnosticRange;
|
||||
|
||||
use deno_ast::SourceRange;
|
||||
|
@ -36,7 +38,6 @@ use deno_semver::package::PackageReq;
|
|||
use deno_semver::package::PackageReqReference;
|
||||
use deno_semver::Version;
|
||||
use import_map::ImportMap;
|
||||
use node_resolver::NpmResolver;
|
||||
use once_cell::sync::Lazy;
|
||||
use regex::Regex;
|
||||
use std::borrow::Cow;
|
||||
|
@ -229,6 +230,7 @@ pub struct TsResponseImportMapper<'a> {
|
|||
documents: &'a Documents,
|
||||
maybe_import_map: Option<&'a ImportMap>,
|
||||
resolver: &'a LspResolver,
|
||||
tsc_specifier_map: &'a tsc::TscSpecifierMap,
|
||||
file_referrer: ModuleSpecifier,
|
||||
}
|
||||
|
||||
|
@ -237,12 +239,14 @@ impl<'a> TsResponseImportMapper<'a> {
|
|||
documents: &'a Documents,
|
||||
maybe_import_map: Option<&'a ImportMap>,
|
||||
resolver: &'a LspResolver,
|
||||
tsc_specifier_map: &'a tsc::TscSpecifierMap,
|
||||
file_referrer: &ModuleSpecifier,
|
||||
) -> Self {
|
||||
Self {
|
||||
documents,
|
||||
maybe_import_map,
|
||||
resolver,
|
||||
tsc_specifier_map,
|
||||
file_referrer: file_referrer.clone(),
|
||||
}
|
||||
}
|
||||
|
@ -336,7 +340,12 @@ impl<'a> TsResponseImportMapper<'a> {
|
|||
.resolver
|
||||
.maybe_managed_npm_resolver(Some(&self.file_referrer))
|
||||
{
|
||||
if npm_resolver.in_npm_package(specifier) {
|
||||
let in_npm_pkg = self
|
||||
.resolver
|
||||
.maybe_node_resolver(Some(&self.file_referrer))
|
||||
.map(|n| n.in_npm_package(specifier))
|
||||
.unwrap_or(false);
|
||||
if in_npm_pkg {
|
||||
if let Ok(Some(pkg_id)) =
|
||||
npm_resolver.resolve_pkg_id_from_specifier(specifier)
|
||||
{
|
||||
|
@ -383,6 +392,11 @@ impl<'a> TsResponseImportMapper<'a> {
|
|||
}
|
||||
}
|
||||
}
|
||||
} else if let Some(dep_name) = self
|
||||
.resolver
|
||||
.file_url_to_package_json_dep(specifier, Some(&self.file_referrer))
|
||||
{
|
||||
return Some(dep_name);
|
||||
}
|
||||
|
||||
// check if the import map has this specifier
|
||||
|
@ -453,19 +467,36 @@ impl<'a> TsResponseImportMapper<'a> {
|
|||
specifier: &str,
|
||||
referrer: &ModuleSpecifier,
|
||||
) -> Option<String> {
|
||||
if let Ok(specifier) = referrer.join(specifier) {
|
||||
if let Some(specifier) = self.check_specifier(&specifier, referrer) {
|
||||
return Some(specifier);
|
||||
}
|
||||
}
|
||||
let specifier = specifier.strip_suffix(".js").unwrap_or(specifier);
|
||||
for ext in SUPPORTED_EXTENSIONS {
|
||||
let specifier_with_ext = format!("{specifier}{ext}");
|
||||
if self
|
||||
.documents
|
||||
.contains_import(&specifier_with_ext, referrer)
|
||||
let specifier_stem = specifier.strip_suffix(".js").unwrap_or(specifier);
|
||||
let specifiers = std::iter::once(Cow::Borrowed(specifier)).chain(
|
||||
SUPPORTED_EXTENSIONS
|
||||
.iter()
|
||||
.map(|ext| Cow::Owned(format!("{specifier_stem}{ext}"))),
|
||||
);
|
||||
for specifier in specifiers {
|
||||
if let Some(specifier) = self
|
||||
.resolver
|
||||
.as_graph_resolver(Some(&self.file_referrer))
|
||||
.resolve(
|
||||
&specifier,
|
||||
&deno_graph::Range {
|
||||
specifier: referrer.clone(),
|
||||
start: deno_graph::Position::zeroed(),
|
||||
end: deno_graph::Position::zeroed(),
|
||||
},
|
||||
ResolutionMode::Types,
|
||||
)
|
||||
.ok()
|
||||
.and_then(|s| self.tsc_specifier_map.normalize(s.as_str()).ok())
|
||||
.filter(|s| self.documents.exists(s, Some(&self.file_referrer)))
|
||||
{
|
||||
return Some(specifier_with_ext);
|
||||
if let Some(specifier) = self
|
||||
.check_specifier(&specifier, referrer)
|
||||
.or_else(|| relative_specifier(referrer, &specifier))
|
||||
.filter(|s| !s.contains("/node_modules/"))
|
||||
{
|
||||
return Some(specifier);
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
|
@ -555,8 +586,9 @@ fn try_reverse_map_package_json_exports(
|
|||
pub fn fix_ts_import_changes(
|
||||
referrer: &ModuleSpecifier,
|
||||
changes: &[tsc::FileTextChanges],
|
||||
import_mapper: &TsResponseImportMapper,
|
||||
language_server: &language_server::Inner,
|
||||
) -> Result<Vec<tsc::FileTextChanges>, AnyError> {
|
||||
let import_mapper = language_server.get_ts_response_import_mapper(referrer);
|
||||
let mut r = Vec::new();
|
||||
for change in changes {
|
||||
let mut text_changes = Vec::new();
|
||||
|
@ -601,7 +633,7 @@ pub fn fix_ts_import_changes(
|
|||
fn fix_ts_import_action<'a>(
|
||||
referrer: &ModuleSpecifier,
|
||||
action: &'a tsc::CodeFixAction,
|
||||
import_mapper: &TsResponseImportMapper,
|
||||
language_server: &language_server::Inner,
|
||||
) -> Option<Cow<'a, tsc::CodeFixAction>> {
|
||||
if !matches!(
|
||||
action.fix_name.as_str(),
|
||||
|
@ -617,6 +649,7 @@ fn fix_ts_import_action<'a>(
|
|||
let Some(specifier) = specifier else {
|
||||
return Some(Cow::Borrowed(action));
|
||||
};
|
||||
let import_mapper = language_server.get_ts_response_import_mapper(referrer);
|
||||
if let Some(new_specifier) =
|
||||
import_mapper.check_unresolved_specifier(specifier, referrer)
|
||||
{
|
||||
|
@ -724,7 +757,7 @@ pub fn ts_changes_to_edit(
|
|||
}))
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CodeActionData {
|
||||
pub specifier: ModuleSpecifier,
|
||||
|
@ -994,11 +1027,8 @@ impl CodeActionCollection {
|
|||
"The action returned from TypeScript is unsupported.",
|
||||
));
|
||||
}
|
||||
let Some(action) = fix_ts_import_action(
|
||||
specifier,
|
||||
action,
|
||||
&language_server.get_ts_response_import_mapper(specifier),
|
||||
) else {
|
||||
let Some(action) = fix_ts_import_action(specifier, action, language_server)
|
||||
else {
|
||||
return Ok(());
|
||||
};
|
||||
let edit = ts_changes_to_edit(&action.changes, language_server)?;
|
||||
|
@ -1047,10 +1077,12 @@ impl CodeActionCollection {
|
|||
specifier: &ModuleSpecifier,
|
||||
diagnostic: &lsp::Diagnostic,
|
||||
) {
|
||||
let data = Some(json!({
|
||||
"specifier": specifier,
|
||||
"fixId": action.fix_id,
|
||||
}));
|
||||
let data = action.fix_id.as_ref().map(|fix_id| {
|
||||
json!(CodeActionData {
|
||||
specifier: specifier.clone(),
|
||||
fix_id: fix_id.clone(),
|
||||
})
|
||||
});
|
||||
let title = if let Some(description) = &action.fix_all_description {
|
||||
description.clone()
|
||||
} else {
|
||||
|
@ -1199,14 +1231,11 @@ impl CodeActionCollection {
|
|||
}),
|
||||
);
|
||||
|
||||
match parsed_source.program_ref() {
|
||||
deno_ast::swc::ast::Program::Module(module) => module
|
||||
.body
|
||||
.iter()
|
||||
.find(|i| i.range().contains(&specifier_range))
|
||||
.map(|i| text_info.line_and_column_index(i.range().start)),
|
||||
deno_ast::swc::ast::Program::Script(_) => None,
|
||||
}
|
||||
parsed_source
|
||||
.program_ref()
|
||||
.body()
|
||||
.find(|i| i.range().contains(&specifier_range))
|
||||
.map(|i| text_info.line_and_column_index(i.range().start))
|
||||
}
|
||||
|
||||
async fn deno_types_for_npm_action(
|
||||
|
|
|
@ -421,7 +421,7 @@ pub fn collect_test(
|
|||
) -> Result<Vec<lsp::CodeLens>, AnyError> {
|
||||
let mut collector =
|
||||
DenoTestCollector::new(specifier.clone(), parsed_source.clone());
|
||||
parsed_source.module().visit_with(&mut collector);
|
||||
parsed_source.program().visit_with(&mut collector);
|
||||
Ok(collector.take())
|
||||
}
|
||||
|
||||
|
@ -581,7 +581,7 @@ mod tests {
|
|||
.unwrap();
|
||||
let mut collector =
|
||||
DenoTestCollector::new(specifier, parsed_module.clone());
|
||||
parsed_module.module().visit_with(&mut collector);
|
||||
parsed_module.program().visit_with(&mut collector);
|
||||
assert_eq!(
|
||||
collector.take(),
|
||||
vec![
|
||||
|
|
|
@ -41,6 +41,7 @@ use deno_runtime::deno_node::PackageJson;
|
|||
use indexmap::IndexSet;
|
||||
use lsp_types::ClientCapabilities;
|
||||
use std::collections::BTreeMap;
|
||||
use std::collections::BTreeSet;
|
||||
use std::collections::HashMap;
|
||||
use std::ops::Deref;
|
||||
use std::ops::DerefMut;
|
||||
|
@ -984,7 +985,7 @@ impl Config {
|
|||
| MediaType::Tsx => Some(&workspace_settings.typescript),
|
||||
MediaType::Json
|
||||
| MediaType::Wasm
|
||||
| MediaType::TsBuildInfo
|
||||
| MediaType::Css
|
||||
| MediaType::SourceMap
|
||||
| MediaType::Unknown => None,
|
||||
}
|
||||
|
@ -1190,6 +1191,7 @@ pub struct ConfigData {
|
|||
pub resolver: Arc<WorkspaceResolver>,
|
||||
pub sloppy_imports_resolver: Option<Arc<CliSloppyImportsResolver>>,
|
||||
pub import_map_from_settings: Option<ModuleSpecifier>,
|
||||
pub unstable: BTreeSet<String>,
|
||||
watched_files: HashMap<ModuleSpecifier, ConfigWatchedFileType>,
|
||||
}
|
||||
|
||||
|
@ -1587,9 +1589,16 @@ impl ConfigData {
|
|||
.join("\n")
|
||||
);
|
||||
}
|
||||
let unstable = member_dir
|
||||
.workspace
|
||||
.unstable_features()
|
||||
.iter()
|
||||
.chain(settings.unstable.as_deref())
|
||||
.cloned()
|
||||
.collect::<BTreeSet<_>>();
|
||||
let unstable_sloppy_imports = std::env::var("DENO_UNSTABLE_SLOPPY_IMPORTS")
|
||||
.is_ok()
|
||||
|| member_dir.workspace.has_unstable("sloppy-imports");
|
||||
|| unstable.contains("sloppy-imports");
|
||||
let sloppy_imports_resolver = unstable_sloppy_imports.then(|| {
|
||||
Arc::new(CliSloppyImportsResolver::new(
|
||||
SloppyImportsCachedFs::new_without_stat_cache(Arc::new(
|
||||
|
@ -1630,6 +1639,7 @@ impl ConfigData {
|
|||
lockfile,
|
||||
npmrc,
|
||||
import_map_from_settings,
|
||||
unstable,
|
||||
watched_files,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -272,7 +272,7 @@ fn get_maybe_test_module_fut(
|
|||
parsed_source.specifier().clone(),
|
||||
parsed_source.text_info_lazy().clone(),
|
||||
);
|
||||
parsed_source.module().visit_with(&mut collector);
|
||||
parsed_source.program().visit_with(&mut collector);
|
||||
Arc::new(collector.take())
|
||||
})
|
||||
.map(Result::ok)
|
||||
|
@ -332,12 +332,8 @@ impl Document {
|
|||
.filter(|s| cache.is_valid_file_referrer(s))
|
||||
.cloned()
|
||||
.or(file_referrer);
|
||||
let media_type = resolve_media_type(
|
||||
&specifier,
|
||||
maybe_headers.as_ref(),
|
||||
maybe_language_id,
|
||||
&resolver,
|
||||
);
|
||||
let media_type =
|
||||
resolve_media_type(&specifier, maybe_headers.as_ref(), maybe_language_id);
|
||||
let (maybe_parsed_source, maybe_module) =
|
||||
if media_type_is_diagnosable(media_type) {
|
||||
parse_and_analyze_module(
|
||||
|
@ -399,7 +395,6 @@ impl Document {
|
|||
&self.specifier,
|
||||
self.maybe_headers.as_ref(),
|
||||
self.maybe_language_id,
|
||||
&resolver,
|
||||
);
|
||||
let dependencies;
|
||||
let maybe_types_dependency;
|
||||
|
@ -764,14 +759,7 @@ fn resolve_media_type(
|
|||
specifier: &ModuleSpecifier,
|
||||
maybe_headers: Option<&HashMap<String, String>>,
|
||||
maybe_language_id: Option<LanguageId>,
|
||||
resolver: &LspResolver,
|
||||
) -> MediaType {
|
||||
if resolver.in_node_modules(specifier) {
|
||||
if let Some(media_type) = resolver.node_media_type(specifier) {
|
||||
return media_type;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(language_id) = maybe_language_id {
|
||||
return MediaType::from_specifier_and_content_type(
|
||||
specifier,
|
||||
|
@ -1071,34 +1059,6 @@ impl Documents {
|
|||
self.cache.is_valid_file_referrer(specifier)
|
||||
}
|
||||
|
||||
/// Return `true` if the provided specifier can be resolved to a document,
|
||||
/// otherwise `false`.
|
||||
pub fn contains_import(
|
||||
&self,
|
||||
specifier: &str,
|
||||
referrer: &ModuleSpecifier,
|
||||
) -> bool {
|
||||
let file_referrer = self.get_file_referrer(referrer);
|
||||
let maybe_specifier = self
|
||||
.resolver
|
||||
.as_graph_resolver(file_referrer.as_deref())
|
||||
.resolve(
|
||||
specifier,
|
||||
&deno_graph::Range {
|
||||
specifier: referrer.clone(),
|
||||
start: deno_graph::Position::zeroed(),
|
||||
end: deno_graph::Position::zeroed(),
|
||||
},
|
||||
ResolutionMode::Types,
|
||||
)
|
||||
.ok();
|
||||
if let Some(import_specifier) = maybe_specifier {
|
||||
self.exists(&import_specifier, file_referrer.as_deref())
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resolve_document_specifier(
|
||||
&self,
|
||||
specifier: &ModuleSpecifier,
|
||||
|
@ -1561,7 +1521,7 @@ fn parse_source(
|
|||
text: Arc<str>,
|
||||
media_type: MediaType,
|
||||
) -> ParsedSourceResult {
|
||||
deno_ast::parse_module(deno_ast::ParseParams {
|
||||
deno_ast::parse_program(deno_ast::ParseParams {
|
||||
specifier,
|
||||
text,
|
||||
media_type,
|
||||
|
|
|
@ -863,7 +863,10 @@ impl Inner {
|
|||
// We ignore these directories by default because there is a
|
||||
// high likelihood they aren't relevant. Someone can opt-into
|
||||
// them by specifying one of them as an enabled path.
|
||||
if matches!(dir_name.as_str(), "vendor" | "node_modules" | ".git") {
|
||||
if matches!(
|
||||
dir_name.as_str(),
|
||||
"vendor" | "coverage" | "node_modules" | ".git"
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
// ignore cargo target directories for anyone using Deno with Rust
|
||||
|
@ -904,7 +907,7 @@ impl Inner {
|
|||
| MediaType::Tsx => {}
|
||||
MediaType::Wasm
|
||||
| MediaType::SourceMap
|
||||
| MediaType::TsBuildInfo
|
||||
| MediaType::Css
|
||||
| MediaType::Unknown => {
|
||||
if path.extension().and_then(|s| s.to_str()) != Some("jsonc") {
|
||||
continue;
|
||||
|
@ -1384,14 +1387,10 @@ impl Inner {
|
|||
.clone();
|
||||
fmt_options.use_tabs = Some(!params.options.insert_spaces);
|
||||
fmt_options.indent_width = Some(params.options.tab_size as u8);
|
||||
let maybe_workspace = self
|
||||
.config
|
||||
.tree
|
||||
.data_for_specifier(&specifier)
|
||||
.map(|d| &d.member_dir.workspace);
|
||||
let config_data = self.config.tree.data_for_specifier(&specifier);
|
||||
let unstable_options = UnstableFmtOptions {
|
||||
component: maybe_workspace
|
||||
.map(|w| w.has_unstable("fmt-component"))
|
||||
component: config_data
|
||||
.map(|d| d.unstable.contains("fmt-component"))
|
||||
.unwrap_or(false),
|
||||
};
|
||||
let document = document.clone();
|
||||
|
@ -1838,7 +1837,7 @@ impl Inner {
|
|||
fix_ts_import_changes(
|
||||
&code_action_data.specifier,
|
||||
&combined_code_actions.changes,
|
||||
&self.get_ts_response_import_mapper(&code_action_data.specifier),
|
||||
self,
|
||||
)
|
||||
.map_err(|err| {
|
||||
error!("Unable to remap changes: {:#}", err);
|
||||
|
@ -1891,7 +1890,7 @@ impl Inner {
|
|||
refactor_edit_info.edits = fix_ts_import_changes(
|
||||
&action_data.specifier,
|
||||
&refactor_edit_info.edits,
|
||||
&self.get_ts_response_import_mapper(&action_data.specifier),
|
||||
self,
|
||||
)
|
||||
.map_err(|err| {
|
||||
error!("Unable to remap changes: {:#}", err);
|
||||
|
@ -1922,7 +1921,8 @@ impl Inner {
|
|||
// todo(dsherret): this should probably just take the resolver itself
|
||||
// as the import map is an implementation detail
|
||||
.and_then(|d| d.resolver.maybe_import_map()),
|
||||
self.resolver.as_ref(),
|
||||
&self.resolver,
|
||||
&self.ts_server.specifier_map,
|
||||
file_referrer,
|
||||
)
|
||||
}
|
||||
|
@ -2285,7 +2285,11 @@ impl Inner {
|
|||
.into(),
|
||||
scope.cloned(),
|
||||
)
|
||||
.await;
|
||||
.await
|
||||
.unwrap_or_else(|err| {
|
||||
error!("Unable to get completion info from TypeScript: {:#}", err);
|
||||
None
|
||||
});
|
||||
|
||||
if let Some(completions) = maybe_completion_info {
|
||||
response = Some(
|
||||
|
@ -3948,7 +3952,9 @@ mod tests {
|
|||
fn test_walk_workspace() {
|
||||
let temp_dir = TempDir::new();
|
||||
temp_dir.create_dir_all("root1/vendor/");
|
||||
temp_dir.create_dir_all("root1/coverage/");
|
||||
temp_dir.write("root1/vendor/mod.ts", ""); // no, vendor
|
||||
temp_dir.write("root1/coverage/mod.ts", ""); // no, coverage
|
||||
|
||||
temp_dir.create_dir_all("root1/node_modules/");
|
||||
temp_dir.write("root1/node_modules/mod.ts", ""); // no, node_modules
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
use dashmap::DashMap;
|
||||
use deno_ast::MediaType;
|
||||
use deno_ast::ParsedSource;
|
||||
use deno_cache_dir::npm::NpmCacheDir;
|
||||
use deno_cache_dir::HttpCache;
|
||||
use deno_config::workspace::PackageJsonDepResolution;
|
||||
use deno_config::workspace::WorkspaceResolver;
|
||||
|
@ -14,15 +16,15 @@ use deno_path_util::url_to_file_path;
|
|||
use deno_runtime::deno_fs;
|
||||
use deno_runtime::deno_node::NodeResolver;
|
||||
use deno_runtime::deno_node::PackageJson;
|
||||
use deno_runtime::deno_node::PackageJsonResolver;
|
||||
use deno_semver::jsr::JsrPackageReqReference;
|
||||
use deno_semver::npm::NpmPackageReqReference;
|
||||
use deno_semver::package::PackageNv;
|
||||
use deno_semver::package::PackageReq;
|
||||
use indexmap::IndexMap;
|
||||
use node_resolver::errors::ClosestPkgJsonError;
|
||||
use node_resolver::NodeResolution;
|
||||
use node_resolver::InNpmPackageChecker;
|
||||
use node_resolver::NodeResolutionMode;
|
||||
use node_resolver::NpmResolver;
|
||||
use std::borrow::Cow;
|
||||
use std::collections::BTreeMap;
|
||||
use std::collections::BTreeSet;
|
||||
|
@ -36,6 +38,7 @@ use crate::args::create_default_npmrc;
|
|||
use crate::args::CacheSetting;
|
||||
use crate::args::CliLockfile;
|
||||
use crate::args::NpmInstallDepsProvider;
|
||||
use crate::cache::DenoCacheEnvFsAdapter;
|
||||
use crate::graph_util::CliJsrUrlProvider;
|
||||
use crate::http_util::HttpClientProvider;
|
||||
use crate::lsp::config::Config;
|
||||
|
@ -43,40 +46,50 @@ use crate::lsp::config::ConfigData;
|
|||
use crate::lsp::logging::lsp_warn;
|
||||
use crate::npm::create_cli_npm_resolver_for_lsp;
|
||||
use crate::npm::CliByonmNpmResolverCreateOptions;
|
||||
use crate::npm::CliManagedInNpmPkgCheckerCreateOptions;
|
||||
use crate::npm::CliManagedNpmResolverCreateOptions;
|
||||
use crate::npm::CliNpmResolver;
|
||||
use crate::npm::CliNpmResolverCreateOptions;
|
||||
use crate::npm::CliNpmResolverManagedCreateOptions;
|
||||
use crate::npm::CliNpmResolverManagedSnapshotOption;
|
||||
use crate::npm::CreateInNpmPkgCheckerOptions;
|
||||
use crate::npm::ManagedCliNpmResolver;
|
||||
use crate::resolver::CjsResolutionStore;
|
||||
use crate::resolver::CjsTracker;
|
||||
use crate::resolver::CjsTrackerOptions;
|
||||
use crate::resolver::CliDenoResolverFs;
|
||||
use crate::resolver::CliGraphResolver;
|
||||
use crate::resolver::CliGraphResolverOptions;
|
||||
use crate::resolver::CliNodeResolver;
|
||||
use crate::resolver::WorkerCliNpmGraphResolver;
|
||||
use crate::tsc::into_specifier_and_media_type;
|
||||
use crate::util::progress_bar::ProgressBar;
|
||||
use crate::util::progress_bar::ProgressBarStyle;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct LspScopeResolver {
|
||||
cjs_tracker: Option<Arc<LspCjsTracker>>,
|
||||
graph_resolver: Arc<CliGraphResolver>,
|
||||
jsr_resolver: Option<Arc<JsrCacheResolver>>,
|
||||
npm_resolver: Option<Arc<dyn CliNpmResolver>>,
|
||||
node_resolver: Option<Arc<CliNodeResolver>>,
|
||||
pkg_json_resolver: Option<Arc<PackageJsonResolver>>,
|
||||
redirect_resolver: Option<Arc<RedirectResolver>>,
|
||||
graph_imports: Arc<IndexMap<ModuleSpecifier, GraphImport>>,
|
||||
package_json_deps_by_resolution: Arc<IndexMap<ModuleSpecifier, String>>,
|
||||
config_data: Option<Arc<ConfigData>>,
|
||||
}
|
||||
|
||||
impl Default for LspScopeResolver {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
cjs_tracker: None,
|
||||
graph_resolver: create_graph_resolver(None, None, None),
|
||||
jsr_resolver: None,
|
||||
npm_resolver: None,
|
||||
node_resolver: None,
|
||||
pkg_json_resolver: None,
|
||||
redirect_resolver: None,
|
||||
graph_imports: Default::default(),
|
||||
package_json_deps_by_resolution: Default::default(),
|
||||
config_data: None,
|
||||
}
|
||||
}
|
||||
|
@ -90,14 +103,35 @@ impl LspScopeResolver {
|
|||
) -> Self {
|
||||
let mut npm_resolver = None;
|
||||
let mut node_resolver = None;
|
||||
let mut lsp_cjs_tracker = None;
|
||||
let fs = Arc::new(deno_fs::RealFs);
|
||||
let pkg_json_resolver = Arc::new(PackageJsonResolver::new(
|
||||
deno_runtime::deno_node::DenoFsNodeResolverEnv::new(fs.clone()),
|
||||
));
|
||||
if let Some(http_client) = http_client_provider {
|
||||
npm_resolver = create_npm_resolver(
|
||||
config_data.map(|d| d.as_ref()),
|
||||
cache,
|
||||
http_client,
|
||||
&pkg_json_resolver,
|
||||
)
|
||||
.await;
|
||||
node_resolver = create_node_resolver(npm_resolver.as_ref());
|
||||
if let Some(npm_resolver) = &npm_resolver {
|
||||
let in_npm_pkg_checker = create_in_npm_pkg_checker(npm_resolver);
|
||||
let cjs_tracker = create_cjs_tracker(
|
||||
in_npm_pkg_checker.clone(),
|
||||
pkg_json_resolver.clone(),
|
||||
);
|
||||
lsp_cjs_tracker =
|
||||
Some(Arc::new(LspCjsTracker::new(cjs_tracker.clone())));
|
||||
node_resolver = Some(create_node_resolver(
|
||||
cjs_tracker,
|
||||
fs.clone(),
|
||||
in_npm_pkg_checker,
|
||||
npm_resolver,
|
||||
pkg_json_resolver.clone(),
|
||||
));
|
||||
}
|
||||
}
|
||||
let graph_resolver = create_graph_resolver(
|
||||
config_data.map(|d| d.as_ref()),
|
||||
|
@ -133,13 +167,43 @@ impl LspScopeResolver {
|
|||
)
|
||||
})
|
||||
.unwrap_or_default();
|
||||
let package_json_deps_by_resolution = (|| {
|
||||
let node_resolver = node_resolver.as_ref()?;
|
||||
let package_json = config_data?.maybe_pkg_json()?;
|
||||
let referrer = package_json.specifier();
|
||||
let dependencies = package_json.dependencies.as_ref()?;
|
||||
let result = dependencies
|
||||
.iter()
|
||||
.flat_map(|(name, _)| {
|
||||
let req_ref =
|
||||
NpmPackageReqReference::from_str(&format!("npm:{name}")).ok()?;
|
||||
let specifier = into_specifier_and_media_type(Some(
|
||||
node_resolver
|
||||
.resolve_req_reference(
|
||||
&req_ref,
|
||||
&referrer,
|
||||
NodeResolutionMode::Types,
|
||||
)
|
||||
.ok()?,
|
||||
))
|
||||
.0;
|
||||
Some((specifier, name.clone()))
|
||||
})
|
||||
.collect();
|
||||
Some(result)
|
||||
})();
|
||||
let package_json_deps_by_resolution =
|
||||
Arc::new(package_json_deps_by_resolution.unwrap_or_default());
|
||||
Self {
|
||||
cjs_tracker: lsp_cjs_tracker,
|
||||
graph_resolver,
|
||||
jsr_resolver,
|
||||
npm_resolver,
|
||||
node_resolver,
|
||||
pkg_json_resolver: Some(pkg_json_resolver),
|
||||
redirect_resolver,
|
||||
graph_imports,
|
||||
package_json_deps_by_resolution,
|
||||
config_data: config_data.cloned(),
|
||||
}
|
||||
}
|
||||
|
@ -147,19 +211,44 @@ impl LspScopeResolver {
|
|||
fn snapshot(&self) -> Arc<Self> {
|
||||
let npm_resolver =
|
||||
self.npm_resolver.as_ref().map(|r| r.clone_snapshotted());
|
||||
let node_resolver = create_node_resolver(npm_resolver.as_ref());
|
||||
let fs = Arc::new(deno_fs::RealFs);
|
||||
let pkg_json_resolver = Arc::new(PackageJsonResolver::new(
|
||||
deno_runtime::deno_node::DenoFsNodeResolverEnv::new(fs.clone()),
|
||||
));
|
||||
let mut node_resolver = None;
|
||||
let mut lsp_cjs_tracker = None;
|
||||
if let Some(npm_resolver) = &npm_resolver {
|
||||
let in_npm_pkg_checker = create_in_npm_pkg_checker(npm_resolver);
|
||||
let cjs_tracker = create_cjs_tracker(
|
||||
in_npm_pkg_checker.clone(),
|
||||
pkg_json_resolver.clone(),
|
||||
);
|
||||
lsp_cjs_tracker = Some(Arc::new(LspCjsTracker::new(cjs_tracker.clone())));
|
||||
node_resolver = Some(create_node_resolver(
|
||||
cjs_tracker,
|
||||
fs,
|
||||
in_npm_pkg_checker,
|
||||
npm_resolver,
|
||||
pkg_json_resolver.clone(),
|
||||
));
|
||||
}
|
||||
let graph_resolver = create_graph_resolver(
|
||||
self.config_data.as_deref(),
|
||||
npm_resolver.as_ref(),
|
||||
node_resolver.as_ref(),
|
||||
);
|
||||
Arc::new(Self {
|
||||
cjs_tracker: lsp_cjs_tracker,
|
||||
graph_resolver,
|
||||
jsr_resolver: self.jsr_resolver.clone(),
|
||||
npm_resolver,
|
||||
node_resolver,
|
||||
redirect_resolver: self.redirect_resolver.clone(),
|
||||
pkg_json_resolver: Some(pkg_json_resolver),
|
||||
graph_imports: self.graph_imports.clone(),
|
||||
package_json_deps_by_resolution: self
|
||||
.package_json_deps_by_resolution
|
||||
.clone(),
|
||||
config_data: self.config_data.clone(),
|
||||
})
|
||||
}
|
||||
|
@ -261,6 +350,22 @@ impl LspResolver {
|
|||
resolver.graph_resolver.create_graph_npm_resolver()
|
||||
}
|
||||
|
||||
pub fn maybe_cjs_tracker(
|
||||
&self,
|
||||
file_referrer: Option<&ModuleSpecifier>,
|
||||
) -> Option<&Arc<LspCjsTracker>> {
|
||||
let resolver = self.get_scope_resolver(file_referrer);
|
||||
resolver.cjs_tracker.as_ref()
|
||||
}
|
||||
|
||||
pub fn maybe_node_resolver(
|
||||
&self,
|
||||
file_referrer: Option<&ModuleSpecifier>,
|
||||
) -> Option<&Arc<CliNodeResolver>> {
|
||||
let resolver = self.get_scope_resolver(file_referrer);
|
||||
resolver.node_resolver.as_ref()
|
||||
}
|
||||
|
||||
pub fn maybe_managed_npm_resolver(
|
||||
&self,
|
||||
file_referrer: Option<&ModuleSpecifier>,
|
||||
|
@ -328,13 +433,25 @@ impl LspResolver {
|
|||
) -> Option<(ModuleSpecifier, MediaType)> {
|
||||
let resolver = self.get_scope_resolver(file_referrer);
|
||||
let node_resolver = resolver.node_resolver.as_ref()?;
|
||||
Some(NodeResolution::into_specifier_and_media_type(Some(
|
||||
Some(into_specifier_and_media_type(Some(
|
||||
node_resolver
|
||||
.resolve_req_reference(req_ref, referrer, NodeResolutionMode::Types)
|
||||
.ok()?,
|
||||
)))
|
||||
}
|
||||
|
||||
pub fn file_url_to_package_json_dep(
|
||||
&self,
|
||||
specifier: &ModuleSpecifier,
|
||||
file_referrer: Option<&ModuleSpecifier>,
|
||||
) -> Option<String> {
|
||||
let resolver = self.get_scope_resolver(file_referrer);
|
||||
resolver
|
||||
.package_json_deps_by_resolution
|
||||
.get(specifier)
|
||||
.cloned()
|
||||
}
|
||||
|
||||
pub fn in_node_modules(&self, specifier: &ModuleSpecifier) -> bool {
|
||||
fn has_node_modules_dir(specifier: &ModuleSpecifier) -> bool {
|
||||
// consider any /node_modules/ directory as being in the node_modules
|
||||
|
@ -346,14 +463,10 @@ impl LspResolver {
|
|||
.contains("/node_modules/")
|
||||
}
|
||||
|
||||
let global_npm_resolver = self
|
||||
.get_scope_resolver(Some(specifier))
|
||||
.npm_resolver
|
||||
.as_ref()
|
||||
.and_then(|npm_resolver| npm_resolver.as_managed())
|
||||
.filter(|r| r.root_node_modules_path().is_none());
|
||||
if let Some(npm_resolver) = &global_npm_resolver {
|
||||
if npm_resolver.in_npm_package(specifier) {
|
||||
if let Some(node_resolver) =
|
||||
&self.get_scope_resolver(Some(specifier)).node_resolver
|
||||
{
|
||||
if node_resolver.in_npm_package(specifier) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -361,18 +474,6 @@ impl LspResolver {
|
|||
has_node_modules_dir(specifier)
|
||||
}
|
||||
|
||||
pub fn node_media_type(
|
||||
&self,
|
||||
specifier: &ModuleSpecifier,
|
||||
) -> Option<MediaType> {
|
||||
let resolver = self.get_scope_resolver(Some(specifier));
|
||||
let node_resolver = resolver.node_resolver.as_ref()?;
|
||||
let resolution = node_resolver
|
||||
.url_to_node_resolution(specifier.clone())
|
||||
.ok()?;
|
||||
Some(NodeResolution::into_specifier_and_media_type(Some(resolution)).1)
|
||||
}
|
||||
|
||||
pub fn is_bare_package_json_dep(
|
||||
&self,
|
||||
specifier_text: &str,
|
||||
|
@ -398,10 +499,10 @@ impl LspResolver {
|
|||
referrer: &ModuleSpecifier,
|
||||
) -> Result<Option<Arc<PackageJson>>, ClosestPkgJsonError> {
|
||||
let resolver = self.get_scope_resolver(Some(referrer));
|
||||
let Some(node_resolver) = resolver.node_resolver.as_ref() else {
|
||||
let Some(pkg_json_resolver) = resolver.pkg_json_resolver.as_ref() else {
|
||||
return Ok(None);
|
||||
};
|
||||
node_resolver.get_closest_package_json(referrer)
|
||||
pkg_json_resolver.get_closest_package_json(referrer)
|
||||
}
|
||||
|
||||
pub fn resolve_redirects(
|
||||
|
@ -457,11 +558,13 @@ async fn create_npm_resolver(
|
|||
config_data: Option<&ConfigData>,
|
||||
cache: &LspCache,
|
||||
http_client_provider: &Arc<HttpClientProvider>,
|
||||
pkg_json_resolver: &Arc<PackageJsonResolver>,
|
||||
) -> Option<Arc<dyn CliNpmResolver>> {
|
||||
let enable_byonm = config_data.map(|d| d.byonm).unwrap_or(false);
|
||||
let options = if enable_byonm {
|
||||
CliNpmResolverCreateOptions::Byonm(CliByonmNpmResolverCreateOptions {
|
||||
fs: CliDenoResolverFs(Arc::new(deno_fs::RealFs)),
|
||||
pkg_json_resolver: pkg_json_resolver.clone(),
|
||||
root_node_modules_dir: config_data.and_then(|config_data| {
|
||||
config_data.node_modules_dir.clone().or_else(|| {
|
||||
url_to_file_path(&config_data.scope)
|
||||
|
@ -471,7 +574,15 @@ async fn create_npm_resolver(
|
|||
}),
|
||||
})
|
||||
} else {
|
||||
CliNpmResolverCreateOptions::Managed(CliNpmResolverManagedCreateOptions {
|
||||
let npmrc = config_data
|
||||
.and_then(|d| d.npmrc.clone())
|
||||
.unwrap_or_else(create_default_npmrc);
|
||||
let npm_cache_dir = Arc::new(NpmCacheDir::new(
|
||||
&DenoCacheEnvFsAdapter(&deno_fs::RealFs),
|
||||
cache.deno_dir().npm_folder_path(),
|
||||
npmrc.get_all_known_registries_urls(),
|
||||
));
|
||||
CliNpmResolverCreateOptions::Managed(CliManagedNpmResolverCreateOptions {
|
||||
http_client_provider: http_client_provider.clone(),
|
||||
snapshot: match config_data.and_then(|d| d.lockfile.as_ref()) {
|
||||
Some(lockfile) => {
|
||||
|
@ -485,7 +596,7 @@ async fn create_npm_resolver(
|
|||
// updating it. Only the cache request should update the lockfile.
|
||||
maybe_lockfile: None,
|
||||
fs: Arc::new(deno_fs::RealFs),
|
||||
npm_global_cache_dir: cache.deno_dir().npm_folder_path(),
|
||||
npm_cache_dir,
|
||||
// Use an "only" cache setting in order to make the
|
||||
// user do an explicit "cache" command and prevent
|
||||
// the cache from being filled with lots of packages while
|
||||
|
@ -496,9 +607,7 @@ async fn create_npm_resolver(
|
|||
.and_then(|d| d.node_modules_dir.clone()),
|
||||
// only used for top level install, so we can ignore this
|
||||
npm_install_deps_provider: Arc::new(NpmInstallDepsProvider::empty()),
|
||||
npmrc: config_data
|
||||
.and_then(|d| d.npmrc.clone())
|
||||
.unwrap_or_else(create_default_npmrc),
|
||||
npmrc,
|
||||
npm_system_info: NpmSystemInfo::default(),
|
||||
lifecycle_scripts: Default::default(),
|
||||
})
|
||||
|
@ -506,28 +615,59 @@ async fn create_npm_resolver(
|
|||
Some(create_cli_npm_resolver_for_lsp(options).await)
|
||||
}
|
||||
|
||||
fn create_cjs_tracker(
|
||||
in_npm_pkg_checker: Arc<dyn InNpmPackageChecker>,
|
||||
pkg_json_resolver: Arc<PackageJsonResolver>,
|
||||
) -> Arc<CjsTracker> {
|
||||
Arc::new(CjsTracker::new(
|
||||
in_npm_pkg_checker,
|
||||
pkg_json_resolver,
|
||||
CjsTrackerOptions {
|
||||
// todo(dsherret): support in the lsp by stabilizing the feature
|
||||
// so that we don't have to pipe the config in here
|
||||
unstable_detect_cjs: false,
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
fn create_in_npm_pkg_checker(
|
||||
npm_resolver: &Arc<dyn CliNpmResolver>,
|
||||
) -> Arc<dyn InNpmPackageChecker> {
|
||||
crate::npm::create_in_npm_pkg_checker(match npm_resolver.as_inner() {
|
||||
crate::npm::InnerCliNpmResolverRef::Byonm(_) => {
|
||||
CreateInNpmPkgCheckerOptions::Byonm
|
||||
}
|
||||
crate::npm::InnerCliNpmResolverRef::Managed(m) => {
|
||||
CreateInNpmPkgCheckerOptions::Managed(
|
||||
CliManagedInNpmPkgCheckerCreateOptions {
|
||||
root_cache_dir_url: m.global_cache_root_url(),
|
||||
maybe_node_modules_path: m.maybe_node_modules_path(),
|
||||
},
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn create_node_resolver(
|
||||
npm_resolver: Option<&Arc<dyn CliNpmResolver>>,
|
||||
) -> Option<Arc<CliNodeResolver>> {
|
||||
use once_cell::sync::Lazy;
|
||||
|
||||
// it's not ideal to share this across all scopes and to
|
||||
// never clear it, but it's fine for the time being
|
||||
static CJS_RESOLUTIONS: Lazy<Arc<CjsResolutionStore>> =
|
||||
Lazy::new(Default::default);
|
||||
|
||||
let npm_resolver = npm_resolver?;
|
||||
let fs = Arc::new(deno_fs::RealFs);
|
||||
cjs_tracker: Arc<CjsTracker>,
|
||||
fs: Arc<dyn deno_fs::FileSystem>,
|
||||
in_npm_pkg_checker: Arc<dyn InNpmPackageChecker>,
|
||||
npm_resolver: &Arc<dyn CliNpmResolver>,
|
||||
pkg_json_resolver: Arc<PackageJsonResolver>,
|
||||
) -> Arc<CliNodeResolver> {
|
||||
let node_resolver_inner = Arc::new(NodeResolver::new(
|
||||
deno_runtime::deno_node::DenoFsNodeResolverEnv::new(fs.clone()),
|
||||
in_npm_pkg_checker.clone(),
|
||||
npm_resolver.clone().into_npm_resolver(),
|
||||
pkg_json_resolver.clone(),
|
||||
));
|
||||
Some(Arc::new(CliNodeResolver::new(
|
||||
CJS_RESOLUTIONS.clone(),
|
||||
Arc::new(CliNodeResolver::new(
|
||||
cjs_tracker.clone(),
|
||||
fs,
|
||||
in_npm_pkg_checker,
|
||||
node_resolver_inner,
|
||||
npm_resolver.clone(),
|
||||
)))
|
||||
))
|
||||
}
|
||||
|
||||
fn create_graph_resolver(
|
||||
|
@ -555,8 +695,8 @@ fn create_graph_resolver(
|
|||
workspace.to_maybe_jsx_import_source_config().ok().flatten()
|
||||
}),
|
||||
maybe_vendor_dir: config_data.and_then(|d| d.vendor_dir.as_ref()),
|
||||
bare_node_builtins_enabled: workspace
|
||||
.is_some_and(|workspace| workspace.has_unstable("bare-node-builtins")),
|
||||
bare_node_builtins_enabled: config_data
|
||||
.is_some_and(|d| d.unstable.contains("bare-node-builtins")),
|
||||
sloppy_imports_resolver: config_data
|
||||
.and_then(|d| d.sloppy_imports_resolver.clone()),
|
||||
}))
|
||||
|
@ -702,6 +842,45 @@ impl RedirectResolver {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct LspCjsTracker {
|
||||
cjs_tracker: Arc<CjsTracker>,
|
||||
}
|
||||
|
||||
impl LspCjsTracker {
|
||||
pub fn new(cjs_tracker: Arc<CjsTracker>) -> Self {
|
||||
Self { cjs_tracker }
|
||||
}
|
||||
|
||||
pub fn is_cjs(
|
||||
&self,
|
||||
specifier: &ModuleSpecifier,
|
||||
media_type: MediaType,
|
||||
maybe_parsed_source: Option<&ParsedSource>,
|
||||
) -> bool {
|
||||
if let Some(module_kind) =
|
||||
self.cjs_tracker.get_known_kind(specifier, media_type)
|
||||
{
|
||||
module_kind.is_cjs()
|
||||
} else {
|
||||
let maybe_is_script = maybe_parsed_source.map(|p| p.compute_is_script());
|
||||
maybe_is_script
|
||||
.and_then(|is_script| {
|
||||
self
|
||||
.cjs_tracker
|
||||
.is_cjs_with_known_is_script(specifier, media_type, is_script)
|
||||
.ok()
|
||||
})
|
||||
.unwrap_or_else(|| {
|
||||
self
|
||||
.cjs_tracker
|
||||
.is_maybe_cjs(specifier, media_type)
|
||||
.unwrap_or(false)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
|
|
@ -650,7 +650,7 @@ pub mod tests {
|
|||
.unwrap();
|
||||
let text_info = parsed_module.text_info_lazy().clone();
|
||||
let mut collector = TestCollector::new(specifier, text_info);
|
||||
parsed_module.module().visit_with(&mut collector);
|
||||
parsed_module.program().visit_with(&mut collector);
|
||||
collector.take()
|
||||
}
|
||||
|
||||
|
|
129
cli/lsp/tsc.rs
129
cli/lsp/tsc.rs
|
@ -236,7 +236,7 @@ pub struct TsServer {
|
|||
performance: Arc<Performance>,
|
||||
sender: mpsc::UnboundedSender<Request>,
|
||||
receiver: Mutex<Option<mpsc::UnboundedReceiver<Request>>>,
|
||||
specifier_map: Arc<TscSpecifierMap>,
|
||||
pub specifier_map: Arc<TscSpecifierMap>,
|
||||
inspector_server: Mutex<Option<Arc<InspectorServer>>>,
|
||||
pending_change: Mutex<Option<PendingChange>>,
|
||||
}
|
||||
|
@ -882,20 +882,22 @@ impl TsServer {
|
|||
options: GetCompletionsAtPositionOptions,
|
||||
format_code_settings: FormatCodeSettings,
|
||||
scope: Option<ModuleSpecifier>,
|
||||
) -> Option<CompletionInfo> {
|
||||
) -> Result<Option<CompletionInfo>, AnyError> {
|
||||
let req = TscRequest::GetCompletionsAtPosition(Box::new((
|
||||
self.specifier_map.denormalize(&specifier),
|
||||
position,
|
||||
options,
|
||||
format_code_settings,
|
||||
)));
|
||||
match self.request(snapshot, req, scope).await {
|
||||
Ok(maybe_info) => maybe_info,
|
||||
Err(err) => {
|
||||
log::error!("Unable to get completion info from TypeScript: {:#}", err);
|
||||
None
|
||||
}
|
||||
}
|
||||
self
|
||||
.request::<Option<CompletionInfo>>(snapshot, req, scope)
|
||||
.await
|
||||
.map(|mut info| {
|
||||
if let Some(info) = &mut info {
|
||||
info.normalize(&self.specifier_map);
|
||||
}
|
||||
info
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn get_completion_details(
|
||||
|
@ -3642,6 +3644,12 @@ pub struct CompletionInfo {
|
|||
}
|
||||
|
||||
impl CompletionInfo {
|
||||
fn normalize(&mut self, specifier_map: &TscSpecifierMap) {
|
||||
for entry in &mut self.entries {
|
||||
entry.normalize(specifier_map);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_completion_response(
|
||||
&self,
|
||||
line_index: Arc<LineIndex>,
|
||||
|
@ -3703,11 +3711,17 @@ pub struct CompletionItemData {
|
|||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct CompletionEntryDataImport {
|
||||
struct CompletionEntryDataAutoImport {
|
||||
module_specifier: String,
|
||||
file_name: String,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct CompletionNormalizedAutoImportData {
|
||||
raw: CompletionEntryDataAutoImport,
|
||||
normalized: ModuleSpecifier,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CompletionEntry {
|
||||
|
@ -3740,9 +3754,28 @@ pub struct CompletionEntry {
|
|||
is_import_statement_completion: Option<bool>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
data: Option<Value>,
|
||||
/// This is not from tsc, we add it for convenience during normalization.
|
||||
/// Represents `self.data.file_name`, but normalized.
|
||||
#[serde(skip)]
|
||||
auto_import_data: Option<CompletionNormalizedAutoImportData>,
|
||||
}
|
||||
|
||||
impl CompletionEntry {
|
||||
fn normalize(&mut self, specifier_map: &TscSpecifierMap) {
|
||||
let Some(data) = &self.data else {
|
||||
return;
|
||||
};
|
||||
let Ok(raw) =
|
||||
serde_json::from_value::<CompletionEntryDataAutoImport>(data.clone())
|
||||
else {
|
||||
return;
|
||||
};
|
||||
if let Ok(normalized) = specifier_map.normalize(&raw.file_name) {
|
||||
self.auto_import_data =
|
||||
Some(CompletionNormalizedAutoImportData { raw, normalized });
|
||||
}
|
||||
}
|
||||
|
||||
fn get_commit_characters(
|
||||
&self,
|
||||
info: &CompletionInfo,
|
||||
|
@ -3891,25 +3924,24 @@ impl CompletionEntry {
|
|||
|
||||
if let Some(source) = &self.source {
|
||||
let mut display_source = source.clone();
|
||||
if let Some(data) = &self.data {
|
||||
if let Ok(import_data) =
|
||||
serde_json::from_value::<CompletionEntryDataImport>(data.clone())
|
||||
if let Some(import_data) = &self.auto_import_data {
|
||||
if let Some(new_module_specifier) = language_server
|
||||
.get_ts_response_import_mapper(specifier)
|
||||
.check_specifier(&import_data.normalized, specifier)
|
||||
.or_else(|| relative_specifier(specifier, &import_data.normalized))
|
||||
{
|
||||
if let Ok(import_specifier) = resolve_url(&import_data.file_name) {
|
||||
if let Some(new_module_specifier) = language_server
|
||||
.get_ts_response_import_mapper(specifier)
|
||||
.check_specifier(&import_specifier, specifier)
|
||||
.or_else(|| relative_specifier(specifier, &import_specifier))
|
||||
{
|
||||
display_source.clone_from(&new_module_specifier);
|
||||
if new_module_specifier != import_data.module_specifier {
|
||||
specifier_rewrite =
|
||||
Some((import_data.module_specifier, new_module_specifier));
|
||||
}
|
||||
} else if source.starts_with(jsr_url().as_str()) {
|
||||
return None;
|
||||
}
|
||||
if new_module_specifier.contains("/node_modules/") {
|
||||
return None;
|
||||
}
|
||||
display_source.clone_from(&new_module_specifier);
|
||||
if new_module_specifier != import_data.raw.module_specifier {
|
||||
specifier_rewrite = Some((
|
||||
import_data.raw.module_specifier.clone(),
|
||||
new_module_specifier,
|
||||
));
|
||||
}
|
||||
} else if source.starts_with(jsr_url().as_str()) {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
// We want relative or bare (import-mapped or otherwise) specifiers to
|
||||
|
@ -4212,6 +4244,13 @@ impl TscSpecifierMap {
|
|||
return specifier.to_string();
|
||||
}
|
||||
let mut specifier = original.to_string();
|
||||
if specifier.contains("/node_modules/.deno/")
|
||||
&& !specifier.contains("/node_modules/@types/node/")
|
||||
{
|
||||
// The ts server doesn't give completions from files in
|
||||
// `node_modules/.deno/`. We work around it like this.
|
||||
specifier = specifier.replace("/node_modules/", "/$node_modules/");
|
||||
}
|
||||
let media_type = MediaType::from_specifier(original);
|
||||
// If the URL-inferred media type doesn't correspond to tsc's path-inferred
|
||||
// media type, force it to be the same by appending an extension.
|
||||
|
@ -4329,7 +4368,7 @@ fn op_is_cancelled(state: &mut OpState) -> bool {
|
|||
fn op_is_node_file(state: &mut OpState, #[string] path: String) -> bool {
|
||||
let state = state.borrow::<State>();
|
||||
let mark = state.performance.mark("tsc.op.op_is_node_file");
|
||||
let r = match ModuleSpecifier::parse(&path) {
|
||||
let r = match state.specifier_map.normalize(path) {
|
||||
Ok(specifier) => state.state_snapshot.resolver.in_node_modules(&specifier),
|
||||
Err(_) => false,
|
||||
};
|
||||
|
@ -4362,14 +4401,25 @@ fn op_load<'s>(
|
|||
None
|
||||
} else {
|
||||
let asset_or_document = state.get_asset_or_document(&specifier);
|
||||
asset_or_document.map(|doc| LoadResponse {
|
||||
data: doc.text(),
|
||||
script_kind: crate::tsc::as_ts_script_kind(doc.media_type()),
|
||||
version: state.script_version(&specifier),
|
||||
is_cjs: matches!(
|
||||
doc.media_type(),
|
||||
MediaType::Cjs | MediaType::Cts | MediaType::Dcts
|
||||
),
|
||||
asset_or_document.map(|doc| {
|
||||
let maybe_cjs_tracker = state
|
||||
.state_snapshot
|
||||
.resolver
|
||||
.maybe_cjs_tracker(Some(&specifier));
|
||||
LoadResponse {
|
||||
data: doc.text(),
|
||||
script_kind: crate::tsc::as_ts_script_kind(doc.media_type()),
|
||||
version: state.script_version(&specifier),
|
||||
is_cjs: maybe_cjs_tracker
|
||||
.map(|t| {
|
||||
t.is_cjs(
|
||||
&specifier,
|
||||
doc.media_type(),
|
||||
doc.maybe_parsed_source().and_then(|p| p.as_ref().ok()),
|
||||
)
|
||||
})
|
||||
.unwrap_or(false),
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
|
@ -4598,7 +4648,10 @@ fn op_script_names(state: &mut OpState) -> ScriptNames {
|
|||
for doc in &docs {
|
||||
let specifier = doc.specifier();
|
||||
let is_open = doc.is_open();
|
||||
if is_open || specifier.scheme() == "file" {
|
||||
if is_open
|
||||
|| (specifier.scheme() == "file"
|
||||
&& !state.state_snapshot.resolver.in_node_modules(specifier))
|
||||
{
|
||||
let script_names = doc
|
||||
.scope()
|
||||
.and_then(|s| result.by_scope.get_mut(s))
|
||||
|
@ -6024,6 +6077,7 @@ mod tests {
|
|||
Some(temp_dir.url()),
|
||||
)
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
assert_eq!(info.entries.len(), 22);
|
||||
let details = ts_server
|
||||
|
@ -6183,6 +6237,7 @@ mod tests {
|
|||
Some(temp_dir.url()),
|
||||
)
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
let entry = info
|
||||
.entries
|
||||
|
|
|
@ -135,7 +135,7 @@ async fn run_subcommand(flags: Arc<Flags>) -> Result<i32, AnyError> {
|
|||
tools::compile::compile(flags, compile_flags).await
|
||||
}),
|
||||
DenoSubcommand::Coverage(coverage_flags) => spawn_subcommand(async {
|
||||
tools::coverage::cover_files(flags, coverage_flags).await
|
||||
tools::coverage::cover_files(flags, coverage_flags)
|
||||
}),
|
||||
DenoSubcommand::Fmt(fmt_flags) => {
|
||||
spawn_subcommand(
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
use std::borrow::Cow;
|
||||
use std::cell::RefCell;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
use std::pin::Pin;
|
||||
use std::rc::Rc;
|
||||
|
@ -23,19 +24,23 @@ use crate::graph_container::ModuleGraphUpdatePermit;
|
|||
use crate::graph_util::CreateGraphOptions;
|
||||
use crate::graph_util::ModuleGraphBuilder;
|
||||
use crate::node;
|
||||
use crate::node::CliNodeCodeTranslator;
|
||||
use crate::npm::CliNpmResolver;
|
||||
use crate::resolver::CjsTracker;
|
||||
use crate::resolver::CliGraphResolver;
|
||||
use crate::resolver::CliNodeResolver;
|
||||
use crate::resolver::ModuleCodeStringSource;
|
||||
use crate::resolver::NotSupportedKindInNpmError;
|
||||
use crate::resolver::NpmModuleLoader;
|
||||
use crate::tools::check;
|
||||
use crate::tools::check::TypeChecker;
|
||||
use crate::util::progress_bar::ProgressBar;
|
||||
use crate::util::text_encoding::code_without_source_map;
|
||||
use crate::util::text_encoding::source_map_from_code;
|
||||
use crate::worker::ModuleLoaderAndSourceMapGetter;
|
||||
use crate::worker::CreateModuleLoaderResult;
|
||||
use crate::worker::ModuleLoaderFactory;
|
||||
use deno_ast::MediaType;
|
||||
use deno_ast::ModuleKind;
|
||||
use deno_core::anyhow::anyhow;
|
||||
use deno_core::anyhow::bail;
|
||||
use deno_core::anyhow::Context;
|
||||
|
@ -63,9 +68,12 @@ use deno_graph::Module;
|
|||
use deno_graph::ModuleGraph;
|
||||
use deno_graph::Resolution;
|
||||
use deno_runtime::code_cache;
|
||||
use deno_runtime::deno_fs::FileSystem;
|
||||
use deno_runtime::deno_node::create_host_defined_options;
|
||||
use deno_runtime::deno_node::NodeRequireLoader;
|
||||
use deno_runtime::deno_permissions::PermissionsContainer;
|
||||
use deno_semver::npm::NpmPackageReqReference;
|
||||
use node_resolver::InNpmPackageChecker;
|
||||
use node_resolver::NodeResolutionMode;
|
||||
|
||||
pub struct ModuleLoadPreparer {
|
||||
|
@ -198,11 +206,16 @@ struct SharedCliModuleLoaderState {
|
|||
lib_worker: TsTypeLib,
|
||||
initial_cwd: PathBuf,
|
||||
is_inspecting: bool,
|
||||
is_npm_main: bool,
|
||||
is_repl: bool,
|
||||
cjs_tracker: Arc<CjsTracker>,
|
||||
code_cache: Option<Arc<CodeCache>>,
|
||||
emitter: Arc<Emitter>,
|
||||
fs: Arc<dyn FileSystem>,
|
||||
in_npm_pkg_checker: Arc<dyn InNpmPackageChecker>,
|
||||
main_module_graph_container: Arc<MainModuleGraphContainer>,
|
||||
module_load_preparer: Arc<ModuleLoadPreparer>,
|
||||
node_code_translator: Arc<CliNodeCodeTranslator>,
|
||||
node_resolver: Arc<CliNodeResolver>,
|
||||
npm_resolver: Arc<dyn CliNpmResolver>,
|
||||
npm_module_loader: NpmModuleLoader,
|
||||
|
@ -218,10 +231,14 @@ impl CliModuleLoaderFactory {
|
|||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn new(
|
||||
options: &CliOptions,
|
||||
cjs_tracker: Arc<CjsTracker>,
|
||||
code_cache: Option<Arc<CodeCache>>,
|
||||
emitter: Arc<Emitter>,
|
||||
fs: Arc<dyn FileSystem>,
|
||||
in_npm_pkg_checker: Arc<dyn InNpmPackageChecker>,
|
||||
main_module_graph_container: Arc<MainModuleGraphContainer>,
|
||||
module_load_preparer: Arc<ModuleLoadPreparer>,
|
||||
node_code_translator: Arc<CliNodeCodeTranslator>,
|
||||
node_resolver: Arc<CliNodeResolver>,
|
||||
npm_resolver: Arc<dyn CliNpmResolver>,
|
||||
npm_module_loader: NpmModuleLoader,
|
||||
|
@ -235,14 +252,19 @@ impl CliModuleLoaderFactory {
|
|||
lib_worker: options.ts_type_lib_worker(),
|
||||
initial_cwd: options.initial_cwd().to_path_buf(),
|
||||
is_inspecting: options.is_inspecting(),
|
||||
is_npm_main: options.is_npm_main(),
|
||||
is_repl: matches!(
|
||||
options.sub_command(),
|
||||
DenoSubcommand::Repl(_) | DenoSubcommand::Jupyter(_)
|
||||
),
|
||||
cjs_tracker,
|
||||
code_cache,
|
||||
emitter,
|
||||
fs,
|
||||
in_npm_pkg_checker,
|
||||
main_module_graph_container,
|
||||
module_load_preparer,
|
||||
node_code_translator,
|
||||
node_resolver,
|
||||
npm_resolver,
|
||||
npm_module_loader,
|
||||
|
@ -259,19 +281,30 @@ impl CliModuleLoaderFactory {
|
|||
is_worker: bool,
|
||||
parent_permissions: PermissionsContainer,
|
||||
permissions: PermissionsContainer,
|
||||
) -> ModuleLoaderAndSourceMapGetter {
|
||||
let loader = Rc::new(CliModuleLoader(Rc::new(CliModuleLoaderInner {
|
||||
lib,
|
||||
is_worker,
|
||||
parent_permissions,
|
||||
permissions,
|
||||
) -> CreateModuleLoaderResult {
|
||||
let module_loader =
|
||||
Rc::new(CliModuleLoader(Rc::new(CliModuleLoaderInner {
|
||||
lib,
|
||||
is_worker,
|
||||
is_npm_main: self.shared.is_npm_main,
|
||||
parent_permissions,
|
||||
permissions,
|
||||
graph_container: graph_container.clone(),
|
||||
node_code_translator: self.shared.node_code_translator.clone(),
|
||||
emitter: self.shared.emitter.clone(),
|
||||
parsed_source_cache: self.shared.parsed_source_cache.clone(),
|
||||
shared: self.shared.clone(),
|
||||
})));
|
||||
let node_require_loader = Rc::new(CliNodeRequireLoader::new(
|
||||
self.shared.emitter.clone(),
|
||||
self.shared.fs.clone(),
|
||||
graph_container,
|
||||
emitter: self.shared.emitter.clone(),
|
||||
parsed_source_cache: self.shared.parsed_source_cache.clone(),
|
||||
shared: self.shared.clone(),
|
||||
})));
|
||||
ModuleLoaderAndSourceMapGetter {
|
||||
module_loader: loader,
|
||||
self.shared.in_npm_pkg_checker.clone(),
|
||||
self.shared.npm_resolver.clone(),
|
||||
));
|
||||
CreateModuleLoaderResult {
|
||||
module_loader,
|
||||
node_require_loader,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -280,7 +313,7 @@ impl ModuleLoaderFactory for CliModuleLoaderFactory {
|
|||
fn create_for_main(
|
||||
&self,
|
||||
root_permissions: PermissionsContainer,
|
||||
) -> ModuleLoaderAndSourceMapGetter {
|
||||
) -> CreateModuleLoaderResult {
|
||||
self.create_with_lib(
|
||||
(*self.shared.main_module_graph_container).clone(),
|
||||
self.shared.lib_window,
|
||||
|
@ -294,7 +327,7 @@ impl ModuleLoaderFactory for CliModuleLoaderFactory {
|
|||
&self,
|
||||
parent_permissions: PermissionsContainer,
|
||||
permissions: PermissionsContainer,
|
||||
) -> ModuleLoaderAndSourceMapGetter {
|
||||
) -> CreateModuleLoaderResult {
|
||||
self.create_with_lib(
|
||||
// create a fresh module graph for the worker
|
||||
WorkerModuleGraphContainer::new(Arc::new(ModuleGraph::new(
|
||||
|
@ -310,6 +343,7 @@ impl ModuleLoaderFactory for CliModuleLoaderFactory {
|
|||
|
||||
struct CliModuleLoaderInner<TGraphContainer: ModuleGraphContainer> {
|
||||
lib: TsTypeLib,
|
||||
is_npm_main: bool,
|
||||
is_worker: bool,
|
||||
/// The initial set of permissions used to resolve the static imports in the
|
||||
/// worker. These are "allow all" for main worker, and parent thread
|
||||
|
@ -318,6 +352,7 @@ struct CliModuleLoaderInner<TGraphContainer: ModuleGraphContainer> {
|
|||
permissions: PermissionsContainer,
|
||||
shared: Arc<SharedCliModuleLoaderState>,
|
||||
emitter: Arc<Emitter>,
|
||||
node_code_translator: Arc<CliNodeCodeTranslator>,
|
||||
parsed_source_cache: Arc<ParsedSourceCache>,
|
||||
graph_container: TGraphContainer,
|
||||
}
|
||||
|
@ -331,24 +366,7 @@ impl<TGraphContainer: ModuleGraphContainer>
|
|||
maybe_referrer: Option<&ModuleSpecifier>,
|
||||
requested_module_type: RequestedModuleType,
|
||||
) -> Result<ModuleSource, AnyError> {
|
||||
let code_source = match self.load_prepared_module(specifier).await? {
|
||||
Some(code_source) => code_source,
|
||||
None => {
|
||||
if self.shared.npm_module_loader.if_in_npm_package(specifier) {
|
||||
self
|
||||
.shared
|
||||
.npm_module_loader
|
||||
.load(specifier, maybe_referrer)
|
||||
.await?
|
||||
} else {
|
||||
let mut msg = format!("Loading unprepared module: {specifier}");
|
||||
if let Some(referrer) = maybe_referrer {
|
||||
msg = format!("{}, imported from: {}", msg, referrer.as_str());
|
||||
}
|
||||
return Err(anyhow!(msg));
|
||||
}
|
||||
}
|
||||
};
|
||||
let code_source = self.load_code_source(specifier, maybe_referrer).await?;
|
||||
let code = if self.shared.is_inspecting {
|
||||
// we need the code with the source map in order for
|
||||
// it to work with --inspect or --inspect-brk
|
||||
|
@ -402,6 +420,29 @@ impl<TGraphContainer: ModuleGraphContainer>
|
|||
))
|
||||
}
|
||||
|
||||
async fn load_code_source(
|
||||
&self,
|
||||
specifier: &ModuleSpecifier,
|
||||
maybe_referrer: Option<&ModuleSpecifier>,
|
||||
) -> Result<ModuleCodeStringSource, AnyError> {
|
||||
if let Some(code_source) = self.load_prepared_module(specifier).await? {
|
||||
return Ok(code_source);
|
||||
}
|
||||
if self.shared.node_resolver.in_npm_package(specifier) {
|
||||
return self
|
||||
.shared
|
||||
.npm_module_loader
|
||||
.load(specifier, maybe_referrer)
|
||||
.await;
|
||||
}
|
||||
|
||||
let mut msg = format!("Loading unprepared module: {specifier}");
|
||||
if let Some(referrer) = maybe_referrer {
|
||||
msg = format!("{}, imported from: {}", msg, referrer.as_str());
|
||||
}
|
||||
Err(anyhow!(msg))
|
||||
}
|
||||
|
||||
fn resolve_referrer(
|
||||
&self,
|
||||
referrer: &str,
|
||||
|
@ -474,15 +515,11 @@ impl<TGraphContainer: ModuleGraphContainer>
|
|||
if self.shared.is_repl {
|
||||
if let Ok(reference) = NpmPackageReqReference::from_specifier(&specifier)
|
||||
{
|
||||
return self
|
||||
.shared
|
||||
.node_resolver
|
||||
.resolve_req_reference(
|
||||
&reference,
|
||||
referrer,
|
||||
NodeResolutionMode::Execution,
|
||||
)
|
||||
.map(|res| res.into_url());
|
||||
return self.shared.node_resolver.resolve_req_reference(
|
||||
&reference,
|
||||
referrer,
|
||||
NodeResolutionMode::Execution,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -506,13 +543,15 @@ impl<TGraphContainer: ModuleGraphContainer>
|
|||
.with_context(|| {
|
||||
format!("Could not resolve '{}'.", module.nv_reference)
|
||||
})?
|
||||
.into_url()
|
||||
}
|
||||
Some(Module::Node(module)) => module.specifier.clone(),
|
||||
Some(Module::Js(module)) => module.specifier.clone(),
|
||||
Some(Module::Json(module)) => module.specifier.clone(),
|
||||
Some(Module::External(module)) => {
|
||||
node::resolve_specifier_into_node_modules(&module.specifier)
|
||||
node::resolve_specifier_into_node_modules(
|
||||
&module.specifier,
|
||||
self.shared.fs.as_ref(),
|
||||
)
|
||||
}
|
||||
None => specifier.into_owned(),
|
||||
};
|
||||
|
@ -534,7 +573,7 @@ impl<TGraphContainer: ModuleGraphContainer>
|
|||
}) => {
|
||||
let transpile_result = self
|
||||
.emitter
|
||||
.emit_parsed_source(specifier, media_type, source)
|
||||
.emit_parsed_source(specifier, media_type, ModuleKind::Esm, source)
|
||||
.await?;
|
||||
|
||||
// at this point, we no longer need the parsed source in memory, so free it
|
||||
|
@ -547,11 +586,19 @@ impl<TGraphContainer: ModuleGraphContainer>
|
|||
media_type,
|
||||
}))
|
||||
}
|
||||
Some(CodeOrDeferredEmit::Cjs {
|
||||
specifier,
|
||||
media_type,
|
||||
source,
|
||||
}) => self
|
||||
.load_maybe_cjs(specifier, media_type, source)
|
||||
.await
|
||||
.map(Some),
|
||||
None => Ok(None),
|
||||
}
|
||||
}
|
||||
|
||||
fn load_prepared_module_sync(
|
||||
fn load_prepared_module_for_source_map_sync(
|
||||
&self,
|
||||
specifier: &ModuleSpecifier,
|
||||
) -> Result<Option<ModuleCodeStringSource>, AnyError> {
|
||||
|
@ -564,9 +611,12 @@ impl<TGraphContainer: ModuleGraphContainer>
|
|||
media_type,
|
||||
source,
|
||||
}) => {
|
||||
let transpile_result = self
|
||||
.emitter
|
||||
.emit_parsed_source_sync(specifier, media_type, source)?;
|
||||
let transpile_result = self.emitter.emit_parsed_source_sync(
|
||||
specifier,
|
||||
media_type,
|
||||
ModuleKind::Esm,
|
||||
source,
|
||||
)?;
|
||||
|
||||
// at this point, we no longer need the parsed source in memory, so free it
|
||||
self.parsed_source_cache.free(specifier);
|
||||
|
@ -578,6 +628,14 @@ impl<TGraphContainer: ModuleGraphContainer>
|
|||
media_type,
|
||||
}))
|
||||
}
|
||||
Some(CodeOrDeferredEmit::Cjs { .. }) => {
|
||||
self.parsed_source_cache.free(specifier);
|
||||
|
||||
// todo(dsherret): to make this work, we should probably just
|
||||
// rely on the CJS export cache. At the moment this is hard because
|
||||
// cjs export analysis is only async
|
||||
Ok(None)
|
||||
}
|
||||
None => Ok(None),
|
||||
}
|
||||
}
|
||||
|
@ -607,20 +665,40 @@ impl<TGraphContainer: ModuleGraphContainer>
|
|||
source,
|
||||
media_type,
|
||||
specifier,
|
||||
is_script,
|
||||
..
|
||||
})) => {
|
||||
// todo(dsherret): revert in https://github.com/denoland/deno/pull/26439
|
||||
if self.is_npm_main && *is_script
|
||||
|| self.shared.cjs_tracker.is_cjs_with_known_is_script(
|
||||
specifier,
|
||||
*media_type,
|
||||
*is_script,
|
||||
)?
|
||||
{
|
||||
return Ok(Some(CodeOrDeferredEmit::Cjs {
|
||||
specifier,
|
||||
media_type: *media_type,
|
||||
source,
|
||||
}));
|
||||
}
|
||||
let code: ModuleCodeString = match media_type {
|
||||
MediaType::JavaScript
|
||||
| MediaType::Unknown
|
||||
| MediaType::Cjs
|
||||
| MediaType::Mjs
|
||||
| MediaType::Json => source.clone().into(),
|
||||
MediaType::Dts | MediaType::Dcts | MediaType::Dmts => {
|
||||
Default::default()
|
||||
}
|
||||
MediaType::Cjs | MediaType::Cts => {
|
||||
return Ok(Some(CodeOrDeferredEmit::Cjs {
|
||||
specifier,
|
||||
media_type: *media_type,
|
||||
source,
|
||||
}));
|
||||
}
|
||||
MediaType::TypeScript
|
||||
| MediaType::Mts
|
||||
| MediaType::Cts
|
||||
| MediaType::Jsx
|
||||
| MediaType::Tsx => {
|
||||
return Ok(Some(CodeOrDeferredEmit::DeferredEmit {
|
||||
|
@ -629,7 +707,7 @@ impl<TGraphContainer: ModuleGraphContainer>
|
|||
source,
|
||||
}));
|
||||
}
|
||||
MediaType::TsBuildInfo | MediaType::Wasm | MediaType::SourceMap => {
|
||||
MediaType::Css | MediaType::Wasm | MediaType::SourceMap => {
|
||||
panic!("Unexpected media type {media_type} for {specifier}")
|
||||
}
|
||||
};
|
||||
|
@ -651,6 +729,48 @@ impl<TGraphContainer: ModuleGraphContainer>
|
|||
| None => Ok(None),
|
||||
}
|
||||
}
|
||||
|
||||
async fn load_maybe_cjs(
|
||||
&self,
|
||||
specifier: &ModuleSpecifier,
|
||||
media_type: MediaType,
|
||||
original_source: &Arc<str>,
|
||||
) -> Result<ModuleCodeStringSource, AnyError> {
|
||||
let js_source = if media_type.is_emittable() {
|
||||
Cow::Owned(
|
||||
self
|
||||
.emitter
|
||||
.emit_parsed_source(
|
||||
specifier,
|
||||
media_type,
|
||||
ModuleKind::Cjs,
|
||||
original_source,
|
||||
)
|
||||
.await?,
|
||||
)
|
||||
} else {
|
||||
Cow::Borrowed(original_source.as_ref())
|
||||
};
|
||||
let text = self
|
||||
.node_code_translator
|
||||
.translate_cjs_to_esm(specifier, Some(js_source))
|
||||
.await?;
|
||||
// at this point, we no longer need the parsed source in memory, so free it
|
||||
self.parsed_source_cache.free(specifier);
|
||||
Ok(ModuleCodeStringSource {
|
||||
code: match text {
|
||||
// perf: if the text is borrowed, that means it didn't make any changes
|
||||
// to the original source, so we can just provide that instead of cloning
|
||||
// the borrowed text
|
||||
Cow::Borrowed(_) => {
|
||||
ModuleSourceCode::String(original_source.clone().into())
|
||||
}
|
||||
Cow::Owned(text) => ModuleSourceCode::String(text.into()),
|
||||
},
|
||||
found_url: specifier.clone(),
|
||||
media_type,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
enum CodeOrDeferredEmit<'a> {
|
||||
|
@ -660,6 +780,11 @@ enum CodeOrDeferredEmit<'a> {
|
|||
media_type: MediaType,
|
||||
source: &'a Arc<str>,
|
||||
},
|
||||
Cjs {
|
||||
specifier: &'a ModuleSpecifier,
|
||||
media_type: MediaType,
|
||||
source: &'a Arc<str>,
|
||||
},
|
||||
}
|
||||
|
||||
// todo(dsherret): this double Rc boxing is not ideal
|
||||
|
@ -821,7 +946,10 @@ impl<TGraphContainer: ModuleGraphContainer> ModuleLoader
|
|||
"wasm" | "file" | "http" | "https" | "data" | "blob" => (),
|
||||
_ => return None,
|
||||
}
|
||||
let source = self.0.load_prepared_module_sync(&specifier).ok()??;
|
||||
let source = self
|
||||
.0
|
||||
.load_prepared_module_for_source_map_sync(&specifier)
|
||||
.ok()??;
|
||||
source_map_from_code(source.code.as_bytes())
|
||||
}
|
||||
|
||||
|
@ -900,3 +1028,79 @@ impl ModuleGraphUpdatePermit for WorkerModuleGraphUpdatePermit {
|
|||
drop(self.permit); // explicit drop for clarity
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct CliNodeRequireLoader<TGraphContainer: ModuleGraphContainer> {
|
||||
emitter: Arc<Emitter>,
|
||||
fs: Arc<dyn FileSystem>,
|
||||
graph_container: TGraphContainer,
|
||||
in_npm_pkg_checker: Arc<dyn InNpmPackageChecker>,
|
||||
npm_resolver: Arc<dyn CliNpmResolver>,
|
||||
}
|
||||
|
||||
impl<TGraphContainer: ModuleGraphContainer>
|
||||
CliNodeRequireLoader<TGraphContainer>
|
||||
{
|
||||
pub fn new(
|
||||
emitter: Arc<Emitter>,
|
||||
fs: Arc<dyn FileSystem>,
|
||||
graph_container: TGraphContainer,
|
||||
in_npm_pkg_checker: Arc<dyn InNpmPackageChecker>,
|
||||
npm_resolver: Arc<dyn CliNpmResolver>,
|
||||
) -> Self {
|
||||
Self {
|
||||
emitter,
|
||||
fs,
|
||||
graph_container,
|
||||
in_npm_pkg_checker,
|
||||
npm_resolver,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<TGraphContainer: ModuleGraphContainer> NodeRequireLoader
|
||||
for CliNodeRequireLoader<TGraphContainer>
|
||||
{
|
||||
fn ensure_read_permission<'a>(
|
||||
&self,
|
||||
permissions: &mut dyn deno_runtime::deno_node::NodePermissions,
|
||||
path: &'a Path,
|
||||
) -> Result<std::borrow::Cow<'a, Path>, AnyError> {
|
||||
if let Ok(url) = deno_path_util::url_from_file_path(path) {
|
||||
// allow reading if it's in the module graph
|
||||
if self.graph_container.graph().get(&url).is_some() {
|
||||
return Ok(std::borrow::Cow::Borrowed(path));
|
||||
}
|
||||
}
|
||||
self.npm_resolver.ensure_read_permission(permissions, path)
|
||||
}
|
||||
|
||||
fn load_text_file_lossy(&self, path: &Path) -> Result<String, AnyError> {
|
||||
// todo(dsherret): use the preloaded module from the graph if available?
|
||||
let media_type = MediaType::from_path(path);
|
||||
let text = self.fs.read_text_file_lossy_sync(path, None)?;
|
||||
if media_type.is_emittable() {
|
||||
let specifier = deno_path_util::url_from_file_path(path)?;
|
||||
if self.in_npm_pkg_checker.in_npm_package(&specifier) {
|
||||
return Err(
|
||||
NotSupportedKindInNpmError {
|
||||
media_type,
|
||||
specifier,
|
||||
}
|
||||
.into(),
|
||||
);
|
||||
}
|
||||
self.emitter.emit_parsed_source_sync(
|
||||
&specifier,
|
||||
media_type,
|
||||
// this is probably not super accurate due to require esm, but probably ok.
|
||||
// If we find this causes a lot of churn in the emit cache then we should
|
||||
// investigate how we can make this better
|
||||
ModuleKind::Cjs,
|
||||
&text.into(),
|
||||
)
|
||||
} else {
|
||||
Ok(text)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
134
cli/node.rs
134
cli/node.rs
|
@ -1,11 +1,14 @@
|
|||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::sync::Arc;
|
||||
|
||||
use deno_ast::MediaType;
|
||||
use deno_ast::ModuleSpecifier;
|
||||
use deno_core::error::AnyError;
|
||||
use deno_graph::ParsedSourceStore;
|
||||
use deno_path_util::url_from_file_path;
|
||||
use deno_path_util::url_to_file_path;
|
||||
use deno_runtime::deno_fs;
|
||||
use deno_runtime::deno_node::DenoFsNodeResolverEnv;
|
||||
use node_resolver::analyze::CjsAnalysis as ExtNodeCjsAnalysis;
|
||||
|
@ -18,8 +21,8 @@ use serde::Serialize;
|
|||
use crate::cache::CacheDBHash;
|
||||
use crate::cache::NodeAnalysisCache;
|
||||
use crate::cache::ParsedSourceCache;
|
||||
use crate::resolver::CliNodeResolver;
|
||||
use crate::util::fs::canonicalize_path_maybe_not_exists;
|
||||
use crate::resolver::CjsTracker;
|
||||
use crate::util::fs::canonicalize_path_maybe_not_exists_with_fs;
|
||||
|
||||
pub type CliNodeCodeTranslator =
|
||||
NodeCodeTranslator<CliCjsCodeAnalyzer, DenoFsNodeResolverEnv>;
|
||||
|
@ -32,14 +35,14 @@ pub type CliNodeCodeTranslator =
|
|||
/// because the node_modules folder might not exist at that time.
|
||||
pub fn resolve_specifier_into_node_modules(
|
||||
specifier: &ModuleSpecifier,
|
||||
fs: &dyn deno_fs::FileSystem,
|
||||
) -> ModuleSpecifier {
|
||||
specifier
|
||||
.to_file_path()
|
||||
url_to_file_path(specifier)
|
||||
.ok()
|
||||
// this path might not exist at the time the graph is being created
|
||||
// because the node_modules folder might not yet exist
|
||||
.and_then(|path| canonicalize_path_maybe_not_exists(&path).ok())
|
||||
.and_then(|path| ModuleSpecifier::from_file_path(path).ok())
|
||||
.and_then(|path| canonicalize_path_maybe_not_exists_with_fs(&path, fs).ok())
|
||||
.and_then(|path| url_from_file_path(&path).ok())
|
||||
.unwrap_or_else(|| specifier.clone())
|
||||
}
|
||||
|
||||
|
@ -56,23 +59,29 @@ pub enum CliCjsAnalysis {
|
|||
|
||||
pub struct CliCjsCodeAnalyzer {
|
||||
cache: NodeAnalysisCache,
|
||||
cjs_tracker: Arc<CjsTracker>,
|
||||
fs: deno_fs::FileSystemRc,
|
||||
node_resolver: Arc<CliNodeResolver>,
|
||||
parsed_source_cache: Option<Arc<ParsedSourceCache>>,
|
||||
// todo(dsherret): hack, remove in https://github.com/denoland/deno/pull/26439
|
||||
// For example, this does not properly handle if cjs analysis was already done
|
||||
// and has been cached.
|
||||
is_npm_main: bool,
|
||||
}
|
||||
|
||||
impl CliCjsCodeAnalyzer {
|
||||
pub fn new(
|
||||
cache: NodeAnalysisCache,
|
||||
cjs_tracker: Arc<CjsTracker>,
|
||||
fs: deno_fs::FileSystemRc,
|
||||
node_resolver: Arc<CliNodeResolver>,
|
||||
parsed_source_cache: Option<Arc<ParsedSourceCache>>,
|
||||
is_npm_main: bool,
|
||||
) -> Self {
|
||||
Self {
|
||||
cache,
|
||||
cjs_tracker,
|
||||
fs,
|
||||
node_resolver,
|
||||
parsed_source_cache,
|
||||
is_npm_main,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -88,7 +97,7 @@ impl CliCjsCodeAnalyzer {
|
|||
return Ok(analysis);
|
||||
}
|
||||
|
||||
let mut media_type = MediaType::from_specifier(specifier);
|
||||
let media_type = MediaType::from_specifier(specifier);
|
||||
if media_type == MediaType::Json {
|
||||
return Ok(CliCjsAnalysis::Cjs {
|
||||
exports: vec![],
|
||||
|
@ -96,62 +105,53 @@ impl CliCjsCodeAnalyzer {
|
|||
});
|
||||
}
|
||||
|
||||
if media_type == MediaType::JavaScript {
|
||||
if let Some(package_json) =
|
||||
self.node_resolver.get_closest_package_json(specifier)?
|
||||
{
|
||||
match package_json.typ.as_str() {
|
||||
"commonjs" => {
|
||||
media_type = MediaType::Cjs;
|
||||
}
|
||||
"module" => {
|
||||
media_type = MediaType::Mjs;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
let cjs_tracker = self.cjs_tracker.clone();
|
||||
let is_npm_main = self.is_npm_main;
|
||||
let is_maybe_cjs =
|
||||
cjs_tracker.is_maybe_cjs(specifier, media_type)? || is_npm_main;
|
||||
let analysis = if is_maybe_cjs {
|
||||
let maybe_parsed_source = self
|
||||
.parsed_source_cache
|
||||
.as_ref()
|
||||
.and_then(|c| c.remove_parsed_source(specifier));
|
||||
|
||||
let maybe_parsed_source = self
|
||||
.parsed_source_cache
|
||||
.as_ref()
|
||||
.and_then(|c| c.remove_parsed_source(specifier));
|
||||
|
||||
let analysis = deno_core::unsync::spawn_blocking({
|
||||
let specifier = specifier.clone();
|
||||
let source: Arc<str> = source.into();
|
||||
move || -> Result<_, deno_ast::ParseDiagnostic> {
|
||||
let parsed_source =
|
||||
maybe_parsed_source.map(Ok).unwrap_or_else(|| {
|
||||
deno_ast::parse_program(deno_ast::ParseParams {
|
||||
specifier,
|
||||
text: source,
|
||||
media_type,
|
||||
capture_tokens: true,
|
||||
scope_analysis: false,
|
||||
maybe_syntax: None,
|
||||
deno_core::unsync::spawn_blocking({
|
||||
let specifier = specifier.clone();
|
||||
let source: Arc<str> = source.into();
|
||||
move || -> Result<_, AnyError> {
|
||||
let parsed_source =
|
||||
maybe_parsed_source.map(Ok).unwrap_or_else(|| {
|
||||
deno_ast::parse_program(deno_ast::ParseParams {
|
||||
specifier,
|
||||
text: source,
|
||||
media_type,
|
||||
capture_tokens: true,
|
||||
scope_analysis: false,
|
||||
maybe_syntax: None,
|
||||
})
|
||||
})?;
|
||||
let is_script = parsed_source.compute_is_script();
|
||||
let is_cjs = cjs_tracker.is_cjs_with_known_is_script(
|
||||
parsed_source.specifier(),
|
||||
media_type,
|
||||
is_script,
|
||||
)? || is_script && is_npm_main;
|
||||
if is_cjs {
|
||||
let analysis = parsed_source.analyze_cjs();
|
||||
Ok(CliCjsAnalysis::Cjs {
|
||||
exports: analysis.exports,
|
||||
reexports: analysis.reexports,
|
||||
})
|
||||
})?;
|
||||
if parsed_source.is_script() {
|
||||
let analysis = parsed_source.analyze_cjs();
|
||||
Ok(CliCjsAnalysis::Cjs {
|
||||
exports: analysis.exports,
|
||||
reexports: analysis.reexports,
|
||||
})
|
||||
} else if media_type == MediaType::Cjs {
|
||||
// FIXME: `deno_ast` should internally handle MediaType::Cjs implying that
|
||||
// the result must never be Esm
|
||||
Ok(CliCjsAnalysis::Cjs {
|
||||
exports: vec![],
|
||||
reexports: vec![],
|
||||
})
|
||||
} else {
|
||||
Ok(CliCjsAnalysis::Esm)
|
||||
} else {
|
||||
Ok(CliCjsAnalysis::Esm)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
.await
|
||||
.unwrap()?;
|
||||
})
|
||||
.await
|
||||
.unwrap()?
|
||||
} else {
|
||||
CliCjsAnalysis::Esm
|
||||
};
|
||||
|
||||
self
|
||||
.cache
|
||||
|
@ -163,11 +163,11 @@ impl CliCjsCodeAnalyzer {
|
|||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl CjsCodeAnalyzer for CliCjsCodeAnalyzer {
|
||||
async fn analyze_cjs(
|
||||
async fn analyze_cjs<'a>(
|
||||
&self,
|
||||
specifier: &ModuleSpecifier,
|
||||
source: Option<String>,
|
||||
) -> Result<ExtNodeCjsAnalysis, AnyError> {
|
||||
source: Option<Cow<'a, str>>,
|
||||
) -> Result<ExtNodeCjsAnalysis<'a>, AnyError> {
|
||||
let source = match source {
|
||||
Some(source) => source,
|
||||
None => {
|
||||
|
@ -175,7 +175,7 @@ impl CjsCodeAnalyzer for CliCjsCodeAnalyzer {
|
|||
if let Ok(source_from_file) =
|
||||
self.fs.read_text_file_lossy_async(path, None).await
|
||||
{
|
||||
source_from_file
|
||||
Cow::Owned(source_from_file)
|
||||
} else {
|
||||
return Ok(ExtNodeCjsAnalysis::Cjs(CjsAnalysisExports {
|
||||
exports: vec![],
|
||||
|
|
|
@ -10,8 +10,8 @@ use deno_core::serde_json;
|
|||
use deno_core::url::Url;
|
||||
use deno_resolver::npm::ByonmNpmResolver;
|
||||
use deno_resolver::npm::ByonmNpmResolverCreateOptions;
|
||||
use deno_runtime::deno_node::DenoFsNodeResolverEnv;
|
||||
use deno_runtime::deno_node::NodePermissions;
|
||||
use deno_runtime::deno_node::NodeRequireResolver;
|
||||
use deno_runtime::ops::process::NpmProcessStateProvider;
|
||||
use deno_semver::package::PackageReq;
|
||||
use node_resolver::NpmResolver;
|
||||
|
@ -25,30 +25,14 @@ use super::InnerCliNpmResolverRef;
|
|||
use super::ResolvePkgFolderFromDenoReqError;
|
||||
|
||||
pub type CliByonmNpmResolverCreateOptions =
|
||||
ByonmNpmResolverCreateOptions<CliDenoResolverFs>;
|
||||
pub type CliByonmNpmResolver = ByonmNpmResolver<CliDenoResolverFs>;
|
||||
ByonmNpmResolverCreateOptions<CliDenoResolverFs, DenoFsNodeResolverEnv>;
|
||||
pub type CliByonmNpmResolver =
|
||||
ByonmNpmResolver<CliDenoResolverFs, DenoFsNodeResolverEnv>;
|
||||
|
||||
// todo(dsherret): the services hanging off `CliNpmResolver` doesn't seem ideal. We should probably decouple.
|
||||
#[derive(Debug)]
|
||||
struct CliByonmWrapper(Arc<CliByonmNpmResolver>);
|
||||
|
||||
impl NodeRequireResolver for CliByonmWrapper {
|
||||
fn ensure_read_permission<'a>(
|
||||
&self,
|
||||
permissions: &mut dyn NodePermissions,
|
||||
path: &'a Path,
|
||||
) -> Result<Cow<'a, Path>, AnyError> {
|
||||
if !path
|
||||
.components()
|
||||
.any(|c| c.as_os_str().to_ascii_lowercase() == "node_modules")
|
||||
{
|
||||
permissions.check_read_path(path)
|
||||
} else {
|
||||
Ok(Cow::Borrowed(path))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl NpmProcessStateProvider for CliByonmWrapper {
|
||||
fn get_npm_process_state(&self) -> String {
|
||||
serde_json::to_string(&NpmProcessState {
|
||||
|
@ -67,10 +51,6 @@ impl CliNpmResolver for CliByonmNpmResolver {
|
|||
self
|
||||
}
|
||||
|
||||
fn into_require_resolver(self: Arc<Self>) -> Arc<dyn NodeRequireResolver> {
|
||||
Arc::new(CliByonmWrapper(self))
|
||||
}
|
||||
|
||||
fn into_process_state_provider(
|
||||
self: Arc<Self>,
|
||||
) -> Arc<dyn NpmProcessStateProvider> {
|
||||
|
@ -100,6 +80,21 @@ impl CliNpmResolver for CliByonmNpmResolver {
|
|||
.map_err(ResolvePkgFolderFromDenoReqError::Byonm)
|
||||
}
|
||||
|
||||
fn ensure_read_permission<'a>(
|
||||
&self,
|
||||
permissions: &mut dyn NodePermissions,
|
||||
path: &'a Path,
|
||||
) -> Result<Cow<'a, Path>, AnyError> {
|
||||
if !path
|
||||
.components()
|
||||
.any(|c| c.as_os_str().to_ascii_lowercase() == "node_modules")
|
||||
{
|
||||
permissions.check_read_path(path).map_err(Into::into)
|
||||
} else {
|
||||
Ok(Cow::Borrowed(path))
|
||||
}
|
||||
}
|
||||
|
||||
fn check_state_hash(&self) -> Option<u64> {
|
||||
// it is very difficult to determine the check state hash for byonm
|
||||
// so we just return None to signify check caching is not supported
|
||||
|
|
12
cli/npm/managed/cache/mod.rs
vendored
12
cli/npm/managed/cache/mod.rs
vendored
|
@ -36,7 +36,7 @@ pub use tarball::TarballCache;
|
|||
/// Stores a single copy of npm packages in a cache.
|
||||
#[derive(Debug)]
|
||||
pub struct NpmCache {
|
||||
cache_dir: NpmCacheDir,
|
||||
cache_dir: Arc<NpmCacheDir>,
|
||||
cache_setting: CacheSetting,
|
||||
npmrc: Arc<ResolvedNpmRc>,
|
||||
/// ensures a package is only downloaded once per run
|
||||
|
@ -45,7 +45,7 @@ pub struct NpmCache {
|
|||
|
||||
impl NpmCache {
|
||||
pub fn new(
|
||||
cache_dir: NpmCacheDir,
|
||||
cache_dir: Arc<NpmCacheDir>,
|
||||
cache_setting: CacheSetting,
|
||||
npmrc: Arc<ResolvedNpmRc>,
|
||||
) -> Self {
|
||||
|
@ -61,6 +61,10 @@ impl NpmCache {
|
|||
&self.cache_setting
|
||||
}
|
||||
|
||||
pub fn root_dir_path(&self) -> &Path {
|
||||
self.cache_dir.root_dir()
|
||||
}
|
||||
|
||||
pub fn root_dir_url(&self) -> &Url {
|
||||
self.cache_dir.root_dir_url()
|
||||
}
|
||||
|
@ -152,10 +156,6 @@ impl NpmCache {
|
|||
self.cache_dir.package_name_folder(name, registry_url)
|
||||
}
|
||||
|
||||
pub fn root_folder(&self) -> PathBuf {
|
||||
self.cache_dir.root_dir().to_owned()
|
||||
}
|
||||
|
||||
pub fn resolve_package_folder_id_from_specifier(
|
||||
&self,
|
||||
specifier: &ModuleSpecifier,
|
||||
|
|
|
@ -12,6 +12,7 @@ use deno_cache_dir::npm::NpmCacheDir;
|
|||
use deno_core::anyhow::Context;
|
||||
use deno_core::error::AnyError;
|
||||
use deno_core::serde_json;
|
||||
use deno_core::url::Url;
|
||||
use deno_npm::npm_rc::ResolvedNpmRc;
|
||||
use deno_npm::registry::NpmPackageInfo;
|
||||
use deno_npm::registry::NpmRegistryApi;
|
||||
|
@ -24,12 +25,12 @@ use deno_npm::NpmSystemInfo;
|
|||
use deno_runtime::colors;
|
||||
use deno_runtime::deno_fs::FileSystem;
|
||||
use deno_runtime::deno_node::NodePermissions;
|
||||
use deno_runtime::deno_node::NodeRequireResolver;
|
||||
use deno_runtime::ops::process::NpmProcessStateProvider;
|
||||
use deno_semver::package::PackageNv;
|
||||
use deno_semver::package::PackageReq;
|
||||
use node_resolver::errors::PackageFolderResolveError;
|
||||
use node_resolver::errors::PackageFolderResolveIoError;
|
||||
use node_resolver::InNpmPackageChecker;
|
||||
use node_resolver::NpmResolver;
|
||||
use resolution::AddPkgReqsResult;
|
||||
|
||||
|
@ -38,7 +39,7 @@ use crate::args::LifecycleScriptsConfig;
|
|||
use crate::args::NpmInstallDepsProvider;
|
||||
use crate::args::NpmProcessState;
|
||||
use crate::args::NpmProcessStateKind;
|
||||
use crate::cache::DenoCacheEnvFsAdapter;
|
||||
use crate::args::PackageJsonDepValueParseWithLocationError;
|
||||
use crate::cache::FastInsecureHasher;
|
||||
use crate::http_util::HttpClientProvider;
|
||||
use crate::util::fs::canonicalize_path_maybe_not_exists_with_fs;
|
||||
|
@ -65,12 +66,12 @@ pub enum CliNpmResolverManagedSnapshotOption {
|
|||
Specified(Option<ValidSerializedNpmResolutionSnapshot>),
|
||||
}
|
||||
|
||||
pub struct CliNpmResolverManagedCreateOptions {
|
||||
pub struct CliManagedNpmResolverCreateOptions {
|
||||
pub snapshot: CliNpmResolverManagedSnapshotOption,
|
||||
pub maybe_lockfile: Option<Arc<CliLockfile>>,
|
||||
pub fs: Arc<dyn deno_runtime::deno_fs::FileSystem>,
|
||||
pub http_client_provider: Arc<crate::http_util::HttpClientProvider>,
|
||||
pub npm_global_cache_dir: PathBuf,
|
||||
pub npm_cache_dir: Arc<NpmCacheDir>,
|
||||
pub cache_setting: crate::args::CacheSetting,
|
||||
pub text_only_progress_bar: crate::util::progress_bar::ProgressBar,
|
||||
pub maybe_node_modules_path: Option<PathBuf>,
|
||||
|
@ -81,7 +82,7 @@ pub struct CliNpmResolverManagedCreateOptions {
|
|||
}
|
||||
|
||||
pub async fn create_managed_npm_resolver_for_lsp(
|
||||
options: CliNpmResolverManagedCreateOptions,
|
||||
options: CliManagedNpmResolverCreateOptions,
|
||||
) -> Arc<dyn CliNpmResolver> {
|
||||
let npm_cache = create_cache(&options);
|
||||
let npm_api = create_api(&options, npm_cache.clone());
|
||||
|
@ -114,7 +115,7 @@ pub async fn create_managed_npm_resolver_for_lsp(
|
|||
}
|
||||
|
||||
pub async fn create_managed_npm_resolver(
|
||||
options: CliNpmResolverManagedCreateOptions,
|
||||
options: CliManagedNpmResolverCreateOptions,
|
||||
) -> Result<Arc<dyn CliNpmResolver>, AnyError> {
|
||||
let npm_cache = create_cache(&options);
|
||||
let npm_api = create_api(&options, npm_cache.clone());
|
||||
|
@ -188,20 +189,16 @@ fn create_inner(
|
|||
))
|
||||
}
|
||||
|
||||
fn create_cache(options: &CliNpmResolverManagedCreateOptions) -> Arc<NpmCache> {
|
||||
fn create_cache(options: &CliManagedNpmResolverCreateOptions) -> Arc<NpmCache> {
|
||||
Arc::new(NpmCache::new(
|
||||
NpmCacheDir::new(
|
||||
&DenoCacheEnvFsAdapter(options.fs.as_ref()),
|
||||
options.npm_global_cache_dir.clone(),
|
||||
options.npmrc.get_all_known_registries_urls(),
|
||||
),
|
||||
options.npm_cache_dir.clone(),
|
||||
options.cache_setting.clone(),
|
||||
options.npmrc.clone(),
|
||||
))
|
||||
}
|
||||
|
||||
fn create_api(
|
||||
options: &CliNpmResolverManagedCreateOptions,
|
||||
options: &CliManagedNpmResolverCreateOptions,
|
||||
npm_cache: Arc<NpmCache>,
|
||||
) -> Arc<CliNpmRegistryApi> {
|
||||
Arc::new(CliNpmRegistryApi::new(
|
||||
|
@ -258,6 +255,35 @@ async fn snapshot_from_lockfile(
|
|||
Ok(snapshot)
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct ManagedInNpmPackageChecker {
|
||||
root_dir: Url,
|
||||
}
|
||||
|
||||
impl InNpmPackageChecker for ManagedInNpmPackageChecker {
|
||||
fn in_npm_package(&self, specifier: &Url) -> bool {
|
||||
specifier.as_ref().starts_with(self.root_dir.as_str())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CliManagedInNpmPkgCheckerCreateOptions<'a> {
|
||||
pub root_cache_dir_url: &'a Url,
|
||||
pub maybe_node_modules_path: Option<&'a Path>,
|
||||
}
|
||||
|
||||
pub fn create_managed_in_npm_pkg_checker(
|
||||
options: CliManagedInNpmPkgCheckerCreateOptions,
|
||||
) -> Arc<dyn InNpmPackageChecker> {
|
||||
let root_dir = match options.maybe_node_modules_path {
|
||||
Some(node_modules_folder) => {
|
||||
deno_path_util::url_from_directory_path(node_modules_folder).unwrap()
|
||||
}
|
||||
None => options.root_cache_dir_url.clone(),
|
||||
};
|
||||
debug_assert!(root_dir.as_str().ends_with('/'));
|
||||
Arc::new(ManagedInNpmPackageChecker { root_dir })
|
||||
}
|
||||
|
||||
/// An npm resolver where the resolution is managed by Deno rather than
|
||||
/// the user bringing their own node_modules (BYONM) on the file system.
|
||||
pub struct ManagedCliNpmResolver {
|
||||
|
@ -480,19 +506,24 @@ impl ManagedCliNpmResolver {
|
|||
self.resolution.resolve_pkg_id_from_pkg_req(req)
|
||||
}
|
||||
|
||||
pub fn ensure_no_pkg_json_dep_errors(&self) -> Result<(), AnyError> {
|
||||
pub fn ensure_no_pkg_json_dep_errors(
|
||||
&self,
|
||||
) -> Result<(), Box<PackageJsonDepValueParseWithLocationError>> {
|
||||
for err in self.npm_install_deps_provider.pkg_json_dep_errors() {
|
||||
match err {
|
||||
match &err.source {
|
||||
deno_package_json::PackageJsonDepValueParseError::VersionReq(_) => {
|
||||
return Err(
|
||||
AnyError::from(err.clone())
|
||||
.context("Failed to install from package.json"),
|
||||
);
|
||||
return Err(Box::new(err.clone()));
|
||||
}
|
||||
deno_package_json::PackageJsonDepValueParseError::Unsupported {
|
||||
..
|
||||
} => {
|
||||
log::warn!("{} {} in package.json", colors::yellow("Warning"), err)
|
||||
// only warn for this one
|
||||
log::warn!(
|
||||
"{} {}\n at {}",
|
||||
colors::yellow("Warning"),
|
||||
err.source,
|
||||
err.location,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -549,8 +580,16 @@ impl ManagedCliNpmResolver {
|
|||
.map_err(|err| err.into())
|
||||
}
|
||||
|
||||
pub fn global_cache_root_folder(&self) -> PathBuf {
|
||||
self.npm_cache.root_folder()
|
||||
pub fn maybe_node_modules_path(&self) -> Option<&Path> {
|
||||
self.fs_resolver.node_modules_path()
|
||||
}
|
||||
|
||||
pub fn global_cache_root_path(&self) -> &Path {
|
||||
self.npm_cache.root_dir_path()
|
||||
}
|
||||
|
||||
pub fn global_cache_root_url(&self) -> &Url {
|
||||
self.npm_cache.root_dir_url()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -585,22 +624,6 @@ impl NpmResolver for ManagedCliNpmResolver {
|
|||
log::debug!("Resolved {} from {} to {}", name, referrer, path.display());
|
||||
Ok(path)
|
||||
}
|
||||
|
||||
fn in_npm_package(&self, specifier: &ModuleSpecifier) -> bool {
|
||||
let root_dir_url = self.fs_resolver.root_dir_url();
|
||||
debug_assert!(root_dir_url.as_str().ends_with('/'));
|
||||
specifier.as_ref().starts_with(root_dir_url.as_str())
|
||||
}
|
||||
}
|
||||
|
||||
impl NodeRequireResolver for ManagedCliNpmResolver {
|
||||
fn ensure_read_permission<'a>(
|
||||
&self,
|
||||
permissions: &mut dyn NodePermissions,
|
||||
path: &'a Path,
|
||||
) -> Result<Cow<'a, Path>, AnyError> {
|
||||
self.fs_resolver.ensure_read_permission(permissions, path)
|
||||
}
|
||||
}
|
||||
|
||||
impl NpmProcessStateProvider for ManagedCliNpmResolver {
|
||||
|
@ -617,10 +640,6 @@ impl CliNpmResolver for ManagedCliNpmResolver {
|
|||
self
|
||||
}
|
||||
|
||||
fn into_require_resolver(self: Arc<Self>) -> Arc<dyn NodeRequireResolver> {
|
||||
self
|
||||
}
|
||||
|
||||
fn into_process_state_provider(
|
||||
self: Arc<Self>,
|
||||
) -> Arc<dyn NpmProcessStateProvider> {
|
||||
|
@ -681,6 +700,14 @@ impl CliNpmResolver for ManagedCliNpmResolver {
|
|||
.map_err(ResolvePkgFolderFromDenoReqError::Managed)
|
||||
}
|
||||
|
||||
fn ensure_read_permission<'a>(
|
||||
&self,
|
||||
permissions: &mut dyn NodePermissions,
|
||||
path: &'a Path,
|
||||
) -> Result<Cow<'a, Path>, AnyError> {
|
||||
self.fs_resolver.ensure_read_permission(permissions, path)
|
||||
}
|
||||
|
||||
fn check_state_hash(&self) -> Option<u64> {
|
||||
// We could go further and check all the individual
|
||||
// npm packages, but that's probably overkill.
|
||||
|
|
|
@ -17,7 +17,6 @@ use deno_core::anyhow::Context;
|
|||
use deno_core::error::AnyError;
|
||||
use deno_core::futures;
|
||||
use deno_core::futures::StreamExt;
|
||||
use deno_core::url::Url;
|
||||
use deno_npm::NpmPackageCacheFolderId;
|
||||
use deno_npm::NpmPackageId;
|
||||
use deno_npm::NpmResolutionPackage;
|
||||
|
@ -30,9 +29,6 @@ use crate::npm::managed::cache::TarballCache;
|
|||
/// Part of the resolution that interacts with the file system.
|
||||
#[async_trait(?Send)]
|
||||
pub trait NpmPackageFsResolver: Send + Sync {
|
||||
/// Specifier for the root directory.
|
||||
fn root_dir_url(&self) -> &Url;
|
||||
|
||||
/// The local node_modules folder if it is applicable to the implementation.
|
||||
fn node_modules_path(&self) -> Option<&Path>;
|
||||
|
||||
|
@ -137,7 +133,7 @@ impl RegistryReadPermissionChecker {
|
|||
}
|
||||
}
|
||||
|
||||
permissions.check_read_path(path)
|
||||
permissions.check_read_path(path).map_err(Into::into)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,6 @@ use crate::colors;
|
|||
use async_trait::async_trait;
|
||||
use deno_ast::ModuleSpecifier;
|
||||
use deno_core::error::AnyError;
|
||||
use deno_core::url::Url;
|
||||
use deno_npm::NpmPackageCacheFolderId;
|
||||
use deno_npm::NpmPackageId;
|
||||
use deno_npm::NpmResolutionPackage;
|
||||
|
@ -56,7 +55,7 @@ impl GlobalNpmPackageResolver {
|
|||
Self {
|
||||
registry_read_permission_checker: RegistryReadPermissionChecker::new(
|
||||
fs,
|
||||
cache.root_folder(),
|
||||
cache.root_dir_path().to_path_buf(),
|
||||
),
|
||||
cache,
|
||||
tarball_cache,
|
||||
|
@ -69,10 +68,6 @@ impl GlobalNpmPackageResolver {
|
|||
|
||||
#[async_trait(?Send)]
|
||||
impl NpmPackageFsResolver for GlobalNpmPackageResolver {
|
||||
fn root_dir_url(&self) -> &Url {
|
||||
self.cache.root_dir_url()
|
||||
}
|
||||
|
||||
fn node_modules_path(&self) -> Option<&Path> {
|
||||
None
|
||||
}
|
||||
|
|
|
@ -155,10 +155,6 @@ impl LocalNpmPackageResolver {
|
|||
|
||||
#[async_trait(?Send)]
|
||||
impl NpmPackageFsResolver for LocalNpmPackageResolver {
|
||||
fn root_dir_url(&self) -> &Url {
|
||||
&self.root_node_modules_url
|
||||
}
|
||||
|
||||
fn node_modules_path(&self) -> Option<&Path> {
|
||||
Some(self.root_node_modules_path.as_ref())
|
||||
}
|
||||
|
@ -1039,12 +1035,18 @@ fn junction_or_symlink_dir(
|
|||
if symlink_err.kind() == std::io::ErrorKind::PermissionDenied =>
|
||||
{
|
||||
USE_JUNCTIONS.store(true, std::sync::atomic::Ordering::Relaxed);
|
||||
junction::create(old_path, new_path).map_err(Into::into)
|
||||
junction::create(old_path, new_path)
|
||||
.context("Failed creating junction in node_modules folder")
|
||||
}
|
||||
Err(symlink_err) => {
|
||||
log::warn!(
|
||||
"{} Unexpected error symlinking node_modules: {symlink_err}",
|
||||
colors::yellow("Warning")
|
||||
);
|
||||
USE_JUNCTIONS.store(true, std::sync::atomic::Ordering::Relaxed);
|
||||
junction::create(old_path, new_path)
|
||||
.context("Failed creating junction in node_modules folder")
|
||||
}
|
||||
Err(symlink_err) => Err(
|
||||
AnyError::from(symlink_err)
|
||||
.context("Failed creating symlink in node_modules folder"),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ mod byonm;
|
|||
mod common;
|
||||
mod managed;
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
|
@ -15,13 +16,16 @@ use deno_core::error::AnyError;
|
|||
use deno_core::serde_json;
|
||||
use deno_npm::npm_rc::ResolvedNpmRc;
|
||||
use deno_npm::registry::NpmPackageInfo;
|
||||
use deno_resolver::npm::ByonmInNpmPackageChecker;
|
||||
use deno_resolver::npm::ByonmNpmResolver;
|
||||
use deno_resolver::npm::ByonmResolvePkgFolderFromDenoReqError;
|
||||
use deno_runtime::deno_node::NodeRequireResolver;
|
||||
use deno_runtime::deno_node::NodePermissions;
|
||||
use deno_runtime::ops::process::NpmProcessStateProvider;
|
||||
use deno_semver::package::PackageNv;
|
||||
use deno_semver::package::PackageReq;
|
||||
use managed::cache::registry_info::get_package_url;
|
||||
use managed::create_managed_in_npm_pkg_checker;
|
||||
use node_resolver::InNpmPackageChecker;
|
||||
use node_resolver::NpmResolver;
|
||||
use thiserror::Error;
|
||||
|
||||
|
@ -29,7 +33,8 @@ use crate::file_fetcher::FileFetcher;
|
|||
|
||||
pub use self::byonm::CliByonmNpmResolver;
|
||||
pub use self::byonm::CliByonmNpmResolverCreateOptions;
|
||||
pub use self::managed::CliNpmResolverManagedCreateOptions;
|
||||
pub use self::managed::CliManagedInNpmPkgCheckerCreateOptions;
|
||||
pub use self::managed::CliManagedNpmResolverCreateOptions;
|
||||
pub use self::managed::CliNpmResolverManagedSnapshotOption;
|
||||
pub use self::managed::ManagedCliNpmResolver;
|
||||
|
||||
|
@ -42,7 +47,7 @@ pub enum ResolvePkgFolderFromDenoReqError {
|
|||
}
|
||||
|
||||
pub enum CliNpmResolverCreateOptions {
|
||||
Managed(CliNpmResolverManagedCreateOptions),
|
||||
Managed(CliManagedNpmResolverCreateOptions),
|
||||
Byonm(CliByonmNpmResolverCreateOptions),
|
||||
}
|
||||
|
||||
|
@ -68,6 +73,22 @@ pub async fn create_cli_npm_resolver(
|
|||
}
|
||||
}
|
||||
|
||||
pub enum CreateInNpmPkgCheckerOptions<'a> {
|
||||
Managed(CliManagedInNpmPkgCheckerCreateOptions<'a>),
|
||||
Byonm,
|
||||
}
|
||||
|
||||
pub fn create_in_npm_pkg_checker(
|
||||
options: CreateInNpmPkgCheckerOptions,
|
||||
) -> Arc<dyn InNpmPackageChecker> {
|
||||
match options {
|
||||
CreateInNpmPkgCheckerOptions::Managed(options) => {
|
||||
create_managed_in_npm_pkg_checker(options)
|
||||
}
|
||||
CreateInNpmPkgCheckerOptions::Byonm => Arc::new(ByonmInNpmPackageChecker),
|
||||
}
|
||||
}
|
||||
|
||||
pub enum InnerCliNpmResolverRef<'a> {
|
||||
Managed(&'a ManagedCliNpmResolver),
|
||||
#[allow(dead_code)]
|
||||
|
@ -76,7 +97,6 @@ pub enum InnerCliNpmResolverRef<'a> {
|
|||
|
||||
pub trait CliNpmResolver: NpmResolver {
|
||||
fn into_npm_resolver(self: Arc<Self>) -> Arc<dyn NpmResolver>;
|
||||
fn into_require_resolver(self: Arc<Self>) -> Arc<dyn NodeRequireResolver>;
|
||||
fn into_process_state_provider(
|
||||
self: Arc<Self>,
|
||||
) -> Arc<dyn NpmProcessStateProvider>;
|
||||
|
@ -107,6 +127,12 @@ pub trait CliNpmResolver: NpmResolver {
|
|||
referrer: &ModuleSpecifier,
|
||||
) -> Result<PathBuf, ResolvePkgFolderFromDenoReqError>;
|
||||
|
||||
fn ensure_read_permission<'a>(
|
||||
&self,
|
||||
permissions: &mut dyn NodePermissions,
|
||||
path: &'a Path,
|
||||
) -> Result<Cow<'a, Path>, AnyError>;
|
||||
|
||||
/// Returns a hash returning the state of the npm resolver
|
||||
/// or `None` if the state currently can't be determined.
|
||||
fn check_state_hash(&self) -> Option<u64>;
|
||||
|
@ -189,3 +215,15 @@ impl NpmFetchResolver {
|
|||
info
|
||||
}
|
||||
}
|
||||
|
||||
pub const NPM_CONFIG_USER_AGENT_ENV_VAR: &str = "npm_config_user_agent";
|
||||
|
||||
pub fn get_npm_config_user_agent() -> String {
|
||||
format!(
|
||||
"deno/{} npm/? deno/{} {} {}",
|
||||
env!("CARGO_PKG_VERSION"),
|
||||
env!("CARGO_PKG_VERSION"),
|
||||
std::env::consts::OS,
|
||||
std::env::consts::ARCH
|
||||
)
|
||||
}
|
||||
|
|
354
cli/resolver.rs
354
cli/resolver.rs
|
@ -4,6 +4,7 @@ use async_trait::async_trait;
|
|||
use dashmap::DashMap;
|
||||
use dashmap::DashSet;
|
||||
use deno_ast::MediaType;
|
||||
use deno_ast::ModuleKind;
|
||||
use deno_config::workspace::MappedResolution;
|
||||
use deno_config::workspace::MappedResolutionDiagnostic;
|
||||
use deno_config::workspace::MappedResolutionError;
|
||||
|
@ -11,6 +12,7 @@ use deno_config::workspace::WorkspaceResolver;
|
|||
use deno_core::anyhow::anyhow;
|
||||
use deno_core::anyhow::Context;
|
||||
use deno_core::error::AnyError;
|
||||
use deno_core::url::Url;
|
||||
use deno_core::ModuleSourceCode;
|
||||
use deno_core::ModuleSpecifier;
|
||||
use deno_graph::source::ResolutionMode;
|
||||
|
@ -29,6 +31,7 @@ use deno_runtime::deno_fs;
|
|||
use deno_runtime::deno_fs::FileSystem;
|
||||
use deno_runtime::deno_node::is_builtin_node_module;
|
||||
use deno_runtime::deno_node::NodeResolver;
|
||||
use deno_runtime::deno_node::PackageJsonResolver;
|
||||
use deno_semver::npm::NpmPackageReqReference;
|
||||
use deno_semver::package::PackageReq;
|
||||
use node_resolver::errors::ClosestPkgJsonError;
|
||||
|
@ -38,21 +41,22 @@ use node_resolver::errors::PackageFolderResolveErrorKind;
|
|||
use node_resolver::errors::PackageFolderResolveIoError;
|
||||
use node_resolver::errors::PackageNotFoundError;
|
||||
use node_resolver::errors::PackageResolveErrorKind;
|
||||
use node_resolver::errors::UrlToNodeResolutionError;
|
||||
use node_resolver::errors::PackageSubpathResolveError;
|
||||
use node_resolver::InNpmPackageChecker;
|
||||
use node_resolver::NodeModuleKind;
|
||||
use node_resolver::NodeResolution;
|
||||
use node_resolver::NodeResolutionMode;
|
||||
use node_resolver::PackageJson;
|
||||
use std::borrow::Cow;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
use thiserror::Error;
|
||||
|
||||
use crate::args::JsxImportSourceConfig;
|
||||
use crate::args::DENO_DISABLE_PEDANTIC_NODE_WARNINGS;
|
||||
use crate::node::CliNodeCodeTranslator;
|
||||
use crate::npm::CliNpmResolver;
|
||||
use crate::npm::InnerCliNpmResolverRef;
|
||||
use crate::util::path::specifier_has_extension;
|
||||
use crate::util::sync::AtomicFlag;
|
||||
use crate::util::text_encoding::from_utf8_lossy_owned;
|
||||
|
||||
|
@ -104,36 +108,32 @@ impl deno_resolver::fs::DenoResolverFs for CliDenoResolverFs {
|
|||
|
||||
#[derive(Debug)]
|
||||
pub struct CliNodeResolver {
|
||||
cjs_resolutions: Arc<CjsResolutionStore>,
|
||||
cjs_tracker: Arc<CjsTracker>,
|
||||
fs: Arc<dyn deno_fs::FileSystem>,
|
||||
in_npm_pkg_checker: Arc<dyn InNpmPackageChecker>,
|
||||
node_resolver: Arc<NodeResolver>,
|
||||
npm_resolver: Arc<dyn CliNpmResolver>,
|
||||
}
|
||||
|
||||
impl CliNodeResolver {
|
||||
pub fn new(
|
||||
cjs_resolutions: Arc<CjsResolutionStore>,
|
||||
cjs_tracker: Arc<CjsTracker>,
|
||||
fs: Arc<dyn deno_fs::FileSystem>,
|
||||
in_npm_pkg_checker: Arc<dyn InNpmPackageChecker>,
|
||||
node_resolver: Arc<NodeResolver>,
|
||||
npm_resolver: Arc<dyn CliNpmResolver>,
|
||||
) -> Self {
|
||||
Self {
|
||||
cjs_resolutions,
|
||||
cjs_tracker,
|
||||
fs,
|
||||
in_npm_pkg_checker,
|
||||
node_resolver,
|
||||
npm_resolver,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn in_npm_package(&self, specifier: &ModuleSpecifier) -> bool {
|
||||
self.npm_resolver.in_npm_package(specifier)
|
||||
}
|
||||
|
||||
pub fn get_closest_package_json(
|
||||
&self,
|
||||
referrer: &ModuleSpecifier,
|
||||
) -> Result<Option<Arc<PackageJson>>, ClosestPkgJsonError> {
|
||||
self.node_resolver.get_closest_package_json(referrer)
|
||||
self.in_npm_pkg_checker.in_npm_package(specifier)
|
||||
}
|
||||
|
||||
pub fn resolve_if_for_npm_pkg(
|
||||
|
@ -153,8 +153,7 @@ impl CliNodeResolver {
|
|||
| NodeResolveErrorKind::UnsupportedEsmUrlScheme(_)
|
||||
| NodeResolveErrorKind::DataUrlReferrer(_)
|
||||
| NodeResolveErrorKind::TypesNotFound(_)
|
||||
| NodeResolveErrorKind::FinalizeResolution(_)
|
||||
| NodeResolveErrorKind::UrlToNodeResolution(_) => Err(err.into()),
|
||||
| NodeResolveErrorKind::FinalizeResolution(_) => Err(err.into()),
|
||||
NodeResolveErrorKind::PackageResolve(err) => {
|
||||
let err = err.into_kind();
|
||||
match err {
|
||||
|
@ -216,7 +215,11 @@ impl CliNodeResolver {
|
|||
referrer: &ModuleSpecifier,
|
||||
mode: NodeResolutionMode,
|
||||
) -> Result<NodeResolution, NodeResolveError> {
|
||||
let referrer_kind = if self.cjs_resolutions.is_known_cjs(referrer) {
|
||||
let referrer_kind = if self
|
||||
.cjs_tracker
|
||||
.is_maybe_cjs(referrer, MediaType::from_specifier(referrer))
|
||||
.map_err(|err| NodeResolveErrorKind::PackageResolve(err.into()))?
|
||||
{
|
||||
NodeModuleKind::Cjs
|
||||
} else {
|
||||
NodeModuleKind::Esm
|
||||
|
@ -226,7 +229,7 @@ impl CliNodeResolver {
|
|||
self
|
||||
.node_resolver
|
||||
.resolve(specifier, referrer, referrer_kind, mode)?;
|
||||
Ok(self.handle_node_resolution(res))
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
pub fn resolve_req_reference(
|
||||
|
@ -234,7 +237,7 @@ impl CliNodeResolver {
|
|||
req_ref: &NpmPackageReqReference,
|
||||
referrer: &ModuleSpecifier,
|
||||
mode: NodeResolutionMode,
|
||||
) -> Result<NodeResolution, AnyError> {
|
||||
) -> Result<ModuleSpecifier, AnyError> {
|
||||
self.resolve_req_with_sub_path(
|
||||
req_ref.req(),
|
||||
req_ref.sub_path(),
|
||||
|
@ -249,7 +252,7 @@ impl CliNodeResolver {
|
|||
sub_path: Option<&str>,
|
||||
referrer: &ModuleSpecifier,
|
||||
mode: NodeResolutionMode,
|
||||
) -> Result<NodeResolution, AnyError> {
|
||||
) -> Result<ModuleSpecifier, AnyError> {
|
||||
let package_folder = self
|
||||
.npm_resolver
|
||||
.resolve_pkg_folder_from_deno_module_req(req, referrer)?;
|
||||
|
@ -260,7 +263,7 @@ impl CliNodeResolver {
|
|||
mode,
|
||||
);
|
||||
match resolution_result {
|
||||
Ok(resolution) => Ok(resolution),
|
||||
Ok(url) => Ok(url),
|
||||
Err(err) => {
|
||||
if self.npm_resolver.as_byonm().is_some() {
|
||||
let package_json_path = package_folder.join("package.json");
|
||||
|
@ -271,7 +274,7 @@ impl CliNodeResolver {
|
|||
));
|
||||
}
|
||||
}
|
||||
Err(err)
|
||||
Err(err.into())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -282,16 +285,13 @@ impl CliNodeResolver {
|
|||
sub_path: Option<&str>,
|
||||
maybe_referrer: Option<&ModuleSpecifier>,
|
||||
mode: NodeResolutionMode,
|
||||
) -> Result<NodeResolution, AnyError> {
|
||||
let res = self
|
||||
.node_resolver
|
||||
.resolve_package_subpath_from_deno_module(
|
||||
package_folder,
|
||||
sub_path,
|
||||
maybe_referrer,
|
||||
mode,
|
||||
)?;
|
||||
Ok(self.handle_node_resolution(res))
|
||||
) -> Result<ModuleSpecifier, PackageSubpathResolveError> {
|
||||
self.node_resolver.resolve_package_subpath_from_deno_module(
|
||||
package_folder,
|
||||
sub_path,
|
||||
maybe_referrer,
|
||||
mode,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn handle_if_in_node_modules(
|
||||
|
@ -306,71 +306,45 @@ impl CliNodeResolver {
|
|||
// so canoncalize then check if it's in the node_modules directory.
|
||||
// If so, check if we need to store this specifier as being a CJS
|
||||
// resolution.
|
||||
let specifier =
|
||||
crate::node::resolve_specifier_into_node_modules(specifier);
|
||||
if self.in_npm_package(&specifier) {
|
||||
let resolution =
|
||||
self.node_resolver.url_to_node_resolution(specifier)?;
|
||||
let resolution = self.handle_node_resolution(resolution);
|
||||
return Ok(Some(resolution.into_url()));
|
||||
}
|
||||
let specifier = crate::node::resolve_specifier_into_node_modules(
|
||||
specifier,
|
||||
self.fs.as_ref(),
|
||||
);
|
||||
return Ok(Some(specifier));
|
||||
}
|
||||
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
pub fn url_to_node_resolution(
|
||||
&self,
|
||||
specifier: ModuleSpecifier,
|
||||
) -> Result<NodeResolution, UrlToNodeResolutionError> {
|
||||
self.node_resolver.url_to_node_resolution(specifier)
|
||||
}
|
||||
|
||||
fn handle_node_resolution(
|
||||
&self,
|
||||
resolution: NodeResolution,
|
||||
) -> NodeResolution {
|
||||
if let NodeResolution::CommonJs(specifier) = &resolution {
|
||||
// remember that this was a common js resolution
|
||||
self.mark_cjs_resolution(specifier.clone());
|
||||
}
|
||||
resolution
|
||||
}
|
||||
|
||||
pub fn mark_cjs_resolution(&self, specifier: ModuleSpecifier) {
|
||||
self.cjs_resolutions.insert(specifier);
|
||||
}
|
||||
}
|
||||
|
||||
// todo(dsherret): move to module_loader.rs
|
||||
#[derive(Debug, Error)]
|
||||
#[error("{media_type} files are not supported in npm packages: {specifier}")]
|
||||
pub struct NotSupportedKindInNpmError {
|
||||
pub media_type: MediaType,
|
||||
pub specifier: Url,
|
||||
}
|
||||
|
||||
// todo(dsherret): move to module_loader.rs (it seems to be here due to use in standalone)
|
||||
#[derive(Clone)]
|
||||
pub struct NpmModuleLoader {
|
||||
cjs_resolutions: Arc<CjsResolutionStore>,
|
||||
node_code_translator: Arc<CliNodeCodeTranslator>,
|
||||
cjs_tracker: Arc<CjsTracker>,
|
||||
fs: Arc<dyn deno_fs::FileSystem>,
|
||||
node_resolver: Arc<CliNodeResolver>,
|
||||
node_code_translator: Arc<CliNodeCodeTranslator>,
|
||||
}
|
||||
|
||||
impl NpmModuleLoader {
|
||||
pub fn new(
|
||||
cjs_resolutions: Arc<CjsResolutionStore>,
|
||||
node_code_translator: Arc<CliNodeCodeTranslator>,
|
||||
cjs_tracker: Arc<CjsTracker>,
|
||||
fs: Arc<dyn deno_fs::FileSystem>,
|
||||
node_resolver: Arc<CliNodeResolver>,
|
||||
node_code_translator: Arc<CliNodeCodeTranslator>,
|
||||
) -> Self {
|
||||
Self {
|
||||
cjs_resolutions,
|
||||
cjs_tracker,
|
||||
node_code_translator,
|
||||
fs,
|
||||
node_resolver,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn if_in_npm_package(&self, specifier: &ModuleSpecifier) -> bool {
|
||||
self.node_resolver.in_npm_package(specifier)
|
||||
|| self.cjs_resolutions.is_known_cjs(specifier)
|
||||
}
|
||||
|
||||
pub async fn load(
|
||||
&self,
|
||||
specifier: &ModuleSpecifier,
|
||||
|
@ -413,20 +387,30 @@ impl NpmModuleLoader {
|
|||
}
|
||||
})?;
|
||||
|
||||
let code = if self.cjs_resolutions.is_known_cjs(specifier) {
|
||||
let media_type = MediaType::from_specifier(specifier);
|
||||
if media_type.is_emittable() {
|
||||
return Err(AnyError::from(NotSupportedKindInNpmError {
|
||||
media_type,
|
||||
specifier: specifier.clone(),
|
||||
}));
|
||||
}
|
||||
|
||||
let code = if self.cjs_tracker.is_maybe_cjs(specifier, media_type)? {
|
||||
// translate cjs to esm if it's cjs and inject node globals
|
||||
let code = from_utf8_lossy_owned(code);
|
||||
ModuleSourceCode::String(
|
||||
self
|
||||
.node_code_translator
|
||||
.translate_cjs_to_esm(specifier, Some(code))
|
||||
.translate_cjs_to_esm(specifier, Some(Cow::Owned(code)))
|
||||
.await?
|
||||
.into_owned()
|
||||
.into(),
|
||||
)
|
||||
} else {
|
||||
// esm and json code is untouched
|
||||
ModuleSourceCode::Bytes(code.into_boxed_slice().into())
|
||||
};
|
||||
|
||||
Ok(ModuleCodeStringSource {
|
||||
code,
|
||||
found_url: specifier.clone(),
|
||||
|
@ -435,21 +419,165 @@ impl NpmModuleLoader {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct CjsTrackerOptions {
|
||||
pub unstable_detect_cjs: bool,
|
||||
}
|
||||
|
||||
/// Keeps track of what module specifiers were resolved as CJS.
|
||||
#[derive(Debug, Default)]
|
||||
pub struct CjsResolutionStore(DashSet<ModuleSpecifier>);
|
||||
///
|
||||
/// Modules that are `.js` or `.ts` are only known to be CJS or
|
||||
/// ESM after they're loaded based on their contents. So these files
|
||||
/// will be "maybe CJS" until they're loaded.
|
||||
#[derive(Debug)]
|
||||
pub struct CjsTracker {
|
||||
in_npm_pkg_checker: Arc<dyn InNpmPackageChecker>,
|
||||
pkg_json_resolver: Arc<PackageJsonResolver>,
|
||||
unstable_detect_cjs: bool,
|
||||
known: DashMap<ModuleSpecifier, ModuleKind>,
|
||||
}
|
||||
|
||||
impl CjsResolutionStore {
|
||||
pub fn is_known_cjs(&self, specifier: &ModuleSpecifier) -> bool {
|
||||
if specifier.scheme() != "file" {
|
||||
return false;
|
||||
impl CjsTracker {
|
||||
pub fn new(
|
||||
in_npm_pkg_checker: Arc<dyn InNpmPackageChecker>,
|
||||
pkg_json_resolver: Arc<PackageJsonResolver>,
|
||||
options: CjsTrackerOptions,
|
||||
) -> Self {
|
||||
Self {
|
||||
in_npm_pkg_checker,
|
||||
pkg_json_resolver,
|
||||
unstable_detect_cjs: options.unstable_detect_cjs,
|
||||
known: Default::default(),
|
||||
}
|
||||
|
||||
specifier_has_extension(specifier, "cjs") || self.0.contains(specifier)
|
||||
}
|
||||
|
||||
pub fn insert(&self, specifier: ModuleSpecifier) {
|
||||
self.0.insert(specifier);
|
||||
/// Checks whether the file might be treated as CJS, but it's not for sure
|
||||
/// yet because the source hasn't been loaded to see whether it contains
|
||||
/// imports or exports.
|
||||
pub fn is_maybe_cjs(
|
||||
&self,
|
||||
specifier: &ModuleSpecifier,
|
||||
media_type: MediaType,
|
||||
) -> Result<bool, ClosestPkgJsonError> {
|
||||
self.treat_as_cjs_with_is_script(specifier, media_type, None)
|
||||
}
|
||||
|
||||
/// Gets whether the file is CJS. If true, this is for sure
|
||||
/// cjs because `is_script` is provided.
|
||||
///
|
||||
/// `is_script` should be `true` when the contents of the file at the
|
||||
/// provided specifier are known to be a script and not an ES module.
|
||||
pub fn is_cjs_with_known_is_script(
|
||||
&self,
|
||||
specifier: &ModuleSpecifier,
|
||||
media_type: MediaType,
|
||||
is_script: bool,
|
||||
) -> Result<bool, ClosestPkgJsonError> {
|
||||
self.treat_as_cjs_with_is_script(specifier, media_type, Some(is_script))
|
||||
}
|
||||
|
||||
fn treat_as_cjs_with_is_script(
|
||||
&self,
|
||||
specifier: &ModuleSpecifier,
|
||||
media_type: MediaType,
|
||||
is_script: Option<bool>,
|
||||
) -> Result<bool, ClosestPkgJsonError> {
|
||||
let kind = match self
|
||||
.get_known_kind_with_is_script(specifier, media_type, is_script)
|
||||
{
|
||||
Some(kind) => kind,
|
||||
None => self.check_based_on_pkg_json(specifier)?,
|
||||
};
|
||||
Ok(kind.is_cjs())
|
||||
}
|
||||
|
||||
pub fn get_known_kind(
|
||||
&self,
|
||||
specifier: &ModuleSpecifier,
|
||||
media_type: MediaType,
|
||||
) -> Option<ModuleKind> {
|
||||
self.get_known_kind_with_is_script(specifier, media_type, None)
|
||||
}
|
||||
|
||||
fn get_known_kind_with_is_script(
|
||||
&self,
|
||||
specifier: &ModuleSpecifier,
|
||||
media_type: MediaType,
|
||||
is_script: Option<bool>,
|
||||
) -> Option<ModuleKind> {
|
||||
if specifier.scheme() != "file" {
|
||||
return Some(ModuleKind::Esm);
|
||||
}
|
||||
|
||||
match media_type {
|
||||
MediaType::Mts | MediaType::Mjs | MediaType::Dmts => Some(ModuleKind::Esm),
|
||||
MediaType::Cjs | MediaType::Cts | MediaType::Dcts => Some(ModuleKind::Cjs),
|
||||
MediaType::Dts => {
|
||||
// dts files are always determined based on the package.json because
|
||||
// they contain imports/exports even when considered CJS
|
||||
if let Some(value) = self.known.get(specifier).map(|v| *v) {
|
||||
Some(value)
|
||||
} else {
|
||||
let value = self.check_based_on_pkg_json(specifier).ok();
|
||||
if let Some(value) = value {
|
||||
self.known.insert(specifier.clone(), value);
|
||||
}
|
||||
Some(value.unwrap_or(ModuleKind::Esm))
|
||||
}
|
||||
}
|
||||
MediaType::Wasm |
|
||||
MediaType::Json => Some(ModuleKind::Esm),
|
||||
MediaType::JavaScript
|
||||
| MediaType::Jsx
|
||||
| MediaType::TypeScript
|
||||
| MediaType::Tsx
|
||||
// treat these as unknown
|
||||
| MediaType::Css
|
||||
| MediaType::SourceMap
|
||||
| MediaType::Unknown => {
|
||||
if let Some(value) = self.known.get(specifier).map(|v| *v) {
|
||||
if value.is_cjs() && is_script == Some(false) {
|
||||
// we now know this is actually esm
|
||||
self.known.insert(specifier.clone(), ModuleKind::Esm);
|
||||
Some(ModuleKind::Esm)
|
||||
} else {
|
||||
Some(value)
|
||||
}
|
||||
} else if is_script == Some(false) {
|
||||
// we know this is esm
|
||||
self.known.insert(specifier.clone(), ModuleKind::Esm);
|
||||
Some(ModuleKind::Esm)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_based_on_pkg_json(
|
||||
&self,
|
||||
specifier: &ModuleSpecifier,
|
||||
) -> Result<ModuleKind, ClosestPkgJsonError> {
|
||||
if self.in_npm_pkg_checker.in_npm_package(specifier) {
|
||||
if let Some(pkg_json) =
|
||||
self.pkg_json_resolver.get_closest_package_json(specifier)?
|
||||
{
|
||||
let is_file_location_cjs = pkg_json.typ != "module";
|
||||
Ok(ModuleKind::from_is_cjs(is_file_location_cjs))
|
||||
} else {
|
||||
Ok(ModuleKind::Cjs)
|
||||
}
|
||||
} else if self.unstable_detect_cjs {
|
||||
if let Some(pkg_json) =
|
||||
self.pkg_json_resolver.get_closest_package_json(specifier)?
|
||||
{
|
||||
let is_cjs_type = pkg_json.typ == "commonjs";
|
||||
Ok(ModuleKind::from_is_cjs(is_cjs_type))
|
||||
} else {
|
||||
Ok(ModuleKind::Esm)
|
||||
}
|
||||
} else {
|
||||
Ok(ModuleKind::Esm)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -633,8 +761,7 @@ impl Resolver for CliGraphResolver {
|
|||
Some(referrer),
|
||||
to_node_mode(mode),
|
||||
)
|
||||
.map_err(ResolveError::Other)
|
||||
.map(|res| res.into_url()),
|
||||
.map_err(|e| ResolveError::Other(e.into())),
|
||||
MappedResolution::PackageJson {
|
||||
dep_result,
|
||||
alias,
|
||||
|
@ -665,19 +792,17 @@ impl Resolver for CliGraphResolver {
|
|||
)
|
||||
.map_err(|e| ResolveError::Other(e.into()))
|
||||
.and_then(|pkg_folder| {
|
||||
Ok(
|
||||
self
|
||||
.node_resolver
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.resolve_package_sub_path_from_deno_module(
|
||||
pkg_folder,
|
||||
sub_path.as_deref(),
|
||||
Some(referrer),
|
||||
to_node_mode(mode),
|
||||
)?
|
||||
.into_url(),
|
||||
)
|
||||
self
|
||||
.node_resolver
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.resolve_package_sub_path_from_deno_module(
|
||||
pkg_folder,
|
||||
sub_path.as_deref(),
|
||||
Some(referrer),
|
||||
to_node_mode(mode),
|
||||
)
|
||||
.map_err(|e| ResolveError::Other(e.into()))
|
||||
}),
|
||||
})
|
||||
}
|
||||
|
@ -717,23 +842,20 @@ impl Resolver for CliGraphResolver {
|
|||
npm_req_ref.req(),
|
||||
)
|
||||
{
|
||||
return Ok(
|
||||
node_resolver
|
||||
.resolve_package_sub_path_from_deno_module(
|
||||
pkg_folder,
|
||||
npm_req_ref.sub_path(),
|
||||
Some(referrer),
|
||||
to_node_mode(mode),
|
||||
)?
|
||||
.into_url(),
|
||||
);
|
||||
return node_resolver
|
||||
.resolve_package_sub_path_from_deno_module(
|
||||
pkg_folder,
|
||||
npm_req_ref.sub_path(),
|
||||
Some(referrer),
|
||||
to_node_mode(mode),
|
||||
)
|
||||
.map_err(|e| ResolveError::Other(e.into()));
|
||||
}
|
||||
|
||||
// do npm resolution for byonm
|
||||
if is_byonm {
|
||||
return node_resolver
|
||||
.resolve_req_reference(&npm_req_ref, referrer, to_node_mode(mode))
|
||||
.map(|res| res.into_url())
|
||||
.map_err(|err| err.into());
|
||||
}
|
||||
}
|
||||
|
@ -751,9 +873,7 @@ impl Resolver for CliGraphResolver {
|
|||
.map_err(ResolveError::Other)?;
|
||||
if let Some(res) = maybe_resolution {
|
||||
match res {
|
||||
NodeResolution::Esm(url) | NodeResolution::CommonJs(url) => {
|
||||
return Ok(url)
|
||||
}
|
||||
NodeResolution::Module(url) => return Ok(url),
|
||||
NodeResolution::BuiltIn(_) => {
|
||||
// don't resolve bare specifiers for built-in modules via node resolution
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ use std::process::Command;
|
|||
use std::sync::Arc;
|
||||
|
||||
use deno_ast::MediaType;
|
||||
use deno_ast::ModuleKind;
|
||||
use deno_ast::ModuleSpecifier;
|
||||
use deno_config::workspace::PackageJsonDepResolution;
|
||||
use deno_config::workspace::ResolverWorkspaceJsrPackage;
|
||||
|
@ -67,6 +68,7 @@ use crate::file_fetcher::FileFetcher;
|
|||
use crate::http_util::HttpClientProvider;
|
||||
use crate::npm::CliNpmResolver;
|
||||
use crate::npm::InnerCliNpmResolverRef;
|
||||
use crate::resolver::CjsTracker;
|
||||
use crate::shared::ReleaseChannel;
|
||||
use crate::standalone::virtual_fs::VfsEntry;
|
||||
use crate::util::archive;
|
||||
|
@ -257,6 +259,10 @@ impl StandaloneModules {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn has_file(&self, path: &Path) -> bool {
|
||||
self.vfs.file_entry(path).is_ok()
|
||||
}
|
||||
|
||||
pub fn read<'a>(
|
||||
&'a self,
|
||||
specifier: &'a ModuleSpecifier,
|
||||
|
@ -353,6 +359,7 @@ pub fn extract_standalone(
|
|||
}
|
||||
|
||||
pub struct DenoCompileBinaryWriter<'a> {
|
||||
cjs_tracker: &'a CjsTracker,
|
||||
deno_dir: &'a DenoDir,
|
||||
emitter: &'a Emitter,
|
||||
file_fetcher: &'a FileFetcher,
|
||||
|
@ -365,6 +372,7 @@ pub struct DenoCompileBinaryWriter<'a> {
|
|||
impl<'a> DenoCompileBinaryWriter<'a> {
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn new(
|
||||
cjs_tracker: &'a CjsTracker,
|
||||
deno_dir: &'a DenoDir,
|
||||
emitter: &'a Emitter,
|
||||
file_fetcher: &'a FileFetcher,
|
||||
|
@ -374,6 +382,7 @@ impl<'a> DenoCompileBinaryWriter<'a> {
|
|||
npm_system_info: NpmSystemInfo,
|
||||
) -> Self {
|
||||
Self {
|
||||
cjs_tracker,
|
||||
deno_dir,
|
||||
emitter,
|
||||
file_fetcher,
|
||||
|
@ -599,19 +608,21 @@ impl<'a> DenoCompileBinaryWriter<'a> {
|
|||
}
|
||||
let (maybe_source, media_type) = match module {
|
||||
deno_graph::Module::Js(m) => {
|
||||
// todo(https://github.com/denoland/deno_media_type/pull/12): use is_emittable()
|
||||
let is_emittable = matches!(
|
||||
m.media_type,
|
||||
MediaType::TypeScript
|
||||
| MediaType::Mts
|
||||
| MediaType::Cts
|
||||
| MediaType::Jsx
|
||||
| MediaType::Tsx
|
||||
);
|
||||
let source = if is_emittable {
|
||||
let source = if m.media_type.is_emittable() {
|
||||
let is_cjs = self.cjs_tracker.is_cjs_with_known_is_script(
|
||||
&m.specifier,
|
||||
m.media_type,
|
||||
m.is_script,
|
||||
)?;
|
||||
let module_kind = ModuleKind::from_is_cjs(is_cjs);
|
||||
let source = self
|
||||
.emitter
|
||||
.emit_parsed_source(&m.specifier, m.media_type, &m.source)
|
||||
.emit_parsed_source(
|
||||
&m.specifier,
|
||||
m.media_type,
|
||||
module_kind,
|
||||
&m.source,
|
||||
)
|
||||
.await?;
|
||||
source.into_bytes()
|
||||
} else {
|
||||
|
@ -745,8 +756,9 @@ impl<'a> DenoCompileBinaryWriter<'a> {
|
|||
} else {
|
||||
// DO NOT include the user's registry url as it may contain credentials,
|
||||
// but also don't make this dependent on the registry url
|
||||
let global_cache_root_path = npm_resolver.global_cache_root_folder();
|
||||
let mut builder = VfsBuilder::new(global_cache_root_path)?;
|
||||
let global_cache_root_path = npm_resolver.global_cache_root_path();
|
||||
let mut builder =
|
||||
VfsBuilder::new(global_cache_root_path.to_path_buf())?;
|
||||
let mut packages =
|
||||
npm_resolver.all_system_packages(&self.npm_system_info);
|
||||
packages.sort_by(|a, b| a.id.cmp(&b.id)); // determinism
|
||||
|
|
|
@ -19,6 +19,7 @@ use deno_core::error::type_error;
|
|||
use deno_core::error::AnyError;
|
||||
use deno_core::futures::FutureExt;
|
||||
use deno_core::v8_set_flags;
|
||||
use deno_core::FastString;
|
||||
use deno_core::FeatureChecker;
|
||||
use deno_core::ModuleLoader;
|
||||
use deno_core::ModuleSourceCode;
|
||||
|
@ -30,7 +31,9 @@ use deno_npm::npm_rc::ResolvedNpmRc;
|
|||
use deno_package_json::PackageJsonDepValue;
|
||||
use deno_runtime::deno_fs;
|
||||
use deno_runtime::deno_node::create_host_defined_options;
|
||||
use deno_runtime::deno_node::NodeRequireLoader;
|
||||
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;
|
||||
|
@ -43,6 +46,7 @@ use deno_semver::npm::NpmPackageReqReference;
|
|||
use import_map::parse_from_json;
|
||||
use node_resolver::analyze::NodeCodeTranslator;
|
||||
use node_resolver::NodeResolutionMode;
|
||||
use serialization::DenoCompileModuleSource;
|
||||
use std::borrow::Cow;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
|
@ -61,12 +65,18 @@ use crate::cache::NodeAnalysisCache;
|
|||
use crate::cache::RealDenoCacheEnv;
|
||||
use crate::http_util::HttpClientProvider;
|
||||
use crate::node::CliCjsCodeAnalyzer;
|
||||
use crate::node::CliNodeCodeTranslator;
|
||||
use crate::npm::create_cli_npm_resolver;
|
||||
use crate::npm::create_in_npm_pkg_checker;
|
||||
use crate::npm::CliByonmNpmResolverCreateOptions;
|
||||
use crate::npm::CliManagedInNpmPkgCheckerCreateOptions;
|
||||
use crate::npm::CliManagedNpmResolverCreateOptions;
|
||||
use crate::npm::CliNpmResolver;
|
||||
use crate::npm::CliNpmResolverCreateOptions;
|
||||
use crate::npm::CliNpmResolverManagedCreateOptions;
|
||||
use crate::npm::CliNpmResolverManagedSnapshotOption;
|
||||
use crate::resolver::CjsResolutionStore;
|
||||
use crate::npm::CreateInNpmPkgCheckerOptions;
|
||||
use crate::resolver::CjsTracker;
|
||||
use crate::resolver::CjsTrackerOptions;
|
||||
use crate::resolver::CliDenoResolverFs;
|
||||
use crate::resolver::CliNodeResolver;
|
||||
use crate::resolver::NpmModuleLoader;
|
||||
|
@ -75,7 +85,7 @@ use crate::util::progress_bar::ProgressBarStyle;
|
|||
use crate::util::v8::construct_v8_flags;
|
||||
use crate::worker::CliMainWorkerFactory;
|
||||
use crate::worker::CliMainWorkerOptions;
|
||||
use crate::worker::ModuleLoaderAndSourceMapGetter;
|
||||
use crate::worker::CreateModuleLoaderResult;
|
||||
use crate::worker::ModuleLoaderFactory;
|
||||
|
||||
pub mod binary;
|
||||
|
@ -91,10 +101,14 @@ use self::binary::Metadata;
|
|||
use self::file_system::DenoCompileFileSystem;
|
||||
|
||||
struct SharedModuleLoaderState {
|
||||
cjs_tracker: Arc<CjsTracker>,
|
||||
fs: Arc<dyn deno_fs::FileSystem>,
|
||||
modules: StandaloneModules,
|
||||
workspace_resolver: WorkspaceResolver,
|
||||
node_code_translator: Arc<CliNodeCodeTranslator>,
|
||||
node_resolver: Arc<CliNodeResolver>,
|
||||
npm_module_loader: Arc<NpmModuleLoader>,
|
||||
npm_resolver: Arc<dyn CliNpmResolver>,
|
||||
workspace_resolver: WorkspaceResolver,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
|
@ -102,6 +116,12 @@ struct EmbeddedModuleLoader {
|
|||
shared: Arc<SharedModuleLoaderState>,
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for EmbeddedModuleLoader {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("EmbeddedModuleLoader").finish()
|
||||
}
|
||||
}
|
||||
|
||||
pub const MODULE_NOT_FOUND: &str = "Module not found";
|
||||
pub const UNSUPPORTED_SCHEME: &str = "Unsupported scheme";
|
||||
|
||||
|
@ -159,8 +179,7 @@ impl ModuleLoader for EmbeddedModuleLoader {
|
|||
sub_path.as_deref(),
|
||||
Some(&referrer),
|
||||
NodeResolutionMode::Execution,
|
||||
)?
|
||||
.into_url(),
|
||||
)?,
|
||||
),
|
||||
Ok(MappedResolution::PackageJson {
|
||||
dep_result,
|
||||
|
@ -168,16 +187,14 @@ impl ModuleLoader for EmbeddedModuleLoader {
|
|||
alias,
|
||||
..
|
||||
}) => match dep_result.as_ref().map_err(|e| AnyError::from(e.clone()))? {
|
||||
PackageJsonDepValue::Req(req) => self
|
||||
.shared
|
||||
.node_resolver
|
||||
.resolve_req_with_sub_path(
|
||||
PackageJsonDepValue::Req(req) => {
|
||||
self.shared.node_resolver.resolve_req_with_sub_path(
|
||||
req,
|
||||
sub_path.as_deref(),
|
||||
&referrer,
|
||||
NodeResolutionMode::Execution,
|
||||
)
|
||||
.map(|res| res.into_url()),
|
||||
}
|
||||
PackageJsonDepValue::Workspace(version_req) => {
|
||||
let pkg_folder = self
|
||||
.shared
|
||||
|
@ -195,8 +212,7 @@ impl ModuleLoader for EmbeddedModuleLoader {
|
|||
sub_path.as_deref(),
|
||||
Some(&referrer),
|
||||
NodeResolutionMode::Execution,
|
||||
)?
|
||||
.into_url(),
|
||||
)?,
|
||||
)
|
||||
}
|
||||
},
|
||||
|
@ -205,15 +221,11 @@ impl ModuleLoader for EmbeddedModuleLoader {
|
|||
if let Ok(reference) =
|
||||
NpmPackageReqReference::from_specifier(&specifier)
|
||||
{
|
||||
return self
|
||||
.shared
|
||||
.node_resolver
|
||||
.resolve_req_reference(
|
||||
&reference,
|
||||
&referrer,
|
||||
NodeResolutionMode::Execution,
|
||||
)
|
||||
.map(|res| res.into_url());
|
||||
return self.shared.node_resolver.resolve_req_reference(
|
||||
&reference,
|
||||
&referrer,
|
||||
NodeResolutionMode::Execution,
|
||||
);
|
||||
}
|
||||
|
||||
if specifier.scheme() == "jsr" {
|
||||
|
@ -317,17 +329,72 @@ impl ModuleLoader for EmbeddedModuleLoader {
|
|||
|
||||
match self.shared.modules.read(original_specifier) {
|
||||
Ok(Some(module)) => {
|
||||
let media_type = module.media_type;
|
||||
let (module_specifier, module_type, module_source) =
|
||||
module.into_for_v8();
|
||||
deno_core::ModuleLoadResponse::Sync(Ok(
|
||||
deno_core::ModuleSource::new_with_redirect(
|
||||
module_type,
|
||||
module_source,
|
||||
original_specifier,
|
||||
module_specifier,
|
||||
None,
|
||||
),
|
||||
))
|
||||
module.into_parts();
|
||||
let is_maybe_cjs = match self
|
||||
.shared
|
||||
.cjs_tracker
|
||||
.is_maybe_cjs(original_specifier, media_type)
|
||||
{
|
||||
Ok(is_maybe_cjs) => is_maybe_cjs,
|
||||
Err(err) => {
|
||||
return deno_core::ModuleLoadResponse::Sync(Err(type_error(
|
||||
format!("{:?}", err),
|
||||
)));
|
||||
}
|
||||
};
|
||||
if is_maybe_cjs {
|
||||
let original_specifier = original_specifier.clone();
|
||||
let module_specifier = module_specifier.clone();
|
||||
let shared = self.shared.clone();
|
||||
deno_core::ModuleLoadResponse::Async(
|
||||
async move {
|
||||
let source = match module_source {
|
||||
DenoCompileModuleSource::String(string) => {
|
||||
Cow::Borrowed(string)
|
||||
}
|
||||
DenoCompileModuleSource::Bytes(module_code_bytes) => {
|
||||
match module_code_bytes {
|
||||
Cow::Owned(bytes) => Cow::Owned(
|
||||
crate::util::text_encoding::from_utf8_lossy_owned(bytes),
|
||||
),
|
||||
Cow::Borrowed(bytes) => String::from_utf8_lossy(bytes),
|
||||
}
|
||||
}
|
||||
};
|
||||
let source = shared
|
||||
.node_code_translator
|
||||
.translate_cjs_to_esm(&module_specifier, Some(source))
|
||||
.await?;
|
||||
let module_source = match source {
|
||||
Cow::Owned(source) => ModuleSourceCode::String(source.into()),
|
||||
Cow::Borrowed(source) => {
|
||||
ModuleSourceCode::String(FastString::from_static(source))
|
||||
}
|
||||
};
|
||||
Ok(deno_core::ModuleSource::new_with_redirect(
|
||||
module_type,
|
||||
module_source,
|
||||
&original_specifier,
|
||||
&module_specifier,
|
||||
None,
|
||||
))
|
||||
}
|
||||
.boxed_local(),
|
||||
)
|
||||
} else {
|
||||
let module_source = module_source.into_for_v8();
|
||||
deno_core::ModuleLoadResponse::Sync(Ok(
|
||||
deno_core::ModuleSource::new_with_redirect(
|
||||
module_type,
|
||||
module_source,
|
||||
original_specifier,
|
||||
module_specifier,
|
||||
None,
|
||||
),
|
||||
))
|
||||
}
|
||||
}
|
||||
Ok(None) => deno_core::ModuleLoadResponse::Sync(Err(type_error(
|
||||
format!("{MODULE_NOT_FOUND}: {}", original_specifier),
|
||||
|
@ -339,32 +406,61 @@ impl ModuleLoader for EmbeddedModuleLoader {
|
|||
}
|
||||
}
|
||||
|
||||
impl NodeRequireLoader for EmbeddedModuleLoader {
|
||||
fn ensure_read_permission<'a>(
|
||||
&self,
|
||||
permissions: &mut dyn deno_runtime::deno_node::NodePermissions,
|
||||
path: &'a std::path::Path,
|
||||
) -> Result<Cow<'a, std::path::Path>, AnyError> {
|
||||
if self.shared.modules.has_file(path) {
|
||||
// allow reading if the file is in the snapshot
|
||||
return Ok(Cow::Borrowed(path));
|
||||
}
|
||||
|
||||
self
|
||||
.shared
|
||||
.npm_resolver
|
||||
.ensure_read_permission(permissions, path)
|
||||
}
|
||||
|
||||
fn load_text_file_lossy(
|
||||
&self,
|
||||
path: &std::path::Path,
|
||||
) -> Result<String, AnyError> {
|
||||
Ok(self.shared.fs.read_text_file_lossy_sync(path, None)?)
|
||||
}
|
||||
}
|
||||
|
||||
struct StandaloneModuleLoaderFactory {
|
||||
shared: Arc<SharedModuleLoaderState>,
|
||||
}
|
||||
|
||||
impl StandaloneModuleLoaderFactory {
|
||||
pub fn create_result(&self) -> CreateModuleLoaderResult {
|
||||
let loader = Rc::new(EmbeddedModuleLoader {
|
||||
shared: self.shared.clone(),
|
||||
});
|
||||
CreateModuleLoaderResult {
|
||||
module_loader: loader.clone(),
|
||||
node_require_loader: loader,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ModuleLoaderFactory for StandaloneModuleLoaderFactory {
|
||||
fn create_for_main(
|
||||
&self,
|
||||
_root_permissions: PermissionsContainer,
|
||||
) -> ModuleLoaderAndSourceMapGetter {
|
||||
ModuleLoaderAndSourceMapGetter {
|
||||
module_loader: Rc::new(EmbeddedModuleLoader {
|
||||
shared: self.shared.clone(),
|
||||
}),
|
||||
}
|
||||
) -> CreateModuleLoaderResult {
|
||||
self.create_result()
|
||||
}
|
||||
|
||||
fn create_for_worker(
|
||||
&self,
|
||||
_parent_permissions: PermissionsContainer,
|
||||
_permissions: PermissionsContainer,
|
||||
) -> ModuleLoaderAndSourceMapGetter {
|
||||
ModuleLoaderAndSourceMapGetter {
|
||||
module_loader: Rc::new(EmbeddedModuleLoader {
|
||||
shared: self.shared.clone(),
|
||||
}),
|
||||
}
|
||||
) -> CreateModuleLoaderResult {
|
||||
self.create_result()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -410,106 +506,155 @@ pub async fn run(data: StandaloneData) -> Result<i32, AnyError> {
|
|||
let main_module = root_dir_url.join(&metadata.entrypoint_key).unwrap();
|
||||
let npm_global_cache_dir = root_path.join(".deno_compile_node_modules");
|
||||
let cache_setting = CacheSetting::Only;
|
||||
let npm_resolver = match metadata.node_modules {
|
||||
let pkg_json_resolver = Arc::new(PackageJsonResolver::new(
|
||||
deno_runtime::deno_node::DenoFsNodeResolverEnv::new(fs.clone()),
|
||||
));
|
||||
let (in_npm_pkg_checker, npm_resolver) = match metadata.node_modules {
|
||||
Some(binary::NodeModules::Managed { node_modules_dir }) => {
|
||||
// create an npmrc that uses the fake npm_registry_url to resolve packages
|
||||
let npmrc = Arc::new(ResolvedNpmRc {
|
||||
default_config: deno_npm::npm_rc::RegistryConfigWithUrl {
|
||||
registry_url: npm_registry_url.clone(),
|
||||
config: Default::default(),
|
||||
},
|
||||
scopes: Default::default(),
|
||||
registry_configs: Default::default(),
|
||||
});
|
||||
let npm_cache_dir = Arc::new(NpmCacheDir::new(
|
||||
&DenoCacheEnvFsAdapter(fs.as_ref()),
|
||||
npm_global_cache_dir,
|
||||
npmrc.get_all_known_registries_urls(),
|
||||
));
|
||||
let snapshot = npm_snapshot.unwrap();
|
||||
let maybe_node_modules_path = node_modules_dir
|
||||
.map(|node_modules_dir| root_path.join(node_modules_dir));
|
||||
create_cli_npm_resolver(CliNpmResolverCreateOptions::Managed(
|
||||
CliNpmResolverManagedCreateOptions {
|
||||
snapshot: CliNpmResolverManagedSnapshotOption::Specified(Some(
|
||||
snapshot,
|
||||
)),
|
||||
maybe_lockfile: None,
|
||||
fs: fs.clone(),
|
||||
http_client_provider: http_client_provider.clone(),
|
||||
npm_global_cache_dir,
|
||||
cache_setting,
|
||||
text_only_progress_bar: progress_bar,
|
||||
maybe_node_modules_path,
|
||||
npm_system_info: Default::default(),
|
||||
npm_install_deps_provider: Arc::new(
|
||||
// this is only used for installing packages, which isn't necessary with deno compile
|
||||
NpmInstallDepsProvider::empty(),
|
||||
),
|
||||
// create an npmrc that uses the fake npm_registry_url to resolve packages
|
||||
npmrc: Arc::new(ResolvedNpmRc {
|
||||
default_config: deno_npm::npm_rc::RegistryConfigWithUrl {
|
||||
registry_url: npm_registry_url.clone(),
|
||||
config: Default::default(),
|
||||
},
|
||||
scopes: Default::default(),
|
||||
registry_configs: Default::default(),
|
||||
}),
|
||||
lifecycle_scripts: Default::default(),
|
||||
},
|
||||
))
|
||||
.await?
|
||||
let in_npm_pkg_checker =
|
||||
create_in_npm_pkg_checker(CreateInNpmPkgCheckerOptions::Managed(
|
||||
CliManagedInNpmPkgCheckerCreateOptions {
|
||||
root_cache_dir_url: npm_cache_dir.root_dir_url(),
|
||||
maybe_node_modules_path: maybe_node_modules_path.as_deref(),
|
||||
},
|
||||
));
|
||||
let npm_resolver =
|
||||
create_cli_npm_resolver(CliNpmResolverCreateOptions::Managed(
|
||||
CliManagedNpmResolverCreateOptions {
|
||||
snapshot: CliNpmResolverManagedSnapshotOption::Specified(Some(
|
||||
snapshot,
|
||||
)),
|
||||
maybe_lockfile: None,
|
||||
fs: fs.clone(),
|
||||
http_client_provider: http_client_provider.clone(),
|
||||
npm_cache_dir,
|
||||
cache_setting,
|
||||
text_only_progress_bar: progress_bar,
|
||||
maybe_node_modules_path,
|
||||
npm_system_info: Default::default(),
|
||||
npm_install_deps_provider: Arc::new(
|
||||
// this is only used for installing packages, which isn't necessary with deno compile
|
||||
NpmInstallDepsProvider::empty(),
|
||||
),
|
||||
npmrc,
|
||||
lifecycle_scripts: Default::default(),
|
||||
},
|
||||
))
|
||||
.await?;
|
||||
(in_npm_pkg_checker, npm_resolver)
|
||||
}
|
||||
Some(binary::NodeModules::Byonm {
|
||||
root_node_modules_dir,
|
||||
}) => {
|
||||
let root_node_modules_dir =
|
||||
root_node_modules_dir.map(|p| vfs.root().join(p));
|
||||
create_cli_npm_resolver(CliNpmResolverCreateOptions::Byonm(
|
||||
CliByonmNpmResolverCreateOptions {
|
||||
let in_npm_pkg_checker =
|
||||
create_in_npm_pkg_checker(CreateInNpmPkgCheckerOptions::Byonm);
|
||||
let npm_resolver = create_cli_npm_resolver(
|
||||
CliNpmResolverCreateOptions::Byonm(CliByonmNpmResolverCreateOptions {
|
||||
fs: CliDenoResolverFs(fs.clone()),
|
||||
pkg_json_resolver: pkg_json_resolver.clone(),
|
||||
root_node_modules_dir,
|
||||
},
|
||||
))
|
||||
.await?
|
||||
}),
|
||||
)
|
||||
.await?;
|
||||
(in_npm_pkg_checker, npm_resolver)
|
||||
}
|
||||
None => {
|
||||
create_cli_npm_resolver(CliNpmResolverCreateOptions::Managed(
|
||||
CliNpmResolverManagedCreateOptions {
|
||||
snapshot: CliNpmResolverManagedSnapshotOption::Specified(None),
|
||||
maybe_lockfile: None,
|
||||
fs: fs.clone(),
|
||||
http_client_provider: http_client_provider.clone(),
|
||||
npm_global_cache_dir,
|
||||
cache_setting,
|
||||
text_only_progress_bar: progress_bar,
|
||||
maybe_node_modules_path: None,
|
||||
npm_system_info: Default::default(),
|
||||
npm_install_deps_provider: Arc::new(
|
||||
// this is only used for installing packages, which isn't necessary with deno compile
|
||||
NpmInstallDepsProvider::empty(),
|
||||
),
|
||||
// Packages from different registries are already inlined in the binary,
|
||||
// so no need to create actual `.npmrc` configuration.
|
||||
npmrc: create_default_npmrc(),
|
||||
lifecycle_scripts: Default::default(),
|
||||
},
|
||||
))
|
||||
.await?
|
||||
// Packages from different registries are already inlined in the binary,
|
||||
// so no need to create actual `.npmrc` configuration.
|
||||
let npmrc = create_default_npmrc();
|
||||
let npm_cache_dir = Arc::new(NpmCacheDir::new(
|
||||
&DenoCacheEnvFsAdapter(fs.as_ref()),
|
||||
npm_global_cache_dir,
|
||||
npmrc.get_all_known_registries_urls(),
|
||||
));
|
||||
let in_npm_pkg_checker =
|
||||
create_in_npm_pkg_checker(CreateInNpmPkgCheckerOptions::Managed(
|
||||
CliManagedInNpmPkgCheckerCreateOptions {
|
||||
root_cache_dir_url: npm_cache_dir.root_dir_url(),
|
||||
maybe_node_modules_path: None,
|
||||
},
|
||||
));
|
||||
let npm_resolver =
|
||||
create_cli_npm_resolver(CliNpmResolverCreateOptions::Managed(
|
||||
CliManagedNpmResolverCreateOptions {
|
||||
snapshot: CliNpmResolverManagedSnapshotOption::Specified(None),
|
||||
maybe_lockfile: None,
|
||||
fs: fs.clone(),
|
||||
http_client_provider: http_client_provider.clone(),
|
||||
npm_cache_dir,
|
||||
cache_setting,
|
||||
text_only_progress_bar: progress_bar,
|
||||
maybe_node_modules_path: None,
|
||||
npm_system_info: Default::default(),
|
||||
npm_install_deps_provider: Arc::new(
|
||||
// this is only used for installing packages, which isn't necessary with deno compile
|
||||
NpmInstallDepsProvider::empty(),
|
||||
),
|
||||
npmrc: create_default_npmrc(),
|
||||
lifecycle_scripts: Default::default(),
|
||||
},
|
||||
))
|
||||
.await?;
|
||||
(in_npm_pkg_checker, npm_resolver)
|
||||
}
|
||||
};
|
||||
|
||||
let has_node_modules_dir = npm_resolver.root_node_modules_path().is_some();
|
||||
let node_resolver = Arc::new(NodeResolver::new(
|
||||
deno_runtime::deno_node::DenoFsNodeResolverEnv::new(fs.clone()),
|
||||
in_npm_pkg_checker.clone(),
|
||||
npm_resolver.clone().into_npm_resolver(),
|
||||
pkg_json_resolver.clone(),
|
||||
));
|
||||
let cjs_tracker = Arc::new(CjsTracker::new(
|
||||
in_npm_pkg_checker.clone(),
|
||||
pkg_json_resolver.clone(),
|
||||
CjsTrackerOptions {
|
||||
unstable_detect_cjs: metadata.unstable_config.detect_cjs,
|
||||
},
|
||||
));
|
||||
let cjs_resolutions = Arc::new(CjsResolutionStore::default());
|
||||
let cache_db = Caches::new(deno_dir_provider.clone());
|
||||
let node_analysis_cache = NodeAnalysisCache::new(cache_db.node_analysis_db());
|
||||
let cli_node_resolver = Arc::new(CliNodeResolver::new(
|
||||
cjs_resolutions.clone(),
|
||||
cjs_tracker.clone(),
|
||||
fs.clone(),
|
||||
in_npm_pkg_checker.clone(),
|
||||
node_resolver.clone(),
|
||||
npm_resolver.clone(),
|
||||
));
|
||||
let cjs_esm_code_analyzer = CliCjsCodeAnalyzer::new(
|
||||
node_analysis_cache,
|
||||
cjs_tracker.clone(),
|
||||
fs.clone(),
|
||||
cli_node_resolver.clone(),
|
||||
None,
|
||||
false,
|
||||
);
|
||||
let node_code_translator = Arc::new(NodeCodeTranslator::new(
|
||||
cjs_esm_code_analyzer,
|
||||
deno_runtime::deno_node::DenoFsNodeResolverEnv::new(fs.clone()),
|
||||
in_npm_pkg_checker,
|
||||
node_resolver.clone(),
|
||||
npm_resolver.clone().into_npm_resolver(),
|
||||
pkg_json_resolver.clone(),
|
||||
));
|
||||
let workspace_resolver = {
|
||||
let import_map = match metadata.workspace_resolver.import_map {
|
||||
|
@ -562,15 +707,18 @@ pub async fn run(data: StandaloneData) -> Result<i32, AnyError> {
|
|||
};
|
||||
let module_loader_factory = StandaloneModuleLoaderFactory {
|
||||
shared: Arc::new(SharedModuleLoaderState {
|
||||
cjs_tracker: cjs_tracker.clone(),
|
||||
fs: fs.clone(),
|
||||
modules,
|
||||
workspace_resolver,
|
||||
node_code_translator: node_code_translator.clone(),
|
||||
node_resolver: cli_node_resolver.clone(),
|
||||
npm_module_loader: Arc::new(NpmModuleLoader::new(
|
||||
cjs_resolutions.clone(),
|
||||
node_code_translator,
|
||||
cjs_tracker.clone(),
|
||||
fs.clone(),
|
||||
cli_node_resolver,
|
||||
node_code_translator,
|
||||
)),
|
||||
npm_resolver: npm_resolver.clone(),
|
||||
workspace_resolver,
|
||||
}),
|
||||
};
|
||||
|
||||
|
@ -609,7 +757,6 @@ pub async fn run(data: StandaloneData) -> Result<i32, AnyError> {
|
|||
});
|
||||
let worker_factory = CliMainWorkerFactory::new(
|
||||
Arc::new(BlobStore::default()),
|
||||
cjs_resolutions,
|
||||
// Code cache is not supported for standalone binary yet.
|
||||
None,
|
||||
feature_checker,
|
||||
|
@ -620,6 +767,7 @@ pub async fn run(data: StandaloneData) -> Result<i32, AnyError> {
|
|||
Box::new(module_loader_factory),
|
||||
node_resolver,
|
||||
npm_resolver,
|
||||
pkg_json_resolver,
|
||||
root_cert_store_provider,
|
||||
permissions,
|
||||
StorageKeyResolver::empty(),
|
||||
|
@ -635,7 +783,6 @@ pub async fn run(data: StandaloneData) -> Result<i32, AnyError> {
|
|||
inspect_wait: false,
|
||||
strace_ops: None,
|
||||
is_inspecting: false,
|
||||
is_npm_main: main_module.scheme() == "npm",
|
||||
skip_op_registration: true,
|
||||
location: metadata.location,
|
||||
argv0: NpmPackageReqReference::from_specifier(&main_module)
|
||||
|
@ -652,7 +799,6 @@ pub async fn run(data: StandaloneData) -> Result<i32, AnyError> {
|
|||
node_ipc: None,
|
||||
serve_port: None,
|
||||
serve_host: None,
|
||||
unstable_detect_cjs: metadata.unstable_config.detect_cjs,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
|
@ -214,14 +214,13 @@ impl RemoteModulesStoreBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct DenoCompileModuleData<'a> {
|
||||
pub specifier: &'a Url,
|
||||
pub media_type: MediaType,
|
||||
pub data: Cow<'static, [u8]>,
|
||||
pub enum DenoCompileModuleSource {
|
||||
String(&'static str),
|
||||
Bytes(Cow<'static, [u8]>),
|
||||
}
|
||||
|
||||
impl<'a> DenoCompileModuleData<'a> {
|
||||
pub fn into_for_v8(self) -> (&'a Url, ModuleType, ModuleSourceCode) {
|
||||
impl DenoCompileModuleSource {
|
||||
pub fn into_for_v8(self) -> ModuleSourceCode {
|
||||
fn into_bytes(data: Cow<'static, [u8]>) -> ModuleSourceCode {
|
||||
ModuleSourceCode::Bytes(match data {
|
||||
Cow::Borrowed(d) => d.into(),
|
||||
|
@ -229,16 +228,31 @@ impl<'a> DenoCompileModuleData<'a> {
|
|||
})
|
||||
}
|
||||
|
||||
fn into_string_unsafe(data: Cow<'static, [u8]>) -> ModuleSourceCode {
|
||||
match self {
|
||||
// todo(https://github.com/denoland/deno_core/pull/943): store whether
|
||||
// the string is ascii or not ahead of time so we can avoid the is_ascii()
|
||||
// check in FastString::from_static
|
||||
Self::String(s) => ModuleSourceCode::String(FastString::from_static(s)),
|
||||
Self::Bytes(b) => into_bytes(b),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct DenoCompileModuleData<'a> {
|
||||
pub specifier: &'a Url,
|
||||
pub media_type: MediaType,
|
||||
pub data: Cow<'static, [u8]>,
|
||||
}
|
||||
|
||||
impl<'a> DenoCompileModuleData<'a> {
|
||||
pub fn into_parts(self) -> (&'a Url, ModuleType, DenoCompileModuleSource) {
|
||||
fn into_string_unsafe(data: Cow<'static, [u8]>) -> DenoCompileModuleSource {
|
||||
match data {
|
||||
Cow::Borrowed(d) => ModuleSourceCode::String(
|
||||
Cow::Borrowed(d) => DenoCompileModuleSource::String(
|
||||
// SAFETY: we know this is a valid utf8 string
|
||||
unsafe { FastString::from_static(std::str::from_utf8_unchecked(d)) },
|
||||
unsafe { std::str::from_utf8_unchecked(d) },
|
||||
),
|
||||
Cow::Owned(d) => ModuleSourceCode::Bytes(d.into_boxed_slice().into()),
|
||||
Cow::Owned(d) => DenoCompileModuleSource::Bytes(Cow::Owned(d)),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -257,11 +271,14 @@ impl<'a> DenoCompileModuleData<'a> {
|
|||
(ModuleType::JavaScript, into_string_unsafe(self.data))
|
||||
}
|
||||
MediaType::Json => (ModuleType::Json, into_string_unsafe(self.data)),
|
||||
MediaType::Wasm => (ModuleType::Wasm, into_bytes(self.data)),
|
||||
// just assume javascript if we made it here
|
||||
MediaType::TsBuildInfo | MediaType::SourceMap | MediaType::Unknown => {
|
||||
(ModuleType::JavaScript, into_bytes(self.data))
|
||||
MediaType::Wasm => {
|
||||
(ModuleType::Wasm, DenoCompileModuleSource::Bytes(self.data))
|
||||
}
|
||||
// just assume javascript if we made it here
|
||||
MediaType::Css | MediaType::SourceMap | MediaType::Unknown => (
|
||||
ModuleType::JavaScript,
|
||||
DenoCompileModuleSource::Bytes(self.data),
|
||||
),
|
||||
};
|
||||
(self.specifier, media_type, source)
|
||||
}
|
||||
|
@ -551,7 +568,7 @@ fn serialize_media_type(media_type: MediaType) -> u8 {
|
|||
MediaType::Tsx => 10,
|
||||
MediaType::Json => 11,
|
||||
MediaType::Wasm => 12,
|
||||
MediaType::TsBuildInfo => 13,
|
||||
MediaType::Css => 13,
|
||||
MediaType::SourceMap => 14,
|
||||
MediaType::Unknown => 15,
|
||||
}
|
||||
|
@ -572,7 +589,7 @@ fn deserialize_media_type(value: u8) -> Result<MediaType, AnyError> {
|
|||
10 => Ok(MediaType::Tsx),
|
||||
11 => Ok(MediaType::Json),
|
||||
12 => Ok(MediaType::Wasm),
|
||||
13 => Ok(MediaType::TsBuildInfo),
|
||||
13 => Ok(MediaType::Css),
|
||||
14 => Ok(MediaType::SourceMap),
|
||||
15 => Ok(MediaType::Unknown),
|
||||
_ => bail!("Unknown media type value: {}", value),
|
||||
|
|
|
@ -155,6 +155,12 @@ fn prepare_env_vars(
|
|||
initial_cwd.to_string_lossy().to_string(),
|
||||
);
|
||||
}
|
||||
if !env_vars.contains_key(crate::npm::NPM_CONFIG_USER_AGENT_ENV_VAR) {
|
||||
env_vars.insert(
|
||||
crate::npm::NPM_CONFIG_USER_AGENT_ENV_VAR.into(),
|
||||
crate::npm::get_npm_config_user_agent(),
|
||||
);
|
||||
}
|
||||
if let Some(node_modules_dir) = node_modules_dir {
|
||||
prepend_to_path(
|
||||
&mut env_vars,
|
||||
|
@ -204,7 +210,7 @@ impl ShellCommand for NpmCommand {
|
|||
mut context: ShellCommandContext,
|
||||
) -> LocalBoxFuture<'static, ExecuteResult> {
|
||||
if context.args.first().map(|s| s.as_str()) == Some("run")
|
||||
&& context.args.len() > 2
|
||||
&& context.args.len() >= 2
|
||||
// for now, don't run any npm scripts that have a flag because
|
||||
// we don't handle stuff like `--workspaces` properly
|
||||
&& !context.args.iter().any(|s| s.starts_with('-'))
|
||||
|
@ -267,10 +273,12 @@ impl ShellCommand for NodeCommand {
|
|||
)
|
||||
.execute(context);
|
||||
}
|
||||
|
||||
args.extend(["run", "-A"].into_iter().map(|s| s.to_string()));
|
||||
args.extend(context.args.iter().cloned());
|
||||
|
||||
let mut state = context.state;
|
||||
|
||||
state.apply_env_var(USE_PKG_JSON_HIDDEN_ENV_VAR_NAME, "1");
|
||||
ExecutableCommand::new("deno".to_string(), std::env::current_exe().unwrap())
|
||||
.execute(ShellCommandContext {
|
||||
|
|
|
@ -193,7 +193,7 @@ async fn bench_specifier_inner(
|
|||
.await?;
|
||||
|
||||
// We execute the main module as a side module so that import.meta.main is not set.
|
||||
worker.execute_side_module_possibly_with_npm().await?;
|
||||
worker.execute_side_module().await?;
|
||||
|
||||
let mut worker = worker.into_main_worker();
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@ use crate::graph_util::ModuleGraphBuilder;
|
|||
use crate::npm::CliNpmResolver;
|
||||
use crate::tsc;
|
||||
use crate::tsc::Diagnostics;
|
||||
use crate::tsc::TypeCheckingCjsTracker;
|
||||
use crate::util::extract;
|
||||
use crate::util::path::to_percent_decoded_str;
|
||||
|
||||
|
@ -99,6 +100,7 @@ pub struct CheckOptions {
|
|||
|
||||
pub struct TypeChecker {
|
||||
caches: Arc<Caches>,
|
||||
cjs_tracker: Arc<TypeCheckingCjsTracker>,
|
||||
cli_options: Arc<CliOptions>,
|
||||
module_graph_builder: Arc<ModuleGraphBuilder>,
|
||||
node_resolver: Arc<NodeResolver>,
|
||||
|
@ -108,6 +110,7 @@ pub struct TypeChecker {
|
|||
impl TypeChecker {
|
||||
pub fn new(
|
||||
caches: Arc<Caches>,
|
||||
cjs_tracker: Arc<TypeCheckingCjsTracker>,
|
||||
cli_options: Arc<CliOptions>,
|
||||
module_graph_builder: Arc<ModuleGraphBuilder>,
|
||||
node_resolver: Arc<NodeResolver>,
|
||||
|
@ -115,6 +118,7 @@ impl TypeChecker {
|
|||
) -> Self {
|
||||
Self {
|
||||
caches,
|
||||
cjs_tracker,
|
||||
cli_options,
|
||||
module_graph_builder,
|
||||
node_resolver,
|
||||
|
@ -244,6 +248,7 @@ impl TypeChecker {
|
|||
graph: graph.clone(),
|
||||
hash_data,
|
||||
maybe_npm: Some(tsc::RequestNpmState {
|
||||
cjs_tracker: self.cjs_tracker.clone(),
|
||||
node_resolver: self.node_resolver.clone(),
|
||||
npm_resolver: self.npm_resolver.clone(),
|
||||
}),
|
||||
|
@ -346,7 +351,7 @@ fn get_check_hash(
|
|||
}
|
||||
}
|
||||
MediaType::Json
|
||||
| MediaType::TsBuildInfo
|
||||
| MediaType::Css
|
||||
| MediaType::SourceMap
|
||||
| MediaType::Wasm
|
||||
| MediaType::Unknown => continue,
|
||||
|
@ -428,7 +433,7 @@ fn get_tsc_roots(
|
|||
}
|
||||
MediaType::Json
|
||||
| MediaType::Wasm
|
||||
| MediaType::TsBuildInfo
|
||||
| MediaType::Css
|
||||
| MediaType::SourceMap
|
||||
| MediaType::Unknown => None,
|
||||
},
|
||||
|
@ -536,7 +541,7 @@ fn has_ts_check(media_type: MediaType, file_text: &str) -> bool {
|
|||
| MediaType::Tsx
|
||||
| MediaType::Json
|
||||
| MediaType::Wasm
|
||||
| MediaType::TsBuildInfo
|
||||
| MediaType::Css
|
||||
| MediaType::SourceMap
|
||||
| MediaType::Unknown => false,
|
||||
}
|
||||
|
|
|
@ -53,16 +53,6 @@ pub async fn compile(
|
|||
);
|
||||
}
|
||||
|
||||
if cli_options.unstable_detect_cjs() {
|
||||
log::warn!(
|
||||
concat!(
|
||||
"{} --unstable-detect-cjs is not properly supported in deno compile. ",
|
||||
"The compiled executable may encounter runtime errors.",
|
||||
),
|
||||
crate::colors::yellow("Warning"),
|
||||
);
|
||||
}
|
||||
|
||||
let output_path = resolve_compile_executable_output_path(
|
||||
http_client,
|
||||
&compile_flags,
|
||||
|
|
|
@ -6,12 +6,12 @@ use crate::args::FileFlags;
|
|||
use crate::args::Flags;
|
||||
use crate::cdp;
|
||||
use crate::factory::CliFactory;
|
||||
use crate::npm::CliNpmResolver;
|
||||
use crate::tools::fmt::format_json;
|
||||
use crate::tools::test::is_supported_test_path;
|
||||
use crate::util::text_encoding::source_map_from_code;
|
||||
|
||||
use deno_ast::MediaType;
|
||||
use deno_ast::ModuleKind;
|
||||
use deno_ast::ModuleSpecifier;
|
||||
use deno_config::glob::FileCollector;
|
||||
use deno_config::glob::FilePatterns;
|
||||
|
@ -25,6 +25,7 @@ use deno_core::serde_json;
|
|||
use deno_core::sourcemap::SourceMap;
|
||||
use deno_core::url::Url;
|
||||
use deno_core::LocalInspectorSession;
|
||||
use node_resolver::InNpmPackageChecker;
|
||||
use regex::Regex;
|
||||
use std::fs;
|
||||
use std::fs::File;
|
||||
|
@ -327,6 +328,7 @@ fn generate_coverage_report(
|
|||
|
||||
coverage_report.found_lines =
|
||||
if let Some(source_map) = maybe_source_map.as_ref() {
|
||||
let script_source_lines = script_source.lines().collect::<Vec<_>>();
|
||||
let mut found_lines = line_counts
|
||||
.iter()
|
||||
.enumerate()
|
||||
|
@ -334,7 +336,23 @@ fn generate_coverage_report(
|
|||
// get all the mappings from this destination line to a different src line
|
||||
let mut results = source_map
|
||||
.tokens()
|
||||
.filter(move |token| token.get_dst_line() as usize == index)
|
||||
.filter(|token| {
|
||||
let dst_line = token.get_dst_line() as usize;
|
||||
dst_line == index && {
|
||||
let dst_col = token.get_dst_col() as usize;
|
||||
let content = script_source_lines
|
||||
.get(dst_line)
|
||||
.and_then(|line| {
|
||||
line.get(dst_col..std::cmp::min(dst_col + 2, line.len()))
|
||||
})
|
||||
.unwrap_or("");
|
||||
|
||||
!content.is_empty()
|
||||
&& content != "/*"
|
||||
&& content != "*/"
|
||||
&& content != "//"
|
||||
}
|
||||
})
|
||||
.map(move |token| (token.get_src_line() as usize, *count))
|
||||
.collect::<Vec<_>>();
|
||||
// only keep the results that point at different src lines
|
||||
|
@ -444,7 +462,7 @@ fn filter_coverages(
|
|||
coverages: Vec<cdp::ScriptCoverage>,
|
||||
include: Vec<String>,
|
||||
exclude: Vec<String>,
|
||||
npm_resolver: &dyn CliNpmResolver,
|
||||
in_npm_pkg_checker: &dyn InNpmPackageChecker,
|
||||
) -> Vec<cdp::ScriptCoverage> {
|
||||
let include: Vec<Regex> =
|
||||
include.iter().map(|e| Regex::new(e).unwrap()).collect();
|
||||
|
@ -468,7 +486,7 @@ fn filter_coverages(
|
|||
|| doc_test_re.is_match(e.url.as_str())
|
||||
|| Url::parse(&e.url)
|
||||
.ok()
|
||||
.map(|url| npm_resolver.in_npm_package(&url))
|
||||
.map(|url| in_npm_pkg_checker.in_npm_package(&url))
|
||||
.unwrap_or(false);
|
||||
|
||||
let is_included = include.iter().any(|p| p.is_match(&e.url));
|
||||
|
@ -479,7 +497,7 @@ fn filter_coverages(
|
|||
.collect::<Vec<cdp::ScriptCoverage>>()
|
||||
}
|
||||
|
||||
pub async fn cover_files(
|
||||
pub fn cover_files(
|
||||
flags: Arc<Flags>,
|
||||
coverage_flags: CoverageFlags,
|
||||
) -> Result<(), AnyError> {
|
||||
|
@ -489,9 +507,10 @@ pub async fn cover_files(
|
|||
|
||||
let factory = CliFactory::from_flags(flags);
|
||||
let cli_options = factory.cli_options()?;
|
||||
let npm_resolver = factory.npm_resolver().await?;
|
||||
let in_npm_pkg_checker = factory.in_npm_pkg_checker()?;
|
||||
let file_fetcher = factory.file_fetcher()?;
|
||||
let emitter = factory.emitter()?;
|
||||
let cjs_tracker = factory.cjs_tracker()?;
|
||||
|
||||
assert!(!coverage_flags.files.include.is_empty());
|
||||
|
||||
|
@ -511,7 +530,7 @@ pub async fn cover_files(
|
|||
script_coverages,
|
||||
coverage_flags.include,
|
||||
coverage_flags.exclude,
|
||||
npm_resolver.as_ref(),
|
||||
in_npm_pkg_checker.as_ref(),
|
||||
);
|
||||
if script_coverages.is_empty() {
|
||||
return Err(generic_error("No covered files included in the report"));
|
||||
|
@ -568,6 +587,8 @@ pub async fn cover_files(
|
|||
let transpiled_code = match file.media_type {
|
||||
MediaType::JavaScript
|
||||
| MediaType::Unknown
|
||||
| MediaType::Css
|
||||
| MediaType::Wasm
|
||||
| MediaType::Cjs
|
||||
| MediaType::Mjs
|
||||
| MediaType::Json => None,
|
||||
|
@ -577,7 +598,10 @@ pub async fn cover_files(
|
|||
| MediaType::Mts
|
||||
| MediaType::Cts
|
||||
| MediaType::Tsx => {
|
||||
Some(match emitter.maybe_cached_emit(&file.specifier, &file.source) {
|
||||
let module_kind = ModuleKind::from_is_cjs(
|
||||
cjs_tracker.is_maybe_cjs(&file.specifier, file.media_type)?,
|
||||
);
|
||||
Some(match emitter.maybe_cached_emit(&file.specifier, module_kind, &file.source) {
|
||||
Some(code) => code,
|
||||
None => {
|
||||
return Err(anyhow!(
|
||||
|
@ -588,7 +612,7 @@ pub async fn cover_files(
|
|||
}
|
||||
})
|
||||
}
|
||||
MediaType::Wasm | MediaType::TsBuildInfo | MediaType::SourceMap => {
|
||||
MediaType::SourceMap => {
|
||||
unreachable!()
|
||||
}
|
||||
};
|
||||
|
|
|
@ -22,9 +22,9 @@ use deno_core::serde_json;
|
|||
use deno_doc as doc;
|
||||
use deno_doc::html::UrlResolveKind;
|
||||
use deno_graph::source::NullFileSystem;
|
||||
use deno_graph::EsParser;
|
||||
use deno_graph::GraphKind;
|
||||
use deno_graph::ModuleAnalyzer;
|
||||
use deno_graph::ModuleParser;
|
||||
use deno_graph::ModuleSpecifier;
|
||||
use doc::html::ShortPath;
|
||||
use doc::DocDiagnostic;
|
||||
|
@ -37,7 +37,7 @@ const JSON_SCHEMA_VERSION: u8 = 1;
|
|||
|
||||
async fn generate_doc_nodes_for_builtin_types(
|
||||
doc_flags: DocFlags,
|
||||
parser: &dyn ModuleParser,
|
||||
parser: &dyn EsParser,
|
||||
analyzer: &dyn ModuleAnalyzer,
|
||||
) -> Result<IndexMap<ModuleSpecifier, Vec<doc::DocNode>>, AnyError> {
|
||||
let source_file_specifier =
|
||||
|
@ -96,7 +96,7 @@ pub async fn doc(
|
|||
let module_info_cache = factory.module_info_cache()?;
|
||||
let parsed_source_cache = factory.parsed_source_cache();
|
||||
let capturing_parser = parsed_source_cache.as_capturing_parser();
|
||||
let analyzer = module_info_cache.as_module_analyzer(parsed_source_cache);
|
||||
let analyzer = module_info_cache.as_module_analyzer();
|
||||
|
||||
let doc_nodes_by_url = match doc_flags.source_files {
|
||||
DocSourceFileFlag::Builtin => {
|
||||
|
|
|
@ -353,6 +353,21 @@ fn format_yaml(
|
|||
file_text: &str,
|
||||
fmt_options: &FmtOptionsConfig,
|
||||
) -> Result<Option<String>, AnyError> {
|
||||
let ignore_file = file_text
|
||||
.lines()
|
||||
.take_while(|line| line.starts_with('#'))
|
||||
.any(|line| {
|
||||
line
|
||||
.strip_prefix('#')
|
||||
.unwrap()
|
||||
.trim()
|
||||
.starts_with("deno-fmt-ignore-file")
|
||||
});
|
||||
|
||||
if ignore_file {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
let formatted_str =
|
||||
pretty_yaml::format_text(file_text, &get_resolved_yaml_config(fmt_options))
|
||||
.map_err(AnyError::from)?;
|
||||
|
@ -1017,7 +1032,7 @@ fn get_resolved_markup_fmt_config(
|
|||
max_attrs_per_line: None,
|
||||
prefer_attrs_single_line: false,
|
||||
html_normal_self_closing: None,
|
||||
html_void_self_closing: Some(true),
|
||||
html_void_self_closing: None,
|
||||
component_self_closing: None,
|
||||
svg_self_closing: None,
|
||||
mathml_self_closing: None,
|
||||
|
|
|
@ -530,7 +530,7 @@ impl<'a> GraphDisplayContext<'a> {
|
|||
|
||||
fn build_module_info(&mut self, module: &Module, type_dep: bool) -> TreeNode {
|
||||
enum PackageOrSpecifier {
|
||||
Package(NpmResolutionPackage),
|
||||
Package(Box<NpmResolutionPackage>),
|
||||
Specifier(ModuleSpecifier),
|
||||
}
|
||||
|
||||
|
@ -538,7 +538,7 @@ impl<'a> GraphDisplayContext<'a> {
|
|||
|
||||
let package_or_specifier = match module.npm() {
|
||||
Some(npm) => match self.npm_info.resolve_package(npm.nv_reference.nv()) {
|
||||
Some(package) => Package(package.clone()),
|
||||
Some(package) => Package(Box::new(package.clone())),
|
||||
None => Specifier(module.specifier().clone()), // should never happen
|
||||
},
|
||||
None => Specifier(module.specifier().clone()),
|
||||
|
@ -645,10 +645,12 @@ impl<'a> GraphDisplayContext<'a> {
|
|||
let message = match err {
|
||||
HttpsChecksumIntegrity(_) => "(checksum integrity error)",
|
||||
Decode(_) => "(loading decode error)",
|
||||
Loader(err) => match deno_core::error::get_custom_error_class(err) {
|
||||
Some("NotCapable") => "(not capable, requires --allow-import)",
|
||||
_ => "(loading error)",
|
||||
},
|
||||
Loader(err) => {
|
||||
match deno_runtime::errors::get_error_class_name(err) {
|
||||
Some("NotCapable") => "(not capable, requires --allow-import)",
|
||||
_ => "(loading error)",
|
||||
}
|
||||
}
|
||||
Jsr(_) => "(loading error)",
|
||||
NodeUnknownBuiltinModule(_) => "(unknown node built-in error)",
|
||||
Npm(_) => "(npm loading error)",
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
|
||||
|
@ -11,7 +12,9 @@ use deno_core::futures::StreamExt;
|
|||
use deno_path_util::url_to_file_path;
|
||||
use deno_semver::jsr::JsrPackageReqReference;
|
||||
use deno_semver::npm::NpmPackageReqReference;
|
||||
use deno_semver::package::PackageNv;
|
||||
use deno_semver::package::PackageReq;
|
||||
use deno_semver::Version;
|
||||
use deno_semver::VersionReq;
|
||||
use jsonc_parser::cst::CstObject;
|
||||
use jsonc_parser::cst::CstObjectProp;
|
||||
|
@ -333,6 +336,14 @@ fn load_configs(
|
|||
Ok((cli_factory, npm_config, deno_config))
|
||||
}
|
||||
|
||||
fn path_distance(a: &Path, b: &Path) -> usize {
|
||||
let diff = pathdiff::diff_paths(a, b);
|
||||
let Some(diff) = diff else {
|
||||
return usize::MAX;
|
||||
};
|
||||
diff.components().count()
|
||||
}
|
||||
|
||||
pub async fn add(
|
||||
flags: Arc<Flags>,
|
||||
add_flags: AddFlags,
|
||||
|
@ -357,6 +368,21 @@ pub async fn add(
|
|||
}
|
||||
}
|
||||
|
||||
let start_dir = cli_factory.cli_options()?.start_dir.dir_path();
|
||||
|
||||
// only prefer to add npm deps to `package.json` if there isn't a closer deno.json.
|
||||
// example: if deno.json is in the CWD and package.json is in the parent, we should add
|
||||
// npm deps to deno.json, since it's closer
|
||||
let prefer_npm_config = match (npm_config.as_ref(), deno_config.as_ref()) {
|
||||
(Some(npm), Some(deno)) => {
|
||||
let npm_distance = path_distance(&npm.path, &start_dir);
|
||||
let deno_distance = path_distance(&deno.path, &start_dir);
|
||||
npm_distance <= deno_distance
|
||||
}
|
||||
(Some(_), None) => true,
|
||||
(None, _) => false,
|
||||
};
|
||||
|
||||
let http_client = cli_factory.http_client_provider();
|
||||
let deps_http_cache = cli_factory.global_http_cache()?;
|
||||
let mut deps_file_fetcher = FileFetcher::new(
|
||||
|
@ -431,15 +457,32 @@ pub async fn add(
|
|||
match package_and_version {
|
||||
PackageAndVersion::NotFound {
|
||||
package: package_name,
|
||||
found_npm_package,
|
||||
help,
|
||||
package_req,
|
||||
} => {
|
||||
if found_npm_package {
|
||||
bail!("{} was not found, but a matching npm package exists. Did you mean `{}`?", crate::colors::red(package_name), crate::colors::yellow(format!("deno {cmd_name} npm:{package_req}")));
|
||||
} else {
|
||||
bail!("{} was not found.", crate::colors::red(package_name));
|
||||
} => match help {
|
||||
Some(NotFoundHelp::NpmPackage) => {
|
||||
bail!(
|
||||
"{} was not found, but a matching npm package exists. Did you mean `{}`?",
|
||||
crate::colors::red(package_name),
|
||||
crate::colors::yellow(format!("deno {cmd_name} npm:{package_req}"))
|
||||
);
|
||||
}
|
||||
}
|
||||
Some(NotFoundHelp::JsrPackage) => {
|
||||
bail!(
|
||||
"{} was not found, but a matching jsr package exists. Did you mean `{}`?",
|
||||
crate::colors::red(package_name),
|
||||
crate::colors::yellow(format!("deno {cmd_name} jsr:{package_req}"))
|
||||
)
|
||||
}
|
||||
Some(NotFoundHelp::PreReleaseVersion(version)) => {
|
||||
bail!(
|
||||
"{} has only pre-release versions available. Try specifying a version: `{}`",
|
||||
crate::colors::red(&package_name),
|
||||
crate::colors::yellow(format!("deno {cmd_name} {package_name}@^{version}"))
|
||||
)
|
||||
}
|
||||
None => bail!("{} was not found.", crate::colors::red(package_name)),
|
||||
},
|
||||
PackageAndVersion::Selected(selected) => {
|
||||
selected_packages.push(selected);
|
||||
}
|
||||
|
@ -455,7 +498,7 @@ pub async fn add(
|
|||
selected_package.selected_version
|
||||
);
|
||||
|
||||
if selected_package.package_name.starts_with("npm:") {
|
||||
if selected_package.package_name.starts_with("npm:") && prefer_npm_config {
|
||||
if let Some(npm) = &mut npm_config {
|
||||
npm.add(selected_package, dev);
|
||||
} else {
|
||||
|
@ -487,76 +530,144 @@ struct SelectedPackage {
|
|||
selected_version: String,
|
||||
}
|
||||
|
||||
enum NotFoundHelp {
|
||||
NpmPackage,
|
||||
JsrPackage,
|
||||
PreReleaseVersion(Version),
|
||||
}
|
||||
|
||||
enum PackageAndVersion {
|
||||
NotFound {
|
||||
package: String,
|
||||
found_npm_package: bool,
|
||||
package_req: PackageReq,
|
||||
help: Option<NotFoundHelp>,
|
||||
},
|
||||
Selected(SelectedPackage),
|
||||
}
|
||||
|
||||
fn best_version<'a>(
|
||||
versions: impl Iterator<Item = &'a Version>,
|
||||
) -> Option<&'a Version> {
|
||||
let mut maybe_best_version: Option<&Version> = None;
|
||||
for version in versions {
|
||||
let is_best_version = maybe_best_version
|
||||
.as_ref()
|
||||
.map(|best_version| (*best_version).cmp(version).is_lt())
|
||||
.unwrap_or(true);
|
||||
if is_best_version {
|
||||
maybe_best_version = Some(version);
|
||||
}
|
||||
}
|
||||
maybe_best_version
|
||||
}
|
||||
|
||||
trait PackageInfoProvider {
|
||||
const SPECIFIER_PREFIX: &str;
|
||||
/// The help to return if a package is found by this provider
|
||||
const HELP: NotFoundHelp;
|
||||
async fn req_to_nv(&self, req: &PackageReq) -> Option<PackageNv>;
|
||||
async fn latest_version<'a>(&self, req: &PackageReq) -> Option<Version>;
|
||||
}
|
||||
|
||||
impl PackageInfoProvider for Arc<JsrFetchResolver> {
|
||||
const HELP: NotFoundHelp = NotFoundHelp::JsrPackage;
|
||||
const SPECIFIER_PREFIX: &str = "jsr";
|
||||
async fn req_to_nv(&self, req: &PackageReq) -> Option<PackageNv> {
|
||||
(**self).req_to_nv(req).await
|
||||
}
|
||||
|
||||
async fn latest_version<'a>(&self, req: &PackageReq) -> Option<Version> {
|
||||
let info = self.package_info(&req.name).await?;
|
||||
best_version(
|
||||
info
|
||||
.versions
|
||||
.iter()
|
||||
.filter(|(_, version_info)| !version_info.yanked)
|
||||
.map(|(version, _)| version),
|
||||
)
|
||||
.cloned()
|
||||
}
|
||||
}
|
||||
|
||||
impl PackageInfoProvider for Arc<NpmFetchResolver> {
|
||||
const HELP: NotFoundHelp = NotFoundHelp::NpmPackage;
|
||||
const SPECIFIER_PREFIX: &str = "npm";
|
||||
async fn req_to_nv(&self, req: &PackageReq) -> Option<PackageNv> {
|
||||
(**self).req_to_nv(req).await
|
||||
}
|
||||
|
||||
async fn latest_version<'a>(&self, req: &PackageReq) -> Option<Version> {
|
||||
let info = self.package_info(&req.name).await?;
|
||||
best_version(info.versions.keys()).cloned()
|
||||
}
|
||||
}
|
||||
|
||||
async fn find_package_and_select_version_for_req(
|
||||
jsr_resolver: Arc<JsrFetchResolver>,
|
||||
npm_resolver: Arc<NpmFetchResolver>,
|
||||
add_package_req: AddRmPackageReq,
|
||||
) -> Result<PackageAndVersion, AnyError> {
|
||||
match add_package_req.value {
|
||||
AddRmPackageReqValue::Jsr(req) => {
|
||||
let jsr_prefixed_name = format!("jsr:{}", &req.name);
|
||||
let Some(nv) = jsr_resolver.req_to_nv(&req).await else {
|
||||
if npm_resolver.req_to_nv(&req).await.is_some() {
|
||||
async fn select<T: PackageInfoProvider, S: PackageInfoProvider>(
|
||||
main_resolver: T,
|
||||
fallback_resolver: S,
|
||||
add_package_req: AddRmPackageReq,
|
||||
) -> Result<PackageAndVersion, AnyError> {
|
||||
let req = match &add_package_req.value {
|
||||
AddRmPackageReqValue::Jsr(req) => req,
|
||||
AddRmPackageReqValue::Npm(req) => req,
|
||||
};
|
||||
let prefixed_name = format!("{}:{}", T::SPECIFIER_PREFIX, req.name);
|
||||
let help_if_found_in_fallback = S::HELP;
|
||||
let Some(nv) = main_resolver.req_to_nv(req).await else {
|
||||
if fallback_resolver.req_to_nv(req).await.is_some() {
|
||||
// it's in the other registry
|
||||
return Ok(PackageAndVersion::NotFound {
|
||||
package: prefixed_name,
|
||||
help: Some(help_if_found_in_fallback),
|
||||
package_req: req.clone(),
|
||||
});
|
||||
}
|
||||
if req.version_req.version_text() == "*" {
|
||||
if let Some(pre_release_version) =
|
||||
main_resolver.latest_version(req).await
|
||||
{
|
||||
return Ok(PackageAndVersion::NotFound {
|
||||
package: jsr_prefixed_name,
|
||||
found_npm_package: true,
|
||||
package_req: req,
|
||||
package: prefixed_name,
|
||||
package_req: req.clone(),
|
||||
help: Some(NotFoundHelp::PreReleaseVersion(
|
||||
pre_release_version.clone(),
|
||||
)),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return Ok(PackageAndVersion::NotFound {
|
||||
package: jsr_prefixed_name,
|
||||
found_npm_package: false,
|
||||
package_req: req,
|
||||
});
|
||||
};
|
||||
let range_symbol = if req.version_req.version_text().starts_with('~') {
|
||||
"~"
|
||||
} else if req.version_req.version_text() == nv.version.to_string() {
|
||||
""
|
||||
} else {
|
||||
"^"
|
||||
};
|
||||
Ok(PackageAndVersion::Selected(SelectedPackage {
|
||||
import_name: add_package_req.alias,
|
||||
package_name: jsr_prefixed_name,
|
||||
version_req: format!("{}{}", range_symbol, &nv.version),
|
||||
selected_version: nv.version.to_string(),
|
||||
}))
|
||||
return Ok(PackageAndVersion::NotFound {
|
||||
package: prefixed_name,
|
||||
help: None,
|
||||
package_req: req.clone(),
|
||||
});
|
||||
};
|
||||
let range_symbol = if req.version_req.version_text().starts_with('~') {
|
||||
"~"
|
||||
} else if req.version_req.version_text() == nv.version.to_string() {
|
||||
""
|
||||
} else {
|
||||
"^"
|
||||
};
|
||||
Ok(PackageAndVersion::Selected(SelectedPackage {
|
||||
import_name: add_package_req.alias,
|
||||
package_name: prefixed_name,
|
||||
version_req: format!("{}{}", range_symbol, &nv.version),
|
||||
selected_version: nv.version.to_string(),
|
||||
}))
|
||||
}
|
||||
|
||||
match &add_package_req.value {
|
||||
AddRmPackageReqValue::Jsr(_) => {
|
||||
select(jsr_resolver, npm_resolver, add_package_req).await
|
||||
}
|
||||
AddRmPackageReqValue::Npm(req) => {
|
||||
let npm_prefixed_name = format!("npm:{}", &req.name);
|
||||
let Some(nv) = npm_resolver.req_to_nv(&req).await else {
|
||||
return Ok(PackageAndVersion::NotFound {
|
||||
package: npm_prefixed_name,
|
||||
found_npm_package: false,
|
||||
package_req: req,
|
||||
});
|
||||
};
|
||||
|
||||
let range_symbol = if req.version_req.version_text().starts_with('~') {
|
||||
"~"
|
||||
} else if req.version_req.version_text() == nv.version.to_string() {
|
||||
""
|
||||
} else {
|
||||
"^"
|
||||
};
|
||||
|
||||
Ok(PackageAndVersion::Selected(SelectedPackage {
|
||||
import_name: add_package_req.alias,
|
||||
package_name: npm_prefixed_name,
|
||||
version_req: format!("{}{}", range_symbol, &nv.version),
|
||||
selected_version: nv.version.to_string(),
|
||||
}))
|
||||
AddRmPackageReqValue::Npm(_) => {
|
||||
select(npm_resolver, jsr_resolver, add_package_req).await
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -120,7 +120,7 @@ fn resolve_content_maybe_unfurling(
|
|||
| MediaType::Unknown
|
||||
| MediaType::Json
|
||||
| MediaType::Wasm
|
||||
| MediaType::TsBuildInfo => {
|
||||
| MediaType::Css => {
|
||||
// not unfurlable data
|
||||
return Ok(data);
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ use deno_ast::swc::visit::noop_visit_type;
|
|||
use deno_ast::swc::visit::Visit;
|
||||
use deno_ast::swc::visit::VisitWith;
|
||||
use deno_ast::ImportsNotUsedAsValues;
|
||||
use deno_ast::ModuleKind;
|
||||
use deno_ast::ModuleSpecifier;
|
||||
use deno_ast::ParseDiagnosticsError;
|
||||
use deno_ast::ParsedSource;
|
||||
|
@ -641,6 +642,10 @@ impl ReplSession {
|
|||
jsx_fragment_factory: self.jsx.frag_factory.clone(),
|
||||
jsx_import_source: self.jsx.import_source.clone(),
|
||||
var_decl_imports: true,
|
||||
verbatim_module_syntax: false,
|
||||
},
|
||||
&deno_ast::TranspileModuleOptions {
|
||||
module_kind: Some(ModuleKind::Esm),
|
||||
},
|
||||
&deno_ast::EmitOptions {
|
||||
source_map: deno_ast::SourceMapOption::None,
|
||||
|
@ -651,7 +656,6 @@ impl ReplSession {
|
|||
},
|
||||
)?
|
||||
.into_source()
|
||||
.into_string()?
|
||||
.text;
|
||||
|
||||
let value = self
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
use crate::cdp;
|
||||
use crate::emit::Emitter;
|
||||
use crate::util::file_watcher::WatcherCommunicator;
|
||||
use crate::util::file_watcher::WatcherRestartMode;
|
||||
use std::collections::HashMap;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
|
||||
use deno_ast::MediaType;
|
||||
use deno_ast::ModuleKind;
|
||||
use deno_core::error::generic_error;
|
||||
use deno_core::error::AnyError;
|
||||
use deno_core::futures::StreamExt;
|
||||
|
@ -12,11 +14,14 @@ use deno_core::serde_json::{self};
|
|||
use deno_core::url::Url;
|
||||
use deno_core::LocalInspectorSession;
|
||||
use deno_terminal::colors;
|
||||
use std::collections::HashMap;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
use tokio::select;
|
||||
|
||||
use crate::cdp;
|
||||
use crate::emit::Emitter;
|
||||
use crate::resolver::CjsTracker;
|
||||
use crate::util::file_watcher::WatcherCommunicator;
|
||||
use crate::util::file_watcher::WatcherRestartMode;
|
||||
|
||||
fn explain(status: &cdp::Status) -> &'static str {
|
||||
match status {
|
||||
cdp::Status::Ok => "OK",
|
||||
|
@ -58,6 +63,7 @@ pub struct HmrRunner {
|
|||
session: LocalInspectorSession,
|
||||
watcher_communicator: Arc<WatcherCommunicator>,
|
||||
script_ids: HashMap<String, String>,
|
||||
cjs_tracker: Arc<CjsTracker>,
|
||||
emitter: Arc<Emitter>,
|
||||
}
|
||||
|
||||
|
@ -139,7 +145,8 @@ impl crate::worker::HmrRunner for HmrRunner {
|
|||
};
|
||||
|
||||
let source_code = self.emitter.load_and_emit_for_hmr(
|
||||
&module_url
|
||||
&module_url,
|
||||
ModuleKind::from_is_cjs(self.cjs_tracker.is_maybe_cjs(&module_url, MediaType::from_specifier(&module_url))?),
|
||||
).await?;
|
||||
|
||||
let mut tries = 1;
|
||||
|
@ -172,12 +179,14 @@ impl crate::worker::HmrRunner for HmrRunner {
|
|||
|
||||
impl HmrRunner {
|
||||
pub fn new(
|
||||
cjs_tracker: Arc<CjsTracker>,
|
||||
emitter: Arc<Emitter>,
|
||||
session: LocalInspectorSession,
|
||||
watcher_communicator: Arc<WatcherCommunicator>,
|
||||
) -> Self {
|
||||
Self {
|
||||
session,
|
||||
cjs_tracker,
|
||||
emitter,
|
||||
watcher_communicator,
|
||||
script_ids: HashMap::new(),
|
||||
|
|
|
@ -30,6 +30,16 @@ To grant permissions, set them before the script argument. For example:
|
|||
}
|
||||
}
|
||||
|
||||
fn set_npm_user_agent() {
|
||||
static ONCE: std::sync::Once = std::sync::Once::new();
|
||||
ONCE.call_once(|| {
|
||||
std::env::set_var(
|
||||
crate::npm::NPM_CONFIG_USER_AGENT_ENV_VAR,
|
||||
crate::npm::get_npm_config_user_agent(),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
pub async fn run_script(
|
||||
mode: WorkerExecutionMode,
|
||||
flags: Arc<Flags>,
|
||||
|
@ -58,6 +68,10 @@ pub async fn run_script(
|
|||
|
||||
let main_module = cli_options.resolve_main_module()?;
|
||||
|
||||
if main_module.scheme() == "npm" {
|
||||
set_npm_user_agent();
|
||||
}
|
||||
|
||||
maybe_npm_install(&factory).await?;
|
||||
|
||||
let worker_factory = factory.create_cli_main_worker_factory().await?;
|
||||
|
@ -119,6 +133,10 @@ async fn run_with_watch(
|
|||
let cli_options = factory.cli_options()?;
|
||||
let main_module = cli_options.resolve_main_module()?;
|
||||
|
||||
if main_module.scheme() == "npm" {
|
||||
set_npm_user_agent();
|
||||
}
|
||||
|
||||
maybe_npm_install(&factory).await?;
|
||||
|
||||
let _ = watcher_communicator.watch_paths(cli_options.watch_paths());
|
||||
|
|
|
@ -44,12 +44,15 @@ pub async fn serve(
|
|||
maybe_npm_install(&factory).await?;
|
||||
|
||||
let worker_factory = factory.create_cli_main_worker_factory().await?;
|
||||
|
||||
let hmr = serve_flags
|
||||
.watch
|
||||
.map(|watch_flags| watch_flags.hmr)
|
||||
.unwrap_or(false);
|
||||
do_serve(
|
||||
worker_factory,
|
||||
main_module.clone(),
|
||||
serve_flags.worker_count,
|
||||
false,
|
||||
hmr,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
@ -109,8 +112,6 @@ async fn do_serve(
|
|||
}
|
||||
}
|
||||
Ok(exit_code)
|
||||
|
||||
// main.await?
|
||||
}
|
||||
|
||||
async fn run_worker(
|
||||
|
@ -119,7 +120,7 @@ async fn run_worker(
|
|||
main_module: ModuleSpecifier,
|
||||
hmr: bool,
|
||||
) -> Result<i32, AnyError> {
|
||||
let mut worker = worker_factory
|
||||
let mut worker: crate::worker::CliMainWorker = worker_factory
|
||||
.create_main_worker(
|
||||
deno_runtime::WorkerExecutionMode::Serve {
|
||||
is_main: false,
|
||||
|
|
|
@ -631,7 +631,7 @@ async fn configure_main_worker(
|
|||
"Deno[Deno.internal].core.setLeakTracingEnabled(true);",
|
||||
)?;
|
||||
}
|
||||
let res = worker.execute_side_module_possibly_with_npm().await;
|
||||
let res = worker.execute_side_module().await;
|
||||
let mut worker = worker.into_main_worker();
|
||||
match res {
|
||||
Ok(()) => Ok(()),
|
||||
|
|
|
@ -801,13 +801,18 @@ delete Object.prototype.__proto__;
|
|||
if (logDebug) {
|
||||
debug(`host.getScriptSnapshot("${specifier}")`);
|
||||
}
|
||||
const sourceFile = sourceFileCache.get(specifier);
|
||||
if (sourceFile) {
|
||||
if (!assetScopes.has(specifier)) {
|
||||
assetScopes.set(specifier, lastRequestScope);
|
||||
if (specifier.startsWith(ASSETS_URL_PREFIX)) {
|
||||
const sourceFile = this.getSourceFile(
|
||||
specifier,
|
||||
ts.ScriptTarget.ESNext,
|
||||
);
|
||||
if (sourceFile) {
|
||||
if (!assetScopes.has(specifier)) {
|
||||
assetScopes.set(specifier, lastRequestScope);
|
||||
}
|
||||
// This case only occurs for assets.
|
||||
return ts.ScriptSnapshot.fromString(sourceFile.text);
|
||||
}
|
||||
// This case only occurs for assets.
|
||||
return ts.ScriptSnapshot.fromString(sourceFile.text);
|
||||
}
|
||||
let sourceText = sourceTextCache.get(specifier);
|
||||
if (sourceText == undefined) {
|
||||
|
@ -845,6 +850,8 @@ delete Object.prototype.__proto__;
|
|||
jqueryMessage,
|
||||
"Cannot_find_name_0_Do_you_need_to_install_type_definitions_for_jQuery_Try_npm_i_save_dev_types_Slash_2592":
|
||||
jqueryMessage,
|
||||
"Module_0_was_resolved_to_1_but_allowArbitraryExtensions_is_not_set_6263":
|
||||
"Module '{0}' was resolved to '{1}', but importing these modules is not supported.",
|
||||
};
|
||||
})());
|
||||
|
||||
|
|
|
@ -323,7 +323,7 @@ impl Diagnostics {
|
|||
// todo(dsherret): use a short lived cache to prevent parsing
|
||||
// source maps so often
|
||||
if let Ok(source_map) =
|
||||
SourceMap::from_slice(&fast_check_module.source_map)
|
||||
SourceMap::from_slice(fast_check_module.source_map.as_bytes())
|
||||
{
|
||||
if let Some(start) = d.start.as_mut() {
|
||||
let maybe_token = source_map
|
||||
|
|
37
cli/tsc/dts/lib.deno.ns.d.ts
vendored
37
cli/tsc/dts/lib.deno.ns.d.ts
vendored
|
@ -556,14 +556,23 @@ declare namespace Deno {
|
|||
*/
|
||||
env?: "inherit" | boolean | string[];
|
||||
|
||||
/** Specifies if the `sys` permission should be requested or revoked.
|
||||
* If set to `"inherit"`, the current `sys` permission will be inherited.
|
||||
* If set to `true`, the global `sys` permission will be requested.
|
||||
* If set to `false`, the global `sys` permission will be revoked.
|
||||
/** Specifies if the `ffi` permission should be requested or revoked.
|
||||
* If set to `"inherit"`, the current `ffi` permission will be inherited.
|
||||
* If set to `true`, the global `ffi` permission will be requested.
|
||||
* If set to `false`, the global `ffi` permission will be revoked.
|
||||
*
|
||||
* @default {false}
|
||||
*/
|
||||
sys?: "inherit" | boolean | string[];
|
||||
ffi?: "inherit" | boolean | Array<string | URL>;
|
||||
|
||||
/** Specifies if the `import` permission should be requested or revoked.
|
||||
* If set to `"inherit"` the current `import` permission will be inherited.
|
||||
* If set to `true`, the global `import` permission will be requested.
|
||||
* If set to `false`, the global `import` permission will be revoked.
|
||||
* If set to `Array<string>`, the `import` permissions will be requested with the
|
||||
* specified domains.
|
||||
*/
|
||||
import?: "inherit" | boolean | Array<string>;
|
||||
|
||||
/** Specifies if the `net` permission should be requested or revoked.
|
||||
* if set to `"inherit"`, the current `net` permission will be inherited.
|
||||
|
@ -638,15 +647,6 @@ declare namespace Deno {
|
|||
*/
|
||||
net?: "inherit" | boolean | string[];
|
||||
|
||||
/** Specifies if the `ffi` permission should be requested or revoked.
|
||||
* If set to `"inherit"`, the current `ffi` permission will be inherited.
|
||||
* If set to `true`, the global `ffi` permission will be requested.
|
||||
* If set to `false`, the global `ffi` permission will be revoked.
|
||||
*
|
||||
* @default {false}
|
||||
*/
|
||||
ffi?: "inherit" | boolean | Array<string | URL>;
|
||||
|
||||
/** Specifies if the `read` permission should be requested or revoked.
|
||||
* If set to `"inherit"`, the current `read` permission will be inherited.
|
||||
* If set to `true`, the global `read` permission will be requested.
|
||||
|
@ -667,6 +667,15 @@ declare namespace Deno {
|
|||
*/
|
||||
run?: "inherit" | boolean | Array<string | URL>;
|
||||
|
||||
/** Specifies if the `sys` permission should be requested or revoked.
|
||||
* If set to `"inherit"`, the current `sys` permission will be inherited.
|
||||
* If set to `true`, the global `sys` permission will be requested.
|
||||
* If set to `false`, the global `sys` permission will be revoked.
|
||||
*
|
||||
* @default {false}
|
||||
*/
|
||||
sys?: "inherit" | boolean | string[];
|
||||
|
||||
/** Specifies if the `write` permission should be requested or revoked.
|
||||
* If set to `"inherit"`, the current `write` permission will be inherited.
|
||||
* If set to `true`, the global `write` permission will be requested.
|
||||
|
|
153
cli/tsc/mod.rs
153
cli/tsc/mod.rs
|
@ -3,9 +3,11 @@
|
|||
use crate::args::TsConfig;
|
||||
use crate::args::TypeCheckMode;
|
||||
use crate::cache::FastInsecureHasher;
|
||||
use crate::cache::ModuleInfoCache;
|
||||
use crate::node;
|
||||
use crate::npm::CliNpmResolver;
|
||||
use crate::npm::ResolvePkgFolderFromDenoReqError;
|
||||
use crate::resolver::CjsTracker;
|
||||
use crate::util::checksum;
|
||||
use crate::util::path::mapped_specifier_for_tsc;
|
||||
|
||||
|
@ -32,13 +34,13 @@ use deno_graph::GraphKind;
|
|||
use deno_graph::Module;
|
||||
use deno_graph::ModuleGraph;
|
||||
use deno_graph::ResolutionResolved;
|
||||
use deno_runtime::deno_fs;
|
||||
use deno_runtime::deno_node::NodeResolver;
|
||||
use deno_semver::npm::NpmPackageReqReference;
|
||||
use node_resolver::errors::NodeJsErrorCode;
|
||||
use node_resolver::errors::NodeJsErrorCoded;
|
||||
use node_resolver::errors::ResolvePkgSubpathFromDenoModuleError;
|
||||
use node_resolver::errors::PackageSubpathResolveError;
|
||||
use node_resolver::NodeModuleKind;
|
||||
use node_resolver::NodeResolution;
|
||||
use node_resolver::NodeResolutionMode;
|
||||
use once_cell::sync::Lazy;
|
||||
use std::borrow::Cow;
|
||||
|
@ -302,8 +304,76 @@ pub struct EmittedFile {
|
|||
pub media_type: MediaType,
|
||||
}
|
||||
|
||||
pub fn into_specifier_and_media_type(
|
||||
specifier: Option<ModuleSpecifier>,
|
||||
) -> (ModuleSpecifier, MediaType) {
|
||||
match specifier {
|
||||
Some(specifier) => {
|
||||
let media_type = MediaType::from_specifier(&specifier);
|
||||
|
||||
(specifier, media_type)
|
||||
}
|
||||
None => (
|
||||
Url::parse("internal:///missing_dependency.d.ts").unwrap(),
|
||||
MediaType::Dts,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct TypeCheckingCjsTracker {
|
||||
cjs_tracker: Arc<CjsTracker>,
|
||||
module_info_cache: Arc<ModuleInfoCache>,
|
||||
}
|
||||
|
||||
impl TypeCheckingCjsTracker {
|
||||
pub fn new(
|
||||
cjs_tracker: Arc<CjsTracker>,
|
||||
module_info_cache: Arc<ModuleInfoCache>,
|
||||
) -> Self {
|
||||
Self {
|
||||
cjs_tracker,
|
||||
module_info_cache,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_cjs(
|
||||
&self,
|
||||
specifier: &ModuleSpecifier,
|
||||
media_type: MediaType,
|
||||
code: &Arc<str>,
|
||||
) -> bool {
|
||||
if let Some(module_kind) =
|
||||
self.cjs_tracker.get_known_kind(specifier, media_type)
|
||||
{
|
||||
module_kind.is_cjs()
|
||||
} else {
|
||||
let maybe_is_script = self
|
||||
.module_info_cache
|
||||
.as_module_analyzer()
|
||||
.analyze_sync(specifier, media_type, code)
|
||||
.ok()
|
||||
.map(|info| info.is_script);
|
||||
maybe_is_script
|
||||
.and_then(|is_script| {
|
||||
self
|
||||
.cjs_tracker
|
||||
.is_cjs_with_known_is_script(specifier, media_type, is_script)
|
||||
.ok()
|
||||
})
|
||||
.unwrap_or_else(|| {
|
||||
self
|
||||
.cjs_tracker
|
||||
.is_maybe_cjs(specifier, media_type)
|
||||
.unwrap_or(false)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct RequestNpmState {
|
||||
pub cjs_tracker: Arc<TypeCheckingCjsTracker>,
|
||||
pub node_resolver: Arc<NodeResolver>,
|
||||
pub npm_resolver: Arc<dyn CliNpmResolver>,
|
||||
}
|
||||
|
@ -456,7 +526,7 @@ pub fn as_ts_script_kind(media_type: MediaType) -> i32 {
|
|||
MediaType::Tsx => 4,
|
||||
MediaType::Json => 6,
|
||||
MediaType::SourceMap
|
||||
| MediaType::TsBuildInfo
|
||||
| MediaType::Css
|
||||
| MediaType::Wasm
|
||||
| MediaType::Unknown => 0,
|
||||
}
|
||||
|
@ -489,25 +559,22 @@ fn op_load_inner(
|
|||
) -> Result<Option<LoadResponse>, AnyError> {
|
||||
fn load_from_node_modules(
|
||||
specifier: &ModuleSpecifier,
|
||||
node_resolver: Option<&NodeResolver>,
|
||||
npm_state: Option<&RequestNpmState>,
|
||||
media_type: &mut MediaType,
|
||||
is_cjs: &mut bool,
|
||||
) -> Result<String, AnyError> {
|
||||
*media_type = MediaType::from_specifier(specifier);
|
||||
*is_cjs = node_resolver
|
||||
.map(|node_resolver| {
|
||||
match node_resolver.url_to_node_resolution(specifier.clone()) {
|
||||
Ok(NodeResolution::CommonJs(_)) => true,
|
||||
Ok(NodeResolution::Esm(_))
|
||||
| Ok(NodeResolution::BuiltIn(_))
|
||||
| Err(_) => false,
|
||||
}
|
||||
})
|
||||
.unwrap_or(false);
|
||||
let file_path = specifier.to_file_path().unwrap();
|
||||
let code = std::fs::read_to_string(&file_path)
|
||||
.with_context(|| format!("Unable to load {}", file_path.display()))?;
|
||||
Ok(code)
|
||||
let code: Arc<str> = code.into();
|
||||
*is_cjs = npm_state
|
||||
.map(|npm_state| {
|
||||
npm_state.cjs_tracker.is_cjs(specifier, *media_type, &code)
|
||||
})
|
||||
.unwrap_or(false);
|
||||
// todo(dsherret): how to avoid cloning here?
|
||||
Ok(code.to_string())
|
||||
}
|
||||
|
||||
let state = state.borrow_mut::<State>();
|
||||
|
@ -560,6 +627,9 @@ fn op_load_inner(
|
|||
match module {
|
||||
Module::Js(module) => {
|
||||
media_type = module.media_type;
|
||||
if matches!(media_type, MediaType::Cjs | MediaType::Cts) {
|
||||
is_cjs = true;
|
||||
}
|
||||
let source = module
|
||||
.fast_check_module()
|
||||
.map(|m| &*m.source)
|
||||
|
@ -573,11 +643,13 @@ fn op_load_inner(
|
|||
Module::Npm(_) | Module::Node(_) => None,
|
||||
Module::External(module) => {
|
||||
// means it's Deno code importing an npm module
|
||||
let specifier =
|
||||
node::resolve_specifier_into_node_modules(&module.specifier);
|
||||
let specifier = node::resolve_specifier_into_node_modules(
|
||||
&module.specifier,
|
||||
&deno_fs::RealFs,
|
||||
);
|
||||
Some(Cow::Owned(load_from_node_modules(
|
||||
&specifier,
|
||||
state.maybe_npm.as_ref().map(|n| n.node_resolver.as_ref()),
|
||||
state.maybe_npm.as_ref(),
|
||||
&mut media_type,
|
||||
&mut is_cjs,
|
||||
)?))
|
||||
|
@ -590,7 +662,7 @@ fn op_load_inner(
|
|||
{
|
||||
Some(Cow::Owned(load_from_node_modules(
|
||||
specifier,
|
||||
Some(npm.node_resolver.as_ref()),
|
||||
Some(npm),
|
||||
&mut media_type,
|
||||
&mut is_cjs,
|
||||
)?))
|
||||
|
@ -739,7 +811,13 @@ fn op_resolve_inner(
|
|||
}
|
||||
}
|
||||
};
|
||||
(specifier_str, media_type.as_ts_extension())
|
||||
(
|
||||
specifier_str,
|
||||
match media_type {
|
||||
MediaType::Css => ".js", // surface these as .js for typescript
|
||||
media_type => media_type.as_ts_extension(),
|
||||
},
|
||||
)
|
||||
}
|
||||
None => (
|
||||
MISSING_DEPENDENCY_SPECIFIER.to_string(),
|
||||
|
@ -810,29 +888,27 @@ fn resolve_graph_specifier_types(
|
|||
Some(referrer),
|
||||
NodeResolutionMode::Types,
|
||||
);
|
||||
let maybe_resolution = match res_result {
|
||||
Ok(res) => Some(res),
|
||||
let maybe_url = match res_result {
|
||||
Ok(url) => Some(url),
|
||||
Err(err) => match err.code() {
|
||||
NodeJsErrorCode::ERR_TYPES_NOT_FOUND
|
||||
| NodeJsErrorCode::ERR_MODULE_NOT_FOUND => None,
|
||||
_ => return Err(err.into()),
|
||||
},
|
||||
};
|
||||
Ok(Some(NodeResolution::into_specifier_and_media_type(
|
||||
maybe_resolution,
|
||||
)))
|
||||
Ok(Some(into_specifier_and_media_type(maybe_url)))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
Some(Module::External(module)) => {
|
||||
// we currently only use "External" for when the module is in an npm package
|
||||
Ok(state.maybe_npm.as_ref().map(|npm| {
|
||||
let specifier =
|
||||
node::resolve_specifier_into_node_modules(&module.specifier);
|
||||
NodeResolution::into_specifier_and_media_type(
|
||||
npm.node_resolver.url_to_node_resolution(specifier).ok(),
|
||||
)
|
||||
Ok(state.maybe_npm.as_ref().map(|_| {
|
||||
let specifier = node::resolve_specifier_into_node_modules(
|
||||
&module.specifier,
|
||||
&deno_fs::RealFs,
|
||||
);
|
||||
into_specifier_and_media_type(Some(specifier))
|
||||
}))
|
||||
}
|
||||
Some(Module::Node(_)) | None => Ok(None),
|
||||
|
@ -844,7 +920,7 @@ enum ResolveNonGraphSpecifierTypesError {
|
|||
#[error(transparent)]
|
||||
ResolvePkgFolderFromDenoReq(#[from] ResolvePkgFolderFromDenoReqError),
|
||||
#[error(transparent)]
|
||||
ResolvePkgSubpathFromDenoModule(#[from] ResolvePkgSubpathFromDenoModuleError),
|
||||
PackageSubpathResolve(#[from] PackageSubpathResolveError),
|
||||
}
|
||||
|
||||
fn resolve_non_graph_specifier_types(
|
||||
|
@ -863,7 +939,7 @@ fn resolve_non_graph_specifier_types(
|
|||
let node_resolver = &npm.node_resolver;
|
||||
if node_resolver.in_npm_package(referrer) {
|
||||
// we're in an npm package, so use node resolution
|
||||
Ok(Some(NodeResolution::into_specifier_and_media_type(
|
||||
Ok(Some(into_specifier_and_media_type(
|
||||
node_resolver
|
||||
.resolve(
|
||||
raw_specifier,
|
||||
|
@ -871,7 +947,8 @@ fn resolve_non_graph_specifier_types(
|
|||
referrer_kind,
|
||||
NodeResolutionMode::Types,
|
||||
)
|
||||
.ok(),
|
||||
.ok()
|
||||
.map(|res| res.into_url()),
|
||||
)))
|
||||
} else if let Ok(npm_req_ref) =
|
||||
NpmPackageReqReference::from_str(raw_specifier)
|
||||
|
@ -890,17 +967,15 @@ fn resolve_non_graph_specifier_types(
|
|||
Some(referrer),
|
||||
NodeResolutionMode::Types,
|
||||
);
|
||||
let maybe_resolution = match res_result {
|
||||
Ok(res) => Some(res),
|
||||
let maybe_url = match res_result {
|
||||
Ok(url) => Some(url),
|
||||
Err(err) => match err.code() {
|
||||
NodeJsErrorCode::ERR_TYPES_NOT_FOUND
|
||||
| NodeJsErrorCode::ERR_MODULE_NOT_FOUND => None,
|
||||
_ => return Err(err.into()),
|
||||
},
|
||||
};
|
||||
Ok(Some(NodeResolution::into_specifier_and_media_type(
|
||||
maybe_resolution,
|
||||
)))
|
||||
Ok(Some(into_specifier_and_media_type(maybe_url)))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
|
|
|
@ -64,7 +64,7 @@ fn extract_inner(
|
|||
}) {
|
||||
Ok(parsed) => {
|
||||
let mut c = ExportCollector::default();
|
||||
c.visit_program(parsed.program_ref());
|
||||
c.visit_program(parsed.program().as_ref());
|
||||
c
|
||||
}
|
||||
Err(_) => ExportCollector::default(),
|
||||
|
@ -570,14 +570,14 @@ fn generate_pseudo_file(
|
|||
})?;
|
||||
|
||||
let top_level_atoms = swc_utils::collect_decls_with_ctxt::<Atom, _>(
|
||||
parsed.program_ref(),
|
||||
&parsed.program_ref(),
|
||||
parsed.top_level_context(),
|
||||
);
|
||||
|
||||
let transformed =
|
||||
parsed
|
||||
.program_ref()
|
||||
.clone()
|
||||
.to_owned()
|
||||
.fold_with(&mut as_folder(Transform {
|
||||
specifier: &file.specifier,
|
||||
base_file_specifier,
|
||||
|
@ -1416,7 +1416,7 @@ console.log(Foo);
|
|||
})
|
||||
.unwrap();
|
||||
|
||||
collector.visit_program(parsed.program_ref());
|
||||
parsed.program_ref().visit_with(&mut collector);
|
||||
collector
|
||||
}
|
||||
|
||||
|
|
|
@ -565,7 +565,9 @@ pub fn symlink_dir(oldpath: &Path, newpath: &Path) -> Result<(), Error> {
|
|||
use std::os::windows::fs::symlink_dir;
|
||||
symlink_dir(oldpath, newpath).map_err(|err| {
|
||||
if let Some(code) = err.raw_os_error() {
|
||||
if code as u32 == winapi::shared::winerror::ERROR_PRIVILEGE_NOT_HELD {
|
||||
if code as u32 == winapi::shared::winerror::ERROR_PRIVILEGE_NOT_HELD
|
||||
|| code as u32 == winapi::shared::winerror::ERROR_INVALID_FUNCTION
|
||||
{
|
||||
return err_mapper(err, Some(ErrorKind::PermissionDenied));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -65,6 +65,8 @@ pub fn init(maybe_level: Option<log::Level>) {
|
|||
.filter_module("swc_ecma_parser", log::LevelFilter::Error)
|
||||
// Suppress span lifecycle logs since they are too verbose
|
||||
.filter_module("tracing::span", log::LevelFilter::Off)
|
||||
// for deno_compile, this is too verbose
|
||||
.filter_module("editpe", log::LevelFilter::Error)
|
||||
.format(|buf, record| {
|
||||
let mut target = record.target().to_string();
|
||||
if let Some(line_no) = record.line() {
|
||||
|
|
|
@ -42,21 +42,6 @@ pub fn get_extension(file_path: &Path) -> Option<String> {
|
|||
.map(|e| e.to_lowercase());
|
||||
}
|
||||
|
||||
pub fn specifier_has_extension(
|
||||
specifier: &ModuleSpecifier,
|
||||
searching_ext: &str,
|
||||
) -> bool {
|
||||
let Some((_, ext)) = specifier.path().rsplit_once('.') else {
|
||||
return false;
|
||||
};
|
||||
let searching_ext = searching_ext.strip_prefix('.').unwrap_or(searching_ext);
|
||||
debug_assert!(!searching_ext.contains('.')); // exts like .d.ts are not implemented here
|
||||
if ext.len() != searching_ext.len() {
|
||||
return false;
|
||||
}
|
||||
ext.eq_ignore_ascii_case(searching_ext)
|
||||
}
|
||||
|
||||
pub fn get_atomic_dir_path(file_path: &Path) -> PathBuf {
|
||||
let rand = gen_rand_path_component();
|
||||
let new_file_name = format!(
|
||||
|
@ -350,18 +335,6 @@ mod test {
|
|||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_specifier_has_extension() {
|
||||
fn get(specifier: &str, ext: &str) -> bool {
|
||||
specifier_has_extension(&ModuleSpecifier::parse(specifier).unwrap(), ext)
|
||||
}
|
||||
|
||||
assert!(get("file:///a/b/c.ts", "ts"));
|
||||
assert!(get("file:///a/b/c.ts", ".ts"));
|
||||
assert!(!get("file:///a/b/c.ts", ".cts"));
|
||||
assert!(get("file:///a/b/c.CtS", ".cts"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_to_percent_decoded_str() {
|
||||
let str = to_percent_decoded_str("%F0%9F%A6%95");
|
||||
|
|
|
@ -193,10 +193,16 @@ impl ProgressBarRenderer for TextOnlyProgressBarRenderer {
|
|||
}
|
||||
};
|
||||
|
||||
// TODO(@marvinhagemeister): We're trying to reconstruct the original
|
||||
// specifier from the resolved one, but we lack the information about
|
||||
// private registries URLs and other things here.
|
||||
let message = display_entry
|
||||
.message
|
||||
.replace("https://registry.npmjs.org/", "npm:")
|
||||
.replace("https://jsr.io/", "jsr:");
|
||||
.replace("https://jsr.io/", "jsr:")
|
||||
.replace("%2f", "/")
|
||||
.replace("%2F", "/");
|
||||
|
||||
display_str.push_str(
|
||||
&colors::gray(format!(" - {}{}\n", message, bytes_text)).to_string(),
|
||||
);
|
||||
|
|
|
@ -97,6 +97,7 @@ fn find_source_map_range(code: &[u8]) -> Option<Range<usize>> {
|
|||
}
|
||||
|
||||
/// Converts an `Arc<str>` to an `Arc<[u8]>`.
|
||||
#[allow(dead_code)]
|
||||
pub fn arc_str_to_bytes(arc_str: Arc<str>) -> Arc<[u8]> {
|
||||
let raw = Arc::into_raw(arc_str);
|
||||
// SAFETY: This is safe because they have the same memory layout.
|
||||
|
|
171
cli/worker.rs
171
cli/worker.rs
|
@ -14,16 +14,17 @@ use deno_core::v8;
|
|||
use deno_core::CompiledWasmModuleStore;
|
||||
use deno_core::Extension;
|
||||
use deno_core::FeatureChecker;
|
||||
use deno_core::ModuleId;
|
||||
use deno_core::ModuleLoader;
|
||||
use deno_core::PollEventLoopOptions;
|
||||
use deno_core::SharedArrayBufferStore;
|
||||
use deno_runtime::code_cache;
|
||||
use deno_runtime::deno_broadcast_channel::InMemoryBroadcastChannel;
|
||||
use deno_runtime::deno_fs;
|
||||
use deno_runtime::deno_node;
|
||||
use deno_runtime::deno_node::NodeExtInitServices;
|
||||
use deno_runtime::deno_node::NodeRequireLoader;
|
||||
use deno_runtime::deno_node::NodeRequireLoaderRc;
|
||||
use deno_runtime::deno_node::NodeResolver;
|
||||
use deno_runtime::deno_node::PackageJsonResolver;
|
||||
use deno_runtime::deno_permissions::PermissionsContainer;
|
||||
use deno_runtime::deno_tls::RootCertStoreProvider;
|
||||
use deno_runtime::deno_web::BlobStore;
|
||||
|
@ -42,7 +43,6 @@ use deno_runtime::WorkerExecutionMode;
|
|||
use deno_runtime::WorkerLogLevel;
|
||||
use deno_semver::npm::NpmPackageReqReference;
|
||||
use deno_terminal::colors;
|
||||
use node_resolver::NodeResolution;
|
||||
use node_resolver::NodeResolutionMode;
|
||||
use tokio::select;
|
||||
|
||||
|
@ -51,28 +51,27 @@ use crate::args::DenoSubcommand;
|
|||
use crate::args::StorageKeyResolver;
|
||||
use crate::errors;
|
||||
use crate::npm::CliNpmResolver;
|
||||
use crate::resolver::CjsResolutionStore;
|
||||
use crate::util::checksum;
|
||||
use crate::util::file_watcher::WatcherCommunicator;
|
||||
use crate::util::file_watcher::WatcherRestartMode;
|
||||
use crate::util::path::specifier_has_extension;
|
||||
use crate::version;
|
||||
|
||||
pub struct ModuleLoaderAndSourceMapGetter {
|
||||
pub struct CreateModuleLoaderResult {
|
||||
pub module_loader: Rc<dyn ModuleLoader>,
|
||||
pub node_require_loader: Rc<dyn NodeRequireLoader>,
|
||||
}
|
||||
|
||||
pub trait ModuleLoaderFactory: Send + Sync {
|
||||
fn create_for_main(
|
||||
&self,
|
||||
root_permissions: PermissionsContainer,
|
||||
) -> ModuleLoaderAndSourceMapGetter;
|
||||
) -> CreateModuleLoaderResult;
|
||||
|
||||
fn create_for_worker(
|
||||
&self,
|
||||
parent_permissions: PermissionsContainer,
|
||||
permissions: PermissionsContainer,
|
||||
) -> ModuleLoaderAndSourceMapGetter;
|
||||
) -> CreateModuleLoaderResult;
|
||||
}
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
|
@ -109,7 +108,6 @@ pub struct CliMainWorkerOptions {
|
|||
pub inspect_wait: bool,
|
||||
pub strace_ops: Option<Vec<String>>,
|
||||
pub is_inspecting: bool,
|
||||
pub is_npm_main: bool,
|
||||
pub location: Option<Url>,
|
||||
pub argv0: Option<String>,
|
||||
pub node_debug: Option<String>,
|
||||
|
@ -122,13 +120,11 @@ pub struct CliMainWorkerOptions {
|
|||
pub node_ipc: Option<i64>,
|
||||
pub serve_port: Option<u16>,
|
||||
pub serve_host: Option<String>,
|
||||
pub unstable_detect_cjs: bool,
|
||||
}
|
||||
|
||||
struct SharedWorkerState {
|
||||
blob_store: Arc<BlobStore>,
|
||||
broadcast_channel: InMemoryBroadcastChannel,
|
||||
cjs_resolution_store: Arc<CjsResolutionStore>,
|
||||
code_cache: Option<Arc<dyn code_cache::CodeCache>>,
|
||||
compiled_wasm_module_store: CompiledWasmModuleStore,
|
||||
feature_checker: Arc<FeatureChecker>,
|
||||
|
@ -139,6 +135,7 @@ struct SharedWorkerState {
|
|||
module_loader_factory: Box<dyn ModuleLoaderFactory>,
|
||||
node_resolver: Arc<NodeResolver>,
|
||||
npm_resolver: Arc<dyn CliNpmResolver>,
|
||||
pkg_json_resolver: Arc<PackageJsonResolver>,
|
||||
root_cert_store_provider: Arc<dyn RootCertStoreProvider>,
|
||||
root_permissions: PermissionsContainer,
|
||||
shared_array_buffer_store: SharedArrayBufferStore,
|
||||
|
@ -148,11 +145,15 @@ struct SharedWorkerState {
|
|||
}
|
||||
|
||||
impl SharedWorkerState {
|
||||
pub fn create_node_init_services(&self) -> NodeExtInitServices {
|
||||
pub fn create_node_init_services(
|
||||
&self,
|
||||
node_require_loader: NodeRequireLoaderRc,
|
||||
) -> NodeExtInitServices {
|
||||
NodeExtInitServices {
|
||||
node_require_resolver: self.npm_resolver.clone().into_require_resolver(),
|
||||
node_require_loader,
|
||||
node_resolver: self.node_resolver.clone(),
|
||||
npm_resolver: self.npm_resolver.clone().into_npm_resolver(),
|
||||
pkg_json_resolver: self.pkg_json_resolver.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -163,7 +164,6 @@ impl SharedWorkerState {
|
|||
|
||||
pub struct CliMainWorker {
|
||||
main_module: ModuleSpecifier,
|
||||
is_main_cjs: bool,
|
||||
worker: MainWorker,
|
||||
shared: Arc<SharedWorkerState>,
|
||||
}
|
||||
|
@ -185,17 +185,7 @@ impl CliMainWorker {
|
|||
|
||||
log::debug!("main_module {}", self.main_module);
|
||||
|
||||
if self.is_main_cjs {
|
||||
deno_node::load_cjs_module(
|
||||
&mut self.worker.js_runtime,
|
||||
&self.main_module.to_file_path().unwrap().to_string_lossy(),
|
||||
true,
|
||||
self.shared.options.inspect_brk,
|
||||
)?;
|
||||
} else {
|
||||
self.execute_main_module_possibly_with_npm().await?;
|
||||
}
|
||||
|
||||
self.execute_main_module().await?;
|
||||
self.worker.dispatch_load_event()?;
|
||||
|
||||
loop {
|
||||
|
@ -283,22 +273,7 @@ impl CliMainWorker {
|
|||
/// Execute the given main module emitting load and unload events before and after execution
|
||||
/// respectively.
|
||||
pub async fn execute(&mut self) -> Result<(), AnyError> {
|
||||
if self.inner.is_main_cjs {
|
||||
deno_node::load_cjs_module(
|
||||
&mut self.inner.worker.js_runtime,
|
||||
&self
|
||||
.inner
|
||||
.main_module
|
||||
.to_file_path()
|
||||
.unwrap()
|
||||
.to_string_lossy(),
|
||||
true,
|
||||
self.inner.shared.options.inspect_brk,
|
||||
)?;
|
||||
} else {
|
||||
self.inner.execute_main_module_possibly_with_npm().await?;
|
||||
}
|
||||
|
||||
self.inner.execute_main_module().await?;
|
||||
self.inner.worker.dispatch_load_event()?;
|
||||
self.pending_unload = true;
|
||||
|
||||
|
@ -339,24 +314,13 @@ impl CliMainWorker {
|
|||
executor.execute().await
|
||||
}
|
||||
|
||||
pub async fn execute_main_module_possibly_with_npm(
|
||||
&mut self,
|
||||
) -> Result<(), AnyError> {
|
||||
pub async fn execute_main_module(&mut self) -> Result<(), AnyError> {
|
||||
let id = self.worker.preload_main_module(&self.main_module).await?;
|
||||
self.evaluate_module_possibly_with_npm(id).await
|
||||
self.worker.evaluate_module(id).await
|
||||
}
|
||||
|
||||
pub async fn execute_side_module_possibly_with_npm(
|
||||
&mut self,
|
||||
) -> Result<(), AnyError> {
|
||||
pub async fn execute_side_module(&mut self) -> Result<(), AnyError> {
|
||||
let id = self.worker.preload_side_module(&self.main_module).await?;
|
||||
self.evaluate_module_possibly_with_npm(id).await
|
||||
}
|
||||
|
||||
async fn evaluate_module_possibly_with_npm(
|
||||
&mut self,
|
||||
id: ModuleId,
|
||||
) -> Result<(), AnyError> {
|
||||
self.worker.evaluate_module(id).await
|
||||
}
|
||||
|
||||
|
@ -426,7 +390,6 @@ impl CliMainWorkerFactory {
|
|||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn new(
|
||||
blob_store: Arc<BlobStore>,
|
||||
cjs_resolution_store: Arc<CjsResolutionStore>,
|
||||
code_cache: Option<Arc<dyn code_cache::CodeCache>>,
|
||||
feature_checker: Arc<FeatureChecker>,
|
||||
fs: Arc<dyn deno_fs::FileSystem>,
|
||||
|
@ -436,6 +399,7 @@ impl CliMainWorkerFactory {
|
|||
module_loader_factory: Box<dyn ModuleLoaderFactory>,
|
||||
node_resolver: Arc<NodeResolver>,
|
||||
npm_resolver: Arc<dyn CliNpmResolver>,
|
||||
pkg_json_resolver: Arc<PackageJsonResolver>,
|
||||
root_cert_store_provider: Arc<dyn RootCertStoreProvider>,
|
||||
root_permissions: PermissionsContainer,
|
||||
storage_key_resolver: StorageKeyResolver,
|
||||
|
@ -446,7 +410,6 @@ impl CliMainWorkerFactory {
|
|||
shared: Arc::new(SharedWorkerState {
|
||||
blob_store,
|
||||
broadcast_channel: Default::default(),
|
||||
cjs_resolution_store,
|
||||
code_cache,
|
||||
compiled_wasm_module_store: Default::default(),
|
||||
feature_checker,
|
||||
|
@ -457,6 +420,7 @@ impl CliMainWorkerFactory {
|
|||
module_loader_factory,
|
||||
node_resolver,
|
||||
npm_resolver,
|
||||
pkg_json_resolver,
|
||||
root_cert_store_provider,
|
||||
root_permissions,
|
||||
shared_array_buffer_store: Default::default(),
|
||||
|
@ -492,10 +456,13 @@ impl CliMainWorkerFactory {
|
|||
stdio: deno_runtime::deno_io::Stdio,
|
||||
) -> Result<CliMainWorker, AnyError> {
|
||||
let shared = &self.shared;
|
||||
let ModuleLoaderAndSourceMapGetter { module_loader } = shared
|
||||
let CreateModuleLoaderResult {
|
||||
module_loader,
|
||||
node_require_loader,
|
||||
} = shared
|
||||
.module_loader_factory
|
||||
.create_for_main(permissions.clone());
|
||||
let (main_module, is_main_cjs) = if let Ok(package_ref) =
|
||||
let main_module = if let Ok(package_ref) =
|
||||
NpmPackageReqReference::from_specifier(&main_module)
|
||||
{
|
||||
if let Some(npm_resolver) = shared.npm_resolver.as_managed() {
|
||||
|
@ -515,9 +482,8 @@ impl CliMainWorkerFactory {
|
|||
package_ref.req(),
|
||||
&referrer,
|
||||
)?;
|
||||
let node_resolution = self
|
||||
let main_module = self
|
||||
.resolve_binary_entrypoint(&package_folder, package_ref.sub_path())?;
|
||||
let is_main_cjs = matches!(node_resolution, NodeResolution::CommonJs(_));
|
||||
|
||||
if let Some(lockfile) = &shared.maybe_lockfile {
|
||||
// For npm binary commands, ensure that the lockfile gets updated
|
||||
|
@ -526,36 +492,9 @@ impl CliMainWorkerFactory {
|
|||
lockfile.write_if_changed()?;
|
||||
}
|
||||
|
||||
(node_resolution.into_url(), is_main_cjs)
|
||||
} else if shared.options.is_npm_main
|
||||
|| shared.node_resolver.in_npm_package(&main_module)
|
||||
{
|
||||
let node_resolution =
|
||||
shared.node_resolver.url_to_node_resolution(main_module)?;
|
||||
let is_main_cjs = matches!(node_resolution, NodeResolution::CommonJs(_));
|
||||
(node_resolution.into_url(), is_main_cjs)
|
||||
main_module
|
||||
} else {
|
||||
let is_maybe_cjs_js_ext = self.shared.options.unstable_detect_cjs
|
||||
&& specifier_has_extension(&main_module, "js")
|
||||
&& self
|
||||
.shared
|
||||
.node_resolver
|
||||
.get_closest_package_json(&main_module)
|
||||
.ok()
|
||||
.flatten()
|
||||
.map(|pkg_json| pkg_json.typ == "commonjs")
|
||||
.unwrap_or(false);
|
||||
let is_cjs = if is_maybe_cjs_js_ext {
|
||||
// fill the cjs resolution store by preparing the module load
|
||||
module_loader
|
||||
.prepare_load(&main_module, None, false)
|
||||
.await?;
|
||||
self.shared.cjs_resolution_store.is_known_cjs(&main_module)
|
||||
} else {
|
||||
main_module.scheme() == "file"
|
||||
&& specifier_has_extension(&main_module, "cjs")
|
||||
};
|
||||
(main_module, is_cjs)
|
||||
main_module
|
||||
};
|
||||
|
||||
let maybe_inspector_server = shared.maybe_inspector_server.clone();
|
||||
|
@ -597,7 +536,9 @@ impl CliMainWorkerFactory {
|
|||
root_cert_store_provider: Some(shared.root_cert_store_provider.clone()),
|
||||
module_loader,
|
||||
fs: shared.fs.clone(),
|
||||
node_services: Some(shared.create_node_init_services()),
|
||||
node_services: Some(
|
||||
shared.create_node_init_services(node_require_loader),
|
||||
),
|
||||
npm_process_state_provider: Some(shared.npm_process_state_provider()),
|
||||
blob_store: shared.blob_store.clone(),
|
||||
broadcast_channel: shared.broadcast_channel.clone(),
|
||||
|
@ -682,7 +623,6 @@ impl CliMainWorkerFactory {
|
|||
|
||||
Ok(CliMainWorker {
|
||||
main_module,
|
||||
is_main_cjs,
|
||||
worker,
|
||||
shared: shared.clone(),
|
||||
})
|
||||
|
@ -692,19 +632,19 @@ impl CliMainWorkerFactory {
|
|||
&self,
|
||||
package_folder: &Path,
|
||||
sub_path: Option<&str>,
|
||||
) -> Result<NodeResolution, AnyError> {
|
||||
) -> Result<ModuleSpecifier, AnyError> {
|
||||
match self
|
||||
.shared
|
||||
.node_resolver
|
||||
.resolve_binary_export(package_folder, sub_path)
|
||||
{
|
||||
Ok(node_resolution) => Ok(node_resolution),
|
||||
Ok(specifier) => Ok(specifier),
|
||||
Err(original_err) => {
|
||||
// if the binary entrypoint was not found, fallback to regular node resolution
|
||||
let result =
|
||||
self.resolve_binary_entrypoint_fallback(package_folder, sub_path);
|
||||
match result {
|
||||
Ok(Some(resolution)) => Ok(resolution),
|
||||
Ok(Some(specifier)) => Ok(specifier),
|
||||
Ok(None) => Err(original_err.into()),
|
||||
Err(fallback_err) => {
|
||||
bail!("{:#}\n\nFallback failed: {:#}", original_err, fallback_err)
|
||||
|
@ -719,7 +659,7 @@ impl CliMainWorkerFactory {
|
|||
&self,
|
||||
package_folder: &Path,
|
||||
sub_path: Option<&str>,
|
||||
) -> Result<Option<NodeResolution>, AnyError> {
|
||||
) -> Result<Option<ModuleSpecifier>, AnyError> {
|
||||
// only fallback if the user specified a sub path
|
||||
if sub_path.is_none() {
|
||||
// it's confusing to users if the package doesn't have any binary
|
||||
|
@ -728,7 +668,7 @@ impl CliMainWorkerFactory {
|
|||
return Ok(None);
|
||||
}
|
||||
|
||||
let resolution = self
|
||||
let specifier = self
|
||||
.shared
|
||||
.node_resolver
|
||||
.resolve_package_subpath_from_deno_module(
|
||||
|
@ -737,19 +677,14 @@ impl CliMainWorkerFactory {
|
|||
/* referrer */ None,
|
||||
NodeResolutionMode::Execution,
|
||||
)?;
|
||||
match &resolution {
|
||||
NodeResolution::BuiltIn(_) => Ok(None),
|
||||
NodeResolution::CommonJs(specifier) | NodeResolution::Esm(specifier) => {
|
||||
if specifier
|
||||
.to_file_path()
|
||||
.map(|p| p.exists())
|
||||
.unwrap_or(false)
|
||||
{
|
||||
Ok(Some(resolution))
|
||||
} else {
|
||||
bail!("Cannot find module '{}'", specifier)
|
||||
}
|
||||
}
|
||||
if specifier
|
||||
.to_file_path()
|
||||
.map(|p| p.exists())
|
||||
.unwrap_or(false)
|
||||
{
|
||||
Ok(Some(specifier))
|
||||
} else {
|
||||
bail!("Cannot find module '{}'", specifier)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -761,11 +696,13 @@ fn create_web_worker_callback(
|
|||
Arc::new(move |args| {
|
||||
let maybe_inspector_server = shared.maybe_inspector_server.clone();
|
||||
|
||||
let ModuleLoaderAndSourceMapGetter { module_loader } =
|
||||
shared.module_loader_factory.create_for_worker(
|
||||
args.parent_permissions.clone(),
|
||||
args.permissions.clone(),
|
||||
);
|
||||
let CreateModuleLoaderResult {
|
||||
module_loader,
|
||||
node_require_loader,
|
||||
} = shared.module_loader_factory.create_for_worker(
|
||||
args.parent_permissions.clone(),
|
||||
args.permissions.clone(),
|
||||
);
|
||||
let create_web_worker_cb =
|
||||
create_web_worker_callback(shared.clone(), stdio.clone());
|
||||
|
||||
|
@ -795,7 +732,9 @@ fn create_web_worker_callback(
|
|||
root_cert_store_provider: Some(shared.root_cert_store_provider.clone()),
|
||||
module_loader,
|
||||
fs: shared.fs.clone(),
|
||||
node_services: Some(shared.create_node_init_services()),
|
||||
node_services: Some(
|
||||
shared.create_node_init_services(node_require_loader),
|
||||
),
|
||||
blob_store: shared.blob_store.clone(),
|
||||
broadcast_channel: shared.broadcast_channel.clone(),
|
||||
shared_array_buffer_store: Some(shared.shared_array_buffer_store.clone()),
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
[package]
|
||||
name = "deno_broadcast_channel"
|
||||
version = "0.168.0"
|
||||
version = "0.170.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
|
2
ext/cache/Cargo.toml
vendored
2
ext/cache/Cargo.toml
vendored
|
@ -2,7 +2,7 @@
|
|||
|
||||
[package]
|
||||
name = "deno_cache"
|
||||
version = "0.106.0"
|
||||
version = "0.108.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
[package]
|
||||
name = "deno_canvas"
|
||||
version = "0.43.0"
|
||||
version = "0.45.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
[package]
|
||||
name = "deno_console"
|
||||
version = "0.174.0"
|
||||
version = "0.176.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
[package]
|
||||
name = "deno_cron"
|
||||
version = "0.54.0"
|
||||
version = "0.56.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
[package]
|
||||
name = "deno_crypto"
|
||||
version = "0.188.0"
|
||||
version = "0.190.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
[package]
|
||||
name = "deno_fetch"
|
||||
version = "0.198.0"
|
||||
version = "0.200.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
|
|
@ -39,6 +39,7 @@ use deno_core::OpState;
|
|||
use deno_core::RcRef;
|
||||
use deno_core::Resource;
|
||||
use deno_core::ResourceId;
|
||||
use deno_permissions::PermissionCheckError;
|
||||
use deno_tls::rustls::RootCertStore;
|
||||
use deno_tls::Proxy;
|
||||
use deno_tls::RootCertStoreProvider;
|
||||
|
@ -149,7 +150,7 @@ pub enum FetchError {
|
|||
#[error(transparent)]
|
||||
Resource(deno_core::error::AnyError),
|
||||
#[error(transparent)]
|
||||
Permission(deno_core::error::AnyError),
|
||||
Permission(#[from] PermissionCheckError),
|
||||
#[error("NetworkError when attempting to fetch resource")]
|
||||
NetworkError,
|
||||
#[error("Fetching files only supports the GET method: received {0}")]
|
||||
|
@ -346,13 +347,13 @@ pub trait FetchPermissions {
|
|||
&mut self,
|
||||
url: &Url,
|
||||
api_name: &str,
|
||||
) -> Result<(), deno_core::error::AnyError>;
|
||||
) -> Result<(), PermissionCheckError>;
|
||||
#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
|
||||
fn check_read<'a>(
|
||||
&mut self,
|
||||
p: &'a Path,
|
||||
api_name: &str,
|
||||
) -> Result<Cow<'a, Path>, deno_core::error::AnyError>;
|
||||
) -> Result<Cow<'a, Path>, PermissionCheckError>;
|
||||
}
|
||||
|
||||
impl FetchPermissions for deno_permissions::PermissionsContainer {
|
||||
|
@ -361,7 +362,7 @@ impl FetchPermissions for deno_permissions::PermissionsContainer {
|
|||
&mut self,
|
||||
url: &Url,
|
||||
api_name: &str,
|
||||
) -> Result<(), deno_core::error::AnyError> {
|
||||
) -> Result<(), PermissionCheckError> {
|
||||
deno_permissions::PermissionsContainer::check_net_url(self, url, api_name)
|
||||
}
|
||||
|
||||
|
@ -370,7 +371,7 @@ impl FetchPermissions for deno_permissions::PermissionsContainer {
|
|||
&mut self,
|
||||
path: &'a Path,
|
||||
api_name: &str,
|
||||
) -> Result<Cow<'a, Path>, deno_core::error::AnyError> {
|
||||
) -> Result<Cow<'a, Path>, PermissionCheckError> {
|
||||
deno_permissions::PermissionsContainer::check_read_path(
|
||||
self,
|
||||
path,
|
||||
|
@ -414,9 +415,7 @@ where
|
|||
"file" => {
|
||||
let path = url.to_file_path().map_err(|_| FetchError::NetworkError)?;
|
||||
let permissions = state.borrow_mut::<FP>();
|
||||
let path = permissions
|
||||
.check_read(&path, "fetch()")
|
||||
.map_err(FetchError::Permission)?;
|
||||
let path = permissions.check_read(&path, "fetch()")?;
|
||||
let url = match path {
|
||||
Cow::Owned(path) => Url::from_file_path(path).unwrap(),
|
||||
Cow::Borrowed(_) => url,
|
||||
|
@ -442,9 +441,7 @@ where
|
|||
}
|
||||
"http" | "https" => {
|
||||
let permissions = state.borrow_mut::<FP>();
|
||||
permissions
|
||||
.check_net_url(&url, "fetch()")
|
||||
.map_err(FetchError::Resource)?;
|
||||
permissions.check_net_url(&url, "fetch()")?;
|
||||
|
||||
let maybe_authority = extract_authority(&mut url);
|
||||
let uri = url
|
||||
|
@ -863,9 +860,7 @@ where
|
|||
if let Some(proxy) = args.proxy.clone() {
|
||||
let permissions = state.borrow_mut::<FP>();
|
||||
let url = Url::parse(&proxy.url)?;
|
||||
permissions
|
||||
.check_net_url(&url, "Deno.createHttpClient()")
|
||||
.map_err(FetchError::Permission)?;
|
||||
permissions.check_net_url(&url, "Deno.createHttpClient()")?;
|
||||
}
|
||||
|
||||
let options = state.borrow::<Options>();
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
[package]
|
||||
name = "deno_ffi"
|
||||
version = "0.161.0"
|
||||
version = "0.163.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
|
|
@ -32,7 +32,9 @@ pub enum CallError {
|
|||
#[error("Invalid FFI symbol name: '{0}'")]
|
||||
InvalidSymbol(String),
|
||||
#[error(transparent)]
|
||||
Permission(deno_core::error::AnyError),
|
||||
Permission(#[from] deno_permissions::PermissionCheckError),
|
||||
#[error(transparent)]
|
||||
Resource(deno_core::error::AnyError),
|
||||
#[error(transparent)]
|
||||
Callback(#[from] super::CallbackError),
|
||||
}
|
||||
|
@ -301,9 +303,7 @@ where
|
|||
{
|
||||
let mut state = state.borrow_mut();
|
||||
let permissions = state.borrow_mut::<FP>();
|
||||
permissions
|
||||
.check_partial_no_path()
|
||||
.map_err(CallError::Permission)?;
|
||||
permissions.check_partial_no_path()?;
|
||||
};
|
||||
|
||||
let symbol = PtrSymbol::new(pointer, &def)?;
|
||||
|
@ -347,7 +347,7 @@ pub fn op_ffi_call_nonblocking(
|
|||
let resource = state
|
||||
.resource_table
|
||||
.get::<DynamicLibraryResource>(rid)
|
||||
.map_err(CallError::Permission)?;
|
||||
.map_err(CallError::Resource)?;
|
||||
let symbols = &resource.symbols;
|
||||
*symbols
|
||||
.get(&symbol)
|
||||
|
@ -401,9 +401,7 @@ where
|
|||
{
|
||||
let mut state = state.borrow_mut();
|
||||
let permissions = state.borrow_mut::<FP>();
|
||||
permissions
|
||||
.check_partial_no_path()
|
||||
.map_err(CallError::Permission)?;
|
||||
permissions.check_partial_no_path()?;
|
||||
};
|
||||
|
||||
let symbol = PtrSymbol::new(pointer, &def)?;
|
||||
|
|
|
@ -38,7 +38,7 @@ pub enum CallbackError {
|
|||
#[error(transparent)]
|
||||
Resource(deno_core::error::AnyError),
|
||||
#[error(transparent)]
|
||||
Permission(deno_core::error::AnyError),
|
||||
Permission(#[from] deno_permissions::PermissionCheckError),
|
||||
#[error(transparent)]
|
||||
Other(deno_core::error::AnyError),
|
||||
}
|
||||
|
@ -572,9 +572,7 @@ where
|
|||
FP: FfiPermissions + 'static,
|
||||
{
|
||||
let permissions = state.borrow_mut::<FP>();
|
||||
permissions
|
||||
.check_partial_no_path()
|
||||
.map_err(CallbackError::Permission)?;
|
||||
permissions.check_partial_no_path()?;
|
||||
|
||||
let thread_id: u32 = LOCAL_THREAD_ID.with(|s| {
|
||||
let value = *s.borrow();
|
||||
|
|
|
@ -30,7 +30,7 @@ pub enum DlfcnError {
|
|||
#[error(transparent)]
|
||||
Dlopen(#[from] dlopen2::Error),
|
||||
#[error(transparent)]
|
||||
Permission(deno_core::error::AnyError),
|
||||
Permission(#[from] deno_permissions::PermissionCheckError),
|
||||
#[error(transparent)]
|
||||
Other(deno_core::error::AnyError),
|
||||
}
|
||||
|
@ -133,9 +133,7 @@ where
|
|||
FP: FfiPermissions + 'static,
|
||||
{
|
||||
let permissions = state.borrow_mut::<FP>();
|
||||
let path = permissions
|
||||
.check_partial_with_path(&args.path)
|
||||
.map_err(DlfcnError::Permission)?;
|
||||
let path = permissions.check_partial_with_path(&args.path)?;
|
||||
|
||||
let lib = Library::open(&path).map_err(|e| {
|
||||
dlopen2::Error::OpeningLibraryError(std::io::Error::new(
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
use deno_core::error::AnyError;
|
||||
|
||||
use std::mem::size_of;
|
||||
use std::os::raw::c_char;
|
||||
use std::os::raw::c_short;
|
||||
|
@ -31,6 +29,7 @@ use symbol::Symbol;
|
|||
|
||||
pub use call::CallError;
|
||||
pub use callback::CallbackError;
|
||||
use deno_permissions::PermissionCheckError;
|
||||
pub use dlfcn::DlfcnError;
|
||||
pub use ir::IRError;
|
||||
pub use r#static::StaticError;
|
||||
|
@ -48,17 +47,17 @@ const _: () = {
|
|||
pub const UNSTABLE_FEATURE_NAME: &str = "ffi";
|
||||
|
||||
pub trait FfiPermissions {
|
||||
fn check_partial_no_path(&mut self) -> Result<(), AnyError>;
|
||||
fn check_partial_no_path(&mut self) -> Result<(), PermissionCheckError>;
|
||||
#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
|
||||
fn check_partial_with_path(
|
||||
&mut self,
|
||||
path: &str,
|
||||
) -> Result<PathBuf, AnyError>;
|
||||
) -> Result<PathBuf, PermissionCheckError>;
|
||||
}
|
||||
|
||||
impl FfiPermissions for deno_permissions::PermissionsContainer {
|
||||
#[inline(always)]
|
||||
fn check_partial_no_path(&mut self) -> Result<(), AnyError> {
|
||||
fn check_partial_no_path(&mut self) -> Result<(), PermissionCheckError> {
|
||||
deno_permissions::PermissionsContainer::check_ffi_partial_no_path(self)
|
||||
}
|
||||
|
||||
|
@ -66,7 +65,7 @@ impl FfiPermissions for deno_permissions::PermissionsContainer {
|
|||
fn check_partial_with_path(
|
||||
&mut self,
|
||||
path: &str,
|
||||
) -> Result<PathBuf, AnyError> {
|
||||
) -> Result<PathBuf, PermissionCheckError> {
|
||||
deno_permissions::PermissionsContainer::check_ffi_partial_with_path(
|
||||
self, path,
|
||||
)
|
||||
|
|
|
@ -46,7 +46,7 @@ pub enum ReprError {
|
|||
#[error("Invalid pointer pointer, pointer is null")]
|
||||
InvalidPointer,
|
||||
#[error(transparent)]
|
||||
Permission(deno_core::error::AnyError),
|
||||
Permission(#[from] deno_permissions::PermissionCheckError),
|
||||
}
|
||||
|
||||
#[op2(fast)]
|
||||
|
@ -58,9 +58,7 @@ where
|
|||
FP: FfiPermissions + 'static,
|
||||
{
|
||||
let permissions = state.borrow_mut::<FP>();
|
||||
permissions
|
||||
.check_partial_no_path()
|
||||
.map_err(ReprError::Permission)?;
|
||||
permissions.check_partial_no_path()?;
|
||||
|
||||
Ok(ptr_number as *mut c_void)
|
||||
}
|
||||
|
@ -75,9 +73,7 @@ where
|
|||
FP: FfiPermissions + 'static,
|
||||
{
|
||||
let permissions = state.borrow_mut::<FP>();
|
||||
permissions
|
||||
.check_partial_no_path()
|
||||
.map_err(ReprError::Permission)?;
|
||||
permissions.check_partial_no_path()?;
|
||||
|
||||
Ok(a == b)
|
||||
}
|
||||
|
@ -91,9 +87,7 @@ where
|
|||
FP: FfiPermissions + 'static,
|
||||
{
|
||||
let permissions = state.borrow_mut::<FP>();
|
||||
permissions
|
||||
.check_partial_no_path()
|
||||
.map_err(ReprError::Permission)?;
|
||||
permissions.check_partial_no_path()?;
|
||||
|
||||
Ok(buf as *mut c_void)
|
||||
}
|
||||
|
@ -107,9 +101,7 @@ where
|
|||
FP: FfiPermissions + 'static,
|
||||
{
|
||||
let permissions = state.borrow_mut::<FP>();
|
||||
permissions
|
||||
.check_partial_no_path()
|
||||
.map_err(ReprError::Permission)?;
|
||||
permissions.check_partial_no_path()?;
|
||||
|
||||
let Some(buf) = buf.get_backing_store() else {
|
||||
return Ok(0 as _);
|
||||
|
@ -130,9 +122,7 @@ where
|
|||
FP: FfiPermissions + 'static,
|
||||
{
|
||||
let permissions = state.borrow_mut::<FP>();
|
||||
permissions
|
||||
.check_partial_no_path()
|
||||
.map_err(ReprError::Permission)?;
|
||||
permissions.check_partial_no_path()?;
|
||||
|
||||
if ptr.is_null() {
|
||||
return Err(ReprError::InvalidOffset);
|
||||
|
@ -162,9 +152,7 @@ where
|
|||
FP: FfiPermissions + 'static,
|
||||
{
|
||||
let permissions = state.borrow_mut::<FP>();
|
||||
permissions
|
||||
.check_partial_no_path()
|
||||
.map_err(ReprError::Permission)?;
|
||||
permissions.check_partial_no_path()?;
|
||||
|
||||
Ok(ptr as usize)
|
||||
}
|
||||
|
@ -181,9 +169,7 @@ where
|
|||
FP: FfiPermissions + 'static,
|
||||
{
|
||||
let permissions = state.borrow_mut::<FP>();
|
||||
permissions
|
||||
.check_partial_no_path()
|
||||
.map_err(ReprError::Permission)?;
|
||||
permissions.check_partial_no_path()?;
|
||||
|
||||
if ptr.is_null() {
|
||||
return Err(ReprError::InvalidArrayBuffer);
|
||||
|
@ -215,9 +201,7 @@ where
|
|||
FP: FfiPermissions + 'static,
|
||||
{
|
||||
let permissions = state.borrow_mut::<FP>();
|
||||
permissions
|
||||
.check_partial_no_path()
|
||||
.map_err(ReprError::Permission)?;
|
||||
permissions.check_partial_no_path()?;
|
||||
|
||||
if src.is_null() {
|
||||
Err(ReprError::InvalidArrayBuffer)
|
||||
|
@ -246,9 +230,7 @@ where
|
|||
FP: FfiPermissions + 'static,
|
||||
{
|
||||
let permissions = state.borrow_mut::<FP>();
|
||||
permissions
|
||||
.check_partial_no_path()
|
||||
.map_err(ReprError::Permission)?;
|
||||
permissions.check_partial_no_path()?;
|
||||
|
||||
if ptr.is_null() {
|
||||
return Err(ReprError::InvalidCString);
|
||||
|
@ -272,9 +254,7 @@ where
|
|||
FP: FfiPermissions + 'static,
|
||||
{
|
||||
let permissions = state.borrow_mut::<FP>();
|
||||
permissions
|
||||
.check_partial_no_path()
|
||||
.map_err(ReprError::Permission)?;
|
||||
permissions.check_partial_no_path()?;
|
||||
|
||||
if ptr.is_null() {
|
||||
return Err(ReprError::InvalidBool);
|
||||
|
@ -294,9 +274,7 @@ where
|
|||
FP: FfiPermissions + 'static,
|
||||
{
|
||||
let permissions = state.borrow_mut::<FP>();
|
||||
permissions
|
||||
.check_partial_no_path()
|
||||
.map_err(ReprError::Permission)?;
|
||||
permissions.check_partial_no_path()?;
|
||||
|
||||
if ptr.is_null() {
|
||||
return Err(ReprError::InvalidU8);
|
||||
|
@ -318,9 +296,7 @@ where
|
|||
FP: FfiPermissions + 'static,
|
||||
{
|
||||
let permissions = state.borrow_mut::<FP>();
|
||||
permissions
|
||||
.check_partial_no_path()
|
||||
.map_err(ReprError::Permission)?;
|
||||
permissions.check_partial_no_path()?;
|
||||
|
||||
if ptr.is_null() {
|
||||
return Err(ReprError::InvalidI8);
|
||||
|
@ -342,9 +318,7 @@ where
|
|||
FP: FfiPermissions + 'static,
|
||||
{
|
||||
let permissions = state.borrow_mut::<FP>();
|
||||
permissions
|
||||
.check_partial_no_path()
|
||||
.map_err(ReprError::Permission)?;
|
||||
permissions.check_partial_no_path()?;
|
||||
|
||||
if ptr.is_null() {
|
||||
return Err(ReprError::InvalidU16);
|
||||
|
@ -366,9 +340,7 @@ where
|
|||
FP: FfiPermissions + 'static,
|
||||
{
|
||||
let permissions = state.borrow_mut::<FP>();
|
||||
permissions
|
||||
.check_partial_no_path()
|
||||
.map_err(ReprError::Permission)?;
|
||||
permissions.check_partial_no_path()?;
|
||||
|
||||
if ptr.is_null() {
|
||||
return Err(ReprError::InvalidI16);
|
||||
|
@ -390,9 +362,7 @@ where
|
|||
FP: FfiPermissions + 'static,
|
||||
{
|
||||
let permissions = state.borrow_mut::<FP>();
|
||||
permissions
|
||||
.check_partial_no_path()
|
||||
.map_err(ReprError::Permission)?;
|
||||
permissions.check_partial_no_path()?;
|
||||
|
||||
if ptr.is_null() {
|
||||
return Err(ReprError::InvalidU32);
|
||||
|
@ -412,9 +382,7 @@ where
|
|||
FP: FfiPermissions + 'static,
|
||||
{
|
||||
let permissions = state.borrow_mut::<FP>();
|
||||
permissions
|
||||
.check_partial_no_path()
|
||||
.map_err(ReprError::Permission)?;
|
||||
permissions.check_partial_no_path()?;
|
||||
|
||||
if ptr.is_null() {
|
||||
return Err(ReprError::InvalidI32);
|
||||
|
@ -437,9 +405,7 @@ where
|
|||
FP: FfiPermissions + 'static,
|
||||
{
|
||||
let permissions = state.borrow_mut::<FP>();
|
||||
permissions
|
||||
.check_partial_no_path()
|
||||
.map_err(ReprError::Permission)?;
|
||||
permissions.check_partial_no_path()?;
|
||||
|
||||
if ptr.is_null() {
|
||||
return Err(ReprError::InvalidU64);
|
||||
|
@ -465,9 +431,7 @@ where
|
|||
FP: FfiPermissions + 'static,
|
||||
{
|
||||
let permissions = state.borrow_mut::<FP>();
|
||||
permissions
|
||||
.check_partial_no_path()
|
||||
.map_err(ReprError::Permission)?;
|
||||
permissions.check_partial_no_path()?;
|
||||
|
||||
if ptr.is_null() {
|
||||
return Err(ReprError::InvalidI64);
|
||||
|
@ -490,9 +454,7 @@ where
|
|||
FP: FfiPermissions + 'static,
|
||||
{
|
||||
let permissions = state.borrow_mut::<FP>();
|
||||
permissions
|
||||
.check_partial_no_path()
|
||||
.map_err(ReprError::Permission)?;
|
||||
permissions.check_partial_no_path()?;
|
||||
|
||||
if ptr.is_null() {
|
||||
return Err(ReprError::InvalidF32);
|
||||
|
@ -512,9 +474,7 @@ where
|
|||
FP: FfiPermissions + 'static,
|
||||
{
|
||||
let permissions = state.borrow_mut::<FP>();
|
||||
permissions
|
||||
.check_partial_no_path()
|
||||
.map_err(ReprError::Permission)?;
|
||||
permissions.check_partial_no_path()?;
|
||||
|
||||
if ptr.is_null() {
|
||||
return Err(ReprError::InvalidF64);
|
||||
|
@ -534,9 +494,7 @@ where
|
|||
FP: FfiPermissions + 'static,
|
||||
{
|
||||
let permissions = state.borrow_mut::<FP>();
|
||||
permissions
|
||||
.check_partial_no_path()
|
||||
.map_err(ReprError::Permission)?;
|
||||
permissions.check_partial_no_path()?;
|
||||
|
||||
if ptr.is_null() {
|
||||
return Err(ReprError::InvalidPointer);
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
[package]
|
||||
name = "deno_fs"
|
||||
version = "0.84.0"
|
||||
version = "0.86.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
|
|
@ -22,8 +22,8 @@ pub use crate::sync::MaybeSync;
|
|||
|
||||
use crate::ops::*;
|
||||
|
||||
use deno_core::error::AnyError;
|
||||
use deno_io::fs::FsError;
|
||||
use deno_permissions::PermissionCheckError;
|
||||
use std::borrow::Cow;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
|
@ -42,45 +42,51 @@ pub trait FsPermissions {
|
|||
&mut self,
|
||||
path: &str,
|
||||
api_name: &str,
|
||||
) -> Result<PathBuf, AnyError>;
|
||||
) -> Result<PathBuf, PermissionCheckError>;
|
||||
#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
|
||||
fn check_read_path<'a>(
|
||||
&mut self,
|
||||
path: &'a Path,
|
||||
api_name: &str,
|
||||
) -> Result<Cow<'a, Path>, AnyError>;
|
||||
fn check_read_all(&mut self, api_name: &str) -> Result<(), AnyError>;
|
||||
) -> Result<Cow<'a, Path>, PermissionCheckError>;
|
||||
fn check_read_all(
|
||||
&mut self,
|
||||
api_name: &str,
|
||||
) -> Result<(), PermissionCheckError>;
|
||||
fn check_read_blind(
|
||||
&mut self,
|
||||
p: &Path,
|
||||
display: &str,
|
||||
api_name: &str,
|
||||
) -> Result<(), AnyError>;
|
||||
) -> Result<(), PermissionCheckError>;
|
||||
#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
|
||||
fn check_write(
|
||||
&mut self,
|
||||
path: &str,
|
||||
api_name: &str,
|
||||
) -> Result<PathBuf, AnyError>;
|
||||
) -> Result<PathBuf, PermissionCheckError>;
|
||||
#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
|
||||
fn check_write_path<'a>(
|
||||
&mut self,
|
||||
path: &'a Path,
|
||||
api_name: &str,
|
||||
) -> Result<Cow<'a, Path>, AnyError>;
|
||||
) -> Result<Cow<'a, Path>, PermissionCheckError>;
|
||||
#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
|
||||
fn check_write_partial(
|
||||
&mut self,
|
||||
path: &str,
|
||||
api_name: &str,
|
||||
) -> Result<PathBuf, AnyError>;
|
||||
fn check_write_all(&mut self, api_name: &str) -> Result<(), AnyError>;
|
||||
) -> Result<PathBuf, PermissionCheckError>;
|
||||
fn check_write_all(
|
||||
&mut self,
|
||||
api_name: &str,
|
||||
) -> Result<(), PermissionCheckError>;
|
||||
fn check_write_blind(
|
||||
&mut self,
|
||||
p: &Path,
|
||||
display: &str,
|
||||
api_name: &str,
|
||||
) -> Result<(), AnyError>;
|
||||
) -> Result<(), PermissionCheckError>;
|
||||
|
||||
fn check<'a>(
|
||||
&mut self,
|
||||
|
@ -140,7 +146,7 @@ impl FsPermissions for deno_permissions::PermissionsContainer {
|
|||
&mut self,
|
||||
path: &str,
|
||||
api_name: &str,
|
||||
) -> Result<PathBuf, AnyError> {
|
||||
) -> Result<PathBuf, PermissionCheckError> {
|
||||
deno_permissions::PermissionsContainer::check_read(self, path, api_name)
|
||||
}
|
||||
|
||||
|
@ -148,7 +154,7 @@ impl FsPermissions for deno_permissions::PermissionsContainer {
|
|||
&mut self,
|
||||
path: &'a Path,
|
||||
api_name: &str,
|
||||
) -> Result<Cow<'a, Path>, AnyError> {
|
||||
) -> Result<Cow<'a, Path>, PermissionCheckError> {
|
||||
deno_permissions::PermissionsContainer::check_read_path(
|
||||
self,
|
||||
path,
|
||||
|
@ -160,7 +166,7 @@ impl FsPermissions for deno_permissions::PermissionsContainer {
|
|||
path: &Path,
|
||||
display: &str,
|
||||
api_name: &str,
|
||||
) -> Result<(), AnyError> {
|
||||
) -> Result<(), PermissionCheckError> {
|
||||
deno_permissions::PermissionsContainer::check_read_blind(
|
||||
self, path, display, api_name,
|
||||
)
|
||||
|
@ -170,7 +176,7 @@ impl FsPermissions for deno_permissions::PermissionsContainer {
|
|||
&mut self,
|
||||
path: &str,
|
||||
api_name: &str,
|
||||
) -> Result<PathBuf, AnyError> {
|
||||
) -> Result<PathBuf, PermissionCheckError> {
|
||||
deno_permissions::PermissionsContainer::check_write(self, path, api_name)
|
||||
}
|
||||
|
||||
|
@ -178,7 +184,7 @@ impl FsPermissions for deno_permissions::PermissionsContainer {
|
|||
&mut self,
|
||||
path: &'a Path,
|
||||
api_name: &str,
|
||||
) -> Result<Cow<'a, Path>, AnyError> {
|
||||
) -> Result<Cow<'a, Path>, PermissionCheckError> {
|
||||
deno_permissions::PermissionsContainer::check_write_path(
|
||||
self, path, api_name,
|
||||
)
|
||||
|
@ -188,7 +194,7 @@ impl FsPermissions for deno_permissions::PermissionsContainer {
|
|||
&mut self,
|
||||
path: &str,
|
||||
api_name: &str,
|
||||
) -> Result<PathBuf, AnyError> {
|
||||
) -> Result<PathBuf, PermissionCheckError> {
|
||||
deno_permissions::PermissionsContainer::check_write_partial(
|
||||
self, path, api_name,
|
||||
)
|
||||
|
@ -199,17 +205,23 @@ impl FsPermissions for deno_permissions::PermissionsContainer {
|
|||
p: &Path,
|
||||
display: &str,
|
||||
api_name: &str,
|
||||
) -> Result<(), AnyError> {
|
||||
) -> Result<(), PermissionCheckError> {
|
||||
deno_permissions::PermissionsContainer::check_write_blind(
|
||||
self, p, display, api_name,
|
||||
)
|
||||
}
|
||||
|
||||
fn check_read_all(&mut self, api_name: &str) -> Result<(), AnyError> {
|
||||
fn check_read_all(
|
||||
&mut self,
|
||||
api_name: &str,
|
||||
) -> Result<(), PermissionCheckError> {
|
||||
deno_permissions::PermissionsContainer::check_read_all(self, api_name)
|
||||
}
|
||||
|
||||
fn check_write_all(&mut self, api_name: &str) -> Result<(), AnyError> {
|
||||
fn check_write_all(
|
||||
&mut self,
|
||||
api_name: &str,
|
||||
) -> Result<(), PermissionCheckError> {
|
||||
deno_permissions::PermissionsContainer::check_write_all(self, api_name)
|
||||
}
|
||||
}
|
||||
|
|
217
ext/fs/ops.rs
217
ext/fs/ops.rs
|
@ -10,6 +10,12 @@ use std::path::PathBuf;
|
|||
use std::path::StripPrefixError;
|
||||
use std::rc::Rc;
|
||||
|
||||
use crate::interface::AccessCheckFn;
|
||||
use crate::interface::FileSystemRc;
|
||||
use crate::interface::FsDirEntry;
|
||||
use crate::interface::FsFileType;
|
||||
use crate::FsPermissions;
|
||||
use crate::OpenOptions;
|
||||
use deno_core::op2;
|
||||
use deno_core::CancelFuture;
|
||||
use deno_core::CancelHandle;
|
||||
|
@ -20,18 +26,12 @@ use deno_core::ToJsBuffer;
|
|||
use deno_io::fs::FileResource;
|
||||
use deno_io::fs::FsError;
|
||||
use deno_io::fs::FsStat;
|
||||
use deno_permissions::PermissionCheckError;
|
||||
use rand::rngs::ThreadRng;
|
||||
use rand::thread_rng;
|
||||
use rand::Rng;
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::interface::AccessCheckFn;
|
||||
use crate::interface::FileSystemRc;
|
||||
use crate::interface::FsDirEntry;
|
||||
use crate::interface::FsFileType;
|
||||
use crate::FsPermissions;
|
||||
use crate::OpenOptions;
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum FsOpsError {
|
||||
#[error("{0}")]
|
||||
|
@ -39,7 +39,7 @@ pub enum FsOpsError {
|
|||
#[error("{0}")]
|
||||
OperationError(#[source] OperationError),
|
||||
#[error(transparent)]
|
||||
Permission(deno_core::error::AnyError),
|
||||
Permission(#[from] PermissionCheckError),
|
||||
#[error(transparent)]
|
||||
Resource(deno_core::error::AnyError),
|
||||
#[error("File name or path {0:?} is not valid UTF-8")]
|
||||
|
@ -150,8 +150,7 @@ where
|
|||
let path = fs.cwd()?;
|
||||
state
|
||||
.borrow_mut::<P>()
|
||||
.check_read_blind(&path, "CWD", "Deno.cwd()")
|
||||
.map_err(FsOpsError::Permission)?;
|
||||
.check_read_blind(&path, "CWD", "Deno.cwd()")?;
|
||||
let path_str = path_into_string(path.into_os_string())?;
|
||||
Ok(path_str)
|
||||
}
|
||||
|
@ -166,8 +165,7 @@ where
|
|||
{
|
||||
let d = state
|
||||
.borrow_mut::<P>()
|
||||
.check_read(directory, "Deno.chdir()")
|
||||
.map_err(FsOpsError::Permission)?;
|
||||
.check_read(directory, "Deno.chdir()")?;
|
||||
state
|
||||
.borrow::<FileSystemRc>()
|
||||
.chdir(&d)
|
||||
|
@ -253,8 +251,7 @@ where
|
|||
|
||||
let path = state
|
||||
.borrow_mut::<P>()
|
||||
.check_write(&path, "Deno.mkdirSync()")
|
||||
.map_err(FsOpsError::Permission)?;
|
||||
.check_write(&path, "Deno.mkdirSync()")?;
|
||||
|
||||
let fs = state.borrow::<FileSystemRc>();
|
||||
fs.mkdir_sync(&path, recursive, Some(mode))
|
||||
|
@ -277,10 +274,7 @@ where
|
|||
|
||||
let (fs, path) = {
|
||||
let mut state = state.borrow_mut();
|
||||
let path = state
|
||||
.borrow_mut::<P>()
|
||||
.check_write(&path, "Deno.mkdir()")
|
||||
.map_err(FsOpsError::Permission)?;
|
||||
let path = state.borrow_mut::<P>().check_write(&path, "Deno.mkdir()")?;
|
||||
(state.borrow::<FileSystemRc>().clone(), path)
|
||||
};
|
||||
|
||||
|
@ -302,8 +296,7 @@ where
|
|||
{
|
||||
let path = state
|
||||
.borrow_mut::<P>()
|
||||
.check_write(&path, "Deno.chmodSync()")
|
||||
.map_err(FsOpsError::Permission)?;
|
||||
.check_write(&path, "Deno.chmodSync()")?;
|
||||
let fs = state.borrow::<FileSystemRc>();
|
||||
fs.chmod_sync(&path, mode).context_path("chmod", &path)?;
|
||||
Ok(())
|
||||
|
@ -320,10 +313,7 @@ where
|
|||
{
|
||||
let (fs, path) = {
|
||||
let mut state = state.borrow_mut();
|
||||
let path = state
|
||||
.borrow_mut::<P>()
|
||||
.check_write(&path, "Deno.chmod()")
|
||||
.map_err(FsOpsError::Permission)?;
|
||||
let path = state.borrow_mut::<P>().check_write(&path, "Deno.chmod()")?;
|
||||
(state.borrow::<FileSystemRc>().clone(), path)
|
||||
};
|
||||
fs.chmod_async(path.clone(), mode)
|
||||
|
@ -344,8 +334,7 @@ where
|
|||
{
|
||||
let path = state
|
||||
.borrow_mut::<P>()
|
||||
.check_write(&path, "Deno.chownSync()")
|
||||
.map_err(FsOpsError::Permission)?;
|
||||
.check_write(&path, "Deno.chownSync()")?;
|
||||
let fs = state.borrow::<FileSystemRc>();
|
||||
fs.chown_sync(&path, uid, gid)
|
||||
.context_path("chown", &path)?;
|
||||
|
@ -364,10 +353,7 @@ where
|
|||
{
|
||||
let (fs, path) = {
|
||||
let mut state = state.borrow_mut();
|
||||
let path = state
|
||||
.borrow_mut::<P>()
|
||||
.check_write(&path, "Deno.chown()")
|
||||
.map_err(FsOpsError::Permission)?;
|
||||
let path = state.borrow_mut::<P>().check_write(&path, "Deno.chown()")?;
|
||||
(state.borrow::<FileSystemRc>().clone(), path)
|
||||
};
|
||||
fs.chown_async(path.clone(), uid, gid)
|
||||
|
@ -387,8 +373,7 @@ where
|
|||
{
|
||||
let path = state
|
||||
.borrow_mut::<P>()
|
||||
.check_write(path, "Deno.removeSync()")
|
||||
.map_err(FsOpsError::Permission)?;
|
||||
.check_write(path, "Deno.removeSync()")?;
|
||||
|
||||
let fs = state.borrow::<FileSystemRc>();
|
||||
fs.remove_sync(&path, recursive)
|
||||
|
@ -411,13 +396,11 @@ where
|
|||
let path = if recursive {
|
||||
state
|
||||
.borrow_mut::<P>()
|
||||
.check_write(&path, "Deno.remove()")
|
||||
.map_err(FsOpsError::Permission)?
|
||||
.check_write(&path, "Deno.remove()")?
|
||||
} else {
|
||||
state
|
||||
.borrow_mut::<P>()
|
||||
.check_write_partial(&path, "Deno.remove()")
|
||||
.map_err(FsOpsError::Permission)?
|
||||
.check_write_partial(&path, "Deno.remove()")?
|
||||
};
|
||||
|
||||
(state.borrow::<FileSystemRc>().clone(), path)
|
||||
|
@ -440,12 +423,8 @@ where
|
|||
P: FsPermissions + 'static,
|
||||
{
|
||||
let permissions = state.borrow_mut::<P>();
|
||||
let from = permissions
|
||||
.check_read(from, "Deno.copyFileSync()")
|
||||
.map_err(FsOpsError::Permission)?;
|
||||
let to = permissions
|
||||
.check_write(to, "Deno.copyFileSync()")
|
||||
.map_err(FsOpsError::Permission)?;
|
||||
let from = permissions.check_read(from, "Deno.copyFileSync()")?;
|
||||
let to = permissions.check_write(to, "Deno.copyFileSync()")?;
|
||||
|
||||
let fs = state.borrow::<FileSystemRc>();
|
||||
fs.copy_file_sync(&from, &to)
|
||||
|
@ -466,12 +445,8 @@ where
|
|||
let (fs, from, to) = {
|
||||
let mut state = state.borrow_mut();
|
||||
let permissions = state.borrow_mut::<P>();
|
||||
let from = permissions
|
||||
.check_read(&from, "Deno.copyFile()")
|
||||
.map_err(FsOpsError::Permission)?;
|
||||
let to = permissions
|
||||
.check_write(&to, "Deno.copyFile()")
|
||||
.map_err(FsOpsError::Permission)?;
|
||||
let from = permissions.check_read(&from, "Deno.copyFile()")?;
|
||||
let to = permissions.check_write(&to, "Deno.copyFile()")?;
|
||||
(state.borrow::<FileSystemRc>().clone(), from, to)
|
||||
};
|
||||
|
||||
|
@ -493,8 +468,7 @@ where
|
|||
{
|
||||
let path = state
|
||||
.borrow_mut::<P>()
|
||||
.check_read(&path, "Deno.statSync()")
|
||||
.map_err(FsOpsError::Permission)?;
|
||||
.check_read(&path, "Deno.statSync()")?;
|
||||
let fs = state.borrow::<FileSystemRc>();
|
||||
let stat = fs.stat_sync(&path).context_path("stat", &path)?;
|
||||
let serializable_stat = SerializableStat::from(stat);
|
||||
|
@ -514,9 +488,7 @@ where
|
|||
let (fs, path) = {
|
||||
let mut state = state.borrow_mut();
|
||||
let permissions = state.borrow_mut::<P>();
|
||||
let path = permissions
|
||||
.check_read(&path, "Deno.stat()")
|
||||
.map_err(FsOpsError::Permission)?;
|
||||
let path = permissions.check_read(&path, "Deno.stat()")?;
|
||||
(state.borrow::<FileSystemRc>().clone(), path)
|
||||
};
|
||||
let stat = fs
|
||||
|
@ -537,8 +509,7 @@ where
|
|||
{
|
||||
let path = state
|
||||
.borrow_mut::<P>()
|
||||
.check_read(&path, "Deno.lstatSync()")
|
||||
.map_err(FsOpsError::Permission)?;
|
||||
.check_read(&path, "Deno.lstatSync()")?;
|
||||
let fs = state.borrow::<FileSystemRc>();
|
||||
let stat = fs.lstat_sync(&path).context_path("lstat", &path)?;
|
||||
let serializable_stat = SerializableStat::from(stat);
|
||||
|
@ -558,9 +529,7 @@ where
|
|||
let (fs, path) = {
|
||||
let mut state = state.borrow_mut();
|
||||
let permissions = state.borrow_mut::<P>();
|
||||
let path = permissions
|
||||
.check_read(&path, "Deno.lstat()")
|
||||
.map_err(FsOpsError::Permission)?;
|
||||
let path = permissions.check_read(&path, "Deno.lstat()")?;
|
||||
(state.borrow::<FileSystemRc>().clone(), path)
|
||||
};
|
||||
let stat = fs
|
||||
|
@ -581,13 +550,9 @@ where
|
|||
{
|
||||
let fs = state.borrow::<FileSystemRc>().clone();
|
||||
let permissions = state.borrow_mut::<P>();
|
||||
let path = permissions
|
||||
.check_read(&path, "Deno.realPathSync()")
|
||||
.map_err(FsOpsError::Permission)?;
|
||||
let path = permissions.check_read(&path, "Deno.realPathSync()")?;
|
||||
if path.is_relative() {
|
||||
permissions
|
||||
.check_read_blind(&fs.cwd()?, "CWD", "Deno.realPathSync()")
|
||||
.map_err(FsOpsError::Permission)?;
|
||||
permissions.check_read_blind(&fs.cwd()?, "CWD", "Deno.realPathSync()")?;
|
||||
}
|
||||
|
||||
let resolved_path =
|
||||
|
@ -610,13 +575,9 @@ where
|
|||
let mut state = state.borrow_mut();
|
||||
let fs = state.borrow::<FileSystemRc>().clone();
|
||||
let permissions = state.borrow_mut::<P>();
|
||||
let path = permissions
|
||||
.check_read(&path, "Deno.realPath()")
|
||||
.map_err(FsOpsError::Permission)?;
|
||||
let path = permissions.check_read(&path, "Deno.realPath()")?;
|
||||
if path.is_relative() {
|
||||
permissions
|
||||
.check_read_blind(&fs.cwd()?, "CWD", "Deno.realPath()")
|
||||
.map_err(FsOpsError::Permission)?;
|
||||
permissions.check_read_blind(&fs.cwd()?, "CWD", "Deno.realPath()")?;
|
||||
}
|
||||
(fs, path)
|
||||
};
|
||||
|
@ -640,8 +601,7 @@ where
|
|||
{
|
||||
let path = state
|
||||
.borrow_mut::<P>()
|
||||
.check_read(&path, "Deno.readDirSync()")
|
||||
.map_err(FsOpsError::Permission)?;
|
||||
.check_read(&path, "Deno.readDirSync()")?;
|
||||
|
||||
let fs = state.borrow::<FileSystemRc>();
|
||||
let entries = fs.read_dir_sync(&path).context_path("readdir", &path)?;
|
||||
|
@ -662,8 +622,7 @@ where
|
|||
let mut state = state.borrow_mut();
|
||||
let path = state
|
||||
.borrow_mut::<P>()
|
||||
.check_read(&path, "Deno.readDir()")
|
||||
.map_err(FsOpsError::Permission)?;
|
||||
.check_read(&path, "Deno.readDir()")?;
|
||||
(state.borrow::<FileSystemRc>().clone(), path)
|
||||
};
|
||||
|
||||
|
@ -685,15 +644,9 @@ where
|
|||
P: FsPermissions + 'static,
|
||||
{
|
||||
let permissions = state.borrow_mut::<P>();
|
||||
let _ = permissions
|
||||
.check_read(&oldpath, "Deno.renameSync()")
|
||||
.map_err(FsOpsError::Permission)?;
|
||||
let oldpath = permissions
|
||||
.check_write(&oldpath, "Deno.renameSync()")
|
||||
.map_err(FsOpsError::Permission)?;
|
||||
let newpath = permissions
|
||||
.check_write(&newpath, "Deno.renameSync()")
|
||||
.map_err(FsOpsError::Permission)?;
|
||||
let _ = permissions.check_read(&oldpath, "Deno.renameSync()")?;
|
||||
let oldpath = permissions.check_write(&oldpath, "Deno.renameSync()")?;
|
||||
let newpath = permissions.check_write(&newpath, "Deno.renameSync()")?;
|
||||
|
||||
let fs = state.borrow::<FileSystemRc>();
|
||||
fs.rename_sync(&oldpath, &newpath)
|
||||
|
@ -714,15 +667,9 @@ where
|
|||
let (fs, oldpath, newpath) = {
|
||||
let mut state = state.borrow_mut();
|
||||
let permissions = state.borrow_mut::<P>();
|
||||
_ = permissions
|
||||
.check_read(&oldpath, "Deno.rename()")
|
||||
.map_err(FsOpsError::Permission)?;
|
||||
let oldpath = permissions
|
||||
.check_write(&oldpath, "Deno.rename()")
|
||||
.map_err(FsOpsError::Permission)?;
|
||||
let newpath = permissions
|
||||
.check_write(&newpath, "Deno.rename()")
|
||||
.map_err(FsOpsError::Permission)?;
|
||||
_ = permissions.check_read(&oldpath, "Deno.rename()")?;
|
||||
let oldpath = permissions.check_write(&oldpath, "Deno.rename()")?;
|
||||
let newpath = permissions.check_write(&newpath, "Deno.rename()")?;
|
||||
(state.borrow::<FileSystemRc>().clone(), oldpath, newpath)
|
||||
};
|
||||
|
||||
|
@ -743,18 +690,10 @@ where
|
|||
P: FsPermissions + 'static,
|
||||
{
|
||||
let permissions = state.borrow_mut::<P>();
|
||||
_ = permissions
|
||||
.check_read(oldpath, "Deno.linkSync()")
|
||||
.map_err(FsOpsError::Permission)?;
|
||||
let oldpath = permissions
|
||||
.check_write(oldpath, "Deno.linkSync()")
|
||||
.map_err(FsOpsError::Permission)?;
|
||||
_ = permissions
|
||||
.check_read(newpath, "Deno.linkSync()")
|
||||
.map_err(FsOpsError::Permission)?;
|
||||
let newpath = permissions
|
||||
.check_write(newpath, "Deno.linkSync()")
|
||||
.map_err(FsOpsError::Permission)?;
|
||||
_ = permissions.check_read(oldpath, "Deno.linkSync()")?;
|
||||
let oldpath = permissions.check_write(oldpath, "Deno.linkSync()")?;
|
||||
_ = permissions.check_read(newpath, "Deno.linkSync()")?;
|
||||
let newpath = permissions.check_write(newpath, "Deno.linkSync()")?;
|
||||
|
||||
let fs = state.borrow::<FileSystemRc>();
|
||||
fs.link_sync(&oldpath, &newpath)
|
||||
|
@ -775,18 +714,10 @@ where
|
|||
let (fs, oldpath, newpath) = {
|
||||
let mut state = state.borrow_mut();
|
||||
let permissions = state.borrow_mut::<P>();
|
||||
_ = permissions
|
||||
.check_read(&oldpath, "Deno.link()")
|
||||
.map_err(FsOpsError::Permission)?;
|
||||
let oldpath = permissions
|
||||
.check_write(&oldpath, "Deno.link()")
|
||||
.map_err(FsOpsError::Permission)?;
|
||||
_ = permissions
|
||||
.check_read(&newpath, "Deno.link()")
|
||||
.map_err(FsOpsError::Permission)?;
|
||||
let newpath = permissions
|
||||
.check_write(&newpath, "Deno.link()")
|
||||
.map_err(FsOpsError::Permission)?;
|
||||
_ = permissions.check_read(&oldpath, "Deno.link()")?;
|
||||
let oldpath = permissions.check_write(&oldpath, "Deno.link()")?;
|
||||
_ = permissions.check_read(&newpath, "Deno.link()")?;
|
||||
let newpath = permissions.check_write(&newpath, "Deno.link()")?;
|
||||
(state.borrow::<FileSystemRc>().clone(), oldpath, newpath)
|
||||
};
|
||||
|
||||
|
@ -811,12 +742,8 @@ where
|
|||
let newpath = PathBuf::from(newpath);
|
||||
|
||||
let permissions = state.borrow_mut::<P>();
|
||||
permissions
|
||||
.check_write_all("Deno.symlinkSync()")
|
||||
.map_err(FsOpsError::Permission)?;
|
||||
permissions
|
||||
.check_read_all("Deno.symlinkSync()")
|
||||
.map_err(FsOpsError::Permission)?;
|
||||
permissions.check_write_all("Deno.symlinkSync()")?;
|
||||
permissions.check_read_all("Deno.symlinkSync()")?;
|
||||
|
||||
let fs = state.borrow::<FileSystemRc>();
|
||||
fs.symlink_sync(&oldpath, &newpath, file_type)
|
||||
|
@ -841,12 +768,8 @@ where
|
|||
let fs = {
|
||||
let mut state = state.borrow_mut();
|
||||
let permissions = state.borrow_mut::<P>();
|
||||
permissions
|
||||
.check_write_all("Deno.symlink()")
|
||||
.map_err(FsOpsError::Permission)?;
|
||||
permissions
|
||||
.check_read_all("Deno.symlink()")
|
||||
.map_err(FsOpsError::Permission)?;
|
||||
permissions.check_write_all("Deno.symlink()")?;
|
||||
permissions.check_read_all("Deno.symlink()")?;
|
||||
state.borrow::<FileSystemRc>().clone()
|
||||
};
|
||||
|
||||
|
@ -868,8 +791,7 @@ where
|
|||
{
|
||||
let path = state
|
||||
.borrow_mut::<P>()
|
||||
.check_read(&path, "Deno.readLink()")
|
||||
.map_err(FsOpsError::Permission)?;
|
||||
.check_read(&path, "Deno.readLink()")?;
|
||||
|
||||
let fs = state.borrow::<FileSystemRc>();
|
||||
|
||||
|
@ -891,8 +813,7 @@ where
|
|||
let mut state = state.borrow_mut();
|
||||
let path = state
|
||||
.borrow_mut::<P>()
|
||||
.check_read(&path, "Deno.readLink()")
|
||||
.map_err(FsOpsError::Permission)?;
|
||||
.check_read(&path, "Deno.readLink()")?;
|
||||
(state.borrow::<FileSystemRc>().clone(), path)
|
||||
};
|
||||
|
||||
|
@ -915,8 +836,7 @@ where
|
|||
{
|
||||
let path = state
|
||||
.borrow_mut::<P>()
|
||||
.check_write(path, "Deno.truncateSync()")
|
||||
.map_err(FsOpsError::Permission)?;
|
||||
.check_write(path, "Deno.truncateSync()")?;
|
||||
|
||||
let fs = state.borrow::<FileSystemRc>();
|
||||
fs.truncate_sync(&path, len)
|
||||
|
@ -938,8 +858,7 @@ where
|
|||
let mut state = state.borrow_mut();
|
||||
let path = state
|
||||
.borrow_mut::<P>()
|
||||
.check_write(&path, "Deno.truncate()")
|
||||
.map_err(FsOpsError::Permission)?;
|
||||
.check_write(&path, "Deno.truncate()")?;
|
||||
(state.borrow::<FileSystemRc>().clone(), path)
|
||||
};
|
||||
|
||||
|
@ -962,10 +881,7 @@ pub fn op_fs_utime_sync<P>(
|
|||
where
|
||||
P: FsPermissions + 'static,
|
||||
{
|
||||
let path = state
|
||||
.borrow_mut::<P>()
|
||||
.check_write(path, "Deno.utime()")
|
||||
.map_err(FsOpsError::Permission)?;
|
||||
let path = state.borrow_mut::<P>().check_write(path, "Deno.utime()")?;
|
||||
|
||||
let fs = state.borrow::<FileSystemRc>();
|
||||
fs.utime_sync(&path, atime_secs, atime_nanos, mtime_secs, mtime_nanos)
|
||||
|
@ -988,10 +904,7 @@ where
|
|||
{
|
||||
let (fs, path) = {
|
||||
let mut state = state.borrow_mut();
|
||||
let path = state
|
||||
.borrow_mut::<P>()
|
||||
.check_write(&path, "Deno.utime()")
|
||||
.map_err(FsOpsError::Permission)?;
|
||||
let path = state.borrow_mut::<P>().check_write(&path, "Deno.utime()")?;
|
||||
(state.borrow::<FileSystemRc>().clone(), path)
|
||||
};
|
||||
|
||||
|
@ -1219,16 +1132,12 @@ where
|
|||
{
|
||||
let fs = state.borrow::<FileSystemRc>().clone();
|
||||
let dir = match dir {
|
||||
Some(dir) => state
|
||||
.borrow_mut::<P>()
|
||||
.check_write(dir, api_name)
|
||||
.map_err(FsOpsError::Permission)?,
|
||||
Some(dir) => state.borrow_mut::<P>().check_write(dir, api_name)?,
|
||||
None => {
|
||||
let dir = fs.tmp_dir().context("tmpdir")?;
|
||||
state
|
||||
.borrow_mut::<P>()
|
||||
.check_write_blind(&dir, "TMP", api_name)
|
||||
.map_err(FsOpsError::Permission)?;
|
||||
.check_write_blind(&dir, "TMP", api_name)?;
|
||||
dir
|
||||
}
|
||||
};
|
||||
|
@ -1246,16 +1155,12 @@ where
|
|||
let mut state = state.borrow_mut();
|
||||
let fs = state.borrow::<FileSystemRc>().clone();
|
||||
let dir = match dir {
|
||||
Some(dir) => state
|
||||
.borrow_mut::<P>()
|
||||
.check_write(dir, api_name)
|
||||
.map_err(FsOpsError::Permission)?,
|
||||
Some(dir) => state.borrow_mut::<P>().check_write(dir, api_name)?,
|
||||
None => {
|
||||
let dir = fs.tmp_dir().context("tmpdir")?;
|
||||
state
|
||||
.borrow_mut::<P>()
|
||||
.check_write_blind(&dir, "TMP", api_name)
|
||||
.map_err(FsOpsError::Permission)?;
|
||||
.check_write_blind(&dir, "TMP", api_name)?;
|
||||
dir
|
||||
}
|
||||
};
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
[package]
|
||||
name = "deno_http"
|
||||
version = "0.172.0"
|
||||
version = "0.174.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
[package]
|
||||
name = "deno_io"
|
||||
version = "0.84.0"
|
||||
version = "0.86.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
[package]
|
||||
name = "deno_kv"
|
||||
version = "0.82.0"
|
||||
version = "0.84.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue