7687 Commits

Author SHA1 Message Date
Damien Arrachequesne
8955eb7b75 docs(examples): add some examples to track the memory usage
Related: fc21c4a05f
2024-06-13 23:21:26 +02:00
Jonathan Perret
fc21c4a05f fix: fix websocket and webtransport send callbacks (#699)
With the `websocket` transport, the callbacks which indicate that the
packets are actually written were not properly called.

Example:

```js
socket.send("hello", () => {
  // the message has been written to the underlying transport
});
```

The bug was caused by the `websocket` transport (and `webtransport` as
well) having its `supportsFraming` property set to `true`, despite
having been changed in [1] to emit a single `drain` event for each
batch of messages written to the transport like the `polling` transport
always did. Note that although [1] is partially reverted in [2], the
new `drain` event behavior is preserved as called out in that commit's
message.

The `supportsFraming` attribute was introduced in [3] (amended by [4])
as a way to distinguish transports that emit one `drain` per message
from those that emit one `drain` per batch. Since the delivery of
`send` callbacks depends on matching `drain` events with
`transport.send` calls, that distinction is vital to correct behavior.

However, now that all transports have converged to "one `drain` per
batch" behavior, this `supportsFraming` property can be retired (and
the code for calling callbacks simplified).

[1]: https://github.com/socketio/engine.io/pull/618
[2]: a65a047526
[3]: https://github.com/socketio/engine.io/pull/130
[4]: https://github.com/socketio/engine.io/pull/132

