Skip to content

Commit

Permalink
fix: ReadableStream detection in Chrome Apps
Browse files Browse the repository at this point in the history
Detection via `stream instanceof Stream` does not work correctly in browser context,
especially when different polyfils are used and mixed together.

This change replaces instanceof check with feature-detection of stream-like objects.
It enables Hapi to be used in Chrome Apps (browser environments with additional chrome.sockets APIs)

Real life example:
ipfs/ipfs-companion#664
  • Loading branch information
lidel committed Sep 12, 2019
1 parent 10d30d0 commit 0d73f8d
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 3 deletions.
6 changes: 3 additions & 3 deletions lib/response.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ exports = module.exports = internals.Response = class {
this.variety = 'buffer';
this._contentType = 'application/octet-stream';
}
else if (source instanceof Stream) {
else if (Streams.isReadableStream(source)) {
this.variety = 'stream';
this._contentType = 'application/octet-stream';
}
Expand Down Expand Up @@ -529,7 +529,7 @@ exports = module.exports = internals.Response = class {

// Stream source

if (source instanceof Stream) {
if (Streams.isStream(source)) {
if (typeof source._read !== 'function') {
throw Boom.badImplementation('Stream must have a readable interface');
}
Expand Down Expand Up @@ -607,7 +607,7 @@ exports = module.exports = internals.Response = class {
}

const stream = this._payload || this.source;
if (stream instanceof Stream) {
if (Streams.isReadableStream(stream)) {
internals.Response.drain(stream);
}
}
Expand Down
14 changes: 14 additions & 0 deletions lib/streams.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,20 @@ const internals = {
team: Symbol('team')
};

exports.isStream = function (stream) {

return stream !== null &&
typeof stream === 'object' &&
typeof stream.pipe === 'function';
};

exports.isReadableStream = function (stream) {

return exports.isStream(stream) &&
stream.readable !== false &&
typeof stream._read === 'function' &&
typeof stream._readableState === 'object';
};

exports.drain = function (stream) {

Expand Down

0 comments on commit 0d73f8d

Please sign in to comment.