diff --git a/dist/binary.js b/dist/binary.js index 2819fa7..2d5764f 100644 --- a/dist/binary.js +++ b/dist/binary.js @@ -1,4 +1,4 @@ -/*! binary.js build:0.0.0, development. Copyright(c) 2012 Eric Zhang MIT Licensed */ +/*! binary.js build:0.0.1, development. Copyright(c) 2012 Eric Zhang MIT Licensed */ (function(exports){ /** * EventEmitter v3.1.5 @@ -312,7 +312,36 @@ var util = { }, info: console.log.bind(console), pack: BinaryPack.pack, - unpack: BinaryPack.unpack + unpack: BinaryPack.unpack, + setZeroTimeout: (function(global) { + var timeouts = []; + var messageName = 'zero-timeout-message'; + + // Like setTimeout, but only takes a function argument. There's + // no time argument (always zero) and no arguments (you have to + // use a closure). + function setZeroTimeoutPostMessage(fn) { + timeouts.push(fn); + global.postMessage(messageName, '*'); + } + + function handleMessage(event) { + if (event.source == global && event.data == messageName) { + if (event.stopPropagation) { + event.stopPropagation(); + } + if (timeouts.length) { + timeouts.shift()(); + } + } + } + if (global.addEventListener) { + global.addEventListener('message', handleMessage, true); + } else if (global.attachEvent) { + global.attachEvent('onmessage', handleMessage); + } + return setZeroTimeoutPostMessage; + }(this)) }; // Stream shim for client side @@ -456,102 +485,105 @@ function BinaryClient(socket) { self.emit('close', code, message); }); this._socket.addEventListener('message', function(data, flags){ - // Message format - // [type, payload, bonus ] - // - // Reserved - // [ 0 , X , X ] - // - // - // New stream - // [ 1 , Meta , new streamId ] - // - // - // Data - // [ 2 , Data , streamId ] - // - // - // Pause - // [ 3 , null , streamId ] - // - // - // Resume - // [ 4 , null , streamId ] - // - // - // End - // [ 5 , null , streamId ] - // - // - // Close - // [ 6 , null , streamId ] - // - - if(data.hasOwnProperty('data')){ - data = data.data; - } - - data = util.unpack(data); - switch(data[0]) { - case 0: - // Reserved - break; - case 1: - var meta = data[1]; - var streamId = data[2]; - var binaryStream = self._receiveStream(streamId); - self.emit('stream', binaryStream, meta); - break; - case 2: - var payload = data[1]; - var streamId = data[2]; - var binaryStream = self._streams[streamId]; - if(binaryStream) { - binaryStream._onData(payload); - } else { - self.emit('error', 'Received `data` message for unknown stream: ' + streamId); - } - break; - case 3: - var streamId = data[2]; - var binaryStream = self._streams[streamId]; - if(binaryStream) { - binaryStream._onPause(); - } else { - self.emit('error', 'Received `pause` message for unknown stream: ' + streamId); - } - break; - case 4: - var streamId = data[2]; - var binaryStream = self._streams[streamId]; - if(binaryStream) { - binaryStream._onResume(); - } else { - self.emit('error', 'Received `resume` message for unknown stream: ' + streamId); - } - break; - case 5: - var streamId = data[2]; - var binaryStream = self._streams[streamId]; - if(binaryStream) { - binaryStream._onEnd(); - } else { - self.emit('error', 'Received `end` message for unknown stream: ' + streamId); - } - break; - case 6: - var streamId = data[2]; - var binaryStream = self._streams[streamId]; - if(binaryStream) { - binaryStream._onClose(); - delete self._streams[streamId]; - } else { - self.emit('error', 'Received `close` message for unknown stream: ' + streamId); - } - break; - default: - self.emit('error', 'Unrecognized message type received: ' + data[0]); - } + util.setZeroTimeout(function(){ + + // Message format + // [type, payload, bonus ] + // + // Reserved + // [ 0 , X , X ] + // + // + // New stream + // [ 1 , Meta , new streamId ] + // + // + // Data + // [ 2 , Data , streamId ] + // + // + // Pause + // [ 3 , null , streamId ] + // + // + // Resume + // [ 4 , null , streamId ] + // + // + // End + // [ 5 , null , streamId ] + // + // + // Close + // [ 6 , null , streamId ] + // + + if(data.hasOwnProperty('data')){ + data = data.data; + } + + data = util.unpack(data); + switch(data[0]) { + case 0: + // Reserved + break; + case 1: + var meta = data[1]; + var streamId = data[2]; + var binaryStream = self._receiveStream(streamId); + self.emit('stream', binaryStream, meta); + break; + case 2: + var payload = data[1]; + var streamId = data[2]; + var binaryStream = self._streams[streamId]; + if(binaryStream) { + binaryStream._onData(payload); + } else { + self.emit('error', 'Received `data` message for unknown stream: ' + streamId); + } + break; + case 3: + var streamId = data[2]; + var binaryStream = self._streams[streamId]; + if(binaryStream) { + binaryStream._onPause(); + } else { + self.emit('error', 'Received `pause` message for unknown stream: ' + streamId); + } + break; + case 4: + var streamId = data[2]; + var binaryStream = self._streams[streamId]; + if(binaryStream) { + binaryStream._onResume(); + } else { + self.emit('error', 'Received `resume` message for unknown stream: ' + streamId); + } + break; + case 5: + var streamId = data[2]; + var binaryStream = self._streams[streamId]; + if(binaryStream) { + binaryStream._onEnd(); + } else { + self.emit('error', 'Received `end` message for unknown stream: ' + streamId); + } + break; + case 6: + var streamId = data[2]; + var binaryStream = self._streams[streamId]; + if(binaryStream) { + binaryStream._onClose(); + delete self._streams[streamId]; + } else { + self.emit('error', 'Received `close` message for unknown stream: ' + streamId); + } + break; + default: + self.emit('error', 'Unrecognized message type received: ' + data[0]); + } + }); }); } diff --git a/dist/binary.min.js b/dist/binary.min.js index 84d34e3..b3844b9 100644 --- a/dist/binary.min.js +++ b/dist/binary.min.js @@ -1,3 +1,3 @@ -/*! binary.min.js build:0.0.0, production. Copyright(c) 2012 Eric Zhang MIT Licensed */ +/*! binary.min.js build:0.0.1, production. Copyright(c) 2012 Eric Zhang MIT Licensed */ (function(exports){ -(function(e){function t(){this._events={},this._maxListeners=10}function n(e,t,n,r,i){this.type=e,this.listener=t,this.scope=n,this.once=r,this.instance=i}function s(e,t,n,r){if(!(this instanceof s))return new s(options);var o=this;i.call(this),this.id=t,this._socket=e,this._socket.addEventListener("error",function(e){o.readable=!1,o.writable=!1,o.emit("error",e)}),this._socket.addEventListener("close",function(e,t){o.readable=!1,o.writable=!1,o.emit("close",e,t)}),this.writable=!0,this.readable=!0,this._paused=!1,n&&this._write(1,r,this.id)}function o(e){if(!(this instanceof o))return new o(options);t.call(this);var n=this;this._streams={},this._nextId=0,typeof e=="string"?this._socket=new WebSocket(e):this._socket=e,this._socket.binaryType="arraybuffer",this._socket.addEventListener("error",function(e){n.emit("error",e)}),this._socket.addEventListener("close",function(e,t){n.emit("close",e,t)}),this._socket.addEventListener("message",function(e,t){e.hasOwnProperty("data")&&(e=e.data),e=r.unpack(e);switch(e[0]){case 0:break;case 1:var i=e[1],s=e[2],o=n._receiveStream(s);n.emit("stream",o,i);break;case 2:var u=e[1],s=e[2],o=n._streams[s];o?o._onData(u):n.emit("error","Received `data` message for unknown stream: "+s);break;case 3:var s=e[2],o=n._streams[s];o?o._onPause():n.emit("error","Received `pause` message for unknown stream: "+s);break;case 4:var s=e[2],o=n._streams[s];o?o._onResume():n.emit("error","Received `resume` message for unknown stream: "+s);break;case 5:var s=e[2],o=n._streams[s];o?o._onEnd():n.emit("error","Received `end` message for unknown stream: "+s);break;case 6:var s=e[2],o=n._streams[s];o?(o._onClose(),delete n._streams[s]):n.emit("error","Received `close` message for unknown stream: "+s);break;default:n.emit("error","Unrecognized message type received: "+e[0])}})}n.prototype.fire=function(e){this.listener.apply(this.scope||this.instance,e);if(this.once)return this.instance.removeListener(this.type,this.listener,this.scope),!1},t.prototype.eachListener=function(e,t){var n=null,r=null,i=null;if(this._events.hasOwnProperty(e)){r=this._events[e];for(n=0;nthis._maxListeners&&(typeof console!="undefined"&&console.warn("Possible EventEmitter memory leak detected. "+this._events[e].length+" listeners added. Use emitter.setMaxListeners() to increase limit."),this._events[e].warned=!0),this},t.prototype.on=t.prototype.addListener,t.prototype.once=function(e,t,n){return this.addListener(e,t,n,!0)},t.prototype.removeListener=function(e,t,n){return this.eachListener(e,function(r,i){r.listener===t&&(!n||r.scope===n)&&this._events[e].splice(i,1)}),this._events[e]&&this._events[e].length===0&&delete this._events[e],this},t.prototype.off=t.prototype.removeListener,t.prototype.removeAllListeners=function(e){return e&&this._events.hasOwnProperty(e)?delete this._events[e]:e||(this._events={}),this},t.prototype.listeners=function(e){if(this._events.hasOwnProperty(e)){var t=[];return this.eachListener(e,function(e){t.push(e.listener)}),t}return[]},t.prototype.emit=function(e){var t=[],n=null;for(n=1;nthis._maxListeners&&(typeof console!="undefined"&&console.warn("Possible EventEmitter memory leak detected. "+this._events[e].length+" listeners added. Use emitter.setMaxListeners() to increase limit."),this._events[e].warned=!0),this},t.prototype.on=t.prototype.addListener,t.prototype.once=function(e,t,n){return this.addListener(e,t,n,!0)},t.prototype.removeListener=function(e,t,n){return this.eachListener(e,function(r,i){r.listener===t&&(!n||r.scope===n)&&this._events[e].splice(i,1)}),this._events[e]&&this._events[e].length===0&&delete this._events[e],this},t.prototype.off=t.prototype.removeListener,t.prototype.removeAllListeners=function(e){return e&&this._events.hasOwnProperty(e)?delete this._events[e]:e||(this._events={}),this},t.prototype.listeners=function(e){if(this._events.hasOwnProperty(e)){var t=[];return this.eachListener(e,function(e){t.push(e.listener)}),t}return[]},t.prototype.emit=function(e){var t=[],n=null;for(n=1;n MIT Licensed */ +/*! binary.js build:0.0.1, development. Copyright(c) 2012 Eric Zhang MIT Licensed */ (function(exports){ /** * EventEmitter v3.1.5 @@ -312,7 +312,36 @@ var util = { }, info: console.log.bind(console), pack: BinaryPack.pack, - unpack: BinaryPack.unpack + unpack: BinaryPack.unpack, + setZeroTimeout: (function(global) { + var timeouts = []; + var messageName = 'zero-timeout-message'; + + // Like setTimeout, but only takes a function argument. There's + // no time argument (always zero) and no arguments (you have to + // use a closure). + function setZeroTimeoutPostMessage(fn) { + timeouts.push(fn); + global.postMessage(messageName, '*'); + } + + function handleMessage(event) { + if (event.source == global && event.data == messageName) { + if (event.stopPropagation) { + event.stopPropagation(); + } + if (timeouts.length) { + timeouts.shift()(); + } + } + } + if (global.addEventListener) { + global.addEventListener('message', handleMessage, true); + } else if (global.attachEvent) { + global.attachEvent('onmessage', handleMessage); + } + return setZeroTimeoutPostMessage; + }(this)) }; // Stream shim for client side @@ -456,102 +485,105 @@ function BinaryClient(socket) { self.emit('close', code, message); }); this._socket.addEventListener('message', function(data, flags){ - // Message format - // [type, payload, bonus ] - // - // Reserved - // [ 0 , X , X ] - // - // - // New stream - // [ 1 , Meta , new streamId ] - // - // - // Data - // [ 2 , Data , streamId ] - // - // - // Pause - // [ 3 , null , streamId ] - // - // - // Resume - // [ 4 , null , streamId ] - // - // - // End - // [ 5 , null , streamId ] - // - // - // Close - // [ 6 , null , streamId ] - // - - if(data.hasOwnProperty('data')){ - data = data.data; - } - - data = util.unpack(data); - switch(data[0]) { - case 0: - // Reserved - break; - case 1: - var meta = data[1]; - var streamId = data[2]; - var binaryStream = self._receiveStream(streamId); - self.emit('stream', binaryStream, meta); - break; - case 2: - var payload = data[1]; - var streamId = data[2]; - var binaryStream = self._streams[streamId]; - if(binaryStream) { - binaryStream._onData(payload); - } else { - self.emit('error', 'Received `data` message for unknown stream: ' + streamId); - } - break; - case 3: - var streamId = data[2]; - var binaryStream = self._streams[streamId]; - if(binaryStream) { - binaryStream._onPause(); - } else { - self.emit('error', 'Received `pause` message for unknown stream: ' + streamId); - } - break; - case 4: - var streamId = data[2]; - var binaryStream = self._streams[streamId]; - if(binaryStream) { - binaryStream._onResume(); - } else { - self.emit('error', 'Received `resume` message for unknown stream: ' + streamId); - } - break; - case 5: - var streamId = data[2]; - var binaryStream = self._streams[streamId]; - if(binaryStream) { - binaryStream._onEnd(); - } else { - self.emit('error', 'Received `end` message for unknown stream: ' + streamId); - } - break; - case 6: - var streamId = data[2]; - var binaryStream = self._streams[streamId]; - if(binaryStream) { - binaryStream._onClose(); - delete self._streams[streamId]; - } else { - self.emit('error', 'Received `close` message for unknown stream: ' + streamId); - } - break; - default: - self.emit('error', 'Unrecognized message type received: ' + data[0]); - } + util.setZeroTimeout(function(){ + + // Message format + // [type, payload, bonus ] + // + // Reserved + // [ 0 , X , X ] + // + // + // New stream + // [ 1 , Meta , new streamId ] + // + // + // Data + // [ 2 , Data , streamId ] + // + // + // Pause + // [ 3 , null , streamId ] + // + // + // Resume + // [ 4 , null , streamId ] + // + // + // End + // [ 5 , null , streamId ] + // + // + // Close + // [ 6 , null , streamId ] + // + + if(data.hasOwnProperty('data')){ + data = data.data; + } + + data = util.unpack(data); + switch(data[0]) { + case 0: + // Reserved + break; + case 1: + var meta = data[1]; + var streamId = data[2]; + var binaryStream = self._receiveStream(streamId); + self.emit('stream', binaryStream, meta); + break; + case 2: + var payload = data[1]; + var streamId = data[2]; + var binaryStream = self._streams[streamId]; + if(binaryStream) { + binaryStream._onData(payload); + } else { + self.emit('error', 'Received `data` message for unknown stream: ' + streamId); + } + break; + case 3: + var streamId = data[2]; + var binaryStream = self._streams[streamId]; + if(binaryStream) { + binaryStream._onPause(); + } else { + self.emit('error', 'Received `pause` message for unknown stream: ' + streamId); + } + break; + case 4: + var streamId = data[2]; + var binaryStream = self._streams[streamId]; + if(binaryStream) { + binaryStream._onResume(); + } else { + self.emit('error', 'Received `resume` message for unknown stream: ' + streamId); + } + break; + case 5: + var streamId = data[2]; + var binaryStream = self._streams[streamId]; + if(binaryStream) { + binaryStream._onEnd(); + } else { + self.emit('error', 'Received `end` message for unknown stream: ' + streamId); + } + break; + case 6: + var streamId = data[2]; + var binaryStream = self._streams[streamId]; + if(binaryStream) { + binaryStream._onClose(); + delete self._streams[streamId]; + } else { + self.emit('error', 'Received `close` message for unknown stream: ' + streamId); + } + break; + default: + self.emit('error', 'Unrecognized message type received: ' + data[0]); + } + }); }); } diff --git a/examples/public/index.html b/examples/public/index.html index 4399178..1c8dcdd 100644 --- a/examples/public/index.html +++ b/examples/public/index.html @@ -27,7 +27,7 @@ // Display new data in browser! var img = document.createElement("img"); - img.src = window.webkitURL.createObjectURL(new Blob(parts));; + img.src = window.webkitURL.createObjectURL(new Blob(parts)); document.body.appendChild(img); console.log('Stream completed', stream.id)}); }); diff --git a/lib/client.js b/lib/client.js index a7e0ad2..16d42be 100644 --- a/lib/client.js +++ b/lib/client.js @@ -39,102 +39,105 @@ function BinaryClient(socket) { self.emit('close', code, message); }); this._socket.addEventListener('message', function(data, flags){ - // Message format - // [type, payload, bonus ] - // - // Reserved - // [ 0 , X , X ] - // - // - // New stream - // [ 1 , Meta , new streamId ] - // - // - // Data - // [ 2 , Data , streamId ] - // - // - // Pause - // [ 3 , null , streamId ] - // - // - // Resume - // [ 4 , null , streamId ] - // - // - // End - // [ 5 , null , streamId ] - // - // - // Close - // [ 6 , null , streamId ] - // - - if(data.hasOwnProperty('data')){ - data = data.data; - } - - data = util.unpack(data); - switch(data[0]) { - case 0: - // Reserved - break; - case 1: - var meta = data[1]; - var streamId = data[2]; - var binaryStream = self._receiveStream(streamId); - self.emit('stream', binaryStream, meta); - break; - case 2: - var payload = data[1]; - var streamId = data[2]; - var binaryStream = self._streams[streamId]; - if(binaryStream) { - binaryStream._onData(payload); - } else { - self.emit('error', 'Received `data` message for unknown stream: ' + streamId); - } - break; - case 3: - var streamId = data[2]; - var binaryStream = self._streams[streamId]; - if(binaryStream) { - binaryStream._onPause(); - } else { - self.emit('error', 'Received `pause` message for unknown stream: ' + streamId); - } - break; - case 4: - var streamId = data[2]; - var binaryStream = self._streams[streamId]; - if(binaryStream) { - binaryStream._onResume(); - } else { - self.emit('error', 'Received `resume` message for unknown stream: ' + streamId); - } - break; - case 5: - var streamId = data[2]; - var binaryStream = self._streams[streamId]; - if(binaryStream) { - binaryStream._onEnd(); - } else { - self.emit('error', 'Received `end` message for unknown stream: ' + streamId); - } - break; - case 6: - var streamId = data[2]; - var binaryStream = self._streams[streamId]; - if(binaryStream) { - binaryStream._onClose(); - delete self._streams[streamId]; - } else { - self.emit('error', 'Received `close` message for unknown stream: ' + streamId); - } - break; - default: - self.emit('error', 'Unrecognized message type received: ' + data[0]); - } + util.setZeroTimeout(function(){ + + // Message format + // [type, payload, bonus ] + // + // Reserved + // [ 0 , X , X ] + // + // + // New stream + // [ 1 , Meta , new streamId ] + // + // + // Data + // [ 2 , Data , streamId ] + // + // + // Pause + // [ 3 , null , streamId ] + // + // + // Resume + // [ 4 , null , streamId ] + // + // + // End + // [ 5 , null , streamId ] + // + // + // Close + // [ 6 , null , streamId ] + // + + if(data.hasOwnProperty('data')){ + data = data.data; + } + + data = util.unpack(data); + switch(data[0]) { + case 0: + // Reserved + break; + case 1: + var meta = data[1]; + var streamId = data[2]; + var binaryStream = self._receiveStream(streamId); + self.emit('stream', binaryStream, meta); + break; + case 2: + var payload = data[1]; + var streamId = data[2]; + var binaryStream = self._streams[streamId]; + if(binaryStream) { + binaryStream._onData(payload); + } else { + self.emit('error', 'Received `data` message for unknown stream: ' + streamId); + } + break; + case 3: + var streamId = data[2]; + var binaryStream = self._streams[streamId]; + if(binaryStream) { + binaryStream._onPause(); + } else { + self.emit('error', 'Received `pause` message for unknown stream: ' + streamId); + } + break; + case 4: + var streamId = data[2]; + var binaryStream = self._streams[streamId]; + if(binaryStream) { + binaryStream._onResume(); + } else { + self.emit('error', 'Received `resume` message for unknown stream: ' + streamId); + } + break; + case 5: + var streamId = data[2]; + var binaryStream = self._streams[streamId]; + if(binaryStream) { + binaryStream._onEnd(); + } else { + self.emit('error', 'Received `end` message for unknown stream: ' + streamId); + } + break; + case 6: + var streamId = data[2]; + var binaryStream = self._streams[streamId]; + if(binaryStream) { + binaryStream._onClose(); + delete self._streams[streamId]; + } else { + self.emit('error', 'Received `close` message for unknown stream: ' + streamId); + } + break; + default: + self.emit('error', 'Unrecognized message type received: ' + data[0]); + } + }); }); } diff --git a/lib/util.js b/lib/util.js index 69298df..b33e5a5 100644 --- a/lib/util.js +++ b/lib/util.js @@ -16,12 +16,42 @@ var util = { }, info: console.log.bind(console), pack: BinaryPack.pack, - unpack: BinaryPack.unpack + unpack: BinaryPack.unpack, + setZeroTimeout: (function(global) { + var timeouts = []; + var messageName = 'zero-timeout-message'; + + // Like setTimeout, but only takes a function argument. There's + // no time argument (always zero) and no arguments (you have to + // use a closure). + function setZeroTimeoutPostMessage(fn) { + timeouts.push(fn); + global.postMessage(messageName, '*'); + } + + function handleMessage(event) { + if (event.source == global && event.data == messageName) { + if (event.stopPropagation) { + event.stopPropagation(); + } + if (timeouts.length) { + timeouts.shift()(); + } + } + } + if (global.addEventListener) { + global.addEventListener('message', handleMessage, true); + } else if (global.attachEvent) { + global.attachEvent('onmessage', handleMessage); + } + return setZeroTimeoutPostMessage; + }(this)) }; // Stream shim for client side // if node var EventEmitter = null; +util.setZeroTimeout = process.nextTick; // end node var Stream = EventEmitter;