* @param {Batch} batch
(batch)
| 499 | * @param {Batch} batch |
| 500 | */ |
| 501 | #merge(batch) { |
| 502 | for (const [source, value] of batch.current) { |
| 503 | if (!this.previous.has(source) && batch.previous.has(source)) { |
| 504 | this.previous.set(source, batch.previous.get(source)); |
| 505 | } |
| 506 | |
| 507 | this.current.set(source, value); |
| 508 | } |
| 509 | |
| 510 | for (const [effect, deferred] of batch.async_deriveds) { |
| 511 | const d = this.async_deriveds.get(effect); |
| 512 | if (d) deferred.promise.then(d.resolve).catch(d.reject); |
| 513 | } |
| 514 | |
| 515 | // Clear them or else those that are still pending might get rejected on discard (after merged-into batch is done). |
| 516 | // This can happen when batch Y merged into X and Y has a pending boundary and therefore still-pending async deriveds inside. |
| 517 | batch.async_deriveds.clear(); |
| 518 | |
| 519 | // Mark is not guaranteed not touch these, so we transfer them |
| 520 | this.transfer_effects(batch.#dirty_effects, batch.#maybe_dirty_effects); |
| 521 | |
| 522 | /** |
| 523 | * mark all effects that depend on `batch.current`, except the |
| 524 | * async effects that we just resolved (TODO unless they depend |
| 525 | * on values in this batch that are NOT in the later batch?). |
| 526 | * Through this we also will populate the correct #skipped_branches, |
| 527 | * oncommit callbacks etc, so we don't need to merge them separately. |
| 528 | * @param {Value} value |
| 529 | */ |
| 530 | const mark = (value) => { |
| 531 | var reactions = value.reactions; |
| 532 | if (reactions === null) return; |
| 533 | |
| 534 | for (const reaction of reactions) { |
| 535 | var flags = reaction.f; |
| 536 | |
| 537 | if ((flags & DERIVED) !== 0) { |
| 538 | mark(/** @type {Derived} */ (reaction)); |
| 539 | } else { |
| 540 | var effect = /** @type {Effect} */ (reaction); |
| 541 | |
| 542 | if (flags & (ASYNC | BLOCK_EFFECT) && !this.async_deriveds.has(effect)) { |
| 543 | this.#maybe_dirty_effects.delete(effect); |
| 544 | set_signal_status(effect, DIRTY); |
| 545 | this.schedule(effect); |
| 546 | } |
| 547 | } |
| 548 | } |
| 549 | }; |
| 550 | |
| 551 | for (const source of this.current.keys()) { |
| 552 | mark(source); |
| 553 | } |
| 554 | |
| 555 | this.oncommit(() => batch.discard()); |
| 556 | batch.#unlink(); |
| 557 | |
| 558 | current_batch = this; |