Skip to content

Commit 285e7cd

Browse files
feat: move binary detection back to the parser
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]: f44256c [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
1 parent 7fc3c42 commit 285e7cd

File tree

7 files changed

+59
-27
lines changed

7 files changed

+59
-27
lines changed

lib/binary.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import isBinary from "./is-binary";
1+
import { isBinary } from "./is-binary";
22

33
/**
44
* Replaces every Buffer | ArrayBuffer | Blob | File in packet with a numbered placeholder.

lib/index.ts

+11-10
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import Emitter from "component-emitter";
1+
import Emitter = require("component-emitter");
22
import { deconstructPacket, reconstructPacket } from "./binary";
3-
import isBinary from "./is-binary";
3+
import { isBinary, hasBinary } from "./is-binary";
44

55
const debug = require("debug")("socket.io-parser");
66

@@ -44,15 +44,16 @@ export class Encoder {
4444
public encode(obj: Packet) {
4545
debug("encoding packet %j", obj);
4646

47-
if (
48-
obj.type === PacketType.BINARY_EVENT ||
49-
obj.type === PacketType.BINARY_ACK
50-
) {
51-
return this.encodeAsBinary(obj);
52-
} else {
53-
const encoding = this.encodeAsString(obj);
54-
return [encoding];
47+
if (obj.type === PacketType.EVENT || obj.type === PacketType.ACK) {
48+
if (hasBinary(obj)) {
49+
obj.type =
50+
obj.type === PacketType.EVENT
51+
? PacketType.BINARY_EVENT
52+
: PacketType.BINARY_ACK;
53+
return this.encodeAsBinary(obj);
54+
}
5555
}
56+
return [this.encodeAsString(obj)];
5657
}
5758

5859
/**

lib/is-binary.ts

+36-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
const withNativeBuffer: boolean =
2-
typeof Buffer === "function" && typeof Buffer.isBuffer === "function";
31
const withNativeArrayBuffer: boolean = typeof ArrayBuffer === "function";
42

53
const isView = (obj: any) => {
@@ -24,11 +22,45 @@ const withNativeFile =
2422
* @private
2523
*/
2624

27-
export default function isBinary(obj: any) {
25+
export function isBinary(obj: any) {
2826
return (
29-
(withNativeBuffer && Buffer.isBuffer(obj)) ||
3027
(withNativeArrayBuffer && (obj instanceof ArrayBuffer || isView(obj))) ||
3128
(withNativeBlob && obj instanceof Blob) ||
3229
(withNativeFile && obj instanceof File)
3330
);
3431
}
32+
33+
export function hasBinary(obj: any, toJSON?: boolean) {
34+
if (!obj || typeof obj !== "object") {
35+
return false;
36+
}
37+
38+
if (Array.isArray(obj)) {
39+
for (let i = 0, l = obj.length; i < l; i++) {
40+
if (hasBinary(obj[i])) {
41+
return true;
42+
}
43+
}
44+
return false;
45+
}
46+
47+
if (isBinary(obj)) {
48+
return true;
49+
}
50+
51+
if (
52+
obj.toJSON &&
53+
typeof obj.toJSON === "function" &&
54+
arguments.length === 1
55+
) {
56+
return hasBinary(obj.toJSON(), true);
57+
}
58+
59+
for (const key in obj) {
60+
if (Object.prototype.hasOwnProperty.call(obj, key) && hasBinary(obj[key])) {
61+
return true;
62+
}
63+
}
64+
65+
return false;
66+
}

test/arraybuffer.js

+5-5
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ const encoder = new Encoder();
66
describe("parser", () => {
77
it("encodes an ArrayBuffer", (done) => {
88
const packet = {
9-
type: PacketType.BINARY_EVENT,
9+
type: PacketType.EVENT,
1010
data: ["a", new ArrayBuffer(2)],
1111
id: 0,
1212
nsp: "/",
@@ -19,7 +19,7 @@ describe("parser", () => {
1919
for (let i = 0; i < array.length; i++) array[i] = i;
2020

2121
const packet = {
22-
type: PacketType.BINARY_EVENT,
22+
type: PacketType.EVENT,
2323
data: ["a", array],
2424
id: 0,
2525
nsp: "/",
@@ -29,7 +29,7 @@ describe("parser", () => {
2929

3030
it("encodes ArrayBuffers deep in JSON", (done) => {
3131
const packet = {
32-
type: PacketType.BINARY_EVENT,
32+
type: PacketType.EVENT,
3333
data: [
3434
"a",
3535
{
@@ -46,7 +46,7 @@ describe("parser", () => {
4646

4747
it("encodes deep binary JSON with null values", (done) => {
4848
const packet = {
49-
type: PacketType.BINARY_EVENT,
49+
type: PacketType.EVENT,
5050
data: ["a", { a: "b", c: 4, e: { g: null }, h: new ArrayBuffer(9) }],
5151
nsp: "/",
5252
id: 600,
@@ -56,7 +56,7 @@ describe("parser", () => {
5656

5757
it("cleans itself up on close", () => {
5858
const packet = {
59-
type: PacketType.BINARY_EVENT,
59+
type: PacketType.EVENT,
6060
data: ["a", new ArrayBuffer(2), new ArrayBuffer(3)],
6161
id: 0,
6262
nsp: "/",

test/blob.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ describe("parser", () => {
2424
}
2525

2626
const packet = {
27-
type: PacketType.BINARY_EVENT,
27+
type: PacketType.EVENT,
2828
data: ["a", data],
2929
id: 0,
3030
nsp: "/",
@@ -43,7 +43,7 @@ describe("parser", () => {
4343
}
4444

4545
const packet = {
46-
type: PacketType.BINARY_EVENT,
46+
type: PacketType.EVENT,
4747
data: ["a", { a: "hi", b: { why: data }, c: "bye" }],
4848
id: 999,
4949
nsp: "/deep",
@@ -62,7 +62,7 @@ describe("parser", () => {
6262
}
6363

6464
const packet = {
65-
type: PacketType.BINARY_ACK,
65+
type: PacketType.ACK,
6666
data: [{ a: "hi ack", b: { why: data }, c: "bye ack" }],
6767
id: 999,
6868
nsp: "/deep",

test/buffer.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ describe("parser", () => {
55
it("encodes a Buffer", (done) => {
66
helpers.test_bin(
77
{
8-
type: PacketType.BINARY_EVENT,
8+
type: PacketType.EVENT,
99
data: ["a", Buffer.from("abc", "utf8")],
1010
id: 23,
1111
nsp: "/cool",
@@ -17,7 +17,7 @@ describe("parser", () => {
1717
it("encodes a binary ack with Buffer", (done) => {
1818
helpers.test_bin(
1919
{
20-
type: PacketType.BINARY_ACK,
20+
type: PacketType.ACK,
2121
data: ["a", Buffer.from("xxx", "utf8"), {}],
2222
id: 127,
2323
nsp: "/back",

tsconfig.json

+1-2
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@
44
"allowJs": false,
55
"target": "es2017",
66
"module": "commonjs",
7-
"declaration": true,
8-
"esModuleInterop": true
7+
"declaration": true
98
},
109
"include": [
1110
"./lib/**/*"

0 commit comments

Comments
 (0)