New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

simple-websocket

Package Overview
Dependencies
Maintainers
1
Versions
52
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

simple-websocket - npm Package Compare versions

Comparing version 7.2.0 to 8.0.0

406

index.js
/* global WebSocket, DOMException */
module.exports = Socket
const debug = require('debug')('simple-websocket')
const randombytes = require('randombytes')
const stream = require('readable-stream')
const ws = require('ws') // websockets in node - will be empty object in browser
var debug = require('debug')('simple-websocket')
var inherits = require('inherits')
var randombytes = require('randombytes')
var stream = require('readable-stream')
var ws = require('ws') // websockets in node - will be empty object in browser
const _WebSocket = typeof ws !== 'function' ? WebSocket : ws
var _WebSocket = typeof ws !== 'function' ? WebSocket : ws
const MAX_BUFFERED_AMOUNT = 64 * 1024
var MAX_BUFFERED_AMOUNT = 64 * 1024
inherits(Socket, stream.Duplex)
/**

@@ -23,252 +18,243 @@ * WebSocket. Same API as node core `net.Socket`. Duplex stream.

*/
function Socket (opts) {
var self = this
if (!(self instanceof Socket)) return new Socket(opts)
if (!opts) opts = {}
class Socket extends stream.Duplex {
constructor (opts = {}) {
// Support simple usage: `new Socket(url)`
if (typeof opts === 'string') {
opts = { url: opts }
}
// Support simple usage: `new Socket(url)`
if (typeof opts === 'string') {
opts = { url: opts }
}
opts = Object.assign({
allowHalfOpen: false
}, opts)
if (opts.url == null && opts.socket == null) {
throw new Error('Missing required `url` or `socket` option')
}
if (opts.url != null && opts.socket != null) {
throw new Error('Must specify either `url` or `socket` option, not both')
}
super(opts)
self._id = randombytes(4).toString('hex').slice(0, 7)
self._debug('new websocket: %o', opts)
if (opts.url == null && opts.socket == null) {
throw new Error('Missing required `url` or `socket` option')
}
if (opts.url != null && opts.socket != null) {
throw new Error('Must specify either `url` or `socket` option, not both')
}
opts = Object.assign({
allowHalfOpen: false
}, opts)
this._id = randombytes(4).toString('hex').slice(0, 7)
this._debug('new websocket: %o', opts)
stream.Duplex.call(self, opts)
this.connected = false
this.destroyed = false
self.connected = false
self.destroyed = false
this._chunk = null
this._cb = null
this._interval = null
self._chunk = null
self._cb = null
self._interval = null
if (opts.socket) {
self.url = opts.socket.url
self._ws = opts.socket
} else {
self.url = opts.url
try {
if (typeof ws === 'function') {
// `ws` package accepts options
self._ws = new _WebSocket(opts.url, opts)
} else {
self._ws = new _WebSocket(opts.url)
if (opts.socket) {
this.url = opts.socket.url
this._ws = opts.socket
} else {
this.url = opts.url
try {
if (typeof ws === 'function') {
// `ws` package accepts options
this._ws = new _WebSocket(opts.url, opts)
} else {
this._ws = new _WebSocket(opts.url)
}
} catch (err) {
process.nextTick(() => this.destroy(err))
return
}
} catch (err) {
process.nextTick(function () {
self.destroy(err)
})
return
}
this._ws.binaryType = 'arraybuffer'
this._ws.onopen = () => {
this._onOpen()
}
this._ws.onmessage = event => {
this._onMessage(event)
}
this._ws.onclose = () => {
this._onClose()
}
this._ws.onerror = () => {
this.destroy(new Error('connection error to ' + this.url))
}
this._onFinishBound = () => {
this._onFinish()
}
this.once('finish', this._onFinishBound)
}
self._ws.binaryType = 'arraybuffer'
self._ws.onopen = function () {
self._onOpen()
/**
* Send text/binary data to the WebSocket server.
* @param {TypedArrayView|ArrayBuffer|Buffer|string|Blob|Object} chunk
*/
send (chunk) {
this._ws.send(chunk)
}
self._ws.onmessage = function (event) {
self._onMessage(event)
}
self._ws.onclose = function () {
self._onClose()
}
self._ws.onerror = function () {
self.destroy(new Error('connection error to ' + self.url))
}
self._onFinishBound = function () {
self._onFinish()
// TODO: Delete this method once readable-stream is updated to contain a default
// implementation of destroy() that automatically calls _destroy()
// See: https://github.com/nodejs/readable-stream/issues/283
destroy (err) {
this._destroy(err, () => {})
}
self.once('finish', self._onFinishBound)
}
Socket.WEBSOCKET_SUPPORT = !!_WebSocket
_destroy (err, cb) {
if (this.destroyed) return
/**
* Send text/binary data to the WebSocket server.
* @param {TypedArrayView|ArrayBuffer|Buffer|string|Blob|Object} chunk
*/
Socket.prototype.send = function (chunk) {
this._ws.send(chunk)
}
this._debug('destroy (error: %s)', err && (err.message || err))
// TODO: Delete this method once readable-stream is updated to contain a default
// implementation of destroy() that automatically calls _destroy()
// See: https://github.com/nodejs/readable-stream/issues/283
Socket.prototype.destroy = function (err) {
this._destroy(err, function () {})
}
this.readable = this.writable = false
if (!this._readableState.ended) this.push(null)
if (!this._writableState.finished) this.end()
Socket.prototype._destroy = function (err, cb) {
var self = this
if (self.destroyed) return
this.connected = false
this.destroyed = true
self._debug('destroy (error: %s)', err && (err.message || err))
clearInterval(this._interval)
this._interval = null
this._chunk = null
this._cb = null
self.readable = self.writable = false
if (!self._readableState.ended) self.push(null)
if (!self._writableState.finished) self.end()
if (this._onFinishBound) this.removeListener('finish', this._onFinishBound)
this._onFinishBound = null
self.connected = false
self.destroyed = true
clearInterval(self._interval)
self._interval = null
self._chunk = null
self._cb = null
if (self._onFinishBound) self.removeListener('finish', self._onFinishBound)
self._onFinishBound = null
if (self._ws) {
var ws = self._ws
var onClose = function () {
ws.onclose = null
}
if (ws.readyState === _WebSocket.CLOSED) {
onClose()
} else {
try {
ws.onclose = onClose
ws.close()
} catch (err) {
if (this._ws) {
const ws = this._ws
const onClose = () => {
ws.onclose = null
}
if (ws.readyState === _WebSocket.CLOSED) {
onClose()
} else {
try {
ws.onclose = onClose
ws.close()
} catch (err) {
onClose()
}
}
ws.onopen = null
ws.onmessage = null
ws.onerror = () => {}
}
this._ws = null
ws.onopen = null
ws.onmessage = null
ws.onerror = function () {}
}
self._ws = null
if (err) {
if (typeof DOMException !== 'undefined' && err instanceof DOMException) {
// Convert Edge DOMException object to Error object
var code = err.code
err = new Error(err.message)
err.code = code
if (err) {
if (typeof DOMException !== 'undefined' && err instanceof DOMException) {
// Convert Edge DOMException object to Error object
const code = err.code
err = new Error(err.message)
err.code = code
}
this.emit('error', err)
}
self.emit('error', err)
this.emit('close')
cb()
}
self.emit('close')
cb()
}
Socket.prototype._read = function () {}
_read () {}
Socket.prototype._write = function (chunk, encoding, cb) {
if (this.destroyed) return cb(new Error('cannot write after socket is destroyed'))
_write (chunk, encoding, cb) {
if (this.destroyed) return cb(new Error('cannot write after socket is destroyed'))
if (this.connected) {
try {
this.send(chunk)
} catch (err) {
return this.destroy(err)
}
if (typeof ws !== 'function' && this._ws.bufferedAmount > MAX_BUFFERED_AMOUNT) {
this._debug('start backpressure: bufferedAmount %d', this._ws.bufferedAmount)
if (this.connected) {
try {
this.send(chunk)
} catch (err) {
return this.destroy(err)
}
if (typeof ws !== 'function' && this._ws.bufferedAmount > MAX_BUFFERED_AMOUNT) {
this._debug('start backpressure: bufferedAmount %d', this._ws.bufferedAmount)
this._cb = cb
} else {
cb(null)
}
} else {
this._debug('write before connect')
this._chunk = chunk
this._cb = cb
} else {
cb(null)
}
} else {
this._debug('write before connect')
this._chunk = chunk
this._cb = cb
}
}
// When stream finishes writing, close socket. Half open connections are not
// supported.
Socket.prototype._onFinish = function () {
var self = this
if (self.destroyed) return
// When stream finishes writing, close socket. Half open connections are not
// supported.
_onFinish () {
if (this.destroyed) return
if (self.connected) {
destroySoon()
} else {
self.once('connect', destroySoon)
// Wait a bit before destroying so the socket flushes.
// TODO: is there a more reliable way to accomplish this?
const destroySoon = () => {
setTimeout(() => this.destroy(), 1000)
}
if (this.connected) {
destroySoon()
} else {
this.once('connect', destroySoon)
}
}
// Wait a bit before destroying so the socket flushes.
// TODO: is there a more reliable way to accomplish this?
function destroySoon () {
setTimeout(function () {
self.destroy()
}, 1000)
_onMessage (event) {
if (this.destroyed) return
let data = event.data
if (data instanceof ArrayBuffer) data = Buffer.from(data)
this.push(data)
}
}
Socket.prototype._onMessage = function (event) {
if (this.destroyed) return
var data = event.data
if (data instanceof ArrayBuffer) data = Buffer.from(data)
this.push(data)
}
_onOpen () {
if (this.connected || this.destroyed) return
this.connected = true
Socket.prototype._onOpen = function () {
var self = this
if (self.connected || self.destroyed) return
self.connected = true
if (this._chunk) {
try {
this.send(this._chunk)
} catch (err) {
return this.destroy(err)
}
this._chunk = null
this._debug('sent chunk from "write before connect"')
if (self._chunk) {
try {
self.send(self._chunk)
} catch (err) {
return self.destroy(err)
const cb = this._cb
this._cb = null
cb(null)
}
self._chunk = null
self._debug('sent chunk from "write before connect"')
var cb = self._cb
self._cb = null
// Backpressure is not implemented in Node.js. The `ws` module has a buggy
// `bufferedAmount` property. See: https://github.com/websockets/ws/issues/492
if (typeof ws !== 'function') {
this._interval = setInterval(() => this._onInterval(), 150)
if (this._interval.unref) this._interval.unref()
}
this._debug('connect')
this.emit('connect')
}
_onInterval () {
if (!this._cb || !this._ws || this._ws.bufferedAmount > MAX_BUFFERED_AMOUNT) {
return
}
this._debug('ending backpressure: bufferedAmount %d', this._ws.bufferedAmount)
const cb = this._cb
this._cb = null
cb(null)
}
// Backpressure is not implemented in Node.js. The `ws` module has a buggy
// `bufferedAmount` property. See: https://github.com/websockets/ws/issues/492
if (typeof ws !== 'function') {
self._interval = setInterval(function () {
self._onInterval()
}, 150)
if (self._interval.unref) self._interval.unref()
_onClose () {
if (this.destroyed) return
this._debug('on close')
this.destroy()
}
self._debug('connect')
self.emit('connect')
}
Socket.prototype._onInterval = function () {
if (!this._cb || !this._ws || this._ws.bufferedAmount > MAX_BUFFERED_AMOUNT) {
return
_debug () {
const args = [].slice.call(arguments)
args[0] = '[' + this._id + '] ' + args[0]
debug.apply(null, args)
}
this._debug('ending backpressure: bufferedAmount %d', this._ws.bufferedAmount)
var cb = this._cb
this._cb = null
cb(null)
}
Socket.prototype._onClose = function () {
if (this.destroyed) return
this._debug('on close')
this.destroy()
}
Socket.WEBSOCKET_SUPPORT = !!_WebSocket
Socket.prototype._debug = function () {
var args = [].slice.call(arguments)
args[0] = '[' + this._id + '] ' + args[0]
debug.apply(null, args)
}
module.exports = Socket
{
"name": "simple-websocket",
"description": "Simple, EventEmitter API for WebSockets (browser)",
"version": "7.2.0",
"version": "8.0.0",
"author": {

@@ -17,10 +17,10 @@ "name": "Feross Aboukhadijeh",

"dependencies": {
"debug": "^3.1.0",
"inherits": "^2.0.1",
"debug": "^4.1.1",
"randombytes": "^2.0.3",
"readable-stream": "^2.0.5",
"ws": "^6.0.0"
"readable-stream": "^3.1.1",
"ws": "^7.0.0"
},
"devDependencies": {
"airtap": "0.1.0",
"airtap": "^2.0.3",
"babel-minify": "^0.5.0",
"browserify": "^16.1.0",

@@ -30,4 +30,3 @@ "prettier-bytes": "^1.0.3",

"standard": "*",
"tape": "^4.0.0",
"uglify-js": "^3.1.8"
"tape": "^4.0.0"
},

@@ -50,3 +49,3 @@ "homepage": "https://github.com/feross/simple-websocket",

"scripts": {
"build": "browserify -s SimpleWebsocket -r ./ | uglifyjs -c warnings=false -m > simplewebsocket.min.js",
"build": "browserify -s SimpleWebsocket -r ./ | minify > simplewebsocket.min.js",
"test": "standard && npm run test-node && npm run test-browser",

@@ -53,0 +52,0 @@ "test-browser": "airtap -- test/*.js",

@@ -38,2 +38,3 @@ # simple-websocket [![travis][travis-image]][travis-url] [![npm][npm-image]][npm-url] [![downloads][downloads-image]][downloads-url] [![javascript style guide][standard-image]][standard-url]

- [lxjs-chat](https://github.com/feross/lxjs-chat) - Omegle chat clone
- [Metastream](https://github.com/samuelmaddock/metastream) - Watch streaming media with friends.
- \[ your application here - send a PR \]

@@ -40,0 +41,0 @@

@@ -1,77 +0,63 @@

module.exports = SocketServer
const events = require('events')
const Socket = require('./')
const WebSocketServer = require('ws').Server
var events = require('events')
var inherits = require('inherits')
var Socket = require('./')
var WebSocketServer = require('ws').Server
class SocketServer extends events.EventEmitter {
constructor (opts) {
opts = Object.assign({
clientTracking: false,
perMessageDeflate: false
}, opts)
inherits(SocketServer, events.EventEmitter)
super()
function SocketServer (opts) {
var self = this
if (!(self instanceof SocketServer)) return new SocketServer(opts)
this.destroyed = false
opts = Object.assign({
clientTracking: false,
perMessageDeflate: false
}, opts)
this._server = new WebSocketServer(opts)
events.EventEmitter.call(self)
this._onListeningBound = () => this._onListening()
this._server.on('listening', this._onListeningBound)
self.destroyed = false
this._onConnectionBound = conn => this._onConnection(conn)
this._server.on('connection', this._onConnectionBound)
self._server = new WebSocketServer(opts)
this._onErrorBound = err => this._onError(err)
this._server.once('error', this._onErrorBound)
}
self._onListeningBound = function () {
self._onListening()
address () {
return this._server.address()
}
self._server.on('listening', self._onListeningBound)
self._onConnectionBound = function (conn) {
self._onConnection(conn)
close (cb) {
if (this.destroyed) return cb(new Error('server is closed'))
this.destroyed = true
if (cb) this.once('close', cb)
this._server.removeListener('listening', this._onListeningBound)
this._server.removeListener('connection', this._onConnectionBound)
this._server.removeListener('error', this._onErrorBound)
this._server.close(() => this.emit('close'))
}
self._server.on('connection', self._onConnectionBound)
self._onErrorBound = function (err) {
self._onError(err)
_onListening () {
this.emit('listening')
}
self._server.once('error', self._onErrorBound)
}
SocketServer.prototype.address = function () {
return this._server.address()
}
_onConnection (conn) {
const socket = new Socket({ socket: conn })
socket._onOpen()
socket.upgradeReq = conn.upgradeReq
this.emit('connection', socket)
this.once('close', () => {
socket.upgradeReq = null
})
}
SocketServer.prototype.close = function (cb) {
var self = this
if (self.destroyed) return cb(new Error('server is closed'))
self.destroyed = true
if (cb) self.once('close', cb)
self._server.removeListener('listening', self._onListeningBound)
self._server.removeListener('connection', self._onConnectionBound)
self._server.removeListener('error', self._onErrorBound)
self._server.close(function () {
self.emit('close')
})
_onError (err) {
this.emit('error', err)
this.close()
}
}
SocketServer.prototype._onListening = function () {
this.emit('listening')
}
SocketServer.prototype._onConnection = function (conn) {
var socket = new Socket({ socket: conn })
socket._onOpen()
socket.upgradeReq = conn.upgradeReq
this.emit('connection', socket)
this.once('close', function () {
socket.upgradeReq = null
})
}
SocketServer.prototype._onError = function (err) {
this.emit('error', err)
this.close()
}
module.exports = SocketServer

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc