summaryrefslogtreecommitdiff
path: root/chromium/third_party/devtools-frontend/src/node_modules/ws
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2022-05-12 15:59:20 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2022-05-25 06:57:22 +0000
commitf7eaed5286974984ba5f9e3189d8f49d03e99f81 (patch)
treecaed19b2af2024f35449fb0b781d0a25e09d4f8f /chromium/third_party/devtools-frontend/src/node_modules/ws
parent9729c4479fe23554eae6e6dd1f30ff488f470c84 (diff)
downloadqtwebengine-chromium-f7eaed5286974984ba5f9e3189d8f49d03e99f81.tar.gz
BASELINE: Update Chromium to 100.0.4896.167
Change-Id: I98cbeb5d7543d966ffe04d8cefded0c493a11333 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/third_party/devtools-frontend/src/node_modules/ws')
-rw-r--r--chromium/third_party/devtools-frontend/src/node_modules/ws/LICENSE2
-rw-r--r--chromium/third_party/devtools-frontend/src/node_modules/ws/README.md111
-rw-r--r--chromium/third_party/devtools-frontend/src/node_modules/ws/index.js3
-rw-r--r--chromium/third_party/devtools-frontend/src/node_modules/ws/lib/buffer-util.js9
-rw-r--r--chromium/third_party/devtools-frontend/src/node_modules/ws/lib/constants.js4
-rw-r--r--chromium/third_party/devtools-frontend/src/node_modules/ws/lib/event-target.js262
-rw-r--r--chromium/third_party/devtools-frontend/src/node_modules/ws/lib/extension.js36
-rw-r--r--chromium/third_party/devtools-frontend/src/node_modules/ws/lib/permessage-deflate.js25
-rw-r--r--chromium/third_party/devtools-frontend/src/node_modules/ws/lib/receiver.js47
-rw-r--r--chromium/third_party/devtools-frontend/src/node_modules/ws/lib/sender.js95
-rw-r--r--chromium/third_party/devtools-frontend/src/node_modules/ws/lib/stream.js30
-rw-r--r--chromium/third_party/devtools-frontend/src/node_modules/ws/lib/subprotocol.js62
-rw-r--r--chromium/third_party/devtools-frontend/src/node_modules/ws/lib/validation.js36
-rw-r--r--chromium/third_party/devtools-frontend/src/node_modules/ws/lib/websocket-server.js144
-rw-r--r--chromium/third_party/devtools-frontend/src/node_modules/ws/lib/websocket.js365
-rw-r--r--chromium/third_party/devtools-frontend/src/node_modules/ws/package.json17
-rw-r--r--chromium/third_party/devtools-frontend/src/node_modules/ws/wrapper.mjs8
17 files changed, 819 insertions, 437 deletions
diff --git a/chromium/third_party/devtools-frontend/src/node_modules/ws/LICENSE b/chromium/third_party/devtools-frontend/src/node_modules/ws/LICENSE
index a145cd1dff0..65ff176bf67 100644
--- a/chromium/third_party/devtools-frontend/src/node_modules/ws/LICENSE
+++ b/chromium/third_party/devtools-frontend/src/node_modules/ws/LICENSE
@@ -1,5 +1,3 @@
-The MIT License (MIT)
-
Copyright (c) 2011 Einar Otto Stangvik <einaros@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
diff --git a/chromium/third_party/devtools-frontend/src/node_modules/ws/README.md b/chromium/third_party/devtools-frontend/src/node_modules/ws/README.md
index 1cb19d65040..82ca8db4981 100644
--- a/chromium/third_party/devtools-frontend/src/node_modules/ws/README.md
+++ b/chromium/third_party/devtools-frontend/src/node_modules/ws/README.md
@@ -1,8 +1,7 @@
# ws: a Node.js WebSocket library
[![Version npm](https://img.shields.io/npm/v/ws.svg?logo=npm)](https://www.npmjs.com/package/ws)
-[![Build](https://img.shields.io/github/workflow/status/websockets/ws/CI/master?label=build&logo=github)](https://github.com/websockets/ws/actions?query=workflow%3ACI+branch%3Amaster)
-[![Windows x86 Build](https://img.shields.io/appveyor/ci/lpinca/ws/master.svg?logo=appveyor)](https://ci.appveyor.com/project/lpinca/ws)
+[![CI](https://img.shields.io/github/workflow/status/websockets/ws/CI/master?label=CI&logo=github)](https://github.com/websockets/ws/actions?query=workflow%3ACI+branch%3Amaster)
[![Coverage Status](https://img.shields.io/coveralls/websockets/ws/master.svg?logo=coveralls)](https://coveralls.io/github/websockets/ws)
ws is a simple to use, blazing fast, and thoroughly tested WebSocket client and
@@ -98,9 +97,9 @@ into the creation of [raw deflate/inflate streams][node-zlib-deflaterawdocs].
See [the docs][ws-server-options] for more options.
```js
-const WebSocket = require('ws');
+import WebSocket, { WebSocketServer } from 'ws';
-const wss = new WebSocket.Server({
+const wss = new WebSocketServer({
port: 8080,
perMessageDeflate: {
zlibDeflateOptions: {
@@ -119,7 +118,7 @@ const wss = new WebSocket.Server({
// Below options specified as default values.
concurrencyLimit: 10, // Limits zlib concurrency for perf.
threshold: 1024 // Size (in bytes) below which messages
- // should not be compressed.
+ // should not be compressed if context takeover is disabled.
}
});
```
@@ -129,7 +128,7 @@ server. To always disable the extension on the client set the
`perMessageDeflate` option to `false`.
```js
-const WebSocket = require('ws');
+import WebSocket from 'ws';
const ws = new WebSocket('ws://www.host.com/path', {
perMessageDeflate: false
@@ -141,7 +140,7 @@ const ws = new WebSocket('ws://www.host.com/path', {
### Sending and receiving text data
```js
-const WebSocket = require('ws');
+import WebSocket from 'ws';
const ws = new WebSocket('ws://www.host.com/path');
@@ -149,15 +148,15 @@ ws.on('open', function open() {
ws.send('something');
});
-ws.on('message', function incoming(data) {
- console.log(data);
+ws.on('message', function message(data) {
+ console.log('received: %s', data);
});
```
### Sending binary data
```js
-const WebSocket = require('ws');
+import WebSocket from 'ws';
const ws = new WebSocket('ws://www.host.com/path');
@@ -175,13 +174,13 @@ ws.on('open', function open() {
### Simple server
```js
-const WebSocket = require('ws');
+import { WebSocketServer } from 'ws';
-const wss = new WebSocket.Server({ port: 8080 });
+const wss = new WebSocketServer({ port: 8080 });
wss.on('connection', function connection(ws) {
- ws.on('message', function incoming(message) {
- console.log('received: %s', message);
+ ws.on('message', function message(data) {
+ console.log('received: %s', data);
});
ws.send('something');
@@ -191,19 +190,19 @@ wss.on('connection', function connection(ws) {
### External HTTP/S server
```js
-const fs = require('fs');
-const https = require('https');
-const WebSocket = require('ws');
+import { createServer } from 'https';
+import { readFileSync } from 'fs';
+import { WebSocketServer } from 'ws';
-const server = https.createServer({
- cert: fs.readFileSync('/path/to/cert.pem'),
- key: fs.readFileSync('/path/to/key.pem')
+const server = createServer({
+ cert: readFileSync('/path/to/cert.pem'),
+ key: readFileSync('/path/to/key.pem')
});
-const wss = new WebSocket.Server({ server });
+const wss = new WebSocketServer({ server });
wss.on('connection', function connection(ws) {
- ws.on('message', function incoming(message) {
- console.log('received: %s', message);
+ ws.on('message', function message(data) {
+ console.log('received: %s', data);
});
ws.send('something');
@@ -215,13 +214,13 @@ server.listen(8080);
### Multiple servers sharing a single HTTP/S server
```js
-const http = require('http');
-const WebSocket = require('ws');
-const url = require('url');
+import { createServer } from 'http';
+import { parse } from 'url';
+import { WebSocketServer } from 'ws';
-const server = http.createServer();
-const wss1 = new WebSocket.Server({ noServer: true });
-const wss2 = new WebSocket.Server({ noServer: true });
+const server = createServer();
+const wss1 = new WebSocketServer({ noServer: true });
+const wss2 = new WebSocketServer({ noServer: true });
wss1.on('connection', function connection(ws) {
// ...
@@ -232,7 +231,7 @@ wss2.on('connection', function connection(ws) {
});
server.on('upgrade', function upgrade(request, socket, head) {
- const pathname = url.parse(request.url).pathname;
+ const { pathname } = parse(request.url);
if (pathname === '/foo') {
wss1.handleUpgrade(request, socket, head, function done(ws) {
@@ -253,21 +252,21 @@ server.listen(8080);
### Client authentication
```js
-const http = require('http');
-const WebSocket = require('ws');
+import WebSocket from 'ws';
+import { createServer } from 'http';
-const server = http.createServer();
-const wss = new WebSocket.Server({ noServer: true });
+const server = createServer();
+const wss = new WebSocketServer({ noServer: true });
wss.on('connection', function connection(ws, request, client) {
- ws.on('message', function message(msg) {
- console.log(`Received message ${msg} from user ${client}`);
+ ws.on('message', function message(data) {
+ console.log(`Received message ${data} from user ${client}`);
});
});
server.on('upgrade', function upgrade(request, socket, head) {
// This function is not defined on purpose. Implement it with your own logic.
- authenticate(request, (err, client) => {
+ authenticate(request, function next(err, client) {
if (err || !client) {
socket.write('HTTP/1.1 401 Unauthorized\r\n\r\n');
socket.destroy();
@@ -291,15 +290,15 @@ A client WebSocket broadcasting to all connected WebSocket clients, including
itself.
```js
-const WebSocket = require('ws');
+import WebSocket, { WebSocketServer } from 'ws';
-const wss = new WebSocket.Server({ port: 8080 });
+const wss = new WebSocketServer({ port: 8080 });
wss.on('connection', function connection(ws) {
- ws.on('message', function incoming(data) {
+ ws.on('message', function message(data, isBinary) {
wss.clients.forEach(function each(client) {
if (client.readyState === WebSocket.OPEN) {
- client.send(data);
+ client.send(data, { binary: isBinary });
}
});
});
@@ -310,15 +309,15 @@ A client WebSocket broadcasting to every other connected WebSocket clients,
excluding itself.
```js
-const WebSocket = require('ws');
+import WebSocket, { WebSocketServer } from 'ws';
-const wss = new WebSocket.Server({ port: 8080 });
+const wss = new WebSocketServer({ port: 8080 });
wss.on('connection', function connection(ws) {
- ws.on('message', function incoming(data) {
+ ws.on('message', function message(data, isBinary) {
wss.clients.forEach(function each(client) {
if (client !== ws && client.readyState === WebSocket.OPEN) {
- client.send(data);
+ client.send(data, { binary: isBinary });
}
});
});
@@ -328,7 +327,7 @@ wss.on('connection', function connection(ws) {
### echo.websocket.org demo
```js
-const WebSocket = require('ws');
+import WebSocket from 'ws';
const ws = new WebSocket('wss://echo.websocket.org/', {
origin: 'https://websocket.org'
@@ -343,7 +342,7 @@ ws.on('close', function close() {
console.log('disconnected');
});
-ws.on('message', function incoming(data) {
+ws.on('message', function message(data) {
console.log(`Roundtrip time: ${Date.now() - data} ms`);
setTimeout(function timeout() {
@@ -355,13 +354,13 @@ ws.on('message', function incoming(data) {
### Use the Node.js streams API
```js
-const WebSocket = require('ws');
+import WebSocket, { createWebSocketStream } from 'ws';
const ws = new WebSocket('wss://echo.websocket.org/', {
origin: 'https://websocket.org'
});
-const duplex = WebSocket.createWebSocketStream(ws, { encoding: 'utf8' });
+const duplex = createWebSocketStream(ws, { encoding: 'utf8' });
duplex.pipe(process.stdout);
process.stdin.pipe(duplex);
@@ -381,9 +380,9 @@ Otherwise, see the test cases.
The remote IP address can be obtained from the raw socket.
```js
-const WebSocket = require('ws');
+import { WebSocketServer } from 'ws';
-const wss = new WebSocket.Server({ port: 8080 });
+const wss = new WebSocketServer({ port: 8080 });
wss.on('connection', function connection(ws, req) {
const ip = req.socket.remoteAddress;
@@ -409,15 +408,13 @@ In these cases ping messages can be used as a means to verify that the remote
endpoint is still responsive.
```js
-const WebSocket = require('ws');
-
-function noop() {}
+import { WebSocketServer } from 'ws';
function heartbeat() {
this.isAlive = true;
}
-const wss = new WebSocket.Server({ port: 8080 });
+const wss = new WebSocketServer({ port: 8080 });
wss.on('connection', function connection(ws) {
ws.isAlive = true;
@@ -429,7 +426,7 @@ const interval = setInterval(function ping() {
if (ws.isAlive === false) return ws.terminate();
ws.isAlive = false;
- ws.ping(noop);
+ ws.ping();
});
}, 30000);
@@ -446,7 +443,7 @@ without knowing it. You might want to add a ping listener on your clients to
prevent that. A simple implementation would be:
```js
-const WebSocket = require('ws');
+import WebSocket from 'ws';
function heartbeat() {
clearTimeout(this.pingTimeout);
diff --git a/chromium/third_party/devtools-frontend/src/node_modules/ws/index.js b/chromium/third_party/devtools-frontend/src/node_modules/ws/index.js
index 722c78676ef..41edb3b81bc 100644
--- a/chromium/third_party/devtools-frontend/src/node_modules/ws/index.js
+++ b/chromium/third_party/devtools-frontend/src/node_modules/ws/index.js
@@ -7,4 +7,7 @@ WebSocket.Server = require('./lib/websocket-server');
WebSocket.Receiver = require('./lib/receiver');
WebSocket.Sender = require('./lib/sender');
+WebSocket.WebSocket = WebSocket;
+WebSocket.WebSocketServer = WebSocket.Server;
+
module.exports = WebSocket;
diff --git a/chromium/third_party/devtools-frontend/src/node_modules/ws/lib/buffer-util.js b/chromium/third_party/devtools-frontend/src/node_modules/ws/lib/buffer-util.js
index 6fd84c31174..1ba1d1beb32 100644
--- a/chromium/third_party/devtools-frontend/src/node_modules/ws/lib/buffer-util.js
+++ b/chromium/third_party/devtools-frontend/src/node_modules/ws/lib/buffer-util.js
@@ -52,9 +52,7 @@ function _mask(source, mask, output, offset, length) {
* @public
*/
function _unmask(buffer, mask) {
- // Required until https://github.com/nodejs/node/issues/9006 is resolved.
- const length = buffer.length;
- for (let i = 0; i < length; i++) {
+ for (let i = 0; i < buffer.length; i++) {
buffer[i] ^= mask[i & 3];
}
}
@@ -103,19 +101,18 @@ function toBuffer(data) {
try {
const bufferUtil = require('bufferutil');
- const bu = bufferUtil.BufferUtil || bufferUtil;
module.exports = {
concat,
mask(source, mask, output, offset, length) {
if (length < 48) _mask(source, mask, output, offset, length);
- else bu.mask(source, mask, output, offset, length);
+ else bufferUtil.mask(source, mask, output, offset, length);
},
toArrayBuffer,
toBuffer,
unmask(buffer, mask) {
if (buffer.length < 32) _unmask(buffer, mask);
- else bu.unmask(buffer, mask);
+ else bufferUtil.unmask(buffer, mask);
}
};
} catch (e) /* istanbul ignore next */ {
diff --git a/chromium/third_party/devtools-frontend/src/node_modules/ws/lib/constants.js b/chromium/third_party/devtools-frontend/src/node_modules/ws/lib/constants.js
index 4082981f89d..d691b30a17f 100644
--- a/chromium/third_party/devtools-frontend/src/node_modules/ws/lib/constants.js
+++ b/chromium/third_party/devtools-frontend/src/node_modules/ws/lib/constants.js
@@ -2,9 +2,11 @@
module.exports = {
BINARY_TYPES: ['nodebuffer', 'arraybuffer', 'fragments'],
+ EMPTY_BUFFER: Buffer.alloc(0),
GUID: '258EAFA5-E914-47DA-95CA-C5AB0DC85B11',
+ kForOnEventAttribute: Symbol('kIsForOnEventAttribute'),
+ kListener: Symbol('kListener'),
kStatusCode: Symbol('status-code'),
kWebSocket: Symbol('websocket'),
- EMPTY_BUFFER: Buffer.alloc(0),
NOOP: () => {}
};
diff --git a/chromium/third_party/devtools-frontend/src/node_modules/ws/lib/event-target.js b/chromium/third_party/devtools-frontend/src/node_modules/ws/lib/event-target.js
index a6fbe72b7b1..d5abd83a0f6 100644
--- a/chromium/third_party/devtools-frontend/src/node_modules/ws/lib/event-target.js
+++ b/chromium/third_party/devtools-frontend/src/node_modules/ws/lib/event-target.js
@@ -1,111 +1,172 @@
'use strict';
+const { kForOnEventAttribute, kListener } = require('./constants');
+
+const kCode = Symbol('kCode');
+const kData = Symbol('kData');
+const kError = Symbol('kError');
+const kMessage = Symbol('kMessage');
+const kReason = Symbol('kReason');
+const kTarget = Symbol('kTarget');
+const kType = Symbol('kType');
+const kWasClean = Symbol('kWasClean');
+
/**
* Class representing an event.
- *
- * @private
*/
class Event {
/**
* Create a new `Event`.
*
* @param {String} type The name of the event
- * @param {Object} target A reference to the target to which the event was
- * dispatched
+ * @throws {TypeError} If the `type` argument is not specified
*/
- constructor(type, target) {
- this.target = target;
- this.type = type;
+ constructor(type) {
+ this[kTarget] = null;
+ this[kType] = type;
}
-}
-/**
- * Class representing a message event.
- *
- * @extends Event
- * @private
- */
-class MessageEvent extends Event {
/**
- * Create a new `MessageEvent`.
- *
- * @param {(String|Buffer|ArrayBuffer|Buffer[])} data The received data
- * @param {WebSocket} target A reference to the target to which the event was
- * dispatched
+ * @type {*}
*/
- constructor(data, target) {
- super('message', target);
+ get target() {
+ return this[kTarget];
+ }
- this.data = data;
+ /**
+ * @type {String}
+ */
+ get type() {
+ return this[kType];
}
}
+Object.defineProperty(Event.prototype, 'target', { enumerable: true });
+Object.defineProperty(Event.prototype, 'type', { enumerable: true });
+
/**
* Class representing a close event.
*
* @extends Event
- * @private
*/
class CloseEvent extends Event {
/**
* Create a new `CloseEvent`.
*
- * @param {Number} code The status code explaining why the connection is being
- * closed
- * @param {String} reason A human-readable string explaining why the
- * connection is closing
- * @param {WebSocket} target A reference to the target to which the event was
- * dispatched
+ * @param {String} type The name of the event
+ * @param {Object} [options] A dictionary object that allows for setting
+ * attributes via object members of the same name
+ * @param {Number} [options.code=0] The status code explaining why the
+ * connection was closed
+ * @param {String} [options.reason=''] A human-readable string explaining why
+ * the connection was closed
+ * @param {Boolean} [options.wasClean=false] Indicates whether or not the
+ * connection was cleanly closed
+ */
+ constructor(type, options = {}) {
+ super(type);
+
+ this[kCode] = options.code === undefined ? 0 : options.code;
+ this[kReason] = options.reason === undefined ? '' : options.reason;
+ this[kWasClean] = options.wasClean === undefined ? false : options.wasClean;
+ }
+
+ /**
+ * @type {Number}
*/
- constructor(code, reason, target) {
- super('close', target);
+ get code() {
+ return this[kCode];
+ }
+
+ /**
+ * @type {String}
+ */
+ get reason() {
+ return this[kReason];
+ }
- this.wasClean = target._closeFrameReceived && target._closeFrameSent;
- this.reason = reason;
- this.code = code;
+ /**
+ * @type {Boolean}
+ */
+ get wasClean() {
+ return this[kWasClean];
}
}
+Object.defineProperty(CloseEvent.prototype, 'code', { enumerable: true });
+Object.defineProperty(CloseEvent.prototype, 'reason', { enumerable: true });
+Object.defineProperty(CloseEvent.prototype, 'wasClean', { enumerable: true });
+
/**
- * Class representing an open event.
+ * Class representing an error event.
*
* @extends Event
- * @private
*/
-class OpenEvent extends Event {
+class ErrorEvent extends Event {
/**
- * Create a new `OpenEvent`.
+ * Create a new `ErrorEvent`.
*
- * @param {WebSocket} target A reference to the target to which the event was
- * dispatched
+ * @param {String} type The name of the event
+ * @param {Object} [options] A dictionary object that allows for setting
+ * attributes via object members of the same name
+ * @param {*} [options.error=null] The error that generated this event
+ * @param {String} [options.message=''] The error message
*/
- constructor(target) {
- super('open', target);
+ constructor(type, options = {}) {
+ super(type);
+
+ this[kError] = options.error === undefined ? null : options.error;
+ this[kMessage] = options.message === undefined ? '' : options.message;
+ }
+
+ /**
+ * @type {*}
+ */
+ get error() {
+ return this[kError];
+ }
+
+ /**
+ * @type {String}
+ */
+ get message() {
+ return this[kMessage];
}
}
+Object.defineProperty(ErrorEvent.prototype, 'error', { enumerable: true });
+Object.defineProperty(ErrorEvent.prototype, 'message', { enumerable: true });
+
/**
- * Class representing an error event.
+ * Class representing a message event.
*
* @extends Event
- * @private
*/
-class ErrorEvent extends Event {
+class MessageEvent extends Event {
/**
- * Create a new `ErrorEvent`.
+ * Create a new `MessageEvent`.
*
- * @param {Object} error The error that generated this event
- * @param {WebSocket} target A reference to the target to which the event was
- * dispatched
+ * @param {String} type The name of the event
+ * @param {Object} [options] A dictionary object that allows for setting
+ * attributes via object members of the same name
+ * @param {*} [options.data=null] The message content
*/
- constructor(error, target) {
- super('error', target);
+ constructor(type, options = {}) {
+ super(type);
- this.message = error.message;
- this.error = error;
+ this[kData] = options.data === undefined ? null : options.data;
+ }
+
+ /**
+ * @type {*}
+ */
+ get data() {
+ return this[kData];
}
}
+Object.defineProperty(MessageEvent.prototype, 'data', { enumerable: true });
+
/**
* This provides methods for emulating the `EventTarget` interface. It's not
* meant to be used directly.
@@ -120,46 +181,62 @@ const EventTarget = {
* @param {Function} listener The listener to add
* @param {Object} [options] An options object specifies characteristics about
* the event listener
- * @param {Boolean} [options.once=false] A `Boolean`` indicating that the
+ * @param {Boolean} [options.once=false] A `Boolean` indicating that the
* listener should be invoked at most once after being added. If `true`,
* the listener would be automatically removed when invoked.
* @public
*/
- addEventListener(type, listener, options) {
- if (typeof listener !== 'function') return;
+ addEventListener(type, listener, options = {}) {
+ let wrapper;
- function onMessage(data) {
- listener.call(this, new MessageEvent(data, this));
- }
+ if (type === 'message') {
+ wrapper = function onMessage(data, isBinary) {
+ const event = new MessageEvent('message', {
+ data: isBinary ? data : data.toString()
+ });
- function onClose(code, message) {
- listener.call(this, new CloseEvent(code, message, this));
- }
+ event[kTarget] = this;
+ listener.call(this, event);
+ };
+ } else if (type === 'close') {
+ wrapper = function onClose(code, message) {
+ const event = new CloseEvent('close', {
+ code,
+ reason: message.toString(),
+ wasClean: this._closeFrameReceived && this._closeFrameSent
+ });
- function onError(error) {
- listener.call(this, new ErrorEvent(error, this));
- }
+ event[kTarget] = this;
+ listener.call(this, event);
+ };
+ } else if (type === 'error') {
+ wrapper = function onError(error) {
+ const event = new ErrorEvent('error', {
+ error,
+ message: error.message
+ });
- function onOpen() {
- listener.call(this, new OpenEvent(this));
+ event[kTarget] = this;
+ listener.call(this, event);
+ };
+ } else if (type === 'open') {
+ wrapper = function onOpen() {
+ const event = new Event('open');
+
+ event[kTarget] = this;
+ listener.call(this, event);
+ };
+ } else {
+ return;
}
- const method = options && options.once ? 'once' : 'on';
+ wrapper[kForOnEventAttribute] = !!options[kForOnEventAttribute];
+ wrapper[kListener] = listener;
- if (type === 'message') {
- onMessage._listener = listener;
- this[method](type, onMessage);
- } else if (type === 'close') {
- onClose._listener = listener;
- this[method](type, onClose);
- } else if (type === 'error') {
- onError._listener = listener;
- this[method](type, onError);
- } else if (type === 'open') {
- onOpen._listener = listener;
- this[method](type, onOpen);
+ if (options.once) {
+ this.once(type, wrapper);
} else {
- this[method](type, listener);
+ this.on(type, wrapper);
}
},
@@ -167,18 +244,23 @@ const EventTarget = {
* Remove an event listener.
*
* @param {String} type A string representing the event type to remove
- * @param {Function} listener The listener to remove
+ * @param {Function} handler The listener to remove
* @public
*/
- removeEventListener(type, listener) {
- const listeners = this.listeners(type);
-
- for (let i = 0; i < listeners.length; i++) {
- if (listeners[i] === listener || listeners[i]._listener === listener) {
- this.removeListener(type, listeners[i]);
+ removeEventListener(type, handler) {
+ for (const listener of this.listeners(type)) {
+ if (listener[kListener] === handler && !listener[kForOnEventAttribute]) {
+ this.removeListener(type, listener);
+ break;
}
}
}
};
-module.exports = EventTarget;
+module.exports = {
+ CloseEvent,
+ ErrorEvent,
+ Event,
+ EventTarget,
+ MessageEvent
+};
diff --git a/chromium/third_party/devtools-frontend/src/node_modules/ws/lib/extension.js b/chromium/third_party/devtools-frontend/src/node_modules/ws/lib/extension.js
index 87a421329d4..3d7895c1b06 100644
--- a/chromium/third_party/devtools-frontend/src/node_modules/ws/lib/extension.js
+++ b/chromium/third_party/devtools-frontend/src/node_modules/ws/lib/extension.js
@@ -1,27 +1,6 @@
'use strict';
-//
-// Allowed token characters:
-//
-// '!', '#', '$', '%', '&', ''', '*', '+', '-',
-// '.', 0-9, A-Z, '^', '_', '`', a-z, '|', '~'
-//
-// tokenChars[32] === 0 // ' '
-// tokenChars[33] === 1 // '!'
-// tokenChars[34] === 0 // '"'
-// ...
-//
-// prettier-ignore
-const tokenChars = [
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0 - 15
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16 - 31
- 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, // 32 - 47
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, // 48 - 63
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64 - 79
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, // 80 - 95
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96 - 111
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0 // 112 - 127
-];
+const { tokenChars } = require('./validation');
/**
* Adds an offer to the map of extension offers or a parameter to the map of
@@ -47,9 +26,6 @@ function push(dest, name, elem) {
*/
function parse(header) {
const offers = Object.create(null);
-
- if (header === undefined || header === '') return offers;
-
let params = Object.create(null);
let mustUnescape = false;
let isEscaping = false;
@@ -57,16 +33,20 @@ function parse(header) {
let extensionName;
let paramName;
let start = -1;
+ let code = -1;
let end = -1;
let i = 0;
for (; i < header.length; i++) {
- const code = header.charCodeAt(i);
+ code = header.charCodeAt(i);
if (extensionName === undefined) {
if (end === -1 && tokenChars[code] === 1) {
if (start === -1) start = i;
- } else if (code === 0x20 /* ' ' */ || code === 0x09 /* '\t' */) {
+ } else if (
+ i !== 0 &&
+ (code === 0x20 /* ' ' */ || code === 0x09) /* '\t' */
+ ) {
if (end === -1 && start !== -1) end = i;
} else if (code === 0x3b /* ';' */ || code === 0x2c /* ',' */) {
if (start === -1) {
@@ -167,7 +147,7 @@ function parse(header) {
}
}
- if (start === -1 || inQuotes) {
+ if (start === -1 || inQuotes || code === 0x20 || code === 0x09) {
throw new SyntaxError('Unexpected end of input');
}
diff --git a/chromium/third_party/devtools-frontend/src/node_modules/ws/lib/permessage-deflate.js b/chromium/third_party/devtools-frontend/src/node_modules/ws/lib/permessage-deflate.js
index ce91784295c..50406971922 100644
--- a/chromium/third_party/devtools-frontend/src/node_modules/ws/lib/permessage-deflate.js
+++ b/chromium/third_party/devtools-frontend/src/node_modules/ws/lib/permessage-deflate.js
@@ -4,7 +4,7 @@ const zlib = require('zlib');
const bufferUtil = require('./buffer-util');
const Limiter = require('./limiter');
-const { kStatusCode, NOOP } = require('./constants');
+const { kStatusCode } = require('./constants');
const TRAILER = Buffer.from([0x00, 0x00, 0xff, 0xff]);
const kPerMessageDeflate = Symbol('permessage-deflate');
@@ -30,22 +30,22 @@ class PerMessageDeflate {
* Creates a PerMessageDeflate instance.
*
* @param {Object} [options] Configuration options
- * @param {Boolean} [options.serverNoContextTakeover=false] Request/accept
- * disabling of server context takeover
+ * @param {(Boolean|Number)} [options.clientMaxWindowBits] Advertise support
+ * for, or request, a custom client window size
* @param {Boolean} [options.clientNoContextTakeover=false] Advertise/
* acknowledge disabling of client context takeover
+ * @param {Number} [options.concurrencyLimit=10] The number of concurrent
+ * calls to zlib
* @param {(Boolean|Number)} [options.serverMaxWindowBits] Request/confirm the
* use of a custom server window size
- * @param {(Boolean|Number)} [options.clientMaxWindowBits] Advertise support
- * for, or request, a custom client window size
+ * @param {Boolean} [options.serverNoContextTakeover=false] Request/accept
+ * disabling of server context takeover
+ * @param {Number} [options.threshold=1024] Size (in bytes) below which
+ * messages should not be compressed if context takeover is disabled
* @param {Object} [options.zlibDeflateOptions] Options to pass to zlib on
* deflate
* @param {Object} [options.zlibInflateOptions] Options to pass to zlib on
* inflate
- * @param {Number} [options.threshold=1024] Size (in bytes) below which
- * messages should not be compressed
- * @param {Number} [options.concurrencyLimit=10] The number of concurrent
- * calls to zlib
* @param {Boolean} [isServer=false] Create the instance in either server or
* client mode
* @param {Number} [maxPayload=0] The maximum allowed message length
@@ -418,13 +418,6 @@ class PerMessageDeflate {
this._deflate[kTotalLength] = 0;
this._deflate[kBuffers] = [];
- //
- // An `'error'` event is emitted, only on Node.js < 10.0.0, if the
- // `zlib.DeflateRaw` instance is closed while data is being processed.
- // This can happen if `PerMessageDeflate#cleanup()` is called at the wrong
- // time due to an abnormal WebSocket closure.
- //
- this._deflate.on('error', NOOP);
this._deflate.on('data', deflateOnData);
}
diff --git a/chromium/third_party/devtools-frontend/src/node_modules/ws/lib/receiver.js b/chromium/third_party/devtools-frontend/src/node_modules/ws/lib/receiver.js
index 1d2af76e1f2..2d29d62bb08 100644
--- a/chromium/third_party/devtools-frontend/src/node_modules/ws/lib/receiver.js
+++ b/chromium/third_party/devtools-frontend/src/node_modules/ws/lib/receiver.js
@@ -28,20 +28,25 @@ class Receiver extends Writable {
/**
* Creates a Receiver instance.
*
- * @param {String} [binaryType=nodebuffer] The type for binary data
- * @param {Object} [extensions] An object containing the negotiated extensions
- * @param {Boolean} [isServer=false] Specifies whether to operate in client or
- * server mode
- * @param {Number} [maxPayload=0] The maximum allowed message length
+ * @param {Object} [options] Options object
+ * @param {String} [options.binaryType=nodebuffer] The type for binary data
+ * @param {Object} [options.extensions] An object containing the negotiated
+ * extensions
+ * @param {Boolean} [options.isServer=false] Specifies whether to operate in
+ * client or server mode
+ * @param {Number} [options.maxPayload=0] The maximum allowed message length
+ * @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or
+ * not to skip UTF-8 validation for text and close messages
*/
- constructor(binaryType, extensions, isServer, maxPayload) {
+ constructor(options = {}) {
super();
- this._binaryType = binaryType || BINARY_TYPES[0];
+ this._binaryType = options.binaryType || BINARY_TYPES[0];
+ this._extensions = options.extensions || {};
+ this._isServer = !!options.isServer;
+ this._maxPayload = options.maxPayload | 0;
+ this._skipUTF8Validation = !!options.skipUTF8Validation;
this[kWebSocket] = undefined;
- this._extensions = extensions || {};
- this._isServer = !!isServer;
- this._maxPayload = maxPayload | 0;
this._bufferedBytes = 0;
this._buffers = [];
@@ -412,7 +417,13 @@ class Receiver extends Writable {
}
data = this.consume(this._payloadLength);
- if (this._masked) unmask(data, this._mask);
+
+ if (
+ this._masked &&
+ (this._mask[0] | this._mask[1] | this._mask[2] | this._mask[3]) !== 0
+ ) {
+ unmask(data, this._mask);
+ }
}
if (this._opcode > 0x07) return this.controlMessage(data);
@@ -425,7 +436,7 @@ class Receiver extends Writable {
if (data.length) {
//
- // This message is not compressed so its lenght is the sum of the payload
+ // This message is not compressed so its length is the sum of the payload
// length of all fragments.
//
this._messageLength = this._totalPayloadLength;
@@ -499,11 +510,11 @@ class Receiver extends Writable {
data = fragments;
}
- this.emit('message', data);
+ this.emit('message', data, true);
} else {
const buf = concat(fragments, messageLength);
- if (!isValidUTF8(buf)) {
+ if (!this._skipUTF8Validation && !isValidUTF8(buf)) {
this._loop = false;
return error(
Error,
@@ -514,7 +525,7 @@ class Receiver extends Writable {
);
}
- this.emit('message', buf.toString());
+ this.emit('message', buf, false);
}
}
@@ -533,7 +544,7 @@ class Receiver extends Writable {
this._loop = false;
if (data.length === 0) {
- this.emit('conclude', 1005, '');
+ this.emit('conclude', 1005, EMPTY_BUFFER);
this.end();
} else if (data.length === 1) {
return error(
@@ -558,7 +569,7 @@ class Receiver extends Writable {
const buf = data.slice(2);
- if (!isValidUTF8(buf)) {
+ if (!this._skipUTF8Validation && !isValidUTF8(buf)) {
return error(
Error,
'invalid UTF-8 sequence',
@@ -568,7 +579,7 @@ class Receiver extends Writable {
);
}
- this.emit('conclude', code, buf.toString());
+ this.emit('conclude', code, buf);
this.end();
}
} else if (this._opcode === 0x09) {
diff --git a/chromium/third_party/devtools-frontend/src/node_modules/ws/lib/sender.js b/chromium/third_party/devtools-frontend/src/node_modules/ws/lib/sender.js
index 441171c5795..2417656d706 100644
--- a/chromium/third_party/devtools-frontend/src/node_modules/ws/lib/sender.js
+++ b/chromium/third_party/devtools-frontend/src/node_modules/ws/lib/sender.js
@@ -11,7 +11,7 @@ const { EMPTY_BUFFER } = require('./constants');
const { isValidStatusCode } = require('./validation');
const { mask: applyMask, toBuffer } = require('./buffer-util');
-const mask = Buffer.alloc(4);
+const maskBuffer = Buffer.alloc(4);
/**
* HyBi Sender implementation.
@@ -22,9 +22,17 @@ class Sender {
*
* @param {(net.Socket|tls.Socket)} socket The connection socket
* @param {Object} [extensions] An object containing the negotiated extensions
+ * @param {Function} [generateMask] The function used to generate the masking
+ * key
*/
- constructor(socket, extensions) {
+ constructor(socket, extensions, generateMask) {
this._extensions = extensions || {};
+
+ if (generateMask) {
+ this._generateMask = generateMask;
+ this._maskBuffer = Buffer.alloc(4);
+ }
+
this._socket = socket;
this._firstFragment = true;
@@ -40,21 +48,43 @@ class Sender {
*
* @param {Buffer} data The data to frame
* @param {Object} options Options object
- * @param {Number} options.opcode The opcode
- * @param {Boolean} [options.readOnly=false] Specifies whether `data` can be
- * modified
* @param {Boolean} [options.fin=false] Specifies whether or not to set the
* FIN bit
+ * @param {Function} [options.generateMask] The function used to generate the
+ * masking key
* @param {Boolean} [options.mask=false] Specifies whether or not to mask
* `data`
+ * @param {Buffer} [options.maskBuffer] The buffer used to store the masking
+ * key
+ * @param {Number} options.opcode The opcode
+ * @param {Boolean} [options.readOnly=false] Specifies whether `data` can be
+ * modified
* @param {Boolean} [options.rsv1=false] Specifies whether or not to set the
* RSV1 bit
* @return {Buffer[]} The framed data as a list of `Buffer` instances
* @public
*/
static frame(data, options) {
- const merge = options.mask && options.readOnly;
- let offset = options.mask ? 6 : 2;
+ let mask;
+ let merge = false;
+ let offset = 2;
+ let skipMasking = false;
+
+ if (options.mask) {
+ mask = options.maskBuffer || maskBuffer;
+
+ if (options.generateMask) {
+ options.generateMask(mask);
+ } else {
+ randomFillSync(mask, 0, 4);
+ }
+
+ skipMasking = (mask[0] | mask[1] | mask[2] | mask[3]) === 0;
+ if (options.readOnly && !skipMasking) merge = true;
+
+ offset = 6;
+ }
+
let payloadLength = data.length;
if (data.length >= 65536) {
@@ -75,20 +105,20 @@ class Sender {
if (payloadLength === 126) {
target.writeUInt16BE(data.length, 2);
} else if (payloadLength === 127) {
- target.writeUInt32BE(0, 2);
- target.writeUInt32BE(data.length, 6);
+ target[2] = target[3] = 0;
+ target.writeUIntBE(data.length, 4, 6);
}
if (!options.mask) return [target, data];
- randomFillSync(mask, 0, 4);
-
target[1] |= 0x80;
target[offset - 4] = mask[0];
target[offset - 3] = mask[1];
target[offset - 2] = mask[2];
target[offset - 1] = mask[3];
+ if (skipMasking) return [target, data];
+
if (merge) {
applyMask(data, mask, target, offset, data.length);
return [target];
@@ -102,7 +132,7 @@ class Sender {
* Sends a close message to the other peer.
*
* @param {Number} [code] The status code component of the body
- * @param {String} [data] The message component of the body
+ * @param {(String|Buffer)} [data] The message component of the body
* @param {Boolean} [mask=false] Specifies whether or not to mask the message
* @param {Function} [cb] Callback
* @public
@@ -114,7 +144,7 @@ class Sender {
buf = EMPTY_BUFFER;
} else if (typeof code !== 'number' || !isValidStatusCode(code)) {
throw new TypeError('First argument must be a valid error code number');
- } else if (data === undefined || data === '') {
+ } else if (data === undefined || !data.length) {
buf = Buffer.allocUnsafe(2);
buf.writeUInt16BE(code, 0);
} else {
@@ -126,7 +156,12 @@ class Sender {
buf = Buffer.allocUnsafe(2 + length);
buf.writeUInt16BE(code, 0);
- buf.write(data, 2);
+
+ if (typeof data === 'string') {
+ buf.write(data, 2);
+ } else {
+ buf.set(data, 2);
+ }
}
if (this._deflating) {
@@ -151,6 +186,8 @@ class Sender {
rsv1: false,
opcode: 0x08,
mask,
+ maskBuffer: this._maskBuffer,
+ generateMask: this._generateMask,
readOnly: false
}),
cb
@@ -195,6 +232,8 @@ class Sender {
rsv1: false,
opcode: 0x09,
mask,
+ maskBuffer: this._maskBuffer,
+ generateMask: this._generateMask,
readOnly
}),
cb
@@ -239,6 +278,8 @@ class Sender {
rsv1: false,
opcode: 0x0a,
mask,
+ maskBuffer: this._maskBuffer,
+ generateMask: this._generateMask,
readOnly
}),
cb
@@ -250,10 +291,10 @@ class Sender {
*
* @param {*} data The message to send
* @param {Object} options Options object
- * @param {Boolean} [options.compress=false] Specifies whether or not to
- * compress `data`
* @param {Boolean} [options.binary=false] Specifies whether `data` is binary
* or text
+ * @param {Boolean} [options.compress=false] Specifies whether or not to
+ * compress `data`
* @param {Boolean} [options.fin=false] Specifies whether the fragment is the
* last one
* @param {Boolean} [options.mask=false] Specifies whether or not to mask
@@ -269,7 +310,15 @@ class Sender {
if (this._firstFragment) {
this._firstFragment = false;
- if (rsv1 && perMessageDeflate) {
+ if (
+ rsv1 &&
+ perMessageDeflate &&
+ perMessageDeflate.params[
+ perMessageDeflate._isServer
+ ? 'server_no_context_takeover'
+ : 'client_no_context_takeover'
+ ]
+ ) {
rsv1 = buf.length >= perMessageDeflate._threshold;
}
this._compress = rsv1;
@@ -286,6 +335,8 @@ class Sender {
rsv1,
opcode,
mask: options.mask,
+ maskBuffer: this._maskBuffer,
+ generateMask: this._generateMask,
readOnly: toBuffer.readOnly
};
@@ -301,6 +352,8 @@ class Sender {
rsv1: false,
opcode,
mask: options.mask,
+ maskBuffer: this._maskBuffer,
+ generateMask: this._generateMask,
readOnly: toBuffer.readOnly
}),
cb
@@ -316,12 +369,16 @@ class Sender {
* `data`
* @param {Object} options Options object
* @param {Number} options.opcode The opcode
- * @param {Boolean} [options.readOnly=false] Specifies whether `data` can be
- * modified
* @param {Boolean} [options.fin=false] Specifies whether or not to set the
* FIN bit
+ * @param {Function} [options.generateMask] The function used to generate the
+ * masking key
* @param {Boolean} [options.mask=false] Specifies whether or not to mask
* `data`
+ * @param {Buffer} [options.maskBuffer] The buffer used to store the masking
+ * key
+ * @param {Boolean} [options.readOnly=false] Specifies whether `data` can be
+ * modified
* @param {Boolean} [options.rsv1=false] Specifies whether or not to set the
* RSV1 bit
* @param {Function} [cb] Callback
diff --git a/chromium/third_party/devtools-frontend/src/node_modules/ws/lib/stream.js b/chromium/third_party/devtools-frontend/src/node_modules/ws/lib/stream.js
index b0896ff8394..230734b79a8 100644
--- a/chromium/third_party/devtools-frontend/src/node_modules/ws/lib/stream.js
+++ b/chromium/third_party/devtools-frontend/src/node_modules/ws/lib/stream.js
@@ -47,23 +47,8 @@ function duplexOnError(err) {
* @public
*/
function createWebSocketStream(ws, options) {
- let resumeOnReceiverDrain = true;
let terminateOnDestroy = true;
- function receiverOnDrain() {
- if (resumeOnReceiverDrain) ws._socket.resume();
- }
-
- if (ws.readyState === ws.CONNECTING) {
- ws.once('open', function open() {
- ws._receiver.removeAllListeners('drain');
- ws._receiver.on('drain', receiverOnDrain);
- });
- } else {
- ws._receiver.removeAllListeners('drain');
- ws._receiver.on('drain', receiverOnDrain);
- }
-
const duplex = new Duplex({
...options,
autoDestroy: false,
@@ -72,11 +57,11 @@ function createWebSocketStream(ws, options) {
writableObjectMode: false
});
- ws.on('message', function message(msg) {
- if (!duplex.push(msg)) {
- resumeOnReceiverDrain = false;
- ws._socket.pause();
- }
+ ws.on('message', function message(msg, isBinary) {
+ const data =
+ !isBinary && duplex._readableState.objectMode ? msg.toString() : msg;
+
+ if (!duplex.push(data)) ws.pause();
});
ws.once('error', function error(err) {
@@ -152,10 +137,7 @@ function createWebSocketStream(ws, options) {
};
duplex._read = function () {
- if (ws.readyState === ws.OPEN && !resumeOnReceiverDrain) {
- resumeOnReceiverDrain = true;
- if (!ws._receiver._writableState.needDrain) ws._socket.resume();
- }
+ if (ws.isPaused) ws.resume();
};
duplex._write = function (chunk, encoding, callback) {
diff --git a/chromium/third_party/devtools-frontend/src/node_modules/ws/lib/subprotocol.js b/chromium/third_party/devtools-frontend/src/node_modules/ws/lib/subprotocol.js
new file mode 100644
index 00000000000..d4381e8864f
--- /dev/null
+++ b/chromium/third_party/devtools-frontend/src/node_modules/ws/lib/subprotocol.js
@@ -0,0 +1,62 @@
+'use strict';
+
+const { tokenChars } = require('./validation');
+
+/**
+ * Parses the `Sec-WebSocket-Protocol` header into a set of subprotocol names.
+ *
+ * @param {String} header The field value of the header
+ * @return {Set} The subprotocol names
+ * @public
+ */
+function parse(header) {
+ const protocols = new Set();
+ let start = -1;
+ let end = -1;
+ let i = 0;
+
+ for (i; i < header.length; i++) {
+ const code = header.charCodeAt(i);
+
+ if (end === -1 && tokenChars[code] === 1) {
+ if (start === -1) start = i;
+ } else if (
+ i !== 0 &&
+ (code === 0x20 /* ' ' */ || code === 0x09) /* '\t' */
+ ) {
+ if (end === -1 && start !== -1) end = i;
+ } else if (code === 0x2c /* ',' */) {
+ if (start === -1) {
+ throw new SyntaxError(`Unexpected character at index ${i}`);
+ }
+
+ if (end === -1) end = i;
+
+ const protocol = header.slice(start, end);
+
+ if (protocols.has(protocol)) {
+ throw new SyntaxError(`The "${protocol}" subprotocol is duplicated`);
+ }
+
+ protocols.add(protocol);
+ start = end = -1;
+ } else {
+ throw new SyntaxError(`Unexpected character at index ${i}`);
+ }
+ }
+
+ if (start === -1 || end !== -1) {
+ throw new SyntaxError('Unexpected end of input');
+ }
+
+ const protocol = header.slice(start, i);
+
+ if (protocols.has(protocol)) {
+ throw new SyntaxError(`The "${protocol}" subprotocol is duplicated`);
+ }
+
+ protocols.add(protocol);
+ return protocols;
+}
+
+module.exports = { parse };
diff --git a/chromium/third_party/devtools-frontend/src/node_modules/ws/lib/validation.js b/chromium/third_party/devtools-frontend/src/node_modules/ws/lib/validation.js
index 169ac6f0631..ed98c75911f 100644
--- a/chromium/third_party/devtools-frontend/src/node_modules/ws/lib/validation.js
+++ b/chromium/third_party/devtools-frontend/src/node_modules/ws/lib/validation.js
@@ -1,5 +1,28 @@
'use strict';
+//
+// Allowed token characters:
+//
+// '!', '#', '$', '%', '&', ''', '*', '+', '-',
+// '.', 0-9, A-Z, '^', '_', '`', a-z, '|', '~'
+//
+// tokenChars[32] === 0 // ' '
+// tokenChars[33] === 1 // '!'
+// tokenChars[34] === 0 // '"'
+// ...
+//
+// prettier-ignore
+const tokenChars = [
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0 - 15
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16 - 31
+ 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, // 32 - 47
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, // 48 - 63
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64 - 79
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, // 80 - 95
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96 - 111
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0 // 112 - 127
+];
+
/**
* Checks if a status code is allowed in a close frame.
*
@@ -83,22 +106,19 @@ function _isValidUTF8(buf) {
}
try {
- let isValidUTF8 = require('utf-8-validate');
-
- /* istanbul ignore if */
- if (typeof isValidUTF8 === 'object') {
- isValidUTF8 = isValidUTF8.Validation.isValidUTF8; // utf-8-validate@<3.0.0
- }
+ const isValidUTF8 = require('utf-8-validate');
module.exports = {
isValidStatusCode,
isValidUTF8(buf) {
return buf.length < 150 ? _isValidUTF8(buf) : isValidUTF8(buf);
- }
+ },
+ tokenChars
};
} catch (e) /* istanbul ignore next */ {
module.exports = {
isValidStatusCode,
- isValidUTF8: _isValidUTF8
+ isValidUTF8: _isValidUTF8,
+ tokenChars
};
}
diff --git a/chromium/third_party/devtools-frontend/src/node_modules/ws/lib/websocket-server.js b/chromium/third_party/devtools-frontend/src/node_modules/ws/lib/websocket-server.js
index fe7fdf501ce..3c7939f28af 100644
--- a/chromium/third_party/devtools-frontend/src/node_modules/ws/lib/websocket-server.js
+++ b/chromium/third_party/devtools-frontend/src/node_modules/ws/lib/websocket-server.js
@@ -9,9 +9,10 @@ const net = require('net');
const tls = require('tls');
const { createHash } = require('crypto');
+const extension = require('./extension');
const PerMessageDeflate = require('./permessage-deflate');
+const subprotocol = require('./subprotocol');
const WebSocket = require('./websocket');
-const { format, parse } = require('./extension');
const { GUID, kWebSocket } = require('./constants');
const keyRegex = /^[+/0-9A-Za-z]{22}==$/;
@@ -45,6 +46,8 @@ class WebSocketServer extends EventEmitter {
* @param {Number} [options.port] The port where to bind the server
* @param {(http.Server|https.Server)} [options.server] A pre-created HTTP/S
* server to use
+ * @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or
+ * not to skip UTF-8 validation for text and close messages
* @param {Function} [options.verifyClient] A hook to reject connections
* @param {Function} [callback] A listener for the `listening` event
*/
@@ -53,6 +56,7 @@ class WebSocketServer extends EventEmitter {
options = {
maxPayload: 100 * 1024 * 1024,
+ skipUTF8Validation: false,
perMessageDeflate: false,
handleProtocols: null,
clientTracking: true,
@@ -110,7 +114,11 @@ class WebSocketServer extends EventEmitter {
}
if (options.perMessageDeflate === true) options.perMessageDeflate = {};
- if (options.clientTracking) this.clients = new Set();
+ if (options.clientTracking) {
+ this.clients = new Set();
+ this._shouldEmitClose = false;
+ }
+
this.options = options;
this._state = RUNNING;
}
@@ -134,45 +142,58 @@ class WebSocketServer extends EventEmitter {
}
/**
- * Close the server.
+ * Stop the server from accepting new connections and emit the `'close'` event
+ * when all existing connections are closed.
*
- * @param {Function} [cb] Callback
+ * @param {Function} [cb] A one-time listener for the `'close'` event
* @public
*/
close(cb) {
- if (cb) this.once('close', cb);
-
if (this._state === CLOSED) {
+ if (cb) {
+ this.once('close', () => {
+ cb(new Error('The server is not running'));
+ });
+ }
+
process.nextTick(emitClose, this);
return;
}
+ if (cb) this.once('close', cb);
+
if (this._state === CLOSING) return;
this._state = CLOSING;
- //
- // Terminate all associated clients.
- //
- if (this.clients) {
- for (const client of this.clients) client.terminate();
- }
+ if (this.options.noServer || this.options.server) {
+ if (this._server) {
+ this._removeListeners();
+ this._removeListeners = this._server = null;
+ }
- const server = this._server;
+ if (this.clients) {
+ if (!this.clients.size) {
+ process.nextTick(emitClose, this);
+ } else {
+ this._shouldEmitClose = true;
+ }
+ } else {
+ process.nextTick(emitClose, this);
+ }
+ } else {
+ const server = this._server;
- if (server) {
this._removeListeners();
this._removeListeners = this._server = null;
//
- // Close the http server if it was internally created.
+ // The HTTP/S server was created internally. Close it, and rely on its
+ // `'close'` event.
//
- if (this.options.port != null) {
- server.close(emitClose.bind(undefined, this));
- return;
- }
+ server.close(() => {
+ emitClose(this);
+ });
}
-
- process.nextTick(emitClose, this);
}
/**
@@ -208,10 +229,9 @@ class WebSocketServer extends EventEmitter {
const key =
req.headers['sec-websocket-key'] !== undefined
- ? req.headers['sec-websocket-key'].trim()
+ ? req.headers['sec-websocket-key']
: false;
const version = +req.headers['sec-websocket-version'];
- const extensions = {};
if (
req.method !== 'GET' ||
@@ -224,7 +244,24 @@ class WebSocketServer extends EventEmitter {
return abortHandshake(socket, 400);
}
- if (this.options.perMessageDeflate) {
+ const secWebSocketProtocol = req.headers['sec-websocket-protocol'];
+ let protocols = new Set();
+
+ if (secWebSocketProtocol !== undefined) {
+ try {
+ protocols = subprotocol.parse(secWebSocketProtocol);
+ } catch (err) {
+ return abortHandshake(socket, 400);
+ }
+ }
+
+ const secWebSocketExtensions = req.headers['sec-websocket-extensions'];
+ const extensions = {};
+
+ if (
+ this.options.perMessageDeflate &&
+ secWebSocketExtensions !== undefined
+ ) {
const perMessageDeflate = new PerMessageDeflate(
this.options.perMessageDeflate,
true,
@@ -232,7 +269,7 @@ class WebSocketServer extends EventEmitter {
);
try {
- const offers = parse(req.headers['sec-websocket-extensions']);
+ const offers = extension.parse(secWebSocketExtensions);
if (offers[PerMessageDeflate.extensionName]) {
perMessageDeflate.accept(offers[PerMessageDeflate.extensionName]);
@@ -260,7 +297,15 @@ class WebSocketServer extends EventEmitter {
return abortHandshake(socket, code || 401, message, headers);
}
- this.completeUpgrade(key, extensions, req, socket, head, cb);
+ this.completeUpgrade(
+ extensions,
+ key,
+ protocols,
+ req,
+ socket,
+ head,
+ cb
+ );
});
return;
}
@@ -268,14 +313,15 @@ class WebSocketServer extends EventEmitter {
if (!this.options.verifyClient(info)) return abortHandshake(socket, 401);
}
- this.completeUpgrade(key, extensions, req, socket, head, cb);
+ this.completeUpgrade(extensions, key, protocols, req, socket, head, cb);
}
/**
* Upgrade the connection to WebSocket.
*
- * @param {String} key The value of the `Sec-WebSocket-Key` header
* @param {Object} extensions The accepted extensions
+ * @param {String} key The value of the `Sec-WebSocket-Key` header
+ * @param {Set} protocols The subprotocols
* @param {http.IncomingMessage} req The request object
* @param {(net.Socket|tls.Socket)} socket The network socket between the
* server and client
@@ -284,7 +330,7 @@ class WebSocketServer extends EventEmitter {
* @throws {Error} If called more than once with the same socket
* @private
*/
- completeUpgrade(key, extensions, req, socket, head, cb) {
+ completeUpgrade(extensions, key, protocols, req, socket, head, cb) {
//
// Destroy the socket if the client has already sent a FIN packet.
//
@@ -311,19 +357,14 @@ class WebSocketServer extends EventEmitter {
];
const ws = new WebSocket(null);
- let protocol = req.headers['sec-websocket-protocol'];
-
- if (protocol) {
- protocol = protocol.split(',').map(trim);
+ if (protocols.size) {
//
// Optionally call external protocol selection handler.
//
- if (this.options.handleProtocols) {
- protocol = this.options.handleProtocols(protocol, req);
- } else {
- protocol = protocol[0];
- }
+ const protocol = this.options.handleProtocols
+ ? this.options.handleProtocols(protocols, req)
+ : protocols.values().next().value;
if (protocol) {
headers.push(`Sec-WebSocket-Protocol: ${protocol}`);
@@ -333,7 +374,7 @@ class WebSocketServer extends EventEmitter {
if (extensions[PerMessageDeflate.extensionName]) {
const params = extensions[PerMessageDeflate.extensionName].params;
- const value = format({
+ const value = extension.format({
[PerMessageDeflate.extensionName]: [params]
});
headers.push(`Sec-WebSocket-Extensions: ${value}`);
@@ -348,11 +389,20 @@ class WebSocketServer extends EventEmitter {
socket.write(headers.concat('\r\n').join('\r\n'));
socket.removeListener('error', socketOnError);
- ws.setSocket(socket, head, this.options.maxPayload);
+ ws.setSocket(socket, head, {
+ maxPayload: this.options.maxPayload,
+ skipUTF8Validation: this.options.skipUTF8Validation
+ });
if (this.clients) {
this.clients.add(ws);
- ws.on('close', () => this.clients.delete(ws));
+ ws.on('close', () => {
+ this.clients.delete(ws);
+
+ if (this._shouldEmitClose && !this.clients.size) {
+ process.nextTick(emitClose, this);
+ }
+ });
}
cb(ws, req);
@@ -433,15 +483,3 @@ function abortHandshake(socket, code, message, headers) {
socket.removeListener('error', socketOnError);
socket.destroy();
}
-
-/**
- * Remove whitespace characters from both ends of a string.
- *
- * @param {String} str The string
- * @return {String} A new string representing `str` stripped of whitespace
- * characters from both its beginning and end
- * @private
- */
-function trim(str) {
- return str.trim();
-}
diff --git a/chromium/third_party/devtools-frontend/src/node_modules/ws/lib/websocket.js b/chromium/third_party/devtools-frontend/src/node_modules/ws/lib/websocket.js
index 7f1e3bcfae8..57710f4e125 100644
--- a/chromium/third_party/devtools-frontend/src/node_modules/ws/lib/websocket.js
+++ b/chromium/third_party/devtools-frontend/src/node_modules/ws/lib/websocket.js
@@ -1,3 +1,5 @@
+/* eslint no-unused-vars: ["error", { "varsIgnorePattern": "^Readable$" }] */
+
'use strict';
const EventEmitter = require('events');
@@ -6,6 +8,7 @@ const http = require('http');
const net = require('net');
const tls = require('tls');
const { randomBytes, createHash } = require('crypto');
+const { Readable } = require('stream');
const { URL } = require('url');
const PerMessageDeflate = require('./permessage-deflate');
@@ -15,15 +18,20 @@ const {
BINARY_TYPES,
EMPTY_BUFFER,
GUID,
+ kForOnEventAttribute,
+ kListener,
kStatusCode,
kWebSocket,
NOOP
} = require('./constants');
-const { addEventListener, removeEventListener } = require('./event-target');
+const {
+ EventTarget: { addEventListener, removeEventListener }
+} = require('./event-target');
const { format, parse } = require('./extension');
const { toBuffer } = require('./buffer-util');
const readyStates = ['CONNECTING', 'OPEN', 'CLOSING', 'CLOSED'];
+const subprotocolRegex = /^[!#$%&'*+\-.0-9A-Z^_`|a-z~]+$/;
const protocolVersions = [8, 13];
const closeTimeout = 30 * 1000;
@@ -47,9 +55,10 @@ class WebSocket extends EventEmitter {
this._closeCode = 1006;
this._closeFrameReceived = false;
this._closeFrameSent = false;
- this._closeMessage = '';
+ this._closeMessage = EMPTY_BUFFER;
this._closeTimer = null;
this._extensions = {};
+ this._paused = false;
this._protocol = '';
this._readyState = WebSocket.CONNECTING;
this._receiver = null;
@@ -61,11 +70,15 @@ class WebSocket extends EventEmitter {
this._isServer = false;
this._redirects = 0;
- if (Array.isArray(protocols)) {
- protocols = protocols.join(', ');
- } else if (typeof protocols === 'object' && protocols !== null) {
- options = protocols;
- protocols = undefined;
+ if (protocols === undefined) {
+ protocols = [];
+ } else if (!Array.isArray(protocols)) {
+ if (typeof protocols === 'object' && protocols !== null) {
+ options = protocols;
+ protocols = [];
+ } else {
+ protocols = [protocols];
+ }
}
initAsClient(this, address, protocols, options);
@@ -113,49 +126,44 @@ class WebSocket extends EventEmitter {
}
/**
+ * @type {Boolean}
+ */
+ get isPaused() {
+ return this._paused;
+ }
+
+ /**
* @type {Function}
*/
/* istanbul ignore next */
get onclose() {
- return undefined;
+ return null;
}
- /* istanbul ignore next */
- set onclose(listener) {}
-
/**
* @type {Function}
*/
/* istanbul ignore next */
get onerror() {
- return undefined;
+ return null;
}
- /* istanbul ignore next */
- set onerror(listener) {}
-
/**
* @type {Function}
*/
/* istanbul ignore next */
get onopen() {
- return undefined;
+ return null;
}
- /* istanbul ignore next */
- set onopen(listener) {}
-
/**
* @type {Function}
*/
/* istanbul ignore next */
get onmessage() {
- return undefined;
+ return null;
}
- /* istanbul ignore next */
- set onmessage(listener) {}
-
/**
* @type {String}
*/
@@ -183,18 +191,24 @@ class WebSocket extends EventEmitter {
* @param {(net.Socket|tls.Socket)} socket The network socket between the
* server and client
* @param {Buffer} head The first packet of the upgraded stream
- * @param {Number} [maxPayload=0] The maximum allowed message size
+ * @param {Object} options Options object
+ * @param {Function} [options.generateMask] The function used to generate the
+ * masking key
+ * @param {Number} [options.maxPayload=0] The maximum allowed message size
+ * @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or
+ * not to skip UTF-8 validation for text and close messages
* @private
*/
- setSocket(socket, head, maxPayload) {
- const receiver = new Receiver(
- this.binaryType,
- this._extensions,
- this._isServer,
- maxPayload
- );
+ setSocket(socket, head, options) {
+ const receiver = new Receiver({
+ binaryType: this.binaryType,
+ extensions: this._extensions,
+ isServer: this._isServer,
+ maxPayload: options.maxPayload,
+ skipUTF8Validation: options.skipUTF8Validation
+ });
- this._sender = new Sender(socket, this._extensions);
+ this._sender = new Sender(socket, this._extensions, options.generateMask);
this._receiver = receiver;
this._socket = socket;
@@ -259,7 +273,8 @@ class WebSocket extends EventEmitter {
* +---+
*
* @param {Number} [code] Status code explaining why the connection is closing
- * @param {String} [data] A string explaining why the connection is closing
+ * @param {(String|Buffer)} [data] The reason why the connection is
+ * closing
* @public
*/
close(code, data) {
@@ -308,6 +323,23 @@ class WebSocket extends EventEmitter {
}
/**
+ * Pause the socket.
+ *
+ * @public
+ */
+ pause() {
+ if (
+ this.readyState === WebSocket.CONNECTING ||
+ this.readyState === WebSocket.CLOSED
+ ) {
+ return;
+ }
+
+ this._paused = true;
+ this._socket.pause();
+ }
+
+ /**
* Send a ping.
*
* @param {*} [data] The data to send
@@ -372,14 +404,31 @@ class WebSocket extends EventEmitter {
}
/**
+ * Resume the socket.
+ *
+ * @public
+ */
+ resume() {
+ if (
+ this.readyState === WebSocket.CONNECTING ||
+ this.readyState === WebSocket.CLOSED
+ ) {
+ return;
+ }
+
+ this._paused = false;
+ if (!this._receiver._writableState.needDrain) this._socket.resume();
+ }
+
+ /**
* Send a data message.
*
* @param {*} data The message to send
* @param {Object} [options] Options object
- * @param {Boolean} [options.compress] Specifies whether or not to compress
- * `data`
* @param {Boolean} [options.binary] Specifies whether `data` is binary or
* text
+ * @param {Boolean} [options.compress] Specifies whether or not to compress
+ * `data`
* @param {Boolean} [options.fin=true] Specifies whether the fragment is the
* last one
* @param {Boolean} [options.mask] Specifies whether or not to mask `data`
@@ -513,6 +562,7 @@ Object.defineProperty(WebSocket.prototype, 'CLOSED', {
'binaryType',
'bufferedAmount',
'extensions',
+ 'isPaused',
'protocol',
'readyState',
'url'
@@ -528,22 +578,25 @@ Object.defineProperty(WebSocket.prototype, 'CLOSED', {
Object.defineProperty(WebSocket.prototype, `on${method}`, {
enumerable: true,
get() {
- const listeners = this.listeners(method);
- for (let i = 0; i < listeners.length; i++) {
- if (listeners[i]._listener) return listeners[i]._listener;
+ for (const listener of this.listeners(method)) {
+ if (listener[kForOnEventAttribute]) return listener[kListener];
}
- return undefined;
+ return null;
},
- set(listener) {
- const listeners = this.listeners(method);
- for (let i = 0; i < listeners.length; i++) {
- //
- // Remove only the listeners added via `addEventListener`.
- //
- if (listeners[i]._listener) this.removeListener(method, listeners[i]);
+ set(handler) {
+ for (const listener of this.listeners(method)) {
+ if (listener[kForOnEventAttribute]) {
+ this.removeListener(method, listener);
+ break;
+ }
}
- this.addEventListener(method, listener);
+
+ if (typeof handler !== 'function') return;
+
+ this.addEventListener(method, handler, {
+ [kForOnEventAttribute]: true
+ });
}
});
});
@@ -558,28 +611,33 @@ module.exports = WebSocket;
*
* @param {WebSocket} websocket The client to initialize
* @param {(String|URL)} address The URL to which to connect
- * @param {String} [protocols] The subprotocols
+ * @param {Array} protocols The subprotocols
* @param {Object} [options] Connection options
- * @param {(Boolean|Object)} [options.perMessageDeflate=true] Enable/disable
- * permessage-deflate
+ * @param {Boolean} [options.followRedirects=false] Whether or not to follow
+ * redirects
+ * @param {Function} [options.generateMask] The function used to generate the
+ * masking key
* @param {Number} [options.handshakeTimeout] Timeout in milliseconds for the
* handshake request
- * @param {Number} [options.protocolVersion=13] Value of the
- * `Sec-WebSocket-Version` header
- * @param {String} [options.origin] Value of the `Origin` or
- * `Sec-WebSocket-Origin` header
* @param {Number} [options.maxPayload=104857600] The maximum allowed message
* size
- * @param {Boolean} [options.followRedirects=false] Whether or not to follow
- * redirects
* @param {Number} [options.maxRedirects=10] The maximum number of redirects
* allowed
+ * @param {String} [options.origin] Value of the `Origin` or
+ * `Sec-WebSocket-Origin` header
+ * @param {(Boolean|Object)} [options.perMessageDeflate=true] Enable/disable
+ * permessage-deflate
+ * @param {Number} [options.protocolVersion=13] Value of the
+ * `Sec-WebSocket-Version` header
+ * @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or
+ * not to skip UTF-8 validation for text and close messages
* @private
*/
function initAsClient(websocket, address, protocols, options) {
const opts = {
protocolVersion: protocolVersions[1],
maxPayload: 100 * 1024 * 1024,
+ skipUTF8Validation: false,
perMessageDeflate: true,
followRedirects: false,
maxRedirects: 10,
@@ -608,21 +666,43 @@ function initAsClient(websocket, address, protocols, options) {
parsedUrl = address;
websocket._url = address.href;
} else {
- parsedUrl = new URL(address);
+ try {
+ parsedUrl = new URL(address);
+ } catch (e) {
+ throw new SyntaxError(`Invalid URL: ${address}`);
+ }
+
websocket._url = address;
}
+ const isSecure = parsedUrl.protocol === 'wss:';
const isUnixSocket = parsedUrl.protocol === 'ws+unix:';
+ let invalidURLMessage;
+
+ if (parsedUrl.protocol !== 'ws:' && !isSecure && !isUnixSocket) {
+ invalidURLMessage =
+ 'The URL\'s protocol must be one of "ws:", "wss:", or "ws+unix:"';
+ } else if (isUnixSocket && !parsedUrl.pathname) {
+ invalidURLMessage = "The URL's pathname is empty";
+ } else if (parsedUrl.hash) {
+ invalidURLMessage = 'The URL contains a fragment identifier';
+ }
- if (!parsedUrl.host && (!isUnixSocket || !parsedUrl.pathname)) {
- throw new Error(`Invalid URL: ${websocket.url}`);
+ if (invalidURLMessage) {
+ const err = new SyntaxError(invalidURLMessage);
+
+ if (websocket._redirects === 0) {
+ throw err;
+ } else {
+ emitErrorAndClose(websocket, err);
+ return;
+ }
}
- const isSecure =
- parsedUrl.protocol === 'wss:' || parsedUrl.protocol === 'https:';
const defaultPort = isSecure ? 443 : 80;
const key = randomBytes(16).toString('base64');
const get = isSecure ? https.get : http.get;
+ const protocolSet = new Set();
let perMessageDeflate;
opts.createConnection = isSecure ? tlsConnect : netConnect;
@@ -651,8 +731,22 @@ function initAsClient(websocket, address, protocols, options) {
[PerMessageDeflate.extensionName]: perMessageDeflate.offer()
});
}
- if (protocols) {
- opts.headers['Sec-WebSocket-Protocol'] = protocols;
+ if (protocols.length) {
+ for (const protocol of protocols) {
+ if (
+ typeof protocol !== 'string' ||
+ !subprotocolRegex.test(protocol) ||
+ protocolSet.has(protocol)
+ ) {
+ throw new SyntaxError(
+ 'An invalid or duplicated subprotocol was specified'
+ );
+ }
+
+ protocolSet.add(protocol);
+ }
+
+ opts.headers['Sec-WebSocket-Protocol'] = protocols.join(',');
}
if (opts.origin) {
if (opts.protocolVersion < 13) {
@@ -684,9 +778,7 @@ function initAsClient(websocket, address, protocols, options) {
if (req === null || req.aborted) return;
req = websocket._req = null;
- websocket._readyState = WebSocket.CLOSING;
- websocket.emit('error', err);
- websocket.emitClose();
+ emitErrorAndClose(websocket, err);
});
req.on('response', (res) => {
@@ -706,7 +798,15 @@ function initAsClient(websocket, address, protocols, options) {
req.abort();
- const addr = new URL(location, address);
+ let addr;
+
+ try {
+ addr = new URL(location, address);
+ } catch (e) {
+ const err = new SyntaxError(`Invalid URL: ${location}`);
+ emitErrorAndClose(websocket, err);
+ return;
+ }
initAsClient(websocket, addr, protocols, options);
} else if (!websocket.emit('unexpected-response', req, res)) {
@@ -739,15 +839,16 @@ function initAsClient(websocket, address, protocols, options) {
}
const serverProt = res.headers['sec-websocket-protocol'];
- const protList = (protocols || '').split(/, */);
let protError;
- if (!protocols && serverProt) {
- protError = 'Server sent a subprotocol but none was requested';
- } else if (protocols && !serverProt) {
+ if (serverProt !== undefined) {
+ if (!protocolSet.size) {
+ protError = 'Server sent a subprotocol but none was requested';
+ } else if (!protocolSet.has(serverProt)) {
+ protError = 'Server sent an invalid subprotocol';
+ }
+ } else if (protocolSet.size) {
protError = 'Server sent no subprotocol';
- } else if (serverProt && !protList.includes(serverProt)) {
- protError = 'Server sent an invalid subprotocol';
}
if (protError) {
@@ -780,35 +881,49 @@ function initAsClient(websocket, address, protocols, options) {
const extensionNames = Object.keys(extensions);
- if (extensionNames.length) {
- if (
- extensionNames.length !== 1 ||
- extensionNames[0] !== PerMessageDeflate.extensionName
- ) {
- const message =
- 'Server indicated an extension that was not requested';
- abortHandshake(websocket, socket, message);
- return;
- }
-
- try {
- perMessageDeflate.accept(extensions[PerMessageDeflate.extensionName]);
- } catch (err) {
- const message = 'Invalid Sec-WebSocket-Extensions header';
- abortHandshake(websocket, socket, message);
- return;
- }
+ if (
+ extensionNames.length !== 1 ||
+ extensionNames[0] !== PerMessageDeflate.extensionName
+ ) {
+ const message = 'Server indicated an extension that was not requested';
+ abortHandshake(websocket, socket, message);
+ return;
+ }
- websocket._extensions[PerMessageDeflate.extensionName] =
- perMessageDeflate;
+ try {
+ perMessageDeflate.accept(extensions[PerMessageDeflate.extensionName]);
+ } catch (err) {
+ const message = 'Invalid Sec-WebSocket-Extensions header';
+ abortHandshake(websocket, socket, message);
+ return;
}
+
+ websocket._extensions[PerMessageDeflate.extensionName] =
+ perMessageDeflate;
}
- websocket.setSocket(socket, head, opts.maxPayload);
+ websocket.setSocket(socket, head, {
+ generateMask: opts.generateMask,
+ maxPayload: opts.maxPayload,
+ skipUTF8Validation: opts.skipUTF8Validation
+ });
});
}
/**
+ * Emit the `'error'` and `'close'` event.
+ *
+ * @param {WebSocket} websocket The WebSocket instance
+ * @param {Error} The error to emit
+ * @private
+ */
+function emitErrorAndClose(websocket, err) {
+ websocket._readyState = WebSocket.CLOSING;
+ websocket.emit('error', err);
+ websocket.emitClose();
+}
+
+/**
* Create a `net.Socket` and initiate a connection.
*
* @param {Object} options Connection options
@@ -909,19 +1024,21 @@ function sendAfterClose(websocket, data, cb) {
* The listener of the `Receiver` `'conclude'` event.
*
* @param {Number} code The status code
- * @param {String} reason The reason for closing
+ * @param {Buffer} reason The reason for closing
* @private
*/
function receiverOnConclude(code, reason) {
const websocket = this[kWebSocket];
- websocket._socket.removeListener('data', socketOnData);
- websocket._socket.resume();
-
websocket._closeFrameReceived = true;
websocket._closeMessage = reason;
websocket._closeCode = code;
+ if (websocket._socket[kWebSocket] === undefined) return;
+
+ websocket._socket.removeListener('data', socketOnData);
+ process.nextTick(resume, websocket._socket);
+
if (code === 1005) websocket.close();
else websocket.close(code, reason);
}
@@ -932,7 +1049,9 @@ function receiverOnConclude(code, reason) {
* @private
*/
function receiverOnDrain() {
- this[kWebSocket]._socket.resume();
+ const websocket = this[kWebSocket];
+
+ if (!websocket.isPaused) websocket._socket.resume();
}
/**
@@ -944,10 +1063,18 @@ function receiverOnDrain() {
function receiverOnError(err) {
const websocket = this[kWebSocket];
- websocket._socket.removeListener('data', socketOnData);
- websocket._socket.resume();
+ if (websocket._socket[kWebSocket] !== undefined) {
+ websocket._socket.removeListener('data', socketOnData);
+
+ //
+ // On Node.js < 14.0.0 the `'error'` event is emitted synchronously. See
+ // https://github.com/websockets/ws/issues/1940.
+ //
+ process.nextTick(resume, websocket._socket);
+
+ websocket.close(err[kStatusCode]);
+ }
- websocket.close(err[kStatusCode]);
websocket.emit('error', err);
}
@@ -963,11 +1090,12 @@ function receiverOnFinish() {
/**
* The listener of the `Receiver` `'message'` event.
*
- * @param {(String|Buffer|ArrayBuffer|Buffer[])} data The message
+ * @param {Buffer|ArrayBuffer|Buffer[])} data The message
+ * @param {Boolean} isBinary Specifies whether the message is binary or not
* @private
*/
-function receiverOnMessage(data) {
- this[kWebSocket].emit('message', data);
+function receiverOnMessage(data, isBinary) {
+ this[kWebSocket].emit('message', data, isBinary);
}
/**
@@ -994,6 +1122,16 @@ function receiverOnPong(data) {
}
/**
+ * Resume a readable stream
+ *
+ * @param {Readable} stream The readable stream
+ * @private
+ */
+function resume(stream) {
+ stream.resume();
+}
+
+/**
* The listener of the `net.Socket` `'close'` event.
*
* @private
@@ -1002,10 +1140,13 @@ function socketOnClose() {
const websocket = this[kWebSocket];
this.removeListener('close', socketOnClose);
+ this.removeListener('data', socketOnData);
this.removeListener('end', socketOnEnd);
websocket._readyState = WebSocket.CLOSING;
+ let chunk;
+
//
// The close frame might not have been received or the `'end'` event emitted,
// for example, if the socket was destroyed due to an error. Ensure that the
@@ -1013,13 +1154,19 @@ function socketOnClose() {
// it. If the readable side of the socket is in flowing mode then there is no
// buffered data as everything has been already written and `readable.read()`
// will return `null`. If instead, the socket is paused, any possible buffered
- // data will be read as a single chunk and emitted synchronously in a single
- // `'data'` event.
+ // data will be read as a single chunk.
//
- websocket._socket.read();
+ if (
+ !this._readableState.endEmitted &&
+ !websocket._closeFrameReceived &&
+ !websocket._receiver._writableState.errorEmitted &&
+ (chunk = websocket._socket.read()) !== null
+ ) {
+ websocket._receiver.write(chunk);
+ }
+
websocket._receiver.end();
- this.removeListener('data', socketOnData);
this[kWebSocket] = undefined;
clearTimeout(websocket._closeTimer);
diff --git a/chromium/third_party/devtools-frontend/src/node_modules/ws/package.json b/chromium/third_party/devtools-frontend/src/node_modules/ws/package.json
index d6dff1396c8..813155221b1 100644
--- a/chromium/third_party/devtools-frontend/src/node_modules/ws/package.json
+++ b/chromium/third_party/devtools-frontend/src/node_modules/ws/package.json
@@ -1,6 +1,6 @@
{
"name": "ws",
- "version": "7.5.3",
+ "version": "8.4.0",
"description": "Simple to use, blazing fast and thoroughly tested websocket client and server for Node.js",
"keywords": [
"HyBi",
@@ -16,14 +16,19 @@
"author": "Einar Otto Stangvik <einaros@gmail.com> (http://2x.io)",
"license": "MIT",
"main": "index.js",
+ "exports": {
+ "import": "./wrapper.mjs",
+ "require": "./index.js"
+ },
"browser": "browser.js",
"engines": {
- "node": ">=8.3.0"
+ "node": ">=10.0.0"
},
"files": [
"browser.js",
"index.js",
- "lib/*.js"
+ "lib/*.js",
+ "wrapper.mjs"
],
"scripts": {
"test": "nyc --reporter=lcov --reporter=text mocha --throw-deprecation test/*.test.js",
@@ -45,10 +50,10 @@
"devDependencies": {
"benchmark": "^2.1.4",
"bufferutil": "^4.0.1",
- "eslint": "^7.2.0",
+ "eslint": "^8.0.0",
"eslint-config-prettier": "^8.1.0",
- "eslint-plugin-prettier": "^3.0.1",
- "mocha": "^7.0.0",
+ "eslint-plugin-prettier": "^4.0.0",
+ "mocha": "^8.4.0",
"nyc": "^15.0.0",
"prettier": "^2.0.5",
"utf-8-validate": "^5.0.2"
diff --git a/chromium/third_party/devtools-frontend/src/node_modules/ws/wrapper.mjs b/chromium/third_party/devtools-frontend/src/node_modules/ws/wrapper.mjs
new file mode 100644
index 00000000000..7245ad15d02
--- /dev/null
+++ b/chromium/third_party/devtools-frontend/src/node_modules/ws/wrapper.mjs
@@ -0,0 +1,8 @@
+import createWebSocketStream from './lib/stream.js';
+import Receiver from './lib/receiver.js';
+import Sender from './lib/sender.js';
+import WebSocket from './lib/websocket.js';
+import WebSocketServer from './lib/websocket-server.js';
+
+export { createWebSocketStream, Receiver, Sender, WebSocket, WebSocketServer };
+export default WebSocket;