mirror of
https://github.com/react/react-native-devtools-frontend.git
synced 2026-10-07 04:26:32 +08:00
The update contains a bug fix that improves the quality for DevTools release source maps. The update also seems to stop minifiying certain names in the overlay bundle so we had to slightly bump the limit. * Old size: 69660 * New size: 71295 DISABLE_THIRD_PARTY_CHECK=Bump overlay size limit R=alexrudenko@chromium.org Bug: 1459146 Change-Id: I3036787bbb3ba8d28669b9aaab9c29c5f5581e55 Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/4693881 Commit-Queue: Simon Zünd <szuend@chromium.org> Reviewed-by: Alex Rudenko <alexrudenko@chromium.org>
294 lines
9.1 KiB
JavaScript
294 lines
9.1 KiB
JavaScript
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 = debugModule("socket.io-parser"); // debug()
|
|
/**
|
|
* Protocol version.
|
|
*
|
|
* @public
|
|
*/
|
|
export const protocol = 5;
|
|
export var PacketType;
|
|
(function (PacketType) {
|
|
PacketType[PacketType["CONNECT"] = 0] = "CONNECT";
|
|
PacketType[PacketType["DISCONNECT"] = 1] = "DISCONNECT";
|
|
PacketType[PacketType["EVENT"] = 2] = "EVENT";
|
|
PacketType[PacketType["ACK"] = 3] = "ACK";
|
|
PacketType[PacketType["CONNECT_ERROR"] = 4] = "CONNECT_ERROR";
|
|
PacketType[PacketType["BINARY_EVENT"] = 5] = "BINARY_EVENT";
|
|
PacketType[PacketType["BINARY_ACK"] = 6] = "BINARY_ACK";
|
|
})(PacketType || (PacketType = {}));
|
|
/**
|
|
* A socket.io Encoder instance
|
|
*/
|
|
export class Encoder {
|
|
/**
|
|
* Encoder constructor
|
|
*
|
|
* @param {function} replacer - custom replacer to pass down to JSON.parse
|
|
*/
|
|
constructor(replacer) {
|
|
this.replacer = replacer;
|
|
}
|
|
/**
|
|
* Encode a packet as a single string if non-binary, or as a
|
|
* buffer sequence, depending on packet type.
|
|
*
|
|
* @param {Object} obj - packet object
|
|
*/
|
|
encode(obj) {
|
|
debug("encoding packet %j", obj);
|
|
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)];
|
|
}
|
|
/**
|
|
* Encode packet as string.
|
|
*/
|
|
encodeAsString(obj) {
|
|
// first is type
|
|
let str = "" + obj.type;
|
|
// attachments if we have them
|
|
if (obj.type === PacketType.BINARY_EVENT ||
|
|
obj.type === PacketType.BINARY_ACK) {
|
|
str += obj.attachments + "-";
|
|
}
|
|
// if we have a namespace other than `/`
|
|
// we append it followed by a comma `,`
|
|
if (obj.nsp && "/" !== obj.nsp) {
|
|
str += obj.nsp + ",";
|
|
}
|
|
// immediately followed by the id
|
|
if (null != obj.id) {
|
|
str += obj.id;
|
|
}
|
|
// json data
|
|
if (null != obj.data) {
|
|
str += JSON.stringify(obj.data, this.replacer);
|
|
}
|
|
debug("encoded %j as %s", obj, str);
|
|
return str;
|
|
}
|
|
/**
|
|
* Encode packet as 'buffer sequence' by removing blobs, and
|
|
* deconstructing packet into object with placeholders and
|
|
* a list of buffers.
|
|
*/
|
|
encodeAsBinary(obj) {
|
|
const deconstruction = deconstructPacket(obj);
|
|
const pack = this.encodeAsString(deconstruction.packet);
|
|
const buffers = deconstruction.buffers;
|
|
buffers.unshift(pack); // add packet info to beginning of data list
|
|
return buffers; // write all the buffers
|
|
}
|
|
}
|
|
/**
|
|
* A socket.io Decoder instance
|
|
*
|
|
* @return {Object} decoder
|
|
*/
|
|
export class Decoder extends Emitter {
|
|
/**
|
|
* Decoder constructor
|
|
*
|
|
* @param {function} reviver - custom reviver to pass down to JSON.stringify
|
|
*/
|
|
constructor(reviver) {
|
|
super();
|
|
this.reviver = reviver;
|
|
}
|
|
/**
|
|
* Decodes an encoded packet string into packet JSON.
|
|
*
|
|
* @param {String} obj - encoded packet
|
|
*/
|
|
add(obj) {
|
|
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 ||
|
|
packet.type === PacketType.BINARY_ACK) {
|
|
// binary packet's json
|
|
this.reconstructor = new BinaryReconstructor(packet);
|
|
// no attachments, labeled binary but no binary data to follow
|
|
if (packet.attachments === 0) {
|
|
super.emitReserved("decoded", packet);
|
|
}
|
|
}
|
|
else {
|
|
// non-binary full packet
|
|
super.emitReserved("decoded", packet);
|
|
}
|
|
}
|
|
else if (isBinary(obj) || obj.base64) {
|
|
// raw binary data
|
|
if (!this.reconstructor) {
|
|
throw new Error("got binary data when not reconstructing a packet");
|
|
}
|
|
else {
|
|
packet = this.reconstructor.takeBinaryData(obj);
|
|
if (packet) {
|
|
// received final buffer
|
|
this.reconstructor = null;
|
|
super.emitReserved("decoded", packet);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
throw new Error("Unknown type: " + obj);
|
|
}
|
|
}
|
|
/**
|
|
* Decode a packet String (JSON data)
|
|
*
|
|
* @param {String} str
|
|
* @return {Object} packet
|
|
*/
|
|
decodeString(str) {
|
|
let i = 0;
|
|
// look up type
|
|
const p = {
|
|
type: Number(str.charAt(0)),
|
|
};
|
|
if (PacketType[p.type] === undefined) {
|
|
throw new Error("unknown packet type " + p.type);
|
|
}
|
|
// look up attachments if type binary
|
|
if (p.type === PacketType.BINARY_EVENT ||
|
|
p.type === PacketType.BINARY_ACK) {
|
|
const start = i + 1;
|
|
while (str.charAt(++i) !== "-" && i != str.length) { }
|
|
const buf = str.substring(start, i);
|
|
if (buf != Number(buf) || str.charAt(i) !== "-") {
|
|
throw new Error("Illegal attachments");
|
|
}
|
|
p.attachments = Number(buf);
|
|
}
|
|
// look up namespace (if any)
|
|
if ("/" === str.charAt(i + 1)) {
|
|
const start = i + 1;
|
|
while (++i) {
|
|
const c = str.charAt(i);
|
|
if ("," === c)
|
|
break;
|
|
if (i === str.length)
|
|
break;
|
|
}
|
|
p.nsp = str.substring(start, i);
|
|
}
|
|
else {
|
|
p.nsp = "/";
|
|
}
|
|
// look up id
|
|
const next = str.charAt(i + 1);
|
|
if ("" !== next && Number(next) == next) {
|
|
const start = i + 1;
|
|
while (++i) {
|
|
const c = str.charAt(i);
|
|
if (null == c || Number(c) != c) {
|
|
--i;
|
|
break;
|
|
}
|
|
if (i === str.length)
|
|
break;
|
|
}
|
|
p.id = Number(str.substring(start, i + 1));
|
|
}
|
|
// look up json data
|
|
if (str.charAt(++i)) {
|
|
const payload = this.tryParse(str.substr(i));
|
|
if (Decoder.isPayloadValid(p.type, payload)) {
|
|
p.data = payload;
|
|
}
|
|
else {
|
|
throw new Error("invalid payload");
|
|
}
|
|
}
|
|
debug("decoded %s as %j", str, p);
|
|
return p;
|
|
}
|
|
tryParse(str) {
|
|
try {
|
|
return JSON.parse(str, this.reviver);
|
|
}
|
|
catch (e) {
|
|
return false;
|
|
}
|
|
}
|
|
static isPayloadValid(type, payload) {
|
|
switch (type) {
|
|
case PacketType.CONNECT:
|
|
return typeof payload === "object";
|
|
case PacketType.DISCONNECT:
|
|
return payload === undefined;
|
|
case PacketType.CONNECT_ERROR:
|
|
return typeof payload === "string" || typeof payload === "object";
|
|
case PacketType.EVENT:
|
|
case PacketType.BINARY_EVENT:
|
|
return Array.isArray(payload) && payload.length > 0;
|
|
case PacketType.ACK:
|
|
case PacketType.BINARY_ACK:
|
|
return Array.isArray(payload);
|
|
}
|
|
}
|
|
/**
|
|
* Deallocates a parser's resources
|
|
*/
|
|
destroy() {
|
|
if (this.reconstructor) {
|
|
this.reconstructor.finishedReconstruction();
|
|
}
|
|
}
|
|
}
|
|
/**
|
|
* A manager of a binary event's 'buffer sequence'. Should
|
|
* be constructed whenever a packet of type BINARY_EVENT is
|
|
* decoded.
|
|
*
|
|
* @param {Object} packet
|
|
* @return {BinaryReconstructor} initialized reconstructor
|
|
*/
|
|
class BinaryReconstructor {
|
|
constructor(packet) {
|
|
this.packet = packet;
|
|
this.buffers = [];
|
|
this.reconPack = packet;
|
|
}
|
|
/**
|
|
* Method to be called when binary data received from connection
|
|
* after a BINARY_EVENT packet.
|
|
*
|
|
* @param {Buffer | ArrayBuffer} binData - the raw binary data received
|
|
* @return {null | Object} returns null if more binary data is expected or
|
|
* a reconstructed packet object if all buffers have been received.
|
|
*/
|
|
takeBinaryData(binData) {
|
|
this.buffers.push(binData);
|
|
if (this.buffers.length === this.reconPack.attachments) {
|
|
// done with buffer list
|
|
const packet = reconstructPacket(this.reconPack, this.buffers);
|
|
this.finishedReconstruction();
|
|
return packet;
|
|
}
|
|
return null;
|
|
}
|
|
/**
|
|
* Cleans up binary packet reconstruction variables.
|
|
*/
|
|
finishedReconstruction() {
|
|
this.reconPack = null;
|
|
this.buffers = [];
|
|
}
|
|
}
|