@@ -467,30 +467,40 @@ function createBlobReaderStream(reader) { |
467 | 467 | // There really should only be one read at a time so using an |
468 | 468 | // array here is purely defensive. |
469 | 469 | this.pendingPulls = []; |
470 | | - // Register a wakeup callback that the C++ side can invoke |
| 470 | + // Lazily register a wakeup callback that the C++ side can invoke |
471 | 471 | // when new data is available after a STATUS_BLOCK. |
472 | | - reader.setWakeup(() => { |
| 472 | + this.wakeup = () => { |
473 | 473 | if (this.pendingPulls.length > 0) { |
474 | 474 | this.readNext(c); |
475 | 475 | } |
476 | | - }); |
| 476 | + }; |
477 | 477 | }, |
478 | 478 | pull(c) { |
479 | 479 | const { promise, resolve, reject } = PromiseWithResolvers(); |
| 480 | + if (this.pendingPulls.length === 0) { |
| 481 | + reader.setWakeup(this.wakeup); |
| 482 | + } |
480 | 483 | this.pendingPulls.push({ resolve, reject }); |
481 | 484 | this.readNext(c); |
482 | 485 | return promise; |
483 | 486 | }, |
| 487 | + clearWakeupIfIdle() { |
| 488 | + if (this.pendingPulls.length === 0) { |
| 489 | + reader.setWakeup(undefined); |
| 490 | + } |
| 491 | + }, |
484 | 492 | readNext(c) { |
485 | 493 | reader.pull((status, buffer) => { |
486 | 494 | // If pendingPulls is empty here, the stream had to have |
487 | 495 | // been canceled, and we don't really care about the result. |
488 | 496 | // We can simply exit. |
489 | 497 | if (this.pendingPulls.length === 0) { |
| 498 | + reader.setWakeup(undefined); |
490 | 499 | return; |
491 | 500 | } |
492 | 501 | if (status === 0) { |
493 | 502 | // EOS |
| 503 | + reader.setWakeup(undefined); |
494 | 504 | c.close(); |
495 | 505 | // This is to signal the end for byob readers |
496 | 506 | // see https://streams.spec.whatwg.org/#example-rbs-pull |
@@ -502,6 +512,7 @@ function createBlobReaderStream(reader) { |
502 | 512 | // The read could fail for many different reasons when reading |
503 | 513 | // from a non-memory resident blob part (e.g. file-backed blob). |
504 | 514 | // The error details the system error code. |
| 515 | + reader.setWakeup(undefined); |
505 | 516 | const error = |
506 | 517 | lazyDOMException('The blob could not be read', |
507 | 518 | 'NotReadableError'); |
@@ -511,7 +522,7 @@ function createBlobReaderStream(reader) { |
511 | 522 | return; |
512 | 523 | } else if (status === 2) { |
513 | 524 | // STATUS_BLOCK: No data available yet. The wakeup callback |
514 | | - // registered in start() will re-invoke readNext when data |
| 525 | + // registered in pull() will re-invoke readNext when data |
515 | 526 | // arrives. |
516 | 527 | return; |
517 | 528 | } |
@@ -531,6 +542,7 @@ function createBlobReaderStream(reader) { |
531 | 542 | if (this.pendingPulls.length !== 0) { |
532 | 543 | const pending = this.pendingPulls.shift(); |
533 | 544 | pending.resolve(); |
| 545 | + this.clearWakeupIfIdle(); |
534 | 546 | } |
535 | 547 | return; |
536 | 548 | } |
@@ -539,6 +551,7 @@ function createBlobReaderStream(reader) { |
539 | 551 | }); |
540 | 552 | }, |
541 | 553 | cancel(reason) { |
| 554 | + reader.setWakeup(undefined); |
542 | 555 | // Reject any currently pending pulls here. |
543 | 556 | for (const pending of this.pendingPulls) { |
544 | 557 | pending.reject(reason); |
|