This change allows us to:
- reduce the size of the bundle
- provide an ESM bundle (for usage in <script type="module">)
BREAKING CHANGE: due to how default export works with ES modules, we
have removed the default export of the library, which means the
following code:
```js
require("engine.io-client")(...);
```
will not work anymore. The named export must be used instead:
```js
const { Socket } = require("engine.io-client);
// or import { Socket } from "engine.io-client";
const socket = new Socket(...);
```
Note: the UMD build still exposes a function though:
```html
<script src="/path/to/engine.io.js"></script>
<script>
const socket = eio(...);
</script>
```
Note: webpack is still used with zuul because of the custom builder
(zuul-builder-webpack)
This allows to control the behavior of mocked timers (@sinonjs/fake-timers),
depending on the value of the "useNativeTimers" option:
- true: use native setTimeout function
- false (default): use classic timers, that may be mocked
The "installTimerFunctions" method will also be used in the
`socket.io-client` package:
```
import { installTimerFunctions } from "engine.io-client/lib/util";
```
Note: we could also have put the method in its own library, but that
sounded a bit overkill
Related: https://github.com/socketio/socket.io-client/pull/1479
An immediate setTimeout was used to unblock the WebSocket write.
Unfortunately, this setTimeout can be throttled by browsers when the
tab is backgrounded.
This can lead to missed pong responses to server pings, which
eventually leads to disconnection.
Related: https://github.com/socketio/engine.io-client/issues/649
Since [1], the socket is now closed when receiving the "beforeunload"
event in the browser.
This change was meant to fix a discrepancy between Chrome and Firefox
when the user reloads/closes a browser tab: Firefox would close the
connection (and emit a "disconnect" event, at the Socket.IO level), but
not Chrome (see [2]).
But it also closes the connection when there is another "beforeunload"
handler, for example when the user is prompted "are you sure you want
to leave this page?".
Note: calling "stopImmediatePropagation()" was a possible workaround:
```js
window.addEventListener('beforeunload', (event) => {
event.preventDefault();
event.stopImmediatePropagation();
event.returnValue = 'are you sure you want to leave this page?';
});
```
This commit adds a "closeOnBeforeunload" option, which controls whether
a handler is registered for the "beforeunload" event.
Syntax:
```js
const socket = require('engine.io-client')('ws://localhost', {
closeOnBeforeunload: false // defaults to true
});
```
[1]: ed48b5dc34
[2]: https://github.com/socketio/socket.io/issues/3639
Related:
- https://github.com/socketio/engine.io-client/issues/661
- https://github.com/socketio/engine.io-client/issues/658
- https://github.com/socketio/socket.io-client/issues/1451
Reference: https://developer.mozilla.org/en-US/docs/Web/API/Window/beforeunload_event
In some cases, a "Transport not open" error could be thrown when the
transport was silently closed in the onbeforeunload event (added in
[1]).
To reproduce:
```js
window.addEventListener("unload", () => {
socket.write("...");
});
```
[1]: ed48b5dc34
Related: https://github.com/socketio/socket.io/issues/3838
With autoUnref set to true (default: false), the Engine.IO client will
allow the program to exit if there is no other active timer/socket in
the event system.
Note: the 'xmlhttprequest-ssl' package has been copied in the contrib/
directory, until the change is merged upstream
Related: https://github.com/socketio/engine.io-client/issues/653
The `supportsBinary` attribute and the `forceBase64` option are kept
untouched, though they are not used by the polling transport, which
now always converts the payloads to base64.
Related: https://github.com/socketio/socket.io-client/issues/1391
The undefined value breaks React Native on Android with a rather cryptic error message:
```
Attempt to invoke virtual method 'boolean java.lang.Boolean.booleanValue() on a null object reference
```
This bug was introduced by [1].
[1]: 5f47a50ee5
Related: https://github.com/socketio/socket.io-client/issues/1403
Only 'headers' and 'localAddress' options are supported by the
WebSocket implementation in React Native.
The following message was printed to the console:
> Unrecognized WebSocket connection option(s) `agent`, `perMessageDeflate`, `pfx`, `key`, `passphrase`, `cert`, `ca`, `ciphers`, `rejectUnauthorized`. Did you mean to put these under `headers`?
Reference: https://reactnative.dev/docs/network.html#websocket-support
The ping packets will now be sent by the server, because the timers set
in the browsers are not reliable enough. We suspect that a lot of
timeout problems came from timers being delayed on the client-side.
Breaking change: v3.x clients will not be able to connect anymore (they
will send a ping packet and timeout while waiting for a pong packet).
Related: https://github.com/socketio/engine.io/issues/312
React-Native provides a Websocket object that is more functionally aligned with the Node.js websocket than the browser websocket.
It has the same constructor signature as the Node.js websocket and can support extraHeaders and protocols.
This PR will detect when the engine.io-client is running in React-Native, call the proper Websocket constructor, and enable support for extraHeaders.