|
|
|
@ -140,12 +140,12 @@ function default_equals(a, b) {
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
function create_source_signal(flags, value) {
|
|
|
|
function create_source_signal(flags, value) {
|
|
|
|
return {
|
|
|
|
return {
|
|
|
|
consumers: null,
|
|
|
|
c: null,
|
|
|
|
// We can remove this if we get rid of beforeUpdate/afterUpdate
|
|
|
|
// We can remove this if we get rid of beforeUpdate/afterUpdate
|
|
|
|
context: null,
|
|
|
|
x: null,
|
|
|
|
equals: null,
|
|
|
|
e: null,
|
|
|
|
flags,
|
|
|
|
f: flags,
|
|
|
|
value
|
|
|
|
v: value
|
|
|
|
};
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -158,16 +158,16 @@ function create_source_signal(flags, value) {
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
function create_computation_signal(flags, value, block) {
|
|
|
|
function create_computation_signal(flags, value, block) {
|
|
|
|
return {
|
|
|
|
return {
|
|
|
|
block,
|
|
|
|
b: block,
|
|
|
|
consumers: null,
|
|
|
|
c: null,
|
|
|
|
context: null,
|
|
|
|
x: null,
|
|
|
|
dependencies: null,
|
|
|
|
d: null,
|
|
|
|
destroy: null,
|
|
|
|
y: null,
|
|
|
|
equals: null,
|
|
|
|
e: null,
|
|
|
|
flags,
|
|
|
|
f: flags,
|
|
|
|
init: null,
|
|
|
|
i: null,
|
|
|
|
references: null,
|
|
|
|
r: null,
|
|
|
|
value
|
|
|
|
v: value
|
|
|
|
};
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -177,9 +177,9 @@ function create_computation_signal(flags, value, block) {
|
|
|
|
* @returns {void}
|
|
|
|
* @returns {void}
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
function push_reference(target_signal, ref_signal) {
|
|
|
|
function push_reference(target_signal, ref_signal) {
|
|
|
|
const references = target_signal.references;
|
|
|
|
const references = target_signal.r;
|
|
|
|
if (references === null) {
|
|
|
|
if (references === null) {
|
|
|
|
target_signal.references = [ref_signal];
|
|
|
|
target_signal.r = [ref_signal];
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
references.push(ref_signal);
|
|
|
|
references.push(ref_signal);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -191,32 +191,31 @@ function push_reference(target_signal, ref_signal) {
|
|
|
|
* @returns {boolean}
|
|
|
|
* @returns {boolean}
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
function is_signal_dirty(signal) {
|
|
|
|
function is_signal_dirty(signal) {
|
|
|
|
const flags = signal.flags;
|
|
|
|
const flags = signal.f;
|
|
|
|
if ((flags & DIRTY) !== 0 || signal.value === UNINITIALIZED) {
|
|
|
|
if ((flags & DIRTY) !== 0 || signal.v === UNINITIALIZED) {
|
|
|
|
return true;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ((flags & MAYBE_DIRTY) !== 0) {
|
|
|
|
if ((flags & MAYBE_DIRTY) !== 0) {
|
|
|
|
const dependencies = /** @type {import('./types.js').ComputationSignal<V>} **/ (signal)
|
|
|
|
const dependencies = /** @type {import('./types.js').ComputationSignal<V>} **/ (signal).d;
|
|
|
|
.dependencies;
|
|
|
|
|
|
|
|
if (dependencies !== null) {
|
|
|
|
if (dependencies !== null) {
|
|
|
|
const length = dependencies.length;
|
|
|
|
const length = dependencies.length;
|
|
|
|
let i;
|
|
|
|
let i;
|
|
|
|
for (i = 0; i < length; i++) {
|
|
|
|
for (i = 0; i < length; i++) {
|
|
|
|
const dependency = dependencies[i];
|
|
|
|
const dependency = dependencies[i];
|
|
|
|
|
|
|
|
|
|
|
|
if ((dependency.flags & MAYBE_DIRTY) !== 0 && !is_signal_dirty(dependency)) {
|
|
|
|
if ((dependency.f & MAYBE_DIRTY) !== 0 && !is_signal_dirty(dependency)) {
|
|
|
|
set_signal_status(dependency, CLEAN);
|
|
|
|
set_signal_status(dependency, CLEAN);
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// The flags can be marked as dirty from the above is_signal_dirty call.
|
|
|
|
// The flags can be marked as dirty from the above is_signal_dirty call.
|
|
|
|
if ((dependency.flags & DIRTY) !== 0) {
|
|
|
|
if ((dependency.f & DIRTY) !== 0) {
|
|
|
|
if ((dependency.flags & DERIVED) !== 0) {
|
|
|
|
if ((dependency.f & DERIVED) !== 0) {
|
|
|
|
update_derived(
|
|
|
|
update_derived(
|
|
|
|
/** @type {import('./types.js').ComputationSignal<V>} **/ (dependency),
|
|
|
|
/** @type {import('./types.js').ComputationSignal<V>} **/ (dependency),
|
|
|
|
true
|
|
|
|
true
|
|
|
|
);
|
|
|
|
);
|
|
|
|
// Might have been mutated from above get.
|
|
|
|
// Might have been mutated from above get.
|
|
|
|
if ((signal.flags & DIRTY) !== 0) {
|
|
|
|
if ((signal.f & DIRTY) !== 0) {
|
|
|
|
return true;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
@ -235,21 +234,21 @@ function is_signal_dirty(signal) {
|
|
|
|
* @returns {V}
|
|
|
|
* @returns {V}
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
function execute_signal_fn(signal) {
|
|
|
|
function execute_signal_fn(signal) {
|
|
|
|
const init = signal.init;
|
|
|
|
const init = signal.i;
|
|
|
|
const previous_dependencies = current_dependencies;
|
|
|
|
const previous_dependencies = current_dependencies;
|
|
|
|
const previous_dependencies_index = current_dependencies_index;
|
|
|
|
const previous_dependencies_index = current_dependencies_index;
|
|
|
|
const previous_consumer = current_consumer;
|
|
|
|
const previous_consumer = current_consumer;
|
|
|
|
const previous_block = current_block;
|
|
|
|
const previous_block = current_block;
|
|
|
|
const previous_component_context = current_component_context;
|
|
|
|
const previous_component_context = current_component_context;
|
|
|
|
const previous_skip_consumer = current_skip_consumer;
|
|
|
|
const previous_skip_consumer = current_skip_consumer;
|
|
|
|
const is_render_effect = (signal.flags & RENDER_EFFECT) !== 0;
|
|
|
|
const is_render_effect = (signal.f & RENDER_EFFECT) !== 0;
|
|
|
|
const previous_untracking = current_untracking;
|
|
|
|
const previous_untracking = current_untracking;
|
|
|
|
current_dependencies = /** @type {null | import('./types.js').Signal[]} */ (null);
|
|
|
|
current_dependencies = /** @type {null | import('./types.js').Signal[]} */ (null);
|
|
|
|
current_dependencies_index = 0;
|
|
|
|
current_dependencies_index = 0;
|
|
|
|
current_consumer = signal;
|
|
|
|
current_consumer = signal;
|
|
|
|
current_block = signal.block;
|
|
|
|
current_block = signal.b;
|
|
|
|
current_component_context = signal.context;
|
|
|
|
current_component_context = signal.x;
|
|
|
|
current_skip_consumer = current_effect === null && (signal.flags & UNOWNED) !== 0;
|
|
|
|
current_skip_consumer = current_effect === null && (signal.f & UNOWNED) !== 0;
|
|
|
|
current_untracking = false;
|
|
|
|
current_untracking = false;
|
|
|
|
|
|
|
|
|
|
|
|
// Render effects are invoked when the UI is about to be updated - run beforeUpdate at that point
|
|
|
|
// Render effects are invoked when the UI is about to be updated - run beforeUpdate at that point
|
|
|
|
@ -261,12 +260,12 @@ function execute_signal_fn(signal) {
|
|
|
|
let res;
|
|
|
|
let res;
|
|
|
|
if (is_render_effect) {
|
|
|
|
if (is_render_effect) {
|
|
|
|
res = /** @type {(block: import('./types.js').Block) => V} */ (init)(
|
|
|
|
res = /** @type {(block: import('./types.js').Block) => V} */ (init)(
|
|
|
|
/** @type {import('./types.js').Block} */ (signal.block)
|
|
|
|
/** @type {import('./types.js').Block} */ (signal.b)
|
|
|
|
);
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
res = /** @type {() => V} */ (init)();
|
|
|
|
res = /** @type {() => V} */ (init)();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
let dependencies = /** @type {import('./types.js').Signal<unknown>[]} **/ (signal.dependencies);
|
|
|
|
let dependencies = /** @type {import('./types.js').Signal<unknown>[]} **/ (signal.d);
|
|
|
|
|
|
|
|
|
|
|
|
if (current_dependencies !== null) {
|
|
|
|
if (current_dependencies !== null) {
|
|
|
|
let i;
|
|
|
|
let i;
|
|
|
|
@ -278,7 +277,7 @@ function execute_signal_fn(signal) {
|
|
|
|
dependencies[current_dependencies_index + i] = current_dependencies[i];
|
|
|
|
dependencies[current_dependencies_index + i] = current_dependencies[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
signal.dependencies = /** @type {import('./types.js').Signal<V>[]} **/ (
|
|
|
|
signal.d = /** @type {import('./types.js').Signal<V>[]} **/ (
|
|
|
|
dependencies = current_dependencies
|
|
|
|
dependencies = current_dependencies
|
|
|
|
);
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -287,10 +286,10 @@ function execute_signal_fn(signal) {
|
|
|
|
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];
|
|
|
|
|
|
|
|
|
|
|
|
if (dependency.consumers === null) {
|
|
|
|
if (dependency.c === null) {
|
|
|
|
dependency.consumers = [signal];
|
|
|
|
dependency.c = [signal];
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
dependency.consumers.push(signal);
|
|
|
|
dependency.c.push(signal);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -318,17 +317,17 @@ function execute_signal_fn(signal) {
|
|
|
|
* @returns {void}
|
|
|
|
* @returns {void}
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
function remove_consumer(signal, start_index, remove_unowned) {
|
|
|
|
function remove_consumer(signal, start_index, remove_unowned) {
|
|
|
|
const dependencies = signal.dependencies;
|
|
|
|
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.consumers;
|
|
|
|
const consumers = dependency.c;
|
|
|
|
let consumers_length = 0;
|
|
|
|
let consumers_length = 0;
|
|
|
|
if (consumers !== null) {
|
|
|
|
if (consumers !== null) {
|
|
|
|
consumers_length = consumers.length - 1;
|
|
|
|
consumers_length = consumers.length - 1;
|
|
|
|
if (consumers_length === 0) {
|
|
|
|
if (consumers_length === 0) {
|
|
|
|
dependency.consumers = null;
|
|
|
|
dependency.c = null;
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
const index = consumers.indexOf(signal);
|
|
|
|
const index = consumers.indexOf(signal);
|
|
|
|
// Swap with last element and then remove.
|
|
|
|
// Swap with last element and then remove.
|
|
|
|
@ -336,7 +335,7 @@ function remove_consumer(signal, start_index, remove_unowned) {
|
|
|
|
consumers.pop();
|
|
|
|
consumers.pop();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (remove_unowned && consumers_length === 0 && (dependency.flags & UNOWNED) !== 0) {
|
|
|
|
if (remove_unowned && consumers_length === 0 && (dependency.f & UNOWNED) !== 0) {
|
|
|
|
remove_consumer(
|
|
|
|
remove_consumer(
|
|
|
|
/** @type {import('./types.js').ComputationSignal<V>} **/ (dependency),
|
|
|
|
/** @type {import('./types.js').ComputationSignal<V>} **/ (dependency),
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
@ -353,17 +352,17 @@ function remove_consumer(signal, start_index, remove_unowned) {
|
|
|
|
* @returns {void}
|
|
|
|
* @returns {void}
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
function destroy_references(signal) {
|
|
|
|
function destroy_references(signal) {
|
|
|
|
const references = signal.references;
|
|
|
|
const references = signal.r;
|
|
|
|
signal.references = null;
|
|
|
|
signal.r = null;
|
|
|
|
if (references !== null) {
|
|
|
|
if (references !== null) {
|
|
|
|
let i;
|
|
|
|
let i;
|
|
|
|
for (i = 0; i < references.length; i++) {
|
|
|
|
for (i = 0; i < references.length; i++) {
|
|
|
|
const reference = references[i];
|
|
|
|
const reference = references[i];
|
|
|
|
if ((reference.flags & IS_EFFECT) !== 0) {
|
|
|
|
if ((reference.f & IS_EFFECT) !== 0) {
|
|
|
|
destroy_signal(reference);
|
|
|
|
destroy_signal(reference);
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
remove_consumer(reference, 0, true);
|
|
|
|
remove_consumer(reference, 0, true);
|
|
|
|
reference.dependencies = null;
|
|
|
|
reference.d = null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -388,10 +387,10 @@ function report_error(block, error) {
|
|
|
|
* @returns {void}
|
|
|
|
* @returns {void}
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
export function execute_effect(signal) {
|
|
|
|
export function execute_effect(signal) {
|
|
|
|
if ((signal.flags & DESTROYED) !== 0) {
|
|
|
|
if ((signal.f & DESTROYED) !== 0) {
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
const teardown = signal.value;
|
|
|
|
const teardown = signal.v;
|
|
|
|
const previous_effect = current_effect;
|
|
|
|
const previous_effect = current_effect;
|
|
|
|
current_effect = signal;
|
|
|
|
current_effect = signal;
|
|
|
|
|
|
|
|
|
|
|
|
@ -402,10 +401,10 @@ export function execute_effect(signal) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
const possible_teardown = execute_signal_fn(signal);
|
|
|
|
const possible_teardown = execute_signal_fn(signal);
|
|
|
|
if (typeof possible_teardown === 'function') {
|
|
|
|
if (typeof possible_teardown === 'function') {
|
|
|
|
signal.value = possible_teardown;
|
|
|
|
signal.v = possible_teardown;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} catch (error) {
|
|
|
|
} catch (error) {
|
|
|
|
const block = signal.block;
|
|
|
|
const block = signal.b;
|
|
|
|
if (block !== null) {
|
|
|
|
if (block !== null) {
|
|
|
|
report_error(block, error);
|
|
|
|
report_error(block, error);
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
@ -414,10 +413,10 @@ export function execute_effect(signal) {
|
|
|
|
} finally {
|
|
|
|
} finally {
|
|
|
|
current_effect = previous_effect;
|
|
|
|
current_effect = previous_effect;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
const component_context = signal.context;
|
|
|
|
const component_context = signal.x;
|
|
|
|
if (
|
|
|
|
if (
|
|
|
|
is_runes(component_context) && // Don't rerun pre effects more than once to accomodate for "$: only runs once" behavior
|
|
|
|
is_runes(component_context) && // Don't rerun pre effects more than once to accomodate for "$: only runs once" behavior
|
|
|
|
(signal.flags & PRE_EFFECT) !== 0 &&
|
|
|
|
(signal.f & PRE_EFFECT) !== 0 &&
|
|
|
|
current_queued_pre_and_render_effects.length > 0
|
|
|
|
current_queued_pre_and_render_effects.length > 0
|
|
|
|
) {
|
|
|
|
) {
|
|
|
|
flush_local_pre_effects(component_context);
|
|
|
|
flush_local_pre_effects(component_context);
|
|
|
|
@ -441,7 +440,7 @@ function flush_queued_effects(effects) {
|
|
|
|
let i;
|
|
|
|
let i;
|
|
|
|
for (i = 0; i < length; i++) {
|
|
|
|
for (i = 0; i < length; i++) {
|
|
|
|
const signal = effects[i];
|
|
|
|
const signal = effects[i];
|
|
|
|
const flags = signal.flags;
|
|
|
|
const flags = signal.f;
|
|
|
|
if ((flags & (DESTROYED | INERT)) === 0) {
|
|
|
|
if ((flags & (DESTROYED | INERT)) === 0) {
|
|
|
|
if (is_signal_dirty(signal)) {
|
|
|
|
if (is_signal_dirty(signal)) {
|
|
|
|
set_signal_status(signal, CLEAN);
|
|
|
|
set_signal_status(signal, CLEAN);
|
|
|
|
@ -477,7 +476,7 @@ function process_microtask() {
|
|
|
|
* @returns {void}
|
|
|
|
* @returns {void}
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
export function schedule_effect(signal, sync) {
|
|
|
|
export function schedule_effect(signal, sync) {
|
|
|
|
const flags = signal.flags;
|
|
|
|
const flags = signal.f;
|
|
|
|
if (sync || (flags & SYNC_EFFECT) !== 0) {
|
|
|
|
if (sync || (flags & SYNC_EFFECT) !== 0) {
|
|
|
|
execute_effect(signal);
|
|
|
|
execute_effect(signal);
|
|
|
|
set_signal_status(signal, CLEAN);
|
|
|
|
set_signal_status(signal, CLEAN);
|
|
|
|
@ -524,7 +523,7 @@ export function flush_local_render_effects() {
|
|
|
|
const effects = [];
|
|
|
|
const effects = [];
|
|
|
|
for (let i = 0; i < current_queued_pre_and_render_effects.length; i++) {
|
|
|
|
for (let i = 0; i < current_queued_pre_and_render_effects.length; i++) {
|
|
|
|
const effect = current_queued_pre_and_render_effects[i];
|
|
|
|
const effect = current_queued_pre_and_render_effects[i];
|
|
|
|
if ((effect.flags & RENDER_EFFECT) !== 0 && effect.context === current_component_context) {
|
|
|
|
if ((effect.f & RENDER_EFFECT) !== 0 && effect.x === current_component_context) {
|
|
|
|
effects.push(effect);
|
|
|
|
effects.push(effect);
|
|
|
|
current_queued_pre_and_render_effects.splice(i, 1);
|
|
|
|
current_queued_pre_and_render_effects.splice(i, 1);
|
|
|
|
i--;
|
|
|
|
i--;
|
|
|
|
@ -541,7 +540,7 @@ export function flush_local_pre_effects(context) {
|
|
|
|
const effects = [];
|
|
|
|
const effects = [];
|
|
|
|
for (let i = 0; i < current_queued_pre_and_render_effects.length; i++) {
|
|
|
|
for (let i = 0; i < current_queued_pre_and_render_effects.length; i++) {
|
|
|
|
const effect = current_queued_pre_and_render_effects[i];
|
|
|
|
const effect = current_queued_pre_and_render_effects[i];
|
|
|
|
if ((effect.flags & PRE_EFFECT) !== 0 && effect.context === context) {
|
|
|
|
if ((effect.f & PRE_EFFECT) !== 0 && effect.x === context) {
|
|
|
|
effects.push(effect);
|
|
|
|
effects.push(effect);
|
|
|
|
current_queued_pre_and_render_effects.splice(i, 1);
|
|
|
|
current_queued_pre_and_render_effects.splice(i, 1);
|
|
|
|
i--;
|
|
|
|
i--;
|
|
|
|
@ -607,13 +606,13 @@ export async function tick() {
|
|
|
|
function update_derived(signal, force_schedule) {
|
|
|
|
function update_derived(signal, force_schedule) {
|
|
|
|
const value = execute_signal_fn(signal);
|
|
|
|
const value = execute_signal_fn(signal);
|
|
|
|
const status =
|
|
|
|
const status =
|
|
|
|
current_skip_consumer || (current_effect === null && (signal.flags & UNOWNED) !== 0)
|
|
|
|
current_skip_consumer || (current_effect === null && (signal.f & UNOWNED) !== 0)
|
|
|
|
? DIRTY
|
|
|
|
? DIRTY
|
|
|
|
: CLEAN;
|
|
|
|
: CLEAN;
|
|
|
|
set_signal_status(signal, status);
|
|
|
|
set_signal_status(signal, status);
|
|
|
|
const equals = /** @type {import('./types.js').EqualsFunctions} */ (signal.equals);
|
|
|
|
const equals = /** @type {import('./types.js').EqualsFunctions} */ (signal.e);
|
|
|
|
if (!equals(value, signal.value)) {
|
|
|
|
if (!equals(value, signal.v)) {
|
|
|
|
signal.value = value;
|
|
|
|
signal.v = value;
|
|
|
|
mark_signal_consumers(signal, DIRTY, force_schedule);
|
|
|
|
mark_signal_consumers(signal, DIRTY, force_schedule);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -731,9 +730,9 @@ export function exposable(fn) {
|
|
|
|
* @returns {V}
|
|
|
|
* @returns {V}
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
export function get(signal) {
|
|
|
|
export function get(signal) {
|
|
|
|
const flags = signal.flags;
|
|
|
|
const flags = signal.f;
|
|
|
|
if ((flags & DESTROYED) !== 0) {
|
|
|
|
if ((flags & DESTROYED) !== 0) {
|
|
|
|
return signal.value;
|
|
|
|
return signal.v;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (is_signal_exposed && current_should_capture_signal) {
|
|
|
|
if (is_signal_exposed && current_should_capture_signal) {
|
|
|
|
@ -745,13 +744,9 @@ export function get(signal) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Register the dependency on the current consumer signal.
|
|
|
|
// Register the dependency on the current consumer signal.
|
|
|
|
if (
|
|
|
|
if (current_consumer !== null && (current_consumer.f & MANAGED) === 0 && !current_untracking) {
|
|
|
|
current_consumer !== null &&
|
|
|
|
const unowned = (current_consumer.f & UNOWNED) !== 0;
|
|
|
|
(current_consumer.flags & MANAGED) === 0 &&
|
|
|
|
const dependencies = current_consumer.d;
|
|
|
|
!current_untracking
|
|
|
|
|
|
|
|
) {
|
|
|
|
|
|
|
|
const unowned = (current_consumer.flags & UNOWNED) !== 0;
|
|
|
|
|
|
|
|
const dependencies = current_consumer.dependencies;
|
|
|
|
|
|
|
|
if (
|
|
|
|
if (
|
|
|
|
current_dependencies === null &&
|
|
|
|
current_dependencies === null &&
|
|
|
|
dependencies !== null &&
|
|
|
|
dependencies !== null &&
|
|
|
|
@ -769,7 +764,7 @@ export function get(signal) {
|
|
|
|
if ((flags & DERIVED) !== 0 && is_signal_dirty(signal)) {
|
|
|
|
if ((flags & DERIVED) !== 0 && is_signal_dirty(signal)) {
|
|
|
|
update_derived(/** @type {import('./types.js').ComputationSignal<V>} **/ (signal), false);
|
|
|
|
update_derived(/** @type {import('./types.js').ComputationSignal<V>} **/ (signal), false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return signal.value;
|
|
|
|
return signal.v;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
@ -877,14 +872,14 @@ export function mutate_store(store, expression, new_value) {
|
|
|
|
* @returns {void}
|
|
|
|
* @returns {void}
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
export function mark_subtree_inert(signal, inert) {
|
|
|
|
export function mark_subtree_inert(signal, inert) {
|
|
|
|
const flags = signal.flags;
|
|
|
|
const flags = signal.f;
|
|
|
|
if (((flags & INERT) === 0 && inert) || ((flags & INERT) !== 0 && !inert)) {
|
|
|
|
if (((flags & INERT) === 0 && inert) || ((flags & INERT) !== 0 && !inert)) {
|
|
|
|
signal.flags ^= INERT;
|
|
|
|
signal.f ^= INERT;
|
|
|
|
if (!inert && (flags & IS_EFFECT) !== 0 && (flags & CLEAN) === 0) {
|
|
|
|
if (!inert && (flags & IS_EFFECT) !== 0 && (flags & CLEAN) === 0) {
|
|
|
|
schedule_effect(/** @type {import('./types.js').EffectSignal} */ (signal), false);
|
|
|
|
schedule_effect(/** @type {import('./types.js').EffectSignal} */ (signal), false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
const references = signal.references;
|
|
|
|
const references = signal.r;
|
|
|
|
if (references !== null) {
|
|
|
|
if (references !== null) {
|
|
|
|
let i;
|
|
|
|
let i;
|
|
|
|
for (i = 0; i < references.length; i++) {
|
|
|
|
for (i = 0; i < references.length; i++) {
|
|
|
|
@ -901,14 +896,14 @@ export function mark_subtree_inert(signal, inert) {
|
|
|
|
* @returns {void}
|
|
|
|
* @returns {void}
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
function mark_signal_consumers(signal, to_status, force_schedule) {
|
|
|
|
function mark_signal_consumers(signal, to_status, force_schedule) {
|
|
|
|
const runes = is_runes(signal.context);
|
|
|
|
const runes = is_runes(signal.x);
|
|
|
|
const consumers = signal.consumers;
|
|
|
|
const consumers = signal.c;
|
|
|
|
if (consumers !== null) {
|
|
|
|
if (consumers !== null) {
|
|
|
|
const length = consumers.length;
|
|
|
|
const length = consumers.length;
|
|
|
|
let i;
|
|
|
|
let i;
|
|
|
|
for (i = 0; i < length; i++) {
|
|
|
|
for (i = 0; i < length; i++) {
|
|
|
|
const consumer = consumers[i];
|
|
|
|
const consumer = consumers[i];
|
|
|
|
const flags = consumer.flags;
|
|
|
|
const flags = consumer.f;
|
|
|
|
const unowned = (flags & UNOWNED) !== 0;
|
|
|
|
const unowned = (flags & UNOWNED) !== 0;
|
|
|
|
const dirty = (flags & DIRTY) !== 0;
|
|
|
|
const dirty = (flags & DIRTY) !== 0;
|
|
|
|
// We skip any effects that are already dirty (but not unowned). Additionally, we also
|
|
|
|
// We skip any effects that are already dirty (but not unowned). Additionally, we also
|
|
|
|
@ -922,7 +917,7 @@ function mark_signal_consumers(signal, to_status, force_schedule) {
|
|
|
|
// are already dirty. Unowned signals might be dirty because they are not captured as part of an
|
|
|
|
// are already dirty. Unowned signals might be dirty because they are not captured as part of an
|
|
|
|
// effect.
|
|
|
|
// effect.
|
|
|
|
if ((flags & CLEAN) !== 0 || (dirty && unowned)) {
|
|
|
|
if ((flags & CLEAN) !== 0 || (dirty && unowned)) {
|
|
|
|
if ((consumer.flags & IS_EFFECT) !== 0) {
|
|
|
|
if ((consumer.f & IS_EFFECT) !== 0) {
|
|
|
|
schedule_effect(/** @type {import('./types.js').EffectSignal} */ (consumer), false);
|
|
|
|
schedule_effect(/** @type {import('./types.js').EffectSignal} */ (consumer), false);
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
mark_signal_consumers(consumer, MAYBE_DIRTY, force_schedule);
|
|
|
|
mark_signal_consumers(consumer, MAYBE_DIRTY, force_schedule);
|
|
|
|
@ -943,8 +938,8 @@ export function set_signal_value(signal, value) {
|
|
|
|
!current_untracking &&
|
|
|
|
!current_untracking &&
|
|
|
|
!ignore_mutation_validation &&
|
|
|
|
!ignore_mutation_validation &&
|
|
|
|
current_consumer !== null &&
|
|
|
|
current_consumer !== null &&
|
|
|
|
is_runes(signal.context) &&
|
|
|
|
is_runes(signal.x) &&
|
|
|
|
(current_consumer.flags & DERIVED) !== 0
|
|
|
|
(current_consumer.f & DERIVED) !== 0
|
|
|
|
) {
|
|
|
|
) {
|
|
|
|
throw new Error(
|
|
|
|
throw new Error(
|
|
|
|
"Unsafe mutations during Svelte's render or derived phase are not permitted in runes mode. " +
|
|
|
|
"Unsafe mutations during Svelte's render or derived phase are not permitted in runes mode. " +
|
|
|
|
@ -953,11 +948,11 @@ export function set_signal_value(signal, value) {
|
|
|
|
);
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (
|
|
|
|
if (
|
|
|
|
(signal.flags & SOURCE) !== 0 &&
|
|
|
|
(signal.f & SOURCE) !== 0 &&
|
|
|
|
!(/** @type {import('./types.js').EqualsFunctions} */ (signal.equals)(value, signal.value))
|
|
|
|
!(/** @type {import('./types.js').EqualsFunctions} */ (signal.e)(value, signal.v))
|
|
|
|
) {
|
|
|
|
) {
|
|
|
|
const component_context = signal.context;
|
|
|
|
const component_context = signal.x;
|
|
|
|
signal.value = value;
|
|
|
|
signal.v = value;
|
|
|
|
// If the current signal is running for the first time, it won't have any
|
|
|
|
// If the current signal is running for the first time, it won't have any
|
|
|
|
// consumers as we only allocate and assign the consumers after the signal
|
|
|
|
// consumers as we only allocate and assign the consumers after the signal
|
|
|
|
// has fully executed. So in the case of ensuring it registers the consumer
|
|
|
|
// has fully executed. So in the case of ensuring it registers the consumer
|
|
|
|
@ -969,8 +964,8 @@ export function set_signal_value(signal, value) {
|
|
|
|
if (
|
|
|
|
if (
|
|
|
|
is_runes(component_context) &&
|
|
|
|
is_runes(component_context) &&
|
|
|
|
current_effect !== null &&
|
|
|
|
current_effect !== null &&
|
|
|
|
current_effect.consumers === null &&
|
|
|
|
current_effect.c === null &&
|
|
|
|
(current_effect.flags & CLEAN) !== 0 &&
|
|
|
|
(current_effect.f & CLEAN) !== 0 &&
|
|
|
|
current_dependencies !== null &&
|
|
|
|
current_dependencies !== null &&
|
|
|
|
current_dependencies.includes(signal)
|
|
|
|
current_dependencies.includes(signal)
|
|
|
|
) {
|
|
|
|
) {
|
|
|
|
@ -1000,19 +995,19 @@ export function set_signal_value(signal, value) {
|
|
|
|
* @returns {void}
|
|
|
|
* @returns {void}
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
export function destroy_signal(signal) {
|
|
|
|
export function destroy_signal(signal) {
|
|
|
|
const teardown = /** @type {null | (() => void)} */ (signal.value);
|
|
|
|
const teardown = /** @type {null | (() => void)} */ (signal.v);
|
|
|
|
const destroy = signal.destroy;
|
|
|
|
const destroy = signal.y;
|
|
|
|
const flags = signal.flags;
|
|
|
|
const flags = signal.f;
|
|
|
|
destroy_references(signal);
|
|
|
|
destroy_references(signal);
|
|
|
|
remove_consumer(signal, 0, true);
|
|
|
|
remove_consumer(signal, 0, true);
|
|
|
|
signal.init = null;
|
|
|
|
signal.i = null;
|
|
|
|
signal.references = null;
|
|
|
|
signal.r = null;
|
|
|
|
signal.destroy = null;
|
|
|
|
signal.y = null;
|
|
|
|
signal.context = null;
|
|
|
|
signal.x = null;
|
|
|
|
signal.block = null;
|
|
|
|
signal.b = null;
|
|
|
|
signal.value = /** @type {V} */ (null);
|
|
|
|
signal.v = /** @type {V} */ (null);
|
|
|
|
signal.dependencies = null;
|
|
|
|
signal.d = null;
|
|
|
|
signal.consumers = null;
|
|
|
|
signal.c = null;
|
|
|
|
set_signal_status(signal, DESTROYED);
|
|
|
|
set_signal_status(signal, DESTROYED);
|
|
|
|
if (destroy !== null) {
|
|
|
|
if (destroy !== null) {
|
|
|
|
if (is_array(destroy)) {
|
|
|
|
if (is_array(destroy)) {
|
|
|
|
@ -1024,7 +1019,7 @@ export function destroy_signal(signal) {
|
|
|
|
destroy();
|
|
|
|
destroy();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (teardown !== null && (signal.flags & IS_EFFECT) !== 0) {
|
|
|
|
if (teardown !== null && (flags & IS_EFFECT) !== 0) {
|
|
|
|
teardown();
|
|
|
|
teardown();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -1042,9 +1037,9 @@ export function derived(init, equals) {
|
|
|
|
const signal = /** @type {import('./types.js').ComputationSignal<V>} */ (
|
|
|
|
const signal = /** @type {import('./types.js').ComputationSignal<V>} */ (
|
|
|
|
create_computation_signal(flags | CLEAN, UNINITIALIZED, current_block)
|
|
|
|
create_computation_signal(flags | CLEAN, UNINITIALIZED, current_block)
|
|
|
|
);
|
|
|
|
);
|
|
|
|
signal.init = init;
|
|
|
|
signal.i = init;
|
|
|
|
signal.context = current_component_context;
|
|
|
|
signal.x = current_component_context;
|
|
|
|
signal.equals = get_equals_method(equals);
|
|
|
|
signal.e = get_equals_method(equals);
|
|
|
|
if (!is_unowned) {
|
|
|
|
if (!is_unowned) {
|
|
|
|
push_reference(/** @type {import('./types.js').EffectSignal} */ (current_effect), signal);
|
|
|
|
push_reference(/** @type {import('./types.js').EffectSignal} */ (current_effect), signal);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -1060,8 +1055,8 @@ export function derived(init, equals) {
|
|
|
|
/*#__NO_SIDE_EFFECTS__*/
|
|
|
|
/*#__NO_SIDE_EFFECTS__*/
|
|
|
|
export function source(initial_value, equals) {
|
|
|
|
export function source(initial_value, equals) {
|
|
|
|
const source = create_source_signal(SOURCE | CLEAN, initial_value);
|
|
|
|
const source = create_source_signal(SOURCE | CLEAN, initial_value);
|
|
|
|
source.context = current_component_context;
|
|
|
|
source.x = current_component_context;
|
|
|
|
source.equals = get_equals_method(equals);
|
|
|
|
source.e = get_equals_method(equals);
|
|
|
|
return source;
|
|
|
|
return source;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -1108,8 +1103,8 @@ export function untrack(fn) {
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
function internal_create_effect(type, init, sync, block, schedule) {
|
|
|
|
function internal_create_effect(type, init, sync, block, schedule) {
|
|
|
|
const signal = create_computation_signal(type | DIRTY, null, block);
|
|
|
|
const signal = create_computation_signal(type | DIRTY, null, block);
|
|
|
|
signal.init = init;
|
|
|
|
signal.i = init;
|
|
|
|
signal.context = current_component_context;
|
|
|
|
signal.x = current_component_context;
|
|
|
|
if (schedule) {
|
|
|
|
if (schedule) {
|
|
|
|
schedule_effect(signal, sync);
|
|
|
|
schedule_effect(signal, sync);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -1128,7 +1123,7 @@ export function user_effect(init) {
|
|
|
|
throw new Error('The Svelte $effect rune can only be used during component initialisation.');
|
|
|
|
throw new Error('The Svelte $effect rune can only be used during component initialisation.');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
const apply_component_effect_heuristics =
|
|
|
|
const apply_component_effect_heuristics =
|
|
|
|
current_effect.flags & RENDER_EFFECT &&
|
|
|
|
current_effect.f & RENDER_EFFECT &&
|
|
|
|
current_component_context !== null &&
|
|
|
|
current_component_context !== null &&
|
|
|
|
!current_component_context.mounted;
|
|
|
|
!current_component_context.mounted;
|
|
|
|
const effect = internal_create_effect(
|
|
|
|
const effect = internal_create_effect(
|
|
|
|
@ -1186,7 +1181,7 @@ export function pre_effect(init) {
|
|
|
|
'The Svelte $effect.pre rune can only be used during component initialisation.'
|
|
|
|
'The Svelte $effect.pre rune can only be used during component initialisation.'
|
|
|
|
);
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
const sync = current_effect !== null && (current_effect.flags & RENDER_EFFECT) !== 0;
|
|
|
|
const sync = current_effect !== null && (current_effect.f & RENDER_EFFECT) !== 0;
|
|
|
|
return internal_create_effect(
|
|
|
|
return internal_create_effect(
|
|
|
|
PRE_EFFECT,
|
|
|
|
PRE_EFFECT,
|
|
|
|
() => {
|
|
|
|
() => {
|
|
|
|
@ -1243,13 +1238,13 @@ export function managed_render_effect(init, block = current_block, sync = true)
|
|
|
|
* @returns {void}
|
|
|
|
* @returns {void}
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
export function push_destroy_fn(signal, destroy_fn) {
|
|
|
|
export function push_destroy_fn(signal, destroy_fn) {
|
|
|
|
let destroy = signal.destroy;
|
|
|
|
let destroy = signal.y;
|
|
|
|
if (destroy === null) {
|
|
|
|
if (destroy === null) {
|
|
|
|
signal.destroy = destroy_fn;
|
|
|
|
signal.y = destroy_fn;
|
|
|
|
} else if (is_array(destroy)) {
|
|
|
|
} else if (is_array(destroy)) {
|
|
|
|
destroy.push(destroy_fn);
|
|
|
|
destroy.push(destroy_fn);
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
signal.destroy = [destroy, destroy_fn];
|
|
|
|
signal.y = [destroy, destroy_fn];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -1260,16 +1255,16 @@ export function push_destroy_fn(signal, destroy_fn) {
|
|
|
|
* @returns {void}
|
|
|
|
* @returns {void}
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
export function set_signal_status(signal, status) {
|
|
|
|
export function set_signal_status(signal, status) {
|
|
|
|
const flags = signal.flags;
|
|
|
|
const flags = signal.f;
|
|
|
|
if ((flags & status) === 0) {
|
|
|
|
if ((flags & status) === 0) {
|
|
|
|
if ((flags & MAYBE_DIRTY) !== 0) {
|
|
|
|
if ((flags & MAYBE_DIRTY) !== 0) {
|
|
|
|
signal.flags ^= MAYBE_DIRTY;
|
|
|
|
signal.f ^= MAYBE_DIRTY;
|
|
|
|
} else if ((flags & CLEAN) !== 0) {
|
|
|
|
} else if ((flags & CLEAN) !== 0) {
|
|
|
|
signal.flags ^= CLEAN;
|
|
|
|
signal.f ^= CLEAN;
|
|
|
|
} else if ((flags & DIRTY) !== 0) {
|
|
|
|
} else if ((flags & DIRTY) !== 0) {
|
|
|
|
signal.flags ^= DIRTY;
|
|
|
|
signal.f ^= DIRTY;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
signal.flags ^= status;
|
|
|
|
signal.f ^= status;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -1282,7 +1277,7 @@ export function is_signal(val) {
|
|
|
|
return (
|
|
|
|
return (
|
|
|
|
typeof val === 'object' &&
|
|
|
|
typeof val === 'object' &&
|
|
|
|
val !== null &&
|
|
|
|
val !== null &&
|
|
|
|
typeof (/** @type {import('./types.js').Signal<V>} */ (val).flags) === 'number'
|
|
|
|
typeof (/** @type {import('./types.js').Signal<V>} */ (val).f) === 'number'
|
|
|
|
);
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -1328,9 +1323,9 @@ export function prop_source(props_obj, key, default_value, call_default_value) {
|
|
|
|
|
|
|
|
|
|
|
|
if (
|
|
|
|
if (
|
|
|
|
is_signal(possible_signal) &&
|
|
|
|
is_signal(possible_signal) &&
|
|
|
|
possible_signal.value === value &&
|
|
|
|
possible_signal.v === value &&
|
|
|
|
update_bound_prop === undefined &&
|
|
|
|
update_bound_prop === undefined &&
|
|
|
|
get_equals_method() === possible_signal.equals
|
|
|
|
get_equals_method() === possible_signal.e
|
|
|
|
) {
|
|
|
|
) {
|
|
|
|
if (should_set_default_value) {
|
|
|
|
if (should_set_default_value) {
|
|
|
|
set(
|
|
|
|
set(
|
|
|
|
@ -1372,7 +1367,7 @@ export function prop_source(props_obj, key, default_value, call_default_value) {
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (not_equal(immutable, propagating_value, source_signal.value)) {
|
|
|
|
if (not_equal(immutable, propagating_value, source_signal.v)) {
|
|
|
|
ignore_next2 = true;
|
|
|
|
ignore_next2 = true;
|
|
|
|
// TODO figure out why we need it this way and the explain in a comment;
|
|
|
|
// TODO figure out why we need it this way and the explain in a comment;
|
|
|
|
// some tests fail is we just do set_signal_value(source_signal, propagating_value)
|
|
|
|
// some tests fail is we just do set_signal_value(source_signal, propagating_value)
|
|
|
|
@ -1394,7 +1389,7 @@ export function prop_source(props_obj, key, default_value, call_default_value) {
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (not_equal(immutable, propagating_value, possible_signal.value)) {
|
|
|
|
if (not_equal(immutable, propagating_value, possible_signal.v)) {
|
|
|
|
ignore_next1 = true;
|
|
|
|
ignore_next1 = true;
|
|
|
|
untrack(() => update_bound_prop(propagating_value));
|
|
|
|
untrack(() => update_bound_prop(propagating_value));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|