engine.io
Advanced tools
Comparing version 0.2.2 to 0.3.0
0.3.0 / 2012-10-04 | ||
================== | ||
* socket: `writeBuffer` now gets sliced, and is recoverable after `close` [afshinm] | ||
* server: expect ping from client and send interval with handshake [cadorn] | ||
* polling-jsonp: prevent client breakage with utf8 whitespace | ||
* socket: fix `flush` and `drain` events | ||
* socket: add `send` callback [afshinm] | ||
* transport: avoid unhandled error events for stale transports | ||
* README: documentation improvements [EugenDueck] | ||
0.2.2 / 2012-08-26 | ||
@@ -3,0 +14,0 @@ ================== |
@@ -1,2 +0,1 @@ | ||
/** | ||
@@ -6,2 +5,2 @@ * Exposes the client parser to avoid code repetition. | ||
module.exports = require('engine.io-client').parser; | ||
module.exports = require('engine.io-client/lib/parser'); |
@@ -10,2 +10,3 @@ | ||
, crypto = require('crypto') | ||
, base64id = require('base64id') | ||
, transports = require('./transports') | ||
@@ -115,18 +116,2 @@ , EventEmitter = require('events').EventEmitter | ||
/** | ||
* Generates an id. | ||
* | ||
* @api private | ||
*/ | ||
Server.prototype.id = function(){ | ||
var rand = new Buffer(15); | ||
this.sequenceNumber = (this.sequenceNumber + 1) | 0; | ||
rand.writeInt32BE(this.sequenceNumber, 11); | ||
crypto.randomBytes(12).copy(rand); | ||
var id = rand.toString('base64').replace(/\//g, '_').replace(/\+/g, '-'); | ||
if (this.clients[id]) return this.id(); | ||
return id; | ||
}; | ||
/** | ||
* Closes all clients. | ||
@@ -183,3 +168,3 @@ * | ||
Server.prototype.handshake = function(transport, req){ | ||
var id = this.id(); | ||
var id = base64id.generateId(); | ||
@@ -186,0 +171,0 @@ debug('handshaking client "%d"', id); |
@@ -26,2 +26,3 @@ /** | ||
this.writeBuffer = []; | ||
this.packetsFn = []; | ||
@@ -62,2 +63,3 @@ this.setTransport(transport); | ||
, upgrades: this.getAvailableUpgrades() | ||
, pingInterval: this.server.pingInterval | ||
, pingTimeout: this.server.pingTimeout | ||
@@ -67,3 +69,3 @@ })); | ||
this.emit('open'); | ||
this.ping(); | ||
this.setPingTimeout(); | ||
}; | ||
@@ -81,6 +83,8 @@ | ||
switch (packet.type) { | ||
case 'pong': | ||
debug('got pong'); | ||
case 'ping': | ||
debug('got ping'); | ||
this.sendPacket('pong'); | ||
this.emit('heartbeat'); | ||
this.ping(); | ||
this.setPingTimeout(); | ||
break; | ||
@@ -107,3 +111,3 @@ | ||
/** | ||
* Pings a client. | ||
* Sets and resets ping timeout timer based on client pings. | ||
* | ||
@@ -113,14 +117,8 @@ * @api private | ||
Socket.prototype.ping = function () { | ||
clearTimeout(this.pingIntervalTimer); | ||
Socket.prototype.setPingTimeout = function () { | ||
var self = this; | ||
this.pingIntervalTimer = setTimeout(function () { | ||
debug('writing ping packet - expected pong in %sms', self.server.pingTimeout); | ||
self.sendPacket('ping'); | ||
clearTimeout(self.pingTimeoutTimer); | ||
self.pingTimeoutTimer = setTimeout(function () { | ||
self.onClose('ping timeout'); | ||
}, self.server.pingTimeout); | ||
}, this.server.pingInterval); | ||
clearTimeout(self.pingTimeoutTimer); | ||
self.pingTimeoutTimer = setTimeout(function () { | ||
self.onClose('ping timeout'); | ||
}, self.server.pingInterval + self.server.pingTimeout); | ||
}; | ||
@@ -141,2 +139,4 @@ | ||
this.transport.once('close', this.onClose.bind(this, 'transport close')); | ||
//this function will manage packet events (also message callbacks) | ||
this.setupSendCallback(); | ||
}; | ||
@@ -183,3 +183,3 @@ | ||
self.setTransport(transport); | ||
self.ping(); | ||
self.setPingTimeout(); | ||
self.flush(); | ||
@@ -218,2 +218,3 @@ clearTimeout(upgradeTimeout); | ||
if ('closed' != this.readyState) { | ||
this.packetsFn = []; | ||
this.clearTransport(); | ||
@@ -226,5 +227,26 @@ this.readyState = 'closed'; | ||
/** | ||
* Setup and manage send callback | ||
* | ||
* @api private | ||
*/ | ||
Socket.prototype.setupSendCallback = function () { | ||
var self = this; | ||
//the message was sent successfully, execute the callback | ||
this.transport.on('drain', function() { | ||
if (self.packetsFn.length > 0) { | ||
var seqFn = self.packetsFn.splice(0,1)[0]; | ||
if ('function' == typeof seqFn) { | ||
debug('executing send callback'); | ||
seqFn(self.transport); | ||
} | ||
} | ||
}); | ||
}; | ||
/** | ||
* Sends a message packet. | ||
* | ||
* @param {String} message | ||
* @param {Function} callback | ||
* @return {Socket} for chaining | ||
@@ -234,4 +256,4 @@ * @api public | ||
Socket.prototype.send = function (data) { | ||
this.sendPacket('message', data); | ||
Socket.prototype.send = function (data, callback) { | ||
this.sendPacket('message', data, callback); | ||
return this; | ||
@@ -248,6 +270,10 @@ }; | ||
Socket.prototype.sendPacket = function (type, data) { | ||
Socket.prototype.sendPacket = function (type, data, callback) { | ||
if ('closing' != this.readyState) { | ||
debug('sending packet "%s" (%s)', type, data); | ||
this.writeBuffer.push({ type: type, data: data }); | ||
//add send callback to object | ||
if (callback) { | ||
this.packetsFn.push(callback); | ||
} | ||
this.flush(); | ||
@@ -254,0 +280,0 @@ } |
@@ -57,4 +57,11 @@ | ||
JSONP.prototype.doWrite = function (data) { | ||
data = this.head + JSON.stringify(data) + this.foot; | ||
// we must output valid javascript, not valid json | ||
// see: http://timelessrepo.com/json-isnt-a-javascript-subset | ||
var js = JSON.stringify(data) | ||
.replace(/\u2028/g, '\\u2028') | ||
.replace(/\u2029/g, '\\u2029'); | ||
// prepare response | ||
data = this.head + js + this.foot; | ||
// explicit UTF-8 is required for pages not served under utf | ||
@@ -61,0 +68,0 @@ var headers = { |
{ | ||
"name": "engine.io" | ||
, "version": "0.2.2" | ||
, "version": "0.3.0" | ||
, "description": "The realtime engine behind Socket.IO. Provides the foundation of a bidirectional connection between client and server" | ||
@@ -8,8 +8,10 @@ , "main": "./lib/engine.io" | ||
, "contributors": [ | ||
{ "name": "Eugen Dueck", "web": "https://github.com/EugenDueck" } | ||
{ "name": "Eugen Dueck", "web": "https://github.com/EugenDueck" }, | ||
{ "name": "Afshin Mehrabani", "web": "https://github.com/afshinm" } | ||
] | ||
, "dependencies": { | ||
"debug": "0.6.0" | ||
, "engine.io-client": "0.2.2" | ||
, "engine.io-client": "0.3.0" | ||
, "ws": "~0.4.21" | ||
, "base64id": "0.1.0" | ||
} | ||
@@ -16,0 +18,0 @@ , "devDependencies": { |
@@ -61,3 +61,3 @@ # Engine.IO: the realtime engine | ||
<script> | ||
var socket = new eio.Socket({ host: 'localhost', port: 80 }); | ||
var socket = new eio.Socket('ws://localhost/'); | ||
socket.on('open', function () { | ||
@@ -137,7 +137,5 @@ socket.on('message', function (data) { }); | ||
- **Options** | ||
- `path` (`String`) default prefix path (`/engine.io`) | ||
- `resource` (`String`): name of resource for this server (`default`). | ||
Setting a resource allows you to initialize multiple engine.io | ||
endpoints on the same host without them interfering, and without | ||
changing the `path` directly. | ||
endpoints on the same host without them interfering. | ||
- `policyFile` (`Boolean`): whether to handle policy file requests (`true`) | ||
@@ -253,2 +251,3 @@ - `destroyUpgrade` (`Boolean`): destroy unhandled upgrade requests (`true`) | ||
- `String`: a string or any object implementing `toString()`, with outgoing data | ||
- `Function`: optional, a callback executed when the message gets flushed out by the transport | ||
- **Returns** `Socket` for chaining | ||
@@ -269,2 +268,14 @@ - `close` | ||
## Debug / logging | ||
Engine.IO is powered by [debug](http://github.com/visionmedia/debug). | ||
In order to see all the debug output, run your app with the env variable | ||
`DEBUG` including the desired scope. | ||
To see the output from all of Engine.IO's debugging scopes you can use: | ||
``` | ||
DEBUG=engine* node myapp | ||
``` | ||
## Transports | ||
@@ -271,0 +282,0 @@ |
/** | ||
* Instrument. | ||
*/ | ||
var fs = require('fs'); | ||
if (process.env.DEBUG) { | ||
require.extensions['.js'] = function(mod, filename){ | ||
var js = fs.readFileSync(filename, 'utf8'); | ||
// Profiling support | ||
js = js.replace(/^ *\/\/ *(start|end): *([^\n]+)/gm, function(_, type, expr){ | ||
switch (type) { | ||
case 'start': return 'console.time(' + expr + ');'; | ||
case 'end': return 'console.timeEnd(' + expr + ');'; | ||
} | ||
}); | ||
// Debugging | ||
js = js.replace(/^ *\/\/ *debug: *([^\n,]+) *([^\n]+)?/gm, function(_, fmt, args){ | ||
fmt = fmt.replace(/"/g, '\\"'); | ||
return 'console.error(" client\033[90m ' + fmt + '\033[0m"' + (args || '') + ');'; | ||
}); | ||
js = js.replace(/^ *\/\/ *assert: ([^,]+) *, *([^\n]+)/gm, function(_, expr, msg){ | ||
return 'if (!(' + expr + ')) console.error(" client assert\033[31m %s. (%s)\033[0m", ' + msg + ', "' + expr + '");'; | ||
}); | ||
mod._compile(js, filename); | ||
}; | ||
} | ||
/** | ||
* Expose `eio` global. | ||
*/ | ||
eio = require('../index'); | ||
global.eio = require('../index'); | ||
@@ -44,3 +12,3 @@ /** | ||
eioc = require('engine.io-client'); | ||
global.eioc = require('engine.io-client'); | ||
@@ -51,3 +19,3 @@ /** | ||
request = require('superagent'); | ||
global.request = require('superagent'); | ||
@@ -58,3 +26,3 @@ /** | ||
expect = require('expect.js'); | ||
global.expect = require('expect.js'); | ||
@@ -65,3 +33,3 @@ /** | ||
listen = function (opts, fn) { | ||
global.listen = function (opts, fn) { | ||
if ('function' == typeof opts) { | ||
@@ -72,3 +40,3 @@ fn = opts; | ||
var e = eio.listen(null, opts, function () { | ||
var e = global.eio.listen(null, opts, function () { | ||
fn(e.httpServer.address().port); | ||
@@ -78,3 +46,3 @@ }); | ||
return e; | ||
} | ||
}; | ||
@@ -81,0 +49,0 @@ /** |
@@ -0,1 +1,2 @@ | ||
/*global eio,listen,request,expect*/ | ||
@@ -7,3 +8,3 @@ /** | ||
var net = require('net') | ||
, http = require('http') | ||
, http = require('http'); | ||
@@ -10,0 +11,0 @@ /** |
@@ -0,1 +1,2 @@ | ||
/*global eio,eioc,listen,request,expect*/ | ||
@@ -8,3 +9,3 @@ /** | ||
, parser = eio.parser | ||
, WebSocket = require('ws') | ||
, WebSocket = require('ws'); | ||
@@ -21,3 +22,3 @@ /** | ||
request.get('http://localhost:%d/engine.io/default/'.s(port)) | ||
.send({ transport: 'tobi' }) // no tobi transport - outrageous | ||
.query({ transport: 'tobi' }) // no tobi transport - outrageous | ||
.end(function (res) { | ||
@@ -34,3 +35,3 @@ expect(res.status).to.be(500); | ||
request.get('http://localhost:%d/engine.io/default/'.s(port)) | ||
.send({ transport: 'constructor' }) | ||
.query({ transport: 'constructor' }) | ||
.end(function (res) { | ||
@@ -46,3 +47,3 @@ expect(res.status).to.be(500); | ||
request.get('http://localhost:%d/engine.io/default/'.s(port)) | ||
.send({ transport: 'polling', sid: 'test' }) | ||
.query({ transport: 'polling', sid: 'test' }) | ||
.end(function (res) { | ||
@@ -60,3 +61,3 @@ expect(res.status).to.be(500); | ||
request.get('http://localhost:%d/engine.io/default/'.s(port)) | ||
.send({ transport: 'polling' }) | ||
.query({ transport: 'polling' }) | ||
.end(function (res) { | ||
@@ -74,3 +75,3 @@ // hack-obtain sid | ||
request.get('http://localhost:%d/engine.io/default/'.s(port)) | ||
.send({ transport: 'polling' }) | ||
.query({ transport: 'polling' }) | ||
.end(function (res) { | ||
@@ -87,3 +88,3 @@ var sid = res.text.match(/"sid":"([^"]+)"/)[1]; | ||
request.get('http://localhost:%d/engine.io/default/'.s(port)) | ||
.send({ transport: 'polling' }) | ||
.query({ transport: 'polling' }) | ||
.end(function (res) { | ||
@@ -219,3 +220,3 @@ expect(res.headers['set-cookie']).to.be(undefined); | ||
it('should trigger on server if the client does not pong', function (done) { | ||
var opts = { allowUpgrades: false, pingInterval: 5, pingTimeout: 5 } | ||
var opts = { allowUpgrades: false, pingInterval: 5, pingTimeout: 5 }; | ||
var engine = listen(opts, function (port) { | ||
@@ -234,3 +235,3 @@ var socket = new eioc.Socket('http://localhost:%d'.s(port)); | ||
it('should trigger on client if server does not meet ping timeout', function (done) { | ||
var opts = { allowUpgrades: false, pingTimeout: 10 }; | ||
var opts = { allowUpgrades: false, pingInterval: 5, pingTimeout: 5 }; | ||
var engine = listen(opts, function (port) { | ||
@@ -253,3 +254,3 @@ var socket = new eioc.Socket('ws://localhost:%d'.s(port)); | ||
var socket = new eioc.Socket('ws://localhost:%d'.s(port)) | ||
, total = 2 | ||
, total = 2; | ||
@@ -276,3 +277,3 @@ function onClose (reason, err) { | ||
var socket = new eioc.Socket('ws://localhost:%d'.s(port)) | ||
, total = 2 | ||
, total = 2; | ||
@@ -302,3 +303,3 @@ engine.on('connection', function (conn) { | ||
var socket = new eioc.Socket('ws://localhost:%d'.s(port), { transports: ['websocket'] }) | ||
, total = 2 | ||
, total = 2; | ||
@@ -327,3 +328,3 @@ engine.on('connection', function (conn) { | ||
var socket = new eioc.Socket('ws://localhost:%d'.s(port)) | ||
, total = 2 | ||
, total = 2; | ||
@@ -354,3 +355,3 @@ engine.on('connection', function (conn) { | ||
var socket = new eioc.Socket('ws://localhost:%d'.s(port), { transports: ['websocket'] }) | ||
, total = 2 | ||
, total = 2; | ||
@@ -390,7 +391,7 @@ engine.on('connection', function (conn) { | ||
it('should trigger if a poll request is ongoing and the underlying' | ||
+ ' socket closes, as in a browser tab close', function (done) { | ||
it('should trigger if a poll request is ongoing and the underlying' + | ||
' socket closes, as in a browser tab close', function (done) { | ||
var engine = listen({ allowUpgrades: false }, function (port) { | ||
var socket = new eioc.Socket('ws://localhost:%d'.s(port)) | ||
, serverSocket | ||
, serverSocket; | ||
@@ -436,3 +437,3 @@ engine.on('connection', function(socket){ | ||
return oldRequest.apply(this, arguments); | ||
} | ||
}; | ||
@@ -446,3 +447,3 @@ engine.on('connection', function(socket){ | ||
var socket = new eioc.Socket('ws://localhost:%d'.s(port)) | ||
var socket = new eioc.Socket('ws://localhost:%d'.s(port)); | ||
socket.on('open', function(){ | ||
@@ -458,2 +459,108 @@ socket.send('test'); | ||
}); | ||
it('should not trigger early with connection `ping timeout` after post handshake timeout', function (done) { | ||
// First timeout should trigger after `pingInterval + pingTimeout`, not just `pingTimeout`. | ||
var opts = { allowUpgrades: false, pingInterval: 300, pingTimeout: 100 }; | ||
var engine = listen(opts, function (port) { | ||
var socket = new eioc.Socket('ws://localhost:%d'.s(port)); | ||
var clientCloseReason = null; | ||
socket.on('handshake', function() { | ||
socket.onPacket = function(){}; | ||
}); | ||
socket.on('open', function () { | ||
socket.on('close', function (reason) { | ||
clientCloseReason = reason; | ||
}); | ||
}); | ||
setTimeout(function() { | ||
expect(clientCloseReason).to.be(null); | ||
done(); | ||
}, 200); | ||
}); | ||
}); | ||
it('should not trigger early with connection `ping timeout` after post ping timeout', function (done) { | ||
// Ping timeout should trigger after `pingInterval + pingTimeout`, not just `pingTimeout`. | ||
var opts = { allowUpgrades: false, pingInterval: 300, pingTimeout: 100 }; | ||
var engine = listen(opts, function (port) { | ||
var socket = new eioc.Socket('ws://localhost:%d'.s(port)); | ||
var clientCloseReason = null; | ||
engine.on('connection', function(conn){ | ||
conn.on('heartbeat', function() { | ||
conn.onPacket = function(){}; | ||
}); | ||
}); | ||
socket.on('open', function () { | ||
socket.on('close', function (reason) { | ||
clientCloseReason = reason; | ||
}); | ||
}); | ||
setTimeout(function() { | ||
expect(clientCloseReason).to.be(null); | ||
done(); | ||
}, 300); | ||
}); | ||
}); | ||
it('should trigger early with connection `transport close` after missing pong', function (done) { | ||
// Ping timeout should trigger after `pingInterval + pingTimeout`, not just `pingTimeout`. | ||
var opts = { allowUpgrades: false, pingInterval: 300, pingTimeout: 100 }; | ||
var engine = listen(opts, function (port) { | ||
var socket = new eioc.Socket('ws://localhost:%d'.s(port)); | ||
var clientCloseReason = null; | ||
socket.on('open', function () { | ||
socket.on('close', function (reason) { | ||
clientCloseReason = reason; | ||
}); | ||
}); | ||
engine.on('connection', function(conn){ | ||
conn.on('heartbeat', function() { | ||
setTimeout(function() { | ||
conn.close(); | ||
}, 20); | ||
setTimeout(function() { | ||
expect(clientCloseReason).to.be("transport close"); | ||
done(); | ||
}, 150); | ||
}); | ||
}); | ||
}); | ||
}); | ||
it('should trigger with connection `ping timeout` after `pingInterval + pingTimeout`', function (done) { | ||
var opts = { allowUpgrades: false, pingInterval: 30, pingTimeout: 10 }; | ||
var engine = listen(opts, function (port) { | ||
var socket = new eioc.Socket('ws://localhost:%d'.s(port)); | ||
var clientCloseReason = null; | ||
socket.on('open', function () { | ||
socket.on('close', function (reason) { | ||
clientCloseReason = reason; | ||
}); | ||
}); | ||
engine.on('connection', function(conn){ | ||
conn.once('heartbeat', function() { | ||
setTimeout(function() { | ||
socket.onPacket = function(){}; | ||
expect(clientCloseReason).to.be(null); | ||
}, 15); | ||
setTimeout(function() { | ||
expect(clientCloseReason).to.be(null); | ||
}, 35); | ||
setTimeout(function() { | ||
expect(clientCloseReason).to.be("ping timeout"); | ||
done(); | ||
}, 50); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); | ||
@@ -481,3 +588,3 @@ | ||
, expected = ['a', 'b', 'c'] | ||
, i = 0 | ||
, i = 0; | ||
@@ -556,3 +663,4 @@ engine.on('connection', function (conn) { | ||
, expected = ['a', 'b', 'c'] | ||
, i = 0 | ||
, i = 0; | ||
engine.on('connection', function (conn) { | ||
@@ -574,2 +682,3 @@ conn.send('a'); | ||
}); | ||
socket.on('open', function () { | ||
@@ -616,2 +725,146 @@ socket.on('message', function (msg) { | ||
describe('send', function() { | ||
describe('callback', function() { | ||
it('should execute when message sent (polling)', function (done) { | ||
var engine = listen({ allowUpgrades: false }, function (port) { | ||
var socket = new eioc.Socket('ws://localhost:%d'.s(port), { transports: ['polling'] }); | ||
var i = 0; | ||
var j = 0; | ||
engine.on('connection', function (conn) { | ||
conn.send('a', function (transport) { | ||
i++; | ||
}); | ||
}); | ||
socket.on('open', function () { | ||
socket.on('message', function (msg) { | ||
j++; | ||
}); | ||
}); | ||
setTimeout(function() { | ||
expect(i).to.be(j); | ||
done(); | ||
}, 10); | ||
}); | ||
}); | ||
it('should execute when message sent (websocket)', function (done) { | ||
var engine = listen({ allowUpgrades: false }, function (port) { | ||
var socket = new eioc.Socket('ws://localhost:%d'.s(port), { transports: ['websocket'] }); | ||
var i = 0; | ||
var j = 0; | ||
engine.on('connection', function (conn) { | ||
conn.send('a', function (transport) { | ||
i++; | ||
}); | ||
}); | ||
socket.on('open', function () { | ||
socket.on('message', function (msg) { | ||
j++; | ||
}); | ||
}); | ||
setTimeout(function () { | ||
expect(i).to.be(j); | ||
done(); | ||
}, 10); | ||
}); | ||
}); | ||
it('should execute once for each send', function (done) { | ||
var engine = listen(function (port) { | ||
var socket = new eioc.Socket('ws://localhost:%d'.s(port)); | ||
var i = 0; | ||
var ic = 0; | ||
var j = 0; | ||
var jc = 0; | ||
engine.on('connection', function (conn) { | ||
conn.send('b', function (transport) { | ||
jc++; | ||
}); | ||
conn.send('a', function (transport) { | ||
ic++; | ||
}); | ||
}); | ||
socket.on('open', function () { | ||
socket.on('message', function (msg) { | ||
if (msg == 'a') { | ||
i++; | ||
} else if (msg == 'b') { | ||
j++; | ||
} | ||
}); | ||
}); | ||
setTimeout(function () { | ||
expect(i).to.be(ic); | ||
expect(j).to.be(jc); | ||
done(); | ||
}, 100); | ||
}); | ||
}); | ||
it('should execute in multipart packet', function (done) { | ||
var engine = listen(function (port) { | ||
var socket = new eioc.Socket('ws://localhost:%d'.s(port)); | ||
var i = 0; | ||
var j = 0; | ||
engine.on('connection', function (conn) { | ||
conn.send('b', function (transport) { | ||
i++; | ||
}); | ||
conn.send('a', function (transport) { | ||
i++; | ||
}); | ||
}); | ||
socket.on('open', function () { | ||
socket.on('message', function (msg) { | ||
j++; | ||
}); | ||
}); | ||
setTimeout(function () { | ||
expect(i).to.be(j); | ||
done(); | ||
}, 200); | ||
}); | ||
}); | ||
it('should clean callback references when socket gets closed with pending callbacks', function (done) { | ||
var engine = listen({ allowUpgrades: false }, function (port) { | ||
var socket = new eioc.Socket('ws://localhost:%d'.s(port), { transports: ['polling'] }); | ||
engine.on('connection', function (conn) { | ||
socket.transport.on('pollComplete', function () { | ||
conn.send('a', function (transport) { | ||
done(new Error('Test invalidation')); | ||
}); | ||
if (!conn.writeBuffer.length) { | ||
done(new Error('Test invalidation')); | ||
} | ||
// force to close the socket when we have one or more packet(s) in buffer | ||
socket.close(); | ||
}); | ||
conn.on('close', function (reason) { | ||
expect(conn.packetsFn).to.be.empty(); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); | ||
describe('upgrade', function () { | ||
@@ -618,0 +871,0 @@ it('should upgrade', function (done) { |
Sorry, the diff of this file is not supported yet
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
89083
2318
499
4
4
+ Addedbase64id@0.1.0
+ Addedbase64id@0.1.0(transitive)
+ Addedengine.io-client@0.3.0(transitive)
+ Addedxmlhttprequest@1.5.0(transitive)
- Removedengine.io-client@0.2.2(transitive)
- Removedxmlhttprequest@1.4.2(transitive)
Updatedengine.io-client@0.3.0