UNPKG

4.4 kBJavaScriptView Raw
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// a duplex stream is just a stream that is both readable and writable.
22// Since JS doesn't have multiple prototypal inheritance, this class
23// prototypally inherits from Readable, and then parasitically from
24// Writable.
25'use strict';
26/*<replacement>*/
27
28var objectKeys = Object.keys || function (obj) {
29 var keys = [];
30
31 for (var key in obj) {
32 keys.push(key);
33 }
34
35 return keys;
36};
37/*</replacement>*/
38
39
40module.exports = Duplex;
41
42var Readable = require('./_stream_readable');
43
44var Writable = require('./_stream_writable');
45
46require('inherits')(Duplex, Readable);
47
48{
49 // Allow the keys array to be GC'ed.
50 var keys = objectKeys(Writable.prototype);
51
52 for (var v = 0; v < keys.length; v++) {
53 var method = keys[v];
54 if (!Duplex.prototype[method]) Duplex.prototype[method] = Writable.prototype[method];
55 }
56}
57
58function Duplex(options) {
59 if (!(this instanceof Duplex)) return new Duplex(options);
60 Readable.call(this, options);
61 Writable.call(this, options);
62 this.allowHalfOpen = true;
63
64 if (options) {
65 if (options.readable === false) this.readable = false;
66 if (options.writable === false) this.writable = false;
67
68 if (options.allowHalfOpen === false) {
69 this.allowHalfOpen = false;
70 this.once('end', onend);
71 }
72 }
73}
74
75Object.defineProperty(Duplex.prototype, 'writableHighWaterMark', {
76 // making it explicit this property is not enumerable
77 // because otherwise some prototype manipulation in
78 // userland will fail
79 enumerable: false,
80 get: function get() {
81 return this._writableState.highWaterMark;
82 }
83});
84Object.defineProperty(Duplex.prototype, 'writableBuffer', {
85 // making it explicit this property is not enumerable
86 // because otherwise some prototype manipulation in
87 // userland will fail
88 enumerable: false,
89 get: function get() {
90 return this._writableState && this._writableState.getBuffer();
91 }
92});
93Object.defineProperty(Duplex.prototype, 'writableLength', {
94 // making it explicit this property is not enumerable
95 // because otherwise some prototype manipulation in
96 // userland will fail
97 enumerable: false,
98 get: function get() {
99 return this._writableState.length;
100 }
101}); // the no-half-open enforcer
102
103function onend() {
104 // If the writable side ended, then we're ok.
105 if (this._writableState.ended) return; // no more data can be written.
106 // But allow more writes to happen in this tick.
107
108 process.nextTick(onEndNT, this);
109}
110
111function onEndNT(self) {
112 self.end();
113}
114
115Object.defineProperty(Duplex.prototype, 'destroyed', {
116 // making it explicit this property is not enumerable
117 // because otherwise some prototype manipulation in
118 // userland will fail
119 enumerable: false,
120 get: function get() {
121 if (this._readableState === undefined || this._writableState === undefined) {
122 return false;
123 }
124
125 return this._readableState.destroyed && this._writableState.destroyed;
126 },
127 set: function set(value) {
128 // we ignore the value if the stream
129 // has not been initialized yet
130 if (this._readableState === undefined || this._writableState === undefined) {
131 return;
132 } // backward compatibility, the user is explicitly
133 // managing destroyed
134
135
136 this._readableState.destroyed = value;
137 this._writableState.destroyed = value;
138 }
139});
\No newline at end of file