[Pkg-javascript-commits] [sockjs-client] 28/434: Heavy refactoring, open is now a protocol, not a transport thing. Close can be initiated only by the client.
Tonnerre Lombard
tonnerre-guest at moszumanska.debian.org
Wed Jan 8 00:46:59 UTC 2014
This is an automated email from the git hooks/post-receive script.
tonnerre-guest pushed a commit to branch master
in repository sockjs-client.
commit 356aed0d949bb85f05700c8ccb70e39911178a77
Author: Marek Majkowski <majek04 at gmail.com>
Date: Thu Jul 28 13:01:46 2011 +0100
Heavy refactoring, open is now a protocol, not a transport thing. Close can be initiated only by the client.
---
bin/minify.coffee | 6 +-
bin/render.coffee | 2 +-
lib/all.js | 3 +
lib/sockjs.js | 171 +++++++++++++++++++++++-----------------
lib/trans-iframe-eventsource.js | 16 ++--
lib/trans-iframe-htmlfile.js | 6 --
lib/trans-iframe-within.js | 13 +--
lib/trans-iframe.js | 27 +++----
lib/trans-jsonp.js | 117 ++++++++++++---------------
lib/trans-websocket.js | 23 +++---
lib/utils.js | 45 ++++++++---
tests-src/test-factory.coffee | 26 ++++--
12 files changed, 244 insertions(+), 211 deletions(-)
diff --git a/bin/minify.coffee b/bin/minify.coffee
index e5b1b1f..78da0e9 100644
--- a/bin/minify.coffee
+++ b/bin/minify.coffee
@@ -8,7 +8,7 @@ switches = [
['-p', '--pretty', 'Prettify javascript']
]
-minify_options = {}
+minify_options = {toplevel: true}
parser = new optparse.OptionParser(switches)
parser.on 'pretty', ->
minify_options.beautify = true
@@ -22,8 +22,8 @@ console.warn(" [.] Minifying:", filenames.join(', '))
minify = (data, minify_options)->
ast = uglify.parser.parse(data)
- ast = uglify.uglify.ast_mangle(ast)
+ ast = uglify.uglify.ast_mangle(ast, minify_options)
ast = uglify.uglify.ast_squeeze(ast)
uglify.uglify.gen_code(ast, minify_options)
-process.stdout.write(minify(content.join('\n')))
+process.stdout.write(minify(content.join('\n'), minify_options))
diff --git a/bin/render.coffee b/bin/render.coffee
index 2bce25f..21ec25d 100644
--- a/bin/render.coffee
+++ b/bin/render.coffee
@@ -74,7 +74,7 @@ main = ->
['-p', '--pretty', 'Prettify javascript']
['-m', '--minify', 'Minify javascript']
]
- options = {minify:false, toplevel:true}
+ options = {minify: false, toplevel: true}
parser = new optparse.OptionParser(switches)
parser.on 'pretty', ->
options.beautify = true
diff --git a/lib/all.js b/lib/all.js
index 8dcad34..e5d762e 100644
--- a/lib/all.js
+++ b/lib/all.js
@@ -1,4 +1,7 @@
// SockJS client, version <!-- version -->, MIT License
// https://github.com/majek/sockjs-client
+
+// JSON2 by Douglas Crockford (minified).
<!-- include lib/json2.min.js -->
+
<!-- include_and_minify lib/main.js c -->
diff --git a/lib/sockjs.js b/lib/sockjs.js
index a95a164..de063ec 100644
--- a/lib/sockjs.js
+++ b/lib/sockjs.js
@@ -1,27 +1,27 @@
-// Public object.
var SockJS = function(url, protocols, options) {
- this._options = {devel: true, debug: true};
- if (typeof options !== 'undefined') {
- utils.objectExtend(this._options, options);
+ var that = this;
+ that._options = {devel: true, debug: true};
+ if (options) {
+ utils.objectExtend(that._options, options);
}
- this._base_url = url;
- this._server = this._options.server || utils.random_number_string(1000);
- this._connid = utils.random_string(8);
- this._trans_url = this._base_url + '/' + this._server + '/' + this._connid;
- this._protocols = ['websocket', 'iframe-eventsource', 'iframe-htmlfile', 'jsonp'];
+ that._base_url = url;
+ that._server = that._options.server || utils.random_number_string(1000);
+ that._connid = utils.random_string(8);
+ that._trans_url = that._base_url + '/' + that._server + '/' + that._connid;
+ that._protocols = ['websocket', 'iframe-eventsource', 'iframe-htmlfile', 'jsonp'];
switch(typeof protocols) {
case 'undefined': break;
- case 'string': this._protocols = [protocols]; break;
- default: this._protocols = protocols; break;
+ case 'string': that._protocols = [protocols]; break;
+ default: that._protocols = protocols; break;
}
- this.protocol = undefined;
- this.readyState = SockJS.CONNECTING;
- this._try_next_protocol();
+ that.protocol = null;
+ that.readyState = SockJS.CONNECTING;
+ that._try_next_protocol();
};
// Inheritance
SockJS.prototype = new REventTarget();
-SockJS.version = "0.0.1";
+SockJS.version = "<!-- version -->";
SockJS.CONNECTING = 0;
SockJS.OPEN = 1;
@@ -29,89 +29,112 @@ SockJS.CLOSING = 2;
SockJS.CLOSED = 3;
SockJS.prototype._debug = function() {
- if (this._options.debug && 'console' in _window && console.log) {
- console.log.apply(console, arguments);
- }
+ if (this._options.debug)
+ utils.log.apply(utils, arguments);
};
-SockJS.prototype._didOpen = function() {
- if (this.readyState !== SockJS.CONNECTING)
- throw 'INVALID_STATE_ERR';
- this.readyState = SockJS.OPEN;
- this.dispatchEvent(new SimpleEvent("open"));
+SockJS.prototype._dispatchOpen = function() {
+ var that = this;
+ if (that.readyState !== SockJS.CONNECTING)
+ throw Error('INVALID_STATE_ERR');
+ that.readyState = SockJS.OPEN;
+ that.dispatchEvent(new SimpleEvent("open"));
+};
+
+SockJS.prototype._dispatchMessage = function(data) {
+ var that = this;
+ if (that.readyState !== SockJS.OPEN)
+ return;
+ that.dispatchEvent(new SimpleEvent("message", {data: data}));
};
-SockJS.prototype._didClose = function(status, reason) {
- if (this.readyState !== SockJS.CONNECTING &&
- this.readyState !== SockJS.OPEN &&
- this.readyState !== SockJS.CLOSING)
- throw 'INVALID_STATE_ERR';
+SockJS.prototype._didClose = function(status, reason) {
+ var that = this;
+ if (that.readyState !== SockJS.CONNECTING &&
+ that.readyState !== SockJS.OPEN &&
+ that.readyState !== SockJS.CLOSING)
+ throw Error('INVALID_STATE_ERR');
+ that._transport.doCleanup();
+ that._transport = null;
var close_event = new SimpleEvent("close", {status: status, reason: reason});
- if (this.readyState === SockJS.CONNECTING) {
- if (this._try_next_protocol(close_event) === false) {
- this.readyState = SockJS.CLOSED;
- var e = new SimpleEvent("close", {status: 2000,
- reason: "All transports failed."});
- this.dispatchEvent(e);
- }
- } else {
- if (this.readyState === SockJS.CLOSING &&
- status === 1001 && this._close_status) {
- close_event = new SimpleEvent("close", {status: this._close_status,
- reason: this._close_reason});
- }
- this.readyState = SockJS.CLOSED;
- this.dispatchEvent(close_event);
+
+ if (!utils.userSetStatus(status) && that.readyState === SockJS.CONNECTING) {
+ if (that._try_next_protocol(close_event))
+ return;
+ close_event = new SimpleEvent("close", {status: 2000,
+ reason: "All transports failed",
+ last_event: close_event});
}
+ that.readyState = SockJS.CLOSE;
+
+ setTimeout(function() {
+ that.dispatchEvent(close_event);
+ }, 0);
};
SockJS.prototype._didMessage = function(data) {
- if (this.readyState !== SockJS.OPEN)
- return;
- this.dispatchEvent(new SimpleEvent("message", {data: data}));
+ var that = this;
+ var type = data.slice(0, 1);
+ var payload = JSON.parse(data.slice(1) || 'null');
+ switch(type) {
+ case 'o':
+ that._dispatchOpen();
+ break;
+ case 'a':
+ for(var i=0; i < payload.length; i++){
+ that._dispatchMessage(payload[i]);
+ }
+ break;
+ case 'm':
+ that._dispatchMessage(payload);
+ break;
+ case 'c':
+ that._didClose(payload[0], payload[1]);
+ break;
+ }
};
SockJS.prototype._try_next_protocol = function(close_event) {
- if (this.protocol)
- this._debug('Closed transport:', this.protocol, close_event);
-
- if (this._transport) {
- delete this._transport; this._transport = undefined;
- }
+ var that = this;
+ if (that.protocol)
+ that._debug('Closed transport:', that.protocol, ''+close_event);
- this.protocol = this._protocols.shift();
- if (typeof this.protocol === 'undefined') {
- return false;
- }
-
- this._debug('Opening transport:', this.protocol);
- if (SockJS[this.protocol].enabled() === true) {
- this._transport = new SockJS[this.protocol](this, this._trans_url, this._base_url);
- return true;
+ while(1) {
+ that.protocol = that._protocols.shift();
+ if (!that.protocol) {
+ return false;
+ }
+ if (!SockJS[that.protocol].enabled()) {
+ that._debug('Skipping transport:', that.protocol);
+ } else {
+ that._debug('Opening transport:', that.protocol);
+ that._transport = new SockJS[that.protocol](that, that._trans_url,
+ that._base_url);
+ return true;
+ }
}
- var e = new SimpleEvent("close", {status: 1000,
- reason: "Transport unavailable"});
- return this._try_next_protocol(e);
};
SockJS.prototype.close = function(status, reason) {
- if(this.readyState !== SockJS.CONNECTING &&
- this.readyState !== SockJS.OPEN) {
+ var that = this;
+ if (status && !utils.userSetStatus(status))
+ throw Error("INVALID_ACCESS_ERR");
+ if(that.readyState !== SockJS.CONNECTING &&
+ that.readyState !== SockJS.OPEN) {
return false;
}
- this.readyState = SockJS.CLOSING;
- this._close_status = status || 1000;
- this._close_reason = reason || "Normal closure";
- this._transport.doClose();
+ that.readyState = SockJS.CLOSING;
+ that._didClose(status || 1000, reason || "Normal closure");
return true;
};
SockJS.prototype.send = function(data) {
- if (this.readyState === SockJS.CONNECTING)
- throw 'INVALID_STATE_ERR';
- if (this.readyState === SockJS.OPEN) {
- this._transport.doSend(data);
+ var that = this;
+ if (that.readyState === SockJS.CONNECTING)
+ throw Error('INVALID_STATE_ERR');
+ if (that.readyState === SockJS.OPEN) {
+ that._transport.doSend(data);
}
return true;
};
diff --git a/lib/trans-iframe-eventsource.js b/lib/trans-iframe-eventsource.js
index bf5b782..359cad2 100644
--- a/lib/trans-iframe-eventsource.js
+++ b/lib/trans-iframe-eventsource.js
@@ -1,10 +1,12 @@
var EventSourceIframeTransport = SockJS['iframe-eventsource'] = function () {
var that = this;
that.protocol = 'w-iframe-eventsource';
- that.i_constructor.apply(this, arguments);
+ that.i_constructor.apply(that, arguments);
};
+
// Inheritance.
EventSourceIframeTransport.prototype = new IframeTransport();
+
EventSourceIframeTransport.enabled = function () {
return (typeof EventSource === 'function') && IframeTransport.enabled();
};
@@ -16,10 +18,9 @@ var EventSourceTransport = FacadeJS['w-iframe-eventsource'] = function (ri, tran
that.trans_url = trans_url;
var url = trans_url + '/eventsource';
var es = that.es = new EventSource(url);
- es.onopen = function(e){that.ri._didOpen();};
- es.onmessage = function(e){that.ri._didMessage(unescape(e.data.slice(1)));};
- es.onerror = function(e){
- // EventSource reconnects automatically.
+ es.onmessage = function(e) {that.ri._didMessage(unescape(e.data));};
+ es.onerror = function(e) {
+ // EventSource reconnects automatically by default.
that.cleanup();
that.ri._didClose(1001, "Socket closed.");
};
@@ -30,8 +31,9 @@ EventSourceTransport.prototype = new BufferedSender();
EventSourceTransport.prototype.cleanup = function() {
var that = this;
- that.es.onopen = that.es.onmessage = that.es.onerror = null;
- that.es.close();
+ var es = that.es;
+ es.onmessage = es.onerror = null;
+ es.close();
that.es = null;
};
diff --git a/lib/trans-iframe-htmlfile.js b/lib/trans-iframe-htmlfile.js
index 2348e9c..a1ef1be 100644
--- a/lib/trans-iframe-htmlfile.js
+++ b/lib/trans-iframe-htmlfile.js
@@ -25,13 +25,7 @@ var HtmlFileTransport = FacadeJS['w-iframe-htmlfile'] = function (ri, trans_url)
// if (window.console)
// console.log('cb', e, t, typeof t);
switch(t) {
- case 'open':
- // should get a proper messsage from now on.
- that.iframeObj.loaded();
- that.ri._didOpen();
- break;
case 'close':
- that.cleanup();
if (e) {
that.ri._didClose(e.status, e.reason);
} else {
diff --git a/lib/trans-iframe-within.js b/lib/trans-iframe-within.js
index 0997b93..c0fce64 100644
--- a/lib/trans-iframe-within.js
+++ b/lib/trans-iframe-within.js
@@ -1,15 +1,12 @@
var postMessage = function (type, messages) {
var msg = JSON.stringify(messages);
- if(parent !== window) {
+ if(parent !== _window) {
parent.postMessage(type + msg, '*');
}
};
var FacadeJS = function() {};
FacadeJS.prototype._debug = function () {};
-FacadeJS.prototype._didOpen = function () {
- postMessage('o', []);
-};
FacadeJS.prototype._didClose = function (status, reason) {
postMessage('c', [''+status, reason]);
};
@@ -35,11 +32,9 @@ SockJS.bootstrap_iframe = function() {
var protocol = messages[1];
var trans_url = messages[2];
if (version !== SockJS.version) {
- if ('console' in _window && console.error) {
- console.error("Incompatibile SockJS! Main site uses:" +
- " \"" + version + "\", the iframe:" +
- " \"" + SockJS.version + "\".");
- }
+ utils.log("Incompatibile SockJS! Main site uses:" +
+ " \"" + version + "\", the iframe:" +
+ " \"" + SockJS.version + "\".");
}
facade = new FacadeJS();
facade._transport = new FacadeJS[protocol](facade, trans_url);
diff --git a/lib/trans-iframe.js b/lib/trans-iframe.js
index dfb7ea2..8ea1d41 100644
--- a/lib/trans-iframe.js
+++ b/lib/trans-iframe.js
@@ -14,26 +14,28 @@ IframeTransport.prototype.i_constructor = function(ri, trans_url, base_url) {
that.origin = utils.getOrigin(base_url);
that.trans_url = trans_url;
- var iframe_url = base_url + '/iframe-' + SockJS.version + '.html';
+ var iframe_url = base_url + '/iframe.html';
if (that.ri._options.devel) {
iframe_url += '?t=' + (+new Date);
}
- that.iframeObj = utils.createIframe(iframe_url, function() {
- that.cleanup();
- that.ri._didClose(1001, "Can't load iframe");
- });
+ that.iframeObj = utils.createIframe(iframe_url, function(r) {
+ that.ri._didClose(1006, "Unable to load an iframe (" + r + ")");
+ });
that.onmessage_cb = function(e){that.onmessage(e);};
utils.attachMessage(that.onmessage_cb);
};
-IframeTransport.prototype.cleanup = function() {
+IframeTransport.prototype.doCleanup = function() {
var that = this;
if (that.iframeObj) {
- that.iframeObj.cleanup();
utils.detachMessage(that.onmessage_cb);
- that.onmessage_cb = that.iframeObj = undefined;
+ if (that.iframeObj.iframe.contentWindow){
+ that.postMessage('c', []);
+ }
+ that.iframeObj.cleanup();
+ that.onmessage_cb = that.iframeObj = null;
}
};
@@ -41,20 +43,16 @@ IframeTransport.prototype.onmessage = function(e) {
var that = this;
if (e.origin !== that.origin) return;
var type = e.data.slice(0, 1);
- var msg = JSON.parse(e.data.slice(1));
+ var msg = JSON.parse(e.data.slice(1) || 'null');
switch(type) {
case 's':
that.iframeObj.loaded();
that.postMessage('s', [SockJS.version, that.protocol, that.trans_url]);
break;
- case 'o':
- that.ri._didOpen();
- break;
case 'm':
that.ri._didMessage(msg[0]);
break;
case 'c':
- that.cleanup();
that.ri._didClose(Number(msg[0]), msg[1]);
break;
}
@@ -69,9 +67,6 @@ IframeTransport.prototype.postMessage = function(type, messages) {
IframeTransport.prototype.doSend = function (message) {
this.postMessage('m', [message]);
};
-IframeTransport.prototype.doClose = function () {
- this.postMessage('c', []);
-};
IframeTransport.enabled = function() {
// postMessage misbehaves in konqueror 4.6.5 - the messages are delivered with
diff --git a/lib/trans-jsonp.js b/lib/trans-jsonp.js
index ce53c59..785d4c4 100644
--- a/lib/trans-jsonp.js
+++ b/lib/trans-jsonp.js
@@ -4,7 +4,7 @@
// everywhere.
// Known limitations:
// o you will get a spinning cursor
-// o for Konqueror a dumb timer is needed to detect network error
+// o for Konqueror a dumb timer is needed to detect errors
var JsonPTransport = SockJS.jsonp = function(ri, trans_url){
@@ -21,30 +21,13 @@ JsonPTransport.prototype = new BufferedSender();
JsonPTransport.prototype._schedule_recv = function() {
var that = this;
- var callback = function(e, t) {
- that._recv_stop = undefined;
- if (typeof t === 'undefined') {
- // messages
- for(var i=0; i < e.length; i++) {
- that.ri._didMessage(e[i]);
- }
- } else {
- switch (t) {
- case 'open':
- that.ri._didOpen();
- break;
- case 'heartbeat':
- break;
- case 'close':
- if (e) {
- that.ri._didClose(e.status, e.reason);
- } else {
- that.ri._didClose(1001, "Server closed connection");
- }
- break;
- }
+ var callback = function(data) {
+ that._recv_stop = null;
+ if (!that._is_closing) {
+ that.ri._didMessage(data);
}
- if (t !== 'close' && !that._is_closing) {
+ // The message can be a close message, and change is_closing state.
+ if (!that._is_closing) {
that._schedule_recv();
}
};
@@ -52,16 +35,16 @@ JsonPTransport.prototype._schedule_recv = function() {
jsonPGenericReceiver, callback);
};
-JsonPTransport.prototype.doClose = function(status, reason) {
- this._is_closing = true;
- if (this._recv_stop) {
- this._recv_stop();
+JsonPTransport.prototype.doCleanup = function() {
+ var that = this;
+ that._is_closing = true;
+ if (that._recv_stop) {
+ that._recv_stop();
}
- if (this._send_stop) {
- this._send_stop();
+ if (that._send_stop) {
+ that._send_stop();
}
- this._recv_stop = this._send_stop = undefined;
- this.ri._didClose(1001, "User requested");
+ that.ri = that._recv_stop = that._send_stop = null;
};
JsonPTransport.enabled = function() {
@@ -69,19 +52,21 @@ JsonPTransport.enabled = function() {
};
+// Abstract away code that handles global namespace pollution.
var jsonPReceiverWrapper = function(url, constructReceiver, user_callback) {
var id = 'a' + utils.random_string(6);
var url_id = url + '?c=' + escape(WPrefix + '.' + id);
- var callback = function(e, t) {
+ // Callback will be called exactly once.
+ var callback = function(frame) {
delete _window[WPrefix][id];
- user_callback(e, t);
+ user_callback(frame);
};
var close_script = constructReceiver(url_id, callback);
_window[WPrefix][id] = close_script;
var stop = function() {
if (_window[WPrefix][id]) {
- close_script({status:1000, reson:"Normal closure"}, 'stop');
+ _window[WPrefix][id](utils.closeFrame(1000, "JSONP user aborted read"));
}
};
return stop;
@@ -92,45 +77,44 @@ var jsonPReceiverWrapper = function(url, constructReceiver, user_callback) {
// and jQuery-JSONP:
// https://code.google.com/p/jquery-jsonp/source/browse/trunk/core/jquery.jsonp.js
var jsonPGenericReceiver = function(url, callback) {
+ var tref;
var script = _document.createElement('script');
- var script2;
- var close_script = function(v, t) {
- setTimeout(function(){
- if (typeof script2 !== 'undefined') {
- script2.parentNode.removeChild(script2);
- script2 = undefined;
- }
- if (typeof script !== 'undefined') {
- callback(v, t);
- script.parentNode.removeChild(script);
- script.onreadystatechange = script.onerror = script.onload = script.onclick = null;
- delete script;
- script = callback = undefined;
- }
- }, 0);
+ var script2; // Opera synchronous load trick.
+ var close_script = function(frame) {
+ if (script2) {
+ script2.parentNode.removeChild(script2);
+ script2 = null;
+ }
+ if (script) {
+ clearTimeout(tref);
+ script.parentNode.removeChild(script);
+ script.onreadystatechange = script.onerror =
+ script.onload = script.onclick = null;
+ script = null;
+ callback(frame);
+ callback = null;
+ }
};
script.id = 'a' + utils.random_string(8);
script.src = url;
script.type = 'text/javascript';
script.charset = 'UTF-8';
- script.onerror = function(e) {
- close_script({status:1001, reason:"Onerror triggered on script"},
- 'close');
+ script.onerror = function() {
+ close_script(utils.closeFrame(1006, "JSONP script loaded abnormally (onerror)"));
};
script.onload = function(e) {
- close_script({status:1001, reason:"Onload triggered on script"},
- 'close');
+ close_script(utils.closeFrame(1006, "JSONP script loaded abnormally (onload)"));
};
script.onreadystatechange = function(e) {
- if (script.readyState == 'loaded' || script.readyState == 'complete') {
- if (typeof script !== 'undefined' && script.htmlFor && script.onclick) {
+ if (/loaded|closed/.test(script.readyState)) {
+ if (script && script.htmlFor && script.onclick) {
try {
+ // In IE, actually execute the script.
script.onclick();
} catch (x) {}
}
- if (typeof script !== 'undefined') {
- close_script({status:1001, reason:"Onreadystatechange triggered on script"},
- 'close');
+ if (script) {
+ close_script(utils.closeFrame(1006, "JSONP script loaded abnormally (onreadystatechange)"));
}
}
};
@@ -160,21 +144,18 @@ var jsonPGenericReceiver = function(url, callback) {
script2 = _document.createElement('script');
script2.text = "try{document.getElementById('"+script.id+"').onerror();}catch(x){};";
script.async = script2.async = false;
- } else {
- // konqueror. fallback to a stupid timer, 5 seconds shall be plenty.
- setTimeout(function(){
- if (script && script.onerror) {
- script.onerror();
- }
- }, 5000);
}
} else {
script.async = true;
}
+ // Fallback mostly for Konqueror - stupid timer, 5 seconds shall be plenty.
+ tref = setTimeout(function(){
+ close_script(utils.closeFrame(1006, "JSONP script loaded abnormally (timeout)"));
+ }, 5000);
var head = _document.getElementsByTagName('head')[0];
head.insertBefore(script, head.firstChild);
- if (script2){
+ if (script2) {
head.insertBefore(script2, head.firstChild);
}
return close_script;
diff --git a/lib/trans-websocket.js b/lib/trans-websocket.js
index a3fef09..d2ce5b5 100644
--- a/lib/trans-websocket.js
+++ b/lib/trans-websocket.js
@@ -8,13 +8,12 @@ var WebSocketTransport = SockJS.websocket = function(ri, trans_url) {
}
that.ri = ri;
that.url = url;
- var ws = that.ws = new WebSocket(that.url);
- ws.onopen = function(e){that.ri._didOpen();};
- ws.onmessage = function(e){that.ri._didMessage(e.data);};
- ws.onclose = function(e){
- ws.onopen = ws.onmessage = ws.onclose = null;
- that.ws = undefined;
- that.ri._didClose(1001, "Socket closed");
+ that.ws = new WebSocket(that.url);
+ that.ws.onmessage = function(e) {
+ that.ri._didMessage(e.data);
+ };
+ that.ws.onclose = function() {
+ that.ri._didClose(1006, "WebSocket connection broken");
};
};
@@ -22,8 +21,14 @@ WebSocketTransport.prototype.doSend = function(data) {
this.ws.send(data);
};
-WebSocketTransport.prototype.doClose = function() {
- this.ws.close();
+WebSocketTransport.prototype.doCleanup = function() {
+ var that = this;
+ var ws = that.ws;
+ if (ws) {
+ ws.onmessage = ws.onclose = null;
+ ws.close();
+ that.ri = that.ws = null;
+ }
};
WebSocketTransport.enabled = function() {
diff --git a/lib/utils.js b/lib/utils.js
index 41ef971..d59da4a 100644
--- a/lib/utils.js
+++ b/lib/utils.js
@@ -1,11 +1,9 @@
var utils = {};
utils.random_string = function(letters, max) {
var chars = 'abcdefghijklmnopqrstuvwxyz0123456789_';
- if (typeof max === 'undefined') {
- max = chars.length;
- }
+ max = max || chars.length;
var i, ret = [];
- for(i=0; i<letters;i++) {
+ for(i=0; i < letters;i++) {
ret.push( chars[Math.floor(Math.random() * max)] );
}
return ret.join('');
@@ -21,27 +19,34 @@ utils.random_number_string = function(max) {
};
utils.attachMessage = function(listener) {
+ utils.attachEvent('message', listener);
+};
+utils.attachEvent = function(event, listener) {
if (typeof _window.addEventListener !== 'undefined') {
- _window.addEventListener("message", listener, false);
+ _window.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("onmessage", listener);
+ _document.attachEvent("on" + event, listener);
// I get 'window' for ie8.
- _window.attachEvent("onmessage", listener);
+ _window.attachEvent("on" + event, listener);
}
};
utils.detachMessage = function(listener) {
+ utils.detachEvent('message', listener);
+};
+utils.detachEvent = function(event, listener) {
if (typeof _window.addEventListener !== 'undefined') {
- _window.removeEventListener("message", listener, false);
+ _window.removeEventListener(event, listener, false);
} else {
- _document.detachEvent("onmessage", listener);
- _window.detachEvent("onmessage", listener);
+ _document.detachEvent("on" + event, listener);
+ _window.detachEvent("on" + event, listener);
}
};
+
// Assuming that url looks like: http://asdasd:111/asd
utils.getOrigin = function(url) {
url += '/';
@@ -150,18 +155,32 @@ utils.createIframe = function (iframe_url, error_callback) {
iframe.src = iframe_url;
iframe.style.display = 'none';
iframe.style.position = 'absolute';
- iframe.onerror = onerror;
+ iframe.onerror = function(){onerror('onerror');};
iframe.onload = function() {
// `onload` is triggered before scripts on the iframe are
// executed. Give it few seconds to actually load stuff.
clearTimeout(tref);
- tref = setTimeout(onerror, 2000);
+ tref = setTimeout(function(){onerror('onload timeout');}, 2000);
};
_document.body.appendChild(iframe);
- tref = setTimeout(onerror, 5000);
+ tref = setTimeout(function(){onerror('timeout');}, 5000);
return {
iframe: iframe,
cleanup: cleanup,
loaded: unattach
};
};
+
+utils.closeFrame = function (status, reason) {
+ return 'c'+JSON.stringify([status, reason]);
+};
+
+utils.userSetStatus = function (status) {
+ return status === 1000 || (status >= 3000 && status <= 4999);
+};
+
+utils.log = function() {
+ if (_window.console && console.log) {
+ console.log.apply(console, arguments);
+ }
+};
diff --git a/tests-src/test-factory.coffee b/tests-src/test-factory.coffee
index 0aafc2b..a4a5dcb 100644
--- a/tests-src/test-factory.coffee
+++ b/tests-src/test-factory.coffee
@@ -115,23 +115,33 @@ factor_user_close = (protocol) ->
expect(4)
r = new SockJS(sockjs_url + '/echo', [protocol])
ok(r)
+ counter = 0
r.onopen = (e) ->
- ok(true)
+ counter += 1
+ ok(counter is 1)
r.close(3000, "User message")
+ ok(counter is 1)
+ r.onmessage = () ->
+ fail(true)
+ counter += 1
r.onclose = (e) ->
- equals(e.status, 3000)
- equals(e.reason, "User message")
+ counter += 1
+ log('user_close ' + e.status + ' ' + e.reason)
+ ok(counter is 2)
start()
factor_server_close = (protocol) ->
return ->
- expect(3)
+ expect(4)
r = new SockJS(sockjs_url + '/close', [protocol])
ok(r)
r.onopen = (e) ->
ok(true)
+ r.onmessage = (e) ->
+ fail(true)
r.onclose = (e) ->
- equals(e.status, 1001)
+ equals(e.status, 3000)
+ equals(e.reason, "Go away!")
start()
test_invalid_url_404 = (protocol) ->
@@ -139,9 +149,13 @@ test_invalid_url_404 = (protocol) ->
expect(2)
r = new SockJS(sockjs_url + '/invalid_url', [protocol])
ok(r)
+ counter =
r.onopen = (e) ->
fail(true)
+ r.onmessage = (e) ->
+ fail(true)
r.onclose = (e) ->
+ log('404', e)
equals(e.status, 2000)
start()
@@ -153,6 +167,7 @@ test_invalid_url_500 = (protocol) ->
r.onopen = (e) ->
fail(true)
r.onclose = (e) ->
+ log('500', e)
equals(e.status, 2000)
start()
@@ -164,5 +179,6 @@ test_invalid_url_port = (protocol) ->
r.onopen = (e) ->
fail(true)
r.onclose = (e) ->
+ log('port', e)
equals(e.status, 2000)
start()
--
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