Skip to content

streams: non-writable Duplex is writable (more annoyance than bug) #34374

Description

@jasnell

@mcollina @ronag @nodejs/streams

const { Duplex } = require('stream');

const d = new Duplex({
  writable: false,
  write(chunk, encoding, cb) {
    console.log(chunk.toString());
    cb();
  }
});

console.log(d.writable);   // false! as expected...

d.write('darn it');  // prints, 'darn it' and returns true

This isn't a bug since it's been like this forever but the behavior is really counter intuitive, especially since after calling d.end() and then doing a d.write() we get a proper write after end error. It makes implementing a custom Duplex (e.g. QuicStream) more difficult because of the additional checks that need to be made to ensure that even tho the Duplex isn't writable no-one is writing to it.

Not sure what the fix is immediately but wanted to discuss it first.

The ideal behavior, I would think, is an error similar to write after end if write() is called on a non-writable Duplex.

Activity

  1. added
    streamIssues and PRs related to Node.js streams.
    discussIssues opened for discussion and feedback.
    on Jul 15, 2020
  2. jasnell commented on Jul 15, 2020

    @jasnell
    MemberAuthor

    Also, just to be thorough, the same issue exists with readable: false and the readable side. Specifically:

    const d = new stream.Duplex({
      readable: false,
      read() {
        this.push(Buffer.from('abc'));
        this.push(null);
      }
    });
    
    console.log(d.readable);  // false
    
    d.setEncoding('utf8');
    d.on('data', console.log);  // prints abc
  3. ronag commented on Jul 15, 2020

    @ronag
    Member

    What would you like to happen? Error if write/push to a non writable/readable stream?

    readable/writable false should be as if end()/push(null) has been called in the constructor but without emitting the associated events?

  4. preyunk commented on Jul 15, 2020

    @preyunk
    Contributor

    @ronag @jasnell
    Correct me if I am wrong here, according to the readable.readable and writable.writable docs they must be used to check if it is safe to read/write on the stream. That's why setting writable and readable explicitly doesn't seem to work, maybe that's the reason we don't get the option to set writable and readable property as options while creating a new Duplex.
    However if I am wrong, the ideal behavior that is throwing an error as proposed by @jasnell looks good.

  5. ronag commented on Jul 15, 2020

    @ronag
    Member

    Correct me if I am wrong here, according to the readable.readable and writable.writable docs they must be used to check if it is safe to read/write on the stream

    No, they don't need to be checked. Calling it "safe" is maybe a bit misleading, but the following sentence does explain what it means in the context.

    That's why setting writable and readable explicitly doesn't seem to work

    It does "work". Depends on what you mean by "works". Though that usage is deprecated.

    maybe that's the reason we don't get the option to set writable and readable property as options while creating a new Duplex.

    That option actually does exist and should be used. It's just not documented, which we should fix.

  6. ronag commented on Jul 15, 2020

    @ronag
    Member

    @jasnell I'll investigate what we can do to improve this.

  7. self-assigned this
    on Jul 15, 2020
  8. preyunk commented on Jul 15, 2020

    @preyunk
    Contributor

    It does "work". Depends on what you mean by "works". Though that usage is deprecated.

    By "doesn't work" I meant that we are allowed to read/write on a non readable/writable Duplex

    That option actually does exist and should be used. It's just not documented, which we should fix.

    Should I open another issue regarding this? Also are there any more options other than writable and readable that must be included in the docs?

  9. ronag commented on Jul 15, 2020

    @ronag
    Member

    Should I open another issue regarding this?

    Sure!

    Also are there any more options other than writable and readable that must be included in the docs?

    I don't think so.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

discussIssues opened for discussion and feedback.streamIssues and PRs related to Node.js streams.

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions