Skip to content

Commit 3ce8b9b

Browse files
authored
Write after end fix (#97)
* add failing test * fix write-after-end edgecase
1 parent 15d19e8 commit 3ce8b9b

File tree

2 files changed

+28
-3
lines changed

2 files changed

+28
-3
lines changed

index.js

+5-3
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ const WRITE_CORKED = 0b10000000000 << 18
7171

7272
const WRITE_NOT_ACTIVE = MAX ^ (WRITE_ACTIVE | WRITE_WRITING)
7373
const WRITE_NON_PRIMARY = MAX ^ WRITE_PRIMARY
74-
const WRITE_NOT_FINISHING = MAX ^ WRITE_FINISHING
74+
const WRITE_NOT_FINISHING = MAX ^ (WRITE_ACTIVE | WRITE_FINISHING)
7575
const WRITE_DRAINED = MAX ^ WRITE_UNDRAINED
7676
const WRITE_NOT_QUEUED = MAX ^ WRITE_QUEUED
7777
const WRITE_NOT_NEXT_TICK = MAX ^ WRITE_NEXT_TICK
@@ -110,6 +110,7 @@ const WRITE_ACTIVE_AND_WRITING = WRITE_ACTIVE | WRITE_WRITING
110110
const WRITE_FINISHING_STATUS = OPEN_STATUS | WRITE_FINISHING | WRITE_QUEUED_AND_ACTIVE | WRITE_DONE
111111
const WRITE_BACKPRESSURE_STATUS = WRITE_UNDRAINED | DESTROY_STATUS | WRITE_FINISHING | WRITE_DONE
112112
const WRITE_UPDATE_SYNC_STATUS = WRITE_UPDATING | OPEN_STATUS | WRITE_NEXT_TICK | WRITE_PRIMARY
113+
const WRITE_DROP_DATA = WRITE_FINISHING | WRITE_DONE | DESTROY_STATUS
113114

114115
const asyncIterator = Symbol.asyncIterator || Symbol('asyncIterator')
115116

@@ -133,6 +134,7 @@ class WritableState {
133134
}
134135

135136
push (data) {
137+
if ((this.stream._duplexState & WRITE_DROP_DATA) !== 0) return false
136138
if (this.map !== null) data = this.map(data)
137139

138140
this.buffered += this.byteLength(data)
@@ -197,7 +199,7 @@ class WritableState {
197199
const stream = this.stream
198200

199201
if ((stream._duplexState & WRITE_FINISHING_STATUS) === WRITE_FINISHING) {
200-
stream._duplexState = (stream._duplexState | WRITE_ACTIVE) & WRITE_NOT_FINISHING
202+
stream._duplexState = stream._duplexState | WRITE_ACTIVE
201203
stream._final(afterFinal.bind(this))
202204
return
203205
}
@@ -489,7 +491,7 @@ function afterFinal (err) {
489491
stream._duplexState |= DESTROYING
490492
}
491493

492-
stream._duplexState &= WRITE_NOT_ACTIVE
494+
stream._duplexState &= WRITE_NOT_FINISHING
493495

494496
// no need to wait the extra tick here, so we short circuit that
495497
if ((stream._duplexState & WRITE_UPDATING) === 0) this.update()

test/duplex.js

+23
Original file line numberDiff line numberDiff line change
@@ -60,3 +60,26 @@ test('wait for readable', function (t) {
6060
t.is(d.read(), 'ok')
6161
})
6262
})
63+
64+
test('write during end', function (t) {
65+
t.plan(3)
66+
67+
const expected = ['a', 'b']
68+
69+
const w = new Duplex({
70+
write (data, cb) {
71+
t.is(data, expected.shift())
72+
cb(null)
73+
},
74+
final (cb) {
75+
w.write('bad')
76+
cb(null)
77+
}
78+
})
79+
80+
w.write('a')
81+
w.write('b')
82+
w.end()
83+
w.on('finish', () => w.push(null))
84+
w.on('close', () => t.pass('closed'))
85+
})

0 commit comments

Comments
 (0)