Skip to content

Commit

Permalink
lib/WebSocket.js: expose binaryType property
Browse files Browse the repository at this point in the history
The W3C WebSocket interface includes a binaryType attributes for a
socket and a corresponding BinaryType { 'blob', 'arraybuffer' } enum.
This enables support for the 'arraybuffer' BinaryType, but avoiding
changing the existing behaviour the default binaryType is set as
'nodebuffer'. The 'blob' type is left unsupported.

This improves ws compatibility with some existing W3C WebSocket based
client code.

Fixes: websockets#441
  • Loading branch information
rib committed Mar 15, 2016
1 parent 8aae0de commit b80b335
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 0 deletions.
24 changes: 24 additions & 0 deletions lib/WebSocket.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ function WebSocket(address, protocols, options) {
this.readyState = null;
this.supports = {};
this.extensions = {};
this._binaryType = 'nodebuffer';

if (Array.isArray(address)) {
initAsServerClient.apply(this, address.concat(options));
Expand Down Expand Up @@ -371,6 +372,27 @@ Object.defineProperty(WebSocket.prototype, 'bufferedAmount', {
}
});

/**
* Expose binaryType
*
* This deviates from the W3C interface since ws doesn't support the required
* default "blob" type (instead we define a custom "nodebuffer" type).
*
* @see http://dev.w3.org/html5/websockets/#the-websocket-interface
* @api public
*/
Object.defineProperty(WebSocket.prototype, 'binaryType', {
get: function get() {
return this._binaryType;
},
set: function set(type) {
if (type === 'arraybuffer' || type === 'nodebuffer')
this._binaryType = type;
else
throw new SyntaxError('unsupported binaryType: must be either "nodebuffer" or "arraybuffer"');
}
});

/**
* Emulates the W3C Browser based WebSocket interface using function members.
*
Expand Down Expand Up @@ -415,6 +437,8 @@ WebSocket.prototype.addEventListener = function(method, listener) {
var target = this;

function onMessage (data, flags) {
if (flags.binary && this.binaryType === 'arraybuffer')
data = new Uint8Array(data).buffer;
listener.call(target, new MessageEvent(data, !!flags.binary, target));
}

Expand Down
61 changes: 61 additions & 0 deletions test/WebSocket.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1544,6 +1544,10 @@ describe('WebSocket', function() {
ws.onclose = listener;
ws.onopen = listener;

assert.ok(ws.binaryType === 'nodebuffer');
ws.binaryType = 'arraybuffer';
assert.ok(ws.binaryType === 'arraybuffer');

assert.ok(ws.onopen === listener);
assert.ok(ws.onmessage === listener);
assert.ok(ws.onclose === listener);
Expand Down Expand Up @@ -1694,6 +1698,63 @@ describe('WebSocket', function() {
client.send('hi')
});
});

it('should pass binary data as a node.js Buffer by default', function(done) {
server.createServer(++port, function(srv) {
var ws = new WebSocket('ws://localhost:' + port);
var array = new Uint8Array(4096);

ws.onopen = function() {
ws.send(array, {binary: true});
};
ws.onmessage = function(messageEvent) {
assert.ok(messageEvent.binary);
assert.ok(ws.binaryType === 'nodebuffer');
assert.ok(messageEvent.data instanceof Buffer);
ws.terminate();
srv.close();
done();
};
});
});

it('should pass an ArrayBuffer for event.data if binaryType = arraybuffer', function(done) {
server.createServer(++port, function(srv) {
var ws = new WebSocket('ws://localhost:' + port);
ws.binaryType = 'arraybuffer';
var array = new Uint8Array(4096);

ws.onopen = function() {
ws.send(array, {binary: true});
};
ws.onmessage = function(messageEvent) {
assert.ok(messageEvent.binary);
assert.ok(messageEvent.data instanceof ArrayBuffer);
ws.terminate();
srv.close();
done();
};
});
});

it('should ignore binaryType for text messages', function(done) {
server.createServer(++port, function(srv) {
var ws = new WebSocket('ws://localhost:' + port);
ws.binaryType = 'arraybuffer';

ws.onopen = function() {
ws.send('foobar');
};
ws.onmessage = function(messageEvent) {
assert.ok(!messageEvent.binary);
assert.ok(typeof messageEvent.data === 'string');
ws.terminate();
srv.close();
done();
};
});
});

});

describe('ssl', function() {
Expand Down

0 comments on commit b80b335

Please sign in to comment.