This PR is an attempt to fix
https://github.com/denoland/deno/issues/20293, in which node modules
connecting to databases fail due to TLS errors. I ran into this
attempting to use
[node-postgres](https://github.com/brianc/node-postgres) to connect to a
[Neon](https://neon.tech) database.
Investigating via `--inspect-brk` led me to notice that the hostname
eventually passed to `Deno.startTls` was null. The hostname is
determined by the following code:
f6b889b432/ext/node/polyfills/_tls_wrap.ts (L87-L89)
This logic doesn't appear to be correct. I couldn't find reference to
`servername` existing on the `secureContext` in either Node's or Deno's
docs. There's a lot of scope here, and it's my first time reading
through this code, so I could be missing something!
Node uses [the following
logic](2e458d9736/lib/_tls_wrap.js (L1679-L1682)
) to determine the hostname for certificate validation:
```
const hostname = options.servername ||
options.host ||
(options.socket && options.socket._host) ||
'localhost';
```
This PR updates the `TLSSocket` polyfill to use behave similarly (though
I omitted the default to `localhost` at the end; I'm not sure if
including it is necessary or correct). With this change, `node-postgres`
connects to my TLS endpoint successfully (aside: Neon requires SNI,
which also works as expected).
---
I tried to update the tests in
https://github.com/denoland/deno/blob/main/cli/tests/unit_node/tls_test.ts
to exercise this change, but the test fails for me on `main` on Linux. I
investigated briefly and noticed that the test fixture
`cli/tests/testdata/tls/localhost.crt` doesn't appear to include the
`subjectAltName` specified in `domains.txt`. I believe the certificate
isn't matching `localhost`, but that's where I ended investigating.
This commit refactors how we access "core", "internals" and
"primordials" objects coming from `deno_core`, in our internal JavaScript code.
Instead of capturing them from "globalThis.__bootstrap" namespace, we
import them from recently added "ext:core/mod.js" file.
Add support for signing with a RSA PEM private key: `pkcs8` and `pkcs1`.
Fixes https://github.com/denoland/deno/issues/18972
Ref #21124
Verified fix with `npm:sshpk`. Unverfied but fixes
`npm:google-auth-library`, `npm:web-push` & `oracle/oci-typescript-sdk`
---------
Signed-off-by: Divy Srivastava <dj.srivastava23@gmail.com>
Switch `ext/fetch` over to `resourceForReadableStream` to simplify and
unify implementation with `ext/serve`. This allows us to work in Rust
with resources only.
Two additional changes made to `resourceForReadableStream` were
required:
- Add an optional length to `resourceForReadableStream` which translates
to `size_hint`
- Fix a bug where writing to a closed stream that was full would panic
We can move all promise ID knowledge to deno_core, allowing us to better
experiment with promise implementation in deno_core.
`{un,}refOpPromise(promise)` is equivalent to
`{un,}refOp(promise[promiseIdSymbol])`
Workaround the circular references issue by using a initializer function
to give tty stream class to `initStdin`.
Fixes https://github.com/denoland/deno/issues/21024
Fixes https://github.com/denoland/deno/issues/20611
Fixes https://github.com/denoland/deno/issues/20890
Fixes https://github.com/denoland/deno/issues/20336
`create-svelte` works now:
```
divy@mini /t/a> ~/gh/deno/target/debug/deno run -A --unstable --reload npm:create-svelte@latest sveltekit-deno
create-svelte version 5.1.1
┌ Welcome to SvelteKit!
│
◇ Which Svelte app template?
│ Skeleton project
│
◇ Add type checking with TypeScript?
│ Yes, using JavaScript with JSDoc comments
│
◇ Select additional options (use arrow keys/space bar)
│ none
│
└ Your project is ready!
✔ Type-checked JavaScript
https://www.typescriptlang.org/tsconfig#checkJs
Install community-maintained integrations:
https://github.com/svelte-add/svelte-add
Next steps:
1: cd sveltekit-deno
2: npm install
3: git init && git add -A && git commit -m "Initial commit" (optional)
4: npm run dev -- --open
To close the dev server, hit Ctrl-C
Stuck? Visit us at https://svelte.dev/chat
```
---------
Signed-off-by: Divy Srivastava <dj.srivastava23@gmail.com>
This commit improves "node:http2" module implementation, by enabling
to use "options.createConnection" callback when starting an HTTP2
session.
This change enables to pass basic client-side test with "grpc-js/grpc"
package.
Smaller fixes like "Http2Session.unref()" and "Http2Session.setTimeout()"
were handled as well.
Fixes #16647
For the following example, if I set the encoding to `base64url`, it'll
throw an unexpected TypeError:
```ts
import { Buffer } from "node:buffer";
Buffer.from("IntcImhlbGxvXCI6XCJoZGQvZStpXCJ9Ig", "base64url").toString();
// error: Uncaught TypeError: src.subarray is not a function
// const buf = Buffer.from(
// ^
// at blitBuffer (ext:deno_node/internal/buffer.mjs:1779:15)
// at Uint8Array.base64urlWrite (ext:deno_node/internal/buffer.mjs:691:10)
// at Object.write (ext:deno_node/internal/buffer.mjs:2195:11)
// at Uint8Array.write (ext:deno_node/internal/buffer.mjs:794:14)
// at fromString (ext:deno_node/internal/buffer.mjs:214:22)
// at _from (ext:deno_node/internal/buffer.mjs:119:12)
// at Function.from (ext:deno_node/internal/buffer.mjs:157:10)
// at file:///Users/foodieats/temp/buffer1.ts:3:20
```
The error caused by `base64urlWrite` function, it should call
`forgivingBase64UrlDecode` not `forgivingBase64UrlEncode`
Also fixed #20563 .
This commit improves compatibility of "node:http2" module by polyfilling
"connect" method and "ClientHttp2Session" class. Basic operations like
streaming, header and trailer handling are working correctly.
Refing/unrefing is still a TODO and "npm:grpc-js/grpc" is not yet working
correctly.
---------
Co-authored-by: Matt Mastracci <matthew@mastracci.com>
When trying to run
```
deno run -A --unstable npm:astro dev
```
in my Astro project it fails with:
```
Node.js v18.12.1 is not supported by Astro!
Please upgrade Node.js to a supported version: ">=18.14.1"
```
My current version is:
```
~ ❯ node --version
v20.5.1
```
Bumping the version to the latest stable Release of node in
`ext/node/polyfills/_process/process.ts` fixes this.
I don't know if this causes any conflicts, so please feel free to
correct me here.
The fix for #20188 was not entirely correct -- we were unlocking the
global buffer incorrectly. This PR introduces a lock state that ensures
we only unlock a lock we have taken out.
The goal of this PR is to address issue #20106 where a `TypeError`
occurs when the variables `uid` and `gid` from `userInfo()` in `node:os`
are reassigned if the user is on Windows. Both `uid` and `gid` are
marked as `const` therefore producing a `TypeError` when the two are
reassigned.
This PR achieves that goal by marking `uid` and `gid` as `let`
To fix bugs around detection of when node emulation is required, we will
just eagerly initialize it. The improvements we make to reduce the
impact of the startup time:
- [x] Process stdin/stdout/stderr are lazily created
- [x] node.js global proxy no longer allocates on each access check
- [x] Process checks for `beforeExit` listeners before doing expensive
shutdown work
- [x] Process should avoid adding global event handlers until listeners
are added
Benchmarking this PR (`89de7e1ff`) vs main (`41cad2179`)
```
12:36 $ third_party/prebuilt/mac/hyperfine --warmup 100 -S none './deno-41cad2179 run ./empty.js' './deno-89de7e1ff run ./empty.js'
Benchmark 1: ./deno-41cad2179 run ./empty.js
Time (mean ± σ): 24.3 ms ± 1.6 ms [User: 16.2 ms, System: 6.0 ms]
Range (min … max): 21.1 ms … 29.1 ms 115 runs
Benchmark 2: ./deno-89de7e1ff run ./empty.js
Time (mean ± σ): 24.0 ms ± 1.4 ms [User: 16.3 ms, System: 5.6 ms]
Range (min … max): 21.3 ms … 28.6 ms 126 runs
```
Fixes https://github.com/denoland/deno/issues/20142
Fixes https://github.com/denoland/deno/issues/15826
Fixes https://github.com/denoland/deno/issues/20028
This commit provides basic polyfill for "node:test" module. Currently
only top-level "test" function is polyfilled, all remaining functions from
that module throw not implemented errors.
Code run within Deno-mode and Node-mode should have access to a
slightly different set of globals. Previously this was done through a
compile time code-transform for Node-mode, but this is not ideal and has
many edge cases, for example Node's globalThis having a different
identity than Deno's globalThis.
This commit makes the `globalThis` of the entire runtime a semi-proxy.
This proxy returns a different set of globals depending on the caller's
mode. This is not a full proxy, because it is shadowed by "real"
properties on globalThis. This is done to avoid the overhead of a full
proxy for all globalThis operations.
The globals between Deno-mode and Node-mode are now properly segregated.
This means that code running in Deno-mode will not have access to Node's
globals, and vice versa. Deleting a managed global in Deno-mode will
NOT delete the corresponding global in Node-mode, and vice versa.
---------
Co-authored-by: Bartek Iwańczuk <biwanczuk@gmail.com>
Co-authored-by: Aapo Alasuutari <aapo.alasuutari@gmail.com>
This makes the implementation of "AsyncLocalStorage" from
"node:async_hooks" 3.5x faster than before for noop benchmark
(measuring baseline overhead). It's still 3.5x slower than not
using `AsyncLocalStorage` and 1.64x slower than using
noop promise hooks.
Fixes #19568
Values are not coerced to the desired type during deserialisation. This
makes serde_v8 stricter.
---------
Co-authored-by: Bartek Iwańczuk <biwanczuk@gmail.com>
This commit adds basic support for "node:http2" module. Not
all APIs have been yet implemented, but this change already
allows to use this module for some basic functions.
The "grpc" package is still not working, but it's a good stepping
stone.
---------
Co-authored-by: Bartek Iwańczuk <biwanczuk@gmail.com>
## WHY
ref: https://github.com/denoland/deno/issues/19165
The FileHandle class has many missing methods compared to node.
Add these.
## WHAT
- Add close method
---------
Co-authored-by: Matt Mastracci <matthew@mastracci.com>
<!--
Before submitting a PR, please read https://deno.com/manual/contributing
1. Give the PR a descriptive title.
Examples of good title:
- fix(std/http): Fix race condition in server
- docs(console): Update docstrings
- feat(doc): Handle nested reexports
Examples of bad title:
- fix #7123
- update docs
- fix bugs
2. Ensure there is a related issue and it is referenced in the PR text.
3. Ensure there are tests that cover the changes.
4. Ensure `cargo test` passes.
5. Ensure `./tools/format.js` passes without changing files.
6. Ensure `./tools/lint.js` passes.
7. Open as a draft PR if your work is still in progress. The CI won't
run
all steps, but you can add '[ci]' to a commit message to force it to.
8. If you would like to run the benchmarks on the CI, add the 'ci-bench'
label.
-->
Internally, `node-tap` spawns a child process with `stdio: [0, 1, 2]`.
Whilst we don't support passing fd numbers as an argument so far, it
turns out that `[0, 1, 2]` is equivalent to `"inherit"` which we already
support. See: https://nodejs.org/api/child_process.html#optionsstdio
Mapping it to `"inherit"` is fine for us and gets us one step closer in
getting `node-tap` working. I'm now at the stage where already the
coverage table is shown 🎉
<!--
Before submitting a PR, please read https://deno.com/manual/contributing
1. Give the PR a descriptive title.
Examples of good title:
- fix(std/http): Fix race condition in server
- docs(console): Update docstrings
- feat(doc): Handle nested reexports
Examples of bad title:
- fix #7123
- update docs
- fix bugs
2. Ensure there is a related issue and it is referenced in the PR text.
3. Ensure there are tests that cover the changes.
4. Ensure `cargo test` passes.
5. Ensure `./tools/format.js` passes without changing files.
6. Ensure `./tools/lint.js` passes.
7. Open as a draft PR if your work is still in progress. The CI won't
run
all steps, but you can add '[ci]' to a commit message to force it to.
8. If you would like to run the benchmarks on the CI, add the 'ci-bench'
label.
-->
## WHY
ref: https://github.com/denoland/deno/issues/19165
Node's fs/promises includes a FileHandle class, but deno does not. The
open function in Node's fs/promises returns a FileHandle, which provides
an IO interface to the file. However, deno's open function returns a
resource id.
### deno
```js
> const fs = await import("node:fs/promises");
undefined
> const file3 = await fs.open("./README.md");
undefined
> file3
3
> file3.read
undefined
Node:
```
### Node
```js
> const fs = await import("fs/promises");
undefined
> const file3 = await fs.open("./tests/e2e_unit/testdata/file.txt");
undefined
> file3
FileHandle {
_events: [Object: null prototype] {},
_eventsCount: 0,
_maxListeners: undefined,
close: [Function: close],
[Symbol(kCapture)]: false,
[Symbol(kHandle)]: FileHandle {},
[Symbol(kFd)]: 24,
[Symbol(kRefs)]: 1,
[Symbol(kClosePromise)]: null
}
> file3.read
[Function: read]
```
To be compatible with Node, deno's open function should also return a
FileHandle.
## WHAT
I have implemented the first step in adding a FileHandle.
- Changed the return value of the open function to a FileHandle object
- Implemented the readFile method in FileHandle
- Add test code
## What to do next
This PR is the first step in adding a FileHandle, and there are things
that should be done next.
- Add functionality equivalent to Node's FileHandle to FileHandle
(currently there is only readFile)
---------
Co-authored-by: Matt Mastracci <matthew@mastracci.com>
This PR adds the missing `process.reallyExit()` method to node's
`process` object.
Was [pinged on
twitter](https://twitter.com/biwanczuk/status/1663326659787862017)
regarding running the `fastify` test suite in node. They use `node-tap`
which has been around arguably the longest of the test frameworks and
relies on a couple of old APIs. They have `signal-exit` as a dependency
which in turn [makes use of
`process.reallyExit()`](8fa7fc9a9c/src/index.ts (L19)).
That function cannot be found anywhere in their documentation, but
exists at runtime. See
6a6b3c5402/lib/internal/bootstrap/node.js (L172)
This doesn't yet make `node-tap` work, but gets us one step closer.
This commit fixes emitting "unhandledrejection" event when there are
"node:" or "npm:" imports.
Before this commit the Node "unhandledRejection" event was emitted
using a regular listener for Web "unhandledrejection" event. This
listener was installed before any user listener had a chance to be
installed which effectively prevent emitting "unhandledrejection"
events to user code.
Closes https://github.com/denoland/deno/issues/16928
Noticed that we're checking more module paths than necessary. In
particular the module path array contains a couple of entries with a
duplicated `node_modules/node_modules` suffix.
```js
[
// ... more entries before here, where some also contain duplicate suffixes
"/Users/marvinhagemeister/dev/preact-render-to-string/node_modules/.deno/node_modules",
"/Users/marvinhagemeister/dev/preact-render-to-string/node_modules/node_modules", // <-- duplicate suffix
"/Users/marvinhagemeister/dev/preact-render-to-string/node_modules",
"/Users/marvinhagemeister/dev/node_modules",
"/Users/marvinhagemeister/node_modules",
"/Users/node_modules",
"/node_modules",
"/node_modules" // <-- duplicate entry
]
```
This was caused by a misunderstanding in how Rust's
[`Path::ends_with()`](https://doc.rust-lang.org/std/path/struct.Path.html#method.ends_with)
works. It's designed to match on whole path segments and the suffix
`/node_modules` is not that, except for the root entry. This meant that
our check for if the path already ended with `node_module` always
returned `false`. Removing the leading slash fixes that.
While we're at it, we can remove the last condition where we explicitly
added the root `/node_modules` entry since the while loop prior to that
takes care of it already.
This commit changes implementation of "setImmediate"
from "node:timers" module to 0ms timer that is never
clamped to 4ms no matter how many nested calls there are.
Closes https://github.com/denoland/deno/issues/19034
This commit changes the return type of an unstable `Deno.serve()` API
to instead return a `Deno.Server` object that has a `finished` field.
This change is done in preparation to be able to ref/unref the HTTP
server.
This is a bit bare bones but gets `npm-run-all` working. For full stdio
compatibility with node more work is needed which is probably better
done in follow up PRs.
Fixes #19159
This commit reimplements most of "node:http" client APIs using
"ext/fetch".
There is some duplicated code and two removed Node compat tests that
will be fixed in follow up PRs.
---------
Co-authored-by: Bartek Iwańczuk <biwanczuk@gmail.com>
This commit shams "performance.markResourceTiming" API by
using a noop function. It is done to provide compatibility with
"npm:undici" package. We should look into actually implementing
this API properly, but I wanted to unblock support for "undici" and
"astro" for now.
Ref https://github.com/denoland/deno/issues/19065