diff --git a/packages/svelte/src/internal/client/runtime.js b/packages/svelte/src/internal/client/runtime.js index 8631529e62..cb04f9c96b 100644 --- a/packages/svelte/src/internal/client/runtime.js +++ b/packages/svelte/src/internal/client/runtime.js @@ -111,7 +111,7 @@ export function set_is_ssr(ssr) { */ function is_runes(context) { const component_context = context || current_component_context; - return component_context !== null && component_context.r; + return !!component_context && component_context.r; } /** @@ -128,7 +128,7 @@ export function batch_inspect(target, prop, receiver) { return Reflect.apply(value, receiver, arguments); } finally { is_batching_effect = previously_batching_effect; - if (last_inspected_signal !== null) { + if (last_inspected_signal) { for (const fn of last_inspected_signal.inspect) fn(); last_inspected_signal = null; } @@ -256,10 +256,10 @@ function create_computation_signal(flags, value, block) { */ function push_reference(target_signal, ref_signal) { const references = target_signal.r; - if (references === null) { - target_signal.r = [ref_signal]; - } else { + if (references) { references.push(ref_signal); + } else { + target_signal.r = [ref_signal]; } } @@ -270,30 +270,30 @@ function push_reference(target_signal, ref_signal) { */ function is_signal_dirty(signal) { const flags = signal.f; - if ((flags & DIRTY) !== 0 || signal.v === UNINITIALIZED) { + if (flags & DIRTY || signal.v === UNINITIALIZED) { return true; } - if ((flags & MAYBE_DIRTY) !== 0) { + if (flags & MAYBE_DIRTY) { const dependencies = /** @type {import('./types.js').ComputationSignal} **/ (signal).d; - if (dependencies !== null) { + if (dependencies) { const length = dependencies.length; let i; for (i = 0; i < length; i++) { const dependency = dependencies[i]; - if ((dependency.f & MAYBE_DIRTY) !== 0 && !is_signal_dirty(dependency)) { + if (dependency.f & MAYBE_DIRTY && !is_signal_dirty(dependency)) { set_signal_status(dependency, CLEAN); continue; } // The flags can be marked as dirty from the above is_signal_dirty call. - if ((dependency.f & DIRTY) !== 0) { - if ((dependency.f & DERIVED) !== 0) { + if (dependency.f & DIRTY) { + if (dependency.f & DERIVED) { update_derived( /** @type {import('./types.js').ComputationSignal} **/ (dependency), true ); // Might have been mutated from above get. - if ((signal.f & DIRTY) !== 0) { + if (signal.f & DIRTY) { return true; } } else { @@ -320,7 +320,7 @@ function execute_signal_fn(signal) { const previous_block = current_block; const previous_component_context = current_component_context; const previous_skip_consumer = current_skip_consumer; - const is_render_effect = (signal.f & RENDER_EFFECT) !== 0; + const is_render_effect = signal.f & RENDER_EFFECT; const previous_untracking = current_untracking; current_dependencies = /** @type {null | import('./types.js').Signal[]} */ (null); current_dependencies_index = 0; @@ -328,11 +328,11 @@ function execute_signal_fn(signal) { current_consumer = signal; current_block = signal.b; current_component_context = signal.x; - current_skip_consumer = current_effect === null && (signal.f & UNOWNED) !== 0; + current_skip_consumer = !current_effect && !!(signal.f & UNOWNED); current_untracking = false; // Render effects are invoked when the UI is about to be updated - run beforeUpdate at that point - if (is_render_effect && current_component_context?.u != null) { + if (is_render_effect && current_component_context?.u) { // update_callbacks.execute() current_component_context.u.e(); } @@ -348,14 +348,13 @@ function execute_signal_fn(signal) { } let dependencies = /** @type {import('./types.js').Signal[]} **/ (signal.d); - if (current_dependencies !== null) { + if (current_dependencies) { let i; - if (dependencies !== null) { + if (dependencies) { // Include any dependencies up until the current_dependencies_index. - const full_dependencies = - current_dependencies_index === 0 - ? dependencies - : dependencies.slice(0, current_dependencies_index).concat(current_dependencies); + const full_dependencies = !current_dependencies_index + ? dependencies + : dependencies.slice(0, current_dependencies_index).concat(current_dependencies); const dep_length = full_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? @@ -364,7 +363,7 @@ function execute_signal_fn(signal) { for (i = current_dependencies_index; i < dep_length; i++) { const dependency = full_dependencies[i]; if ( - (current_dependencies_set !== null && !current_dependencies_set.has(dependency)) || + (current_dependencies_set && !current_dependencies_set.has(dependency)) || !full_dependencies.includes(dependency) ) { remove_consumer(signal, dependency, false); @@ -372,7 +371,7 @@ function execute_signal_fn(signal) { } } - if (dependencies !== null && current_dependencies_index > 0) { + if (dependencies && current_dependencies_index > 0) { dependencies.length = current_dependencies_index + current_dependencies.length; for (i = 0; i < current_dependencies.length; i++) { dependencies[current_dependencies_index + i] = current_dependencies[i]; @@ -388,14 +387,14 @@ function execute_signal_fn(signal) { const dependency = dependencies[i]; const consumers = dependency.c; - if (consumers === null) { + if (!consumers) { dependency.c = [signal]; } else if (consumers[consumers.length - 1] !== signal) { consumers.push(signal); } } } - } else if (dependencies !== null && current_dependencies_index < dependencies.length) { + } else if (dependencies && current_dependencies_index < dependencies.length) { remove_consumers(signal, current_dependencies_index, false); dependencies.length = current_dependencies_index; } @@ -422,11 +421,11 @@ function execute_signal_fn(signal) { function remove_consumer(signal, dependency, remove_unowned) { const consumers = dependency.c; let consumers_length = 0; - if (consumers !== null) { + if (consumers) { consumers_length = consumers.length - 1; const index = consumers.indexOf(signal); if (index !== -1) { - if (consumers_length === 0) { + if (!consumers_length) { dependency.c = null; } else { // Swap with last element and then remove. @@ -435,7 +434,7 @@ function remove_consumer(signal, dependency, remove_unowned) { } } } - if (remove_unowned && consumers_length === 0 && (dependency.f & UNOWNED) !== 0) { + if (remove_unowned && !consumers_length && dependency.f & UNOWNED) { // If the signal is unowned then we need to make sure to change it to dirty. set_signal_status(dependency, DIRTY); remove_consumers( @@ -455,13 +454,13 @@ function remove_consumer(signal, dependency, remove_unowned) { */ function remove_consumers(signal, start_index, remove_unowned) { const dependencies = signal.d; - if (dependencies !== null) { - const active_dependencies = start_index === 0 ? null : dependencies.slice(0, start_index); + if (dependencies) { + const active_dependencies = !start_index ? null : dependencies.slice(0, start_index); let i; for (i = start_index; i < dependencies.length; i++) { const dependency = dependencies[i]; // Avoid removing a consumer if we know that it is active (start_index will not be 0) - if (active_dependencies === null || !active_dependencies.includes(dependency)) { + if (!active_dependencies || !active_dependencies.includes(dependency)) { remove_consumer(signal, dependency, remove_unowned); } } @@ -476,11 +475,11 @@ function remove_consumers(signal, start_index, remove_unowned) { function destroy_references(signal) { const references = signal.r; signal.r = null; - if (references !== null) { + if (references) { let i; for (i = 0; i < references.length; i++) { const reference = references[i]; - if ((reference.f & IS_EFFECT) !== 0) { + if (reference.f & IS_EFFECT) { destroy_signal(reference); } else { remove_consumers(reference, 0, true); @@ -490,26 +489,12 @@ function destroy_references(signal) { } } -/** - * @param {import('./types.js').Block} block - * @param {unknown} error - * @returns {void} - */ -function report_error(block, error) { - /** @type {import('./types.js').Block | null} */ - let current_block = block; - - if (current_block !== null) { - throw error; - } -} - /** * @param {import('./types.js').EffectSignal} signal * @returns {void} */ export function execute_effect(signal) { - if ((signal.f & DESTROYED) !== 0) { + if (signal.f & DESTROYED) { return; } const teardown = signal.v; @@ -518,7 +503,7 @@ export function execute_effect(signal) { try { destroy_references(signal); - if (teardown !== null) { + if (teardown) { teardown(); } const possible_teardown = execute_signal_fn(signal); @@ -527,18 +512,14 @@ export function execute_effect(signal) { } } catch (error) { const block = signal.b; - if (block !== null) { - report_error(block, error); - } else { - throw error; - } + throw error; } finally { current_effect = previous_effect; } const component_context = signal.x; if ( is_runes(component_context) && // Don't rerun pre effects more than once to accomodate for "$: only runs once" behavior - (signal.f & PRE_EFFECT) !== 0 && + signal.f & PRE_EFFECT && current_queued_pre_and_render_effects.length > 0 ) { flush_local_pre_effects(component_context); @@ -570,11 +551,11 @@ function flush_queued_effects(effects) { for (i = 0; i < length; i++) { const signal = effects[i]; const flags = signal.f; - if ((flags & (DESTROYED | INERT)) === 0) { + if (!(flags & (DESTROYED | INERT))) { if (is_signal_dirty(signal)) { set_signal_status(signal, CLEAN); execute_effect(signal); - } else if ((flags & MAYBE_DIRTY) !== 0) { + } else if (flags & MAYBE_DIRTY) { set_signal_status(signal, CLEAN); } } @@ -621,7 +602,7 @@ export function schedule_effect(signal, sync) { queueMicrotask(process_microtask); } } - if ((flags & EFFECT) !== 0) { + if (flags & EFFECT) { current_queued_effects.push(signal); } else { current_queued_pre_and_render_effects.push(signal); @@ -667,7 +648,7 @@ export function flush_local_render_effects() { const effects = []; for (let i = 0; i < current_queued_pre_and_render_effects.length; i++) { const effect = current_queued_pre_and_render_effects[i]; - if ((effect.f & RENDER_EFFECT) !== 0 && effect.x === current_component_context) { + if (effect.f & RENDER_EFFECT && effect.x === current_component_context) { effects.push(effect); current_queued_pre_and_render_effects.splice(i, 1); i--; @@ -684,7 +665,7 @@ export function flush_local_pre_effects(context) { const effects = []; for (let i = 0; i < current_queued_pre_and_render_effects.length; i++) { const effect = current_queued_pre_and_render_effects[i]; - if ((effect.f & PRE_EFFECT) !== 0 && effect.x === context) { + if (effect.f & PRE_EFFECT && effect.x === context) { effects.push(effect); current_queued_pre_and_render_effects.splice(i, 1); i--; @@ -714,7 +695,7 @@ export function flushSync(fn) { current_queued_effects = effects; flush_queued_effects(previous_queued_pre_and_render_effects); flush_queued_effects(previous_queued_effects); - if (fn !== undefined) { + if (fn) { fn(); } if (current_queued_pre_and_render_effects.length > 0 || effects.length > 0) { @@ -756,10 +737,7 @@ function update_derived(signal, force_schedule) { updating_derived = true; const value = execute_signal_fn(signal); updating_derived = previous_updating_derived; - const status = - current_skip_consumer || (current_effect === null && (signal.f & UNOWNED) !== 0) - ? DIRTY - : CLEAN; + const status = current_skip_consumer || (!current_effect && signal.f & UNOWNED) ? DIRTY : CLEAN; set_signal_status(signal, status); const equals = /** @type {import('./types.js').EqualsFunctions} */ (signal.e); if (!equals(value, signal.v)) { @@ -821,7 +799,7 @@ export function store_get(store, store_name, stores) { * @param {import('./types.js').SourceSignal} source */ function connect_store_to_signal(store, source) { - if (store == null) { + if (!store) { set(source, undefined); return EMPTY_FUNC; } @@ -877,7 +855,7 @@ export function get(signal) { } const flags = signal.f; - if ((flags & DESTROYED) !== 0) { + if (flags & DESTROYED) { return signal.v; } @@ -886,31 +864,31 @@ export function get(signal) { } // Register the dependency on the current consumer signal. - if (current_consumer !== null && (current_consumer.f & MANAGED) === 0 && !current_untracking) { - const unowned = (current_consumer.f & UNOWNED) !== 0; + if (current_consumer && !(current_consumer.f & MANAGED) && !current_untracking) { + const unowned = current_consumer.f & UNOWNED; const dependencies = current_consumer.d; if ( - current_dependencies === null && - dependencies !== null && + !current_dependencies && + dependencies && dependencies[current_dependencies_index] === signal && - !(unowned && current_effect !== null) + !(unowned && current_effect) ) { current_dependencies_index++; } else if ( - dependencies === null || - current_dependencies_index === 0 || + !dependencies || + !current_dependencies_index || dependencies[current_dependencies_index - 1] !== signal ) { - if (current_dependencies === null) { + if (!current_dependencies) { current_dependencies = [signal]; } else if (signal !== current_dependencies[current_dependencies.length - 1]) { current_dependencies.push(signal); } } if ( - current_untracked_writes !== null && - current_effect !== null && - (current_effect.f & CLEAN) !== 0 && + current_untracked_writes && + current_effect && + current_effect.f & CLEAN && current_untracked_writes.includes(signal) ) { set_signal_status(current_effect, DIRTY); @@ -918,7 +896,7 @@ export function get(signal) { } } - if ((flags & DERIVED) !== 0 && is_signal_dirty(signal)) { + if (flags & DERIVED && is_signal_dirty(signal)) { if (DEV) { // we want to avoid tracking indirect dependencies const previous_inspect_fn = inspect_fn; @@ -1013,15 +991,15 @@ export function mutate_store(store, expression, new_value) { */ export function mark_subtree_inert(signal, inert) { const flags = signal.f; - const is_already_inert = (flags & INERT) !== 0; + const is_already_inert = !!(flags & INERT); if (is_already_inert !== inert) { signal.f ^= INERT; - if (!inert && (flags & IS_EFFECT) !== 0 && (flags & CLEAN) === 0) { + if (!inert && flags & IS_EFFECT && !(flags & CLEAN)) { schedule_effect(/** @type {import('./types.js').EffectSignal} */ (signal), false); } } const references = signal.r; - if (references !== null) { + if (references) { let i; for (i = 0; i < references.length; i++) { mark_subtree_inert(references[i], inert); @@ -1039,14 +1017,14 @@ export function mark_subtree_inert(signal, inert) { function mark_signal_consumers(signal, to_status, force_schedule) { const runes = is_runes(signal.x); const consumers = signal.c; - if (consumers !== null) { + if (consumers) { const length = consumers.length; let i; for (i = 0; i < length; i++) { const consumer = consumers[i]; const flags = consumer.f; - const unowned = (flags & UNOWNED) !== 0; - const dirty = (flags & DIRTY) !== 0; + const unowned = flags & UNOWNED; + const dirty = flags & DIRTY; // We skip any effects that are already dirty (but not unowned). Additionally, we also // skip if the consumer is the same as the current effect (except if we're not in runes or we // are in force schedule mode). @@ -1057,8 +1035,8 @@ function mark_signal_consumers(signal, to_status, force_schedule) { // If the signal is not clean, then skip over it – with the exception of unowned signals that // are already dirty. Unowned signals might be dirty because they are not captured as part of an // effect. - if ((flags & CLEAN) !== 0 || (dirty && unowned)) { - if ((consumer.f & IS_EFFECT) !== 0) { + if (flags & CLEAN || (dirty && unowned)) { + if (consumer.f & IS_EFFECT) { schedule_effect(/** @type {import('./types.js').EffectSignal} */ (consumer), false); } else { mark_signal_consumers(consumer, MAYBE_DIRTY, force_schedule); @@ -1078,9 +1056,9 @@ export function set_signal_value(signal, value) { if ( !current_untracking && !ignore_mutation_validation && - current_consumer !== null && + current_consumer && is_runes(signal.x) && - (current_consumer.f & DERIVED) !== 0 + current_consumer.f & DERIVED ) { throw new Error( 'ERR_SVELTE_UNSAFE_MUTATION' + @@ -1092,7 +1070,7 @@ export function set_signal_value(signal, value) { ); } if ( - (signal.f & SOURCE) !== 0 && + signal.f & SOURCE && !(/** @type {import('./types.js').EqualsFunctions} */ (signal.e)(value, signal.v)) ) { const component_context = signal.x; @@ -1107,18 +1085,18 @@ export function set_signal_value(signal, value) { // if ( is_runes(component_context) && - current_effect !== null && - current_effect.c === null && - (current_effect.f & CLEAN) !== 0 + current_effect && + !current_effect.c && + current_effect.f & CLEAN ) { - if (current_dependencies !== null && current_dependencies.includes(signal)) { + if (current_dependencies && current_dependencies.includes(signal)) { set_signal_status(current_effect, DIRTY); schedule_effect(current_effect, false); } else { - if (current_untracked_writes === null) { - current_untracked_writes = [signal]; - } else { + if (current_untracked_writes) { current_untracked_writes.push(signal); + } else { + current_untracked_writes = [signal]; } } } @@ -1126,9 +1104,9 @@ export function set_signal_value(signal, value) { // If we have afterUpdates locally on the component, but we're within a render effect // then we will need to manually invoke the beforeUpdate/afterUpdate logic. // TODO: should we put this being a is_runes check and only run it in non-runes mode? - if (current_effect === null && current_queued_pre_and_render_effects.length === 0) { + if (!current_effect && !current_queued_pre_and_render_effects.length) { const update_callbacks = component_context?.u; - if (update_callbacks != null) { + if (update_callbacks) { run_all(update_callbacks.b); const managed = managed_effect(() => { destroy_signal(managed); @@ -1170,14 +1148,14 @@ export function destroy_signal(signal) { signal.c = null; set_signal_status(signal, DESTROYED); - if (destroy !== null) { + if (destroy) { if (is_array(destroy)) { run_all(destroy); } else { destroy(); } } - if (teardown !== null && (flags & IS_EFFECT) !== 0) { + if (teardown && flags & IS_EFFECT) { teardown(); } } @@ -1189,7 +1167,7 @@ export function destroy_signal(signal) { */ /*#__NO_SIDE_EFFECTS__*/ export function derived(init) { - const is_unowned = current_effect === null; + const is_unowned = !current_effect; const flags = is_unowned ? DERIVED | UNOWNED : DERIVED; const signal = /** @type {import('./types.js').ComputationSignal} */ ( create_computation_signal(flags | CLEAN, UNINITIALIZED, current_block) @@ -1260,7 +1238,7 @@ function internal_create_effect(type, init, sync, block, schedule) { if (schedule) { schedule_effect(signal, sync); } - if (current_effect !== null && (type & MANAGED) === 0) { + if (current_effect && !(type & MANAGED)) { push_reference(current_effect, signal); } return signal; @@ -1270,7 +1248,7 @@ function internal_create_effect(type, init, sync, block, schedule) { * @returns {boolean} */ export function effect_active() { - return current_effect ? (current_effect.f & MANAGED) === 0 : false; + return current_effect ? !(current_effect.f & MANAGED) : false; } /** @@ -1278,16 +1256,14 @@ export function effect_active() { * @returns {import('./types.js').EffectSignal} */ export function user_effect(init) { - if (current_effect === null) { + if (!current_effect) { throw new Error( 'ERR_SVELTE_ORPHAN_EFFECT' + (DEV ? ': The Svelte $effect rune can only be used during component initialisation.' : '') ); } const apply_component_effect_heuristics = - current_effect.f & RENDER_EFFECT && - current_component_context !== null && - !current_component_context.m; + current_effect.f & RENDER_EFFECT && current_component_context && !current_component_context.m; const effect = internal_create_effect( EFFECT, init, @@ -1298,7 +1274,7 @@ export function user_effect(init) { if (apply_component_effect_heuristics) { let effects = /** @type {import('./types.js').ComponentContext} */ (current_component_context) .e; - if (effects === null) { + if (!effects) { effects = /** @type {import('./types.js').ComponentContext} */ (current_component_context).e = []; } @@ -1348,7 +1324,7 @@ export function managed_pre_effect(init, sync) { * @returns {import('./types.js').EffectSignal} */ export function pre_effect(init) { - if (current_effect === null) { + if (!current_effect) { throw new Error( 'ERR_SVELTE_ORPHAN_EFFECT' + (DEV @@ -1356,7 +1332,7 @@ export function pre_effect(init) { : '') ); } - const sync = current_effect !== null && (current_effect.f & RENDER_EFFECT) !== 0; + const sync = current_effect && !!(current_effect.f & RENDER_EFFECT); return internal_create_effect( PRE_EFFECT, () => { @@ -1417,7 +1393,7 @@ export function managed_render_effect(init, block = current_block, sync = true) */ export function push_destroy_fn(signal, destroy_fn) { let destroy = signal.y; - if (destroy === null) { + if (!destroy) { signal.y = destroy_fn; } else if (is_array(destroy)) { destroy.push(destroy_fn); @@ -1445,7 +1421,7 @@ export function set_signal_status(signal, status) { export function is_signal(val) { return ( typeof val === 'object' && - val !== null && + val && typeof (/** @type {import('./types.js').Signal} */ (val).f) === 'number' ); } @@ -1459,7 +1435,7 @@ export function is_signal(val) { export function is_lazy_property(val) { return ( typeof val === 'object' && - val !== null && + val && /** @type {import('./types.js').LazyProperty} */ (val).t === LAZY_PROPERTY ); } @@ -1472,7 +1448,7 @@ export function is_lazy_property(val) { export function is_store(val) { return ( typeof val === 'object' && - val !== null && + !!val && typeof (/** @type {import('./types.js').Store} */ (val).subscribe) === 'function' ); } @@ -1488,8 +1464,8 @@ export function is_store(val) { * @returns {(() => V | ((arg: V) => V) | ((arg: V, mutation: boolean) => V))} */ export function prop(props, key, flags, initial) { - var immutable = (flags & PROPS_IS_IMMUTABLE) !== 0; - var runes = (flags & PROPS_IS_RUNES) !== 0; + var immutable = flags & PROPS_IS_IMMUTABLE; + var runes = flags & PROPS_IS_RUNES; var setter = get_descriptor(props, key)?.set; if (DEV && setter && runes && initial !== undefined) { @@ -1501,7 +1477,7 @@ export function prop(props, key, flags, initial) { if (prop_value === undefined && initial !== undefined) { // @ts-expect-error would need a cumbersome method overload to type this - if ((flags & PROPS_IS_LAZY_INITIAL) !== 0) initial = initial(); + if (flags & PROPS_IS_LAZY_INITIAL) initial = initial(); if (DEV && runes) { initial = readonly(proxy(/** @type {any} */ (initial))); @@ -1519,7 +1495,7 @@ export function prop(props, key, flags, initial) { }; // easy mode — prop is never written to - if ((flags & PROPS_IS_UPDATED) === 0) { + if (!(flags & PROPS_IS_UPDATED)) { return getter; } @@ -1614,14 +1590,14 @@ export function safe_equal(a, b) { /** @returns {Map} */ export function get_or_init_context_map() { const component_context = current_component_context; - if (component_context === null) { + if (!component_context) { throw new Error( 'ERR_SVELTE_ORPHAN_CONTEXT' + (DEV ? 'Context can only be used during component initialisation.' : '') ); } let context_map = component_context.c; - if (context_map === null) { + if (!context_map) { const parent_context = get_parent_context(component_context); context_map = component_context.c = new Map(parent_context || undefined); } @@ -1634,9 +1610,9 @@ export function get_or_init_context_map() { */ function get_parent_context(component_context) { let parent = component_context.p; - while (parent !== null) { + while (parent) { const context_map = parent.c; - if (context_map !== null) { + if (context_map) { return context_map; } parent = parent.p; @@ -1818,12 +1794,12 @@ export function push(props, runes = false) { */ export function pop(accessors) { const context_stack_item = current_component_context; - if (context_stack_item !== null) { - if (accessors !== undefined) { + if (context_stack_item) { + if (accessors) { context_stack_item.a = accessors; } const effects = context_stack_item.e; - if (effects !== null) { + if (effects) { context_stack_item.e = null; for (let i = 0; i < effects.length; i++) { schedule_effect(effects[i], false); diff --git a/packages/svelte/src/store/utils.js b/packages/svelte/src/store/utils.js index 979a2518d8..bfc8bb3c1a 100644 --- a/packages/svelte/src/store/utils.js +++ b/packages/svelte/src/store/utils.js @@ -8,7 +8,7 @@ import { EMPTY_FUNC } from '../internal/common.js'; * @returns {() => void} */ export function subscribe_to_store(store, run, invalidate) { - if (store == null) { + if (!store) { // @ts-expect-error run(undefined);