• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  ObjectKeys,
32  ObjectSetPrototypeOf,
33} = primordials;
34
35module.exports = Duplex;
36
37const Readable = require('_stream_readable');
38const Writable = require('_stream_writable');
39
40ObjectSetPrototypeOf(Duplex.prototype, Readable.prototype);
41ObjectSetPrototypeOf(Duplex, Readable);
42
43{
44  // Allow the keys array to be GC'ed.
45  for (const method of ObjectKeys(Writable.prototype)) {
46    if (!Duplex.prototype[method])
47      Duplex.prototype[method] = Writable.prototype[method];
48  }
49}
50
51function Duplex(options) {
52  if (!(this instanceof Duplex))
53    return new Duplex(options);
54
55  Readable.call(this, options);
56  Writable.call(this, options);
57  this.allowHalfOpen = true;
58
59  if (options) {
60    if (options.readable === false)
61      this.readable = false;
62
63    if (options.writable === false)
64      this.writable = false;
65
66    if (options.allowHalfOpen === false) {
67      this.allowHalfOpen = false;
68      this.once('end', onend);
69    }
70  }
71}
72
73ObjectDefineProperties(Duplex.prototype, {
74
75  destroyed: {
76    get() {
77      if (this._readableState === undefined ||
78        this._writableState === undefined) {
79        return false;
80      }
81      return this._readableState.destroyed && this._writableState.destroyed;
82    },
83    set(value) {
84      // Backward compatibility, the user is explicitly
85      // managing destroyed
86      if (this._readableState && this._writableState) {
87        this._readableState.destroyed = value;
88        this._writableState.destroyed = value;
89      }
90    }
91  },
92
93  writableHighWaterMark: {
94    get() {
95      return this._writableState && this._writableState.highWaterMark;
96    }
97  },
98
99  writableBuffer: {
100    get() {
101      return this._writableState && this._writableState.getBuffer();
102    }
103  },
104
105  writableLength: {
106    get() {
107      return this._writableState && this._writableState.length;
108    }
109  },
110
111  writableFinished: {
112    get() {
113      return this._writableState ? this._writableState.finished : false;
114    }
115  },
116
117  writableCorked: {
118    get() {
119      return this._writableState ? this._writableState.corked : 0;
120    }
121  },
122
123  writableEnded: {
124    get() {
125      return this._writableState ? this._writableState.ending : false;
126    }
127  }
128});
129
130// The no-half-open enforcer
131function onend() {
132  // If the writable side ended, then we're ok.
133  if (this._writableState.ended)
134    return;
135
136  // No more data can be written.
137  // But allow more writes to happen in this tick.
138  process.nextTick(onEndNT, this);
139}
140
141function onEndNT(self) {
142  self.end();
143}
144