1// Copyright Joyent, Inc. and other Node contributors. 2// 3// Permission is hereby granted, free of charge, to any person obtaining a 4// copy of this software and associated documentation files (the 5// "Software"), to deal in the Software without restriction, including 6// without limitation the rights to use, copy, modify, merge, publish, 7// distribute, sublicense, and/or sell copies of the Software, and to permit 8// persons to whom the Software is furnished to do so, subject to the 9// following conditions: 10// 11// The above copyright notice and this permission notice shall be included 12// in all copies or substantial portions of the Software. 13// 14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 17// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 18// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 20// USE OR OTHER DEALINGS IN THE SOFTWARE. 21 22// a duplex stream is just a stream that is both readable and writable. 23// Since JS doesn't have multiple prototype inheritance, this class 24// prototypically inherits from Readable, and then parasitically from 25// Writable. 26 27'use strict'; 28 29const { 30 ObjectDefineProperties, 31 ObjectGetOwnPropertyDescriptor, 32 ObjectKeys, 33 ObjectSetPrototypeOf, 34} = primordials; 35 36module.exports = Duplex; 37 38const Readable = require('internal/streams/readable'); 39const Writable = require('internal/streams/writable'); 40 41ObjectSetPrototypeOf(Duplex.prototype, Readable.prototype); 42ObjectSetPrototypeOf(Duplex, Readable); 43 44{ 45 // Allow the keys array to be GC'ed. 46 for (const method of ObjectKeys(Writable.prototype)) { 47 if (!Duplex.prototype[method]) 48 Duplex.prototype[method] = Writable.prototype[method]; 49 } 50} 51 52function Duplex(options) { 53 if (!(this instanceof Duplex)) 54 return new Duplex(options); 55 56 Readable.call(this, options); 57 Writable.call(this, options); 58 this.allowHalfOpen = true; 59 60 if (options) { 61 if (options.readable === false) 62 this.readable = false; 63 64 if (options.writable === false) 65 this.writable = false; 66 67 if (options.allowHalfOpen === false) { 68 this.allowHalfOpen = false; 69 } 70 } 71} 72 73ObjectDefineProperties(Duplex.prototype, { 74 writable: 75 ObjectGetOwnPropertyDescriptor(Writable.prototype, 'writable'), 76 writableHighWaterMark: 77 ObjectGetOwnPropertyDescriptor(Writable.prototype, 'writableHighWaterMark'), 78 writableObjectMode: 79 ObjectGetOwnPropertyDescriptor(Writable.prototype, 'writableObjectMode'), 80 writableBuffer: 81 ObjectGetOwnPropertyDescriptor(Writable.prototype, 'writableBuffer'), 82 writableLength: 83 ObjectGetOwnPropertyDescriptor(Writable.prototype, 'writableLength'), 84 writableFinished: 85 ObjectGetOwnPropertyDescriptor(Writable.prototype, 'writableFinished'), 86 writableCorked: 87 ObjectGetOwnPropertyDescriptor(Writable.prototype, 'writableCorked'), 88 writableEnded: 89 ObjectGetOwnPropertyDescriptor(Writable.prototype, 'writableEnded'), 90 writableNeedDrain: 91 ObjectGetOwnPropertyDescriptor(Writable.prototype, 'writableNeedDrain'), 92 93 destroyed: { 94 get() { 95 if (this._readableState === undefined || 96 this._writableState === undefined) { 97 return false; 98 } 99 return this._readableState.destroyed && this._writableState.destroyed; 100 }, 101 set(value) { 102 // Backward compatibility, the user is explicitly 103 // managing destroyed. 104 if (this._readableState && this._writableState) { 105 this._readableState.destroyed = value; 106 this._writableState.destroyed = value; 107 } 108 } 109 } 110}); 111