diff --git a/lib/binary.ts b/lib/binary.ts index 80a6b96..89956c2 100644 --- a/lib/binary.ts +++ b/lib/binary.ts @@ -1,4 +1,4 @@ -import isBinary from "./is-binary"; +import { isBinary } from "./is-binary"; /** * Replaces every Buffer | ArrayBuffer | Blob | File in packet with a numbered placeholder. diff --git a/lib/index.ts b/lib/index.ts index ff5671e..cc6e69d 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -1,6 +1,6 @@ -import Emitter from "component-emitter"; +import Emitter = require("component-emitter"); import { deconstructPacket, reconstructPacket } from "./binary"; -import isBinary from "./is-binary"; +import { isBinary, hasBinary } from "./is-binary"; const debug = require("debug")("socket.io-parser"); @@ -44,15 +44,16 @@ export class Encoder { public encode(obj: Packet) { debug("encoding packet %j", obj); - if ( - obj.type === PacketType.BINARY_EVENT || - obj.type === PacketType.BINARY_ACK - ) { - return this.encodeAsBinary(obj); - } else { - const encoding = this.encodeAsString(obj); - return [encoding]; + if (obj.type === PacketType.EVENT || obj.type === PacketType.ACK) { + if (hasBinary(obj)) { + obj.type = + obj.type === PacketType.EVENT + ? PacketType.BINARY_EVENT + : PacketType.BINARY_ACK; + return this.encodeAsBinary(obj); + } } + return [this.encodeAsString(obj)]; } /** diff --git a/lib/is-binary.ts b/lib/is-binary.ts index ed8fdbf..0ec6417 100644 --- a/lib/is-binary.ts +++ b/lib/is-binary.ts @@ -1,5 +1,3 @@ -const withNativeBuffer: boolean = - typeof Buffer === "function" && typeof Buffer.isBuffer === "function"; const withNativeArrayBuffer: boolean = typeof ArrayBuffer === "function"; const isView = (obj: any) => { @@ -24,11 +22,45 @@ const withNativeFile = * @private */ -export default function isBinary(obj: any) { +export function isBinary(obj: any) { return ( - (withNativeBuffer && Buffer.isBuffer(obj)) || (withNativeArrayBuffer && (obj instanceof ArrayBuffer || isView(obj))) || (withNativeBlob && obj instanceof Blob) || (withNativeFile && obj instanceof File) ); } + +export function hasBinary(obj: any, toJSON?: boolean) { + if (!obj || typeof obj !== "object") { + return false; + } + + if (Array.isArray(obj)) { + for (let i = 0, l = obj.length; i < l; i++) { + if (hasBinary(obj[i])) { + return true; + } + } + return false; + } + + if (isBinary(obj)) { + return true; + } + + if ( + obj.toJSON && + typeof obj.toJSON === "function" && + arguments.length === 1 + ) { + return hasBinary(obj.toJSON(), true); + } + + for (const key in obj) { + if (Object.prototype.hasOwnProperty.call(obj, key) && hasBinary(obj[key])) { + return true; + } + } + + return false; +} diff --git a/test/arraybuffer.js b/test/arraybuffer.js index 14ef58c..6d44057 100644 --- a/test/arraybuffer.js +++ b/test/arraybuffer.js @@ -6,7 +6,7 @@ const encoder = new Encoder(); describe("parser", () => { it("encodes an ArrayBuffer", (done) => { const packet = { - type: PacketType.BINARY_EVENT, + type: PacketType.EVENT, data: ["a", new ArrayBuffer(2)], id: 0, nsp: "/", @@ -19,7 +19,7 @@ describe("parser", () => { for (let i = 0; i < array.length; i++) array[i] = i; const packet = { - type: PacketType.BINARY_EVENT, + type: PacketType.EVENT, data: ["a", array], id: 0, nsp: "/", @@ -29,7 +29,7 @@ describe("parser", () => { it("encodes ArrayBuffers deep in JSON", (done) => { const packet = { - type: PacketType.BINARY_EVENT, + type: PacketType.EVENT, data: [ "a", { @@ -46,7 +46,7 @@ describe("parser", () => { it("encodes deep binary JSON with null values", (done) => { const packet = { - type: PacketType.BINARY_EVENT, + type: PacketType.EVENT, data: ["a", { a: "b", c: 4, e: { g: null }, h: new ArrayBuffer(9) }], nsp: "/", id: 600, @@ -56,7 +56,7 @@ describe("parser", () => { it("cleans itself up on close", () => { const packet = { - type: PacketType.BINARY_EVENT, + type: PacketType.EVENT, data: ["a", new ArrayBuffer(2), new ArrayBuffer(3)], id: 0, nsp: "/", diff --git a/test/blob.js b/test/blob.js index 559d7ef..cf0717a 100644 --- a/test/blob.js +++ b/test/blob.js @@ -24,7 +24,7 @@ describe("parser", () => { } const packet = { - type: PacketType.BINARY_EVENT, + type: PacketType.EVENT, data: ["a", data], id: 0, nsp: "/", @@ -43,7 +43,7 @@ describe("parser", () => { } const packet = { - type: PacketType.BINARY_EVENT, + type: PacketType.EVENT, data: ["a", { a: "hi", b: { why: data }, c: "bye" }], id: 999, nsp: "/deep", @@ -62,7 +62,7 @@ describe("parser", () => { } const packet = { - type: PacketType.BINARY_ACK, + type: PacketType.ACK, data: [{ a: "hi ack", b: { why: data }, c: "bye ack" }], id: 999, nsp: "/deep", diff --git a/test/buffer.js b/test/buffer.js index d5ebc23..af8e1ba 100644 --- a/test/buffer.js +++ b/test/buffer.js @@ -5,7 +5,7 @@ describe("parser", () => { it("encodes a Buffer", (done) => { helpers.test_bin( { - type: PacketType.BINARY_EVENT, + type: PacketType.EVENT, data: ["a", Buffer.from("abc", "utf8")], id: 23, nsp: "/cool", @@ -17,7 +17,7 @@ describe("parser", () => { it("encodes a binary ack with Buffer", (done) => { helpers.test_bin( { - type: PacketType.BINARY_ACK, + type: PacketType.ACK, data: ["a", Buffer.from("xxx", "utf8"), {}], id: 127, nsp: "/back", diff --git a/tsconfig.json b/tsconfig.json index bcd6128..87d51bf 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,8 +4,7 @@ "allowJs": false, "target": "es2017", "module": "commonjs", - "declaration": true, - "esModuleInterop": true + "declaration": true }, "include": [ "./lib/**/*"