| // Copyright Joyent, Inc. and other Node contributors. | 
| // | 
| // Permission is hereby granted, free of charge, to any person obtaining a | 
| // copy of this software and associated documentation files (the | 
| // "Software"), to deal in the Software without restriction, including | 
| // without limitation the rights to use, copy, modify, merge, publish, | 
| // distribute, sublicense, and/or sell copies of the Software, and to permit | 
| // persons to whom the Software is furnished to do so, subject to the | 
| // following conditions: | 
| // | 
| // The above copyright notice and this permission notice shall be included | 
| // in all copies or substantial portions of the Software. | 
| // | 
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | 
| // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | 
| // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN | 
| // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, | 
| // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR | 
| // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE | 
| // USE OR OTHER DEALINGS IN THE SOFTWARE. | 
| // a duplex stream is just a stream that is both readable and writable. | 
| // Since JS doesn't have multiple prototypal inheritance, this class | 
| // prototypally inherits from Readable, and then parasitically from | 
| // Writable. | 
| 'use strict'; | 
| /*<replacement>*/ | 
|   | 
| var objectKeys = Object.keys || function (obj) { | 
|   var keys = []; | 
|   | 
|   for (var key in obj) { | 
|     keys.push(key); | 
|   } | 
|   | 
|   return keys; | 
| }; | 
| /*</replacement>*/ | 
|   | 
|   | 
| module.exports = Duplex; | 
|   | 
| var Readable = require('./_stream_readable'); | 
|   | 
| var Writable = require('./_stream_writable'); | 
|   | 
| require('inherits')(Duplex, Readable); | 
|   | 
| { | 
|   // Allow the keys array to be GC'ed. | 
|   var keys = objectKeys(Writable.prototype); | 
|   | 
|   for (var v = 0; v < keys.length; v++) { | 
|     var method = keys[v]; | 
|     if (!Duplex.prototype[method]) Duplex.prototype[method] = Writable.prototype[method]; | 
|   } | 
| } | 
|   | 
| function Duplex(options) { | 
|   if (!(this instanceof Duplex)) return new Duplex(options); | 
|   Readable.call(this, options); | 
|   Writable.call(this, options); | 
|   this.allowHalfOpen = true; | 
|   | 
|   if (options) { | 
|     if (options.readable === false) this.readable = false; | 
|     if (options.writable === false) this.writable = false; | 
|   | 
|     if (options.allowHalfOpen === false) { | 
|       this.allowHalfOpen = false; | 
|       this.once('end', onend); | 
|     } | 
|   } | 
| } | 
|   | 
| Object.defineProperty(Duplex.prototype, 'writableHighWaterMark', { | 
|   // making it explicit this property is not enumerable | 
|   // because otherwise some prototype manipulation in | 
|   // userland will fail | 
|   enumerable: false, | 
|   get: function get() { | 
|     return this._writableState.highWaterMark; | 
|   } | 
| }); | 
| Object.defineProperty(Duplex.prototype, 'writableBuffer', { | 
|   // making it explicit this property is not enumerable | 
|   // because otherwise some prototype manipulation in | 
|   // userland will fail | 
|   enumerable: false, | 
|   get: function get() { | 
|     return this._writableState && this._writableState.getBuffer(); | 
|   } | 
| }); | 
| Object.defineProperty(Duplex.prototype, 'writableLength', { | 
|   // making it explicit this property is not enumerable | 
|   // because otherwise some prototype manipulation in | 
|   // userland will fail | 
|   enumerable: false, | 
|   get: function get() { | 
|     return this._writableState.length; | 
|   } | 
| }); // the no-half-open enforcer | 
|   | 
| function onend() { | 
|   // If the writable side ended, then we're ok. | 
|   if (this._writableState.ended) return; // no more data can be written. | 
|   // But allow more writes to happen in this tick. | 
|   | 
|   process.nextTick(onEndNT, this); | 
| } | 
|   | 
| function onEndNT(self) { | 
|   self.end(); | 
| } | 
|   | 
| Object.defineProperty(Duplex.prototype, 'destroyed', { | 
|   // making it explicit this property is not enumerable | 
|   // because otherwise some prototype manipulation in | 
|   // userland will fail | 
|   enumerable: false, | 
|   get: function get() { | 
|     if (this._readableState === undefined || this._writableState === undefined) { | 
|       return false; | 
|     } | 
|   | 
|     return this._readableState.destroyed && this._writableState.destroyed; | 
|   }, | 
|   set: function set(value) { | 
|     // we ignore the value if the stream | 
|     // has not been initialized yet | 
|     if (this._readableState === undefined || this._writableState === undefined) { | 
|       return; | 
|     } // backward compatibility, the user is explicitly | 
|     // managing destroyed | 
|   | 
|   | 
|     this._readableState.destroyed = value; | 
|     this._writableState.destroyed = value; | 
|   } | 
| }); |