[Pkg-javascript-commits] [sockjs-client] 33/434: Refactoring the world continues.

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 b6485b427c1f3bbec054492e3e9bf440a6d08161
Author: Marek Majkowski <majek04 at gmail.com>
Date:   Mon Aug 1 11:45:32 2011 +0100

    Refactoring the world continues.
---
 lib/main.js                                     |   4 +-
 lib/sockjs.js                                   |   8 +-
 lib/trans-iframe-eventsource.js                 |  16 ++--
 lib/trans-iframe-htmlfile.js                    |  41 +++------
 lib/trans-iframe-within.js                      |  11 ++-
 lib/trans-iframe.js                             |  19 ++--
 lib/{trans-jsonp.js => trans-jsonp-receiver.js} |  80 +----------------
 lib/trans-jsonp-sender.js                       |   8 ++
 lib/trans-jsonp.js                              | 110 +++---------------------
 lib/utils.js                                    |  15 +++-
 tests-src/test-factory.coffee                   |   7 ++
 11 files changed, 85 insertions(+), 234 deletions(-)

diff --git a/lib/main.js b/lib/main.js
index e617bbf..fbfac9d 100644
--- a/lib/main.js
+++ b/lib/main.js
@@ -8,6 +8,7 @@ SockJS = (function(){
 <!-- include lib/sockjs.js -->
 <!-- include lib/trans-websocket.js -->
 <!-- include lib/trans-jsonp-sender.js -->
+<!-- include lib/trans-jsonp-receiver.js -->
 <!-- include lib/trans-jsonp.js -->
 <!-- include lib/trans-iframe.js -->
 <!-- include lib/trans-iframe-within.js -->
@@ -15,4 +16,5 @@ SockJS = (function(){
 <!-- include lib/trans-iframe-htmlfile.js -->
                   return SockJS;
           })();
-if ('_sockjs_onload' in window) setTimeout(function(){_sockjs_onload();}, 0);
+if ('_sockjs_onload' in window) setTimeout(_sockjs_onload, 1);
+
diff --git a/lib/sockjs.js b/lib/sockjs.js
index cc2d847..01f5f1c 100644
--- a/lib/sockjs.js
+++ b/lib/sockjs.js
@@ -36,7 +36,7 @@ SockJS.prototype._debug = function() {
 SockJS.prototype._dispatchOpen = function() {
     var that = this;
     if (that.readyState !== SockJS.CONNECTING)
-            throw Error('INVALID_STATE_ERR');
+            throw new Error('INVALID_STATE_ERR');
     that.readyState = SockJS.OPEN;
     that.dispatchEvent(new SimpleEvent("open"));
 };
@@ -54,7 +54,7 @@ SockJS.prototype._didClose = function(status, reason) {
     if (that.readyState !== SockJS.CONNECTING &&
         that.readyState !== SockJS.OPEN &&
         that.readyState !== SockJS.CLOSING)
-            throw Error('INVALID_STATE_ERR');
+            throw new Error('INVALID_STATE_ERR');
     that._transport.doCleanup();
     that._transport = null;
     var close_event = new SimpleEvent("close", {status: status, reason: reason});
@@ -119,7 +119,7 @@ SockJS.prototype._try_next_protocol = function(close_event) {
 SockJS.prototype.close = function(status, reason) {
     var that = this;
     if (status && !utils.userSetStatus(status))
-        throw Error("INVALID_ACCESS_ERR");
+        throw new Error("INVALID_ACCESS_ERR");
     if(that.readyState !== SockJS.CONNECTING &&
        that.readyState !== SockJS.OPEN) {
         return false;
@@ -132,7 +132,7 @@ SockJS.prototype.close = function(status, reason) {
 SockJS.prototype.send = function(data) {
     var that = this;
     if (that.readyState === SockJS.CONNECTING)
-        throw Error('INVALID_STATE_ERR');
+        throw new Error('INVALID_STATE_ERR');
     if (that.readyState === SockJS.OPEN) {
         that._transport.doSend(JSON.stringify(data));
     }
diff --git a/lib/trans-iframe-eventsource.js b/lib/trans-iframe-eventsource.js
index 359cad2..d42d04e 100644
--- a/lib/trans-iframe-eventsource.js
+++ b/lib/trans-iframe-eventsource.js
@@ -20,8 +20,8 @@ var EventSourceTransport = FacadeJS['w-iframe-eventsource'] = function (ri, tran
     var es = that.es = new EventSource(url);
     es.onmessage = function(e) {that.ri._didMessage(unescape(e.data));};
     es.onerror = function(e) {
-        // EventSource reconnects automatically by default.
-        that.cleanup();
+        // EventSource reconnects automatically.
+        es.close();
         that.ri._didClose(1001, "Socket closed.");
     };
     that.send_constructor(ajaxSender);
@@ -29,19 +29,13 @@ var EventSourceTransport = FacadeJS['w-iframe-eventsource'] = function (ri, tran
 // Inheritnace
 EventSourceTransport.prototype = new BufferedSender();
 
-EventSourceTransport.prototype.cleanup = function() {
+EventSourceTransport.prototype.doCleanup = function() {
     var that = this;
     var es = that.es;
     es.onmessage = es.onerror = null;
     es.close();
-    that.es = null;
-};
-
-EventSourceTransport.prototype.doClose = function(data) {
-    var that = this;
-    that.cleanup();
-    // Send didClose out of band.
-    setTimeout(function(){that.ri._didClose(1001, "Socket closed.");}, 0);
+    that.send_destructor();
+    that.es = that.ri = null;
 };
 
 
diff --git a/lib/trans-iframe-htmlfile.js b/lib/trans-iframe-htmlfile.js
index a1ef1be..23086c4 100644
--- a/lib/trans-iframe-htmlfile.js
+++ b/lib/trans-iframe-htmlfile.js
@@ -1,7 +1,7 @@
 var HtmlFileIframeTransport = SockJS['iframe-htmlfile'] = function () {
     var that = this;
     that.protocol = 'w-iframe-htmlfile';
-    that.i_constructor.apply(this, arguments);
+    that.i_constructor.apply(that, arguments);
 };
 // Inheritance.
 HtmlFileIframeTransport.prototype = new IframeTransport();
@@ -20,46 +20,29 @@ var HtmlFileTransport = FacadeJS['w-iframe-htmlfile'] = function (ri, trans_url)
 
     that.id = 'a' + utils.random_string(6, 26);
     var iframe_url = trans_url + '/htmlfile?c=' + escape(WPrefix + '.' + that.id);
-    var callback = function(e, t) {
-        // alert('cb' + e + ' ' + t);
-        // if (window.console)
-        //     console.log('cb', e, t, typeof t);
-        switch(t) {
-        case 'close':
-            if (e) {
-                that.ri._didClose(e.status, e.reason);
-            } else {
-                that.ri._didClose(1001, "Server closed iframe");
-            }
-            break;
-        }
-        if (typeof t === 'undefined') {
-            that.ri._didMessage(e);
+    that.is_loaded = false;
+    var callback = function(data) {
+        if (!that.is_loaded) {
+            that.is_loaded = true;
+            that.iframeObj.loaded();
         }
+        that.ri._didMessage(data);
     };
     _window[WPrefix][that.id] = callback;
 
-    that.iframeObj = utils.createIframe(iframe_url, function() {
-                                            that.cleanup();
-                                            that.ri._didClose(1001, "Can't load iframe");
+    that.iframeObj = utils.createIframe(iframe_url, function(e) {
+                                            that.doCleanup();
+                                            that.ri._didClose(1001, "Can't load htmlfile iframe (" + e + ")");
                                         });
 };
 // Inheritnace
 HtmlFileTransport.prototype = new BufferedSender();
 
-HtmlFileTransport.prototype.cleanup = function() {
+HtmlFileTransport.prototype.doCleanup = function() {
     var that = this;
     if (that.iframeObj) {
         that.iframeObj.cleanup();
         delete _window[WPrefix][that.id];
     }
+    that.send_destructor();
 };
-
-HtmlFileTransport.prototype.doClose = function(data) {
-    var that = this;
-    that.cleanup();
-    // Send didClose out of band.
-    setTimeout(function(){that.ri._didClose(1001, "Socket closed.");}, 0);
-};
-
-
diff --git a/lib/trans-iframe-within.js b/lib/trans-iframe-within.js
index b392c9d..a43a81c 100644
--- a/lib/trans-iframe-within.js
+++ b/lib/trans-iframe-within.js
@@ -7,18 +7,17 @@ var postMessage = function (type, data) {
 };
 
 var FacadeJS = function() {};
-FacadeJS.prototype._debug = function () {};
 FacadeJS.prototype._didClose = function (status, reason) {
     postMessage('t', utils.closeFrame(status, reason));
 };
 FacadeJS.prototype._didMessage = function (frame) {
     postMessage('t', frame);
 };
-FacadeJS.prototype.send = function (data) {
+FacadeJS.prototype._doSend = function (data) {
     this._transport.doSend(data);
 };
-FacadeJS.prototype.close = function () {
-    this._transport.doClose();
+FacadeJS.prototype._doCleanup = function () {
+    this._transport.doCleanup();
 };
 
 SockJS.bootstrap_iframe = function() {
@@ -42,10 +41,10 @@ SockJS.bootstrap_iframe = function() {
             facade._transport = new FacadeJS[protocol](facade, trans_url);
             break;
         case 'm':
-            facade.send(data);
+            facade._doSend(data);
             break;
         case 'c':
-            facade.close();
+            facade._doCleanup();
             facade = null;
             break;
         }
diff --git a/lib/trans-iframe.js b/lib/trans-iframe.js
index a3cb88d..b68e07d 100644
--- a/lib/trans-iframe.js
+++ b/lib/trans-iframe.js
@@ -23,7 +23,7 @@ IframeTransport.prototype.i_constructor = function(ri, trans_url, base_url) {
                                             that.ri._didClose(1006, "Unable to load an iframe (" + r + ")");
                                         });
 
-    that.onmessage_cb = function(e){that.onmessage(e);};
+    that.onmessage_cb = utils.bind(that.onmessage, that);
     utils.attachMessage(that.onmessage_cb);
 };
 
@@ -31,10 +31,19 @@ IframeTransport.prototype.doCleanup = function() {
     var that = this;
     if (that.iframeObj) {
         utils.detachMessage(that.onmessage_cb);
-        if (that.iframeObj.iframe.contentWindow){
-            that.postMessage('c');
-        }
-        that.iframeObj.cleanup();
+        try {
+            // When the iframe is not loaded, IE raises an exception
+            // on 'contentWindow'.
+            if (that.iframeObj.iframe.contentWindow) {
+                that.postMessage('c');
+            }
+        } catch (x) {}
+        var iframeObj = that.iframeObj;
+        // Give the iframe some time for cleanup.
+        setTimeout(function() {
+                       iframeObj.cleanup();
+                       iframeObj = null;
+                   }, 100);
         that.onmessage_cb  = that.iframeObj = null;
     }
 };
diff --git a/lib/trans-jsonp.js b/lib/trans-jsonp-receiver.js
similarity index 60%
copy from lib/trans-jsonp.js
copy to lib/trans-jsonp-receiver.js
index 785d4c4..696ca91 100644
--- a/lib/trans-jsonp.js
+++ b/lib/trans-jsonp-receiver.js
@@ -1,77 +1,3 @@
-// The simplest and most robust transport, using the well-know cross
-// domain hack - JSONP. This transport is quite inefficient - one
-// mssage could use up to one http request. But at least it works almost
-// everywhere.
-// Known limitations:
-//   o you will get a spinning cursor
-//   o for Konqueror a dumb timer is needed to detect errors
-
-
-var JsonPTransport = SockJS.jsonp = function(ri, trans_url){
-    utils.polluteGlobalNamespace();
-    var that = this;
-    that.ri = ri;
-    that.trans_url = trans_url;
-    that.send_constructor(jsonPGenericSender);
-    that._schedule_recv();
-};
-
-// Inheritnace
-JsonPTransport.prototype = new BufferedSender();
-
-JsonPTransport.prototype._schedule_recv = function() {
-    var that = this;
-    var callback = function(data) {
-        that._recv_stop = null;
-        if (!that._is_closing) {
-            that.ri._didMessage(data);
-        }
-        // The message can be a close message, and change is_closing state.
-        if (!that._is_closing) {
-            that._schedule_recv();
-        }
-    };
-    that._recv_stop = jsonPReceiverWrapper(that.trans_url + '/jsonp',
-                                           jsonPGenericReceiver, callback);
-};
-
-JsonPTransport.prototype.doCleanup = function() {
-    var that = this;
-    that._is_closing = true;
-    if (that._recv_stop) {
-        that._recv_stop();
-    }
-    if (that._send_stop) {
-        that._send_stop();
-    }
-    that.ri = that._recv_stop = that._send_stop = null;
-};
-
-JsonPTransport.enabled = function() {
-    return true;
-};
-
-
-// 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);
-    // Callback will be called exactly once.
-    var callback = function(frame) {
-        delete _window[WPrefix][id];
-        user_callback(frame);
-    };
-
-    var close_script = constructReceiver(url_id, callback);
-    _window[WPrefix][id] = close_script;
-    var stop = function() {
-        if (_window[WPrefix][id]) {
-            _window[WPrefix][id](utils.closeFrame(1000, "JSONP user aborted read"));
-        }
-    };
-    return stop;
-};
-
 // Parts derived from Socket.io:
 //    https://github.com/LearnBoost/socket.io/blob/0.6.17/lib/socket.io/transports/jsonp-polling.js
 // and jQuery-JSONP:
@@ -140,7 +66,7 @@ var jsonPGenericReceiver = function(url, callback) {
             } catch (x) {}
             script.async = true;
         } else if (typeof _document.attachEvent === 'function') {
-            // opera, second sync script hack
+            // Opera, second sync script hack
             script2 = _document.createElement('script');
             script2.text = "try{document.getElementById('"+script.id+"').onerror();}catch(x){};";
             script.async = script2.async = false;
@@ -149,9 +75,9 @@ var jsonPGenericReceiver = function(url, callback) {
         script.async = true;
     }
     // Fallback mostly for Konqueror - stupid timer, 5 seconds shall be plenty.
-    tref = setTimeout(function(){
+    tref = setTimeout(function() {
                           close_script(utils.closeFrame(1006, "JSONP script loaded abnormally (timeout)"));
-                      }, 5000);
+                      }, 15000);
 
     var head = _document.getElementsByTagName('head')[0];
     head.insertBefore(script, head.firstChild);
diff --git a/lib/trans-jsonp-sender.js b/lib/trans-jsonp-sender.js
index 47b12b8..95c29d3 100644
--- a/lib/trans-jsonp-sender.js
+++ b/lib/trans-jsonp-sender.js
@@ -26,6 +26,14 @@ BufferedSender.prototype.send_schedule = function(message) {
     }
 };
 
+BufferedSender.prototype.send_destructor = function() {
+    var that = this;
+    if (that._send_stop) {
+        that._send_stop();
+    }
+    that._send_stop = null;
+};
+
 var jsonPGenericSender = function(url, payload, callback) {
     var that = this;
     if (!('_send_form' in that)) {
diff --git a/lib/trans-jsonp.js b/lib/trans-jsonp.js
index 785d4c4..02bb5ae 100644
--- a/lib/trans-jsonp.js
+++ b/lib/trans-jsonp.js
@@ -23,8 +23,11 @@ JsonPTransport.prototype._schedule_recv = function() {
     var that = this;
     var callback = function(data) {
         that._recv_stop = null;
-        if (!that._is_closing) {
-            that.ri._didMessage(data);
+        if (data) {
+            // no data - heartbeat;
+            if (!that._is_closing) {
+                that.ri._didMessage(data);
+            }
         }
         // The message can be a close message, and change is_closing state.
         if (!that._is_closing) {
@@ -35,20 +38,18 @@ JsonPTransport.prototype._schedule_recv = function() {
                                            jsonPGenericReceiver, callback);
 };
 
+JsonPTransport.enabled = function() {
+    return true;
+};
+
 JsonPTransport.prototype.doCleanup = function() {
     var that = this;
     that._is_closing = true;
     if (that._recv_stop) {
         that._recv_stop();
     }
-    if (that._send_stop) {
-        that._send_stop();
-    }
-    that.ri = that._recv_stop = that._send_stop = null;
-};
-
-JsonPTransport.enabled = function() {
-    return true;
+    that.ri = that._recv_stop = null;
+    that.send_destructor();
 };
 
 
@@ -71,92 +72,3 @@ var jsonPReceiverWrapper = function(url, constructReceiver, user_callback) {
     };
     return stop;
 };
-
-// Parts derived from Socket.io:
-//    https://github.com/LearnBoost/socket.io/blob/0.6.17/lib/socket.io/transports/jsonp-polling.js
-// 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;  // 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() {
-        close_script(utils.closeFrame(1006, "JSONP script loaded abnormally (onerror)"));
-    };
-    script.onload = function(e) {
-        close_script(utils.closeFrame(1006, "JSONP script loaded abnormally (onload)"));
-    };
-    script.onreadystatechange = function(e) {
-        if (/loaded|closed/.test(script.readyState)) {
-            if (script && script.htmlFor && script.onclick) {
-                try {
-                    // In IE, actually execute the script.
-                    script.onclick();
-                } catch (x) {}
-            }
-            if (script) {
-                close_script(utils.closeFrame(1006, "JSONP script loaded abnormally (onreadystatechange)"));
-            }
-        }
-    };
-    // IE: event/htmlFor/onclick trick.
-    // One can't rely on proper order for onreadystatechange. In order to
-    // make sure, set a 'htmlFor' and 'event' properties, so that
-    // script code will be installed as 'onclick' handler for the
-    // script object. Later, onreadystatechange, manually execute this
-    // code. FF and Chrome doesn't work with 'event' and 'htmlFor'
-    // set. For reference see:
-    //   http://jaubourg.net/2010/07/loading-script-as-onclick-handler-of.html
-    // Also, read on that about script ordering:
-    //   http://wiki.whatwg.org/wiki/Dynamic_Script_Execution_Order
-    if (typeof script.async === 'undefined') {
-        // According to mozilla docs, in recent browsers script.async defaults
-        // to 'true', so we may use it to detect a good browser:
-        // https://developer.mozilla.org/en/HTML/Element/script
-        if (typeof _document.attachEvent === 'object') {
-            // ie
-            try {
-                script.htmlFor = script.id;
-                script.event = "onclick";
-            } catch (x) {}
-            script.async = true;
-        } else if (typeof _document.attachEvent === 'function') {
-            // opera, second sync script hack
-            script2 = _document.createElement('script');
-            script2.text = "try{document.getElementById('"+script.id+"').onerror();}catch(x){};";
-            script.async = script2.async = false;
-        }
-    } 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) {
-        head.insertBefore(script2, head.firstChild);
-    }
-    return close_script;
-};
diff --git a/lib/utils.js b/lib/utils.js
index d59da4a..ed3bf99 100644
--- a/lib/utils.js
+++ b/lib/utils.js
@@ -143,13 +143,14 @@ utils.createIframe = function (iframe_url, error_callback) {
         if (iframe) {
             unattach();
             iframe.parentNode.removeChild(iframe);
+            iframe.src = "about:blank";
             iframe = null;
         }
     };
-    var onerror = function() {
+    var onerror = function(r) {
         if (iframe) {
             cleanup();
-            error_callback();
+            error_callback(r);
         }
     };
     iframe.src = iframe_url;
@@ -184,3 +185,13 @@ utils.log = function() {
         console.log.apply(console, arguments);
     }
 };
+
+utils.bind = function(fun, that) {
+    if (fun.bind) {
+        return fun.bind(that);
+    } else {
+        return function() {
+            return fun.apply(that, arguments);
+        };
+    }
+};
diff --git a/tests-src/test-factory.coffee b/tests-src/test-factory.coffee
index 77bb949..3cc985d 100644
--- a/tests-src/test-factory.coffee
+++ b/tests-src/test-factory.coffee
@@ -5,6 +5,7 @@ echo_factory_factory = (protocol, messages) ->
         r = new SockJS(sockjs_url + '/echo', [protocol])
         ok(r)
         r.onopen = (e) ->
+            log('onopen', e)
             ok(true)
             r.send(a[0])
         r.onmessage = (e) ->
@@ -15,6 +16,7 @@ echo_factory_factory = (protocol, messages) ->
             else
                 r.send(a[0])
         r.onclose = (e) ->
+            log('a', ''+e)
             ok(true)
             start()
 
@@ -63,6 +65,11 @@ factor_echo_special_chars = (protocol) ->
         "\nmessage",
         "message\xff",
         "\xffmessage",
+        "A",
+        "b",
+        "c",
+        "d",
+        "e",
         "\ufffd",
         "\ufffd\u0000",
         "message\ufffd",

-- 
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