[Pkg-javascript-commits] [sockjs-client] 274/434: New infrastructure for AJAX/XHR/XDR plus tests

Tonnerre Lombard tonnerre-guest at moszumanska.debian.org
Wed Jan 8 00:47:19 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 cd6106043f5ed1e498a3b6b90f9ea5f83d8a2f9a
Author: Marek Majkowski <majek04 at gmail.com>
Date:   Mon Jan 9 17:48:16 2012 +0000

    New infrastructure for AJAX/XHR/XDR plus tests
---
 lib/dom.js                     |  17 ++++++
 lib/eventemitter.js            |  23 +++++++
 lib/index.js                   |   2 +
 lib/utils2.js                  | 132 +++++++++++++++++++++++++++++++++++++++++
 tests/html/src/domtests.coffee |  60 ++++++++++++++++++-
 tests/server.js                |  14 +++++
 6 files changed, 245 insertions(+), 3 deletions(-)

diff --git a/lib/dom.js b/lib/dom.js
index 55cc573..0fd959d 100644
--- a/lib/dom.js
+++ b/lib/dom.js
@@ -47,6 +47,23 @@ utils.detachEvent = function(event, listener) {
     }
 };
 
+var on_unload = {};
+utils.unload_add = function(listener) {
+    var ref = utils.random_string(8);
+    on_unload[ref] = listener;
+    return ref;
+};
+utils.unload_del = function(ref) {
+    if (ref in on_unload)
+        delete on_unload[ref];
+};
+
+utils.attachEvent('unload', function() {
+    for(var k in on_unload) {
+        on_unload[k]();
+    };
+});
+
 // Try to clear some headers, in order to save bandwidth. For
 // reference see:
 //   http://blog.mibbit.com/?p=143
