Browse files

Dirty hack so essen doesn't need node.

  • Loading branch information...
1 parent 95b8c7a commit 8f2c7a09e4b26519f2f5a17e0bfae3a405a2fa8a Simon MacMullen committed Oct 3, 2011
View
2 Makefile
@@ -12,8 +12,6 @@ test: test-prep all
-run sockjs_test
test-prep: deps/sockjs-client deps/misultin deps/cowboy deps/mochiweb deps/eep0018 priv/www
- cd deps/sockjs-client && npm install
- make -C deps/sockjs-client tests/html/lib/sockjs.js tests/html/lib/tests.js
make -C deps/misultin
make -C deps/cowboy
make -C deps/mochiweb
View
16 deps/sockjs-client/tests/config.js
@@ -0,0 +1,16 @@
+exports.config = {
+ opts: {
+ sockjs_url: "/lib/sockjs.js"
+ },
+ port: process.env.PORT || 8080,
+ host: '0.0.0.0',
+
+ client_opts: {
+ // May be set to empty string if you don't need to test
+ // cross-domain features. In other case set it to a full
+ // url, like: "http://localhost:8080"
+ disabled_transports: [],
+ url: '',
+ sockjs_opts: {devel:true}
+ }
+};
View
118 deps/sockjs-client/tests/html/example-cursors.html
@@ -0,0 +1,118 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta http-equiv="X-UA-Compatible" content="IE=edge" />
+ <meta charset="UTF-8" />
+
+ <link href="data:image/x-icon;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQEAYAAABPYyMiAAAABmJLR0T///////8JWPfcAAAACXBIWXMAAABIAAAASABGyWs+AAAAF0lEQVRIx2NgGAWjYBSMglEwCkbBSAcACBAAAeaR9cIAAAAASUVORK5CYII=" rel="icon" type="image/x-icon" />
+
+ <script type="text/javascript" src="lib/sockjs.js"></script>
+ <script type="text/javascript" src="static/jquery.min.js"></script>
+
+ <script type="text/javascript" src="config.js"></script>
+
+ <style type="text/css">
+ .cursor {
+ height: 30px;
+ width: 30px;
+ position: absolute;
+ border: 1px solid grey;
+ z-index:-1;
+ }
+
+ </style>
+
+</head>
+<body>
+
+<form>
+ <select id="transport">
+ <option value="">- any - </option>
+ <option value="websocket">websocket</option>
+ <option value="xhr-streaming">xhr-streaming</option>
+ <option value="iframe-eventsource">iframe-eventsource</option>
+ <option value="iframe-htmlfile">iframe-htmlfile</option>
+ <option value="xhr-polling">xhr-polling</option>
+ <option value="iframe-xhr-polling">iframe-xhr-polling</option>
+ <option value="jsonp-polling">jsonp-polling</option>
+ </select>
+ <input type="button" value="Connect" id="connect">
+ <input type="button" value="Disconnect" id="disconnect" disabled="yes">
+</form>
+
+ Latency: <code id="latency"></code><br>
+ <code id="logs" style="height:200px; overflow:auto; display: block; border: 1px grey solid;">
+ </code>
+
+<script>
+ function log(a) {
+ if ('console' in window && 'log' in window.console) {
+ console.log(a);
+ }
+ $('#logs').append($("<code>").text(a));
+ $('#logs').append($("<br>"));
+ $('#logs').scrollTop($('#logs').scrollTop()+10000);
+ }
+
+ var sjs = null;
+ var protocol;
+ $('#connect').click(function() {
+ $('#connect').attr('disabled', true);
+ $('#disconnect').attr('disabled', false);
+ var protocol = $('#transport').val() || undefined;
+ log('[connecting] ' + protocol);
+ sjs = new SockJS(client_opts.url + '/broadcast', protocol, client_opts.sockjs_opts);
+ sjs.onopen = onopen
+ sjs.onclose = onclose;
+ sjs.onmessage = onmessage;
+ });
+ $('#disconnect').click(function() {
+ $('#disconnect').attr('disabled', true);
+ log('[disconnecting]');
+ sjs.close();
+ });
+
+ var onopen = function() {
+ log('connected ' + sjs.protocol);
+ };
+ var onclose = function(e) {
+ log('disconnected ' + e);
+ $('#connect').attr('disabled', false);
+ $('#disconnect').attr('disabled', true);
+ };
+ var myself = (''+Math.random()).substr(2);
+ var onmessage = function(e) {
+ var msg = JSON.parse(e.data);
+ if (msg.id === myself) {
+ var td = (new Date()).getTime() - msg.t;
+ $('#latency').text('' + td + ' ms');
+ }
+ var id = 'cursor_'+msg.id;
+ if ($('#'+id).length === 0) {
+ $("body").append('<div id="' + id + '" class="cursor"></div>');
+ }
+ $('#'+id).offset({top:msg.y-15, left:msg.x-15});
+ };
+ var x, y;
+ var last_x, last_y, tref;
+ $(document).mousemove(function(e) {
+ x = e.pageX; y = e.pageY;
+ if(!tref) poll();
+ });
+ var poll = function() {
+ tref = null;
+ if (last_x === x && last_y === y)
+ return;
+ var msg = {x:x, y:y, t: (new Date()).getTime(), id:myself};
+ last_x = x; last_y = y;
+ var raw_msg = JSON.stringify(msg);
+ if (sjs && sjs.readyState === SockJS.OPEN) {
+ sjs.send(raw_msg);
+ }
+ tref = setTimeout(poll, 200);
+ };
+ $('#connect').attr('disabled', false);
+ $('#disconnect').attr('disabled', true);
+</script>
+</body>
+</html>
View
19 deps/sockjs-client/tests/html/index.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta http-equiv="X-UA-Compatible" content="IE=edge" />
+ <meta charset="UTF-8" />
+
+ <link href="data:image/x-icon;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQEAYAAABPYyMiAAAABmJLR0T///////8JWPfcAAAACXBIWXMAAABIAAAASABGyWs+AAAAF0lEQVRIx2NgGAWjYBSMglEwCkbBSAcACBAAAeaR9cIAAAAASUVORK5CYII=" rel="icon" type="image/x-icon" />
+
+</head>
+<body>
+ <h1>SockJS</h1>
+ <ul>
+ <li><a href="tests-qunit.html">QUnit tests</a></li>
+ <li><a href="example-cursors.html">Cursors example</a></li>
+ <li><a href="smoke-throughput.html">Smoketest: througput</a></li>
+ <li><a href="smoke-reconnect.html">Smoketest: reconnect</a></li>
+ </ul>
+</body>
+</html>
View
0 deps/sockjs-client/tests/html/lib/.placeholder
No changes.
View
1,618 deps/sockjs-client/tests/html/lib/sockjs.js
@@ -0,0 +1,1618 @@
+// SockJS client, version 0.0.4.23.g33ec, MIT License
+// https://github.com/sockjs/sockjs-client
+
+// JSON2 by Douglas Crockford (minified).
+var JSON;JSON||(JSON={}),function(){function str(a,b){var c,d,e,f,g=gap,h,i=b[a];i&&typeof i=="object"&&typeof i.toJSON=="function"&&(i=i.toJSON(a)),typeof rep=="function"&&(i=rep.call(b,a,i));switch(typeof i){case"string":return quote(i);case"number":return isFinite(i)?String(i):"null";case"boolean":case"null":return String(i);case"object":if(!i)return"null";gap+=indent,h=[];if(Object.prototype.toString.apply(i)==="[object Array]"){f=i.length;for(c=0;c<f;c+=1)h[c]=str(c,i)||"null";e=h.length===0?"[]":gap?"[\n"+gap+h.join(",\n"+gap)+"\n"+g+"]":"["+h.join(",")+"]",gap=g;return e}if(rep&&typeof rep=="object"){f=rep.length;for(c=0;c<f;c+=1)typeof rep[c]=="string"&&(d=rep[c],e=str(d,i),e&&h.push(quote(d)+(gap?": ":":")+e))}else for(d in i)Object.prototype.hasOwnProperty.call(i,d)&&(e=str(d,i),e&&h.push(quote(d)+(gap?": ":":")+e));e=h.length===0?"{}":gap?"{\n"+gap+h.join(",\n"+gap)+"\n"+g+"}":"{"+h.join(",")+"}",gap=g;return e}}function quote(a){escapable.lastIndex=0;return escapable.test(a)?'"'+a.replace(escapable,function(a){var b=meta[a];return typeof b=="string"?b:"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+a+'"'}function f(a){return a<10?"0"+a:a}"use strict",typeof Date.prototype.toJSON!="function"&&(Date.prototype.toJSON=function(a){return isFinite(this.valueOf())?this.getUTCFullYear()+"-"+f(this.getUTCMonth()+1)+"-"+f(this.getUTCDate())+"T"+f(this.getUTCHours())+":"+f(this.getUTCMinutes())+":"+f(this.getUTCSeconds())+"Z":null},String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(a){return this.valueOf()});var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={"\b":"\\b","\t":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},rep;typeof JSON.stringify!="function"&&(JSON.stringify=function(a,b,c){var d;gap="",indent="";if(typeof c=="number")for(d=0;d<c;d+=1)indent+=" ";else typeof c=="string"&&(indent=c);rep=b;if(!b||typeof b=="function"||typeof b=="object"&&typeof b.length=="number")return str("",{"":a});throw new Error("JSON.stringify")}),typeof JSON.parse!="function"&&(JSON.parse=function(text,reviver){function walk(a,b){var c,d,e=a[b];if(e&&typeof e=="object")for(c in e)Object.prototype.hasOwnProperty.call(e,c)&&(d=walk(e,c),d!==undefined?e[c]=d:delete e[c]);return reviver.call(a,b,e)}var j;text=String(text),cx.lastIndex=0,cx.test(text)&&(text=text.replace(cx,function(a){return"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)}));if(/^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,""))){j=eval("("+text+")");return typeof reviver=="function"?walk({"":j},""):j}throw new SyntaxError("JSON.parse")})}()
+
+
+// [*] Including lib/index.js
+// Public object
+SockJS = (function(){
+ var _document = document;
+ var _window = window;
+
+// [*] Including lib/reventtarget.js
+/* Simplified implementation of DOM2 EventTarget.
+ * http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-EventTarget
+ */
+var REventTarget = function() {};
+REventTarget.prototype.addEventListener = function (eventType, listener) {
+ if(!this._listeners) {
+ this._listeners = {};
+ }
+ if(!(eventType in this._listeners)) {
+ this._listeners[eventType] = [];
+ }
+ var arr = this._listeners[eventType];
+ if(utils.arrIndexOf(arr, listener) === -1) {
+ arr.push(listener);
+ }
+ return;
+};
+
+REventTarget.prototype.removeEventListener = function (eventType, listener) {
+ if(!(this._listeners && (eventType in this._listeners))) {
+ return;
+ }
+ var arr = this._listeners[eventType];
+ var idx = utils.arrIndexOf(arr, listener);
+ if (idx !== -1) {
+ if(arr.length > 1) {
+ this._listeners[eventType] = arr.slice(0, idx).concat( arr.slice(idx+1) );
+ } else {
+ delete this._listeners[eventType];
+ }
+ return;
+ }
+ return;
+};
+
+REventTarget.prototype.dispatchEvent = function (event) {
+ var t = event.type;
+ var args = Array.prototype.slice.call(arguments, 0);
+ if (this['on'+t]) {
+ this['on'+t].apply(this, args);
+ }
+ if (this._listeners && t in this._listeners) {
+ for(var i=0; i < this._listeners[t].length; i++) {
+ this._listeners[t][i].apply(this, args);
+ }
+ }
+};
+// [*] End of lib/reventtarget.js
+
+
+// [*] Including lib/simpleevent.js
+var SimpleEvent = function(type, obj) {
+ this.type = type;
+ if (typeof obj !== 'undefined') {
+ for(var k in obj) {
+ if (!obj.hasOwnProperty(k)) continue;
+ this[k] = obj[k];
+ }
+ }
+};
+
+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(', ') + ')';
+};
+// [*] End of lib/simpleevent.js
+
+
+// [*] Including lib/utils.js
+var utils = {};
+var random_string_chars = ['a','b','c','d','e','f','g','h','i','j',
+ 'k','l','m','n','o','p','q','r','s','t',
+ 'u','v','w','x','y','z',
+ '0','1','2','3','4','5','6','7','8','9','_'];
+utils.random_string = function(letters, max) {
+ max = max || random_string_chars.length;
+ var i, ret = [];
+ for(i=0; i < letters; i++) {
+ ret.push( random_string_chars[Math.floor(Math.random() * max)] );
+ }
+ return ret.join('');
+};
+utils.random_number = function(max) {
+ return Math.floor(Math.random() * max);
+};
+utils.random_number_string = function(max) {
+ var s = ''+utils.random_number(max);
+ var t = (''+(max - 1)).length;
+ while (s.length < t) {s = '0' + s;}
+ return s;
+};
+
+utils.attachMessage = function(listener) {
+ utils.attachEvent('message', listener);
+};
+utils.attachEvent = function(event, listener) {
+ if (typeof _window.addEventListener !== 'undefined') {
+ _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("on" + event, listener);
+ // I get 'window' for ie8.
+ _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(event, listener, false);
+ } else {
+ _document.detachEvent("on" + event, listener);
+ _window.detachEvent("on" + event, listener);
+ }
+};
+
+
+// Assuming that url looks like: http://asdasd:111/asd
+utils.getOrigin = function(url) {
+ url += '/';
+ var parts = url.split('/').slice(0, 3);
+ return parts.join('/');
+};
+
+utils.objectExtend = function(dst, src) {
+ for(var k in src) {
+ if (src.hasOwnProperty(k)) {
+ dst[k] = src[k];
+ }
+ }
+ return dst;
+};
+
+// Try to clear some headers, in order to save bandwidth. For
+// reference see:
+// http://blog.mibbit.com/?p=143
+// http://code.google.com/p/browsersec/wiki/Part2#Same-origin_policy_for_XMLHttpRequest
+var xhrDefaultHeaders = {
+ "User-Agent": '',
+ "Accept": '',
+ "Accept-Language": '',
+ "Content-Type": "T"
+};
+
+if (navigator &&
+ (navigator.userAgent.indexOf('Chrome')!= -1 ||
+ navigator.userAgent.indexOf('Safari') != -1)) {
+ delete xhrDefaultHeaders['User-Agent'];
+}
+
+// References:
+// http://ajaxian.com/archives/100-line-ajax-wrapper
+// http://msdn.microsoft.com/en-us/library/cc288060(v=VS.85).aspx
+utils.createXDR = function(method, url, payload, callback) {
+ var mock_xhr = {status: null, responseText:'', readyState:1};
+ var xdr = new XDomainRequest();
+ // IE caches even POSTs
+ url += ((url.indexOf('?') === -1) ? '?' : '&') + 't='+utils.random_string(8);
+ var cleanup = function() {
+ if (xdr) {
+ onerror = xdr.onerror = xdr.ontimeout = xdr.onprogress =
+ xdr.onload = null;
+ try {
+ xdr.abort();
+ } catch (x) {}
+ xdr = callback = null;
+ }
+ };
+ var onerror = xdr.ontimeout = xdr.onerror = function() {
+ mock_xhr.status = 500;
+ mock_xhr.readyState = 4;
+ callback(mock_xhr);
+ cleanup();
+ };
+ xdr.onload = function() {
+ mock_xhr.status = 200;
+ mock_xhr.readyState = 4;
+ mock_xhr.responseText = xdr.responseText;
+ callback(mock_xhr);
+ cleanup();
+ };
+ xdr.onprogress = function() {
+ mock_xhr.status = 200;
+ mock_xhr.readyState = 3;
+ mock_xhr.responseText = xdr.responseText;
+ callback(mock_xhr);
+ };
+ try {
+ // Fails with AccessDenied if port number is bogus
+ xdr.open(method, url);
+ xdr.send(payload);
+ } catch (x) {
+ utils.delay(onerror);
+ }
+ return function (abort_reason) {
+ if (callback) {
+ callback(mock_xhr, null, abort_reason);
+ cleanup();
+ }
+ };
+};
+
+utils.createXHR = function(method, url, payload, callback) {
+ var xhr;
+ if (_window.ActiveXObject) {
+ // IE caches POSTs
+ url += ((url.indexOf('?') === -1) ? '?' : '&') + 't='+(+new Date);
+ try {
+ xhr = new ActiveXObject('Microsoft.XMLHTTP');
+ } catch(x) {}
+ }
+ if (!xhr) {
+ xhr = new XMLHttpRequest();
+ }
+ xhr.open(method, url, true);
+
+ for (var k in xhrDefaultHeaders) {
+ try {
+ xhr.setRequestHeader(k, xhrDefaultHeaders[k]);
+ } catch(x) {
+ delete xhrDefaultHeaders[k];
+ }
+ }
+ if ('withCredentials' in xhr) {
+ // Set cookies on CORS, please.
+ xhr.withCredentials = "true";
+ }
+
+ var cleanup = function() {
+ if (xhr) {
+ // IE needs this field to be a function
+ try {
+ xhr.onreadystatechange = null;
+ } catch (x) {
+ xhr.onreadystatechange = function(){};
+ }
+ // Explorer tends to keep connection open, even after the
+ // tab gets closed: http://bugs.jquery.com/ticket/5280
+ try {
+ xhr.abort();
+ } catch(e) {};
+ utils.detachEvent('unload', cleanup);
+ }
+ callback = xhr = null;
+ };
+
+ xhr.onreadystatechange = function (e) {
+ if (xhr && callback) {
+ callback(xhr, e);
+ if (xhr && xhr.readyState === 4) {
+ cleanup();
+ }
+ }
+ };
+ xhr.send(payload);
+ utils.attachEvent('unload', cleanup);
+ return function (abort_reason) {
+ if (callback) {
+ callback(xhr, null, abort_reason);
+ cleanup();
+ }
+ };
+};
+
+var WPrefix = '_jp';
+
+utils.polluteGlobalNamespace = function() {
+ if (!(WPrefix in _window)) {
+ _window[WPrefix] = {};
+ }
+};
+
+utils.createIframe = function (iframe_url, error_callback) {
+ var iframe = _document.createElement('iframe');
+ var tref;
+ var unattach = function() {
+ clearTimeout(tref);
+ // Explorer had problems with that.
+ try {iframe.onload = null;} catch (x) {}
+ iframe.onerror = null;
+ };
+ var cleanup = function() {
+ if (iframe) {
+ unattach();
+ iframe.parentNode.removeChild(iframe);
+ iframe.src = "about:blank";
+ iframe = null;
+ utils.detachEvent('unload', cleanup);
+ }
+ };
+ var onerror = function(r) {
+ if (iframe) {
+ cleanup();
+ error_callback(r);
+ }
+ };
+ iframe.src = iframe_url;
+ iframe.style.display = 'none';
+ iframe.style.position = 'absolute';
+ 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(function(){onerror('onload timeout');}, 2000);
+ };
+ _document.body.appendChild(iframe);
+ tref = setTimeout(function(){onerror('timeout');}, 5000);
+ utils.attachEvent('unload', cleanup);
+ return {
+ iframe: iframe,
+ cleanup: cleanup,
+ loaded: unattach
+ };
+};
+
+utils.createHtmlfile = function (iframe_url, error_callback) {
+ var doc = new ActiveXObject('htmlfile');
+ var tref;
+ var iframe;
+ var unattach = function() {
+ clearTimeout(tref);
+ };
+ var cleanup = function() {
+ if (doc) {
+ unattach();
+ utils.detachEvent('unload', cleanup);
+ try {
+ iframe.src = "about:blank";
+ } catch (x) {}
+ iframe.parentNode.removeChild(iframe);
+ iframe = doc = null;
+ CollectGarbage();
+ }
+ };
+ var onerror = function(r) {
+ if (doc) {
+ cleanup();
+ error_callback(r);
+ }
+ };
+
+ doc.open();
+ doc.write('<html><script>' +
+ 'document.domain="' + document.domain + '";' +
+ '</script></html>');
+ doc.close();
+ doc.parentWindow[WPrefix] = _window[WPrefix];
+ var c = doc.createElement('div');
+ doc.body.appendChild(c);
+ iframe = doc.createElement('iframe');
+ c.appendChild(iframe);
+ iframe.src = iframe_url;
+ tref = setTimeout(function(){onerror('timeout');}, 5000);
+ utils.attachEvent('unload', cleanup);
+ 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.log.apply(console, arguments);
+ }
+};
+
+utils.bind = function(fun, that) {
+ if (fun.bind) {
+ return fun.bind(that);
+ } else {
+ return function() {
+ return fun.apply(that, arguments);
+ };
+ }
+};
+
+utils.amendUrl = function(url) {
+ var dl = _document.location;
+ // falsy url means use current document location as url
+ if (!url) url = dl;
+ // '//abc' --> 'http://abc'
+ if (url.indexOf('//') === 0) {
+ url = dl.protocol + url;
+ }
+ // '/abc' --> 'http://localhost:80/abc'
+ if (url.indexOf('/') === 0) {
+ url = dl.protocol + '//' + dl.host + url;
+ }
+ url = url.replace(/[/]+$/,''); // strip trailing slashes
+ return url;
+};
+
+// IE doesn't support [].indexOf.
+utils.arrIndexOf = function(arr, obj){
+ for(var i=0; i < arr.length; i++){
+ if(arr[i] === obj){
+ return i;
+ }
+ }
+ return -1;
+};
+
+utils.delay = function(t, fun) {
+ if(typeof t === 'function') {
+ fun = t;
+ t = 0;
+ }
+ return setTimeout(fun, t);
+};
+// [*] End of lib/utils.js
+
+
+// [*] Including lib/sockjs.js
+var SockJS = function(url, protocols, options) {
+ var that = this;
+ that._options = {devel: false, debug: false, chunking: undefined};
+ if (options) {
+ utils.objectExtend(that._options, options);
+ }
+ that._base_url = utils.amendUrl(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',
+ 'xhr-streaming',
+ 'iframe-eventsource',
+ 'iframe-htmlfile',
+ 'xhr-polling',
+ 'iframe-xhr-polling',
+ 'jsonp-polling'];
+ switch(typeof protocols) {
+ case 'undefined': break;
+ case 'string': that._protocols = [protocols]; break;
+ default: that._protocols = protocols; break;
+ }
+ that.protocol = null;
+ that.readyState = SockJS.CONNECTING;
+ that._didClose();
+};
+// Inheritance
+SockJS.prototype = new REventTarget();
+
+SockJS.version = "0.0.4.23.g33ec";
+
+SockJS.CONNECTING = 0;
+SockJS.OPEN = 1;
+SockJS.CLOSING = 2;
+SockJS.CLOSED = 3;
+
+SockJS.prototype._debug = function() {
+ if (this._options.debug)
+ utils.log.apply(utils, arguments);
+};
+
+SockJS.prototype._dispatchOpen = function() {
+ var that = this;
+ if (that.readyState === SockJS.CONNECTING) {
+ if (that._transport_tref) {
+ clearTimeout(that._transport_tref);
+ that._transport_tref = null;
+ }
+ that.readyState = SockJS.OPEN;
+ that.dispatchEvent(new SimpleEvent("open"));
+ } else {
+ // The server might have been restarted, and lost track of our
+ // connection.
+ that._didClose(1006, "Server lost session");
+ }
+};
+
+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) {
+ var that = this;
+ if (that.readyState !== SockJS.CONNECTING &&
+ that.readyState !== SockJS.OPEN &&
+ that.readyState !== SockJS.CLOSING)
+ throw new Error('INVALID_STATE_ERR');
+ if (that._transport)
+ that._transport.doCleanup();
+ that._transport = null;
+ if (that._transport_tref) {
+ clearTimeout(that._transport_tref);
+ that._transport_tref = null;
+ }
+ var close_event = new SimpleEvent("close", {status: status, reason: reason});
+
+ if (!utils.userSetStatus(status) && that.readyState === SockJS.CONNECTING) {
+ if (that._try_next_protocol(close_event)) {
+ that._transport_tref = setTimeout(
+ function() {
+ if (that.readyState === SockJS.CONNECTING) {
+ // I can't understand how it is possible to run
+ // this timer, when the state is CLOSED, but
+ // apparently in IE everythin is possible.
+ that._didClose(2007,
+ "Transport timeouted");
+ }
+ }, 5001);
+ return;
+ }
+ close_event = new SimpleEvent("close", {status: 2000,
+ reason: "All transports failed",
+ last_event: close_event});
+ }
+ that.readyState = SockJS.CLOSED;
+
+ utils.delay(function() {
+ that.dispatchEvent(close_event);
+ });
+};
+
+SockJS.prototype._didMessage = function(data) {
+ var that = this;
+ var type = data.slice(0, 1);
+ switch(type) {
+ case 'o':
+ that._dispatchOpen();
+ break;
+ case 'a':
+ var payload = JSON.parse(data.slice(1) || '[]');
+ for(var i=0; i < payload.length; i++){
+ that._dispatchMessage(payload[i]);
+ }
+ break;
+ case 'm':
+ var payload = JSON.parse(data.slice(1) || 'null');
+ that._dispatchMessage(payload);
+ break;
+ case 'c':
+ var payload = JSON.parse(data.slice(1) || '[]');
+ that._didClose(payload[0], payload[1]);
+ break;
+ case 'h':// heartbeat, ignore
+ break;
+ }
+};
+
+SockJS.prototype._try_next_protocol = function(close_event) {
+ var that = this;
+ if (that.protocol) {
+ that._debug('Closed transport:', that.protocol, ''+close_event);
+ that.protocol = null;
+ }
+
+ while(1) {
+ var protocol = that.protocol = that._protocols.shift();
+ if (!protocol) {
+ return false;
+ }
+ // Some protocols require chunking, we may need to run the
+ // test beforehand.
+ if (SockJS[protocol] &&
+ SockJS[protocol].need_chunking === true &&
+ that._options.chunking === undefined) {
+ that._protocols.unshift(protocol);
+ that.protocol = 'chunking-test';
+ // Assert false, in case test timeouts.
+ that._options.chunking = false;
+ chunkingTest(that._base_url, function(chunking) {
+ that._options.chunking = chunking;
+ that._try_next_protocol();
+ }, that._options);
+ return true;
+ }
+
+ if (!SockJS[protocol] ||
+ (SockJS[protocol].need_chunking === true &&
+ that._options.chunking !== true) ||
+ !SockJS[protocol].enabled(that._options)) {
+ that._debug('Skipping transport:', protocol);
+ } else {
+ that._debug('Opening transport:', protocol);
+ that._transport = new SockJS[protocol](that, that._trans_url,
+ that._base_url);
+ return true;
+ }
+ }
+};
+
+SockJS.prototype.close = function(status, reason) {
+ var that = this;
+ if (status && !utils.userSetStatus(status))
+ throw new Error("INVALID_ACCESS_ERR");
+ if(that.readyState !== SockJS.CONNECTING &&
+ that.readyState !== SockJS.OPEN) {
+ return false;
+ }
+ that.readyState = SockJS.CLOSING;
+ that._didClose(status || 1000, reason || "Normal closure");
+ return true;
+};
+
+SockJS.prototype.send = function(data) {
+ var that = this;
+ if (that.readyState === SockJS.CONNECTING)
+ throw new Error('INVALID_STATE_ERR');
+ if (that.readyState === SockJS.OPEN) {
+ that._transport.doSend(JSON.stringify(data));
+ }
+ return true;
+};
+// [*] End of lib/sockjs.js
+
+
+// [*] Including lib/trans-websocket.js
+var WebSocketTransport = SockJS.websocket = function(ri, trans_url) {
+ var that = this;
+ var url = trans_url + '/websocket';
+ if (url.slice(0, 5) === 'https') {
+ url = 'wss' + url.slice(5);
+ } else {
+ url = 'ws' + url.slice(4);
+ }
+ that.ri = ri;
+ that.url = url;
+ var Constructor = window.WebSocket || window.MozWebSocket;
+ that.ws = new Constructor(that.url);
+ that.ws.onmessage = function(e) {
+ that.ri._didMessage(e.data);
+ };
+ that.ws.onclose = function() {
+ that.ri._didMessage(utils.closeFrame(1006, "WebSocket connection broken"));
+ };
+};
+
+WebSocketTransport.prototype.doSend = function(data) {
+ this.ws.send(data);
+};
+
+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() {
+ return !!(window.WebSocket || window.MozWebSocket);
+};
+// [*] End of lib/trans-websocket.js
+
+
+// [*] Including lib/trans-sender.js
+var BufferedSender = function() {};
+BufferedSender.prototype.send_constructor = function(sender) {
+ var that = this;
+ that.send_buffer = [];
+ that.sender = sender;
+};
+BufferedSender.prototype.doSend = function(message) {
+ var that = this;
+ that.send_buffer.push(message);
+ if (!that.send_stop) {
+ that.send_schedule();
+ }
+};
+
+// For polling transports in a situation when in the message callback,
+// new message is being send. If the sending connection was started
+// before receiving one, it is possible to saturate the network and
+// timeout due to the lack of receiving socket. To avoid that we delay
+// sending messages by some small time, in order to let receiving
+// connection be started beforehand. This is only a halfmeasure and
+// does not fix the big problem, but it does make the tests go more
+// stable on slow networks.
+BufferedSender.prototype.send_schedule_wait = function() {
+ var that = this;
+ var tref;
+ that.send_stop = function() {
+ that.send_stop = null;
+ clearTimeout(tref);
+ };
+ tref = utils.delay(25, function() {
+ that.send_stop = null;
+ that.send_schedule();
+ });
+};
+
+BufferedSender.prototype.send_schedule = function() {
+ var that = this;
+ if (that.send_buffer.length > 0) {
+ var payload = '[' + that.send_buffer.join(',') + ']';
+ that.send_stop = that.sender(that.trans_url,
+ payload,
+ function() {
+ that.send_stop = null;
+ that.send_schedule_wait();
+ });
+ that.send_buffer = [];
+ }
+};
+
+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)) {
+ var form = that._send_form = _document.createElement('form');
+ var area = that._send_area = _document.createElement('textarea');
+ area.name = 'd';
+ form.style.display = 'none';
+ form.style.position = 'absolute';
+ form.method = 'POST';
+ form.enctype = 'application/x-www-form-urlencoded';
+ form.acceptCharset = "UTF-8";
+ form.appendChild(area);
+ _document.body.appendChild(form);
+ }
+ var form = that._send_form;
+ var area = that._send_area;
+ var id = 'a' + utils.random_string(8);
+ form.target = id;
+ form.action = url + '/jsonp_send?i=' + id;
+
+ var iframe;
+ try {
+ // ie6 dynamic iframes with target="" support (thanks Chris Lambacher)
+ iframe = _document.createElement('<iframe name="'+ id +'">');
+ } catch(x) {
+ iframe = _document.createElement('iframe');
+ iframe.name = id;
+ }
+ iframe.id = id;
+ form.appendChild(iframe);
+ iframe.style.display = 'none';
+
+ area.value = payload;
+ form.submit();
+
+ var completed = function(e) {
+ if (!iframe.onerror) return;
+ iframe.onreadystatechange = iframe.onerror = iframe.onload = null;
+ // Opera mini doesn't like if we GC iframe
+ // immediately, thus this timeout.
+ utils.delay(500, function() {
+ iframe.parentNode.removeChild(iframe);
+ iframe = null;
+ });
+ area.value = null;
+ callback();
+ };
+ iframe.onerror = iframe.onload = completed;
+ iframe.onreadystatechange = function(e) {
+ if (iframe.readyState == 'complete') completed();
+ };
+ return completed;
+};
+
+var ajaxSender = function(url, payload, callback) {
+ var orsc = function (xhr, e, abort_reason) {
+ if(xhr.readyState === 4 || abort_reason) {
+ callback(xhr.status, abort_reason);
+ }
+ };
+ return utils.createXHR('POST', url + '/xhr_send', payload, orsc);
+};
+
+var xdrSender = function(url, payload, callback) {
+ var orsc = function (xhr, e, abort_reason) {
+ if(xhr.readyState === 4 || abort_reason) {
+ callback(xhr.status, abort_reason);
+ }
+ };
+ var fun = window.XDomainRequest ? utils.createXDR : utils.createXHR;
+ return fun('POST', url + '/xhr_send', payload, orsc);
+};
+// [*] End of lib/trans-sender.js
+
+
+// [*] Including lib/trans-jsonp-receiver.js
+// 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{var a = document.getElementById('"+script.id+"'); if(a)a.onerror();}catch(x){};";
+ script.async = script2.async = false;
+ }
+ } else {
+ script.async = true;
+ }
+
+ // Fallback mostly for Konqueror - stupid timer, 35 seconds shall be plenty.
+ tref = setTimeout(function() {
+ close_script(utils.closeFrame(1006, "JSONP script loaded abnormally (timeout)"));
+ }, 35000);
+
+ var head = _document.getElementsByTagName('head')[0];
+ head.insertBefore(script, head.firstChild);
+ if (script2) {
+ head.insertBefore(script2, head.firstChild);
+ }
+ return close_script;
+};
+// [*] End of lib/trans-jsonp-receiver.js
+
+
+// [*] Including lib/trans-jsonp-polling.js
+// 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-polling'] = 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 (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) {
+ that._schedule_recv();
+ }
+ };
+ that._recv_stop = jsonPReceiverWrapper(that.trans_url + '/jsonp',
+ 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();
+ }
+ that.ri = that._recv_stop = null;
+ that.send_destructor();
+};
+
+
+// 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;
+};
+// [*] End of lib/trans-jsonp-polling.js
+
+
+// [*] Including lib/trans-xhr-streaming.js
+var XhrStreamingTransport = SockJS['xhr-streaming'] = function (ri, trans_url) {
+ var that = this;
+ that.ri = ri;
+ that.trans_url = trans_url;
+ that.send_constructor(xdrSender);
+ that.poll = new Polling(ri, XhrReceiver,
+ trans_url + '/xhr_streaming',
+ {cors: true});
+};
+
+// Inheritnace
+XhrStreamingTransport.prototype = new BufferedSender();
+
+XhrStreamingTransport.prototype.doCleanup = function() {
+ var that = this;
+ if (that.poll) {
+ that.poll.abort();
+ that.poll = null;
+ }
+};
+
+// According to:
+// http://stackoverflow.com/questions/1641507/detect-browser-support-for-cross-domain-xmlhttprequests
+// http://hacks.mozilla.org/2009/07/cross-site-xmlhttprequest-with-cors/
+XhrStreamingTransport.enabled = function(options) {
+ if (options.cookie !== true && window.XDomainRequest) return true;
+ if (window.XMLHttpRequest &&
+ 'withCredentials' in new XMLHttpRequest()) return true;
+ return false;
+};
+
+XhrStreamingTransport.need_chunking = true;
+// [*] End of lib/trans-xhr-streaming.js
+
+
+// [*] Including lib/trans-xhr-polling.js
+var XhrPollingTransport = SockJS['xhr-polling'] = function (ri, trans_url) {
+ var that = this;
+ that.ri = ri;
+ that.trans_url = trans_url;
+ that.send_constructor(xdrSender);
+ that.poll = new Polling(ri, XhrReceiver, trans_url + '/xhr', {cors: true});
+};
+
+// Inheritnace
+XhrPollingTransport.prototype = new BufferedSender();
+
+XhrPollingTransport.prototype.doCleanup = function() {
+ var that = this;
+ if (that.poll) {
+ that.poll.abort();
+ that.poll = null;
+ }
+};
+
+XhrPollingTransport.enabled = XhrStreamingTransport.enabled;
+// [*] End of lib/trans-xhr-polling.js
+
+
+// [*] Including lib/trans-iframe.js
+// 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
+// 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
+
+var IframeTransport = function() {};
+
+IframeTransport.prototype.i_constructor = function(ri, trans_url, base_url) {
+ var that = this;
+ that.ri = ri;
+ that.origin = utils.getOrigin(base_url);
+ that.base_url = base_url;
+ that.trans_url = trans_url;
+
+ var iframe_url = base_url + '/iframe.html';
+ if (that.ri._options.devel) {
+ iframe_url += '?t=' + (+new Date);
+ }
+ that.window_id = utils.random_string(8);
+ iframe_url += '#' + that.window_id;
+
+ that.iframeObj = utils.createIframe(iframe_url, function(r) {
+ that.ri._didClose(1006, "Unable to load an iframe (" + r + ")");
+ });
+
+ that.onmessage_cb = utils.bind(that.onmessage, that);
+ utils.attachMessage(that.onmessage_cb);
+};
+
+IframeTransport.prototype.doCleanup = function() {
+ var that = this;
+ if (that.iframeObj) {
+ utils.detachMessage(that.onmessage_cb);
+ try {
+ // When the iframe is not loaded, IE raises an exception
+ // on 'contentWindow'.
+ if (that.iframeObj.iframe.contentWindow) {
+ that.postMessage('c');
+ }
+ } catch (x) {}
+ that.iframeObj.cleanup();
+ that.iframeObj = null;
+ that.onmessage_cb = that.iframeObj = null;
+ }
+};
+
+IframeTransport.prototype.onmessage = function(e) {
+ var that = this;
+ if (e.origin !== that.origin) return;
+ var window_id = e.data.slice(0, 8);
+ var type = e.data.slice(8, 9);
+ var data = e.data.slice(9);
+
+ if (window_id !== that.window_id) return;
+
+ switch(type) {
+ case 's':
+ that.iframeObj.loaded();
+ that.postMessage('s', JSON.stringify([SockJS.version, that.protocol, that.trans_url, that.base_url]));
+ break;
+ case 't':
+ that.ri._didMessage(data);
+ break;
+ }
+};
+
+IframeTransport.prototype.postMessage = function(type, data) {
+ var that = this;
+ that.iframeObj.iframe.contentWindow.postMessage(that.window_id + type + (data || ''), that.origin);
+};
+
+IframeTransport.prototype.doSend = function (message) {
+ this.postMessage('m', 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));
+};
+// [*] End of lib/trans-iframe.js
+
+
+// [*] Including lib/trans-iframe-within.js
+var curr_window_id;
+
+var postMessage = function (type, data) {
+ if(parent !== _window) {
+ parent.postMessage(curr_window_id + type + (data || ''), '*');
+ } else {
+ utils.log("Can't postMessage, no parent window.", type, data);
+ }
+};
+
+var FacadeJS = function() {};
+FacadeJS.prototype._didClose = function (status, reason) {
+ postMessage('t', utils.closeFrame(status, reason));
+};
+FacadeJS.prototype._didMessage = function (frame) {
+ postMessage('t', frame);
+};
+FacadeJS.prototype._doSend = function (data) {
+ this._transport.doSend(data);
+};
+FacadeJS.prototype._doCleanup = function () {
+ this._transport.doCleanup();
+};
+
+SockJS.bootstrap_iframe = function() {
+ var facade;
+ curr_window_id = _document.location.hash.slice(1);
+ var onMessage = function(e) {
+ if(e.source !== parent) return;
+ var window_id = e.data.slice(0, 8);
+ var type = e.data.slice(8, 9);
+ var data = e.data.slice(9);
+ if (window_id !== curr_window_id) return;
+ switch(type) {
+ case 's':
+ var p = JSON.parse(data);
+ var version = p[0];
+ var protocol = p[1];
+ var trans_url = p[2];
+ var base_url = p[3];
+ if (version !== 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, base_url);
+ break;
+ case 'm':
+ facade._doSend(data);
+ break;
+ case 'c':
+ facade._doCleanup();
+ facade = null;
+ break;
+ }
+ };
+
+ // alert('test ticker');
+ // facade = new FacadeJS();
+ // facade._transport = new FacadeJS['w-iframe-xhr-polling'](facade, 'http://mmajkowski.eng.vmware.com:9999/ticker/12/basd');
+
+ utils.attachMessage(onMessage);
+
+ // Start
+ postMessage('s');
+};
+// [*] End of lib/trans-iframe-within.js
+
+
+// [*] Including lib/chunking-test.js
+var doChunkingTest = function(base_url, callback, cors) {
+ var recv = new XhrReceiver(base_url + '/chunking_test', {cors: cors});
+ var result = 0;
+ recv.onmessage = function(e) {
+ // Now a cool hack: we can stop receiving after we got at least
+ // one chunk, contains some data, but not everyting.
+ var l = e.responsetext.split('h\n').length;
+ if(e.readystate === 3 && l > 0 && l < 6 ) {
+ result = l;
+ recv.abort();
+ }
+ };
+ recv.onclose = function(e) {
+ recv = recv.onmessage = recv.onclose = null;
+ utils.log('Chunking test: ' + (result ? 'passed' : 'failed')
+ + ' (' + result + ' chunk received)');
+ callback(!!result);
+ };
+};
+
+var ChunkingTestIframe = FacadeJS['w-iframe-chunking-test'] = function (ri, trans_url, base_url) {
+ doChunkingTest(base_url, function(r) {
+ ri._didMessage('m'+r);
+ ri._didClose();
+ }, false);
+};
+ChunkingTestIframe.prototype.doCleanup = function() {};
+
+var chunkingTestUncached = SockJS.chunkingTest = function(base_url, callback, options) {
+ base_url = utils.amendUrl(base_url);
+ // 1. CORS
+ if (_window.XDomainRequest ||
+ (_window.XMLHttpRequest && 'withCredentials' in new XMLHttpRequest())) {
+ doChunkingTest(base_url, callback, true);
+ return;
+ }
+ // 2. Iframe
+ if (IframeTransport.enabled()) {
+ var ifr = new IframeTransport();
+ ifr.protocol = 'w-iframe-chunking-test';
+ var fun = function(r) {
+ if (ifr) {
+ callback(r === 'mtrue');
+ ifr.doCleanup();
+ ifr = null;
+ }
+ };
+ var mock_ri = {
+ _options: options || {},
+ _didClose: fun,
+ _didMessage: fun
+ };
+ ifr.i_constructor(mock_ri, '', base_url);
+ return;
+ }
+ // 3. Fall back to polling (IE 7)
+ setTimeout(function() {
+ callback(false);
+ }, 0);
+ return;
+};
+
+// Although chunking test is run against a particular 'base_url', it's
+// safe to assume that if chunking works for client, it will work for
+// any SockJS server. That means we can cache the result of
+// chunkingTest, at least until user switches network. Let's assume a
+// value of 10 seconds.
+var chunkingTest = function() {
+ var value;
+ var t0 = 0;
+ return function (base_url, callback) {
+ var t1 = (new Date()).getTime();
+ if (t1 - t0 > 10000) {
+ chunkingTestUncached(base_url, function (v) {
+ value = v;
+ t0 = (new Date()).getTime();
+ callback(value);
+ });
+ } else {
+ setTimeout(function() {
+ callback(value);
+ }, 0);
+ }
+ };
+}();
+// [*] End of lib/chunking-test.js
+
+
+// [*] Including lib/trans-iframe-eventsource.js
+var EventSourceIframeTransport = SockJS['iframe-eventsource'] = function () {
+ var that = this;
+ that.protocol = 'w-iframe-eventsource';
+ that.i_constructor.apply(that, arguments);
+};
+
+// Inheritance.
+EventSourceIframeTransport.prototype = new IframeTransport();
+
+EventSourceIframeTransport.enabled = function () {
+ return ('EventSource' in window) && IframeTransport.enabled();
+};
+
+EventSourceIframeTransport.need_chunking = true;
+
+
+var EventSourceTransport = FacadeJS['w-iframe-eventsource'] = function (ri, trans_url) {
+ var that = this;
+ that.ri = ri;
+ that.trans_url = trans_url;
+ that.send_constructor(ajaxSender);
+ that.poll = new Polling(ri, EventSourceReceiver, trans_url + '/eventsource');
+};
+
+// Inheritnace
+EventSourceTransport.prototype = new BufferedSender();
+
+EventSourceTransport.prototype.doCleanup = function() {
+ var that = this;
+ if (that.poll) {
+ that.poll.abort();
+ that.poll = null;
+ }
+};
+// [*] End of lib/trans-iframe-eventsource.js
+
+
+// [*] Including lib/trans-iframe-xhr-polling.js
+var XhrPollingIframeTransport = SockJS['iframe-xhr-polling'] = function () {
+ var that = this;
+ that.protocol = 'w-iframe-xhr-polling';
+ that.i_constructor.apply(that, arguments);
+};
+
+// Inheritance.
+XhrPollingIframeTransport.prototype = new IframeTransport();
+
+XhrPollingIframeTransport.enabled = function () {
+ return window.XMLHttpRequest && IframeTransport.enabled();
+};
+
+
+var XhrPollingITransport = FacadeJS['w-iframe-xhr-polling'] = function (ri, trans_url) {
+ var that = this;
+ that.trans_url = trans_url;
+ that.send_constructor(ajaxSender);
+ that.poll = new Polling(ri, XhrReceiver, trans_url + '/xhr', {cors: false});
+};
+
+
+// Inheritnace
+XhrPollingITransport.prototype = new BufferedSender();
+
+XhrPollingITransport.prototype.doCleanup = function() {
+ var that = this;
+ if (that.poll) {
+ that.poll.abort();
+ that.poll = null;
+ }
+};
+// [*] End of lib/trans-iframe-xhr-polling.js
+
+
+// [*] Including lib/trans-iframe-htmlfile.js
+// This transport generally works in any browser, but will cause a
+// spinning cursor to appear in any browser other than IE.
+// We may test this transport in all browsers - why not, but in
+// production it should be only run in IE.
+
+var HtmlFileIframeTransport = SockJS['iframe-htmlfile'] = function () {
+ var that = this;
+ that.protocol = 'w-iframe-htmlfile';
+ that.i_constructor.apply(that, arguments);
+};
+
+// Inheritance.
+HtmlFileIframeTransport.prototype = new IframeTransport();
+
+HtmlFileIframeTransport.enabled = function (options) {
+ // Development or IE _and_ iframe postWindow working.
+ var ie = isIeHtmlfileCapable();
+ return (options.cookie !== false && IframeTransport.enabled());
+};
+
+HtmlFileIframeTransport.need_chunking = true;
+
+
+var HtmlFileTransport = FacadeJS['w-iframe-htmlfile'] = function (ri, trans_url) {
+ var that = this;
+ that.trans_url = trans_url;
+ that.send_constructor(ajaxSender);
+ that.poll = new Polling(ri, HtmlfileReceiver, trans_url + '/htmlfile');
+};
+
+// Inheritnace
+HtmlFileTransport.prototype = new BufferedSender();
+
+HtmlFileTransport.prototype.doCleanup = function() {
+ var that = this;
+ if (that.poll) {
+ that.poll.abort();
+ that.poll = null;
+ }
+};
+// [*] End of lib/trans-iframe-htmlfile.js
+
+
+// [*] Including lib/trans-polling.js
+
+var Polling = function(ri, Receiver, recv_url, opts) {
+ var that = this;
+ that.ri = ri;
+ that.Receiver = Receiver;
+ that.recv_url = recv_url;
+ that.opts = opts;
+ that._scheduleRecv();
+};
+
+Polling.prototype._scheduleRecv = function() {
+ var that = this;
+ var poll = that.poll = new that.Receiver(that.recv_url, that.opts);
+ var msg_counter = 0;
+ poll.onmessage = function(e) {
+ msg_counter += 1;
+ that.ri._didMessage(e.data);
+ };
+ poll.onclose = function(e) {
+ that.poll = poll = poll.onmessage = poll.onclose = null;
+ if (!that.poll_is_closing) {
+ if (e.reason === 'permanent') {
+ that.ri._didClose(1006, 'Polling error (' + e.reason + ')');
+ } else {
+ that._scheduleRecv();
+ }
+ }
+ };
+};
+
+Polling.prototype.abort = function() {
+ var that = this;
+ that.poll_is_closing = true;
+ if (that.poll) {
+ that.poll.abort();
+ }
+};
+// [*] End of lib/trans-polling.js
+
+
+// [*] Including lib/trans-receiver-eventsource.js
+
+var EventSourceReceiver = function(url) {
+ var that = this;
+ var es = new EventSource(url);
+ es.onmessage = function(e) {
+ that.dispatchEvent(new SimpleEvent('message',
+ {'data': unescape(e.data)}));
+ };
+ that.es_close = es.onerror = function(e, abort_reason) {
+ // ES on reconnection has readyState = 0 or 1.
+ // on network error it's CLOSED = 2
+ var reason = abort_reason ? 'user' :
+ (es.readyState !== 2 ? 'network' : 'permanent');
+ that.es_close = es.onmessage = es.onerror = null;
+ // EventSource reconnects automatically.
+ es.close();
+ es = null;
+ // Safari and chrome < 15 crash if we close window before
+ // waiting for ES cleanup. See:
+ // https://code.google.com/p/chromium/issues/detail?id=89155
+ utils.delay(200, function() {
+ that.dispatchEvent(new SimpleEvent('close', {reason: reason}));
+ });
+ };
+};
+
+EventSourceReceiver.prototype = new REventTarget();
+
+EventSourceReceiver.prototype.abort = function() {
+ var that = this;
+ if (that.es_close) {
+ that.es_close({}, true);
+ }
+};
+// [*] End of lib/trans-receiver-eventsource.js
+
+
+// [*] Including lib/trans-receiver-htmlfile.js
+var _is_ie_htmlfile_capable;
+var isIeHtmlfileCapable = function() {
+ if (_is_ie_htmlfile_capable === undefined) {
+ if ('ActiveXObject' in window) {
+ try {
+ _is_ie_htmlfile_capable = !!new ActiveXObject('htmlfile');
+ } catch (x) {}
+ } else {
+ _is_ie_htmlfile_capable = false;
+ }
+ }
+ return _is_ie_htmlfile_capable;
+};
+
+
+var HtmlfileReceiver = function(url) {
+ var that = this;
+ utils.polluteGlobalNamespace();
+
+ that.id = 'a' + utils.random_string(6, 26);
+ url += ((url.indexOf('?') === -1) ? '?' : '&') +
+ 'c=' + escape(WPrefix + '.' + that.id);
+
+ var constructor = isIeHtmlfileCapable() ?
+ utils.createHtmlfile : utils.createIframe;
+
+ var iframeObj;
+ _window[WPrefix][that.id] = {
+ start: function () {
+ iframeObj.loaded();
+ },
+ message: function (data) {
+ that.dispatchEvent(new SimpleEvent('message', {'data': data}));
+ },
+ stop: function () {
+ that.iframe_close({}, 'network');
+ }
+ };
+ that.iframe_close = function(e, abort_reason) {
+ iframeObj.cleanup();
+ that.iframe_close = iframeObj = null;
+ delete _window[WPrefix][that.id];
+ that.dispatchEvent(new SimpleEvent('close', {reason: abort_reason}));
+ };
+ iframeObj = constructor(url, function(e) {
+ that.iframe_close({}, 'permanent');
+ });
+};
+
+HtmlfileReceiver.prototype = new REventTarget();
+
+HtmlfileReceiver.prototype.abort = function() {
+ var that = this;
+ if (that.iframe_close) {
+ that.iframe_close({}, 'user');
+ }
+};
+// [*] End of lib/trans-receiver-htmlfile.js
+
+
+// [*] Including lib/trans-receiver-xhr.js
+
+var XhrReceiver = function(url, opts) {
+ var that = this;
+ var buf_pos = 0;
+ var orsc = function (xhr, e, abort_reason) {
+ if (xhr.readyState === 3 || xhr.readyState === 4) {
+ // IE doesn't like peeking into responseText or status on
+ // XHR and readystate=3
+ try {
+ var responseText = xhr.responseText;
+ var status = xhr.status;
+ } catch (x) {}
+ if (responseText && status === 200) {
+ var msgs = [];
+ while (1) {
+ var buf = responseText.slice(buf_pos);
+ var p = buf.indexOf('\n');
+ if (p === -1) break;
+ buf_pos += p+1;
+ var msg = buf.slice(0, p);
+ that.dispatchEvent(
+ new SimpleEvent('message', {
+ data: msg,
+ readystate: xhr.readyState,
+ responsetext: responseText
+ }));
+ }
+ }
+ }
+ if (xhr.readyState === 4 || abort_reason) {
+ var reason = abort_reason ? 'user' :
+ (xhr.status === 200 ? 'network' : 'permanent');
+ that.xhr_close = null;
+ that.dispatchEvent(new SimpleEvent('close', {reason: reason}));
+ }
+ };
+ var createXhr = (opts.cors && _window.XDomainRequest) ?
+ utils.createXDR : utils.createXHR;
+ that.xhr_close = createXhr('POST', url, null, orsc);
+};
+
+XhrReceiver.prototype = new REventTarget();
+
+XhrReceiver.prototype.abort = function() {
+ var that = this;
+ if (that.xhr_close) {
+ that.xhr_close(true);
+ }
+};
+// [*] End of lib/trans-receiver-xhr.js
+
+ return SockJS;
+ })();
+if ('_sockjs_onload' in window) setTimeout(_sockjs_onload, 1);
+// [*] End of lib/index.js
+
+// [*] End of lib/all.js
+
View
398 deps/sockjs-client/tests/html/lib/tests.js
@@ -0,0 +1,398 @@
+var arrIndexOf, batch_factory_factory, batch_factory_factory_amp, chunking_test_factory, echo_factory_factory, factor_batch_large, factor_batch_large_amp, factor_echo_basic, factor_echo_large_message, factor_echo_rich, factor_echo_special_chars, factor_echo_unicode, factor_server_close, factor_user_close, newSockJS, protocol, protocols, test_invalid_url_404, test_invalid_url_500, test_invalid_url_port, test_protocol_errors, test_protocol_messages, _i, _j, _len, _len2;
+protocols = ['websocket', 'xhr-streaming', 'iframe-eventsource', 'iframe-htmlfile', 'xhr-polling', 'iframe-xhr-polling', 'jsonp-polling'];
+newSockJS = function(path, protocol) {
+ var url;
+ url = /^http/.test(path) ? path : client_opts.url + path;
+ return new SockJS(url, [protocol], client_opts.sockjs_opts);
+};
+echo_factory_factory = function(protocol, messages) {
+ return function() {
+ var a, r;
+ expect(2 + messages.length);
+ a = messages.slice(0);
+ r = newSockJS('/echo', protocol);
+ r.onopen = function(e) {
+ log('onopen ' + e);
+ ok(true);
+ return r.send(a[0]);
+ };
+ r.onmessage = function(e) {
+ deepEqual(e.data, a[0]);
+ a.shift();
+ if (typeof a[0] === 'undefined') {
+ return r.close();
+ } else {
+ return r.send(a[0]);
+ }
+ };
+ return r.onclose = function(e) {
+ if (a.length) {
+ ok(false, "Transport closed prematurely. " + e);
+ } else {
+ ok(true);
+ }
+ return start();
+ };
+ };
+};
+factor_echo_basic = function(protocol) {
+ var messages;
+ messages = ['data'];
+ return echo_factory_factory(protocol, messages);
+};
+factor_echo_rich = function(protocol) {
+ var messages;
+ messages = [
+ [1, 2, 3, 'data'], null, "data", 1, 12.0, {
+ a: 1,
+ b: 2
+ }
+ ];
+ return echo_factory_factory(protocol, messages);
+};
+factor_echo_unicode = function(protocol) {
+ var messages;
+ messages = ["Τη γλώσσα μου έδωσαν ελληνική το σπίτι φτωχικό στις αμμουδιές του ", "ღმერთსი შემვედრე, ნუთუ კვლა დამხსნას სოფლისა შრომასა, ცეცხლს, წყალს", "⠊⠀⠉⠁⠝⠀⠑⠁⠞⠀⠛⠇⠁⠎⠎⠀⠁⠝⠙⠀⠊⠞⠀⠙⠕⠑⠎⠝⠞⠀⠓⠥⠗⠞⠀⠍⠑", "Би шил идэй чадна, надад хортой биш", "을", "나는 유리를 먹을 수 있어요. 그래도 아프지 않아요", "ฉันกินกระจกได้ แต่มันไม่ทำให้ฉันเจ็บฉันกินกระจกได้ แต่มันไม่ทำให้ฉันเจ็บ", "Ég get etið gler án þess að meiða mig.", "Mogę jeść szkło, i mi nie szkodzi.", "\ufffd\u10102\u2f877", "Начало музыкальной карьеры\nБритни пела в церковном хоре местной баптистской церкви. В возрасте 8-ми лет Спирс прошла аудирование для участия в шоу «Новый Клуб Микки-Мауса» на канале «Дисней». И хотя продюсеры решили, что Спирс слишком молода для участия в шоу, они представили её агенту в Нью-Йорке. Следующие 3 года Бритни училась в актёрской школе Professional Performing Arts School в Нью-Йорке и участвовала в нескольких постановках, в том числе «Ruthless!» 1991 года. В 1992 году Спирс участвовала в конкурсе Star Search, но проиграла во втором туре.\nВ 1993 году Спирс вернулась на канал «Дисней» и в течение 2-х лет участвовала в шоу «Новый Клуб Микки-Мауса». Другие будущие знаменитости, начинавшие с этого шоу — Кристина Агилера, участники 'N Sync Джастин Тимберлейк и Джейси Шазе, звезда сериала «Счастье» Кери Расселл и актёр фильма «Дневник памяти» Райан Гослинг.\nВ 1994 году шоу закрыли, Бритни вернулась домой в Луизиану, где поступила в среднюю школу. Некоторое время она пела в девичьей группе Innosense, но вскоре, решив начать сольную карьеру, записала демодиск, который попал в руки продюсерам из Jive Records, и те заключили с ней контракт.\nДалее последовал тур по стране, выступления в супермаркетах и работа на разогреве у групп 'N Sync и Backstreet Boys.\n[править]1999—2000: Ранний коммерческий успех\nВ октябре 1998 года вышел дебютный сингл Бритни Спирс «…Baby One More Time» . Песня имела огромный успех, в первые же недели возглавила международные чарты, мировые продажи сингла составили 9 миллионов копий, что сделало диск дважды платиновым. Альбом с одноимённым названием вышел в январе 1999 года. Альбом стартовал на первом месте рейтинга Billboard 200, пятьдесят одну неделю продержался в верхней десятке и шестьдесят недель в двадцати лучших. Альбом стал 15-кратным платиновым и на сегодняшний день является самым успешным альбомом Бритни Спирс.\nВ 1999 году Бритни снялась для апрельского номера журнала Rolling Stone. Откровенные фотографии спровоцировали слухи о том, что 17-летняя звезда сделала операцию по увеличению груди, что сама Спирс отрицала. Успех альбома и противоречивый образ Спирс, созданный массмедиа, сделали её главной звездой 1999 года.\nВслед за успешным дебютом последовал второй альбом певицы «Oops!... I Did It Again», также стартовавший на 1-м месте в США. Продажи за первую неделю составили 1 319 193 копии, что являлось абсолютным рекордом, который затем побил американский рэпер Эминем. Летом 2000 года Спирс отправилась в свой первый мировой тур, «Oops!… I Did It Again World Tour». В 2000 году Спирс получила две награды Billboards Music Awards и была номинирована на «Грэмми» в двух категориях — «Лучший поп-альбом» и «Лучшее живое выступление».\n[править]2001—2003: Вершина карьеры\n\n\nИсполняя «Me Against the Music»\nУспех Спирс сделал её заметной фигурой и в музыкальной индустрии, и в поп-культуре. В начале 2001 года она привлекла внимание «Пепси», эта компания предложила ей многомиллионный контракт, включавший телевизионную рекламу и участие в промо-акциях.\nВ ноябре 2001 года вышел третий альбом Спирс — Britney. Альбом дебютировал на первом месте в США с продажами в 745 744 пластинок за первую неделю, что сделало Бритни первой в истории исполнительницей, чьи первые три альбома стартовали на вершине рейтинга. Сразу же после выхода альбома Спирс отправилась в тур Dream Within a Dream Tour, по окончании которого объявила, что хочет взять 6-месячный перерыв в карьере.\nВ этом же году Спирс рассталась с солистом 'N Sync Джастином Тимберлейком, с которым встречалась 4 года.\nБритни вернулась на сцену в августе 2003 года.\nВ ноябре 2003 года вышел четвёртый студийный альбом Спирс In The Zone. Бритни участвовала в написании восьми из тринадцати композиций, а также выступила в качестве продюсера альбома. In The Zone дебютировал на первом месте в США, что сделало Бритни первой в истории исполнительницей, чьи первые четыре альбома стартовали на вершине рейтинга. Самый успешный сингл с альбома — Toxic — принёс Бритни первую для неё награду Грэмми в категории «Лучшая танцевальная композиция».\n[править]2007—2008: Возвращение к музыке\nВ начале 2007 года после двухлетнего перерыва Спирс приступила к записи нового сольного альбома, продюсерами которого выступили Nate «Danja» Hills, Шон Гарретт и Джонатан Ротэм.\nВ мае 2007 года Спирс в составе коллектива «The M and M’s» дала 6 концертов в рамках тура «House of Blues» в Лос-Анджелесе, Сан-Диего, Анахайме, Лас-Вегасе, Орландо и Майами. Каждый концерт длился около 15 минут и включал 5 старых хитов певицы.[4]\n30 августа 2007 года на волнах нью-йоркской радиостанции Z100 состоялась премьера песни «Gimme More», первого сингла с нового альбома Спирс.[5] Сингл вышел на iTunes 24 сентября и на CD 29 октября 2007.\n9 сентября 2007 года Спирс исполнила «Gimme More» на церемонии вручения наград MTV Video Music Awards. Выступление оказалось неудачным; Спирс выглядела непрофессионально — не всегда попадала в фонограмму и в танце отставала от группы хореографической поддержки.[6]\nНесмотря на это, в начале октября 2007 года сингл «Gimme More» достиг 3-го места в чарте Billboard Hot 100, став таким образом одним из самых успешных синглов Спирс.[7]"];
+ return echo_factory_factory(protocol, messages);
+};
+factor_echo_special_chars = function(protocol) {
+ var messages;
+ messages = [" ", "\u0000", "\xff", "\xff\x00", "\x00\xff", " \r ", " \n ", " \r\n ", "\r\n", "", "message\t", "\tmessage", "message ", " message", "message\r", "\rmessage", "message\n", "\nmessage", "message\xff", "\xffmessage", "A", "b", "c", "d", "e", "\ufffd", "\ufffd\u0000", "message\ufffd", "\ufffdmessage"];
+ return echo_factory_factory(protocol, messages);
+};
+factor_echo_large_message = function(protocol) {
+ var messages;
+ messages = [Array(Math.pow(2, 1)).join('x'), Array(Math.pow(2, 2)).join('x'), Array(Math.pow(2, 4)).join('x'), Array(Math.pow(2, 8)).join('x'), Array(Math.pow(2, 13)).join('x'), Array(Math.pow(2, 13)).join('x')];
+ return echo_factory_factory(protocol, messages);
+};
+batch_factory_factory = function(protocol, messages) {
+ return function() {
+ var counter, r;
+ expect(3 + messages.length);
+ r = newSockJS('/echo', protocol);
+ ok(r);
+ counter = 0;
+ r.onopen = function(e) {
+ var msg, _i, _len, _results;
+ ok(true);
+ _results = [];
+ for (_i = 0, _len = messages.length; _i < _len; _i++) {
+ msg = messages[_i];
+ _results.push(r.send(msg));
+ }
+ return _results;
+ };
+ r.onmessage = function(e) {
+ equals(e.data, messages[counter]);
+ counter += 1;
+ if (counter === messages.length) {
+ return r.close();
+ }
+ };
+ return r.onclose = function(e) {
+ if (counter !== messages.length) {
+ ok(false, "Transport closed prematurely. " + e);
+ } else {
+ ok(true);
+ }
+ return start();
+ };
+ };
+};
+factor_batch_large = function(protocol) {
+ var messages;
+ messages = [Array(Math.pow(2, 1)).join('x'), Array(Math.pow(2, 2)).join('x'), Array(Math.pow(2, 4)).join('x'), Array(Math.pow(2, 8)).join('x'), Array(Math.pow(2, 13)).join('x'), Array(Math.pow(2, 13)).join('x')];
+ return batch_factory_factory(protocol, messages);
+};
+batch_factory_factory_amp = function(protocol, messages) {
+ return function() {
+ var counter, r;
+ expect(3 + messages.length);
+ r = newSockJS('/amplify', protocol);
+ ok(r);
+ counter = 0;
+ r.onopen = function(e) {
+ var msg, _i, _len, _results;
+ ok(true);
+ _results = [];
+ for (_i = 0, _len = messages.length; _i < _len; _i++) {
+ msg = messages[_i];
+ _results.push(r.send('' + msg));
+ }
+ return _results;
+ };
+ r.onmessage = function(e) {
+ equals(e.data.length, Math.pow(2, messages[counter]), e.data);
+ counter += 1;
+ if (counter === messages.length) {
+ return r.close();
+ }
+ };
+ return r.onclose = function(e) {
+ if (counter !== messages.length) {
+ ok(false, "Transport closed prematurely. " + e);
+ } else {
+ ok(true);
+ }
+ return start();
+ };
+ };
+};
+factor_batch_large_amp = function(protocol) {
+ var messages;
+ messages = [1, 2, 4, 8, 13, 15, 15];
+ return batch_factory_factory_amp(protocol, messages);
+};
+factor_user_close = function(protocol) {
+ return function() {
+ var counter, r;
+ expect(4);
+ r = newSockJS('/echo', protocol);
+ ok(r);
+ counter = 0;
+ r.onopen = function(e) {
+ counter += 1;
+ ok(counter === 1);
+ r.close(3000, "User message");
+ return ok(counter === 1);
+ };
+ r.onmessage = function() {
+ fail(true);
+ return counter += 1;
+ };
+ return r.onclose = function(e) {
+ counter += 1;
+ log('user_close ' + e.status + ' ' + e.reason);
+ ok(counter === 2);
+ return start();
+ };
+ };
+};
+factor_server_close = function(protocol) {
+ return function() {
+ var r;
+ expect(4);
+ r = newSockJS('/close', protocol);
+ ok(r);
+ r.onopen = function(e) {
+ return ok(true);
+ };
+ r.onmessage = function(e) {
+ return fail(true);
+ };
+ return r.onclose = function(e) {
+ equals(e.status, 3000);
+ equals(e.reason, "Go away!");
+ return start();
+ };
+ };
+};
+test_invalid_url_404 = function(protocol) {
+ return function() {
+ var counter, r;
+ expect(2);
+ r = newSockJS('/invalid_url', protocol);
+ ok(r);
+ counter = r.onopen = function(e) {
+ return fail(true);
+ };
+ r.onmessage = function(e) {
+ return fail(true);
+ };
+ return r.onclose = function(e) {
+ log('404', e);
+ equals(e.status, 2000);
+ return start();
+ };
+ };
+};
+test_invalid_url_500 = function(protocol) {
+ return function() {
+ var r;
+ expect(2);
+ r = newSockJS('/500_error', protocol);
+ ok(r);
+ r.onopen = function(e) {
+ return fail(true);
+ };
+ return r.onclose = function(e) {
+ log('500', e);
+ equals(e.status, 2000);
+ return start();
+ };
+ };
+};
+test_invalid_url_port = function(protocol) {
+ return function() {
+ var dl, r;
+ expect(2);
+ dl = document.location;
+ r = newSockJS(dl.protocol + '//' + dl.hostname + ':1079', protocol);
+ ok(r);
+ r.onopen = function(e) {
+ return fail(true);
+ };
+ return r.onclose = function(e) {
+ log('port', e);
+ equals(e.status, 2000);
+ return start();
+ };
+ };
+};
+arrIndexOf = function(arr, obj) {
+ var i, _ref;
+ for (i = 0, _ref = arr.length; 0 <= _ref ? i < _ref : i > _ref; 0 <= _ref ? i++ : i--) {
+ if (arr[i] === obj) {
+ return i;
+ }
+ }
+ return -1;
+};
+test_protocol_messages = function(protocol) {
+ module(protocol);
+ if (!SockJS[protocol] || !SockJS[protocol].enabled(client_opts.sockjs_opts)) {
+ return test("[unsupported by client]", function() {
+ return log('Unsupported protocol (by client): "' + protocol + '"');
+ });
+ } else if (client_opts.disabled_transports && arrIndexOf(client_opts.disabled_transports, protocol) !== -1) {
+ return test("[unsupported by server]", function() {
+ return log('Unsupported protocol (by server): "' + protocol + '"');
+ });
+ } else {
+ asyncTest("echo1", factor_echo_basic(protocol));
+ asyncTest("echo2", factor_echo_rich(protocol));
+ asyncTest("unicode", factor_echo_unicode(protocol));
+ asyncTest("special_chars", factor_echo_special_chars(protocol));
+ asyncTest("large message (ping-pong)", factor_echo_large_message(protocol));
+ asyncTest("large message (batch)", factor_batch_large(protocol));
+ asyncTest("large download", factor_batch_large_amp(protocol));
+ asyncTest("user close", factor_user_close(protocol));
+ return asyncTest("server close", factor_server_close(protocol));
+ }
+};
+test_protocol_errors = function(protocol) {
+ module(protocol);
+ if (!SockJS[protocol] || !SockJS[protocol].enabled(client_opts.sockjs_opts)) {
+ return test("[unsupported by client]", function() {
+ return log('Unsupported protocol (by client): "' + protocol + '"');
+ });
+ } else if (client_opts.disabled_transports && arrIndexOf(client_opts.disabled_transports, protocol) !== -1) {
+ return test("[unsupported by server]", function() {
+ return log('Unsupported protocol (by server): "' + protocol + '"');
+ });
+ } else {
+ asyncTest("invalid url 404", test_invalid_url_404(protocol));
+ asyncTest("invalid url 500", test_invalid_url_500(protocol));
+ return asyncTest("invalid url port", test_invalid_url_port(protocol));
+ }
+};
+for (_i = 0, _len = protocols.length; _i < _len; _i++) {
+ protocol = protocols[_i];
+ test_protocol_messages(protocol);
+}
+module('other');
+test("amending url", function() {
+ var dl, r;
+ dl = document.location;
+ r = new SockJS('//blah:1/abc', []);
+ equal(r._base_url, dl.protocol + '//blah:1/abc');
+ r = new SockJS('/abc', []);
+ equal(r._base_url, dl.protocol + '//' + dl.host + '/abc');
+ r = new SockJS('http://a:1/abc', []);
+ equal(r._base_url, 'http://a:1/abc');
+ r = new SockJS('http://a:1/abc/', []);
+ equal(r._base_url, 'http://a:1/abc');
+ r = new SockJS('http://a:1/abc//', []);
+ return equal(r._base_url, 'http://a:1/abc');
+});
+test("EventEmitter", function() {
+ var bluff, r, single;
+ expect(4);
+ r = new SockJS('//blah/abc', []);
+ r.addEventListener('message', function() {
+ return ok(true);
+ });
+ r.onmessage = function() {
+ return fail(true);
+ };
+ bluff = function() {
+ return fail(true);
+ };
+ r.addEventListener('message', bluff);
+ r.removeEventListener('message', bluff);
+ r.addEventListener('message', bluff);
+ r.addEventListener('message', function() {
+ return ok(true);
+ });
+ r.onmessage = function() {
+ return ok(true);
+ };
+ r.removeEventListener('message', bluff);
+ r.dispatchEvent({
+ type: 'message'
+ });
+ single = function() {
+ return ok(true);
+ };
+ r.addEventListener('close', single);
+ r.addEventListener('close', single);
+ r.dispatchEvent({
+ type: 'close'
+ });
+ r.removeEventListener('close', single);
+ return r.dispatchEvent({
+ type: 'close'
+ });
+});
+chunking_test_factory = function(counter) {
+ return function() {
+ var a, go;
+ expect(counter);
+ a = new Array(counter);
+ go = function() {
+ return SockJS.chunkingTest(client_opts.url + '/echo', function(r) {
+ if ($.browser.msie && $.browser.version < 8) {
+ equal(r, false);
+ } else {
+ equal(r, true);
+ }
+ a.shift();
+ if (a.length !== 0) {
+ return go();
+ } else {
+ return start();
+ }
+ });
+ };
+ return go();
+ };
+};
+asyncTest("chunking test (simple)", chunking_test_factory(1));
+asyncTest("chunking test (stability)", chunking_test_factory(25));
+asyncTest("chunking test, invalid url 404", function() {
+ expect(1);
+ return SockJS.chunkingTest(client_opts.url + '/invalid_url', function(r) {
+ equal(r, false);
+ return start();
+ });
+});
+asyncTest("chunking test, invalid url 500", function() {
+ expect(1);
+ return SockJS.chunkingTest(client_opts.url + '/500_error', function(r) {
+ equal(r, false);
+ return start();
+ });
+});
+asyncTest("chunking test, invalid url port", function() {
+ var dl;
+ expect(1);
+ dl = document.location;
+ return SockJS.chunkingTest(dl.protocol + '//' + dl.hostname + ':1079', function(r) {
+ equal(r, false);
+ return start();
+ });
+});
+for (_j = 0, _len2 = protocols.length; _j < _len2; _j++) {
+ protocol = protocols[_j];
+ test_protocol_errors(protocol);
+}
View
89 deps/sockjs-client/tests/html/smoke-reconnect.html
@@ -0,0 +1,89 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta http-equiv="X-UA-Compatible" content="IE=edge" />
+ <meta charset="UTF-8" />
+
+ <link href="data:image/x-icon;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQEAYAAABPYyMiAAAABmJLR0T///////8JWPfcAAAACXBIWXMAAABIAAAASABGyWs+AAAAF0lEQVRIx2NgGAWjYBSMglEwCkbBSAcACBAAAeaR9cIAAAAASUVORK5CYII=" rel="icon" type="image/x-icon" />
+
+ <script type="text/javascript" src="lib/sockjs.js"></script>
+ <script type="text/javascript" src="static/jquery.min.js"></script>
+
+ <script type="text/javascript" src="config.js"></script>
+</head>
+<body>
+<form>
+ <select id="transport">
+ <option value="">- any - </option>
+ <option value="websocket">websocket</option>
+ <option value="xhr-streaming">xhr-streaming</option>
+ <option value="iframe-eventsource">iframe-eventsource</option>
+ <