From de2c561e4564efeb78f1bdb1ba39ef81b2822cb3 Mon Sep 17 00:00:00 2001 From: GK Date: Sun, 9 Feb 2014 12:09:57 -0800 Subject: [PATCH 1/4] made parseUri its own node module, change parseUri calls and tests --- engine.io.js | 106 +++++++++++++++++++++++++++++--------------------- lib/socket.js | 3 +- lib/util.js | 26 ------------- package.json | 3 +- test/util.js | 37 ------------------ 5 files changed, 65 insertions(+), 110 deletions(-) diff --git a/engine.io.js b/engine.io.js index 15b7e5ac..c9b4883f 100644 --- a/engine.io.js +++ b/engine.io.js @@ -64,6 +64,7 @@ var Emitter = require('./emitter'); var debug = require('debug')('engine.io-client:socket'); var index = require('indexof'); var parser = require('engine.io-parser'); +var parseuri = require('parseuri'); /** * Module exports. @@ -104,7 +105,7 @@ function Socket(uri, opts){ } if (uri) { - uri = util.parseUri(uri); + uri = parseuri(uri); opts.host = uri.host; opts.secure = uri.protocol == 'https' || uri.protocol == 'wss'; opts.port = uri.port; @@ -365,7 +366,7 @@ Socket.prototype.onOpen = function () { this.flush(); // we check for `readyState` in case an `open` - // listener alreay closed the socket + // listener already closed the socket if ('open' == this.readyState && this.upgrade && this.transport.pause) { debug('starting upgrade probes'); for (var i = 0, l = this.upgrades.length; i < l; i++) { @@ -617,17 +618,14 @@ Socket.prototype.onClose = function (reason, desc) { this.transport.removeAllListeners(); // set ready state - var prev = this.readyState; this.readyState = 'closed'; // clear session id this.id = null; - // emit events - if (prev == 'open') { - this.emit('close', reason, desc); - this.onclose && this.onclose.call(this); - } + // emit close event + this.emit('close', reason, desc); + this.onclose && this.onclose.call(this); } }; @@ -647,7 +645,7 @@ Socket.prototype.filterUpgrades = function (upgrades) { return filteredUpgrades; }; -},{"./emitter":2,"./transport":5,"./transports":7,"./util":12,"debug":14,"engine.io-parser":16,"global":19,"indexof":21}],5:[function(require,module,exports){ +},{"./emitter":2,"./transport":5,"./transports":7,"./util":12,"debug":14,"engine.io-parser":16,"global":19,"indexof":21,"parseuri":22}],5:[function(require,module,exports){ /** * Module dependencies. @@ -1363,7 +1361,7 @@ var global = require('global'); * Obfuscated key for Blue Coat. */ -var xobject = global[['Active'].concat('Object').join('X')]; +var hasAttachEvent = global.document && global.document.attachEvent; /** * Empty function @@ -1536,7 +1534,7 @@ Request.prototype.create = function(){ return; } - if (xobject) { + if (hasAttachEvent) { this.index = Request.requestsCount++; Request.requests[this.index] = this; } @@ -1582,8 +1580,7 @@ Request.prototype.onError = function(err){ */ Request.prototype.cleanup = function(){ - // !this.xhr is used to check both undefined and null, see issue #180 - if (!this.xhr) { + if ('undefined' == typeof this.xhr ) { return; } // xmlhttprequest @@ -1593,7 +1590,7 @@ Request.prototype.cleanup = function(){ this.xhr.abort(); } catch(e) {} - if (xobject) { + if (hasAttachEvent) { delete Request.requests[this.index]; } @@ -1610,7 +1607,12 @@ Request.prototype.abort = function(){ this.cleanup(); }; -if (xobject) { +/** + * Cleanup is needed for old versions of IE + * that leak memory unless we abort request before unload. + */ + +if (hasAttachEvent) { Request.requestsCount = 0; Request.requests = {}; @@ -1863,11 +1865,18 @@ Polling.prototype.uri = function(){ */ var Transport = require('../transport'); -var WebSocket = require('ws'); var parser = require('engine.io-parser'); var util = require('../util'); var debug = require('debug')('engine.io-client:websocket'); +/** + * `ws` exposes a WebSocket-compatible interface in + * Node, or the `WebSocket` or `MozWebSocket` globals + * in the browser. + */ + +var WebSocket = require('ws'); + /** * Module exports. */ @@ -2055,7 +2064,7 @@ WS.prototype.check = function(){ return !!WebSocket && !('__initialize' in WebSocket && this.name === WS.prototype.name); }; -},{"../transport":5,"../util":12,"debug":14,"engine.io-parser":16,"global":19,"ws":22}],12:[function(require,module,exports){ +},{"../transport":5,"../util":12,"debug":14,"engine.io-parser":16,"global":19,"ws":23}],12:[function(require,module,exports){ var global = require('global'); @@ -2214,32 +2223,6 @@ exports.ua.ios6 = exports.ua.ios && /OS 6_/.test(navigator.userAgent); exports.ua.chromeframe = Boolean(global.externalHost); -/** - * Parses an URI - * - * @author Steven Levithan (MIT license) - * @api private - */ - -var re = /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/; - -var parts = [ - 'source', 'protocol', 'authority', 'userInfo', 'user', 'password', 'host' - , 'port', 'relative', 'path', 'directory', 'file', 'query', 'anchor' -]; - -exports.parseUri = function (str) { - var m = re.exec(str || '') - , uri = {} - , i = 14; - - while (i--) { - uri[parts[i]] = m[i] || ''; - } - - return uri; -}; - /** * Compiles a querystring * @@ -2821,8 +2804,14 @@ var global = require('global'); * - https://github.com/Modernizr/Modernizr/blob/master/feature-detects/cors.js */ -module.exports = 'XMLHttpRequest' in global && - 'withCredentials' in new global.XMLHttpRequest(); +try { + module.exports = 'XMLHttpRequest' in global && + 'withCredentials' in new global.XMLHttpRequest(); +} catch (err) { + // if XMLHttp support is disabled in IE then it will throw + // when trying to create + module.exports = false; +} },{"global":19}],21:[function(require,module,exports){ @@ -2836,6 +2825,33 @@ module.exports = function(arr, obj){ return -1; }; },{}],22:[function(require,module,exports){ +/** + * Parses an URI + * + * @author Steven Levithan (MIT license) + * @api private + */ + +var re = /^(?:(?![^:@]+:[^:@\/]*@)(http|https|ws|wss):\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?((?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}|[^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/; + +var parts = [ + 'source', 'protocol', 'authority', 'userInfo', 'user', 'password', 'host' + , 'port', 'relative', 'path', 'directory', 'file', 'query', 'anchor' +]; + +module.exports = function parseuri(str) { + var m = re.exec(str || '') + , uri = {} + , i = 14; + + while (i--) { + uri[parts[i]] = m[i] || ''; + } + + return uri; +}; + +},{}],23:[function(require,module,exports){ /** * Module dependencies. diff --git a/lib/socket.js b/lib/socket.js index f728a468..d11cebb1 100644 --- a/lib/socket.js +++ b/lib/socket.js @@ -8,6 +8,7 @@ var Emitter = require('./emitter'); var debug = require('debug')('engine.io-client:socket'); var index = require('indexof'); var parser = require('engine.io-parser'); +var parseuri = require('parseuri'); /** * Module exports. @@ -48,7 +49,7 @@ function Socket(uri, opts){ } if (uri) { - uri = util.parseUri(uri); + uri = parseuri(uri); opts.host = uri.host; opts.secure = uri.protocol == 'https' || uri.protocol == 'wss'; opts.port = uri.port; diff --git a/lib/util.js b/lib/util.js index 39051671..b1fdb1c6 100644 --- a/lib/util.js +++ b/lib/util.js @@ -156,32 +156,6 @@ exports.ua.ios6 = exports.ua.ios && /OS 6_/.test(navigator.userAgent); exports.ua.chromeframe = Boolean(global.externalHost); -/** - * Parses an URI - * - * @author Steven Levithan (MIT license) - * @api private - */ - -var re = /^(?:(?![^:@]+:[^:@\/]*@)(http|https|ws|wss):\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?((?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}|[^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/; - -var parts = [ - 'source', 'protocol', 'authority', 'userInfo', 'user', 'password', 'host' - , 'port', 'relative', 'path', 'directory', 'file', 'query', 'anchor' -]; - -exports.parseUri = function (str) { - var m = re.exec(str || '') - , uri = {} - , i = 14; - - while (i--) { - uri[parts[i]] = m[i] || ''; - } - - return uri; -}; - /** * Compiles a querystring * diff --git a/package.json b/package.json index 48c67f38..95edc15e 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,8 @@ "emitter": "http://github.com/component/emitter/archive/1.0.1.tar.gz", "indexof": "0.0.1", "engine.io-parser": "0.3.0", - "debug": "0.7.4" + "debug": "0.7.4", + "parseuri": "0.0.2" }, "devDependencies": { "zuul": "1.5.2", diff --git a/test/util.js b/test/util.js index ca475dc6..88dfda8e 100644 --- a/test/util.js +++ b/test/util.js @@ -14,43 +14,6 @@ var util = eio.util describe('util', function () { - it('should parse an uri', function () { - var http = util.parseUri('http://google.com') - , https = util.parseUri('https://www.google.com:80') - , query = util.parseUri('google.com:8080/foo/bar?foo=bar') - , localhost = util.parseUri('localhost:8080') - , ipv6 = util.parseUri('2001:0db8:85a3:0042:1000:8a2e:0370:7334') - , ipv6short = util.parseUri('2001:db8:85a3:42:1000:8a2e:370:7334') - , ipv6port = util.parseUri('2001:db8:85a3:42:1000:8a2e:370:7334:80') - , ipv6abbrev = util.parseUri('2001::7334:a:80') - - expect(http.protocol).to.be('http'); - expect(http.port).to.be(''); - expect(http.host).to.be('google.com'); - expect(https.protocol).to.be('https'); - expect(https.port).to.be('80'); - expect(https.host).to.be('www.google.com'); - expect(query.port).to.be('8080'); - expect(query.query).to.be('foo=bar'); - expect(query.path).to.be('/foo/bar'); - expect(query.relative).to.be('/foo/bar?foo=bar'); - expect(localhost.protocol).to.be(''); - expect(localhost.host).to.be('localhost'); - expect(localhost.port).to.be('8080'); - expect(ipv6.protocol).to.be(''); - expect(ipv6.host).to.be('2001:0db8:85a3:0042:1000:8a2e:0370:7334'); - expect(ipv6.port).to.be(''); - expect(ipv6short.protocol).to.be(''); - expect(ipv6short.host).to.be('2001:db8:85a3:42:1000:8a2e:370:7334'); - expect(ipv6short.port).to.be(''); - expect(ipv6port.protocol).to.be(''); - expect(ipv6port.host).to.be('2001:db8:85a3:42:1000:8a2e:370:7334'); - expect(ipv6port.port).to.be('80'); - expect(ipv6abbrev.protocol).to.be(''); - expect(ipv6abbrev.host).to.be('2001::7334:a:80'); - expect(ipv6abbrev.port).to.be(''); - }); - it('should construct a query string from an object', function () { expect(util.qs({ a: 'b' })).to.be('a=b'); expect(util.qs({ a: 'b', c: 'd' })).to.be('a=b&c=d'); From bc793d30fc5acd439eca6117bf42c73424f0196b Mon Sep 17 00:00:00 2001 From: GK Date: Thu, 20 Feb 2014 14:55:04 -0500 Subject: [PATCH 2/4] checked out build file --- engine.io.js | 106 ++++++++++++++++++++++----------------------------- 1 file changed, 45 insertions(+), 61 deletions(-) diff --git a/engine.io.js b/engine.io.js index c9b4883f..15b7e5ac 100644 --- a/engine.io.js +++ b/engine.io.js @@ -64,7 +64,6 @@ var Emitter = require('./emitter'); var debug = require('debug')('engine.io-client:socket'); var index = require('indexof'); var parser = require('engine.io-parser'); -var parseuri = require('parseuri'); /** * Module exports. @@ -105,7 +104,7 @@ function Socket(uri, opts){ } if (uri) { - uri = parseuri(uri); + uri = util.parseUri(uri); opts.host = uri.host; opts.secure = uri.protocol == 'https' || uri.protocol == 'wss'; opts.port = uri.port; @@ -366,7 +365,7 @@ Socket.prototype.onOpen = function () { this.flush(); // we check for `readyState` in case an `open` - // listener already closed the socket + // listener alreay closed the socket if ('open' == this.readyState && this.upgrade && this.transport.pause) { debug('starting upgrade probes'); for (var i = 0, l = this.upgrades.length; i < l; i++) { @@ -618,14 +617,17 @@ Socket.prototype.onClose = function (reason, desc) { this.transport.removeAllListeners(); // set ready state + var prev = this.readyState; this.readyState = 'closed'; // clear session id this.id = null; - // emit close event - this.emit('close', reason, desc); - this.onclose && this.onclose.call(this); + // emit events + if (prev == 'open') { + this.emit('close', reason, desc); + this.onclose && this.onclose.call(this); + } } }; @@ -645,7 +647,7 @@ Socket.prototype.filterUpgrades = function (upgrades) { return filteredUpgrades; }; -},{"./emitter":2,"./transport":5,"./transports":7,"./util":12,"debug":14,"engine.io-parser":16,"global":19,"indexof":21,"parseuri":22}],5:[function(require,module,exports){ +},{"./emitter":2,"./transport":5,"./transports":7,"./util":12,"debug":14,"engine.io-parser":16,"global":19,"indexof":21}],5:[function(require,module,exports){ /** * Module dependencies. @@ -1361,7 +1363,7 @@ var global = require('global'); * Obfuscated key for Blue Coat. */ -var hasAttachEvent = global.document && global.document.attachEvent; +var xobject = global[['Active'].concat('Object').join('X')]; /** * Empty function @@ -1534,7 +1536,7 @@ Request.prototype.create = function(){ return; } - if (hasAttachEvent) { + if (xobject) { this.index = Request.requestsCount++; Request.requests[this.index] = this; } @@ -1580,7 +1582,8 @@ Request.prototype.onError = function(err){ */ Request.prototype.cleanup = function(){ - if ('undefined' == typeof this.xhr ) { + // !this.xhr is used to check both undefined and null, see issue #180 + if (!this.xhr) { return; } // xmlhttprequest @@ -1590,7 +1593,7 @@ Request.prototype.cleanup = function(){ this.xhr.abort(); } catch(e) {} - if (hasAttachEvent) { + if (xobject) { delete Request.requests[this.index]; } @@ -1607,12 +1610,7 @@ Request.prototype.abort = function(){ this.cleanup(); }; -/** - * Cleanup is needed for old versions of IE - * that leak memory unless we abort request before unload. - */ - -if (hasAttachEvent) { +if (xobject) { Request.requestsCount = 0; Request.requests = {}; @@ -1865,18 +1863,11 @@ Polling.prototype.uri = function(){ */ var Transport = require('../transport'); +var WebSocket = require('ws'); var parser = require('engine.io-parser'); var util = require('../util'); var debug = require('debug')('engine.io-client:websocket'); -/** - * `ws` exposes a WebSocket-compatible interface in - * Node, or the `WebSocket` or `MozWebSocket` globals - * in the browser. - */ - -var WebSocket = require('ws'); - /** * Module exports. */ @@ -2064,7 +2055,7 @@ WS.prototype.check = function(){ return !!WebSocket && !('__initialize' in WebSocket && this.name === WS.prototype.name); }; -},{"../transport":5,"../util":12,"debug":14,"engine.io-parser":16,"global":19,"ws":23}],12:[function(require,module,exports){ +},{"../transport":5,"../util":12,"debug":14,"engine.io-parser":16,"global":19,"ws":22}],12:[function(require,module,exports){ var global = require('global'); @@ -2223,6 +2214,32 @@ exports.ua.ios6 = exports.ua.ios && /OS 6_/.test(navigator.userAgent); exports.ua.chromeframe = Boolean(global.externalHost); +/** + * Parses an URI + * + * @author Steven Levithan (MIT license) + * @api private + */ + +var re = /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/; + +var parts = [ + 'source', 'protocol', 'authority', 'userInfo', 'user', 'password', 'host' + , 'port', 'relative', 'path', 'directory', 'file', 'query', 'anchor' +]; + +exports.parseUri = function (str) { + var m = re.exec(str || '') + , uri = {} + , i = 14; + + while (i--) { + uri[parts[i]] = m[i] || ''; + } + + return uri; +}; + /** * Compiles a querystring * @@ -2804,14 +2821,8 @@ var global = require('global'); * - https://github.com/Modernizr/Modernizr/blob/master/feature-detects/cors.js */ -try { - module.exports = 'XMLHttpRequest' in global && - 'withCredentials' in new global.XMLHttpRequest(); -} catch (err) { - // if XMLHttp support is disabled in IE then it will throw - // when trying to create - module.exports = false; -} +module.exports = 'XMLHttpRequest' in global && + 'withCredentials' in new global.XMLHttpRequest(); },{"global":19}],21:[function(require,module,exports){ @@ -2825,33 +2836,6 @@ module.exports = function(arr, obj){ return -1; }; },{}],22:[function(require,module,exports){ -/** - * Parses an URI - * - * @author Steven Levithan (MIT license) - * @api private - */ - -var re = /^(?:(?![^:@]+:[^:@\/]*@)(http|https|ws|wss):\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?((?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}|[^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/; - -var parts = [ - 'source', 'protocol', 'authority', 'userInfo', 'user', 'password', 'host' - , 'port', 'relative', 'path', 'directory', 'file', 'query', 'anchor' -]; - -module.exports = function parseuri(str) { - var m = re.exec(str || '') - , uri = {} - , i = 14; - - while (i--) { - uri[parts[i]] = m[i] || ''; - } - - return uri; -}; - -},{}],23:[function(require,module,exports){ /** * Module dependencies. From 3011d31aa2e39425b7308d898ab2c30d2f17d912 Mon Sep 17 00:00:00 2001 From: GK Date: Sat, 22 Feb 2014 18:51:09 -0500 Subject: [PATCH 3/4] made parseJSON its own module, update calls --- .gitignore | 1 + lib/socket.js | 3 ++- lib/util.js | 33 --------------------------------- package.json | 3 ++- 4 files changed, 5 insertions(+), 35 deletions(-) diff --git a/.gitignore b/.gitignore index 47d61980..a43605ca 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ build components /coverage npm-debug.log +engine.io.js diff --git a/lib/socket.js b/lib/socket.js index d11cebb1..dc8ab131 100644 --- a/lib/socket.js +++ b/lib/socket.js @@ -9,6 +9,7 @@ var debug = require('debug')('engine.io-client:socket'); var index = require('indexof'); var parser = require('engine.io-parser'); var parseuri = require('parseuri'); +var parsejson = require('parsejson'); /** * Module exports. @@ -336,7 +337,7 @@ Socket.prototype.onPacket = function (packet) { switch (packet.type) { case 'open': - this.onHandshake(util.parseJSON(packet.data)); + this.onHandshake(parsejson(packet.data)); break; case 'pong': diff --git a/lib/util.js b/lib/util.js index b1fdb1c6..a2310b64 100644 --- a/lib/util.js +++ b/lib/util.js @@ -76,39 +76,6 @@ if ('undefined' != typeof window) { }); } -/** - * JSON parse. - * - * @see Based on jQuery#parseJSON (MIT) and JSON2 - * @api private - */ - -var rvalidchars = /^[\],:{}\s]*$/; -var rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g; -var rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g; -var rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g; -var rtrimLeft = /^\s+/; -var rtrimRight = /\s+$/; - -exports.parseJSON = function (data) { - if ('string' != typeof data || !data) { - return null; - } - - data = data.replace(rtrimLeft, '').replace(rtrimRight, ''); - - // Attempt to parse using the native JSON parser first - if (global.JSON && JSON.parse) { - return JSON.parse(data); - } - - if (rvalidchars.test(data.replace(rvalidescape, '@') - .replace(rvalidtokens, ']') - .replace(rvalidbraces, ''))) { - return (new Function('return ' + data))(); - } -}; - /** * UA / engines detection namespace. * diff --git a/package.json b/package.json index 95edc15e..78c95aa6 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,8 @@ "indexof": "0.0.1", "engine.io-parser": "0.3.0", "debug": "0.7.4", - "parseuri": "0.0.2" + "parseuri": "0.0.2", + "parsejson": "0.0.1" }, "devDependencies": { "zuul": "1.5.2", From 6737a83d993d8bfbd65a11f7041ad9595cc2df7a Mon Sep 17 00:00:00 2001 From: GK Date: Thu, 6 Mar 2014 19:49:59 -0500 Subject: [PATCH 4/4] fixed indentation --- .gitignore | 1 - package.json | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index a43605ca..47d61980 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,3 @@ build components /coverage npm-debug.log -engine.io.js diff --git a/package.json b/package.json index 78c95aa6..db92ba43 100644 --- a/package.json +++ b/package.json @@ -30,8 +30,8 @@ "indexof": "0.0.1", "engine.io-parser": "0.3.0", "debug": "0.7.4", - "parseuri": "0.0.2", - "parsejson": "0.0.1" + "parseuri": "0.0.2", + "parsejson": "0.0.1" }, "devDependencies": { "zuul": "1.5.2",