tidy up types a bit

blockless
Rich Harris 2 years ago
parent 987d5e9f6f
commit c6a2e543e9

@ -25,13 +25,13 @@ export function await_block(anchor_node, get_input, pending_fn, then_fn, catch_f
/** @type {any} */ /** @type {any} */
let input; let input;
/** @type {import('../../types.js').EffectSignal | null} */ /** @type {import('../../reactivity/types.js').EffectSignal | null} */
let pending_effect; let pending_effect;
/** @type {import('../../types.js').EffectSignal | null} */ /** @type {import('../../reactivity/types.js').EffectSignal | null} */
let then_effect; let then_effect;
/** @type {import('../../types.js').EffectSignal | null} */ /** @type {import('../../reactivity/types.js').EffectSignal | null} */
let catch_effect; let catch_effect;
const branch = render_effect(() => { const branch = render_effect(() => {

@ -30,6 +30,11 @@ const NEW_BLOCK = -1;
const MOVED_BLOCK = 99999999; const MOVED_BLOCK = 99999999;
const LIS_BLOCK = -2; const LIS_BLOCK = -2;
/**
* @template T
* @typedef {T | import('#client').Signal<T>} MaybeSignal
*/
/** /**
* Reconcile arrays by the equality of the elements in the array. This algorithm * Reconcile arrays by the equality of the elements in the array. This algorithm
* is based on Ivi's reconcilation logic: * is based on Ivi's reconcilation logic:
@ -39,7 +44,7 @@ const LIS_BLOCK = -2;
* @param {() => V[]} collection * @param {() => V[]} collection
* @param {number} flags * @param {number} flags
* @param { ((item: V) => string)} key_fn * @param { ((item: V) => string)} key_fn
* @param {(anchor: null, item: V, index: import('../../types.js').MaybeSignal<number>) => void} render_fn * @param {(anchor: null, item: V, index: MaybeSignal<number>) => void} render_fn
* @param {null | ((anchor: Node) => void)} fallback_fn * @param {null | ((anchor: Node) => void)} fallback_fn
* @returns {void} * @returns {void}
*/ */
@ -56,7 +61,7 @@ export function each_keyed(anchor_node, collection, flags, key_fn, render_fn, fa
} }
} }
/** @type {import('../../types.js').EachItemBlock[]} */ /** @type {import('#client').EachItemBlock[]} */
var a_blocks = []; var a_blocks = [];
render_effect(() => { render_effect(() => {
@ -76,7 +81,7 @@ export function each_keyed(anchor_node, collection, flags, key_fn, render_fn, fa
/** @type {number} */ /** @type {number} */
var b = array.length; var b = array.length;
/** @type {Array<import('../../types.js').EachItemBlock>} */ /** @type {Array<import('#client').EachItemBlock>} */
var b_blocks; var b_blocks;
var a_end = a - 1; var a_end = a - 1;
@ -96,7 +101,7 @@ export function each_keyed(anchor_node, collection, flags, key_fn, render_fn, fa
if (hydrating) { if (hydrating) {
// Hydrate block // Hydrate block
var fragment; var fragment;
var hydration_list = /** @type {import('../../types.js').TemplateNode[]} */ ( var hydration_list = /** @type {import('#client').TemplateNode[]} */ (
current_hydration_fragment current_hydration_fragment
); );
var hydrating_node = hydration_list[0]; var hydrating_node = hydration_list[0];
@ -118,7 +123,7 @@ export function each_keyed(anchor_node, collection, flags, key_fn, render_fn, fa
// Get the <!--ssr:..--> tag of the next item in the list // Get the <!--ssr:..--> tag of the next item in the list
// The fragment array can be empty if each block has no content // The fragment array can be empty if each block has no content
hydrating_node = /** @type {import('../../types.js').TemplateNode} */ ( hydrating_node = /** @type {import('#client').TemplateNode} */ (
/** @type {Node} */ ((fragment.at(-1) || hydrating_node).nextSibling).nextSibling /** @type {Node} */ ((fragment.at(-1) || hydrating_node).nextSibling).nextSibling
); );
} }
@ -285,7 +290,7 @@ export function each_keyed(anchor_node, collection, flags, key_fn, render_fn, fa
* @param {Element | Comment} anchor_node * @param {Element | Comment} anchor_node
* @param {() => V[]} collection * @param {() => V[]} collection
* @param {number} flags * @param {number} flags
* @param {(anchor: Element | Comment | null, item: V | (() => V), index: import('../../types.js').MaybeSignal<number>) => void} render_fn * @param {(anchor: Element | Comment | null, item: V | (() => V), index: MaybeSignal<number>) => void} render_fn
* @param {null | ((anchor: Node) => void)} fallback_fn * @param {null | ((anchor: Node) => void)} fallback_fn
* @returns {void} * @returns {void}
*/ */
@ -310,10 +315,10 @@ export function each_indexed(anchor_node, collection, flags, render_fn, fallback
let length = 0; let length = 0;
/** @type {Array<import('../../types.js').Computation | null>} */ /** @type {Array<import('#client').Computation | null>} */
let effects = []; let effects = [];
/** @type {import('../../types.js').Computation | null} */ /** @type {import('#client').Computation | null} */
let alternate; let alternate;
function truncate() { function truncate() {
@ -398,8 +403,8 @@ export function each_indexed(anchor_node, collection, flags, render_fn, fallback
/** /**
* The server could have rendered more list items than the client specifies. * The server could have rendered more list items than the client specifies.
* In that case, we need to remove the remaining server-rendered nodes. * In that case, we need to remove the remaining server-rendered nodes.
* @param {import('../../types.js').TemplateNode[]} hydration_list * @param {import('#client').TemplateNode[]} hydration_list
* @param {import('../../types.js').TemplateNode | null} next_node * @param {import('#client').TemplateNode | null} next_node
*/ */
function remove_excess_hydration_nodes(hydration_list, next_node) { function remove_excess_hydration_nodes(hydration_list, next_node) {
if (next_node === null) return; if (next_node === null) return;
@ -483,14 +488,14 @@ function mark_lis(a) {
} }
/** /**
* @param {import('../../types.js').EachItemBlock} block * @param {import('#client').EachItemBlock} block
* @param {Element | Comment | Text} dom * @param {Element | Comment | Text} dom
* @param {boolean} is_controlled * @param {boolean} is_controlled
* @param {null | Text | Element | Comment} sibling * @param {null | Text | Element | Comment} sibling
* @returns {Text | Element | Comment} * @returns {Text | Element | Comment}
*/ */
function insert_each_item_block(block, dom, is_controlled, sibling) { function insert_each_item_block(block, dom, is_controlled, sibling) {
var current = /** @type {import('../../types.js').TemplateNode} */ (block.e.dom); var current = /** @type {import('#client').TemplateNode} */ (block.e.dom);
if (sibling === null) { if (sibling === null) {
if (is_controlled) { if (is_controlled) {
@ -504,7 +509,7 @@ function insert_each_item_block(block, dom, is_controlled, sibling) {
} }
/** /**
* @param {import('../../types.js').EachItemBlock} block * @param {import('#client').EachItemBlock} block
* @returns {Text | Element | Comment} * @returns {Text | Element | Comment}
*/ */
function get_first_child(block) { function get_first_child(block) {
@ -518,7 +523,7 @@ function get_first_child(block) {
} }
/** /**
* @param {import('../../types.js').EachItemBlock} block * @param {import('#client').EachItemBlock} block
* @returns {Text | Element | Comment} * @returns {Text | Element | Comment}
*/ */
export function get_first_element(block) { export function get_first_element(block) {
@ -537,7 +542,7 @@ export function get_first_element(block) {
} }
/** /**
* @param {import('../../types.js').EachItemBlock} block * @param {import('#client').EachItemBlock} block
* @param {any} item * @param {any} item
* @param {number} index * @param {number} index
* @param {number} type * @param {number} type
@ -558,7 +563,7 @@ function update_each_item_block(block, item, index, type) {
// each_animation(block, transitions); // each_animation(block, transitions);
} }
if (index_is_reactive) { if (index_is_reactive) {
set_signal_value(/** @type {import('../../types.js').Signal<number>} */ (block.i), index); set_signal_value(/** @type {import('#client').Signal<number>} */ (block.i), index);
} else { } else {
block.i = index; block.i = index;
} }
@ -569,9 +574,9 @@ function update_each_item_block(block, item, index, type) {
* @param {V} item * @param {V} item
* @param {unknown} key * @param {unknown} key
* @param {number} index * @param {number} index
* @param {(anchor: null, item: V, index: number | import('../../types.js').Signal<number>) => void} render_fn * @param {(anchor: null, item: V, index: number | import('#client').Signal<number>) => void} render_fn
* @param {number} flags * @param {number} flags
* @returns {import('../../types.js').EachItemBlock} * @returns {import('#client').EachItemBlock}
*/ */
function each_item_block(item, key, index, render_fn, flags) { function each_item_block(item, key, index, render_fn, flags) {
const each_item_not_reactive = (flags & EACH_ITEM_REACTIVE) === 0; const each_item_not_reactive = (flags & EACH_ITEM_REACTIVE) === 0;
@ -584,7 +589,7 @@ function each_item_block(item, key, index, render_fn, flags) {
const index_value = (flags & EACH_INDEX_REACTIVE) === 0 ? index : source(index); const index_value = (flags & EACH_INDEX_REACTIVE) === 0 ? index : source(index);
/** @type {import('../../types.js').EachItemBlock} */ /** @type {import('#client').EachItemBlock} */
const block = { const block = {
// @ts-expect-error // @ts-expect-error
e: null, e: null,

@ -11,7 +11,7 @@ export function html(anchor_node, get_value, svg) {
/** @type {string} */ /** @type {string} */
let value; let value;
/** @type {import('../../types.js').TemplateNode | import('../../types.js').TemplateNode[]} */ /** @type {import('#client').TemplateNode | import('#client').TemplateNode[]} */
let dom; let dom;
render_effect(() => { render_effect(() => {

@ -21,10 +21,10 @@ export function if_block(anchor_node, condition_fn, consequent_fn, alternate_fn)
/** Whether or not there was a hydration mismatch. Needs to be a `let` or else it isn't treeshaken out */ /** Whether or not there was a hydration mismatch. Needs to be a `let` or else it isn't treeshaken out */
let mismatch = false; let mismatch = false;
/** @type {import('../../types.js').EffectSignal | null} */ /** @type {import('#client').EffectSignal | null} */
let consequent_effect; let consequent_effect;
/** @type {import('../../types.js').EffectSignal | null} */ /** @type {import('#client').EffectSignal | null} */
let alternate_effect; let alternate_effect;
/** @type {boolean | null} */ /** @type {boolean | null} */

@ -16,7 +16,7 @@ export function key_block(anchor_node, get_key, render_fn) {
/** @type {V | typeof UNINITIALIZED} */ /** @type {V | typeof UNINITIALIZED} */
let key = UNINITIALIZED; let key = UNINITIALIZED;
/** @type {import('../../types.js').EffectSignal | null} */ /** @type {import('#client').EffectSignal | null} */
let effect; let effect;
render_effect(() => { render_effect(() => {

@ -9,7 +9,7 @@ import { untrack } from '../../runtime.js';
* @returns {void} * @returns {void}
*/ */
export function snippet_effect(get_snippet, node, ...args) { export function snippet_effect(get_snippet, node, ...args) {
/** @type {import('../../types.js').EffectSignal | null} */ /** @type {import('#client').EffectSignal | null} */
let effect; let effect;
render_effect(() => { render_effect(() => {

@ -15,7 +15,7 @@ export function component(anchor_node, component_fn, render_fn) {
/** @type {C | null} */ /** @type {C | null} */
let Component = null; let Component = null;
/** @type {import('../../types.js').Computation | null} */ /** @type {import('#client').Computation | null} */
let effect = null; let effect = null;
render_effect(() => { render_effect(() => {

@ -23,13 +23,13 @@ export function element(anchor_node, get_tag, is_svg, render_fn) {
/** @type {string} */ /** @type {string} */
let tag; let tag;
/** @type {import('../../types.js').BlockEffect | null} */ /** @type {import('#client').BlockEffect | null} */
let block; let block;
/** @type {Element | null} */ /** @type {Element | null} */
let element; let element;
/** @type {import('../../types.js').EffectSignal} */ /** @type {import('#client').EffectSignal} */
let branch; let branch;
branch = render_effect(() => { branch = render_effect(() => {

@ -30,7 +30,7 @@ import {
* @param {V} value * @param {V} value
*/ */
function create_computation_signal(flags, value) { function create_computation_signal(flags, value) {
/** @type {import('../types.js').Computation<V>} */ /** @type {import('#client').Computation<V>} */
const signal = { const signal = {
c: null, c: null,
d: null, d: null,
@ -55,8 +55,8 @@ function create_computation_signal(flags, value) {
} }
/** /**
* @param {import('../types.js').Computation} target_signal * @param {import('#client').Computation} target_signal
* @param {import('../types.js').Computation} ref_signal * @param {import('#client').Computation} ref_signal
* @returns {void} * @returns {void}
*/ */
export function push_reference(target_signal, ref_signal) { export function push_reference(target_signal, ref_signal) {
@ -73,7 +73,7 @@ export function push_reference(target_signal, ref_signal) {
* @param {(() => void | (() => void))} fn * @param {(() => void | (() => void))} fn
* @param {boolean} sync * @param {boolean} sync
* @param {boolean} schedule * @param {boolean} schedule
* @returns {import('../types.js').EffectSignal} * @returns {import('#client').EffectSignal}
*/ */
function internal_create_effect(type, fn, sync, schedule) { function internal_create_effect(type, fn, sync, schedule) {
const signal = create_computation_signal(type | DIRTY, null); const signal = create_computation_signal(type | DIRTY, null);
@ -99,7 +99,7 @@ export function effect_active() {
/** /**
* Internal representation of `$effect(...)` * Internal representation of `$effect(...)`
* @param {() => void | (() => void)} fn * @param {() => void | (() => void)} fn
* @returns {import('../types.js').EffectSignal} * @returns {import('#client').EffectSignal}
*/ */
export function user_effect(fn) { export function user_effect(fn) {
if (current_effect === null) { if (current_effect === null) {
@ -117,9 +117,7 @@ export function user_effect(fn) {
const effect = internal_create_effect(EFFECT, fn, false, !apply_component_effect_heuristics); const effect = internal_create_effect(EFFECT, fn, false, !apply_component_effect_heuristics);
if (apply_component_effect_heuristics) { if (apply_component_effect_heuristics) {
const context = /** @type {import('../types.js').ComponentContext} */ ( const context = /** @type {import('#client').ComponentContext} */ (current_component_context);
current_component_context
);
(context.e ??= []).push(effect); (context.e ??= []).push(effect);
} }
@ -140,7 +138,7 @@ export function user_root_effect(fn) {
/** /**
* @param {() => void | (() => void)} fn * @param {() => void | (() => void)} fn
* @returns {import('../types.js').EffectSignal} * @returns {import('#client').EffectSignal}
*/ */
export function effect(fn) { export function effect(fn) {
return internal_create_effect(EFFECT, fn, false, true); return internal_create_effect(EFFECT, fn, false, true);
@ -148,7 +146,7 @@ export function effect(fn) {
/** /**
* @param {() => void | (() => void)} fn * @param {() => void | (() => void)} fn
* @returns {import('../types.js').EffectSignal} * @returns {import('#client').EffectSignal}
*/ */
export function managed_effect(fn) { export function managed_effect(fn) {
return internal_create_effect(EFFECT | MANAGED, fn, false, true); return internal_create_effect(EFFECT | MANAGED, fn, false, true);
@ -157,7 +155,7 @@ export function managed_effect(fn) {
/** /**
* @param {() => void | (() => void)} fn * @param {() => void | (() => void)} fn
* @param {boolean} sync * @param {boolean} sync
* @returns {import('../types.js').EffectSignal} * @returns {import('#client').EffectSignal}
*/ */
export function managed_pre_effect(fn, sync) { export function managed_pre_effect(fn, sync) {
return internal_create_effect(PRE_EFFECT | MANAGED, fn, sync, true); return internal_create_effect(PRE_EFFECT | MANAGED, fn, sync, true);
@ -166,7 +164,7 @@ export function managed_pre_effect(fn, sync) {
/** /**
* Internal representation of `$effect.pre(...)` * Internal representation of `$effect.pre(...)`
* @param {() => void | (() => void)} fn * @param {() => void | (() => void)} fn
* @returns {import('../types.js').EffectSignal} * @returns {import('#client').EffectSignal}
*/ */
export function pre_effect(fn) { export function pre_effect(fn) {
if (current_effect === null) { if (current_effect === null) {
@ -195,7 +193,7 @@ export function pre_effect(fn) {
* bindings which are in later effects. However, we don't use a pre_effect directly as we don't want to flush anything. * bindings which are in later effects. However, we don't use a pre_effect directly as we don't want to flush anything.
* *
* @param {() => void | (() => void)} fn * @param {() => void | (() => void)} fn
* @returns {import('../types.js').EffectSignal} * @returns {import('#client').EffectSignal}
*/ */
export function invalidate_effect(fn) { export function invalidate_effect(fn) {
return internal_create_effect(PRE_EFFECT, fn, true, true); return internal_create_effect(PRE_EFFECT, fn, true, true);
@ -205,7 +203,7 @@ export function invalidate_effect(fn) {
* @param {() => void | (() => void)} fn * @param {() => void | (() => void)} fn
* @param {boolean} managed * @param {boolean} managed
* @param {boolean} sync * @param {boolean} sync
* @returns {import('../types.js').EffectSignal} * @returns {import('#client').EffectSignal}
*/ */
export function render_effect(fn, managed = false, sync = true) { export function render_effect(fn, managed = false, sync = true) {
let flags = RENDER_EFFECT; let flags = RENDER_EFFECT;
@ -218,13 +216,13 @@ export function render_effect(fn, managed = false, sync = true) {
/** /**
* @template V * @template V
* @param {() => V} fn * @param {() => V} fn
* @returns {import('../types.js').Computation<V>} * @returns {import('#client').Computation<V>}
*/ */
/*#__NO_SIDE_EFFECTS__*/ /*#__NO_SIDE_EFFECTS__*/
export function derived(fn) { export function derived(fn) {
const is_unowned = current_effect === null; const is_unowned = current_effect === null;
const flags = is_unowned ? DERIVED | UNOWNED : DERIVED; const flags = is_unowned ? DERIVED | UNOWNED : DERIVED;
const signal = /** @type {import('../types.js').Computation<V>} */ ( const signal = /** @type {import('#client').Computation<V>} */ (
create_computation_signal(flags | CLEAN, UNINITIALIZED) create_computation_signal(flags | CLEAN, UNINITIALIZED)
); );
signal.i = fn; signal.i = fn;
@ -238,7 +236,7 @@ export function derived(fn) {
/** /**
* @template V * @template V
* @param {() => V} fn * @param {() => V} fn
* @returns {import('../types.js').Computation<V>} * @returns {import('#client').Computation<V>}
*/ */
/*#__NO_SIDE_EFFECTS__*/ /*#__NO_SIDE_EFFECTS__*/
export function derived_safe_equal(fn) { export function derived_safe_equal(fn) {
@ -248,11 +246,11 @@ export function derived_safe_equal(fn) {
} }
/** /**
* @param {import('../types.js').Computation} effect * @param {import('#client').Computation} effect
* @param {() => void} done * @param {() => void} done
*/ */
export function pause_effect(effect, done) { export function pause_effect(effect, done) {
/** @type {import('../types.js').TransitionObject[]} */ /** @type {import('#client').Transition[]} */
const transitions = []; const transitions = [];
pause_children(effect, transitions, true); pause_children(effect, transitions, true);
@ -277,8 +275,8 @@ export function pause_effect(effect, done) {
} }
/** /**
* @param {import('../types.js').BlockEffect} effect * @param {import('#client').BlockEffect} effect
* @param {import('../types.js').TransitionObject[]} transitions * @param {import('#client').Transition[]} transitions
* @param {boolean} local * @param {boolean} local
*/ */
function pause_children(effect, transitions, local) { function pause_children(effect, transitions, local) {
@ -305,7 +303,7 @@ function pause_children(effect, transitions, local) {
} }
/** /**
* @param {import('../types.js').BlockEffect} effect TODO this isn't just block effects, it's deriveds etc too * @param {import('#client').BlockEffect} effect TODO this isn't just block effects, it's deriveds etc too
*/ */
export function destroy_effect(effect) { export function destroy_effect(effect) {
if ((effect.f & DESTROYED) !== 0) return; if ((effect.f & DESTROYED) !== 0) return;
@ -328,19 +326,19 @@ export function destroy_effect(effect) {
} }
/** /**
* @param {import('../types.js').BlockEffect} effect * @param {import('#client').BlockEffect} effect
*/ */
export function resume_effect(effect) { export function resume_effect(effect) {
resume_children(effect, true); resume_children(effect, true);
} }
/** /**
* @param {import('../types.js').BlockEffect} effect * @param {import('#client').BlockEffect} effect
* @param {boolean} local * @param {boolean} local
*/ */
function resume_children(effect, local) { function resume_children(effect, local) {
if ((effect.f & DERIVED) === 0 && (effect.f & MANAGED) === 0) { if ((effect.f & DERIVED) === 0 && (effect.f & MANAGED) === 0) {
execute_effect(/** @type {import('../types.js').EffectSignal} */ (effect)); execute_effect(/** @type {import('#client').EffectSignal} */ (effect));
} }
if (effect.r) { if (effect.r) {

@ -10,13 +10,13 @@ import { mutable_source } from './sources.js';
* signal that will be updated when the store is. The store references container is needed to * signal that will be updated when the store is. The store references container is needed to
* track reassignments to stores and to track the correct component context. * track reassignments to stores and to track the correct component context.
* @template V * @template V
* @param {import('../types.js').Store<V> | null | undefined} store * @param {import('#client').Store<V> | null | undefined} store
* @param {string} store_name * @param {string} store_name
* @param {import('../types.js').StoreReferencesContainer} stores * @param {import('#client').StoreReferencesContainer} stores
* @returns {V} * @returns {V}
*/ */
export function store_get(store, store_name, stores) { export function store_get(store, store_name, stores) {
/** @type {import('../types.js').StoreReferencesContainer[''] | undefined} */ /** @type {import('#client').StoreReferencesContainer[''] | undefined} */
let entry = stores[store_name]; let entry = stores[store_name];
const is_new = entry === undefined; const is_new = entry === undefined;
@ -29,8 +29,8 @@ export function store_get(store, store_name, stores) {
}; };
// TODO: can we remove this code? it was refactored out when we split up source/comptued signals // TODO: can we remove this code? it was refactored out when we split up source/comptued signals
// push_destroy_fn(entry.value, () => { // push_destroy_fn(entry.value, () => {
// /** @type {import('../types.js').StoreReferencesContainer['']} */ (entry).last_value = // /** @type {import('#client').StoreReferencesContainer['']} */ (entry).last_value =
// /** @type {import('../types.js').StoreReferencesContainer['']} */ (entry).value.value; // /** @type {import('#client').StoreReferencesContainer['']} */ (entry).value.value;
// }); // });
stores[store_name] = entry; stores[store_name] = entry;
} }
@ -49,7 +49,7 @@ export function store_get(store, store_name, stores) {
/** /**
* @template V * @template V
* @param {import('../types.js').Store<V> | null | undefined} store * @param {import('#client').Store<V> | null | undefined} store
* @param {import('./types.js').Source<V>} source * @param {import('./types.js').Source<V>} source
*/ */
function connect_store_to_signal(store, source) { function connect_store_to_signal(store, source) {
@ -70,7 +70,7 @@ function connect_store_to_signal(store, source) {
/** /**
* Sets the new value of a store and returns that value. * Sets the new value of a store and returns that value.
* @template V * @template V
* @param {import('../types.js').Store<V>} store * @param {import('#client').Store<V>} store
* @param {V} value * @param {V} value
* @returns {V} * @returns {V}
*/ */
@ -81,7 +81,7 @@ export function store_set(store, value) {
/** /**
* Unsubscribes from all auto-subscribed stores on destroy * Unsubscribes from all auto-subscribed stores on destroy
* @param {import('../types.js').StoreReferencesContainer} stores * @param {import('#client').StoreReferencesContainer} stores
*/ */
export function unsubscribe_on_destroy(stores) { export function unsubscribe_on_destroy(stores) {
on_destroy(() => { on_destroy(() => {
@ -97,7 +97,7 @@ export function unsubscribe_on_destroy(stores) {
/** /**
* Updates a store with a new value. * Updates a store with a new value.
* @param {import('../types.js').Store<V>} store the store to update * @param {import('#client').Store<V>} store the store to update
* @param {any} expression the expression that mutates the store * @param {any} expression the expression that mutates the store
* @param {V} new_value the new store value * @param {V} new_value the new store value
* @template V * @template V
@ -110,18 +110,18 @@ export function mutate_store(store, expression, new_value) {
/** /**
* @template V * @template V
* @param {unknown} val * @param {unknown} val
* @returns {val is import('../types.js').Store<V>} * @returns {val is import('#client').Store<V>}
*/ */
export function is_store(val) { export function is_store(val) {
return ( return (
typeof val === 'object' && typeof val === 'object' &&
val !== null && val !== null &&
typeof (/** @type {import('../types.js').Store<V>} */ (val).subscribe) === 'function' typeof (/** @type {import('#client').Store<V>} */ (val).subscribe) === 'function'
); );
} }
/** /**
* @param {import('../types.js').Store<number>} store * @param {import('#client').Store<number>} store
* @param {number} store_value * @param {number} store_value
* @param {1 | -1} [d] * @param {1 | -1} [d]
* @returns {number} * @returns {number}
@ -132,7 +132,7 @@ export function update_store(store, store_value, d = 1) {
} }
/** /**
* @param {import('../types.js').Store<number>} store * @param {import('#client').Store<number>} store
* @param {number} store_value * @param {number} store_value
* @param {1 | -1} [d] * @param {1 | -1} [d]
* @returns {number} * @returns {number}

@ -1,5 +1,5 @@
import type { DERIVED, EFFECT, PRE_EFFECT, RENDER_EFFECT, SOURCE } from '../constants'; import type { DERIVED, EFFECT, PRE_EFFECT, RENDER_EFFECT, SOURCE } from '../constants';
import type { Computation, EqualsFunctions } from '../types'; import type { ComponentContext, EqualsFunctions, TemplateNode, Transition } from '../types';
export type SignalFlags = export type SignalFlags =
| typeof SOURCE | typeof SOURCE
@ -27,3 +27,42 @@ export type SourceDebug = {
/** This is DEV only */ /** This is DEV only */
inspect: Set<Function>; inspect: Set<Function>;
}; };
export type Computation<V = unknown> = {
/** consumers: Signals that read from the current signal */
c: null | Computation[];
/** context: The associated component if this signal is an effect/computed */
x: null | ComponentContext;
/** dependencies: Signals that this signal reads from */
d: null | Signal<V>[];
/** destroy: Thing(s) that need destroying */
y: null | (() => void) | Array<() => void>;
/** equals: For value equality */
e: null | EqualsFunctions;
/** The types that the signal represent, as a bitwise value */
f: SignalFlags;
/** init: The function that we invoke for effects and computeds */
i: null | (() => V) | (() => void | (() => void)) | ((b: null, s: Signal) => void | (() => void));
/** references: Anything that a signal owns */
r: null | Computation[];
/** value: The latest value for this signal, doubles as the teardown for effects */
v: V;
/** level: the depth from the root signal, used for ordering render/pre-effects topologically **/
l: number;
/** write version: used for unowned signals to track if their depdendencies are dirty or not **/
w: number;
parent: Signal | null;
};
export type BlockEffect<V = unknown> = Computation<V> & {
in?: Transition[];
out?: Transition[];
dom?: TemplateNode | Array<TemplateNode>;
ran?: boolean;
};
export type Signal<V = unknown> = Source<V> | Computation<V>;
export type SignalDebug<V = unknown> = SourceDebug & Signal<V>;
export type EffectSignal = Computation<null | (() => void)>;

@ -1291,8 +1291,8 @@ export function inspect(get_value, inspect = console.log) {
/** /**
* @template V * @template V
* @param {V} value * @param {import('#client').Signal<V> | (() => V)} value
* @returns {import('./types.js').UnwrappedSignal<V>} * @returns {V}
*/ */
export function unwrap(value) { export function unwrap(value) {
// temporary! // temporary!

@ -263,7 +263,7 @@ export function bind_transition(element, get_fn, get_params, direction, global)
let current_delta = 0; let current_delta = 0;
/** @type {import('./types.js').TransitionObject} */ /** @type {import('./types.js').Transition} */
const transition = { const transition = {
global, global,
to(target, callback) { to(target, callback) {

@ -1,5 +1,7 @@
import { STATE_SYMBOL } from './constants.js'; import { STATE_SYMBOL } from './constants.js';
import type { SignalFlags, Source, SourceDebug } from './reactivity/types.js'; import type { Computation, EffectSignal, Signal, Source } from './reactivity/types.js';
export * from './reactivity/types.js';
type EventCallback = (event: Event) => boolean; type EventCallback = (event: Event) => boolean;
export type EventCallbackMap = Record<string, EventCallback | EventCallback[]>; export type EventCallbackMap = Record<string, EventCallback | EventCallback[]>;
@ -41,80 +43,10 @@ export type ComponentContext = {
}; };
}; };
// We keep two shapes rather than a single monomorphic shape to improve the memory usage.
// Source signals don't need the same shape as they simply don't do as much as computations
// (effects and derived signals). Thus we can improve the memory profile at the slight cost
// of some runtime performance.
export type Computation<V = unknown> = {
/** consumers: Signals that read from the current signal */
c: null | Computation[];
/** context: The associated component if this signal is an effect/computed */
x: null | ComponentContext;
/** dependencies: Signals that this signal reads from */
d: null | Signal<V>[];
/** destroy: Thing(s) that need destroying */
y: null | (() => void) | Array<() => void>;
/** equals: For value equality */
e: null | EqualsFunctions;
/** The types that the signal represent, as a bitwise value */
f: SignalFlags;
/** init: The function that we invoke for effects and computeds */
i: null | (() => V) | (() => void | (() => void)) | ((b: null, s: Signal) => void | (() => void));
/** references: Anything that a signal owns */
r: null | Computation[];
/** value: The latest value for this signal, doubles as the teardown for effects */
v: V;
/** level: the depth from the root signal, used for ordering render/pre-effects topologically **/
l: number;
/** write version: used for unowned signals to track if their depdendencies are dirty or not **/
w: number;
parent: Signal | null;
};
export type BlockEffect<V = unknown> = Computation<V> & {
in?: TransitionObject[];
out?: TransitionObject[];
dom?: TemplateNode | Array<TemplateNode>;
ran?: boolean;
};
export type Signal<V = unknown> = Source<V> | Computation<V>;
export type SignalDebug<V = unknown> = SourceDebug & Signal<V>;
export type EffectSignal = Computation<null | (() => void)>;
export type MaybeSignal<T = unknown> = T | Signal<T>;
export type UnwrappedSignal<T> = T extends Signal<infer U> ? U : T;
export type EqualsFunctions<T = any> = (a: T, v: T) => boolean; export type EqualsFunctions<T = any> = (a: T, v: T) => boolean;
export type TemplateNode = Text | Element | Comment; export type TemplateNode = Text | Element | Comment;
export type Transition = {
/** effect */
e: EffectSignal;
/** payload */
p: null | TransitionPayload;
/** init */
i: (from?: DOMRect) => TransitionPayload;
/** finished */
f: (fn: () => void) => void;
in: () => void;
/** out */
o: () => void;
/** cancel */
c: () => void;
/** cleanup */
x: () => void;
/** direction */
r: 'in' | 'out' | 'both' | 'key';
/** dom */
d: HTMLElement;
};
export type EachItemBlock = { export type EachItemBlock = {
/** effect */ /** effect */
e: Computation; e: Computation;
@ -159,17 +91,6 @@ export type StoreReferencesContainer = Record<
export type ActionPayload<P> = { destroy?: () => void; update?: (value: P) => void }; export type ActionPayload<P> = { destroy?: () => void; update?: (value: P) => void };
export type Render = {
/** dom */
d: null | TemplateNode | Array<TemplateNode>;
/** effect */
e: null | EffectSignal;
/** transitions */
s: Set<Transition>;
/** prev */
p: Render | null;
};
export type Raf = { export type Raf = {
tick: (callback: (time: DOMHighResTimeStamp) => void) => any; tick: (callback: (time: DOMHighResTimeStamp) => void) => any;
now: () => number; now: () => number;
@ -207,7 +128,7 @@ export type ProxyStateObject<T = Record<string | symbol, any>> = T & {
// TODO remove the other transition types once we're // TODO remove the other transition types once we're
// happy we don't need them, and rename this // happy we don't need them, and rename this
export interface TransitionObject { export interface Transition {
global: boolean; global: boolean;
to(target: number, callback?: () => void): void; to(target: number, callback?: () => void): void;
} }

@ -7,7 +7,7 @@ import {
user_effect user_effect
} from '../../src/internal/client/reactivity/computations'; } from '../../src/internal/client/reactivity/computations';
import { source } from '../../src/internal/client/reactivity/sources'; import { source } from '../../src/internal/client/reactivity/sources';
import type { Computation } from '../../src/internal/client/types'; import type { Computation } from '../../src/internal/client/reactivity/types';
import { proxy } from '../../src/internal/client/proxy'; import { proxy } from '../../src/internal/client/proxy';
/** /**

@ -24,7 +24,8 @@
"svelte/motion": ["./src/motion/public.d.ts"], "svelte/motion": ["./src/motion/public.d.ts"],
"svelte/server": ["./src/server/index.js"], "svelte/server": ["./src/server/index.js"],
"svelte/store": ["./src/store/public.d.ts"], "svelte/store": ["./src/store/public.d.ts"],
"#compiler": ["./src/compiler/types/index.d.ts"] "#compiler": ["./src/compiler/types/index.d.ts"],
"#client": ["./src/internal/client/types.d.ts"]
} }
}, },
"include": [ "include": [

Loading…
Cancel
Save