|
7 | 7 | module.exports = Writable;
|
8 | 8 | Writable.WritableState = WritableState;
|
9 | 9 |
|
| 10 | +const assert = require('assert'); |
10 | 11 | const util = require('util');
|
11 | 12 | const internalUtil = require('internal/util');
|
12 | 13 | const Stream = require('stream');
|
@@ -108,6 +109,31 @@ function WritableState(options, stream) {
|
108 | 109 |
|
109 | 110 | // True if the error was already emitted and should not be thrown again
|
110 | 111 | this.errorEmitted = false;
|
| 112 | + |
| 113 | + // count buffered requests |
| 114 | + this.bufferedRequestCount = 0; |
| 115 | + |
| 116 | + // the requests that needs to be called by uncork |
| 117 | + this.corkedCbs = null; |
| 118 | + |
| 119 | + // call all the corked requests |
| 120 | + this.afterCorkedWrite = function afterCorkedWrite(err) { |
| 121 | + var state = stream._writableState; |
| 122 | + var entry = state.corkedCbs; |
| 123 | + var cbs = entry.cbs; |
| 124 | + |
| 125 | + state.corkedCbs = entry.next; |
| 126 | + |
| 127 | + for (var i = 0; i < cbs.length; i++) { |
| 128 | + state.pendingcb--; |
| 129 | + cbs[i](err); |
| 130 | + } |
| 131 | + }; |
| 132 | +} |
| 133 | + |
| 134 | +function CorkedCbs(cbs) { |
| 135 | + this.cbs = cbs; |
| 136 | + this.next = null; |
111 | 137 | }
|
112 | 138 |
|
113 | 139 | WritableState.prototype.getBuffer = function writableStateGetBuffer() {
|
@@ -274,6 +300,7 @@ function writeOrBuffer(stream, state, chunk, encoding, cb) {
|
274 | 300 | } else {
|
275 | 301 | state.bufferedRequest = state.lastBufferedRequest;
|
276 | 302 | }
|
| 303 | + state.bufferedRequestCount++; |
277 | 304 | } else {
|
278 | 305 | doWrite(stream, state, false, len, chunk, encoding, cb);
|
279 | 306 | }
|
@@ -362,27 +389,37 @@ function onwriteDrain(stream, state) {
|
362 | 389 | function clearBuffer(stream, state) {
|
363 | 390 | state.bufferProcessing = true;
|
364 | 391 | var entry = state.bufferedRequest;
|
| 392 | + var bufferedRequestCount = state.bufferedRequestCount; |
| 393 | + |
| 394 | + state.bufferedRequestCount = 0; |
365 | 395 |
|
366 | 396 | if (stream._writev && entry && entry.next) {
|
367 | 397 | // Fast case, write everything using _writev()
|
368 |
| - var buffer = []; |
369 |
| - var cbs = []; |
| 398 | + var buffer = new Array(bufferedRequestCount); |
| 399 | + var cbs = new Array(bufferedRequestCount); |
| 400 | + var count = 0; |
| 401 | + |
370 | 402 | while (entry) {
|
371 |
| - cbs.push(entry.callback); |
372 |
| - buffer.push(entry); |
| 403 | + cbs[count] = entry.callback; |
| 404 | + buffer[count] = entry; |
| 405 | + count++; |
373 | 406 | entry = entry.next;
|
374 | 407 | }
|
375 | 408 |
|
376 | 409 | // count the one we are adding, as well.
|
377 |
| - // TODO(isaacs) clean this up |
378 | 410 | state.pendingcb++;
|
379 | 411 | state.lastBufferedRequest = null;
|
380 |
| - doWrite(stream, state, true, state.length, buffer, '', function(err) { |
381 |
| - for (var i = 0; i < cbs.length; i++) { |
382 |
| - state.pendingcb--; |
383 |
| - cbs[i](err); |
384 |
| - } |
385 |
| - }); |
| 412 | + |
| 413 | + if (state.corkedCbs) { |
| 414 | + // only two corkedCbs objects are supported |
| 415 | + assert(!state.corkedCbs.next); |
| 416 | + state.corkedCbs.next = new CorkedCbs(cbs); |
| 417 | + } else { |
| 418 | + state.corkedCbs = new CorkedCbs(cbs); |
| 419 | + } |
| 420 | + |
| 421 | + doWrite(stream, state, true, state.length, buffer, '', |
| 422 | + state.afterCorkedWrite); |
386 | 423 |
|
387 | 424 | // Clear buffer
|
388 | 425 | } else {
|
|
0 commit comments