Notable changes:
- Respect progress callback function option.
- Set default backup rate to 100 to follow Node's implementation.
- Various validation and error handling.
Note that the op implementation in this PR is still sync.
Given this code:
```js
import { backup, DatabaseSync } from "node:sqlite";
const populate = (database, rows) => {
database.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, name TEXT);");
let values = "";
for (let i = 0; i < rows; i++) {
values += `(${i}, 'Name ${i}'),`;
}
values = values.slice(0, -1);
database.exec(`INSERT INTO test (id, name) VALUES ${values}`);
};
const backupPath = "backup.sqlite";
const database = new DatabaseSync(":memory:");
populate(database, 1000);
const t0 = performance.now();
await backup(database, backupPath, { rate: 1 });
const t1 = performance.now();
database.close();
console.log(`Backup completed in ${(t1 - t0).toFixed(2)} ms`);
```
Results:
```bash
# Node.js v25.2.1
➜ node ./backup-benchmark.js
Backup completed in 0.71 ms
# This PR (debug build mode)
➜ ddeno -A ./backup-benchmark.js
Backup completed in 0.71 ms
# Deno v2.6.0
➜ deno -A ./backup-benchmark.js
Backup completed in 1272.16 ms
```
The current implementation is slow because it sleeps 250ms after each
`sqlite3_backup_step` call.
## Summary
Aligns Deno's Node.js compatibility layer (`node:net`, `node:http`,
`node:https`,
`node:http2`, `node:dns`) with Node.js v18.4.0+ behavior by returning
the `family`
property as a string (`"IPv4"` or `"IPv6"`) rather than a number in
`server.address()`
and socket address methods.
Node.js briefly changed `family` from string to number in v18.0.0
(nodejs/node#41431),
but reverted in v18.4.0 (nodejs/node#43054) due to ecosystem breakage
(nodejs/node#43014).
This fix ensures compatibility with npm packages that rely on the string
format, which
has been the stable API since Node.js v18.4.0.
## Changes
- Modified `ext/node/polyfills/http.ts` to add `family` property to
`address()` return
- Modified `ext/node/polyfills/internal_binding/tcp_wrap.ts` to return
string `family`
instead of number in `getsockname()`, `getpeername()`, and `#connect()`
- Modified `ext/node/polyfills/net.ts` to fix `socket.remoteFamily`
getter (no longer
needs conversion since `family` is now a string)
- Modified `ext/node/polyfills/dns.ts` and
`ext/node/polyfills/internal/dns/promises.ts` to accept string family
values (`"IPv4"`,
`"IPv6"`) in `lookup()`, matching [Node.js
behavior](https://nodejs.org/api/dns.html#dnslookuphostname-options-callback)
- Added tests in `tests/unit_node/http_test.ts`,
`tests/unit_node/http2_test.ts`,
`tests/unit_node/https_test.ts`, `tests/unit_node/dns_test.ts`, and
`tests/unit_node/net_test.ts`
## Node.js Compatibility Note
For non-IP addresses (when `isIP()` returns 0), the `family` property is
`undefined`.
This matches Node.js C++ behavior in
[`AddressToJS`](https://github.com/nodejs/node/blob/main/src/tcp_wrap.cc)
where family
is only set for `AF_INET` (`"IPv4"`) and `AF_INET6` (`"IPv6"`), and left
undefined
otherwise.
## Refs
- nodejs/node#43054
- nodejs/node@70b516e
<!--
Before submitting a PR, please read
https://docs.deno.com/runtime/manual/references/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.
-->
---------
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Daniel Rahmanto <daniel.rahmanto@gmail.com>
## Summary
This PR fixes the behavior of `url.domainToASCII` to match Node.js by
returning an empty string when an invalid domain is passed, instead of
throwing an error.
## Changes
- Modified `op_node_idna_domain_to_ascii` in `ext/node/ops/idna.rs` to
return an empty string on error instead of propagating the error
- Updated documentation in `ext/node/polyfills/internal/idna.ts` to
clarify this behavior
- Added spec test in `tests/specs/node/url_domain_to_ascii/` to verify
the fix
## Test Plan
### Manual Testing
Tested with the example from the issue:
```javascript
import url from 'node:url';
console.log(url.domainToASCII('xn--iñvalid.com')); // Returns empty string instead of throwing
```
Also tested with various valid and invalid domains to ensure
compatibility:
- Valid domains: `example.com` → `example.com`
- Valid unicode: `münchen.de` → `xn--mnchen-3ya.de`
- Invalid punycode: `xn--iñvalid.com` → `` (empty string)
- Invalid domain: `xn--` → `` (empty string)
### Automated Tests
Added spec test that verifies the behavior matches Node.js for both
valid and invalid domains.
## Closes
Fixes#31133
---
_This PR was autogenerated and may require review and adjustments._
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Daniel Rahmanto <daniel.rahmanto@gmail.com>
## Summary
In Node.js, `tty.ReadStream` sets `isTTY` as a simple instance property
(`this.isTTY = true`), making it naturally writable. Deno's polyfill
used a getter-only property definition, preventing assignment.
Some npm packages need to override `isTTY` at runtime. For example,
Playwright's test server sets `process.stdin.isTTY = undefined` to
prevent reporters from blocking on user input during UI mode
(microsoft/playwright#37867).
This aligns stdin with the stdout/stderr fix from #26130, ensuring all
stdio streams behave consistently with Node.js.
## Refs
-
6a1a3ba045/lib/tty.js (L71)
-
3a5a32d26d/packages/playwright/src/runner/testServer.ts (L257-L266)
Co-authored-by: Claude <noreply@anthropic.com>
This speeds up assertions on typed arrays by a ton. This unblocks one of
the node compat tests for advanced serialization, which times out
because the assertion is too slow.
Bench:
```
import assert from "node:assert";
const iters = 10;
let total = 0;
for (let i = 0; i < iters; i++) {
const start = performance.now();
assert.deepStrictEqual(
new Uint8Array(8 * 1024 * 1024).fill(0),
new Uint8Array(8 * 1024 * 1024).fill(0),
);
const end = performance.now();
total += end - start;
}
console.log("took", total / iters, "per iter");
```
Before:
```
took 2634.9984669 per iter
```
After:
```
took 15.0644873 per iter
```
So over 100x faster
Closes#26300
Allows the following node compatibility tests to pass:
-
https://github.com/nodejs/node/blob/v24.2.0/test/parallel/test-dns-lookupService-promises.js
-
https://github.com/nodejs/node/blob/v24.2.0/test/parallel/test-dns-lookupService.js
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Added `dns.lookupService()` for reverse DNS lookups, supporting both
callback and Promise-based APIs.
* Returns hostname and service information for a given IP address and
port combination.
* **Tests**
* Added unit tests for new DNS lookupService functionality across
callback and Promise variants.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Previously, running this code causes segfault:
```ts
import { DatabaseSync } from "node:sqlite";
const db = new DatabaseSync(':memory:');
const stmt = db.prepare('SELECT 1 AS value');
db.close();
stmt.get(); // segmentation fault (core dumped)
```
Changes in this PR also allows the
https://github.com/nodejs/node/blob/v24.2.0/test/parallel/test-sqlite-statement-sync-columns.js
test to pass.
This PR resolves#30964 where process.argv returned getter functions
rather than string values.
---------
Co-authored-by: Daniel Rahmanto <daniel.rahmanto@gmail.com>
Fixes#31172
## Description
The `deepStrictEqual` function was using `asserts.equal()` which doesn't
properly handle boxed primitives like Number objects. Changed it to use
`isDeepStrictEqual()` from `comparisons.ts` which correctly handles
Number, String, Boolean, BigInt, and Symbol objects.
## Changes
- Modified `ext/node/polyfills/assert.ts`:
- Added import for `isDeepStrictEqual` from
`ext:deno_node/internal/util/comparisons.ts`
- Updated `deepStrictEqual` function to use `isDeepStrictEqual()`
instead of `asserts.equal()`
- Added test cases in `tests/unit_node/assert_test.ts`:
- Test that `deepStrictEqual` throws `AssertionError` for different
Number objects
- Test that `deepStrictEqual` passes for equal Number objects
## Testing
Added unit tests to verify:
- `deepStrictEqual` throws `AssertionError` for different Number objects
(e.g., `new Number(1)` vs `new Number(2)`)
- `deepStrictEqual` passes for equal Number objects (e.g., `new
Number(1)` vs `new Number(1)`)
## Related Issue
#31172 - `assert.deepStrictEqual` does not throw exception for Number
objects
---------
Co-authored-by: Daniel Rahmanto <daniel.rahmanto@gmail.com>
I also moved the `RuntimePermissionDescriptorParser` struct from
deno_runtime into deno_permissions, so that extension crates can use it
in tests and stuff like that
Allows
https://github.com/nodejs/node/blob/v24.2.0/test/parallel/test-sqlite-named-parameters.js
to pass.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Corrected an error message for SQLite named parameters validation to
display the expected parameter name accurately.
* **Tests**
* Added new test coverage for SQLite named parameters functionality.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit changes global `setTimeout` and `setInterval` APIs (along
their `clear*` counterparts) to use Node.js APIs instead of the Web
APIs.
For real world usage we expect no difference in code and behavior,
unless user relies on following checks:
```
const id = setTimeout(...);
if (typeof id === "number") {
// ...
}
```
In which case the conditional should be changed to `if (id)`
Allow calling `Deno.env.toObject()` or getting the entire `process.env`
when only having partial permissions.
For example, you can now do `--allow-env --deny-env=SOMETHING` and the
object will have all the env vars except `SOMETHING`
We discussed just never throwing here, but we think it would be a bad
idea because someone might get confused why their program isn't working
whereas now they get alerted about env permissions ("I set this
environment variable, but it's not working!").
Introduces the emitWarning function from the process module to enable
warning capabilities within the console constructor implementation.
This fixes a bug where the `time`, `countReset` and `timeLogImpl`
functions would throw an error due to trying to call `emitWarning`, they
would throw an error for an undefined variable named `emitWarning` or if
a global function had that name` they would call that function, which is
not expected behaviour here.
---------
Signed-off-by: Jake Champion <me@jakechampion.name>
Closes#30013
The `'exit'` event in `node:worker_threads` was not consistently fired,
or in some cases emitted multiple times, diverging from Node.js
behavior.
This PR fixes a bug in `node:crypto.createCipheriv` where the
`authTagLength` option was ignored for AES-GCM ciphers, resulting in a
fixed 16-byte authentication tag regardless of the specified value.
The fix ensures both encryption and decryption paths correctly honor
`authTagLength`, matching Node.js behavior.
Fixes#31102
This commit deprecated `deno_broadcast_channel` crate and merges it into
`deno_web`.
This will allow us to limit number of crates we need to publish and
(maybe) improve compile and link times.
The actual `ext/broadcast_channel` directory will be removed in a follow
up PR, once a new version is published and points to deno_web crate.