e prop for sources

async-another-try
Simon Holthausen 6 days ago
parent 91d215664f
commit 31524c792e
No known key found for this signature in database

@ -1,4 +1,4 @@
/** @import { Derived, Reaction, Value } from '#client' */ /** @import { Derived, Reaction, Source, Value } from '#client' */
import { UNINITIALIZED } from '../../../constants.js'; import { UNINITIALIZED } from '../../../constants.js';
import { snapshot } from '../../shared/clone.js'; import { snapshot } from '../../shared/clone.js';
import { DERIVED, ASYNC, PROXY_PATH_SYMBOL, STATE_SYMBOL } from '#client/constants'; import { DERIVED, ASYNC, PROXY_PATH_SYMBOL, STATE_SYMBOL } from '#client/constants';
@ -131,8 +131,10 @@ export function trace(label, fn) {
} }
/** /**
* @param {Value} source * @template {Value} T
* @param {T} source
* @param {string} label * @param {string} label
* @returns {T}
*/ */
export function tag(source, label) { export function tag(source, label) {
source.label = label; source.label = label;

@ -110,9 +110,6 @@ export class Boundary {
/** @type {Set<Derived>} */ /** @type {Set<Derived>} */
#dirty_deriveds = new Set(); #dirty_deriveds = new Set();
/** @type {Set<Derived>} */
#maybe_dirty_deriveds = new Set();
/** /**
* A source containing the number of pending async deriveds/expressions. * A source containing the number of pending async deriveds/expressions.
* Only created if `$effect.pending()` is used inside the boundary, * Only created if `$effect.pending()` is used inside the boundary,
@ -341,12 +338,7 @@ export class Boundary {
// any effects that were previously deferred should be transferred // any effects that were previously deferred should be transferred
// to the batch, which will flush in the next microtask // to the batch, which will flush in the next microtask
batch.transfer_effects( batch.transfer_effects(this.#dirty_effects, this.#maybe_dirty_effects, this.#dirty_deriveds);
this.#dirty_effects,
this.#maybe_dirty_effects,
this.#dirty_deriveds,
this.#maybe_dirty_deriveds
);
} }
/** /**
@ -354,13 +346,7 @@ export class Boundary {
* @param {Effect} effect * @param {Effect} effect
*/ */
defer_effect(effect) { defer_effect(effect) {
defer_effect( defer_effect(effect, this.#dirty_effects, this.#maybe_dirty_effects, this.#dirty_deriveds);
effect,
this.#dirty_effects,
this.#maybe_dirty_effects,
this.#dirty_deriveds,
this.#maybe_dirty_deriveds
);
} }
/** /**

@ -666,7 +666,7 @@ function reconcile(state, array, anchor, flags, get_key) {
* @param {V} value * @param {V} value
* @param {unknown} key * @param {unknown} key
* @param {number} index * @param {number} index
* @param {(anchor: Node, item: V | Source<V>, index: number | Value<number>, collection: () => V[]) => void} render_fn * @param {(anchor: Node, item: MaybeSource<V>, index: MaybeSource<number>, collection: () => V[]) => void} render_fn
* @param {number} flags * @param {number} flags
* @param {() => V[]} get_collection * @param {() => V[]} get_collection
* @returns {EachItem} * @returns {EachItem}

@ -827,7 +827,7 @@ export class Batch {
* Tell a fork batch that a source has been updated. Will delete that source from the fork, * Tell a fork batch that a source has been updated. Will delete that source from the fork,
* discarding it if it has no other sources left, and rerunning it else with the new value. * discarding it if it has no other sources left, and rerunning it else with the new value.
* @param {Batch} batch A fork * @param {Batch} batch A fork
* @param {Source} source * @param {Value} source
* @param {boolean} is_derived * @param {boolean} is_derived
* @param {any} value * @param {any} value
*/ */
@ -844,7 +844,7 @@ export class Batch {
(!current || current[0] !== value) && (!current || current[0] !== value) &&
((source.f & ASYNC) === 0 || ((source.f & ASYNC) === 0 ||
!depends_on( !depends_on(
source.e, /** @type {Effect} */ (/** @type {Source} */ (source).e),
[...batch.current.keys()].filter((s) => !this.current.has(s)), [...batch.current.keys()].filter((s) => !this.current.has(s)),
new Map() new Map()
)) ))
@ -1283,7 +1283,7 @@ function mark_eager_effects(value, effects) {
/** /**
* @param {Reaction} reaction * @param {Reaction} reaction
* @param {Source[]} sources * @param {Value[]} sources
* @param {Map<Reaction, boolean>} checked * @param {Map<Reaction, boolean>} checked
*/ */
function depends_on(reaction, sources, checked) { function depends_on(reaction, sources, checked) {

@ -139,7 +139,7 @@ export function async_derived(fn, label, location) {
if (DEV) { if (DEV) {
reactivity_loss_tracker = { effect, effect_deps: new Set(), warned: false }; reactivity_loss_tracker = { effect, effect_deps: new Set(), warned: false };
effect.label ??= label ?? fn.toString(); // effect.label ??= label ?? fn.toString(); // TODO add dev time labeling for effects in follow-up PR
} }
/** @type {ReturnType<typeof deferred<V>>} */ /** @type {ReturnType<typeof deferred<V>>} */

@ -47,7 +47,7 @@ import { set_signal_status, update_derived_status } from './status.js';
/** @type {Set<Effect>} */ /** @type {Set<Effect>} */
export let eager_effects = new Set(); export let eager_effects = new Set();
/** @type {Map<Source, any>} */ /** @type {Map<Value, any>} */
export const old_values = new Map(); export const old_values = new Map();
/** /**
@ -71,14 +71,15 @@ export function set_eager_effects_deferred() {
*/ */
// TODO rename this to `state` throughout the codebase // TODO rename this to `state` throughout the codebase
export function source(v, stack) { export function source(v, stack) {
/** @type {Value} */ /** @type {Source} */
var signal = { var signal = {
f: 0, // TODO ideally we could skip this altogether, but it causes type errors f: 0,
v, v,
reactions: null, reactions: null,
equals, equals,
rv: 0, rv: 0,
wv: 0 wv: 0,
e: null
}; };
if (DEV && tracing_mode_flag) { if (DEV && tracing_mode_flag) {
@ -142,7 +143,7 @@ export function mutate(source, value) {
/** /**
* @template V * @template V
* @param {Source<V>} source * @param {Value<V>} source
* @param {V} value * @param {V} value
* @param {boolean} [should_proxy] * @param {boolean} [should_proxy]
* @returns {V} * @returns {V}
@ -182,7 +183,7 @@ var count_deps = 0;
/** /**
* @template V * @template V
* @param {Source<V>} source * @param {Value<V>} source
* @param {V} value * @param {V} value
* @param {Effect[] | null} [updated_during_traversal] * @param {Effect[] | null} [updated_during_traversal]
* @returns {V} * @returns {V}

@ -100,7 +100,10 @@ export interface Effect extends Reaction {
dev_stack?: DevStackEntry | null; dev_stack?: DevStackEntry | null;
} }
export type Source<V = unknown> = Value<V>; export interface Source<V = unknown> extends Value<V> {
/** Only set for ASYNC signals - the corresponding effect that writes to this source */
e: Effect | null;
}
export type MaybeSource<T = unknown> = T | Source<T>; export type MaybeSource<T = unknown> = T | Source<T>;

@ -96,9 +96,9 @@ export function set_active_effect(effect) {
} }
/** /**
* When sources are created within a reaction, reading and writing * When sources/deriveds are created within a reaction, reading and writing
* them within that reaction should not cause a re-run * them within that reaction should not cause a re-run
* @type {null | Set<Source>} * @type {null | Set<Value>}
*/ */
export let current_sources = null; export let current_sources = null;
@ -126,11 +126,11 @@ export let skipped_deps = 0;
/** /**
* Tracks writes that the effect it's executed in doesn't listen to yet, * Tracks writes that the effect it's executed in doesn't listen to yet,
* so that the dependency can be added to the effect later on if it then reads it * so that the dependency can be added to the effect later on if it then reads it
* @type {null | Source[]} * @type {null | Value[]}
*/ */
export let untracked_writes = null; export let untracked_writes = null;
/** @param {null | Source[]} value */ /** @param {null | Value[]} value */
export function set_untracked_writes(value) { export function set_untracked_writes(value) {
untracked_writes = value; untracked_writes = value;
} }

@ -1,4 +1,4 @@
/** @import { Source } from '#client' */ /** @import { Derived } from '#client' */
import { derived } from '../internal/client/index.js'; import { derived } from '../internal/client/index.js';
import { set, state } from '../internal/client/reactivity/sources.js'; import { set, state } from '../internal/client/reactivity/sources.js';
import { tag } from '../internal/client/dev/tracing.js'; import { tag } from '../internal/client/dev/tracing.js';
@ -42,7 +42,7 @@ var inited = false;
export class SvelteDate extends Date { export class SvelteDate extends Date {
#time = state(super.getTime()); #time = state(super.getTime());
/** @type {Map<keyof Date, Source<unknown>>} */ /** @type {Map<keyof Date, Derived<unknown>>} */
#deriveds = new Map(); #deriveds = new Map();
#reaction = active_reaction; #reaction = active_reaction;

Loading…
Cancel
Save