Skip to content

Commit e9d2e50

Browse files
authored
Merge branch 'main' into patch-repl-1
2 parents 178dc1a + f334f90 commit e9d2e50

File tree

12 files changed

+189
-6
lines changed

12 files changed

+189
-6
lines changed

ext/fetch/dns.rs

+55
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use std::future::Future;
33
use std::io;
44
use std::net::SocketAddr;
55
use std::pin::Pin;
6+
use std::sync::Arc;
67
use std::task::Poll;
78
use std::task::{self};
89
use std::vec;
@@ -19,6 +20,24 @@ pub enum Resolver {
1920
Gai(GaiResolver),
2021
/// hickory-resolver's userspace resolver.
2122
Hickory(hickory_resolver::Resolver<TokioConnectionProvider>),
23+
/// A custom resolver that implements `Resolve`.
24+
Custom(Arc<dyn Resolve>),
25+
}
26+
27+
/// Alias for the `Future` type returned by a custom DNS resolver.
28+
// The future has to be `Send` as `tokio::spawn` is used to execute the future.
29+
pub type Resolving =
30+
Pin<Box<dyn Future<Output = Result<SocketAddrs, io::Error>> + Send>>;
31+
32+
/// A trait for customizing DNS resolution in ext/fetch.
33+
// The resolver needs to be `Send` and `Sync` for two reasons. One is it is
34+
// wrapped inside an `Arc` and will be cloned and moved to an async block to
35+
// perfrom DNS resolution. That async block will be executed by `tokio::spawn`,
36+
// so to make that async block `Send`, `Arc<dyn Resolve>` needs to be
37+
// `Send`. The other is `Resolver` needs to be `Send` to make the wrapping
38+
// `HttpConnector` `Send`.
39+
pub trait Resolve: Send + Sync + std::fmt::Debug {
40+
fn resolve(&self, name: Name) -> Resolving;
2241
}
2342

2443
impl Default for Resolver {
@@ -107,7 +126,43 @@ impl Service<Name> for Resolver {
107126
Ok(iter)
108127
})
109128
}
129+
Resolver::Custom(resolver) => {
130+
let resolver = resolver.clone();
131+
tokio::spawn(async move { resolver.resolve(name).await })
132+
}
110133
};
111134
ResolveFut { inner: task }
112135
}
113136
}
137+
138+
#[cfg(test)]
139+
mod tests {
140+
use std::str::FromStr;
141+
142+
use super::*;
143+
144+
// A resolver that resolves any name into the same address.
145+
#[derive(Debug)]
146+
struct DebugResolver(SocketAddr);
147+
148+
impl Resolve for DebugResolver {
149+
fn resolve(&self, _name: Name) -> Resolving {
150+
let addr = self.0;
151+
Box::pin(async move { Ok(vec![addr].into_iter()) })
152+
}
153+
}
154+
155+
#[tokio::test]
156+
async fn custom_dns_resolver() {
157+
let mut resolver = Resolver::Custom(Arc::new(DebugResolver(
158+
"127.0.0.1:8080".parse().unwrap(),
159+
)));
160+
let mut addr = resolver
161+
.call(Name::from_str("foo.com").unwrap())
162+
.await
163+
.unwrap();
164+
165+
let addr = addr.next().unwrap();
166+
assert_eq!(addr, "127.0.0.1:8080".parse().unwrap());
167+
}
168+
}

ext/net/01_net.js

+12
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import {
2727
op_net_recv_unixpacket,
2828
op_net_send_udp,
2929
op_net_send_unixpacket,
30+
op_net_set_broadcast_udp,
3031
op_net_set_multi_loopback_udp,
3132
op_net_set_multi_ttl_udp,
3233
op_set_keepalive,
@@ -377,6 +378,12 @@ class Listener {
377378
}
378379
}
379380

