mirror of
https://github.com/denoland/deno.git
synced 2025-12-23 08:48:24 +00:00
Some checks are pending
ci / test debug windows-x86_64 (push) Blocked by required conditions
ci / test release windows-x86_64 (push) Blocked by required conditions
ci / pre-build (push) Waiting to run
ci / test debug linux-aarch64 (push) Blocked by required conditions
ci / test release linux-aarch64 (push) Blocked by required conditions
ci / test debug macos-aarch64 (push) Blocked by required conditions
ci / test release macos-aarch64 (push) Blocked by required conditions
ci / bench release linux-x86_64 (push) Blocked by required conditions
ci / test debug linux-x86_64 (push) Blocked by required conditions
ci / test release linux-x86_64 (push) Blocked by required conditions
ci / test debug macos-x86_64 (push) Blocked by required conditions
ci / test release macos-x86_64 (push) Blocked by required conditions
ci / lint debug linux-x86_64 (push) Blocked by required conditions
ci / lint debug macos-x86_64 (push) Blocked by required conditions
ci / lint debug windows-x86_64 (push) Blocked by required conditions
ci / build libs (push) Blocked by required conditions
ci / publish canary (push) Blocked by required conditions
## 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>
99 lines
2.9 KiB
TypeScript
99 lines
2.9 KiB
TypeScript
// Copyright 2018-2025 the Deno authors. MIT license.
|
|
import { assertEquals, fail } from "@std/assert";
|
|
import dns, { lookupService } from "node:dns";
|
|
import dnsPromises, {
|
|
lookup as lookupPromise,
|
|
lookupService as lookupServicePromise,
|
|
} from "node:dns/promises";
|
|
import { ErrnoException } from "ext:deno_node/_global.d.ts";
|
|
|
|
interface LookupServiceResult {
|
|
hostname: string;
|
|
service: string;
|
|
}
|
|
|
|
const address = "8.8.8.8";
|
|
const port = 80;
|
|
|
|
Deno.test("lookupService with callback", async () => {
|
|
// Named import
|
|
const result = await new Promise<LookupServiceResult>(
|
|
(resolve, reject) => {
|
|
lookupService(address, port, (err, hostname, service) => {
|
|
if (err) reject(err);
|
|
resolve({ hostname, service });
|
|
});
|
|
},
|
|
);
|
|
assertEquals(typeof result.hostname, "string");
|
|
assertEquals(typeof result.service, "string");
|
|
|
|
// Default import
|
|
const defaultImportResult = await new Promise<LookupServiceResult>(
|
|
(resolve, reject) => {
|
|
dns.lookupService(address, port, (err, hostname, service) => {
|
|
if (err) reject(err);
|
|
resolve({ hostname, service });
|
|
});
|
|
},
|
|
);
|
|
assertEquals(typeof defaultImportResult.hostname, "string");
|
|
assertEquals(typeof defaultImportResult.service, "string");
|
|
});
|
|
|
|
Deno.test("lookupService promise", async () => {
|
|
// Named import
|
|
const result = await lookupServicePromise(address, port);
|
|
assertEquals(typeof result.hostname, "string");
|
|
assertEquals(typeof result.service, "string");
|
|
|
|
// Default import
|
|
const defaultImportResult = await dnsPromises.lookupService(
|
|
address,
|
|
port,
|
|
);
|
|
assertEquals(typeof defaultImportResult.hostname, "string");
|
|
assertEquals(typeof defaultImportResult.service, "string");
|
|
});
|
|
|
|
Deno.test("lookupService not found", async () => {
|
|
const address = "10.0.0.0";
|
|
|
|
// Promise
|
|
try {
|
|
await lookupServicePromise(address, port);
|
|
fail();
|
|
} catch (err) {
|
|
assertEquals(
|
|
(err as ErrnoException).message,
|
|
"getnameinfo ENOTFOUND 10.0.0.0",
|
|
);
|
|
assertEquals((err as ErrnoException).code, "ENOTFOUND");
|
|
assertEquals((err as ErrnoException).syscall, "getnameinfo");
|
|
}
|
|
|
|
// Callback
|
|
await new Promise<void>(
|
|
(resolve, reject) => {
|
|
dns.lookupService(address, port, (err) => {
|
|
if (err) reject(err);
|
|
resolve();
|
|
});
|
|
},
|
|
).then(() => fail(), (err) => {
|
|
assertEquals(
|
|
(err as ErrnoException).message,
|
|
"getnameinfo ENOTFOUND 10.0.0.0",
|
|
);
|
|
assertEquals((err as ErrnoException).code, "ENOTFOUND");
|
|
assertEquals((err as ErrnoException).syscall, "getnameinfo");
|
|
});
|
|
});
|
|
|
|
Deno.test("[node/dns] lookup accepts string family values", async () => {
|
|
const ipv4Result = await lookupPromise("localhost", { family: "IPv4" });
|
|
assertEquals(ipv4Result.family, 4);
|
|
|
|
const ipv6Result = await lookupPromise("localhost", { family: "IPv6" });
|
|
assertEquals(ipv6Result.family, 6);
|
|
});
|