Skip to content

Conversation

@Tango992
Copy link
Member

@Tango992 Tango992 commented Nov 16, 2025

Copilot AI review requested due to automatic review settings November 16, 2025 10:13
Copilot finished reviewing on behalf of Tango992 November 16, 2025 10:17
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR implements the dns.lookupService function for Node.js compatibility in Deno, enabling reverse DNS lookups to resolve IP addresses and ports to hostnames and service names.

  • Adds op_node_getnameinfo operation that wraps platform-specific getnameinfo system calls
  • Implements both callback-based and promise-based lookupService APIs in the dns module
  • Enables two Node.js compatibility tests for dns.lookupService

Reviewed Changes

Copilot reviewed 12 out of 13 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
ext/node/ops/dns.rs Implements op_node_getnameinfo with platform-specific getnameinfo calls for Unix and Windows
ext/node/ops/constant.rs Adds UV error code constants for DNS address info errors
ext/node/polyfills/internal_binding/cares_wrap.ts Adds GetNameInfoReqWrap class and getnameinfo function to wrap the native operation
ext/node/polyfills/internal/errors.ts Adds handleDnsError helper function for DNS error processing
ext/node/polyfills/internal/dns/promises.ts Implements promise-based lookupService function
ext/node/polyfills/dns.ts Implements callback-based lookupService function and exports
ext/node/polyfills/dns/promises.ts Re-exports lookupService from promises module
ext/node/lib.rs Registers the new op_node_getnameinfo operation
ext/node/Cargo.toml Adds socket2 dependency for socket address handling
Cargo.lock Updates lock file with socket2 dependency
tests/unit_node/dns_test.ts Adds unit tests for lookupService with callbacks, promises, and error cases
tests/integration/node_unit_tests.rs Registers the new dns_test module
tests/node_compat/config.toml Enables two Node.js compatibility tests for lookupService

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@coderabbitai
Copy link

coderabbitai bot commented Nov 17, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

This PR adds reverse DNS lookup support (lookupService) for Node.js compatibility. It introduces a new core op (op_node_getnameinfo) and Rust-side DNS error handling, new UV EAI error constants, and WinSock initialization. JavaScript polyfills provide callback and Promise APIs, internal binding wrappers (GetNameInfoReqWrap / getnameinfo), and dns error mapping (handleDnsError). Tests and test config entries for lookupService are added. A workspace dependency (socket2) was also added.

Sequence Diagram(s)

sequenceDiagram
    participant App as User App
    participant API as dns.lookupService / promises.lookupService
    participant Poly as cares_wrap / polyfills
    participant Core as op_node_getnameinfo
    participant OS as Platform getnameinfo

    App->>API: call lookupService(address, port, [callback])
    API->>API: validate args, permissions, port
    API->>Poly: create GetNameInfoReqWrap / promise
    Poly->>Core: invoke op_node_getnameinfo(address, port)
    Core->>OS: platform-specific getnameinfo (Unix/Windows)
    OS-->>Core: (hostname, service) or error
    Core-->>Poly: complete with result or DnsError
    Poly->>API: resolve/reject promise or call callback
    API->>App: return result or error
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~35 minutes

