|
|
@ -349,7 +349,21 @@ function execute_signal_fn(signal) {
|
|
|
|
|
|
|
|
|
|
|
|
if (current_dependencies !== null) {
|
|
|
|
if (current_dependencies !== null) {
|
|
|
|
let i;
|
|
|
|
let i;
|
|
|
|
remove_consumer(signal, current_dependencies_index, false);
|
|
|
|
if (dependencies !== null) {
|
|
|
|
|
|
|
|
const dep_length = dependencies.length;
|
|
|
|
|
|
|
|
// If we have more than 16 elements in the array then use a Set for faster performance
|
|
|
|
|
|
|
|
// TODO: evaluate if we should always just use a Set or not here?
|
|
|
|
|
|
|
|
const current_dependencies_set = dep_length > 16 ? new Set(current_dependencies) : null;
|
|
|
|
|
|
|
|
for (i = current_dependencies_index; i < dep_length; i++) {
|
|
|
|
|
|
|
|
const dependency = dependencies[i];
|
|
|
|
|
|
|
|
if (
|
|
|
|
|
|
|
|
(current_dependencies_set !== null && !current_dependencies_set.has(dependency)) ||
|
|
|
|
|
|
|
|
!current_dependencies.includes(dependency)
|
|
|
|
|
|
|
|
) {
|
|
|
|
|
|
|
|
remove_consumer(signal, dependency, false);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (dependencies !== null && current_dependencies_index > 0) {
|
|
|
|
if (dependencies !== null && current_dependencies_index > 0) {
|
|
|
|
dependencies.length = current_dependencies_index + current_dependencies.length;
|
|
|
|
dependencies.length = current_dependencies_index + current_dependencies.length;
|
|
|
@ -365,16 +379,17 @@ function execute_signal_fn(signal) {
|
|
|
|
if (!current_skip_consumer) {
|
|
|
|
if (!current_skip_consumer) {
|
|
|
|
for (i = current_dependencies_index; i < dependencies.length; i++) {
|
|
|
|
for (i = current_dependencies_index; i < dependencies.length; i++) {
|
|
|
|
const dependency = dependencies[i];
|
|
|
|
const dependency = dependencies[i];
|
|
|
|
|
|
|
|
const consumers = dependency.c;
|
|
|
|
|
|
|
|
|
|
|
|
if (dependency.c === null) {
|
|
|
|
if (consumers === null) {
|
|
|
|
dependency.c = [signal];
|
|
|
|
dependency.c = [signal];
|
|
|
|
} else {
|
|
|
|
} else if (consumers[consumers.length - 1] !== signal) {
|
|
|
|
dependency.c.push(signal);
|
|
|
|
consumers.push(signal);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (dependencies !== null && current_dependencies_index < dependencies.length) {
|
|
|
|
} else if (dependencies !== null && current_dependencies_index < dependencies.length) {
|
|
|
|
remove_consumer(signal, current_dependencies_index, false);
|
|
|
|
remove_consumers(signal, current_dependencies_index, false);
|
|
|
|
dependencies.length = current_dependencies_index;
|
|
|
|
dependencies.length = current_dependencies_index;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
return res;
|
|
|
@ -390,6 +405,40 @@ function execute_signal_fn(signal) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* @template V
|
|
|
|
|
|
|
|
* @param {import('./types.js').ComputationSignal<V>} signal
|
|
|
|
|
|
|
|
* @param {import('./types.js').Signal<V>} dependency
|
|
|
|
|
|
|
|
* @param {boolean} remove_unowned
|
|
|
|
|
|
|
|
* @returns {void}
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
function remove_consumer(signal, dependency, remove_unowned) {
|
|
|
|
|
|
|
|
const consumers = dependency.c;
|
|
|
|
|
|
|
|
let consumers_length = 0;
|
|
|
|
|
|
|
|
if (consumers !== null) {
|
|
|
|
|
|
|
|
consumers_length = consumers.length - 1;
|
|
|
|
|
|
|
|
const index = consumers.indexOf(signal);
|
|
|
|
|
|
|
|
if (index !== -1) {
|
|
|
|
|
|
|
|
if (consumers_length === 0) {
|
|
|
|
|
|
|
|
dependency.c = null;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
// Swap with last element and then remove.
|
|
|
|
|
|
|
|
consumers[index] = consumers[consumers_length];
|
|
|
|
|
|
|
|
consumers.pop();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (remove_unowned && consumers_length === 0 && (dependency.f & UNOWNED) !== 0) {
|
|
|
|
|
|
|
|
// If the signal is unowned then we need to make sure to change it to dirty.
|
|
|
|
|
|
|
|
set_signal_status(dependency, DIRTY);
|
|
|
|
|
|
|
|
remove_consumers(
|
|
|
|
|
|
|
|
/** @type {import('./types.js').ComputationSignal<V>} **/ (dependency),
|
|
|
|
|
|
|
|
0,
|
|
|
|
|
|
|
|
true
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
* @template V
|
|
|
|
* @template V
|
|
|
|
* @param {import('./types.js').ComputationSignal<V>} signal
|
|
|
|
* @param {import('./types.js').ComputationSignal<V>} signal
|
|
|
@ -397,36 +446,13 @@ function execute_signal_fn(signal) {
|
|
|
|
* @param {boolean} remove_unowned
|
|
|
|
* @param {boolean} remove_unowned
|
|
|
|
* @returns {void}
|
|
|
|
* @returns {void}
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
function remove_consumer(signal, start_index, remove_unowned) {
|
|
|
|
function remove_consumers(signal, start_index, remove_unowned) {
|
|
|
|
const dependencies = signal.d;
|
|
|
|
const dependencies = signal.d;
|
|
|
|
if (dependencies !== null) {
|
|
|
|
if (dependencies !== null) {
|
|
|
|
let i;
|
|
|
|
let i;
|
|
|
|
for (i = start_index; i < dependencies.length; i++) {
|
|
|
|
for (i = start_index; i < dependencies.length; i++) {
|
|
|
|
const dependency = dependencies[i];
|
|
|
|
const dependency = dependencies[i];
|
|
|
|
const consumers = dependency.c;
|
|
|
|
remove_consumer(signal, dependency, remove_unowned);
|
|
|
|
let consumers_length = 0;
|
|
|
|
|
|
|
|
if (consumers !== null) {
|
|
|
|
|
|
|
|
consumers_length = consumers.length - 1;
|
|
|
|
|
|
|
|
const index = consumers.indexOf(signal);
|
|
|
|
|
|
|
|
if (index !== -1) {
|
|
|
|
|
|
|
|
if (consumers_length === 0) {
|
|
|
|
|
|
|
|
dependency.c = null;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
// Swap with last element and then remove.
|
|
|
|
|
|
|
|
consumers[index] = consumers[consumers_length];
|
|
|
|
|
|
|
|
consumers.pop();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (remove_unowned && consumers_length === 0 && (dependency.f & UNOWNED) !== 0) {
|
|
|
|
|
|
|
|
// If the signal is unowned then we need to make sure to change it to dirty.
|
|
|
|
|
|
|
|
set_signal_status(dependency, DIRTY);
|
|
|
|
|
|
|
|
remove_consumer(
|
|
|
|
|
|
|
|
/** @type {import('./types.js').ComputationSignal<V>} **/ (dependency),
|
|
|
|
|
|
|
|
0,
|
|
|
|
|
|
|
|
true
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -446,7 +472,7 @@ function destroy_references(signal) {
|
|
|
|
if ((reference.f & IS_EFFECT) !== 0) {
|
|
|
|
if ((reference.f & IS_EFFECT) !== 0) {
|
|
|
|
destroy_signal(reference);
|
|
|
|
destroy_signal(reference);
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
remove_consumer(reference, 0, true);
|
|
|
|
remove_consumers(reference, 0, true);
|
|
|
|
reference.d = null;
|
|
|
|
reference.d = null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -841,10 +867,16 @@ export function get(signal) {
|
|
|
|
!(unowned && current_effect !== null)
|
|
|
|
!(unowned && current_effect !== null)
|
|
|
|
) {
|
|
|
|
) {
|
|
|
|
current_dependencies_index++;
|
|
|
|
current_dependencies_index++;
|
|
|
|
} else if (current_dependencies === null) {
|
|
|
|
} else if (
|
|
|
|
current_dependencies = [signal];
|
|
|
|
dependencies === null ||
|
|
|
|
} else if (signal !== current_dependencies[current_dependencies.length - 1]) {
|
|
|
|
current_dependencies_index === 0 ||
|
|
|
|
current_dependencies.push(signal);
|
|
|
|
dependencies[current_dependencies_index - 1] !== signal
|
|
|
|
|
|
|
|
) {
|
|
|
|
|
|
|
|
if (current_dependencies === null) {
|
|
|
|
|
|
|
|
current_dependencies = [signal];
|
|
|
|
|
|
|
|
} else if (signal !== current_dependencies[current_dependencies.length - 1]) {
|
|
|
|
|
|
|
|
current_dependencies.push(signal);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (
|
|
|
|
if (
|
|
|
|
current_untracked_writes !== null &&
|
|
|
|
current_untracked_writes !== null &&
|
|
|
@ -1098,7 +1130,7 @@ export function destroy_signal(signal) {
|
|
|
|
const destroy = signal.y;
|
|
|
|
const destroy = signal.y;
|
|
|
|
const flags = signal.f;
|
|
|
|
const flags = signal.f;
|
|
|
|
destroy_references(signal);
|
|
|
|
destroy_references(signal);
|
|
|
|
remove_consumer(signal, 0, true);
|
|
|
|
remove_consumers(signal, 0, true);
|
|
|
|
signal.i =
|
|
|
|
signal.i =
|
|
|
|
signal.r =
|
|
|
|
signal.r =
|
|
|
|
signal.y =
|
|
|
|
signal.y =
|
|
|
|