0
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-02-07 23:06:50 -05:00

Compare commits

...

9 commits

Author SHA1 Message Date
Ian Bull
8626ec7c25
refactor(ext/fs): align error messages (#25414)
Aligns the error messages in the ext/fs folder to be in-line with the
Deno style guide.
2024-11-28 18:47:07 +00:00
Marvin Hagemeister
3553aa9132
fix(publish): error on missing name field (#27131)
This PR improves the error output on publish when the `name` filed is
missing:

```json
{
  "exports": "./mod.ts",
  "version": "0.0.1"
}
```

Before:

```sh
deno publish --dry-run
error: You did not specify an entrypoint in file:///Users/marvinh/dev/test/deno-pkg-timers/deno.json. Add `exports` mapping in the configuration file, eg:
{
  "name": "@scope/name",
  "version": "0.0.0",
  "exports": "<path_to_entrypoint>"
}
```

After:

```sh
deno publish --dry-run
error: Missing 'name' field in 'file:///Users/marvinh/dev/test/deno-pkg-timers/deno.json'.
```

Fixes https://github.com/denoland/deno/issues/27116
2024-11-28 18:11:36 +01:00
denobot
12aea2014a
chore: forward v2.1.2 release commit to main (#27136)
This is the release commit being forwarded back to main for 2.1.2

Co-authored-by: bartlomieju <bartlomieju@users.noreply.github.com>
Co-authored-by: Bartek Iwańczuk <biwanczuk@gmail.com>
2024-11-28 17:00:24 +00:00
Marvin Hagemeister
39722f190a
fix(node/timers): error when passing id to clearTimeout/clearInterval (#27130)
As pointed out in https://github.com/denoland/deno/issues/27126 we used
a variable which could potentially be of type `number` instead of the
`Timeout` class instance. Ensure that we're always setting `_destroyed`
on the class instead instead.

Fixes https://github.com/denoland/deno/issues/27126
2024-11-28 15:11:51 +01:00
Marvin Hagemeister
026bbc4a9e
fix(init): support scoped npm packages (#27128)
The naming scheme for create npm packages varies depending on whether
they are scoped or not. We only supported unscoped packages prior to
this PR. This PR adds support for all the following cases which npm
supports:

- `foo` -> `create-foo`
- `@foo/bar` -> `@foo/create-bar`
- `@foo` -> `@foo/create`
- `@foo@2.0.0` -> `@foo/create@2.0.0`
- `@foo/bar@2.0.0` -> `@foo/create-bar@2.0.0`

See https://docs.npmjs.com/cli/v8/commands/npm-init#description

Fixes https://github.com/denoland/deno/issues/27127
2024-11-28 15:07:32 +01:00
Luca Casonato
32e260d55a
fix: support bun specifiers in JSR publish (#24588)
Fixes https://github.com/denoland/deno/issues/26989

---------

Co-authored-by: Nathan Whitaker <nathan@deno.com>
2024-11-28 14:51:24 +01:00
Divy Srivastava
1af2d2474e
fix(ext/node): tls.connect socket upgrades (#27125)
Fixes https://github.com/denoland/deno/issues/27087
Fixes https://github.com/denoland/deno/issues/26685
Fixes https://github.com/denoland/deno/issues/26660
2024-11-28 17:59:20 +05:30
David Sherret
f161adf19e
perf(compile): read embedded files as static references when UTF-8 and reading as strings (#27033) 2024-11-27 21:28:41 -05:00
Nathan Whitaker
76daa03aa9
fix(info): resolve bare specifier pointing to workspace member (#27020)
Fixes https://github.com/denoland/deno/issues/26721

Previously, we were applying only the import map, which would result in
`@scope/foo` expanding to (e.g.) `jsr:@scope/foo@1.0.0`. Since that
didn't exist it would error and fail to resolve.
2024-11-27 13:54:26 -08:00
93 changed files with 636 additions and 206 deletions

View file

@ -5,7 +5,7 @@ import { stringify } from "jsr:@std/yaml@^0.221/stringify";
// Bump this number when you want to purge the cache.
// Note: the tools/release/01_bump_crate_versions.ts script will update this version
// automatically via regex, so ensure that this line maintains this format.
const cacheVersion = 27;
const cacheVersion = 28;
const ubuntuX86Runner = "ubuntu-24.04";
const ubuntuX86XlRunner = "ubuntu-24.04-xl";

View file

@ -361,8 +361,8 @@ jobs:
path: |-
~/.cargo/registry/index
~/.cargo/registry/cache
key: '27-cargo-home-${{ matrix.os }}-${{ matrix.arch }}-${{ hashFiles(''Cargo.lock'') }}'
restore-keys: '27-cargo-home-${{ matrix.os }}-${{ matrix.arch }}'
key: '28-cargo-home-${{ matrix.os }}-${{ matrix.arch }}-${{ hashFiles(''Cargo.lock'') }}'
restore-keys: '28-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: '27-cargo-target-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.profile }}-${{ matrix.job }}-'
restore-keys: '28-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,7 +685,7 @@ jobs:
!./target/*/*.zip
!./target/*/*.sha256sum
!./target/*/*.tar.gz
key: '27-cargo-target-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.profile }}-${{ matrix.job }}-${{ github.sha }}'
key: '28-cargo-target-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.profile }}-${{ matrix.job }}-${{ github.sha }}'
publish-canary:
name: publish canary
runs-on: ubuntu-24.04

60
Cargo.lock generated
View file

@ -1194,7 +1194,7 @@ dependencies = [
[[package]]
name = "deno"
version = "2.1.1"
version = "2.1.2"
dependencies = [
"anstream",
"async-trait",
@ -1365,7 +1365,7 @@ dependencies = [
[[package]]
name = "deno_bench_util"
version = "0.173.0"
version = "0.174.0"
dependencies = [
"bencher",
"deno_core",
@ -1374,7 +1374,7 @@ dependencies = [
[[package]]
name = "deno_broadcast_channel"
version = "0.173.0"
version = "0.174.0"
dependencies = [
"async-trait",
"deno_core",
@ -1385,7 +1385,7 @@ dependencies = [
[[package]]
name = "deno_cache"
version = "0.111.0"
version = "0.112.0"
dependencies = [
"async-trait",
"deno_core",
@ -1418,7 +1418,7 @@ dependencies = [
[[package]]
name = "deno_canvas"
version = "0.48.0"
version = "0.49.0"
dependencies = [
"deno_core",
"deno_webgpu",
@ -1453,7 +1453,7 @@ dependencies = [
[[package]]
name = "deno_console"
version = "0.179.0"
version = "0.180.0"
dependencies = [
"deno_core",
]
@ -1501,7 +1501,7 @@ checksum = "fe4dccb6147bb3f3ba0c7a48e993bfeb999d2c2e47a81badee80e2b370c8d695"
[[package]]
name = "deno_cron"
version = "0.59.0"
version = "0.60.0"
dependencies = [
"anyhow",
"async-trait",
@ -1514,7 +1514,7 @@ dependencies = [
[[package]]
name = "deno_crypto"
version = "0.193.0"
version = "0.194.0"
dependencies = [
"aes",
"aes-gcm",
@ -1580,7 +1580,7 @@ dependencies = [
[[package]]
name = "deno_fetch"
version = "0.203.0"
version = "0.204.0"
dependencies = [
"base64 0.21.7",
"bytes",
@ -1614,7 +1614,7 @@ dependencies = [
[[package]]
name = "deno_ffi"
version = "0.166.0"
version = "0.167.0"
dependencies = [
"deno_core",
"deno_permissions",
@ -1634,7 +1634,7 @@ dependencies = [
[[package]]
name = "deno_fs"
version = "0.89.0"
version = "0.90.0"
dependencies = [
"async-trait",
"base32",
@ -1687,7 +1687,7 @@ dependencies = [
[[package]]
name = "deno_http"
version = "0.177.0"
version = "0.178.0"
dependencies = [
"async-compression",
"async-trait",
@ -1726,7 +1726,7 @@ dependencies = [
[[package]]
name = "deno_io"
version = "0.89.0"
version = "0.90.0"
dependencies = [
"async-trait",
"deno_core",
@ -1747,7 +1747,7 @@ dependencies = [
[[package]]
name = "deno_kv"
version = "0.87.0"
version = "0.88.0"
dependencies = [
"anyhow",
"async-trait",
@ -1820,7 +1820,7 @@ dependencies = [
[[package]]
name = "deno_napi"
version = "0.110.0"
version = "0.111.0"
dependencies = [
"deno_core",
"deno_permissions",
@ -1848,7 +1848,7 @@ dependencies = [
[[package]]
name = "deno_net"
version = "0.171.0"
version = "0.172.0"
dependencies = [
"deno_core",
"deno_permissions",
@ -1865,7 +1865,7 @@ dependencies = [
[[package]]
name = "deno_node"
version = "0.116.0"
version = "0.117.0"
dependencies = [
"aead-gcm-stream",
"aes",
@ -2017,7 +2017,7 @@ dependencies = [
[[package]]
name = "deno_permissions"
version = "0.39.0"
version = "0.40.0"
dependencies = [
"deno_core",
"deno_path_util",
@ -2035,7 +2035,7 @@ dependencies = [
[[package]]
name = "deno_resolver"
version = "0.11.0"
version = "0.12.0"
dependencies = [
"anyhow",
"base32",
@ -2054,7 +2054,7 @@ dependencies = [
[[package]]
name = "deno_runtime"
version = "0.188.0"
version = "0.189.0"
dependencies = [
"color-print",
"deno_ast",
@ -2153,7 +2153,7 @@ dependencies = [
[[package]]
name = "deno_telemetry"
version = "0.1.0"
version = "0.2.0"
dependencies = [
"async-trait",
"deno_core",
@ -2194,7 +2194,7 @@ dependencies = [
[[package]]
name = "deno_tls"
version = "0.166.0"
version = "0.167.0"
dependencies = [
"deno_core",
"deno_native_certs",
@ -2243,7 +2243,7 @@ dependencies = [
[[package]]
name = "deno_url"
version = "0.179.0"
version = "0.180.0"
dependencies = [
"deno_bench_util",
"deno_console",
@ -2255,7 +2255,7 @@ dependencies = [
[[package]]
name = "deno_web"
version = "0.210.0"
version = "0.211.0"
dependencies = [
"async-trait",
"base64-simd 0.8.0",
@ -2277,7 +2277,7 @@ dependencies = [
[[package]]
name = "deno_webgpu"
version = "0.146.0"
version = "0.147.0"
dependencies = [
"deno_core",
"raw-window-handle",
@ -2290,7 +2290,7 @@ dependencies = [
[[package]]
name = "deno_webidl"
version = "0.179.0"
version = "0.180.0"
dependencies = [
"deno_bench_util",
"deno_core",
@ -2298,7 +2298,7 @@ dependencies = [
[[package]]
name = "deno_websocket"
version = "0.184.0"
version = "0.185.0"
dependencies = [
"bytes",
"deno_core",
@ -2320,7 +2320,7 @@ dependencies = [
[[package]]
name = "deno_webstorage"
version = "0.174.0"
version = "0.175.0"
dependencies = [
"deno_core",
"deno_web",
@ -4833,7 +4833,7 @@ dependencies = [
[[package]]
name = "napi_sym"
version = "0.109.0"
version = "0.110.0"
dependencies = [
"quote",
"serde",
@ -4888,7 +4888,7 @@ dependencies = [
[[package]]
name = "node_resolver"
version = "0.18.0"
version = "0.19.0"
dependencies = [
"anyhow",
"async-trait",

View file

@ -49,17 +49,17 @@ repository = "https://github.com/denoland/deno"
deno_ast = { version = "=0.43.3", features = ["transpiling"] }
deno_core = { version = "0.323.0" }
deno_bench_util = { version = "0.173.0", path = "./bench_util" }
deno_bench_util = { version = "0.174.0", path = "./bench_util" }
deno_config = { version = "=0.39.2", features = ["workspace", "sync"] }
deno_lockfile = "=0.23.1"
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.39.0", path = "./runtime/permissions" }
deno_runtime = { version = "0.188.0", path = "./runtime" }
deno_permissions = { version = "0.40.0", path = "./runtime/permissions" }
deno_runtime = { version = "0.189.0", path = "./runtime" }
deno_semver = "=0.5.16"
deno_terminal = "0.2.0"
napi_sym = { version = "0.109.0", path = "./ext/napi/sym" }
napi_sym = { version = "0.110.0", path = "./ext/napi/sym" }
test_util = { package = "test_server", path = "./tests/util/server" }
denokv_proto = "0.8.4"
@ -68,33 +68,33 @@ denokv_remote = "0.8.4"
denokv_sqlite = { default-features = false, version = "0.8.4" }
# exts
deno_broadcast_channel = { version = "0.173.0", path = "./ext/broadcast_channel" }
deno_cache = { version = "0.111.0", path = "./ext/cache" }
deno_canvas = { version = "0.48.0", path = "./ext/canvas" }
deno_console = { version = "0.179.0", path = "./ext/console" }
deno_cron = { version = "0.59.0", path = "./ext/cron" }
deno_crypto = { version = "0.193.0", path = "./ext/crypto" }
deno_fetch = { version = "0.203.0", path = "./ext/fetch" }
deno_ffi = { version = "0.166.0", path = "./ext/ffi" }
deno_fs = { version = "0.89.0", path = "./ext/fs" }
deno_http = { version = "0.177.0", path = "./ext/http" }
deno_io = { version = "0.89.0", path = "./ext/io" }
deno_kv = { version = "0.87.0", path = "./ext/kv" }
deno_napi = { version = "0.110.0", path = "./ext/napi" }
deno_net = { version = "0.171.0", path = "./ext/net" }
deno_node = { version = "0.116.0", path = "./ext/node" }
deno_telemetry = { version = "0.1.0", path = "./ext/telemetry" }
deno_tls = { version = "0.166.0", path = "./ext/tls" }
deno_url = { version = "0.179.0", path = "./ext/url" }
deno_web = { version = "0.210.0", path = "./ext/web" }
deno_webgpu = { version = "0.146.0", path = "./ext/webgpu" }
deno_webidl = { version = "0.179.0", path = "./ext/webidl" }
deno_websocket = { version = "0.184.0", path = "./ext/websocket" }
deno_webstorage = { version = "0.174.0", path = "./ext/webstorage" }
deno_broadcast_channel = { version = "0.174.0", path = "./ext/broadcast_channel" }
deno_cache = { version = "0.112.0", path = "./ext/cache" }
deno_canvas = { version = "0.49.0", path = "./ext/canvas" }
deno_console = { version = "0.180.0", path = "./ext/console" }
deno_cron = { version = "0.60.0", path = "./ext/cron" }
deno_crypto = { version = "0.194.0", path = "./ext/crypto" }
deno_fetch = { version = "0.204.0", path = "./ext/fetch" }
deno_ffi = { version = "0.167.0", path = "./ext/ffi" }
deno_fs = { version = "0.90.0", path = "./ext/fs" }
deno_http = { version = "0.178.0", path = "./ext/http" }
deno_io = { version = "0.90.0", path = "./ext/io" }
deno_kv = { version = "0.88.0", path = "./ext/kv" }
deno_napi = { version = "0.111.0", path = "./ext/napi" }
deno_net = { version = "0.172.0", path = "./ext/net" }
deno_node = { version = "0.117.0", path = "./ext/node" }
deno_telemetry = { version = "0.2.0", path = "./ext/telemetry" }
deno_tls = { version = "0.167.0", path = "./ext/tls" }
deno_url = { version = "0.180.0", path = "./ext/url" }
deno_web = { version = "0.211.0", path = "./ext/web" }
deno_webgpu = { version = "0.147.0", path = "./ext/webgpu" }
deno_webidl = { version = "0.180.0", path = "./ext/webidl" }
deno_websocket = { version = "0.185.0", path = "./ext/websocket" }
deno_webstorage = { version = "0.175.0", path = "./ext/webstorage" }
# resolvers
deno_resolver = { version = "0.11.0", path = "./resolvers/deno" }
node_resolver = { version = "0.18.0", path = "./resolvers/node" }
deno_resolver = { version = "0.12.0", path = "./resolvers/deno" }
node_resolver = { version = "0.19.0", path = "./resolvers/node" }
aes = "=0.8.3"
anyhow = "1.0.57"

View file

@ -6,6 +6,50 @@ https://github.com/denoland/deno/releases
We also have one-line install commands at:
https://github.com/denoland/deno_install
### 2.1.2 / 2024.11.28
- feat(unstable): Instrument Deno.serve (#26964)
- feat(unstable): Instrument fetch (#27057)
- feat(unstable): repurpose `--unstable-detect-cjs` to attempt loading more
modules as cjs (#27094)
- fix(check): support jsdoc `@import` tag (#26991)
- fix(compile): correct buffered reading of assets and files (#27008)
- fix(compile): do not error embedding same symlink via multiple methods
(#27015)
- fix(compile): handle TypeScript file included as asset (#27032)
- fix(ext/fetch): don't throw when `bodyUsed` inspect after upgrade (#27088)
- fix(ext/node): `tls.connect` socket upgrades (#27125)
- fix(ext/node): add `fs.promises.fstat` and `FileHandle#stat` (#26719)
- fix(ext/webgpu): normalize limits to number (#27072)
- fix(ext/webgpu): use correct variable name (#27108)
- fix(ext/websocket): don't throw exception when sending to closed socket
(#26932)
- fix(fmt): return `None` if sql fmt result is the same (#27014)
- fix(info): resolve bare specifier pointing to workspace member (#27020)
- fix(init): always force managed node modules (#27047)
- fix(init): support scoped npm packages (#27128)
- fix(install): don't re-set up node_modules if running lifecycle script
(#26984)
- fix(lsp): remove stray debug output (#27010)
- fix(lsp): support task object notation for tasks request (#27076)
- fix(lsp): wasm file import completions (#27018)
- fix(node): correct resolution of dynamic import of esm from cjs (#27071)
- fix(node/fs): add missing stat path argument validation (#27086)
- fix(node/fs): missing uv error context for readFile (#27011)
- fix(node/http): casing ignored in ServerResponse.hasHeader() (#27105)
- fix(node/timers): error when passing id to clearTimeout/clearInterval (#27130)
- fix(runtime/ops): Fix watchfs remove event (#27041)
- fix(streams): reject `string` in `ReadableStream.from` type (#25116)
- fix(task): handle carriage return in task description (#27099)
- fix(task): handle multiline descriptions properly (#27069)
- fix(task): strip ansi codes and control chars when printing tasks (#27100)
- fix(tools/doc): HTML resolve main entrypoint from config file (#27103)
- fix: support bun specifiers in JSR publish (#24588)
- fix: support non-function exports in Wasm modules (#26992)
- perf(compile): read embedded files as static references when UTF-8 and reading
as strings (#27033)
- perf(ext/webstorage): use object wrap for `Storage` (#26931)
### 2.1.1 / 2024.11.21
- docs(add): clarification to add command (#26968)

View file

@ -2,7 +2,7 @@
[package]
name = "deno_bench_util"
version = "0.173.0"
version = "0.174.0"
authors.workspace = true
edition.workspace = true
license.workspace = true

View file

@ -2,7 +2,7 @@
[package]
name = "deno"
version = "2.1.1"
version = "2.1.2"
authors.workspace = true
default-run = "deno"
edition.workspace = true

View file

@ -22,6 +22,8 @@ impl<'a> deno_config::fs::DenoConfigFs for DenoConfigFsAdapter<'a> {
self
.0
.read_text_file_lossy_sync(path, None)
// todo(https://github.com/denoland/deno_config/pull/140): avoid clone
.map(|s| s.into_owned())
.map_err(|err| err.into_io_error())
}

2
cli/cache/mod.rs vendored
View file

@ -116,6 +116,8 @@ impl<'a> deno_cache_dir::DenoCacheEnv for DenoCacheEnvFsAdapter<'a> {
self
.0
.read_file_sync(path, None)
// todo(https://github.com/denoland/deno_cache_dir/pull/66): avoid clone
.map(|bytes| bytes.into_owned())
.map_err(|err| err.into_io_error())
}

View file

@ -6,6 +6,7 @@ use crate::args::CliLockfile;
use crate::args::CliOptions;
use crate::args::DENO_DISABLE_PEDANTIC_NODE_WARNINGS;
use crate::cache;
use crate::cache::FetchCacher;
use crate::cache::GlobalHttpCache;
use crate::cache::ModuleInfoCache;
use crate::cache::ParsedSourceCache;
@ -254,6 +255,23 @@ impl ModuleGraphCreator {
package_configs: &[JsrPackageConfig],
build_fast_check_graph: bool,
) -> Result<ModuleGraph, AnyError> {
struct PublishLoader(FetchCacher);
impl Loader for PublishLoader {
fn load(
&self,
specifier: &deno_ast::ModuleSpecifier,
options: deno_graph::source::LoadOptions,
) -> deno_graph::source::LoadFuture {
if specifier.scheme() == "bun" {
return Box::pin(std::future::ready(Ok(Some(
deno_graph::source::LoadResponse::External {
specifier: specifier.clone(),
},
))));
}
self.0.load(specifier, options)
}
}
fn graph_has_external_remote(graph: &ModuleGraph) -> bool {
// Earlier on, we marked external non-JSR modules as external.
// If the graph contains any of those, it would cause type checking
@ -271,12 +289,15 @@ impl ModuleGraphCreator {
for package_config in package_configs {
roots.extend(package_config.config_file.resolve_export_value_urls()?);
}
let loader = self.module_graph_builder.create_graph_loader();
let mut publish_loader = PublishLoader(loader);
let mut graph = self
.create_graph_with_options(CreateGraphOptions {
is_dynamic: false,
graph_kind: deno_graph::GraphKind::All,
roots,
loader: None,
loader: Some(&mut publish_loader),
})
.await?;
self.graph_valid(&graph)?;

View file

@ -1060,7 +1060,10 @@ impl<TGraphContainer: ModuleGraphContainer> NodeRequireLoader
self.npm_resolver.ensure_read_permission(permissions, path)
}
fn load_text_file_lossy(&self, path: &Path) -> Result<String, AnyError> {
fn load_text_file_lossy(
&self,
path: &Path,
) -> Result<Cow<'static, str>, 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)?;
@ -1075,15 +1078,18 @@ impl<TGraphContainer: ModuleGraphContainer> NodeRequireLoader
.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(),
)
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(),
)
.map(Cow::Owned)
} else {
Ok(text)
}

View file

@ -160,7 +160,7 @@ impl CjsCodeAnalyzer for CliCjsCodeAnalyzer {
if let Ok(source_from_file) =
self.fs.read_text_file_lossy_async(path, None).await
{
Cow::Owned(source_from_file)
source_from_file
} else {
return Ok(ExtNodeCjsAnalysis::Cjs(CjsAnalysisExports {
exports: vec![],

View file

@ -37,7 +37,7 @@ use crate::node::CliNodeCodeTranslator;
use crate::npm::CliNpmResolver;
use crate::npm::InnerCliNpmResolverRef;
use crate::util::sync::AtomicFlag;
use crate::util::text_encoding::from_utf8_lossy_owned;
use crate::util::text_encoding::from_utf8_lossy_cow;
pub type CjsTracker = deno_resolver::cjs::CjsTracker<DenoFsNodeResolverEnv>;
pub type IsCjsResolver =
@ -62,7 +62,10 @@ pub struct ModuleCodeStringSource {
pub struct CliDenoResolverFs(pub Arc<dyn FileSystem>);
impl deno_resolver::fs::DenoResolverFs for CliDenoResolverFs {
fn read_to_string_lossy(&self, path: &Path) -> std::io::Result<String> {
fn read_to_string_lossy(
&self,
path: &Path,
) -> std::io::Result<Cow<'static, str>> {
self
.0
.read_text_file_lossy_sync(path, None)
@ -182,18 +185,21 @@ impl NpmModuleLoader {
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);
let code = from_utf8_lossy_cow(code);
ModuleSourceCode::String(
self
.node_code_translator
.translate_cjs_to_esm(specifier, Some(Cow::Owned(code)))
.translate_cjs_to_esm(specifier, Some(code))
.await?
.into_owned()
.into(),
)
} else {
// esm and json code is untouched
ModuleSourceCode::Bytes(code.into_boxed_slice().into())
ModuleSourceCode::Bytes(match code {
Cow::Owned(bytes) => bytes.into_boxed_slice().into(),
Cow::Borrowed(bytes) => bytes.into(),
})
};
Ok(ModuleCodeStringSource {

View file

@ -282,14 +282,13 @@ impl StandaloneModules {
.vfs
.read_file_all(entry, VfsFileSubDataKind::ModuleGraph)?,
Err(err) if err.kind() == ErrorKind::NotFound => {
let bytes = match RealFs.read_file_sync(&path, None) {
match RealFs.read_file_sync(&path, None) {
Ok(bytes) => bytes,
Err(FsError::Io(err)) if err.kind() == ErrorKind::NotFound => {
return Ok(None)
}
Err(err) => return Err(err.into()),
};
Cow::Owned(bytes)
}
}
Err(err) => return Err(err.into()),
};
@ -694,7 +693,7 @@ impl<'a> DenoCompileBinaryWriter<'a> {
&file_path,
match maybe_source {
Some(source) => source,
None => RealFs.read_file_sync(&file_path, None)?,
None => RealFs.read_file_sync(&file_path, None)?.into_owned(),
},
VfsFileSubDataKind::ModuleGraph,
)

View file

@ -91,6 +91,7 @@ use crate::resolver::CliNpmReqResolver;
use crate::resolver::NpmModuleLoader;
use crate::util::progress_bar::ProgressBar;
use crate::util::progress_bar::ProgressBarStyle;
use crate::util::text_encoding::from_utf8_lossy_cow;
use crate::util::v8::construct_v8_flags;
use crate::worker::CliCodeCache;
use crate::worker::CliMainWorkerFactory;
@ -516,13 +517,13 @@ impl NodeRequireLoader for EmbeddedModuleLoader {
fn load_text_file_lossy(
&self,
path: &std::path::Path,
) -> Result<String, AnyError> {
) -> Result<Cow<'static, str>, AnyError> {
let file_entry = self.shared.vfs.file_entry(path)?;
let file_bytes = self
.shared
.vfs
.read_file_all(file_entry, VfsFileSubDataKind::ModuleGraph)?;
Ok(String::from_utf8(file_bytes.into_owned())?)
Ok(from_utf8_lossy_cow(file_bytes))
}
fn is_maybe_cjs(

View file

@ -743,15 +743,12 @@ impl deno_io::fs::File for FileBackedVfsFile {
Err(FsError::NotSupported)
}
fn read_all_sync(self: Rc<Self>) -> FsResult<Vec<u8>> {
self.read_to_end().map(|bytes| bytes.into_owned())
fn read_all_sync(self: Rc<Self>) -> FsResult<Cow<'static, [u8]>> {
self.read_to_end()
}
async fn read_all_async(self: Rc<Self>) -> FsResult<Vec<u8>> {
async fn read_all_async(self: Rc<Self>) -> FsResult<Cow<'static, [u8]>> {
let inner = (*self).clone();
tokio::task::spawn_blocking(move || {
inner.read_to_end().map(|bytes| bytes.into_owned())
})
.await?
tokio::task::spawn_blocking(move || inner.read_to_end()).await?
}
fn chmod_sync(self: Rc<Self>, _pathmode: u32) -> FsResult<()> {

View file

@ -49,19 +49,67 @@ pub async fn info(
let module_graph_creator = factory.module_graph_creator().await?;
let npm_resolver = factory.npm_resolver().await?;
let maybe_lockfile = cli_options.maybe_lockfile();
let resolver = factory.workspace_resolver().await?.clone();
let npmrc = cli_options.npmrc();
let resolver = factory.workspace_resolver().await?;
let node_resolver = factory.node_resolver().await?;
let cwd_url =
url::Url::from_directory_path(cli_options.initial_cwd()).unwrap();
let maybe_import_specifier = if let Some(import_map) =
resolver.maybe_import_map()
let maybe_import_specifier = if let Ok(resolved) =
resolver.resolve(&specifier, &cwd_url)
{
if let Ok(imports_specifier) = import_map.resolve(&specifier, &cwd_url) {
Some(imports_specifier)
} else {
None
match resolved {
deno_config::workspace::MappedResolution::Normal {
specifier, ..
}
| deno_config::workspace::MappedResolution::ImportMap {
specifier,
..
}
| deno_config::workspace::MappedResolution::WorkspaceJsrPackage {
specifier,
..
} => Some(specifier),
deno_config::workspace::MappedResolution::WorkspaceNpmPackage {
target_pkg_json,
sub_path,
..
} => Some(node_resolver.resolve_package_subpath_from_deno_module(
target_pkg_json.clone().dir_path(),
sub_path.as_deref(),
Some(&cwd_url),
node_resolver::ResolutionMode::Import,
node_resolver::NodeResolutionKind::Execution,
)?),
deno_config::workspace::MappedResolution::PackageJson {
alias,
sub_path,
dep_result,
..
} => match dep_result.as_ref().map_err(|e| e.clone())? {
deno_package_json::PackageJsonDepValue::Workspace(version_req) => {
let pkg_folder = resolver
.resolve_workspace_pkg_json_folder_for_pkg_json_dep(
alias,
version_req,
)?;
Some(node_resolver.resolve_package_subpath_from_deno_module(
pkg_folder,
sub_path.as_deref(),
Some(&cwd_url),
node_resolver::ResolutionMode::Import,
node_resolver::NodeResolutionKind::Execution,
)?)
}
deno_package_json::PackageJsonDepValue::Req(req) => {
Some(ModuleSpecifier::parse(&format!(
"npm:{}{}",
req,
sub_path.map(|s| format!("/{}", s)).unwrap_or_default()
))?)
}
},
}
} else {
None

View file

@ -252,8 +252,46 @@ Deno.test(function addTest() {
Ok(0)
}
fn npm_name_to_create_package(name: &str) -> String {
let mut s = "npm:".to_string();
let mut scoped = false;
let mut create = false;
for (i, ch) in name.char_indices() {
if i == 0 {
if ch == '@' {
scoped = true;
} else {
create = true;
s.push_str("create-");
}
} else if scoped {
if ch == '/' {
scoped = false;
create = true;
s.push_str("/create-");
continue;
} else if ch == '@' && !create {
scoped = false;
create = true;
s.push_str("/create@");
continue;
}
}
s.push(ch);
}
if !create {
s.push_str("/create");
}
s
}
async fn init_npm(name: &str, args: Vec<String>) -> Result<i32, AnyError> {
let script_name = format!("npm:create-{}", name);
let script_name = npm_name_to_create_package(name);
fn print_manual_usage(script_name: &str, args: &[String]) -> i32 {
log::info!("{}", cformat!("You can initialize project manually by running <u>deno run {} {}</> and applying desired permissions.", script_name, args.join(" ")));
@ -336,3 +374,37 @@ fn create_file(
Ok(())
}
}
#[cfg(test)]
mod test {
use crate::tools::init::npm_name_to_create_package;
#[test]
fn npm_name_to_create_package_test() {
// See https://docs.npmjs.com/cli/v8/commands/npm-init#description
assert_eq!(
npm_name_to_create_package("foo"),
"npm:create-foo".to_string()
);
assert_eq!(
npm_name_to_create_package("foo@1.0.0"),
"npm:create-foo@1.0.0".to_string()
);
assert_eq!(
npm_name_to_create_package("@foo"),
"npm:@foo/create".to_string()
);
assert_eq!(
npm_name_to_create_package("@foo@1.0.0"),
"npm:@foo/create@1.0.0".to_string()
);
assert_eq!(
npm_name_to_create_package("@foo/bar"),
"npm:@foo/create-bar".to_string()
);
assert_eq!(
npm_name_to_create_package("@foo/bar@1.0.0"),
"npm:@foo/create-bar@1.0.0".to_string()
);
}
}

View file

@ -476,7 +476,7 @@ impl Diagnostic for PublishDiagnostic {
InvalidExternalImport { imported, .. } => Cow::Owned(vec![
Cow::Owned(format!("the import was resolved to '{}'", imported)),
Cow::Borrowed("this specifier is not allowed to be imported on jsr"),
Cow::Borrowed("jsr only supports importing `jsr:`, `npm:`, and `data:` specifiers"),
Cow::Borrowed("jsr only supports importing `jsr:`, `npm:`, `data:`, `bun:`, and `node:` specifiers"),
]),
UnsupportedJsxTsx { .. } => Cow::Owned(vec![
Cow::Borrowed("follow https://github.com/jsr-io/jsr/issues/24 for updates"),

View file

@ -47,7 +47,7 @@ impl GraphDiagnosticsCollector {
resolution: &ResolutionResolved| {
if visited.insert(resolution.specifier.clone()) {
match resolution.specifier.scheme() {
"file" | "data" | "node" => {}
"file" | "data" | "node" | "bun" => {}
"jsr" => {
skip_specifiers.insert(resolution.specifier.clone());

View file

@ -97,11 +97,10 @@ pub async fn publish(
match cli_options.start_dir.maybe_deno_json() {
Some(deno_json) => {
debug_assert!(!deno_json.is_package());
if deno_json.json.name.is_none() {
bail!("Missing 'name' field in '{}'.", deno_json.specifier);
}
error_missing_exports_field(deno_json)?;
bail!(
"Missing 'name' or 'exports' field in '{}'.",
deno_json.specifier
);
}
None => {
bail!(

View file

@ -656,17 +656,21 @@ 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,
&deno_fs::RealFs,
);
Some(Cow::Owned(load_from_node_modules(
&specifier,
state.maybe_npm.as_ref(),
&mut media_type,
&mut is_cjs,
)?))
if module.specifier.scheme() != "file" {
None
} else {
// means it's Deno code importing an npm module
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(),
&mut media_type,
&mut is_cjs,
)?))
}
}
}
} else if let Some(npm) = state

View file

@ -11,6 +11,15 @@ use deno_core::ModuleSourceCode;
static SOURCE_MAP_PREFIX: &[u8] =
b"//# sourceMappingURL=data:application/json;base64,";
#[inline(always)]
pub fn from_utf8_lossy_cow(bytes: Cow<[u8]>) -> Cow<str> {
match bytes {
Cow::Borrowed(bytes) => String::from_utf8_lossy(bytes),
Cow::Owned(bytes) => Cow::Owned(from_utf8_lossy_owned(bytes)),
}
}
#[inline(always)]
pub fn from_utf8_lossy_owned(bytes: Vec<u8>) -> String {
match String::from_utf8_lossy(&bytes) {
Cow::Owned(code) => code,

View file

@ -2,7 +2,7 @@
[package]
name = "deno_broadcast_channel"
version = "0.173.0"
version = "0.174.0"
authors.workspace = true
edition.workspace = true
license.workspace = true

View file

@ -2,7 +2,7 @@
[package]
name = "deno_cache"
version = "0.111.0"
version = "0.112.0"
authors.workspace = true
edition.workspace = true
license.workspace = true

View file

@ -2,7 +2,7 @@
[package]
name = "deno_canvas"
version = "0.48.0"
version = "0.49.0"
authors.workspace = true
edition.workspace = true
license.workspace = true

View file

@ -2,7 +2,7 @@
[package]
name = "deno_console"
version = "0.179.0"
version = "0.180.0"
authors.workspace = true
edition.workspace = true
license.workspace = true

View file

@ -2,7 +2,7 @@
[package]
name = "deno_cron"
version = "0.59.0"
version = "0.60.0"
authors.workspace = true
edition.workspace = true
license.workspace = true

View file

@ -2,7 +2,7 @@
[package]
name = "deno_crypto"
version = "0.193.0"
version = "0.194.0"
authors.workspace = true
edition.workspace = true
license.workspace = true

View file

@ -2,7 +2,7 @@
[package]
name = "deno_fetch"
version = "0.203.0"
version = "0.204.0"
authors.workspace = true
edition.workspace = true
license.workspace = true

View file

@ -2,7 +2,7 @@
[package]
name = "deno_ffi"
version = "0.166.0"
version = "0.167.0"
authors.workspace = true
edition.workspace = true
license.workspace = true

View file

@ -578,7 +578,7 @@ class FsFile {
this.#rid = rid;
if (!symbol || symbol !== SymbolFor("Deno.internal.FsFile")) {
throw new TypeError(
"`Deno.FsFile` cannot be constructed, use `Deno.open()` or `Deno.openSync()` instead.",
"'Deno.FsFile' cannot be constructed, use 'Deno.open()' or 'Deno.openSync()' instead",
);
}
}
@ -713,11 +713,15 @@ function checkOpenOptions(options) {
(val) => val === true,
).length === 0
) {
throw new Error("OpenOptions requires at least one option to be true");
throw new Error(
"'options' requires at least one option to be true",
);
}
if (options.truncate && !options.write) {
throw new Error("'truncate' option requires 'write' option");
throw new Error(
"'truncate' option requires 'write' to be true",
);
}
const createOrCreateNewWithoutWriteOrAppend =
@ -726,7 +730,7 @@ function checkOpenOptions(options) {
if (createOrCreateNewWithoutWriteOrAppend) {
throw new Error(
"'create' or 'createNew' options require 'write' or 'append' option",
"'create' or 'createNew' options require 'write' or 'append' to be true",
);
}
}

View file

@ -2,7 +2,7 @@
[package]
name = "deno_fs"
version = "0.89.0"
version = "0.90.0"
authors.workspace = true
edition.workspace = true
license.workspace = true

View file

@ -3,6 +3,7 @@
// Allow using Arc for this module.
#![allow(clippy::disallowed_types)]
use std::borrow::Cow;
use std::collections::hash_map::Entry;
use std::collections::HashMap;
use std::io::Error;
@ -457,11 +458,11 @@ impl FileSystem for InMemoryFs {
&self,
path: &Path,
_access_check: Option<AccessCheckCb>,
) -> FsResult<Vec<u8>> {
) -> FsResult<Cow<'static, [u8]>> {
let entry = self.get_entry(path);
match entry {
Some(entry) => match &*entry {
PathEntry::File(data) => Ok(data.clone()),
PathEntry::File(data) => Ok(Cow::Owned(data.clone())),
PathEntry::Dir => Err(FsError::Io(Error::new(
ErrorKind::InvalidInput,
"Is a directory",
@ -474,7 +475,7 @@ impl FileSystem for InMemoryFs {
&'a self,
path: PathBuf,
access_check: Option<AccessCheckCb<'a>>,
) -> FsResult<Vec<u8>> {
) -> FsResult<Cow<'static, [u8]>> {
self.read_file_sync(&path, access_check)
}
}

View file

@ -1,5 +1,6 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
use core::str;
use std::borrow::Cow;
use std::path::Path;
use std::path::PathBuf;
@ -288,7 +289,7 @@ pub trait FileSystem: std::fmt::Debug + MaybeSend + MaybeSync {
&self,
path: &Path,
access_check: Option<AccessCheckCb>,
) -> FsResult<Vec<u8>> {
) -> FsResult<Cow<'static, [u8]>> {
let options = OpenOptions::read();
let file = self.open_sync(path, options, access_check)?;
let buf = file.read_all_sync()?;
@ -298,7 +299,7 @@ pub trait FileSystem: std::fmt::Debug + MaybeSend + MaybeSync {
&'a self,
path: PathBuf,
access_check: Option<AccessCheckCb<'a>>,
) -> FsResult<Vec<u8>> {
) -> FsResult<Cow<'static, [u8]>> {
let options = OpenOptions::read();
let file = self.open_async(path, options, access_check).await?;
let buf = file.read_all_async().await?;
@ -327,17 +328,25 @@ pub trait FileSystem: std::fmt::Debug + MaybeSend + MaybeSync {
&self,
path: &Path,
access_check: Option<AccessCheckCb>,
) -> FsResult<String> {
) -> FsResult<Cow<'static, str>> {
let buf = self.read_file_sync(path, access_check)?;
Ok(string_from_utf8_lossy(buf))
Ok(string_from_cow_utf8_lossy(buf))
}
async fn read_text_file_lossy_async<'a>(
&'a self,
path: PathBuf,
access_check: Option<AccessCheckCb<'a>>,
) -> FsResult<String> {
) -> FsResult<Cow<'static, str>> {
let buf = self.read_file_async(path, access_check).await?;
Ok(string_from_utf8_lossy(buf))
Ok(string_from_cow_utf8_lossy(buf))
}
}
#[inline(always)]
fn string_from_cow_utf8_lossy(buf: Cow<'static, [u8]>) -> Cow<'static, str> {
match buf {
Cow::Owned(buf) => Cow::Owned(string_from_utf8_lossy(buf)),
Cow::Borrowed(buf) => String::from_utf8_lossy(buf),
}
}

View file

@ -17,6 +17,7 @@ pub use crate::interface::OpenOptions;
pub use crate::ops::FsOpsError;
pub use crate::ops::FsOpsErrorKind;
pub use crate::ops::OperationError;
pub use crate::ops::V8MaybeStaticStr;
pub use crate::std_fs::RealFs;
pub use crate::sync::MaybeSend;
pub use crate::sync::MaybeSync;

View file

@ -1,5 +1,6 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
use std::borrow::Cow;
use std::cell::RefCell;
use std::error::Error;
use std::fmt::Formatter;
@ -18,12 +19,15 @@ use crate::FsPermissions;
use crate::OpenOptions;
use boxed_error::Boxed;
use deno_core::op2;
use deno_core::v8;
use deno_core::CancelFuture;
use deno_core::CancelHandle;
use deno_core::FastString;
use deno_core::JsBuffer;
use deno_core::OpState;
use deno_core::ResourceId;
use deno_core::ToJsBuffer;
use deno_core::ToV8;
use deno_io::fs::FileResource;
use deno_io::fs::FsError;
use deno_io::fs::FsStat;
@ -1333,7 +1337,8 @@ where
.read_file_sync(&path, Some(&mut access_check))
.map_err(|error| map_permission_error("readfile", error, &path))?;
Ok(buf.into())
// todo(https://github.com/denoland/deno/issues/27107): do not clone here
Ok(buf.into_owned().into_boxed_slice().into())
}
#[op2(async, stack_trace)]
@ -1375,15 +1380,61 @@ where
.map_err(|error| map_permission_error("readfile", error, &path))?
};
Ok(buf.into())
// todo(https://github.com/denoland/deno/issues/27107): do not clone here
Ok(buf.into_owned().into_boxed_slice().into())
}
// todo(https://github.com/denoland/deno_core/pull/986): remove
// when upgrading deno_core
#[derive(Debug)]
pub struct FastStringV8AllocationError;
impl std::error::Error for FastStringV8AllocationError {}
impl std::fmt::Display for FastStringV8AllocationError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(
f,
"failed to allocate string; buffer exceeds maximum length"
)
}
}
/// Maintains a static reference to the string if possible.
pub struct V8MaybeStaticStr(pub Cow<'static, str>);
impl<'s> ToV8<'s> for V8MaybeStaticStr {
type Error = FastStringV8AllocationError;
#[inline]
fn to_v8(
self,
scope: &mut v8::HandleScope<'s>,
) -> Result<v8::Local<'s, v8::Value>, Self::Error> {
// todo(https://github.com/denoland/deno_core/pull/986): remove this check
// when upgrading deno_core
const MAX_V8_STRING_LENGTH: usize = 536870888;
if self.0.len() > MAX_V8_STRING_LENGTH {
return Err(FastStringV8AllocationError);
}
Ok(
match self.0 {
Cow::Borrowed(text) => FastString::from_static(text),
Cow::Owned(value) => value.into(),
}
.v8_string(scope)
.into(),
)
}
}
#[op2(stack_trace)]
#[string]
#[to_v8]
pub fn op_fs_read_file_text_sync<P>(
state: &mut OpState,
#[string] path: String,
) -> Result<String, FsOpsError>
) -> Result<V8MaybeStaticStr, FsOpsError>
where
P: FsPermissions + 'static,
{
@ -1395,17 +1446,16 @@ where
let str = fs
.read_text_file_lossy_sync(&path, Some(&mut access_check))
.map_err(|error| map_permission_error("readfile", error, &path))?;
Ok(str)
Ok(V8MaybeStaticStr(str))
}
#[op2(async, stack_trace)]
#[string]
#[to_v8]
pub async fn op_fs_read_file_text_async<P>(
state: Rc<RefCell<OpState>>,
#[string] path: String,
#[smi] cancel_rid: Option<ResourceId>,
) -> Result<String, FsOpsError>
) -> Result<V8MaybeStaticStr, FsOpsError>
where
P: FsPermissions + 'static,
{
@ -1439,7 +1489,7 @@ where
.map_err(|error| map_permission_error("readfile", error, &path))?
};
Ok(str)
Ok(V8MaybeStaticStr(str))
}
fn to_seek_from(offset: i64, whence: i32) -> Result<SeekFrom, FsOpsError> {

View file

@ -2,6 +2,7 @@
#![allow(clippy::disallowed_methods)]
use std::borrow::Cow;
use std::env::current_dir;
use std::fs;
use std::io;
@ -371,7 +372,7 @@ impl FileSystem for RealFs {
&self,
path: &Path,
access_check: Option<AccessCheckCb>,
) -> FsResult<Vec<u8>> {
) -> FsResult<Cow<'static, [u8]>> {
let mut file = open_with_access_check(
OpenOptions {
read: true,
@ -382,13 +383,13 @@ impl FileSystem for RealFs {
)?;
let mut buf = Vec::new();
file.read_to_end(&mut buf)?;
Ok(buf)
Ok(Cow::Owned(buf))
}
async fn read_file_async<'a>(
&'a self,
path: PathBuf,
access_check: Option<AccessCheckCb<'a>>,
) -> FsResult<Vec<u8>> {
) -> FsResult<Cow<'static, [u8]>> {
let mut file = open_with_access_check(
OpenOptions {
read: true,
@ -400,7 +401,7 @@ impl FileSystem for RealFs {
spawn_blocking(move || {
let mut buf = Vec::new();
file.read_to_end(&mut buf)?;
Ok::<_, FsError>(buf)
Ok::<_, FsError>(Cow::Owned(buf))
})
.await?
.map_err(Into::into)

View file

@ -2,7 +2,7 @@
[package]
name = "deno_http"
version = "0.177.0"
version = "0.178.0"
authors.workspace = true
edition.workspace = true
license.workspace = true

View file

@ -2,7 +2,7 @@
[package]
name = "deno_io"
version = "0.89.0"
version = "0.90.0"
authors.workspace = true
edition.workspace = true
license.workspace = true

View file

@ -215,8 +215,8 @@ pub trait File {
fn write_all_sync(self: Rc<Self>, buf: &[u8]) -> FsResult<()>;
async fn write_all(self: Rc<Self>, buf: BufView) -> FsResult<()>;
fn read_all_sync(self: Rc<Self>) -> FsResult<Vec<u8>>;
async fn read_all_async(self: Rc<Self>) -> FsResult<Vec<u8>>;
fn read_all_sync(self: Rc<Self>) -> FsResult<Cow<'static, [u8]>>;
async fn read_all_async(self: Rc<Self>) -> FsResult<Cow<'static, [u8]>>;
fn chmod_sync(self: Rc<Self>, pathmode: u32) -> FsResult<()>;
async fn chmod_async(self: Rc<Self>, mode: u32) -> FsResult<()>;

View file

@ -789,26 +789,26 @@ impl crate::fs::File for StdFileResourceInner {
}
}
fn read_all_sync(self: Rc<Self>) -> FsResult<Vec<u8>> {
fn read_all_sync(self: Rc<Self>) -> FsResult<Cow<'static, [u8]>> {
match self.kind {
StdFileResourceKind::File | StdFileResourceKind::Stdin(_) => {
let mut buf = Vec::new();
self.with_sync(|file| Ok(file.read_to_end(&mut buf)?))?;
Ok(buf)
Ok(Cow::Owned(buf))
}
StdFileResourceKind::Stdout | StdFileResourceKind::Stderr => {
Err(FsError::NotSupported)
}
}
}
async fn read_all_async(self: Rc<Self>) -> FsResult<Vec<u8>> {
async fn read_all_async(self: Rc<Self>) -> FsResult<Cow<'static, [u8]>> {
match self.kind {
StdFileResourceKind::File | StdFileResourceKind::Stdin(_) => {
self
.with_inner_blocking_task(|file| {
let mut buf = Vec::new();
file.read_to_end(&mut buf)?;
Ok(buf)
Ok(Cow::Owned(buf))
})
.await
}

View file

@ -2,7 +2,7 @@
[package]
name = "deno_kv"
version = "0.87.0"
version = "0.88.0"
authors.workspace = true
edition.workspace = true
license.workspace = true

View file

@ -2,7 +2,7 @@
[package]
name = "deno_napi"
version = "0.110.0"
version = "0.111.0"
authors.workspace = true
edition.workspace = true
license.workspace = true

View file

@ -2,7 +2,7 @@
[package]
name = "napi_sym"
version = "0.109.0"
version = "0.110.0"
authors.workspace = true
edition.workspace = true
license.workspace = true

View file

@ -2,7 +2,7 @@
[package]
name = "deno_net"
version = "0.171.0"
version = "0.172.0"
authors.workspace = true
edition.workspace = true
license.workspace = true

View file

@ -2,7 +2,7 @@
[package]
name = "deno_node"
version = "0.116.0"
version = "0.117.0"
authors.workspace = true
edition.workspace = true
license.workspace = true

View file

@ -157,7 +157,10 @@ pub trait NodeRequireLoader {
path: &'a Path,
) -> Result<Cow<'a, Path>, AnyError>;
fn load_text_file_lossy(&self, path: &Path) -> Result<String, AnyError>;
fn load_text_file_lossy(
&self,
path: &Path,
) -> Result<Cow<'static, str>, AnyError>;
/// Get if the module kind is maybe CJS and loading should determine
/// if its CJS or ESM.
@ -873,6 +876,8 @@ impl deno_package_json::fs::DenoPkgJsonFs for DenoFsNodeResolverEnv {
self
.fs
.read_text_file_lossy_sync(path, None)
// todo(https://github.com/denoland/deno_package_json/pull/9): don't clone
.map(|text| text.into_owned())
.map_err(|err| err.into_io_error())
}
}
@ -887,6 +892,8 @@ impl<'a> deno_package_json::fs::DenoPkgJsonFs for DenoPkgJsonFsAdapter<'a> {
self
.0
.read_text_file_lossy_sync(path, None)
// todo(https://github.com/denoland/deno_package_json/pull/9): don't clone
.map(|text| text.into_owned())
.map_err(|err| err.into_io_error())
}
}

View file

@ -8,6 +8,7 @@ use deno_core::v8;
use deno_core::JsRuntimeInspector;
use deno_core::OpState;
use deno_fs::FileSystemRc;
use deno_fs::V8MaybeStaticStr;
use deno_package_json::PackageJsonRc;
use deno_path_util::normalize_path;
use deno_path_util::url_from_file_path;
@ -477,11 +478,11 @@ where
}
#[op2(stack_trace)]
#[string]
#[to_v8]
pub fn op_require_read_file<P>(
state: &mut OpState,
#[string] file_path: String,
) -> Result<String, RequireError>
) -> Result<V8MaybeStaticStr, RequireError>
where
P: NodePermissions + 'static,
{
@ -492,6 +493,7 @@ where
let loader = state.borrow::<NodeRequireLoaderRc>();
loader
.load_text_file_lossy(&file_path)
.map(V8MaybeStaticStr)
.map_err(|e| RequireErrorKind::ReadModule(e).into_box())
}

View file

@ -148,9 +148,13 @@ export class TLSSocket extends net.Socket {
: new TCP(TCPConstants.SOCKET);
}
const { promise, resolve } = Promise.withResolvers();
// Patches `afterConnect` hook to replace TCP conn with TLS conn
const afterConnect = handle.afterConnect;
handle.afterConnect = async (req: any, status: number) => {
options.hostname ??= undefined; // coerce to undefined if null, startTls expects hostname to be undefined
try {
const conn = await Deno.startTls(handle[kStreamBaseField], options);
try {
@ -164,15 +168,25 @@ export class TLSSocket extends net.Socket {
// Don't interrupt "secure" event to let the first read/write
// operation emit the error.
}
// Assign the TLS connection to the handle and resume reading.
handle[kStreamBaseField] = conn;
handle.upgrading = false;
if (!handle.pauseOnCreate) {
handle.readStart();
}
resolve();
tlssock.emit("secure");
tlssock.removeListener("end", onConnectEnd);
} catch (_) {
} catch {
// TODO(kt3k): Handle this
}
return afterConnect.call(handle, req, status);
};
handle.upgrading = promise;
(handle as any).verifyError = function () {
return null; // Never fails, rejectUnauthorized is always true in Deno.
};

View file

@ -479,13 +479,13 @@ export class ClientHttp2Session extends Http2Session {
socket.on("error", socketOnError);
socket.on("close", socketOnClose);
socket[kHandle].pauseOnCreate = true;
const connPromise = new Promise((resolve) => {
const eventName = url.startsWith("https") ? "secureConnect" : "connect";
socket.once(eventName, () => {
const rid = socket[kHandle][kStreamBaseField][internalRidSymbol];
nextTick(() => {
resolve(rid);
});
nextTick(() => resolve(rid));
});
});
socket[kSession] = this;

View file

@ -320,8 +320,16 @@ export class LibuvStreamWrap extends HandleWrap {
/** Internal method for reading from the attached stream. */
async #read() {
let buf = this.#buf;
let nread: number | null;
const ridBefore = this[kStreamBaseField]![internalRidSymbol];
if (this.upgrading) {
// Starting an upgrade, stop reading. Upgrading will resume reading.
this.readStop();
return;
}
try {
nread = await this[kStreamBaseField]!.read(buf);
} catch (e) {
@ -382,6 +390,11 @@ export class LibuvStreamWrap extends HandleWrap {
const ridBefore = this[kStreamBaseField]![internalRidSymbol];
if (this.upgrading) {
// There is an upgrade in progress, queue the write request.
await this.upgrading;
}
let nwritten = 0;
try {
// TODO(crowlKats): duplicate from runtime/js/13_buffer.js
@ -400,7 +413,6 @@ export class LibuvStreamWrap extends HandleWrap {
}
let status: number;
// TODO(cmorten): map err to status codes
if (
e instanceof Deno.errors.BadResource ||

View file

@ -54,7 +54,7 @@ export function clearTimeout(timeout?: Timeout | number) {
const id = +timeout;
const timer = MapPrototypeGet(activeTimers, id);
if (timer) {
timeout._destroyed = true;
timer._destroyed = true;
MapPrototypeDelete(activeTimers, id);
}
clearTimeout_(id);
@ -74,7 +74,7 @@ export function clearInterval(timeout?: Timeout | number | string) {
const id = +timeout;
const timer = MapPrototypeGet(activeTimers, id);
if (timer) {
timeout._destroyed = true;
timer._destroyed = true;
MapPrototypeDelete(activeTimers, id);
}
clearInterval_(id);

View file

@ -2,7 +2,7 @@
[package]
name = "deno_telemetry"
version = "0.1.0"
version = "0.2.0"
authors.workspace = true
edition.workspace = true
license.workspace = true

View file

@ -2,7 +2,7 @@
[package]
name = "deno_tls"
version = "0.166.0"
version = "0.167.0"
authors.workspace = true
edition.workspace = true
license.workspace = true

View file

@ -2,7 +2,7 @@
[package]
name = "deno_url"
version = "0.179.0"
version = "0.180.0"
authors.workspace = true
edition.workspace = true
license.workspace = true

View file

@ -2,7 +2,7 @@
[package]
name = "deno_web"
version = "0.210.0"
version = "0.211.0"
authors.workspace = true
edition.workspace = true
license.workspace = true

View file

@ -2,7 +2,7 @@
[package]
name = "deno_webgpu"
version = "0.146.0"
version = "0.147.0"
authors = ["the Deno authors"]
edition.workspace = true
license = "MIT"

View file

@ -2,7 +2,7 @@
[package]
name = "deno_webidl"
version = "0.179.0"
version = "0.180.0"
authors.workspace = true
edition.workspace = true
license.workspace = true

View file

@ -2,7 +2,7 @@
[package]
name = "deno_websocket"
version = "0.184.0"
version = "0.185.0"
authors.workspace = true
edition.workspace = true
license.workspace = true

View file

@ -2,7 +2,7 @@
[package]
name = "deno_webstorage"
version = "0.174.0"
version = "0.175.0"
authors.workspace = true
edition.workspace = true
license.workspace = true

View file

@ -2,7 +2,7 @@
[package]
name = "deno_resolver"
version = "0.11.0"
version = "0.12.0"
authors.workspace = true
edition.workspace = true
license.workspace = true

View file

@ -1,5 +1,6 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
use std::borrow::Cow;
use std::path::Path;
use std::path::PathBuf;
@ -10,7 +11,10 @@ pub struct DirEntry {
}
pub trait DenoResolverFs {
fn read_to_string_lossy(&self, path: &Path) -> std::io::Result<String>;
fn read_to_string_lossy(
&self,
path: &Path,
) -> std::io::Result<Cow<'static, str>>;
fn realpath_sync(&self, path: &Path) -> std::io::Result<PathBuf>;
fn exists_sync(&self, path: &Path) -> bool;
fn is_dir_sync(&self, path: &Path) -> bool;

View file

@ -2,7 +2,7 @@
[package]
name = "node_resolver"
version = "0.18.0"
version = "0.19.0"
authors.workspace = true
edition.workspace = true
license.workspace = true

View file

@ -2,7 +2,7 @@
[package]
name = "deno_runtime"
version = "0.188.0"
version = "0.189.0"
authors.workspace = true
edition.workspace = true
license.workspace = true

View file

@ -2,7 +2,7 @@
[package]
name = "deno_permissions"
version = "0.39.0"
version = "0.40.0"
authors.workspace = true
edition.workspace = true
license.workspace = true

View file

@ -1,9 +1,21 @@
{
"tempDir": true,
"steps": [
{
"args": "info --quiet main.ts",
"output": "info.out"
"tests": {
"resolves_npm_deps": {
"steps": [
{
"args": "info --quiet main.ts",
"output": "info.out"
}
]
},
"bare_specifier": {
"steps": [
{
"args": "info --quiet @denotest/esm-basic",
"output": "info_bare.out"
}
]
}
]
}
}

View file

@ -0,0 +1,4 @@
dependencies: 0 unique
size: 471B
npm:/@denotest/esm-basic@1.0.0 (471B)

View file

@ -11,6 +11,18 @@
"cwd": "member/sub",
"output": "info_workspace_member_sub.out",
"exitCode": 0
},
"member_bare_specifier": {
"args": "info @denotest/workspace-member",
"output": "info_bare_specifier.out"
},
"member_package_json_specifier": {
"args": "info @denotest/workspace-member-package-json",
"output": "info_bare_specifier_package_json.out"
},
"member_package_json_specifier_subpath": {
"args": "info @denotest/workspace-member-package-json/foo",
"output": "info_bare_specifier_package_json_subpath.out"
}
}
}

View file

@ -1,3 +1,3 @@
{
"workspace": ["./member"]
"workspace": ["./member", "./member2", "./member3"]
}

View file

@ -0,0 +1,6 @@
local: [WILDCARD]mod.ts
type: TypeScript
dependencies: 0 unique
size: [WILDCARD]
file://[WILDCARD]member/mod.ts ([WILDCARD])

View file

@ -0,0 +1,6 @@
local: [WILDCARD]mod.ts
type: TypeScript
dependencies: 0 unique
size: [WILDCARD]
file://[WILDCARD]member3/mod.ts ([WILDCARD])

View file

@ -0,0 +1,6 @@
local: [WILDCARD]bar.ts
type: TypeScript
dependencies: 0 unique
size: [WILDCARD]
file://[WILDCARD]member3/bar.ts ([WILDCARD])

View file

@ -1,4 +1,6 @@
{
"name": "@denotest/workspace-member",
"exports": "./mod.ts",
"imports": {
"foo": "./sub/file.ts"
}

View file

@ -0,0 +1,3 @@
export function hi() {
console.log("hi");
}

View file

@ -0,0 +1 @@
{}

View file

@ -0,0 +1,7 @@
{
"name": "@denotest/workspace-member-package-json",
"exports": {
".": "./mod.ts",
"./foo": "./bar.ts"
}
}

View file

@ -0,0 +1,4 @@
{
"args": "publish --token 'sadfasdf'",
"output": "bun_specifier.out"
}

View file

@ -0,0 +1,6 @@
Check file:///[WILDCARD]/mod.ts
Checking for slow types in the public API...
Check file:///[WILDCARD]/mod.ts
Publishing @foo/bar@1.0.0 ...
Successfully published @foo/bar@1.0.0
Visit http://127.0.0.1:4250/@foo/bar@1.0.0 for details

View file

@ -0,0 +1,8 @@
{
"name": "@foo/bar",
"version": "1.0.0",
"exports": {
".": "./mod.ts"
},
"license": "MIT"
}

View file

@ -0,0 +1 @@
import "bun:sqlite";

View file

@ -12,7 +12,7 @@ error[invalid-external-import]: invalid import to a non-JSR 'http' specifier
info: the import was resolved to 'http://localhost:4545/welcome.ts'
info: this specifier is not allowed to be imported on jsr
info: jsr only supports importing `jsr:`, `npm:`, and `data:` specifiers
info: jsr only supports importing `jsr:`, `npm:`, `data:`, `bun:`, and `node:` specifiers
docs: https://jsr.io/go/invalid-external-import
error[invalid-external-import]: invalid import to a non-JSR 'http' specifier
@ -25,7 +25,7 @@ error[invalid-external-import]: invalid import to a non-JSR 'http' specifier
info: the import was resolved to 'http://localhost:4545/echo.ts'
info: this specifier is not allowed to be imported on jsr
info: jsr only supports importing `jsr:`, `npm:`, and `data:` specifiers
info: jsr only supports importing `jsr:`, `npm:`, `data:`, `bun:`, and `node:` specifiers
docs: https://jsr.io/go/invalid-external-import
error: Found 2 problems

View file

@ -13,7 +13,7 @@ error[invalid-external-import]: invalid import to a non-JSR 'http' specifier
info: the import was resolved to 'http://esm.sh/react-dom@18.2.0/server'
info: this specifier is not allowed to be imported on jsr
info: jsr only supports importing `jsr:`, `npm:`, and `data:` specifiers
info: jsr only supports importing `jsr:`, `npm:`, `data:`, `bun:`, and `node:` specifiers
docs: https://jsr.io/go/invalid-external-import
error: Found 1 problem

View file

@ -0,0 +1,5 @@
{
"args": "publish --token 'sadfasdf'",
"output": "publish.out",
"exitCode": 1
}

View file

@ -0,0 +1,4 @@
{
"version": "1.0.0",
"exports": "./mod.ts"
}

View file

@ -0,0 +1,3 @@
export function add(a: number, b: number): number {
return a + b;
}

View file

@ -0,0 +1 @@
error: Missing 'name' field in 'file:///[WILDCARD]deno.json'.

View file

@ -13,7 +13,7 @@ error[invalid-external-import]: invalid import to a non-JSR 'https' specifier
info: the import was resolved to 'https://deno.land/std/assert/assert.ts'
info: this specifier is not allowed to be imported on jsr
info: jsr only supports importing `jsr:`, `npm:`, and `data:` specifiers
info: jsr only supports importing `jsr:`, `npm:`, `data:`, `bun:`, and `node:` specifiers
docs: https://jsr.io/go/invalid-external-import
error: Found 1 problem

View file

@ -137,7 +137,7 @@ Deno.test(async function openOptions() {
await Deno.open(filename, { write: false });
},
Error,
"OpenOptions requires at least one option to be true",
"'options' requires at least one option to be true",
);
await assertRejects(
@ -145,7 +145,7 @@ Deno.test(async function openOptions() {
await Deno.open(filename, { truncate: true, write: false });
},
Error,
"'truncate' option requires 'write' option",
"'truncate' option requires 'write' to be true",
);
await assertRejects(
@ -153,7 +153,7 @@ Deno.test(async function openOptions() {
await Deno.open(filename, { create: true, write: false });
},
Error,
"'create' or 'createNew' options require 'write' or 'append' option",
"'create' or 'createNew' options require 'write' or 'append' to be true",
);
await assertRejects(
@ -161,7 +161,7 @@ Deno.test(async function openOptions() {
await Deno.open(filename, { createNew: true, append: false });
},
Error,
"'create' or 'createNew' options require 'write' or 'append' option",
"'create' or 'createNew' options require 'write' or 'append' to be true",
);
});

View file

@ -100,6 +100,16 @@ Deno.test("[node/timers refresh cancelled timer]", () => {
p.refresh();
});
Deno.test("[node/timers] clearTimeout with number", () => {
const timer = +timers.setTimeout(() => fail(), 10);
timers.clearTimeout(timer);
});
Deno.test("[node/timers] clearInterval with number", () => {
const timer = +timers.setInterval(() => fail(), 10);
timers.clearInterval(timer);
});
Deno.test("[node/timers setImmediate returns Immediate object]", () => {
const { clearImmediate, setImmediate } = timers;

View file

@ -257,3 +257,17 @@ Deno.test("TLSSocket.alpnProtocol is set for client", async () => {
listener.close();
await new Promise((resolve) => outgoing.on("close", resolve));
});
Deno.test("tls connect upgrade tcp", async () => {
const { promise, resolve } = Promise.withResolvers<void>();
const socket = new net.Socket();
socket.connect(443, "google.com");
socket.on("connect", () => {
const secure = tls.connect({ socket });
secure.on("secureConnect", () => resolve());
});
await promise;
socket.destroy();
});