stream: proper instanceof
for Writable
s
Use `[Symbol.hasInstance]()` to return `true` when asking for `new Duplex() instanceof Writable`. PR-URL: https://github.com/nodejs/node/pull/8834 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Calvin Metcalf <calvin.metcalf@gmail.com>
This commit is contained in:
parent
a6e1be4a4e
commit
2a4b068aca
@ -1559,7 +1559,9 @@ Because JavaScript does not have support for multiple inheritance, the
|
|||||||
to extending the `stream.Readable` *and* `stream.Writable` classes).
|
to extending the `stream.Readable` *and* `stream.Writable` classes).
|
||||||
|
|
||||||
*Note*: The `stream.Duplex` class prototypically inherits from `stream.Readable`
|
*Note*: The `stream.Duplex` class prototypically inherits from `stream.Readable`
|
||||||
and parasitically from `stream.Writable`.
|
and parasitically from `stream.Writable`, but `instanceof` will work properly
|
||||||
|
for both base classes due to overriding [`Symbol.hasInstance`][]
|
||||||
|
on `stream.Writable`.
|
||||||
|
|
||||||
Custom Duplex streams *must* call the `new stream.Duplex([options])`
|
Custom Duplex streams *must* call the `new stream.Duplex([options])`
|
||||||
constructor and implement *both* the `readable._read()` and
|
constructor and implement *both* the `readable._read()` and
|
||||||
@ -2009,3 +2011,4 @@ readable buffer so there is nothing for a user to consume.
|
|||||||
[Transform]: #stream_class_stream_transform
|
[Transform]: #stream_class_stream_transform
|
||||||
[Writable]: #stream_class_stream_writable
|
[Writable]: #stream_class_stream_writable
|
||||||
[zlib]: zlib.html
|
[zlib]: zlib.html
|
||||||
|
[`Symbol.hasInstance`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/hasInstance
|
||||||
|
@ -134,11 +134,32 @@ Object.defineProperty(WritableState.prototype, 'buffer', {
|
|||||||
'instead.')
|
'instead.')
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Test _writableState for inheritance to account for Duplex streams,
|
||||||
|
// whose prototype chain only points to Readable.
|
||||||
|
var realHasInstance;
|
||||||
|
if (typeof Symbol === 'function' && Symbol.hasInstance) {
|
||||||
|
realHasInstance = Function.prototype[Symbol.hasInstance];
|
||||||
|
Object.defineProperty(Writable, Symbol.hasInstance, {
|
||||||
|
value: function(object) {
|
||||||
|
// Trying to move the `realHasInstance` from the Writable constructor
|
||||||
|
// to here will break the Node.js LazyTransform implementation.
|
||||||
|
return object._writableState instanceof WritableState;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
realHasInstance = function(object) {
|
||||||
|
return object instanceof this;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
function Writable(options) {
|
function Writable(options) {
|
||||||
// Writable ctor is applied to Duplexes, though they're not
|
// Writable ctor is applied to Duplexes, too.
|
||||||
// instanceof Writable, they're instanceof Readable.
|
// `realHasInstance` is necessary because using plain `instanceof`
|
||||||
if (!(this instanceof Writable) && !(this instanceof Stream.Duplex))
|
// would return false, as no `_writableState` property is attached.
|
||||||
|
if (!(realHasInstance.call(Writable, this)) &&
|
||||||
|
!(this instanceof Stream.Duplex)) {
|
||||||
return new Writable(options);
|
return new Writable(options);
|
||||||
|
}
|
||||||
|
|
||||||
this._writableState = new WritableState(options, this);
|
this._writableState = new WritableState(options, this);
|
||||||
|
|
||||||
|
29
test/parallel/test-stream-inheritance.js
Normal file
29
test/parallel/test-stream-inheritance.js
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
'use strict';
|
||||||
|
require('../common');
|
||||||
|
const assert = require('assert');
|
||||||
|
const { Readable, Writable, Duplex, Transform } = require('stream');
|
||||||
|
|
||||||
|
const readable = new Readable({ read() {} });
|
||||||
|
const writable = new Writable({ write() {} });
|
||||||
|
const duplex = new Duplex({ read() {}, write() {} });
|
||||||
|
const transform = new Transform({ transform() {} });
|
||||||
|
|
||||||
|
assert.ok(readable instanceof Readable);
|
||||||
|
assert.ok(!(writable instanceof Readable));
|
||||||
|
assert.ok(duplex instanceof Readable);
|
||||||
|
assert.ok(transform instanceof Readable);
|
||||||
|
|
||||||
|
assert.ok(!(readable instanceof Writable));
|
||||||
|
assert.ok(writable instanceof Writable);
|
||||||
|
assert.ok(duplex instanceof Writable);
|
||||||
|
assert.ok(transform instanceof Writable);
|
||||||
|
|
||||||
|
assert.ok(!(readable instanceof Duplex));
|
||||||
|
assert.ok(!(writable instanceof Duplex));
|
||||||
|
assert.ok(duplex instanceof Duplex);
|
||||||
|
assert.ok(transform instanceof Duplex);
|
||||||
|
|
||||||
|
assert.ok(!(readable instanceof Transform));
|
||||||
|
assert.ok(!(writable instanceof Transform));
|
||||||
|
assert.ok(!(duplex instanceof Transform));
|
||||||
|
assert.ok(transform instanceof Transform);
|
Loading…
x
Reference in New Issue
Block a user