381+
const _setBroadcast = Symbol("setBroadcast");
382+
383+
function setDatagramBroadcast(conn, broadcast) {
384+
return conn[_setBroadcast](broadcast);
385+
}
386+
380387
class DatagramConn {
381388
#rid = 0;
382389
#addr = null;
@@ -393,6 +400,10 @@ class DatagramConn {
393400
return this.#addr;
394401
}
395402

403+
[_setBroadcast](broadcast) {
404+
op_net_set_broadcast_udp(this.#rid, broadcast);
405+
}
406+
396407
async joinMulticastV4(addr, multiInterface) {
397408
await op_net_join_multi_v4_udp(
398409
this.#rid,
@@ -688,6 +699,7 @@ export {
688699
Listener,
689700
listenOptionApiName,
690701
resolveDns,
702+
setDatagramBroadcast,
691703
TcpConn,
692704
UnixConn,
693705
UpgradedConn,

ext/net/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ deno_core::extension!(deno_net,
156156
ops::op_net_leave_multi_v6_udp,
157157
ops::op_net_set_multi_loopback_udp,
158158
ops::op_net_set_multi_ttl_udp,
159+
ops::op_net_set_broadcast_udp,
159160
ops::op_dns_resolve<P>,
160161
ops::op_set_nodelay,
161162
ops::op_set_keepalive,

ext/net/ops.rs

+17
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,23 @@ pub async fn op_net_set_multi_ttl_udp(
390390
Ok(())
391391
}
392392

393+
#[op2(async)]
394+
pub async fn op_net_set_broadcast_udp(
395+
state: Rc<RefCell<OpState>>,
396+
#[smi] rid: ResourceId,
397+
broadcast: bool,
398+
) -> Result<(), NetError> {
399+
let resource = state
400+
.borrow_mut()
401+
.resource_table
402+
.get::<UdpSocketResource>(rid)
403+
.map_err(|_| NetError::SocketClosed)?;
404+
let socket = RcRef::map(&resource, |r| &r.socket).borrow().await;
405+
socket.set_broadcast(broadcast)?;
406+
407+
Ok(())
408+
}
409+
393410
/// If this token is present in op_net_connect_tcp call and
394411
/// the hostname matches with one of the resolved IPs, then
395412
/// the permission check is performed against the original hostname.

ext/node/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,7 @@ deno_core::extension!(deno_node,
458458
ops::require::op_require_package_imports_resolve<P, TInNpmPackageChecker, TNpmPackageFolderResolver, TSys>,
459459
ops::require::op_require_break_on_next_statement,
460460
ops::util::op_node_guess_handle_type,
461+
ops::util::op_node_view_has_buffer,
461462
ops::worker_threads::op_worker_threads_filename<P, TSys>,
462463
ops::ipc::op_node_child_ipc_pipe,
463464
ops::ipc::op_node_ipc_write,

ext/node/ops/util.rs

+6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright 2018-2025 the Deno authors. MIT license.
22

33
use deno_core::op2;
4+
use deno_core::v8;
45
use deno_core::OpState;
56
use deno_core::ResourceHandle;
67
use deno_core::ResourceHandleFd;
@@ -80,3 +81,8 @@ fn guess_handle_type(handle: ResourceHandleFd) -> HandleType {
8081
_ => HandleType::Unknown,
8182
}
8283
}
84+
85+
#[op2(fast)]
86+
pub fn op_node_view_has_buffer(buffer: v8::Local<v8::ArrayBufferView>) -> bool {
87+
buffer.has_buffer()
88+
}

ext/node/polyfills/internal_binding/udp_wrap.ts

+7-2
Original file line numberDiff line numberDiff line change
@@ -300,8 +300,13 @@ export class UDP extends HandleWrap {
300300
return this.#doSend(req, bufs, count, args, AF_INET6);
301301
}
302302

303-
setBroadcast(_bool: 0 | 1): number {
304-
notImplemented("udp.UDP.prototype.setBroadcast");
303+
setBroadcast(bool: 0 | 1): number {
304+
if (!this.#listener) {
305+
return codeMap.get("EBADF")!;
306+
}
307+
308+
net.setDatagramBroadcast(this.#listener, bool === 1);
309+
return 0;
305310
}
306311

307312
setMulticastInterface(_interfaceAddress: string): number {

ext/node/polyfills/internal_binding/util.ts

+10-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,10 @@
2828
// TODO(petamoriken): enable prefer-primordials for node polyfills
2929
// deno-lint-ignore-file prefer-primordials
3030

31-
import { op_node_guess_handle_type } from "ext:core/ops";
31+
import {
32+
op_node_guess_handle_type,
33+
op_node_view_has_buffer,
34+
} from "ext:core/ops";
3235

3336
const handleTypes = ["TCP", "TTY", "UDP", "FILE", "PIPE", "UNKNOWN"];
3437
export function guessHandleType(fd: number): string {
@@ -128,3 +131,9 @@ export function getOwnNonIndexProperties(
128131
}
129132
return result;
130133
}
134+
135+
export function arrayBufferViewHasBuffer(
136+
view: ArrayBufferView,
137+
): boolean {
138+
return op_node_view_has_buffer(view);
139+
}

tests/node_compat/config.jsonc

+2
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
"test-blocklist.js",
2525
"test-buffer-alloc.js",
2626
"test-buffer-arraybuffer.js",
27+
"test-buffer-backing-arraybuffer.js",
2728
"test-buffer-includes.js",
2829
"test-buffer-indexof.js",
2930
"test-buffer-tostring-range.js",
@@ -448,6 +449,7 @@
448449
"test-dgram-send-invalid-msg-type.js",
449450
"test-dgram-send-multi-buffer-copy.js",
450451
"test-dgram-send-multi-string-array.js",
452+
"test-dgram-setBroadcast.js",
451453
"test-dgram-udp4.js",
452454
"test-dgram-udp6-send-default-host.js",
453455
"test-dgram-unref.js",

tests/node_compat/runner/TODO.md

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<!-- deno-fmt-ignore-file -->
22
# Remaining Node Tests
33

4-
1163 tests out of 3993 have been ported from Node 23.9.0 (29.13% ported, 71.40% remaining).
4+
1164 tests out of 3993 have been ported from Node 23.9.0 (29.15% ported, 71.37% remaining).
55

66
NOTE: This file should not be manually edited. Please edit `tests/node_compat/config.json` and run `deno task setup` in `tests/node_compat/runner` dir instead.
77

@@ -282,7 +282,6 @@ NOTE: This file should not be manually edited. Please edit `tests/node_compat/co
282282
- [parallel/test-blocklist-clone.js](https://github.com/nodejs/node/tree/v23.9.0/test/parallel/test-blocklist-clone.js)
283283
- [parallel/test-bootstrap-modules.js](https://github.com/nodejs/node/tree/v23.9.0/test/parallel/test-bootstrap-modules.js)
284284
- [parallel/test-broadcastchannel-custom-inspect.js](https://github.com/nodejs/node/tree/v23.9.0/test/parallel/test-broadcastchannel-custom-inspect.js)
285-
- [parallel/test-buffer-backing-arraybuffer.js](https://github.com/nodejs/node/tree/v23.9.0/test/parallel/test-buffer-backing-arraybuffer.js)
286285
- [parallel/test-buffer-compare.js](https://github.com/nodejs/node/tree/v23.9.0/test/parallel/test-buffer-compare.js)
287286
- [parallel/test-buffer-constructor-deprecation-error.js](https://github.com/nodejs/node/tree/v23.9.0/test/parallel/test-buffer-constructor-deprecation-error.js)
288287
- [parallel/test-buffer-constructor-node-modules-paths.js](https://github.com/nodejs/node/tree/v23.9.0/test/parallel/test-buffer-constructor-node-modules-paths.js)
@@ -626,7 +625,6 @@ NOTE: This file should not be manually edited. Please edit `tests/node_compat/co
626625
- [parallel/test-dgram-send-empty-packet.js](https://github.com/nodejs/node/tree/v23.9.0/test/parallel/test-dgram-send-empty-packet.js)
627626
- [parallel/test-dgram-send-queue-info.js](https://github.com/nodejs/node/tree/v23.9.0/test/parallel/test-dgram-send-queue-info.js)
628627
- [parallel/test-dgram-sendto.js](https://github.com/nodejs/node/tree/v23.9.0/test/parallel/test-dgram-sendto.js)
629-
- [parallel/test-dgram-setBroadcast.js](https://github.com/nodejs/node/tree/v23.9.0/test/parallel/test-dgram-setBroadcast.js)
630628
- [parallel/test-dgram-setTTL.js](https://github.com/nodejs/node/tree/v23.9.0/test/parallel/test-dgram-setTTL.js)
631629
- [parallel/test-dgram-udp6-link-local-address.js](https://github.com/nodejs/node/tree/v23.9.0/test/parallel/test-dgram-udp6-link-local-address.js)
632630
- [parallel/test-dgram-unref-in-cluster.js](https://github.com/nodejs/node/tree/v23.9.0/test/parallel/test-dgram-unref-in-cluster.js)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// deno-fmt-ignore-file
2+
// deno-lint-ignore-file
3+
4+
// Copyright Joyent and Node contributors. All rights reserved. MIT license.
5+
// Taken from Node 23.9.0
6+
// This file is automatically generated by `tests/node_compat/runner/setup.ts`. Do not modify this file manually.
7+
8+
// Flags: --expose-internals
9+
'use strict';
10+
require('../common');
11+
const assert = require('assert');
12+
const { internalBinding } = require('internal/test/binding');
13+
const { arrayBufferViewHasBuffer } = internalBinding('util');
14+
15+
// All ABs in Deno are not on heap.
16+
const tests = [
17+
{ length: 0, expectOnHeap: false },
18+
{ length: 48, expectOnHeap: false },
19+
{ length: 96, expectOnHeap: false },
20+
{ length: 1024, expectOnHeap: false },
21+
];
22+
23+
for (const { length, expectOnHeap } of tests) {
24+
const arrays = [
25+
new Uint8Array(length),
26+
new Uint16Array(length / 2),
27+
new Uint32Array(length / 4),
28+
new Float32Array(length / 4),
29+
new Float64Array(length / 8),
30+
Buffer.alloc(length),
31+
Buffer.allocUnsafeSlow(length),
32+
// Buffer.allocUnsafe() is missing because it may use pooled allocations.
33+
];
34+
35+
for (const array of arrays) {
36+
const isOnHeap = !arrayBufferViewHasBuffer(array);
37+
assert.strictEqual(isOnHeap, expectOnHeap,
38+
`mismatch: ${isOnHeap} vs ${expectOnHeap} ` +
39+
`for ${array.constructor.name}, length = ${length}`);
40+
41+
// Consistency check: Accessing .buffer should create it.
42+
array.buffer; // eslint-disable-line no-unused-expressions
43+
assert(arrayBufferViewHasBuffer(array));
44+
}
45+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// deno-fmt-ignore-file
2+
// deno-lint-ignore-file
3+
4+
// Copyright Joyent and Node contributors. All rights reserved. MIT license.
5+
// Taken from Node 23.9.0
6+
// This file is automatically generated by `tests/node_compat/runner/setup.ts`. Do not modify this file manually.
7+
8+
'use strict';
9+
10+
const common = require('../common');
11+
const assert = require('assert');
12+
const dgram = require('dgram');
13+
14+
{
15+
// Should throw EBADF if the socket is never bound.
16+
const socket = dgram.createSocket('udp4');
17+
18+
assert.throws(() => {
19+
socket.setBroadcast(true);
20+
}, /^Error: setBroadcast EBADF$/);
21+
}
22+
23+
{
24+
// Can call setBroadcast() after binding the socket.
25+
const socket = dgram.createSocket('udp4');
26+
27+
socket.bind(0, common.mustCall(() => {
28+
socket.setBroadcast(true);
29+
socket.setBroadcast(false);
30+
socket.close();
31+
}));
32+
}

0 commit comments

Comments
 (0)