mirror of https://github.com/sveltejs/svelte
chore: move reactivity code around (#10696)
* move some code * split computations.js into deriveds.js and effects.js * move reactivity types into separate .d.ts file * move some signal code --------- Co-authored-by: Rich Harris <rich.harris@vercel.com>pull/10697/head
parent
2d15c9de3f
commit
aa29a853dd
@ -0,0 +1,36 @@
|
|||||||
|
import { CLEAN, DERIVED, UNINITIALIZED, UNOWNED } from '../constants.js';
|
||||||
|
import { current_block, current_consumer, current_effect } from '../runtime.js';
|
||||||
|
import { create_computation_signal, push_reference } from './effects.js';
|
||||||
|
import { default_equals, safe_equal } from './equality.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @template V
|
||||||
|
* @param {() => V} fn
|
||||||
|
* @returns {import('../types.js').ComputationSignal<V>}
|
||||||
|
*/
|
||||||
|
/*#__NO_SIDE_EFFECTS__*/
|
||||||
|
export function derived(fn) {
|
||||||
|
const is_unowned = current_effect === null;
|
||||||
|
const flags = is_unowned ? DERIVED | UNOWNED : DERIVED;
|
||||||
|
const signal = /** @type {import('../types.js').ComputationSignal<V>} */ (
|
||||||
|
create_computation_signal(flags | CLEAN, UNINITIALIZED, current_block)
|
||||||
|
);
|
||||||
|
signal.i = fn;
|
||||||
|
signal.e = default_equals;
|
||||||
|
if (current_consumer !== null) {
|
||||||
|
push_reference(current_consumer, signal);
|
||||||
|
}
|
||||||
|
return signal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @template V
|
||||||
|
* @param {() => V} fn
|
||||||
|
* @returns {import('../types.js').ComputationSignal<V>}
|
||||||
|
*/
|
||||||
|
/*#__NO_SIDE_EFFECTS__*/
|
||||||
|
export function derived_safe_equal(fn) {
|
||||||
|
const signal = derived(fn);
|
||||||
|
signal.e = safe_equal;
|
||||||
|
return signal;
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
/**
|
||||||
|
* @param {((value?: number) => number)} fn
|
||||||
|
* @param {1 | -1} [d]
|
||||||
|
* @returns {number}
|
||||||
|
*/
|
||||||
|
export function update_prop(fn, d = 1) {
|
||||||
|
const value = fn();
|
||||||
|
fn(value + d);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {((value?: number) => number)} fn
|
||||||
|
* @param {1 | -1} [d]
|
||||||
|
* @returns {number}
|
||||||
|
*/
|
||||||
|
export function update_pre_prop(fn, d = 1) {
|
||||||
|
const value = fn() + d;
|
||||||
|
fn(value);
|
||||||
|
return value;
|
||||||
|
}
|
@ -0,0 +1,74 @@
|
|||||||
|
import type { Block, ComponentContext, EqualsFunctions } from '#client';
|
||||||
|
import type { DERIVED, EFFECT, PRE_EFFECT, RENDER_EFFECT, SOURCE } from '../constants';
|
||||||
|
|
||||||
|
export type SignalFlags =
|
||||||
|
| typeof SOURCE
|
||||||
|
| typeof DERIVED
|
||||||
|
| typeof EFFECT
|
||||||
|
| typeof PRE_EFFECT
|
||||||
|
| typeof RENDER_EFFECT;
|
||||||
|
export type EffectType = typeof EFFECT | typeof PRE_EFFECT | typeof RENDER_EFFECT;
|
||||||
|
|
||||||
|
// 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 SourceSignal<V = unknown> = {
|
||||||
|
/** consumers: Signals that read from the current signal */
|
||||||
|
c: null | ComputationSignal[];
|
||||||
|
/** equals: For value equality */
|
||||||
|
e: null | EqualsFunctions;
|
||||||
|
/** flags: The types that the signal represent, as a bitwise value */
|
||||||
|
f: SignalFlags;
|
||||||
|
/** value: The latest value for this signal */
|
||||||
|
v: V;
|
||||||
|
// write version
|
||||||
|
w: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type SourceSignalDebug = {
|
||||||
|
/** This is DEV only */
|
||||||
|
inspect: Set<Function>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ComputationSignal<V = unknown> = {
|
||||||
|
/** block: The block associated with this effect/computed */
|
||||||
|
b: null | Block;
|
||||||
|
/** consumers: Signals that read from the current signal */
|
||||||
|
c: null | ComputationSignal[];
|
||||||
|
/** 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: Block, s: Signal) => void | (() => void));
|
||||||
|
/** references: Anything that a signal owns */
|
||||||
|
r: null | ComputationSignal[];
|
||||||
|
/** 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;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type Signal<V = unknown> = SourceSignal<V> | ComputationSignal<V>;
|
||||||
|
|
||||||
|
export type SignalDebug<V = unknown> = SourceSignalDebug & Signal<V>;
|
||||||
|
|
||||||
|
export type EffectSignal = ComputationSignal<null | (() => void)>;
|
||||||
|
|
||||||
|
export type MaybeSignal<T = unknown> = T | Signal<T>;
|
||||||
|
|
||||||
|
export type UnwrappedSignal<T> = T extends Signal<infer U> ? U : T;
|
Loading…
Reference in new issue