[Pkg-javascript-commits] [sockjs-client] 91/350: Basic tests passing
tonnerre at ancient-solutions.com
tonnerre at ancient-solutions.com
Fri Aug 5 01:03:46 UTC 2016
This is an automated email from the git hooks/post-receive script.
tonnerre-guest pushed a commit to branch upstream
in repository sockjs-client.
commit 6bd16c0b58e3f53edd373b4219687500f3caba5d
Author: Bryce Kahle <bkahle at gmail.com>
Date: Tue Oct 7 22:22:16 2014 -0400
Basic tests passing
---
.eslintrc | 18 ++
.travis.yml | 2 +-
gulpfile.js | 27 ++-
lib/abstract-xhr.js | 14 +-
lib/closeevent.js | 2 +-
lib/entry.js | 23 +++
lib/{ => error}/invalidaccesserror.js | 0
lib/{ => error}/invalidstateerror.js | 0
lib/{ => error}/securityerror.js | 0
lib/info-receiver-fake.js | 19 --
lib/info-receiver-iframe.js | 2 +
lib/info-receiver.js | 54 ++++--
lib/main.js | 193 ++++++++++++++++++---
lib/{ => polyfills}/event.js | 0
lib/{ => polyfills}/eventtarget.js | 12 +-
lib/{ => polyfills}/location.js | 1 +
lib/protocols.js | 48 -----
lib/shims.js | 25 +++
lib/simpleevent.js | 23 +--
lib/trans-iframe.js | 14 +-
lib/trans-message-event.js | 15 ++
lib/trans-receiver-eventsource.js | 6 +-
lib/trans-receiver-htmlfile.js | 5 +-
lib/trans-receiver-xhr.js | 5 +-
.../iframe-eventsource.js} | 2 +-
.../iframe-htmlfile.js} | 2 +-
.../iframe-xhr-polling.js} | 2 +-
.../jsonp-polling.js} | 5 +-
lib/{trans-websocket.js => transport/websocket.js} | 29 +++-
.../xdr-polling.js} | 8 +-
.../xdr-streaming.js} | 14 +-
.../xhr-polling.js} | 10 +-
.../xhr-streaming.js} | 14 +-
lib/transports.js | 27 +++
lib/utils.js | 30 ++--
lib/xdr.js | 4 +-
lib/xhr-cors.js | 4 +-
lib/xhr-fake.js | 17 ++
lib/xhr-local.js | 2 +-
package.json | 8 +-
tests/main.js | 23 +--
tests/transports.js | 39 +++++
42 files changed, 529 insertions(+), 219 deletions(-)
diff --git a/.eslintrc b/.eslintrc
new file mode 100644
index 0000000..f7c6371
--- /dev/null
+++ b/.eslintrc
@@ -0,0 +1,18 @@
+{
+ "env": {
+ "node": true,
+ "browser": true
+ },
+ "rules": {
+ "consistent-this": [2, "self"],
+ "quotes": [1, "single", "avoid-escape"],
+ "no-space-before-semi": [0],
+ "no-underscore-dangle": [0]
+ },
+ "globals": {
+ "XDomainRequest": true,
+ "XMLHttpRequest": true,
+ "EventSource": true,
+ "ActiveXObject": true
+ }
+}
diff --git a/.travis.yml b/.travis.yml
index 6ef9762..4b002ad 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -2,7 +2,7 @@ language: node_js
node_js:
- '0.10'
before_script:
- - "gulp test"
+ - "gulp testbundle"
script:
- '[ "${TRAVIS_PULL_REQUEST}" = "false" ] && npm test || false'
addons:
diff --git a/gulpfile.js b/gulpfile.js
index 0487098..3ccaa6c 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -6,12 +6,31 @@ var gulp = require('gulp')
, mold = require('mold-source-map')
, source = require('vinyl-source-stream')
, path = require('path')
- , jsRoot = path.join(__dirname, 'lib')
+ , mocha = require('gulp-mocha')
+ , eslint = require('gulp-eslint')
, pkg = require('./package.json')
+ ;
+
+var jsRoot = path.join(__dirname, 'lib')
, libName = 'sockjs-' + pkg.version
;
-gulp.task('test', function() {
+gulp.task('test', function () {
+ gulp.src('tests/main.js', {read: false})
+ .pipe(mocha());
+});
+
+gulp.task('eslint', function () {
+ gulp.src(['lib/**/*.js', '!lib/sockjs.js'])
+ .pipe(eslint())
+ .pipe(eslint.format());
+});
+
+gulp.task('watch', function () {
+ gulp.watch('tests/*.js', ['test']);
+});
+
+gulp.task('testbundle', function() {
browserify('./lib/sockjs.js')
.bundle({
standalone: 'SockJS'
@@ -48,7 +67,7 @@ gulp.task('browserify:min', function () {
.plugin('minifyify', {
map: libName + '.min.js.map'
, compressPath: jsRoot
- , output: './build/'+ libName + '.min.js.map'
+ , output: './build/' + libName + '.min.js.map'
})
.bundle({
standalone: 'SockJS'
@@ -56,4 +75,4 @@ gulp.task('browserify:min', function () {
.pipe(source(libName + '.min.js'))
.pipe(gulp.dest('./build/'))
;
-});
\ No newline at end of file
+});
diff --git a/lib/abstract-xhr.js b/lib/abstract-xhr.js
index f5dc3a2..de79385 100644
--- a/lib/abstract-xhr.js
+++ b/lib/abstract-xhr.js
@@ -5,16 +5,12 @@ var EventEmitter = require('events').EventEmitter
, utils = require('./utils')
;
-function AbstractXHRObject() {
-}
-
-util.inherits(AbstractXHRObject, EventEmitter);
-
-AbstractXHRObject.prototype._start = function(method, url, payload, opts) {
+function AbstractXHRObject(method, url, payload, opts) {
var self = this;
+ EventEmitter.call(this);
try {
- this.xhr = new XMLHttpRequest();
+ this.xhr = new global.XMLHttpRequest();
} catch(x) {}
if (!this.xhr) {
@@ -88,7 +84,9 @@ AbstractXHRObject.prototype._start = function(method, url, payload, opts) {
}
};
self.xhr.send(payload);
-};
+}
+
+util.inherits(AbstractXHRObject, EventEmitter);
AbstractXHRObject.prototype._cleanup = function(abort) {
if (!this.xhr) {
diff --git a/lib/closeevent.js b/lib/closeevent.js
index 31beb6b..de9a51b 100644
--- a/lib/closeevent.js
+++ b/lib/closeevent.js
@@ -1,7 +1,7 @@
'use strict';
var util = require('util')
- , Event = require('./event')
+ , Event = require('./polyfills/event')
;
function CloseEvent() {
diff --git a/lib/entry.js b/lib/entry.js
new file mode 100644
index 0000000..1591a96
--- /dev/null
+++ b/lib/entry.js
@@ -0,0 +1,23 @@
+'use strict';
+
+var browserTransports = [
+ // streaming transports
+ require('./transport/websocket')
+, require('./transport/xdr-streaming')
+, require('./transport/xhr-streaming')
+, require('./transport/iframe-eventsource')
+
+ // polling transports
+, require('./transport/iframe-htmlfile')
+, require('./transport/xdr-polling')
+, require('./transport/xhr-polling')
+, require('./transport/iframe-xhr-polling')
+, require('./transport/jsonp-polling')
+];
+
+var nodeTransports = [
+ require('./transport/websocket')
+];
+
+var transports = typeof window !== 'undefined' ? browserTransports : nodeTransports;
+module.exports = require('./main')(transports);
diff --git a/lib/invalidaccesserror.js b/lib/error/invalidaccesserror.js
similarity index 100%
rename from lib/invalidaccesserror.js
rename to lib/error/invalidaccesserror.js
diff --git a/lib/invalidstateerror.js b/lib/error/invalidstateerror.js
similarity index 100%
rename from lib/invalidstateerror.js
rename to lib/error/invalidstateerror.js
diff --git a/lib/securityerror.js b/lib/error/securityerror.js
similarity index 100%
rename from lib/securityerror.js
rename to lib/error/securityerror.js
diff --git a/lib/info-receiver-fake.js b/lib/info-receiver-fake.js
deleted file mode 100644
index d64a223..0000000
--- a/lib/info-receiver-fake.js
+++ /dev/null
@@ -1,19 +0,0 @@
-'use strict';
-
-var EventEmitter = require('events').EventEmitter
- , util = require('util')
- ;
-
-var InfoReceiverFake = function() {
- // It may not be possible to do cross domain AJAX to get the info
- // data, for example for IE7. But we want to run JSONP, so let's
- // fake the response, with rtt=2s (rto=6s).
- var self = this;
- process.nextTick(function() {
- self.emit('finish', {}, 2000);
- });
-};
-
-util.inherits(InfoReceiverFake, EventEmitter);
-
-module.exports = InfoReceiverFake;
diff --git a/lib/info-receiver-iframe.js b/lib/info-receiver-iframe.js
index a0562ff..d957cb8 100644
--- a/lib/info-receiver-iframe.js
+++ b/lib/info-receiver-iframe.js
@@ -9,6 +9,8 @@ var EventEmitter = require('events').EventEmitter
function InfoReceiverIframe(baseUrl) {
var self = this;
+ EventEmitter.call(this);
+
var go = function() {
var ifr = new IframeTransport();
ifr.protocol = 'w-iframe-info-receiver';
diff --git a/lib/info-receiver.js b/lib/info-receiver.js
index edee3e4..d61eed0 100644
--- a/lib/info-receiver.js
+++ b/lib/info-receiver.js
@@ -2,11 +2,33 @@
var EventEmitter = require('events').EventEmitter
, util = require('util')
+ , utils = require('./utils')
, JSON3 = require('json3')
+ , loc = require('./polyfills/location')
+ , XHRCors = require('./xhr-cors')
+ , XHRLocal = require('./xhr-local')
+ , XDR = require('./xdr')
+ , XHRFake = require('./xhr-fake')
+ // it seems odd to include these just for the 'enabled' function
+ , XDRPolling = require('./transport/xdr-polling')
+ //, IframeTransport = require('./trans-iframe')
;
-function InfoReceiver(baseUrl, AjaxObject) {
+function InfoReceiver(baseUrl) {
var self = this;
+ EventEmitter.call(this);
+
+ var AjaxObject = XHRFake;
+ if (utils.isSameOriginUrl(baseUrl, loc.href)) {
+ AjaxObject = XHRCors;
+ } else if (utils.isXHRCorsCapable() === 1) {
+ AjaxObject = XHRLocal;
+ } else if (XDRPolling.enabled(baseUrl)) {
+ AjaxObject = XDR;
+ } //else if (IframeTransport.enabled()) {
+ //AjaxObject = IframeXHR;
+ //}
+
process.nextTick(function(){
self.doXhr(baseUrl, AjaxObject);
});
@@ -17,13 +39,15 @@ util.inherits(InfoReceiver, EventEmitter);
InfoReceiver.prototype.doXhr = function(baseUrl, AjaxObject) {
var self = this;
var t0 = Date.now();
- var xo = new AjaxObject('GET', baseUrl + '/info');
+ this.xo = new AjaxObject('GET', baseUrl + '/info');
- var tref = setTimeout(function(){xo.ontimeout();}, 8000);
+ this.timeoutRef = setTimeout(function() {
+ self.xo.close();
+ self.emit('finish');
+ }, 8000);
- xo.on('finish', function(status, text) {
- clearTimeout(tref);
- tref = null;
+ this.xo.on('finish', function(status, text) {
+ self._cleanup(true);
if (status === 200) {
var rtt = Date.now() - t0;
var info;
@@ -41,10 +65,20 @@ InfoReceiver.prototype.doXhr = function(baseUrl, AjaxObject) {
self.emit('finish');
}
});
- xo.ontimeout = function() {
- xo.close();
- self.emit('finish');
- };
+};
+
+InfoReceiver.prototype._cleanup = function(wasClean) {
+ clearTimeout(this.timeoutRef);
+ this.timeoutRef = null;
+ if (!wasClean && this.xo) {
+ this.xo.close();
+ }
+ this.xo = null;
+};
+
+InfoReceiver.prototype.close = function() {
+ this.removeAllListeners();
+ this._cleanup(false);
};
module.exports = InfoReceiver;
diff --git a/lib/main.js b/lib/main.js
index 2789c45..610fb74 100644
--- a/lib/main.js
+++ b/lib/main.js
@@ -4,24 +4,35 @@ require('./shims');
var u = require('url')
, util = require('util')
- , SecurityError = require('./securityerror')
- , InvalidAccessError = require('./invalidaccesserror')
- , InvalidStateError = require('./invalidstateerror')
+ , utils = require('./utils')
+ , SecurityError = require('./error/securityerror')
+ , InvalidAccessError = require('./error/invalidaccesserror')
+ , InvalidStateError = require('./error/invalidstateerror')
+ , Event = require('./polyfills/event')
, CloseEvent = require('./closeevent')
- , EventTarget = require('./eventtarget')
- , loc = require('./location')
+ , EventTarget = require('./polyfills/eventtarget')
+ , loc = require('./polyfills/location')
+ , InfoReceiver = require('./info-receiver')
+ , JSON3 = require('json3')
;
+var transports;
+
// follow constructor steps defined at http://dev.w3.org/html5/websockets/#the-websocket-interface
-function SockJS(url, protocols) {
+function SockJS(url, protocols, transportsWhitelist) {
if (!(this instanceof SockJS)) {
return new SockJS(url, protocols);
}
+ EventTarget.call(this);
this.readyState = SockJS.CONNECTING;
this.extensions = '';
this.protocol = '';
+ // non-standard extension
+ // TODO attempt to remove and provide another way
+ this._transportsWhitelist = transportsWhitelist;
+
// Step 1 of WS spec - parse and validate the url
var parsedUrl = u.parse(url);
if (!parsedUrl.host || !parsedUrl.pathname || !parsedUrl.protocol) {
@@ -63,8 +74,15 @@ function SockJS(url, protocols) {
// Step 7 - start connection in background
this.url = parsedUrl.href;
+ // if we don't have any path component, remove the trailing slash to make code easier
+ if (parsedUrl.path === '/') {
+ this.url = this.url.slice(0, -1);
+ }
- // TODO initiate info request
+ // obtain server info
+ // http://sockjs.github.io/sockjs-protocol/sockjs-protocol-0.3.3.html#section-26
+ this._ir = new InfoReceiver(this.url);
+ this._ir.on('finish', this._receiveInfo.bind(this));
}
util.inherits(SockJS, EventTarget);
@@ -84,10 +102,148 @@ SockJS.prototype.close = function(code, reason) {
return;
}
+ // TODO look at docs to determine how to set this
var wasClean = true;
- // TODO if connection not established, stop it
+ this._close(code || 1000, reason || 'Normal closure', wasClean);
+};
+
+SockJS.prototype.send = function(data) {
+ if (this.readyState === SockJS.CONNECTING) {
+ throw new InvalidStateError('The connection has not been established yet');
+ }
+ if (this.readyState !== SockJS.OPEN) {
+ return;
+ }
+ this._transport.send(data);
+};
+
+SockJS.CONNECTING = 0;
+SockJS.OPEN = 1;
+SockJS.CLOSING = 2;
+SockJS.CLOSED = 3;
+
+SockJS.prototype._receiveInfo = function(info, rtt) {
+ this._ir = null;
+ if (!info) {
+ this._close(1002, 'Cannot connect to server');
+ return;
+ }
+
+ // establish a round-trip timeout (RTO) based on the
+ // round-trip time (RTT)
+ this._rto = utils.countRTO(rtt);
+ // allow server to override url used for the actual transport
+ this._transUrl = info.base_url ? info.base_url : this.url;
+ info.nullOrigin = !document.domain;
+ // determine list of desired and supported transports
+ this._transports = transports(this.url, this._transportsWhitelist, info);
+ this._connect();
+};
+
+SockJS.prototype._connect = function() {
+ for (var Transport = this._transports.shift(); Transport; Transport = this._transports.shift()) {
+ if (Transport.needBody) {
+ if (!document.body ||
+ (typeof document.readyState !== 'undefined' && document.readyState !== 'complete')) {
+ this._transports.unshift(Transport);
+ // TODO attach to load event to call _connect
+ return;
+ }
+ }
+
+ // calculate timeout based on RTO and round trips. Default to 5s
+ var timeoutMs = (this._rto * Transport.roundTrips) || 5000;
+ this._transportTimeoutId = setTimeout(this._transportTimeout.bind(this), timeoutMs);
+
+ var transportUrl = this._transUrl + '/' + this._server + '/' + utils.randomString(8);
+ var transport = new Transport(transportUrl, this._transUrl);
+ transport.onmessage = this._transportMessage.bind(this);
+ transport.onclose = this._transportClose.bind(this);
+ this._transport = transport;
+
+ return;
+ }
+ this._close(2000, 'All transports failed', false);
+};
+
+SockJS.prototype._transportTimeout = function() {
+ if (this.readyState === SockJS.CONNECTING) {
+ this._close(2007, 'Transport timed out');
+ }
+};
+
+SockJS.prototype._transportMessage = function(e) {
+ var type = e.data.slice(0, 1);
+ var payload;
+ switch (type) {
+ case 'o':
+ this._open();
+ break;
+ case 'a':
+ payload = JSON3.parse(e.data.slice(1) || '[]');
+ for (var i = 0; i < payload.length; i++){
+ this._dispatchMessage(payload[i]);
+ }
+ break;
+ case 'm':
+ payload = JSON3.parse(e.data.slice(1) || 'null');
+ this._dispatchMessage(payload);
+ break;
+ case 'c':
+ payload = JSON3.parse(e.data.slice(1) || '[]');
+ this._close(payload[0], payload[1]);
+ break;
+ case 'h':
+ this.dispatchEvent(new Event().initEvent('heartbeat'));
+ break;
+ }
+};
+
+SockJS.prototype._transportClose = function(e) {
+ this._close(e.code, e.reason);
+};
+
+SockJS.prototype._open = function() {
+ if (this.readyState === SockJS.CONNECTING) {
+ if (this._transportTimeoutId) {
+ clearTimeout(this._transportTimeoutId);
+ this._transportTimeoutId = null;
+ }
+ this.readyState = SockJS.OPEN;
+ this.transport = this._transport.transportName;
+ this.dispatchEvent(new Event().initEvent('open'));
+ } else {
+ // The server might have been restarted, and lost track of our
+ // connection.
+ this._close(1006, 'Server lost session');
+ }
+};
+
+SockJS.prototype._dispatchMessage = function(data) {
+ var e = new Event().initEvent('message');
+ e.data = data;
+ this.dispatchEvent(e);
+};
+
+SockJS.prototype._close = function(code, reason, wasClean) {
+ var forceFail = false;
+
+ if (this._ir) {
+ forceFail = true;
+ this._ir.close();
+ this._ir = null;
+ }
+ if (this._transport) {
+ this._transport.close();
+ this._transport.onmessage = null;
+ this._transport.onclose = null;
+ this._transport = null;
+ }
+
+ if (this.readyState === SockJS.CLOSED) {
+ throw new InvalidStateError('SockJS has already been closed');
+ }
- // TODO start closing handshake
this.readyState = SockJS.CLOSING;
process.nextTick(function () {
this.readyState = SockJS.CLOSED;
@@ -103,20 +259,7 @@ SockJS.prototype.close = function(code, reason) {
}.bind(this));
};
-SockJS.prototype.send = function(/* data */) {
- if (this.readyState === SockJS.CONNECTING) {
- throw new InvalidStateError('connection has not been established yet');
- }
- if (this.readyState !== SockJS.OPEN) {
- return;
- }
-
- // TODO send data
+module.exports = function (availableTransports) {
+ transports = require('./transports')(availableTransports);
+ return SockJS;
};
-
-SockJS.CONNECTING = 0;
-SockJS.OPEN = 1;
-SockJS.CLOSING = 2;
-SockJS.CLOSED = 3;
-
-module.exports = SockJS;
diff --git a/lib/event.js b/lib/polyfills/event.js
similarity index 100%
rename from lib/event.js
rename to lib/polyfills/event.js
diff --git a/lib/eventtarget.js b/lib/polyfills/eventtarget.js
similarity index 81%
rename from lib/eventtarget.js
rename to lib/polyfills/eventtarget.js
index f4d85ab..b6d5336 100644
--- a/lib/eventtarget.js
+++ b/lib/polyfills/eventtarget.js
@@ -13,11 +13,11 @@ function arrayIndexOf(arr, item) {
return -1;
}
-var REventTarget = function() {
+var EventTarget = function() {
this._listeners = {};
};
-REventTarget.prototype.addEventListener = function (eventType, listener) {
+EventTarget.prototype.addEventListener = function (eventType, listener) {
if (!(eventType in this._listeners)) {
this._listeners[eventType] = [];
}
@@ -30,7 +30,7 @@ REventTarget.prototype.addEventListener = function (eventType, listener) {
return;
};
-REventTarget.prototype.removeEventListener = function (eventType, listener) {
+EventTarget.prototype.removeEventListener = function (eventType, listener) {
if (!(eventType in this._listeners)) {
return;
}
@@ -38,7 +38,7 @@ REventTarget.prototype.removeEventListener = function (eventType, listener) {
var idx = arrayIndexOf(arr, listener);
if (idx !== -1) {
if (arr.length > 1) {
- // Make a copy so as not to interfer with a current dispatchEvent.
+ // Make a copy so as not to interfere with a current dispatchEvent.
this._listeners[eventType] = arr.slice(0, idx).concat(arr.slice(idx + 1));
} else {
delete this._listeners[eventType];
@@ -48,7 +48,7 @@ REventTarget.prototype.removeEventListener = function (eventType, listener) {
return;
};
-REventTarget.prototype.dispatchEvent = function (event) {
+EventTarget.prototype.dispatchEvent = function (event) {
var t = event.type;
var args = Array.prototype.slice.call(arguments, 0);
// TODO: This doesn't match the real behavior; per spec, onfoo get
@@ -67,4 +67,4 @@ REventTarget.prototype.dispatchEvent = function (event) {
}
};
-module.exports = global.EventTarget || REventTarget;
+module.exports = global.EventTarget || EventTarget;
diff --git a/lib/location.js b/lib/polyfills/location.js
similarity index 83%
rename from lib/location.js
rename to lib/polyfills/location.js
index 9920ade..935f4b1 100644
--- a/lib/location.js
+++ b/lib/polyfills/location.js
@@ -5,4 +5,5 @@ module.exports = global.location || {
, protocol: 'http'
, host: 'localhost'
, port: 80
+, href: 'http://localhost/'
};
diff --git a/lib/protocols.js b/lib/protocols.js
deleted file mode 100644
index c626fcd..0000000
--- a/lib/protocols.js
+++ /dev/null
@@ -1,48 +0,0 @@
-'use strict';
-
-var protocolOrdering = [
- 'websocket',
- 'xdr-streaming',
- 'xhr-streaming',
- 'iframe-eventsource',
- 'iframe-htmlfile',
- 'xdr-polling',
- 'xhr-polling',
- 'iframe-xhr-polling',
- 'jsonp-polling'
-];
-
-var allProtocols = {
- 'websocket': require('./trans-websocket')
-, 'iframe-eventsource': require('./trans-iframe-eventsource')
-, 'iframe-htmlfile': require('./trans-iframe-htmlfile')
-, 'iframe-xhr-polling': require('./trans-iframe-xhr-polling')
-, 'jsonp-polling': require('./trans-jsonp-polling')
-, 'xdr-polling': require('./trans-xdr-polling')
-, 'xdr-streaming': require('./trans-xdr-streaming')
-, 'xhr-polling': require('./trans-xhr-polling')
-, 'xhr-streaming': require('./trans-xhr-streaming')
-};
-
-module.exports = function (url, protocolsWhitelist, info) {
- var protocols = [];
- if (!protocolsWhitelist) {
- protocolsWhitelist = [];
- }
- if (!protocolsWhitelist.length) {
- protocolsWhitelist = protocolOrdering;
- }
-
- for (var i = 0; i < protocolOrdering.length; i++) {
- var protoName = protocolOrdering[i];
- if (protocolsWhitelist.indexOf(protoName) === -1) {
- continue;
- }
-
- var proto = allProtocols[protoName];
- if (proto && proto.enabled(url, info)) {
- protocols.push(proto);
- }
- }
- return protocols;
-};
diff --git a/lib/shims.js b/lib/shims.js
index 2f994c5..a7348da 100644
--- a/lib/shims.js
+++ b/lib/shims.js
@@ -5,3 +5,28 @@ if (!Date.now) {
return new Date().getTime();
};
}
+
+if (!Function.prototype.bind) {
+ Function.prototype.bind = function (oThis) {
+ if (typeof this !== "function") {
+ // closest thing possible to the ECMAScript 5
+ // internal IsCallable function
+ throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
+ }
+
+ var aArgs = Array.prototype.slice.call(arguments, 1),
+ fToBind = this,
+ fNOP = function () {},
+ fBound = function () {
+ return fToBind.apply(this instanceof fNOP && oThis
+ ? this
+ : oThis,
+ aArgs.concat(Array.prototype.slice.call(arguments)));
+ };
+
+ fNOP.prototype = this.prototype;
+ fBound.prototype = new fNOP();
+
+ return fBound;
+ };
+}
\ No newline at end of file
diff --git a/lib/simpleevent.js b/lib/simpleevent.js
index 4bcd8b5..755d424 100644
--- a/lib/simpleevent.js
+++ b/lib/simpleevent.js
@@ -1,7 +1,13 @@
'use strict';
+var util = require('util')
+ , Event = require('./polyfills/event')
+ ;
+
var SimpleEvent = function(type, obj) {
- this.type = type;
+ Event.call(this);
+ this.initEvent(type);
+
if (typeof obj !== 'undefined') {
for (var k in obj) {
if (!obj.hasOwnProperty(k)) {
@@ -12,19 +18,6 @@ var SimpleEvent = function(type, obj) {
}
};
-SimpleEvent.prototype.toString = function() {
- var r = [];
- for (var k in this) {
- if (!this.hasOwnProperty(k)) {
- continue;
- }
- var v = this[k];
- if (typeof v === 'function') {
- v = '[function]';
- }
- r.push(k + '=' + v);
- }
- return 'SimpleEvent(' + r.join(', ') + ')';
-};
+util.inherits(SimpleEvent, Event);
module.exports = SimpleEvent;
diff --git a/lib/trans-iframe.js b/lib/trans-iframe.js
index fe625f2..96ba69f 100644
--- a/lib/trans-iframe.js
+++ b/lib/trans-iframe.js
@@ -1,9 +1,9 @@
'use strict';
// Few cool transports do work only for same-origin. In order to make
-// them working cross-domain we shall use iframe, served form the
-// remote domain. New browsers, have capabilities to communicate with
-// cross domain iframe, using postMessage(). In IE it was implemented
+// them work cross-domain we shall use iframe, served from the
+// remote domain. New browsers have capabilities to communicate with
+// cross domain iframe using postMessage(). In IE it was implemented
// from IE 8+, but of course, IE got some details wrong:
// http://msdn.microsoft.com/en-us/library/cc197015(v=VS.85).aspx
// http://stevesouders.com/misc/test-postmessage.php
@@ -85,9 +85,11 @@ IframeTransport.prototype.doSend = function (message) {
IframeTransport.enabled = function() {
// postMessage misbehaves in konqueror 4.6.5 - the messages are delivered with
// huge delay, or not at all.
- var konqueror = navigator && navigator.userAgent && navigator.userAgent.indexOf('Konqueror') !== -1;
- return ((typeof window.postMessage === 'function' ||
- typeof window.postMessage === 'object') && (!konqueror));
+ var konqueror = global.navigator &&
+ global.navigator.userAgent &&
+ global.navigator.userAgent.indexOf('Konqueror') !== -1;
+ return ((typeof global.postMessage === 'function' ||
+ typeof global.postMessage === 'object') && (!konqueror));
};
module.exports = IframeTransport;
diff --git a/lib/trans-message-event.js b/lib/trans-message-event.js
new file mode 100644
index 0000000..69935ef
--- /dev/null
+++ b/lib/trans-message-event.js
@@ -0,0 +1,15 @@
+'use strict';
+
+var util = require('util')
+ , Event = require('./polyfills/event')
+ ;
+
+function TransportMessageEvent(data) {
+ Event.call(this);
+ this.initEvent('message', false, false);
+ this.data = data;
+}
+
+util.inherits(TransportMessageEvent, Event);
+
+module.exports = TransportMessageEvent;
diff --git a/lib/trans-receiver-eventsource.js b/lib/trans-receiver-eventsource.js
index 0943062..cec679b 100644
--- a/lib/trans-receiver-eventsource.js
+++ b/lib/trans-receiver-eventsource.js
@@ -2,10 +2,12 @@
var util = require('util')
, SimpleEvent = require('./simpleevent')
- , REventTarget = require('./reventtarget')
+ , EventTarget = require('./polyfills/eventtarget')
;
function EventSourceReceiver(url) {
+ EventTarget.call(this);
+
var self = this;
var es = new EventSource(url);
es.onmessage = function(e) {
@@ -29,7 +31,7 @@ function EventSourceReceiver(url) {
};
}
-util.inherits(EventSourceReceiver, REventTarget);
+util.inherits(EventSourceReceiver, EventTarget);
EventSourceReceiver.prototype.abort = function() {
if (this.esClose) {
diff --git a/lib/trans-receiver-htmlfile.js b/lib/trans-receiver-htmlfile.js
index beb0fc4..967fead 100644
--- a/lib/trans-receiver-htmlfile.js
+++ b/lib/trans-receiver-htmlfile.js
@@ -3,7 +3,7 @@
var util = require('util')
, utils = require('./utils')
, SimpleEvent = require('./simpleevent')
- , REventTarget = require('./reventtarget')
+ , EventTarget = require('./polyfills/eventtarget')
;
var _isIeHtmlfileCapable;
@@ -22,6 +22,7 @@ var isIeHtmlfileCapable = function() {
function HtmlfileReceiver(url) {
+ EventTarget.call(this);
var self = this;
utils.polluteGlobalNamespace();
@@ -55,7 +56,7 @@ function HtmlfileReceiver(url) {
});
}
-util.inherits(HtmlfileReceiver, REventTarget);
+util.inherits(HtmlfileReceiver, EventTarget);
HtmlfileReceiver.prototype.abort = function() {
if (this.iframeClose) {
diff --git a/lib/trans-receiver-xhr.js b/lib/trans-receiver-xhr.js
index 8766cd5..6066abd 100644
--- a/lib/trans-receiver-xhr.js
+++ b/lib/trans-receiver-xhr.js
@@ -2,10 +2,11 @@
var util = require('util')
, SimpleEvent = require('./simpleevent')
- , REventTarget = require('./reventtarget')
+ , EventTarget = require('./polyfills/eventtarget')
;
function XhrReceiver(url, AjaxObject) {
+ EventTarget.call(this);
var self = this;
var bufPos = 0;
@@ -34,7 +35,7 @@ function XhrReceiver(url, AjaxObject) {
});
}
-util.inherits(XhrReceiver, REventTarget);
+util.inherits(XhrReceiver, EventTarget);
XhrReceiver.prototype.abort = function() {
if (this.xo) {
diff --git a/lib/trans-iframe-eventsource.js b/lib/transport/iframe-eventsource.js
similarity index 92%
rename from lib/trans-iframe-eventsource.js
rename to lib/transport/iframe-eventsource.js
index 941539c..002b3e7 100644
--- a/lib/trans-iframe-eventsource.js
+++ b/lib/transport/iframe-eventsource.js
@@ -1,7 +1,7 @@
'use strict';
var util = require('util')
- , IframeTransport = require('./trans-iframe')
+ , IframeTransport = require('../trans-iframe')
;
function EventSourceIframeTransport() {
diff --git a/lib/trans-iframe-htmlfile.js b/lib/transport/iframe-htmlfile.js
similarity index 93%
rename from lib/trans-iframe-htmlfile.js
rename to lib/transport/iframe-htmlfile.js
index 11ebff1..aaf2a46 100644
--- a/lib/trans-iframe-htmlfile.js
+++ b/lib/transport/iframe-htmlfile.js
@@ -6,7 +6,7 @@
// production it should be only run in IE.
var util = require('util')
- , IframeTransport = require('./trans-iframe')
+ , IframeTransport = require('../trans-iframe')
;
function HtmlFileIframeTransport() {
diff --git a/lib/trans-iframe-xhr-polling.js b/lib/transport/iframe-xhr-polling.js
similarity index 91%
rename from lib/trans-iframe-xhr-polling.js
rename to lib/transport/iframe-xhr-polling.js
index 04faf6d..3339766 100644
--- a/lib/trans-iframe-xhr-polling.js
+++ b/lib/transport/iframe-xhr-polling.js
@@ -1,7 +1,7 @@
'use strict';
var util = require('util')
- , IframeTransport = require('./trans-iframe')
+ , IframeTransport = require('../trans-iframe')
;
function XhrPollingIframeTransport() {
diff --git a/lib/trans-jsonp-polling.js b/lib/transport/jsonp-polling.js
similarity index 98%
rename from lib/trans-jsonp-polling.js
rename to lib/transport/jsonp-polling.js
index 560af91..faefb91 100644
--- a/lib/trans-jsonp-polling.js
+++ b/lib/transport/jsonp-polling.js
@@ -9,8 +9,8 @@
// o for Konqueror a dumb timer is needed to detect errors
var util = require('util')
- , utils = require('./utils')
- , BufferedSender = require('./buffered-sender')
+ , utils = require('../utils')
+ , BufferedSender = require('../buffered-sender')
;
// Abstract away code that handles global namespace pollution.
@@ -260,6 +260,7 @@ JsonPTransport.enabled = function() {
};
JsonPTransport.transportName = 'jsonp-polling';
+JsonPTransport.roundTrips = 1;
JsonPTransport.needBody = true;
JsonPTransport.prototype.doCleanup = function() {
diff --git a/lib/trans-websocket.js b/lib/transport/websocket.js
similarity index 63%
rename from lib/trans-websocket.js
rename to lib/transport/websocket.js
index b20fe00..a922e87 100644
--- a/lib/trans-websocket.js
+++ b/lib/transport/websocket.js
@@ -1,8 +1,15 @@
'use strict';
-var utils = require('./utils');
+var utils = require('../utils')
+ , util = require('util')
+ , EventTarget = require('../polyfills/eventtarget')
+ , TransportMessageEvent = require('../trans-message-event')
+ , CloseEvent = require('../closeevent')
+ ;
+
+function WebSocketTransport(transUrl) {
+ EventTarget.call(this);
-function WebSocketTransport(ri, transUrl) {
var self = this;
var url = transUrl + '/websocket';
if (url.slice(0, 5) === 'https') {
@@ -10,13 +17,12 @@ function WebSocketTransport(ri, transUrl) {
} else {
url = 'ws' + url.slice(4);
}
- this.ri = ri;
this.url = url;
- var Constructor = window.WebSocket || window.MozWebSocket;
+ var Constructor = global.WebSocket || global.MozWebSocket || require('faye-websocket').Client;
this.ws = new Constructor(this.url);
this.ws.onmessage = function(e) {
- self.ri._didMessage(e.data);
+ self.dispatchEvent(new TransportMessageEvent(e.data));
};
// Firefox has an interesting bug. If a websocket connection is
// created after onunload, it stays alive even when user
@@ -28,21 +34,26 @@ function WebSocketTransport(ri, transUrl) {
self.ws.close();
});
this.ws.onclose = this.ws.onerror = function() {
- self.ri._didMessage(utils.closeFrame(1006, 'WebSocket connection broken'));
+ var closeEvent = new CloseEvent();
+ closeEvent.code = 1006;
+ closeEvent.reason = 'WebSocket connection broken';
+ self.dispatchEvent(closeEvent);
};
}
-WebSocketTransport.prototype.doSend = function(data) {
+util.inherits(WebSocketTransport, EventTarget);
+
+WebSocketTransport.prototype.send = function(data) {
this.ws.send('[' + data + ']');
};
-WebSocketTransport.prototype.doCleanup = function() {
+WebSocketTransport.prototype.close = function() {
var ws = this.ws;
if (ws) {
ws.onmessage = ws.onclose = ws.onerror = null;
ws.close();
utils.unloadDel(this.unloadRef);
- this.unloadRef = this.ri = this.ws = null;
+ this.unloadRef = this.ws = null;
}
};
diff --git a/lib/trans-xdr-polling.js b/lib/transport/xdr-polling.js
similarity index 68%
rename from lib/trans-xdr-polling.js
rename to lib/transport/xdr-polling.js
index f544191..da088fd 100644
--- a/lib/trans-xdr-polling.js
+++ b/lib/transport/xdr-polling.js
@@ -1,10 +1,10 @@
'use strict';
var util = require('util')
- , AjaxBasedTransport = require('./ajax-based')
- , XdrStreamingTransport = require('./trans-xdr-streaming')
- , XhrReceiver = require('./trans-receiver-xhr')
- , XDRObject = require('./xdr')
+ , AjaxBasedTransport = require('../ajax-based')
+ , XdrStreamingTransport = require('./xdr-streaming')
+ , XhrReceiver = require('../trans-receiver-xhr')
+ , XDRObject = require('../xdr')
;
function XdrPollingTransport(ri, transUrl) {
diff --git a/lib/trans-xdr-streaming.js b/lib/transport/xdr-streaming.js
similarity index 67%
rename from lib/trans-xdr-streaming.js
rename to lib/transport/xdr-streaming.js
index 9da1f79..7a2e577 100644
--- a/lib/trans-xdr-streaming.js
+++ b/lib/transport/xdr-streaming.js
@@ -1,10 +1,10 @@
'use strict';
var util = require('util')
- , AjaxBasedTransport = require('./ajax-based')
- , XhrReceiver = require('./trans-receiver-xhr')
- , XDRObject = require('./xdr')
- , utils = require('./utils')
+ , AjaxBasedTransport = require('../ajax-based')
+ , XhrReceiver = require('../trans-receiver-xhr')
+ , XDRObject = require('../xdr')
+ , utils = require('../utils')
;
// According to:
@@ -18,15 +18,15 @@ function XdrStreamingTransport(ri, transUrl) {
util.inherits(XdrStreamingTransport, AjaxBasedTransport);
XdrStreamingTransport.enabled = function(url, info) {
- if (info.cookie_needed || info.null_origin) {
+ if (info && (info.cookie_needed || info.nullOrigin)) {
return false;
}
// IE 8/9 if the request target uses the same scheme - #79
- return !!(window.XDomainRequest && document.domain && utils.isSameOriginScheme(url));
+ return !!(global.XDomainRequest && global.document &&
+ global.document.domain && utils.isSameOriginScheme(url));
};
XdrStreamingTransport.transportName = 'xdr-streaming';
-
XdrStreamingTransport.roundTrips = 2; // preflight, ajax
module.exports = XdrStreamingTransport;
diff --git a/lib/trans-xhr-polling.js b/lib/transport/xhr-polling.js
similarity index 73%
rename from lib/trans-xhr-polling.js
rename to lib/transport/xhr-polling.js
index a55eeba..88ced22 100644
--- a/lib/trans-xhr-polling.js
+++ b/lib/transport/xhr-polling.js
@@ -1,10 +1,10 @@
'use strict';
var util = require('util')
- , AjaxBasedTransport = require('./ajax-based')
- , XhrReceiver = require('./trans-receiver-xhr')
- , XHRCorsObject = require('./xhr-cors')
- , utils = require('./utils')
+ , AjaxBasedTransport = require('../ajax-based')
+ , XhrReceiver = require('../trans-receiver-xhr')
+ , XHRCorsObject = require('../xhr-cors')
+ , utils = require('../utils')
;
function XhrPollingTransport(ri, transUrl) {
@@ -14,7 +14,7 @@ function XhrPollingTransport(ri, transUrl) {
util.inherits(XhrPollingTransport, AjaxBasedTransport);
XhrPollingTransport.enabled = function(url, info) {
- if (info.null_origin) {
+ if (info.nullOrigin) {
return false;
}
if (window.XMLHttpRequest && utils.isSameOriginUrl(url)) {
diff --git a/lib/trans-xhr-streaming.js b/lib/transport/xhr-streaming.js
similarity index 70%
rename from lib/trans-xhr-streaming.js
rename to lib/transport/xhr-streaming.js
index 12014c8..acb8bbb 100644
--- a/lib/trans-xhr-streaming.js
+++ b/lib/transport/xhr-streaming.js
@@ -1,10 +1,10 @@
'use strict';
var util = require('util')
- , AjaxBasedTransport = require('./ajax-based')
- , XhrReceiver = require('./trans-receiver-xhr')
- , XHRCorsObject = require('./xhr-cors')
- , utils = require('./utils')
+ , AjaxBasedTransport = require('../ajax-based')
+ , XhrReceiver = require('../trans-receiver-xhr')
+ , XHRCorsObject = require('../xhr-cors')
+ , utils = require('../utils')
;
function XhrStreamingTransport(ri, transUrl) {
@@ -14,14 +14,14 @@ function XhrStreamingTransport(ri, transUrl) {
util.inherits(XhrStreamingTransport, AjaxBasedTransport);
XhrStreamingTransport.enabled = function(url, info) {
- if (info.null_origin) {
+ if (info.nullOrigin) {
return false;
}
// Opera doesn't support xhr-streaming
- if (/opera/i.test(navigator.userAgent)) {
+ if (/opera/i.test(global.navigator.userAgent)) {
return false;
}
- if (window.XMLHttpRequest && utils.isSameOriginUrl(url)) {
+ if (global.XMLHttpRequest && utils.isSameOriginUrl(url)) {
return true;
}
diff --git a/lib/transports.js b/lib/transports.js
new file mode 100644
index 0000000..499aa76
--- /dev/null
+++ b/lib/transports.js
@@ -0,0 +1,27 @@
+'use strict';
+
+module.exports = function (availableTransports) {
+ return function (url, transportsWhitelist, info) {
+ var transports = [];
+ if (!transportsWhitelist) {
+ transportsWhitelist = [];
+ }
+
+ for (var i = 0; i < availableTransports.length; i++) {
+ var trans = availableTransports[i];
+ if (!trans) {
+ continue;
+ }
+
+ if (transportsWhitelist.length &&
+ transportsWhitelist.indexOf(trans.transportName) === -1) {
+ continue;
+ }
+
+ if (trans.enabled(url, info)) {
+ transports.push(trans);
+ }
+ }
+ return transports;
+ };
+};
diff --git a/lib/utils.js b/lib/utils.js
index 3913cf8..12717e2 100644
--- a/lib/utils.js
+++ b/lib/utils.js
@@ -5,10 +5,10 @@ var IframeTransport = require('./trans-iframe');
var utils = {};
var getRandomBytes;
-if (window && window.crypto && window.crypto.getRandomValues) {
+if (global && global.crypto && global.crypto.getRandomValues) {
getRandomBytes = function (length) {
var bytes = new Uint8Array(length);
- window.crypto.getRandomValues(bytes);
+ global.crypto.getRandomValues(bytes);
return bytes;
};
} else {
@@ -73,14 +73,14 @@ utils.getOrigin = function(url) {
utils.isSameOriginUrl = function(urlA, urlB) {
// location.origin would do, but it's not always available.
if (!urlB) {
- urlB = window.location.href;
+ urlB = global.location.href;
}
return utils.getOrigin(urlA) === utils.getOrigin(urlB);
};
utils.isSameOriginScheme = function(urlA, urlB) {
if (!urlB) {
- urlB = window.location.href;
+ urlB = global.location.href;
}
return (urlA.split(':')[0] === urlB.split(':')[0]);
@@ -316,12 +316,12 @@ utils.quote = function(string) {
// 4. Nope, sorry.
utils.isXHRCorsCapable = function() {
try {
- if (window.XMLHttpRequest && 'withCredentials' in new XMLHttpRequest()) {
+ if (global.XMLHttpRequest && 'withCredentials' in new XMLHttpRequest()) {
return 1;
}
} catch (ignored) {}
// XDomainRequest doesn't work if page is served from file://
- if (window.XDomainRequest && document.domain) {
+ if (global.XDomainRequest && global.document && global.document.domain) {
return 2;
}
if (IframeTransport.enabled()) {
@@ -353,15 +353,15 @@ utils.attachMessage = function(listener) {
utils.attachEvent('message', listener);
};
utils.attachEvent = function(event, listener) {
- if (typeof window.addEventListener !== 'undefined') {
- window.addEventListener(event, listener, false);
+ if (typeof global.addEventListener !== 'undefined') {
+ global.addEventListener(event, listener, false);
} else {
// IE quirks.
// According to: http://stevesouders.com/misc/test-postmessage.php
// the message gets delivered only to 'document', not 'window'.
document.attachEvent('on' + event, listener);
// I get 'window' for ie8.
- window.attachEvent('on' + event, listener);
+ global.attachEvent('on' + event, listener);
}
};
@@ -369,11 +369,11 @@ utils.detachMessage = function(listener) {
utils.detachEvent('message', listener);
};
utils.detachEvent = function(event, listener) {
- if (typeof window.addEventListener !== 'undefined') {
- window.removeEventListener(event, listener, false);
+ if (typeof global.addEventListener !== 'undefined') {
+ global.removeEventListener(event, listener, false);
} else {
document.detachEvent('on' + event, listener);
- window.detachEvent('on' + event, listener);
+ global.detachEvent('on' + event, listener);
}
};
@@ -399,13 +399,15 @@ var unloadTriggered = function() {
// 'unload' alone is not reliable in opera within an iframe, but we
// can't use `beforeunload` as IE fires it on javascript: links.
-utils.attachEvent('unload', unloadTriggered);
+
+// TODO see if we need to uncomment this
+//utils.attachEvent('unload', unloadTriggered);
utils.unloadAdd = function(listener) {
var ref = utils.randomString(8);
onUnload[ref] = listener;
if (afterUnload) {
- setTimeout(triggerUnloadCallbacks, 0);
+ process.nextTick(triggerUnloadCallbacks);
}
return ref;
};
diff --git a/lib/xdr.js b/lib/xdr.js
index 6ba39a7..8291d75 100644
--- a/lib/xdr.js
+++ b/lib/xdr.js
@@ -11,6 +11,8 @@ var EventEmitter = require('events').EventEmitter
function XDRObject(method, url, payload) {
var self = this;
+ EventEmitter.call(this);
+
process.nextTick(function(){
self._start(method, url, payload);
});
@@ -20,7 +22,7 @@ util.inherits(XDRObject, EventEmitter);
XDRObject.prototype._start = function(method, url, payload) {
var self = this;
- var xdr = new XDomainRequest();
+ var xdr = new global.XDomainRequest();
// IE caches even POSTs
url += ((url.indexOf('?') === -1) ? '?' : '&') + 't=' + Date.now();
diff --git a/lib/xhr-cors.js b/lib/xhr-cors.js
index ef79e5f..04d0052 100644
--- a/lib/xhr-cors.js
+++ b/lib/xhr-cors.js
@@ -4,12 +4,12 @@ var util = require('util')
, AbstractXHRObject = require('./abstract-xhr')
;
-function XHRCorsObject() {
+function XHRCorsObject(method, url, payload, opts) {
var self = this
, args = arguments
;
process.nextTick(function(){
- self._start.apply(self, args);
+ AbstractXHRObject.apply(self, args);
});
}
diff --git a/lib/xhr-fake.js b/lib/xhr-fake.js
new file mode 100644
index 0000000..360f08d
--- /dev/null
+++ b/lib/xhr-fake.js
@@ -0,0 +1,17 @@
+'use strict';
+
+var EventEmitter = require('events').EventEmitter
+ , util = require('util')
+ ;
+
+function XHRFake(method, url, payload, opts) {
+ EventEmitter.call(this);
+
+ setTimeout(function() {
+ self.emit('finish', 200, '{}');
+ }, 2000);
+}
+
+util.inherits(XHRFake, EventEmitter);
+
+module.exports = XHRFake;
diff --git a/lib/xhr-local.js b/lib/xhr-local.js
index 5ab3b6d..654da17 100644
--- a/lib/xhr-local.js
+++ b/lib/xhr-local.js
@@ -7,7 +7,7 @@ var util = require('util')
function XHRLocalObject(method, url, payload) {
var self = this;
process.nextTick(function(){
- self._start(method, url, payload, {
+ AbstractXHRObject.call(self, method, url, payload, {
noCredentials: true
});
});
diff --git a/package.json b/package.json
index b62ae2d..bfaf9d2 100644
--- a/package.json
+++ b/package.json
@@ -13,7 +13,8 @@
}
],
"dependencies": {
- "json3": "^3.3.2"
+ "json3": "^3.3.2",
+ "faye-websocket": "~0.7.3"
},
"devDependencies": {
"browserify": "^4.2.3",
@@ -29,7 +30,6 @@
"expect.js": "~0.3.1",
"proxyquire": "~1.0.1",
"gulp-mocha": "~1.1.0",
- "gulp-jsbeautifier": "0.0.2",
"gulp-eslint": "~0.1.8"
},
"homepage": "http://sockjs.org",
@@ -38,14 +38,14 @@
"websocket"
],
"license": "MIT",
- "main": "./lib/sockjs.js",
+ "main": "./lib/entry.js",
"private": true,
"repository": {
"type": "git",
"url": "https://github.com/sockjs/sockjs-client.git"
},
"scripts": {
- "t": "node ./node_modules/mocha/bin/mocha tests/main.js",
+ "t": "node ./node_modules/mocha/bin/mocha tests/main.js tests/transports.js",
"test": "./node_modules/zuul/bin/zuul --sauce-connect -- tests/html/lib/unittests.js tests/html/lib/domtests.js tests/html/lib/endtoendtests.js tests/html/lib/tests.js",
"test_ws": "./node_modules/zuul/bin/zuul --sauce-connect -- tests/html/lib/ws_test.js",
"test_local": "./node_modules/zuul/bin/zuul --local 9090 -- tests/html/lib/unittests.js tests/html/lib/domtests.js tests/html/lib/endtoendtests.js tests/html/lib/tests.js"
diff --git a/tests/main.js b/tests/main.js
index 4ef1ce6..aa7fec2 100644
--- a/tests/main.js
+++ b/tests/main.js
@@ -2,8 +2,8 @@
var expect = require('expect.js')
, proxyquire = require('proxyquire')
- , SecurityError = require('../lib/securityerror')
- , SockJS = require('../lib/main')
+ , SecurityError = require('../lib/error/securityerror')
+ , SockJS = require('../lib/entry')
;
describe('SockJS', function() {
@@ -15,7 +15,7 @@ describe('SockJS', function() {
it('create a valid WebSocket object', function () {
var s = new SockJS('http://sockjs.org');
- expect(s).to.have.property('url', 'http://sockjs.org/');
+ expect(s).to.have.property('url', 'http://sockjs.org');
expect(s).to.have.property('readyState', SockJS.CONNECTING);
expect(s).to.have.property('extensions', '');
expect(s).to.have.property('protocol', '');
@@ -24,13 +24,13 @@ describe('SockJS', function() {
describe('WebSocket specification step #1', function () {
it('should throw SyntaxError for an invalid url', function () {
expect(function () {
- SockJS('//sockjs.org')
+ SockJS('//sockjs.org');
}).to.throwException(function (e) {
expect(e).to.be.a(SyntaxError);
});
expect(function () {
- SockJS('http://')
+ SockJS('http://');
}).to.throwException(function (e) {
expect(e).to.be.a(SyntaxError);
});
@@ -38,13 +38,13 @@ describe('SockJS', function() {
it('should throw SyntaxError when the url contains a querystring or fragment', function () {
expect(function () {
- SockJS('http://sockjs.org/?test')
+ SockJS('http://sockjs.org/?test');
}).to.throwException(function (e) {
expect(e).to.be.a(SyntaxError);
});
expect(function () {
- SockJS('http://sockjs.org/#test')
+ SockJS('http://sockjs.org/#test');
}).to.throwException(function (e) {
expect(e).to.be.a(SyntaxError);
});
@@ -52,7 +52,7 @@ describe('SockJS', function() {
it('should throw SyntaxError for an invalid protocol', function () {
expect(function () {
- SockJS('ftp://sockjs.org')
+ SockJS('ftp://sockjs.org');
}).to.throwException(function (e) {
expect(e).to.be.a(SyntaxError);
});
@@ -61,11 +61,12 @@ describe('SockJS', function() {
describe('WebSocket specification step #2', function () {
it('should throw SecurityError for an insecure url from a secure page', function () {
- var sjs = proxyquire('../lib/main', { './location': {
+ var main = proxyquire('../lib/main', { './polyfills/location': {
protocol: 'https'
}});
+ var sjs = proxyquire('../lib/entry', { './main': main });
expect(function () {
- sjs('http://sockjs.org')
+ sjs('http://sockjs.org');
}).to.throwException(function (e) {
expect(e).to.be.a(SecurityError);
});
@@ -75,7 +76,7 @@ describe('SockJS', function() {
describe('WebSocket specification step #5', function () {
it('should throw SyntaxError for duplicated protocols', function () {
expect(function () {
- SockJS('http://sockjs.org', ['test', 'test'])
+ SockJS('http://sockjs.org', ['test', 'test']);
}).to.throwException(function (e) {
expect(e).to.be.a(SyntaxError);
});
diff --git a/tests/transports.js b/tests/transports.js
new file mode 100644
index 0000000..2808137
--- /dev/null
+++ b/tests/transports.js
@@ -0,0 +1,39 @@
+'use strict';
+
+var expect = require('expect.js')
+ , fs = require('fs')
+ , path = require('path')
+ , EventTarget = require('../lib/polyfills/eventtarget')
+ ;
+
+var transportFiles = [];
+var dir = path.resolve(__dirname, '../lib/transport');
+var files = fs.readdirSync(dir);
+files.forEach(function (file) {
+ if (file[0] === '.') {
+ return;
+ }
+ transportFiles.push(path.resolve(dir, file));
+});
+
+describe('Transports', function () {
+ transportFiles.forEach(function (tf) {
+ describe(path.basename(tf, '.js'), function () {
+ it('has a valid interface', function () {
+ var Trans = require(tf);
+ expect(Trans).to.be.ok();
+ expect(Trans).to.have.property('transportName');
+ expect(Trans.transportName.length).to.be.greaterThan(0);
+
+ expect(Trans).to.have.property('roundTrips');
+ expect(Trans.roundTrips).to.be.a('number');
+
+ expect(Trans).to.have.property('enabled');
+ expect(Trans.enabled).to.be.a('function');
+
+ //expect(new Trans('http://localhost')).to.be.an(EventTarget);
+ // TODO tests for event emitting
+ });
+ });
+ });
+});
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/sockjs-client.git
More information about the Pkg-javascript-commits
mailing list