Skip to content

Commit

Permalink
fix: fix broadcasting from a parent namespace (#5009)
Browse files Browse the repository at this point in the history
Following [1], emitting from a dynamic namespace to a room would throw
this error:

> node_modules/socket.io/dist/parent-namespace.js:88
>         this.children.forEach((nsp) => {
>                       ^
> 
> TypeError: Cannot read properties of undefined (reading 'forEach')
>     at ParentBroadcastAdapter.broadcast (node_modules/socket.io/dist/parent-namespace.js:88:23)
>    at BroadcastOperator.emit (node_modules/socket.io/dist/broadcast-operator.js:169:26)
>    at Socket.<anonymous> (server.js:60:33)
>    at Socket.emit (node:events:520:28)
>    at Socket.emitReserved (node_modules/socket.io/dist/typed-events.js:56:22)
>    at Socket._onclose (node_modules/socket.io/dist/socket.js:547:14)
>    at Client.onclose (node_modules/socket.io/dist/client.js:247:20)
>    at Socket.emit (node:events:532:35)
>    at Socket.onClose (node_modules/engine.io/build/socket.js:304:18)
>    at Object.onceWrapper (node:events:639:28)

Previous output code:

```js
class ParentNamespace extends namespace_1.Namespace {
    constructor(server) {
        super(server, "/_" + ParentNamespace.count++);
        this.children = new Set();
    }
    _initAdapter() {
        this.adapter = new ParentBroadcastAdapter(this, this.children);
    }
}
```

Here, `super()` calls `Namespace._initAdapter()`, but `this.children`
is not defined yet, hence the problem.

[1]: b9ce6a2

Related: #4985
  • Loading branch information
gkt5015 committed Apr 26, 2024
1 parent b25e728 commit 239a2a8
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 6 deletions.
8 changes: 2 additions & 6 deletions lib/parent-namespace.ts
Expand Up @@ -48,7 +48,7 @@ export class ParentNamespace<
* @private
*/
_initAdapter(): void {
this.adapter = new ParentBroadcastAdapter(this, this.children);
this.adapter = new ParentBroadcastAdapter(this);
}

public emit<Ev extends EventNamesWithoutAck<EmitEvents>>(
Expand Down Expand Up @@ -113,12 +113,8 @@ export class ParentNamespace<
* @private file
*/
class ParentBroadcastAdapter extends Adapter {
constructor(parentNsp: any, private readonly children: Set<Namespace>) {
super(parentNsp);
}

broadcast(packet: any, opts: BroadcastOptions) {
this.children.forEach((nsp) => {
this.nsp.children.forEach((nsp) => {
nsp.adapter.broadcast(packet, opts);
});
}
Expand Down
31 changes: 31 additions & 0 deletions test/namespaces.ts
Expand Up @@ -525,6 +525,37 @@ describe("namespaces", () => {
});
});

it("should allow connections to dynamic namespaces with a regex and emit in a room", (done) => {
const io = new Server(0);
const socket = createClient(io, "/dynamic-101");
const partialDone = createPartialDone(4, successFn(done, io, socket));

let dynamicNsp = io
.of(/^\/dynamic-\d+$/)
.on("connect", (socket) => {
expect(socket.nsp.name).to.be("/dynamic-101");
socket.join("some-room");
dynamicNsp.to("some-room").emit("hello", 4, "3", { 2: "1" });
partialDone();
})
.use((socket, next) => {
next();
partialDone();
});
socket.on("connect_error", (err) => {
expect().fail();
});
socket.on("connect", () => {
partialDone();
});
socket.on("hello", (a, b, c) => {
expect(a).to.eql(4);
expect(b).to.eql("3");
expect(c).to.eql({ 2: "1" });
partialDone();
});
});

it("should allow connections to dynamic namespaces with a function", (done) => {
const io = new Server(0);
const socket = createClient(io, "/dynamic-101");
Expand Down

0 comments on commit 239a2a8

Please sign in to comment.