• 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  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