|
|
@ -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();
|
|
|
|