@@ -1,4 +1,4 @@
|
||||
import { isBinary } from "./is-binary"
|
||||
import { isBinary } from "./is-binary.js"
|
||||
|
||||
/**
|
||||
* Replaces every Buffer | ArrayBuffer | Blob | File in packet with a numbered placeholder.
|
||||
@@ -33,7 +33,7 @@ function _deconstructPacket(data, buffers) {
|
||||
} else if (typeof data === "object" && !(data instanceof Date)) {
|
||||
const newData = {}
|
||||
for (const key in data) {
|
||||
if (data.hasOwnProperty(key)) {
|
||||
if (Object.prototype.hasOwnProperty.call(data, key)) {
|
||||
newData[key] = _deconstructPacket(data[key], buffers)
|
||||
}
|
||||
}
|
||||
@@ -60,15 +60,23 @@ export function reconstructPacket(packet, buffers) {
|
||||
function _reconstructPacket(data, buffers) {
|
||||
if (!data) return data
|
||||
|
||||
if (data && data._placeholder) {
|
||||
return buffers[data.num] // appropriate buffer (should be natural order anyway)
|
||||
if (data && data._placeholder === true) {
|
||||
const isIndexValid =
|
||||
typeof data.num === "number" &&
|
||||
data.num >= 0 &&
|
||||
data.num < buffers.length
|
||||
if (isIndexValid) {
|
||||
return buffers[data.num] // appropriate buffer (should be natural order anyway)
|
||||
} else {
|
||||
throw new Error("illegal attachments")
|
||||
}
|
||||
} else if (Array.isArray(data)) {
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
data[i] = _reconstructPacket(data[i], buffers)
|
||||
}
|
||||
} else if (typeof data === "object") {
|
||||
for (const key in data) {
|
||||
if (data.hasOwnProperty(key)) {
|
||||
if (Object.prototype.hasOwnProperty.call(data, key)) {
|
||||
data[key] = _reconstructPacket(data[key], buffers)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import EventEmitter = require("events")
|
||||
import { deconstructPacket, reconstructPacket } from "./binary"
|
||||
import { isBinary, hasBinary } from "./is-binary"
|
||||
import { Emitter } from "@socket.io/component-emitter"
|
||||
import { deconstructPacket, reconstructPacket } from "./binary.js"
|
||||
import { isBinary, hasBinary } from "./is-binary.js"
|
||||
// import debugModule from "debug" // debug()
|
||||
|
||||
// const debug = require("debug")("socket.io-parser")
|
||||
// const debug = debugModule("socket.io-parser") // debug()
|
||||
const debug = require("../debug")("socket.io-client")
|
||||
|
||||
/**
|
||||
* Protocol version.
|
||||
@@ -35,6 +37,12 @@ export interface Packet {
|
||||
*/
|
||||
|
||||
export class Encoder {
|
||||
/**
|
||||
* Encoder constructor
|
||||
*
|
||||
* @param {function} replacer - custom replacer to pass down to JSON.parse
|
||||
*/
|
||||
constructor(private replacer?: (this: any, key: string, value: any) => any) { }
|
||||
/**
|
||||
* Encode a packet as a single string if non-binary, or as a
|
||||
* buffer sequence, depending on packet type.
|
||||
@@ -42,7 +50,7 @@ export class Encoder {
|
||||
* @param {Object} obj - packet object
|
||||
*/
|
||||
public encode(obj: Packet) {
|
||||
console.trace("encoding packet", JSON.stringify(obj))
|
||||
debug("encoding packet %j", obj)
|
||||
|
||||
if (obj.type === PacketType.EVENT || obj.type === PacketType.ACK) {
|
||||
if (hasBinary(obj)) {
|
||||
@@ -85,10 +93,10 @@ export class Encoder {
|
||||
|
||||
// json data
|
||||
if (null != obj.data) {
|
||||
str += JSON.stringify(obj.data)
|
||||
str += JSON.stringify(obj.data, this.replacer)
|
||||
}
|
||||
|
||||
console.trace("encoded", JSON.stringify(obj), "as", str)
|
||||
debug("encoded %j as %s", obj, str)
|
||||
return str
|
||||
}
|
||||
|
||||
@@ -108,15 +116,24 @@ export class Encoder {
|
||||
}
|
||||
}
|
||||
|
||||
interface DecoderReservedEvents {
|
||||
decoded: (packet: Packet) => void
|
||||
}
|
||||
|
||||
/**
|
||||
* A socket.io Decoder instance
|
||||
*
|
||||
* @return {Object} decoder
|
||||
*/
|
||||
export class Decoder extends EventEmitter {
|
||||
export class Decoder extends Emitter<{}, {}, DecoderReservedEvents> {
|
||||
private reconstructor: BinaryReconstructor
|
||||
|
||||
constructor() {
|
||||
/**
|
||||
* Decoder constructor
|
||||
*
|
||||
* @param {function} reviver - custom reviver to pass down to JSON.stringify
|
||||
*/
|
||||
constructor(private reviver?: (this: any, key: string, value: any) => any) {
|
||||
super()
|
||||
}
|
||||
|
||||
@@ -129,6 +146,9 @@ export class Decoder extends EventEmitter {
|
||||
public add(obj: any) {
|
||||
let packet
|
||||
if (typeof obj === "string") {
|
||||
if (this.reconstructor) {
|
||||
throw new Error("got plaintext data when reconstructing a packet")
|
||||
}
|
||||
packet = this.decodeString(obj)
|
||||
if (
|
||||
packet.type === PacketType.BINARY_EVENT ||
|
||||
@@ -139,11 +159,11 @@ export class Decoder extends EventEmitter {
|
||||
|
||||
// no attachments, labeled binary but no binary data to follow
|
||||
if (packet.attachments === 0) {
|
||||
super.emit("decoded", packet)
|
||||
super.emitReserved("decoded", packet)
|
||||
}
|
||||
} else {
|
||||
// non-binary full packet
|
||||
super.emit("decoded", packet)
|
||||
super.emitReserved("decoded", packet)
|
||||
}
|
||||
} else if (isBinary(obj) || obj.base64) {
|
||||
// raw binary data
|
||||
@@ -154,7 +174,7 @@ export class Decoder extends EventEmitter {
|
||||
if (packet) {
|
||||
// received final buffer
|
||||
this.reconstructor = null
|
||||
super.emit("decoded", packet)
|
||||
super.emitReserved("decoded", packet)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -223,7 +243,7 @@ export class Decoder extends EventEmitter {
|
||||
|
||||
// look up json data
|
||||
if (str.charAt(++i)) {
|
||||
const payload = tryParse(str.substr(i))
|
||||
const payload = this.tryParse(str.substr(i))
|
||||
if (Decoder.isPayloadValid(p.type, payload)) {
|
||||
p.data = payload
|
||||
} else {
|
||||
@@ -231,10 +251,18 @@ export class Decoder extends EventEmitter {
|
||||
}
|
||||
}
|
||||
|
||||
console.trace("decoded", str, "as", p)
|
||||
debug("decoded %s as %j", str, p)
|
||||
return p
|
||||
}
|
||||
|
||||
private tryParse(str) {
|
||||
try {
|
||||
return JSON.parse(str, this.reviver)
|
||||
} catch (e) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
private static isPayloadValid(type: PacketType, payload: any): boolean {
|
||||
switch (type) {
|
||||
case PacketType.CONNECT:
|
||||
@@ -262,14 +290,6 @@ export class Decoder extends EventEmitter {
|
||||
}
|
||||
}
|
||||
|
||||
function tryParse(str) {
|
||||
try {
|
||||
return JSON.parse(str)
|
||||
} catch (error: any) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A manager of a binary event's 'buffer sequence'. Should
|
||||
* be constructed whenever a packet of type BINARY_EVENT is
|
||||
|
||||
@@ -7,14 +7,14 @@ const isView = (obj: any) => {
|
||||
}
|
||||
|
||||
const toString = Object.prototype.toString
|
||||
const withNativeBlob = false
|
||||
// typeof Blob === "function" ||
|
||||
// (typeof Blob !== "undefined" &&
|
||||
// toString.call(Blob) === "[object BlobConstructor]")
|
||||
const withNativeFile = false
|
||||
// typeof File === "function" ||
|
||||
// (typeof File !== "undefined" &&
|
||||
// toString.call(File) === "[object FileConstructor]")
|
||||
const withNativeBlob =
|
||||
typeof Blob === "function" ||
|
||||
(typeof Blob !== "undefined" &&
|
||||
toString.call(Blob) === "[object BlobConstructor]")
|
||||
const withNativeFile =
|
||||
typeof File === "function" ||
|
||||
(typeof File !== "undefined" &&
|
||||
toString.call(File) === "[object FileConstructor]")
|
||||
|
||||
/**
|
||||
* Returns true if obj is a Buffer, an ArrayBuffer, a Blob or a File.
|
||||
@@ -24,8 +24,9 @@ const withNativeFile = false
|
||||
|
||||
export function isBinary(obj: any) {
|
||||
return (
|
||||
(withNativeArrayBuffer && (obj instanceof ArrayBuffer || isView(obj)))
|
||||
// || (withNativeBlob && obj instanceof Blob) || (withNativeFile && obj instanceof File)
|
||||
(withNativeArrayBuffer && (obj instanceof ArrayBuffer || isView(obj))) ||
|
||||
(withNativeBlob && obj instanceof Blob) ||
|
||||
(withNativeFile && obj instanceof File)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user