diff --git a/lib/eventemitter.js b/lib/eventemitter.js
new file mode 100644
index 0000000..d7e492f
--- /dev/null
+++ b/lib/eventemitter.js
@@ -0,0 +1,23 @@
+var EventEmitter = function(events) {
+    this.events = events || [];
+};
+EventEmitter.prototype.emit = function(type) {
+    var that = this;
+    var args = Array.prototype.slice.call(arguments, 1);
+    if (!that.nuked && that['on'+type]) {
+        that['on'+type].apply(that, args);
+    }
+    if (utils.arrIndexOf(that.events, type) === -1) {
+        utils.log('Event ' + JSON.stringify(type) +
+                  ' not listed ' + JSON.stringify(that.events) +
+                  ' in ' + that);
+    }
+};
+
+EventEmitter.prototype.nuke = function(type) {
+    var that = this;
+    that.nuked = true;
+    for(var i=0; i<that.events.length; i++) {
+        delete that[that.events[i]];
+    }
+};
diff --git a/lib/index.js b/lib/index.js
index 1fe2aba..7648a34 100644
--- a/lib/index.js
+++ b/lib/index.js
@@ -4,7 +4,9 @@ SockJS = (function(){
               var _window = window;
 <!-- include lib/reventtarget.js -->
 <!-- include lib/simpleevent.js -->
+<!-- include lib/eventemitter.js -->
 <!-- include lib/utils.js -->
+<!-- include lib/utils2.js -->
 <!-- include lib/dom.js -->
 <!-- include lib/sockjs.js -->
 <!-- include lib/trans-websocket.js -->
diff --git a/lib/utils2.js b/lib/utils2.js
new file mode 100644
index 0000000..83f7268
--- /dev/null
+++ b/lib/utils2.js
@@ -0,0 +1,132 @@
+var XHRObject = utils.XHRObject = function(method, url, payload) {
+    var that = this;
+    utils.delay(function(){that._start(method, url, payload);});
+};
+
+XHRObject.prototype = new EventEmitter(['chunk', 'finish']);
+
+XHRObject.prototype._start = function(method, url, payload) {
+    var that = this;
+    if (_window.ActiveXObject) {
+        // IE caches POSTs
+        url += ((url.indexOf('?') === -1) ? '?' : '&') + 't='+(+new Date);
+        try {
+            that.xhr = new ActiveXObject('Microsoft.XMLHTTP');
+        } catch(x) {};
+    }
+    if (!that.xhr) {
+        that.xhr = new XMLHttpRequest();
+    }
+    that.unload_ref = utils.unload_add(function(){that._cleanup(true);});
+    try {
+        that.xhr.open(method, url, true);
+    } catch(e) {
+        // IE raises an exception on wrong port.
+        that.emit('finish', 0, '');
+        that._cleanup();
+        return;
+    };
+
+    if ('withCredentials' in that.xhr) {
+        that.xhr.withCredentials = 'true';
+    }
+
+    that.xhr.onreadystatechange = function() {
+        if (that.xhr) {
+            var x = that.xhr;
+            switch (x.readyState) {
+            case 3:
+                // IE doesn't like peeking into responseText or status on
+                // XHR and readystate=3
+                try {
+                    var status = x.status;
+                    var text = x.responseText;
+                    that.emit('chunk', status, text);
+                } catch (x) {};
+                break;
+            case 4:
+                that.emit('finish', x.status, x.responseText);
+                that._cleanup(false);
+                break;
+            }
+        }
+    };
+    that.xhr.send(payload);
+};
+
+XHRObject.prototype._cleanup = function(abort) {
+    var that = this;
+    if (!that.xhr) return;
+    utils.unload_del(that.unload_ref);
+
+    // IE needs this field to be a function
+    that.xhr.onreadystatechange = function(){};
+
+    if (abort) {
+        try {
+            that.xhr.abort();
+        } catch(x) {};
+    }
+    that.unload_ref = that.xhr = null;
+};
+
+XHRObject.prototype.close = function() {
+    var that = this;
+    that.nuke();
+    that._cleanup(true);
+};
+
+
+var XDRObject = utils.XDRObject = function(method, url, payload) {
+    var that = this;
+    utils.delay(function(){that._start(method, url, payload);});
+};
+XDRObject.prototype = new EventEmitter(['chunk', 'finish']);
+XDRObject.prototype._start = function(method, url, payload) {
+    var that = this;
+    var xdr = new XDomainRequest();
+    // IE caches even POSTs
+    url += ((url.indexOf('?') === -1) ? '?' : '&') + 't='+(+new Date);
+
+    var onerror = xdr.ontimeout = xdr.onerror = function() {
+        that.emit('finish', 0, '');
+        that._cleanup(false);
+    };
+    xdr.onprogress = function() {
+        that.emit('chunk', 200, xdr.responseText);
+    };
+    xdr.onload = function() {
+        that.emit('finish', 200, xdr.responseText);
+        that._cleanup(false);
+    };
+    that.xdr = xdr;
+    that.unload_ref = utils.unload_add(function(){that._cleanup(true);});
+    try {
+        // Fails with AccessDenied if port number is bogus
+        that.xdr.open(method, url);
+        that.xdr.send(payload);
+    } catch(x) {
+        onerror();
+    }
+};
+
+XDRObject.prototype._cleanup = function(abort) {
+    var that = this;
+    if (!that.xdr) return;
+    utils.unload_del(that.unload_ref);
+
+    that.xdr.ontimeout = that.xdr.onerror = that.xdr.onprogress =
+        that.xdr.onload = null;
+    if (abort) {
+        try {
+            that.xdr.abort();
+        } catch(x) {};
+    }
+    that.unload_ref = that.xdr = null;
+};
+
+XDRObject.prototype.close = function() {
+    var that = this;
+    that.nuke();
+    that._cleanup(true);
+};
diff --git a/tests/html/src/domtests.coffee b/tests/html/src/domtests.coffee
index d4d4eff..18eee93 100644
--- a/tests/html/src/domtests.coffee
+++ b/tests/html/src/domtests.coffee
@@ -89,10 +89,64 @@ else
                         start()
 
 
+ajax_simple_factory = (name) ->
+    asyncTest name + ' simple', ->
+        expect(2)
+        x = new u[name]('GET', '/simple.txt', null)
+        x.onfinish = (status, text) ->
+            equal(text.length, 2051)
+            equal(text.slice(-2), 'b\n')
+            start()
+
+ajax_streaming_factory = (name) ->
+    asyncTest name + ' streaming', ->
+        expect(3)
+        x = new u[name]('GET', '/streaming.txt', null)
+        chunkno = 0
+        x.onchunk = (status, text) ->
+            switch chunkno
+                when 0
+                    equal(text.length, 2049)
+                    equal(text.slice(-2), 'a\n')
+            chunkno += 1
+        x.onfinish = (status, text) ->
+            equal(text.slice(-4), 'a\nb\n')
+            start()
+
+
+test_wrong_url = (name, url, statuses) ->
+    expect(2)
+    x = new u[name]('GET', url, null)
+    x.onchunk = ->
+        fail(true)
+    x.onfinish = (status, text) ->
+        ok(u.arrIndexOf(statuses, status) isnt -1)
+        equal(text, '')
+        start()
+
+ajax_wrong_port_factory = (name) ->
+    for port in [25, 8999, 65300]
+        asyncTest name + ' wrong port ' + port, ->
+            test_wrong_url(name, 'http://localhost:'+port+'/streaming.txt', [0])
+
 
+ajax_simple_factory('XHRObject')
+if window.XDomainRequest
+    ajax_simple_factory('XDRObject')
 
+if not window.ActiveXObject
+    # Ajax streaming is not working in ie.
+    ajax_streaming_factory('XHRObject')
+if window.XDomainRequest
+    ajax_streaming_factory('XDRObject')
 
-# 1. data url
-# 2. wrong uri
-# 3. mass run - to verify mem leaks
+ajax_wrong_port_factory('XHRObject')
+if window.XDomainRequest
+    ajax_wrong_port_factory('XDRObject')
 
+asyncTest 'XHRObject wrong url', ->
+    # Opera responds with 0, all other browsers with 404
+    test_wrong_url('XHRObject', '/wrong_url_indeed.txt', [0, 404])
+if window.XDomainRequest
+    asyncTest 'XDRObject wrong url', ->
+        test_wrong_url('XDRObject', '/wrong_url_indeed.txt', [0])
diff --git a/tests/server.js b/tests/server.js
index 4abc30a..f860a8d 100644
--- a/tests/server.js
+++ b/tests/server.js
@@ -14,6 +14,20 @@ server.addListener('request', function(req, res) {
         setTimeout(function() {
             res.end('var a = 1;\n');
         }, 500);
+    } else if ( /\/streaming.txt/.test(req.url) ) {
+        res.setHeader('content-type', 'text/plain');
+        res.setHeader('Access-Control-Allow-Origin', '*')
+
+        res.writeHead(200);
+        res.write(Array(2049).join('a') + '\n');
+        setTimeout(function() {
+            res.end('b\n');
+        }, 250);
+    } else if ( /\/simple.txt/.test(req.url) ) {
+        res.setHeader('content-type', 'text/plain');
+        res.setHeader('Access-Control-Allow-Origin', '*')
+        res.writeHead(200);
+        res.end(Array(2049).join('a') + '\nb\n');
     } else if (req.url === '/config.js') {
         res.setHeader('content-type', 'application/javascript');
         res.writeHead(200);

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