A packet like '2[{"toString":"foo"}]' was decoded as:
{
type: EVENT,
data: [ { "toString": "foo" } ]
}
Which would then throw an error when passed to the EventEmitter class:
> TypeError: Cannot convert object to primitive value
> at Socket.emit (node:events:507:25)
> at .../node_modules/socket.io/lib/socket.js:531:14
History of the isPayloadValid() method:
- added in [78f9fc2](78f9fc2999) (v4.0.1, socket.io@3.0.0)
- updated in [1c220dd](1c220ddbf4) (v4.0.4, socket.io@3.1.0)
If a client was in the process of receiving some binary attachments
when the connection was abruptly closed, then the manager would call
`decoder.destroy()` ([1]) but was then stuck in a "parse error" loop
upon reconnection (since it expected a binary attachment and not a
CONNECT packet).
[1]: a1c528b089/lib/manager.ts (L520)
A specially crafted packet could be incorrectly decoded.
Example:
```js
const decoder = new Decoder();
decoder.on("decoded", (packet) => {
console.log(packet.data); // prints [ 'hello', [Function: splice] ]
})
decoder.add('51-["hello",{"_placeholder":true,"num":"splice"}]');
decoder.add(Buffer.from("world"));
```
As usual, please remember not to trust user input.
The meaning is not modified: this packet type is still used by the
server when the connection to a namespace is refused. But I feel the
name makes more sense:
```js
socket.on("connect", () => {});
socket.on("connect_error", () => {});
// instead of
socket.on("error", () => {});
```
The binary detection was moved from the parser to the client/server in
[1], in order to allow the user to skip the binary detection for huge
JSON payloads.
```js
socket.binary(false).emit(...);
```
The binary detection is needed in the default parser, because the
payload is encoded with JSON.stringify(), which does not support binary
content (ArrayBuffer, Blob, ...).
But other parsers (like [2] or [3]) do not need this check, so we'll
move the binary detection back here and remove the socket.binary()
method, as this use case is now covered by the ability to provide your
own parser.
Note: the hasBinary method was copied from [4].
[1]: f44256c523
[2]: https://github.com/darrachequesne/socket.io-msgpack-parser
[3]: https://github.com/darrachequesne/socket.io-json-parser
[4]: https://github.com/darrachequesne/has-binary
This was needed in a previous version of the parser, which used msgpack
to encode the payload.
Blobs (and Files) will now be included in the array of binary
attachments without any additional transformation.
Breaking change: the encode method is now synchronous
See also 299849b002
It does not make sense to catch the errors thrown by JSON.stringify()
and convert them to an ERROR packet (which are meant for namespace
authentication errors), it should be caught higher in the stack.
Related: 92c530da47
An invalid packet was previously parsed as an ERROR packet, which was
then ignored because it didn't contain any 'nsp' (namespace) field.
This behavior was wrong because:
- it means the other side is sending invalid payloads, so the
connection must be closed right away
- ERROR packets are meant for namespace authentication failures
Parsing an invalid payload will now throw an error, which must be
caught by the caller.
Closes https://github.com/socketio/socket.io-parser/issues/86