|
1 | 1 | 'use strict'; |
2 | 2 |
|
3 | 3 | const { |
4 | | - ArrayPrototypeForEach, |
5 | | - ArrayPrototypeMap, |
6 | | - ArrayPrototypePush, |
| 4 | + Array, |
7 | 5 | FunctionPrototypeBind, |
8 | 6 | FunctionPrototypeCall, |
9 | 7 | ObjectAssign, |
@@ -77,7 +75,7 @@ const kOnMessage = Symbol('kOnMessage'); |
77 | 75 | const kOnMessageError = Symbol('kOnMessageError'); |
78 | 76 | const kPort = Symbol('kPort'); |
79 | 77 | const kWaitingStreams = Symbol('kWaitingStreams'); |
80 | | -const kWritableCallbacks = Symbol('kWritableCallbacks'); |
| 78 | +const kWritableCallback = Symbol('kWritableCallback'); |
81 | 79 | const kStartedReading = Symbol('kStartedReading'); |
82 | 80 | const kStdioWantsMoreDataCallback = Symbol('kStdioWantsMoreDataCallback'); |
83 | 81 | const kCurrentlyReceivingPorts = |
@@ -282,20 +280,29 @@ class WritableWorkerStdio extends Writable { |
282 | 280 | super({ decodeStrings: false }); |
283 | 281 | this[kPort] = port; |
284 | 282 | this[kName] = name; |
285 | | - this[kWritableCallbacks] = []; |
| 283 | + this[kWritableCallback] = null; |
286 | 284 | } |
287 | 285 |
|
288 | 286 | _writev(chunks, cb) { |
| 287 | + const toSend = new Array(chunks.length); |
| 288 | + |
| 289 | + // We avoid .map() because it's a hot path |
| 290 | + for (let i = 0; i < chunks.length; i++) { |
| 291 | + const { chunk, encoding } = chunks[i]; |
| 292 | + toSend[i] = { chunk, encoding }; |
| 293 | + } |
| 294 | + |
289 | 295 | this[kPort].postMessage({ |
290 | 296 | type: messageTypes.STDIO_PAYLOAD, |
291 | 297 | stream: this[kName], |
292 | | - chunks: ArrayPrototypeMap(chunks, |
293 | | - ({ chunk, encoding }) => ({ chunk, encoding })), |
| 298 | + chunks: toSend, |
294 | 299 | }); |
295 | 300 | if (process._exiting) { |
296 | 301 | cb(); |
297 | 302 | } else { |
298 | | - ArrayPrototypePush(this[kWritableCallbacks], cb); |
| 303 | + // Only one writev happens at any given time, |
| 304 | + // so we can safely overwrite the callback. |
| 305 | + this[kWritableCallback] = cb; |
299 | 306 | if (this[kPort][kWaitingStreams]++ === 0) |
300 | 307 | this[kPort].ref(); |
301 | 308 | } |
@@ -311,11 +318,13 @@ class WritableWorkerStdio extends Writable { |
311 | 318 | } |
312 | 319 |
|
313 | 320 | [kStdioWantsMoreDataCallback]() { |
314 | | - const cbs = this[kWritableCallbacks]; |
315 | | - this[kWritableCallbacks] = []; |
316 | | - ArrayPrototypeForEach(cbs, (cb) => cb()); |
317 | | - if ((this[kPort][kWaitingStreams] -= cbs.length) === 0) |
318 | | - this[kPort].unref(); |
| 321 | + const cb = this[kWritableCallback]; |
| 322 | + if (cb) { |
| 323 | + this[kWritableCallback] = null; |
| 324 | + cb(); |
| 325 | + if (--this[kPort][kWaitingStreams] === 0) |
| 326 | + this[kPort].unref(); |
| 327 | + } |
319 | 328 | } |
320 | 329 | } |
321 | 330 |
|
|