Areas requiring extra attention:

  • ext/node/ops/dns.rs: platform-specific getnameinfo implementations, WinSock initialization, and DnsError mappings
  • ext/node/polyfills/internal/errors.ts: correctness of handleDnsError routing
  • API parity: ensure callback and Promise implementations validate and handle errors consistently
  • Tests & test-config: confirm test wiring and expectations match implementation

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 31.25% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: implementing the dns.lookupService function for Node.js compatibility.
Description check ✅ Passed The description clearly references the related issue (#26300) and specifies which Node.js tests should pass after this implementation.
Linked Issues check ✅ Passed All coding requirements from issue #26300 are met: dns.lookupService(address, port, callback) is implemented across callback and Promise APIs with proper error handling.
Out of Scope Changes check ✅ Passed All changes are directly related to implementing dns.lookupService: DNS operations, error types, bindings, polyfills, and tests are all in scope.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 66cb75d and 2f83ae7.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (4)
  • ext/node/lib.rs (1 hunks)
  • ext/node/ops/dns.rs (3 hunks)
  • tests/integration/node_unit_tests.rs (1 hunks)
  • tests/node_compat/config.toml (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • ext/node/lib.rs
  • tests/node_compat/config.toml
🧰 Additional context used
🧬 Code graph analysis (1)
ext/node/ops/dns.rs (3)
ext/net/ops.rs (9)
  • from (69-74)
  • from (78-83)
  • state (191-194)
  • state (235-238)
  • state (269-272)
  • state (306-309)
  • state (328-331)
  • state (349-352)
  • name (554-556)
ext/node/lib.rs (1)
  • state (117-118)
ext/node/polyfills/internal_binding/cares_wrap.ts (1)
  • getnameinfo (163-177)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
  • GitHub Check: lint debug windows-x86_64
  • GitHub Check: test debug linux-aarch64
  • GitHub Check: test debug linux-x86_64
  • GitHub Check: test release macos-x86_64
  • GitHub Check: test debug windows-x86_64
  • GitHub Check: test debug macos-x86_64
  • GitHub Check: test debug macos-aarch64
  • GitHub Check: lint debug linux-x86_64
  • GitHub Check: lint debug macos-x86_64
  • GitHub Check: build libs
🔇 Additional comments (3)
tests/integration/node_unit_tests.rs (1)

73-77: Adding dns_test to the Node unit test matrix looks correct

The new dns_test entry matches the existing naming pattern and will run tests/unit_node/dns_test.ts alongside the other Node-compat tests. No issues here.

ext/node/ops/dns.rs (2)

23-90: DnsError enum and getaddrinfo refactor look consistent and safe

The new DnsError type cleanly unifies permission, resolution, parse, I/O, and UV-style error cases, and the updated op_node_getaddrinfo now returns Result<NetPermToken, DnsError> with clear Resolution(hostname) mapping for name/resolve failures. This aligns with the JS-side uv_errcode handling and doesn’t introduce obvious regressions.


92-113: op_node_getnameinfo async wrapper and permissions are wired correctly

op_node_getnameinfo enforces check_net with the correct "node:dns.lookupService()" tag, parses the IP string via IpAddr, and offloads getnameinfo to spawn_blocking, wrapping thread-level failures as DnsError::Io. The signature and tuple return (hostname, service) line up with the internal binding usage.

Tip

📝 Customizable high-level summaries are now available in beta!

You can now customize how CodeRabbit generates the high-level summary in your pull requests — including its content, structure, tone, and formatting.

  • Provide your own instructions using the high_level_summary_instructions setting.
  • Format the summary however you like (bullet lists, tables, multi-section layouts, contributor stats, etc.).
  • Use high_level_summary_in_walkthrough to move the summary from the description to the walkthrough section.

Example instruction:

"Divide the high-level summary into five sections:

  1. 📝 Description — Summarize the main change in 50–60 words, explaining what was done.
  2. 📓 References — List relevant issues, discussions, documentation, or related PRs.
  3. 📦 Dependencies & Requirements — Mention any new/updated dependencies, environment variable changes, or configuration updates.
  4. 📊 Contributor Summary — Include a Markdown table showing contributions:
    | Contributor | Lines Added | Lines Removed | Files Changed |
  5. ✔️ Additional Notes — Add any extra reviewer context.
    Keep each section concise (under 200 words) and use bullet or numbered lists for clarity."

Note: This feature is currently in beta for Pro-tier users, and pricing will be announced later.


Comment @coderabbitai help to get the list of available commands and usage tips.

@bartlomieju
Copy link
Member

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Nov 17, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
ext/node/polyfills/dns.ts (1)

328-361: Consider adding explicit string validation and JSDoc comments.

The implementation is functionally correct, but could be improved:

  1. String validation: While isIP() handles non-strings by returning 0, explicit validateString(address, "address") before Line 341 would provide clearer error messages and match the pattern used in the lookup() function.

  2. Missing documentation: Unlike other exported functions in this file (e.g., lookup, resolve4), lookupService lacks JSDoc comments. Adding documentation would help users understand the API, especially the callback signature and error handling.

Example addition before Line 337:

+/**
+ * Resolves the given address and port into a hostname and service using the
+ * operating system's underlying `getnameinfo` implementation.
+ *
+ * @param address A string representing an IPv4 or IPv6 address.
+ * @param port The numeric port number.
+ * @param callback The callback function.
+ */
 export function lookupService(

Example addition after Line 338:

   if (arguments.length !== 3) {
     throw new ERR_MISSING_ARGS("address", "port", "callback");
   }
+
+  validateString(address, "address");
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4bf2ad3 and 66cb75d.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (12)
  • ext/node/Cargo.toml (1 hunks)
  • ext/node/lib.rs (1 hunks)
  • ext/node/ops/constant.rs (1 hunks)
  • ext/node/ops/dns.rs (3 hunks)
  • ext/node/polyfills/dns.ts (5 hunks)
  • ext/node/polyfills/dns/promises.ts (1 hunks)
  • ext/node/polyfills/internal/dns/promises.ts (4 hunks)
  • ext/node/polyfills/internal/errors.ts (1 hunks)
  • ext/node/polyfills/internal_binding/cares_wrap.ts (3 hunks)
  • tests/integration/node_unit_tests.rs (1 hunks)
  • tests/node_compat/config.toml (1 hunks)
  • tests/unit_node/dns_test.ts (1 hunks)
🔇 Additional comments (19)
ext/node/Cargo.toml (1)

91-91: socket2 dependency wiring looks correct

Adding socket2.workspace = true is consistent with the new DNS/socket plumbing and matches the existing pattern of workspace-scoped dependencies. No issues from this manifest change alone.

ext/node/lib.rs (1)

349-351: New DNS getnameinfo op is correctly exposed

ops::dns::op_node_getnameinfo<P> is wired into the extension ops list next to op_node_getaddrinfo<P> and uses the same permission generic, which is the expected pattern for new DNS ops.

tests/node_compat/config.toml (1)

336-337: Enabling Node’s lookupService compat tests is appropriate

Registering parallel/test-dns-lookupService.js and parallel/test-dns-lookupService-promises.js here cleanly plugs the new implementation into the Node-compat test matrix and follows the existing config style.

tests/integration/node_unit_tests.rs (1)

74-74: dns_test is correctly hooked into the node_unit_test harness

Adding dns_test to the unit_test_factory! list correctly wires the new DNS unit tests into the existing integration runner with consistent naming.

ext/node/polyfills/dns/promises.ts (1)

23-27: lookupService correctly added to dns promises named exports

Including lookupService in the destructured export from promises aligns node:dns/promises with Node’s public API so that both default and named imports are supported.

tests/unit_node/dns_test.ts (2)

17-56: Good coverage for callback and promise lookupService success paths

These tests exercise both named and default imports of lookupService from node:dns and node:dns/promises, and validate that hostname/service come back as strings, which is exactly what we need for basic behavior verification across both APIs.


58-89: ENOTFOUND behavior is well specified for lookupService

The not-found test checks that both promise- and callback-based lookupService report an ENOTFOUND error with the expected message, code, and syscall fields, which is important for Node-compat error semantics. This should catch regressions in DNS error mapping.

ext/node/polyfills/internal/dns/promises.ts (1)

26-32: lookupService promise implementation and wiring look Node-compatible

The new lookupService flow in the promises layer looks solid:

  • Imports are extended appropriately (validatePort, ERR_MISSING_ARGS, handleDnsError, GetNameInfoReqWrap) to support argument validation and DNS-specific error shaping.
  • onlookupservice uses handleDnsError(err, "getnameinfo", this.address) for async failures and resolves with { hostname, service } on success, matching the expected promise result shape.
  • createLookupServicePromise mirrors the existing createLookupPromise pattern, with GetNameInfoReqWrap carrying address, port, and the completion handler, and uses dnsException for synchronous cares.getnameinfo errors.
  • lookupService(address, port) enforces arity, ensures address is an IP via isIP, validates port with validatePort, and returns the promise from createLookupServicePromise, which is in line with Node’s internal implementation.
  • Adding lookupService to the default export object keeps the public dnsPromises surface coherent with the new functionality.

Overall, this is a clean, idiomatic extension of the existing DNS promises machinery.

Also applies to: 53-58, 59-65, 237-281, 551-553

ext/node/polyfills/internal_binding/cares_wrap.ts (2)

141-161: LGTM! GetNameInfoReqWrap class structure is consistent.

The class follows the same pattern as GetAddrInfoReqWrap and has appropriate type signatures for DNS reverse lookup operations.


163-177: LGTM! The getnameinfo function implementation is correct.

The async operation pattern matches other functions in this file, and error handling is appropriate.

ext/node/polyfills/internal/errors.ts (1)

334-348: LGTM! DNS error handling logic is comprehensive.

The three-tier error handling (UV error codes → NotCapable → generic errors) properly routes DNS-related errors to appropriate constructors.

ext/node/ops/constant.rs (1)

121-135: LGTM! UV error constants are correctly defined.

The constants match libuv's DNS error codes and include all values referenced in the getnameinfo implementation.

ext/node/polyfills/dns.ts (2)

315-326: LGTM! The onlookupservice callback handler is correct.

The error handling via handleDnsError and success path are properly implemented, following the same pattern as other callback handlers in this file.


363-367: LGTM! Promisify configuration is correct.

The customPromisifyArgs property is properly configured to shape promisified results as { hostname, service }, matching the callback signature.

ext/node/ops/dns.rs (5)

23-57: LGTM! DnsError enum is well-designed.

The expanded error type properly handles various DNS error scenarios with appropriate error inheritance and UV error code exposure via the uv_errcode property.


94-118: LGTM! The op_node_getnameinfo operation is correctly implemented.

The operation properly handles permissions, input validation, and uses spawn_blocking for the blocking getnameinfo call, which prevents blocking the async runtime.


124-155: LGTM! Unix getnameinfo implementation is correct.

The implementation properly uses libc::getnameinfo with appropriate buffer sizes and the NI_NAMEREQD flag for hostname resolution.


160-167: Verify type compatibility when mixing winapi and windows_sys crates.

The code uses MAKEWORD from the winapi crate (Line 160) but WSAStartup from the windows_sys crate (Line 161). This mixing was previously flagged as a potential type incompatibility issue.

Consider using windows_sys consistently for all Windows socket operations:

-    use winapi::shared::minwindef::MAKEWORD;
     use windows_sys::Win32::Networking::WinSock;

     // SAFETY: winapi call
     let wsa_startup_code = *WINSOCKET_INIT.get_or_init(|| unsafe {
       let mut wsa_data: WinSock::WSADATA = std::mem::zeroed();
-      WinSock::WSAStartup(MAKEWORD(2, 2), &mut wsa_data)
+      WinSock::WSAStartup((2u16 | (2u16 << 8)), &mut wsa_data)
     });

Alternatively, if winapi must be used, ensure all Windows socket types come from the same crate to avoid ABI issues.

Based on learnings


206-248: LGTM! Platform-specific error mapping is comprehensive.

The assert_success function properly maps platform-specific DNS error codes to UV error codes for both Unix and Windows, with appropriate fallbacks for unmapped errors.

Comment on lines +261 to +265
const errCode = cares.getnameinfo(req, address, port);

if (errCode) {
reject(dnsException(errCode, "getnameinfo", address));
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Our cares.getnameinfo will always return 0, but I use this approach because a test on parallel/test-dns-lookupService.js stubs the return value of this function: https://github.com/nodejs/node/blob/591ba692bfe30408e6a67397e7d18bfa1b9c3561/test/parallel/test-dns-lookupService.js#L9-L10

Comment on lines +336 to +337
"parallel/test-dns-lookupService.js" = {}
"parallel/test-dns-lookupService-promises.js" = {}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work 👍 I just hope they won't be flaky 💀

Copy link
Member

@bartlomieju bartlomieju left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, nice fix

@Tango992 Tango992 enabled auto-merge (squash) November 20, 2025 10:24
@Tango992 Tango992 merged commit 491274d into denoland:main Nov 20, 2025
21 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: dns.lookupService is not a function

2 participants