Related: https://github.com/socketio/engine.io/issues/698
2024-06-13 23:02:22 +02:00
Jakub Szaredko
579d34412a chore: fix compilation on macOS (#1616) 2024-06-11 12:30:57 +02:00
Damien Arrachequesne
b624c50832 fix: add some randomness to the cache busting string generator
The yeast() method could generate the same string twice when used in
two different iframes, which can cause Safari to only send one HTTP
request (deduplication) and trigger an HTTP 400 error afterwards since
the two iframes share the same session ID.

This new method, combining 5 chars from the timestamp and 3 chars from
Math.random() should be sufficient for our use case.

Related: https://github.com/socketio/engine.io/issues/690

See also: 874484cc1e
2024-06-05 13:44:55 +02:00
Damien Arrachequesne
c087dc5f32 docs(changelog): include the size of the bundle 2024-06-04 17:19:31 +02:00
Damien Arrachequesne
ce13763b52 ci: upgrade to actions/checkout@4 and actions/setup-node@4
Reference: https://github.blog/changelog/2023-09-22-github-actions-transitioning-from-node-16-to-node-20/
2024-06-04 17:08:48 +02:00
Damien Arrachequesne
74cfb98f12 refactor: prefix private attributes to allow property mangling
|          | before  | after   |
|----------|---------|---------|
| min      | 27.3 KB | 26.1 KB |
| min+gzip | 8.8 KB  | 8.7 KB  |
| min+br   | 8.0 KB  | 7.8 KB  |

Reference: https://terser.org/docs/options/#mangle-properties-options
2024-06-04 17:06:29 +02:00
Damien Arrachequesne
2b9abbbfae chore: restore the debug package in the dev bundle
The debug package was not included anymore in the dev bundle since the
migration from webpack to rollup ([1]) in version 6.0.0.

[1]: 27de300de4

See also: 4683a954d4
2024-06-03 14:54:49 +02:00
Damien Arrachequesne
e105551ef1 fix: fix cookie management with WebSocket (Node.js only)
Before this commit, the cookies were only sent with the HTTP
long-polling transport, and not when upgrading to WebSocket.

See also: 5fc88a62d4
2024-06-03 09:58:56 +02:00
Damien Arrachequesne
3f6647897a chore: remove unused rollup plugin
This plugin is not needed anymore, since the
`@socket.io/component-emitter` package now includes an ESM version.
2024-05-31 18:46:37 +02:00
Damien Arrachequesne
4aec72a53c chore: use babel loose mode when transpiling classes
By default, Babel uses `Object.defineProperty()` when transpiling
classes. We'll now use the loose mode which creates a more terse
output.

|          | before | after  |
|----------|--------|--------|
| min+gzip | 8.8 KB | 8.6 KB |
| min+br   | 8.0 KB | 7.7 KB |

Reference: https://babeljs.io/docs/babel-plugin-transform-classes
2024-05-31 18:35:31 +02:00
Damien Arrachequesne
dd52844f09 chore: add a script to compute the bundle size 2024-05-31 18:10:02 +02:00
Damien Arrachequesne
f4d898ee96 feat: allow to provide a list of transport implementations
This commit adds the ability to provide a list of transport
implementations to use when connecting to an Engine.IO server.

This can be used to use HTTP long-polling based on `fetch()`, instead
of the default implementation based on the `XMLHttpRequest` object.

```
import { Socket, Fetch, WebSocket } from "engine.io-client";

const socket = new Socket({
  transports: [Fetch, WebSocket]
});
```

This is useful in some environments that do not provide a
`XMLHttpRequest` object, like Chrome extension background scripts.

> XMLHttpRequest() can't be called from a service worker, extension or
otherwise. Replace calls from your background script to
XMLHttpRequest() with calls to global fetch().

Source: https://developer.chrome.com/docs/extensions/develop/migrate/to-service-workers#replace-xmlhttprequest

Related:

- https://github.com/socketio/engine.io-client/issues/716
- https://github.com/socketio/socket.io/issues/4980

This is also useful when running the client with Deno or Bun, as it
allows to use the built-in `fetch()` method and `WebSocket` object,
instead of using the `xmlhttprequest-ssl` and `ws` Node.js packages.

Related: https://github.com/socketio/socket.io-deno/issues/12

This feature also comes with the ability to exclude the code related to
unused transports (a.k.a. "tree-shaking"):

```js
import { SocketWithoutUpgrade, WebSocket } from "engine.io-client";

const socket = new SocketWithoutUpgrade({
  transports: [WebSocket]
});
```

In that case, the code related to HTTP long-polling and WebTransport
will be excluded from the final bundle.

Related: https://github.com/socketio/socket.io/discussions/4393
2024-05-31 16:56:25 +02:00
Damien Arrachequesne
579b243e89 feat: add the ability to test all transports
When setting the `tryAllTransports` option to `true`, if the first
transport (usually, HTTP long-polling) fails, then the other transports
will be tested too.

This is useful in two cases:

> when HTTP long-polling is disabled on the server, or if CORS fails

Related:

- https://github.com/socketio/engine.io-client/issues/575
- https://github.com/socketio/socket.io-client/issues/1448

> when WebSocket is tested first (`transports: ["websocket", "polling"])

Related:

- https://github.com/socketio/engine.io-client/issues/714
- https://github.com/socketio/socket.io-client/issues/1599

The only potential downside is that the connection attempt could take
more time in case of failure, as there have been reports of WebSocket
connection errors taking several seconds before being detected (that's
one reason for using HTTP long-polling first). That's why the option
defaults to `false` for now.
2024-05-28 19:31:36 +02:00
tnfAngel
31f10f6808 fix(types): make io#httpServer public (#5035)
Related: https://github.com/socketio/socket.io/issues/5034
2024-05-27 18:09:14 +02:00
Damien Arrachequesne
2c1851d095 refactor: simplify transport creation
The try/catch clause was needed for the JSONP transport, which was
removed in [1].

[1]: b2c73812e9
2024-05-20 05:32:08 +02:00
Damien Arrachequesne
68f9e0d8e0 refactor: improve the types 2024-05-19 19:54:56 +02:00
Damien Arrachequesne
c060d65947 refactor: improve the constructor types 2024-05-19 19:41:36 +02:00
Damien Arrachequesne
cb10d01fac docs: improve documentation for the autoUnref option 2024-05-19 19:26:46 +02:00
Damien Arrachequesne
156d622c48 refactor: remove unused onlyBinaryUpgrades option
This option no longer has any effect since [1].

[1]: c46611ce44
2024-05-19 19:16:55 +02:00
pouria azad
89c4c7eb47 refactor(examples): minor tweak (#5017) 2024-05-10 05:00:20 +02:00
Gah Tang
239a2a82d0 fix: fix broadcasting from a parent namespace (#5009)
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]: b9ce6a25d1

Related: https://github.com/socketio/socket.io/issues/4985
2024-04-26 15:36:26 +02:00
Damien Arrachequesne
b25e728da0 docs: update TypeScript example 2024-04-26 07:45:48 +02:00
Damien Arrachequesne
8a2ece1f36 chore(release): 3.1.2
Diff: https://github.com/socketio/emitter/compare/3.1.1...3.1.2
2024-04-26 07:31:29 +02:00
Damien Arrachequesne
e6aa1a331c fix: point towards the CommonJS types
In order to fix the following issue:

> error TS1479: The current file is a CommonJS module whose imports will produce 'require' calls; however, the referenced file is an ECMAScript module and cannot be imported with 'require'. Consider writing a dynamic 'import("@socket.io/component-emitter")' call instead.
>
> 1 import { Emitter } from "@socket.io/component-emitter";

This problem was introduced in [1], when reworking the dual packaging.

Related: https://github.com/socketio/socket.io-parser/issues/132

[1]: ba6b56de2c
2024-04-26 07:26:11 +02:00
Damien Arrachequesne
62cbed729d refactor: change URL max length to 8000
The previous limit of 2000 characters was a bit too low in certain cases.

From https://www.rfc-editor.org/rfc/rfc9110#section-4.1-5

> It is RECOMMENDED that all senders and recipients support, at a minimum, URIs with lengths of 8000 octets in protocol elements.

Related: https://github.com/socketio/engine.io-client/issues/715

See also: 707597df26
2024-04-23 11:23:18 +02:00
Damien Arrachequesne
b11763beec feat: add HTTP long-polling implementation based on fetch()
Usage:

```js
import { Socket, transports, Fetch } from "engine.io-client";

transports.polling = Fetch;

const socket = new Socket("https://example.com");
```

Note: tree-shaking unused transports is not currently supported and
will be added later.

Related:

- https://github.com/socketio/socket.io/issues/4980
- https://github.com/socketio/engine.io-client/issues/716
2024-04-23 11:09:57 +02:00
Damien Arrachequesne
14d4997dbc docs: add example with NW.js 2024-04-12 11:13:31 +02:00
Damien Arrachequesne
c68478dcf8 chore(release): 3.1.1
Diff: https://github.com/socketio/emitter/compare/4.0.0...3.1.1
2024-04-10 16:51:42 +02:00
Damien Arrachequesne
ba6b56de2c refactor: rework the dual CommonJS/ES packages
In order to remove the .mjs file, which causes some problems with React
Native.

Related: https://github.com/socketio/socket.io-client/issues/1598
2024-04-10 16:27:02 +02:00
Damien Arrachequesne
4476b52981 revert: refactor: rename emitReserved to _emitReserved to improve mangling
This reverts commit 0852bda0b4.

The impact on the final bundle size is negligible.
2024-04-10 16:20:21 +02:00
Damien Arrachequesne
28c9ed4331 ci: init GitHub Actions 2024-04-10 16:17:24 +02:00
Damien Arrachequesne
907f102517 docs: update React Native example 2024-04-05 19:19:39 +02:00
dependabot[bot]
79ea52dc09 chore(deps): bump express from 4.18.2 to 4.19.2 in /examples/latency (#700)
Bumps [express](https://github.com/expressjs/express) from 4.18.2 to 4.19.2.
- [Release notes](https://github.com/expressjs/express/releases)
- [Changelog](https://github.com/expressjs/express/blob/master/History.md)
- [Commits](https://github.com/expressjs/express/compare/4.18.2...4.19.2)

---
updated-dependencies:
- dependency-name: express
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-29 10:29:47 +01:00
Damien Arrachequesne
be2da4e4dc docs: add example with Nuxt 2024-03-29 10:00:23 +01:00
Damien Arrachequesne
61f444956b docs: add example with Next.js (with app router) 2024-03-27 11:02:03 +01:00
dependabot[bot]
218c3443f6 chore: bump express from 4.17.3 to 4.19.2 (#718)
Bumps [express](https://github.com/expressjs/express) from 4.17.3 to 4.19.2.
- [Release notes](https://github.com/expressjs/express/releases)
- [Changelog](https://github.com/expressjs/express/blob/master/History.md)
- [Commits](https://github.com/expressjs/express/compare/4.17.3...4.19.2)

---
updated-dependencies:
- dependency-name: express
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-26 08:15:20 +01:00
Damien Arrachequesne
b0568b20c1 docs: add example with Next.js (with pages router) 2024-03-25 18:05:22 +01:00
Damien Arrachequesne
50176812a1 chore(release): 4.7.5
Diff: https://github.com/socketio/socket.io/compare/4.7.4...4.7.5
4.7.5 socket.io@4.7.5
2024-03-14 17:55:23 +01:00
Damien Arrachequesne
4f6030f2c4 chore(release): 4.7.5
Diff: https://github.com/socketio/socket.io-client/compare/4.7.4...4.7.5
socket.io-client@4.7.5
2024-03-14 17:43:43 +01:00
Damien Arrachequesne
34cbfbb532 fix: discard acknowledgements upon disconnection
Previously, getting disconnected while waiting for an acknowledgement
would create a memory leak, as the acknowledgement was never received
and the handler would stay in memory forever.

This commit fixes the issue:

- handlers that do accept an error as first argument, such as:

* `socket.emit("test", (err, value) => { ... })` with `ackTimeout` option
* `socket.timeout(5000).emit("test", (err, value) => { ... })`
* `const value = await socket.emitWithAck("test")`

will now properly resolve with an error and get discarded.

- handlers that don't like `socket.emit("test", (value) => { ... });`
will simply be discarded upon disconnection

Note: the structure of the 'acks' attribute has been left untouched, in
order to prevent any breaking change.

Related:

- https://github.com/socketio/socket.io-client/issues/1546
- https://github.com/socketio/socket.io/issues/4964
2024-03-14 17:34:29 +01:00
Damien Arrachequesne
bf64870957 fix: close the adapters when the server is closed
Related:

- https://github.com/socketio/socket.io-mongo-adapter/issues/9
- https://github.com/socketio/socket.io-postgres-adapter/issues/13
- 0e23ff0cc6
2024-02-23 12:10:29 +01:00
Jonathan Perret
0efa04b584 fix(types): make socket.request writable (#697)
Related: https://github.com/socketio/engine.io/issues/696
2024-02-23 10:21:43 +01:00
Damien Arrachequesne
748e18c22e ci: test with older TypeScript version
Related: https://github.com/socketio/socket.io/issues/3891
2024-02-22 10:12:18 +01:00
Damien Arrachequesne
5eae5a0b54 chore(release): 2.5.4
Diff: https://github.com/socketio/socket.io-adapter/compare/2.5.3...2.5.4
2024-02-22 09:33:01 +01:00
Damien Arrachequesne
005d546767 ci: test with older TypeScript version 2024-02-22 09:31:39 +01:00
Damien Arrachequesne
a13f35f0e6 fix: ensure the order of the commands
Before this change, the broadcast() method would send the BROADCAST
command and then apply it locally (which is required to retrieve the
offset of the message, when connection state recovery is enabled),
while the other commands like disconnectSockets() would first apply it
locally and then send the command to the other nodes.

So, for example:

```js
io.emit("bye");
io.disconnectSockets();
```

In that case, the clients connected to the io instance would not receive
the "bye" event, while the clients connected to the other server
instances would receive it before being disconnected.

Related:

- https://github.com/socketio/socket.io-redis-streams-adapter/issues/13
- https://github.com/socketio/socket.io-postgres-adapter/issues/12
2024-02-22 09:15:45 +01:00
Damien Arrachequesne
207c0dba1a refactor: break circular dependency (2) 2024-02-22 08:34:29 +01:00
Damien Arrachequesne
abc93a9ac7 refactor: break circular dependency (1)
This will be done in two steps, in order to preserve the history of the
index.ts file.
2024-02-22 08:32:40 +01:00
Damien Arrachequesne
9d4c4a75a4 refactor(cluster): export ClusterAdapterOptions and MessageType types
Related:

- 89d00a49e4/lib/adapter.ts (L17)
- 89d00a49e4/lib/adapter.ts (L191)
2024-02-22 08:01:30 +01:00