boundary-batch-nullpointer-fix
Rich Harris 3 weeks ago
parent 5d6b755e68
commit bde51cde89

@ -181,12 +181,12 @@ export class Batch {
var current_values = null; var current_values = null;
/** /**
* A batch is superseeded if all of its sources are also in the current batch. * A batch is superseded if all of its sources are also in the current batch.
* If the current batch commits, we don't need the old batch anymore. * If the current batch commits, we don't need the old batch anymore.
* This also prevents memory leaks since the old batch will never be committed. * This also prevents memory leaks since the old batch will never be committed.
* @type {Batch[]} * @type {Batch[]}
*/ */
var superseeded_batches = []; var superseded_batches = [];
// if there are multiple batches, we are 'time travelling' — // if there are multiple batches, we are 'time travelling' —
// we need to undo the changes belonging to any batch // we need to undo the changes belonging to any batch
@ -208,17 +208,17 @@ export class Batch {
continue; continue;
} }
let superseeded = is_prior_batch; let superseded = is_prior_batch;
for (const [source, previous] of batch.#previous) { for (const [source, previous] of batch.#previous) {
if (!current_values.has(source)) { if (!current_values.has(source)) {
superseeded = false; superseded = false;
current_values.set(source, { v: source.v, wv: source.wv }); current_values.set(source, { v: source.v, wv: source.wv });
source.v = previous; source.v = previous;
} }
} }
if (superseeded) superseeded_batches.push(batch); if (superseded) superseded_batches.push(batch);
} }
} }
@ -229,14 +229,14 @@ export class Batch {
// if we didn't start any new async work, and no async work // if we didn't start any new async work, and no async work
// is outstanding from a previous flush, commit // is outstanding from a previous flush, commit
if (this.#async_effects.length === 0 && this.#pending === 0) { if (this.#async_effects.length === 0 && this.#pending === 0) {
if (superseeded_batches.length > 0) { if (superseded_batches.length > 0) {
const own = [...this.#callbacks.keys()].map((c) => c()); const own = [...this.#callbacks.keys()].map((c) => c());
// A superseeded batch could have callbacks for e.g. destroying if blocks // A superseded batch could have callbacks for e.g. destroying if blocks
// that are not part of the current batch because it already happened in the prior one, // that are not part of the current batch because it already happened in the prior one,
// and the corresponding block effect therefore returning early because nothing was changed from its // and the corresponding block effect therefore returning early because nothing was changed from its
// point of view, therefore not adding a callback to the current batch, so we gotta call them here. // point of view, therefore not adding a callback to the current batch, so we gotta call them here.
// We do it from newest to oldest to ensure the correct callback is applied. // We do it from newest to oldest to ensure the correct callback is applied.
for (const batch of superseeded_batches.reverse()) { for (const batch of superseded_batches.reverse()) {
for (const [effect, cb] of batch.#callbacks) { for (const [effect, cb] of batch.#callbacks) {
if (!own.includes(effect())) { if (!own.includes(effect())) {
cb(); cb();

Loading…
Cancel
Save