blockless
Rich Harris 1 year ago
parent 530fd650c3
commit d109adcaea

@ -1,7 +1,6 @@
import { DEV } from 'esm-env'; import { DEV } from 'esm-env';
import { CLEAN, DERIVED, UNINITIALIZED, UNOWNED } from '../constants.js'; import { CLEAN, DERIVED, UNINITIALIZED, UNOWNED } from '../constants.js';
import { current_consumer, current_effect } from '../runtime.js'; import { current_consumer, current_effect } from '../runtime.js';
import { push_reference } from './utils.js';
import { default_equals, safe_equal } from './equality.js'; import { default_equals, safe_equal } from './equality.js';
/** /**
@ -11,15 +10,15 @@ import { default_equals, safe_equal } from './equality.js';
*/ */
/*#__NO_SIDE_EFFECTS__*/ /*#__NO_SIDE_EFFECTS__*/
export function derived(fn) { export function derived(fn) {
const is_unowned = current_effect === null; let flags = DERIVED | CLEAN;
const flags = is_unowned ? DERIVED | UNOWNED : DERIVED; if (current_effect === null) flags |= UNOWNED;
/** @type {import('#client').Derived<V>} */ /** @type {import('#client').Derived<V>} */
const signal = { const signal = {
c: null, c: null,
d: null, d: null,
e: default_equals, e: default_equals,
f: flags | CLEAN, f: flags,
i: fn, i: fn,
r: null, r: null,
// @ts-expect-error // @ts-expect-error
@ -35,7 +34,11 @@ export function derived(fn) {
} }
if (current_consumer !== null) { if (current_consumer !== null) {
push_reference(current_consumer, signal); if (current_consumer.r === null) {
current_consumer.r = [signal];
} else {
current_consumer.r.push(signal);
}
} }
return signal; return signal;

@ -18,7 +18,6 @@ import {
ROOT_EFFECT, ROOT_EFFECT,
DESTROYED DESTROYED
} from '../constants.js'; } from '../constants.js';
import { push_reference } from './utils.js';
/** /**
* @param {import('./types.js').EffectType} type * @param {import('./types.js').EffectType} type
@ -45,7 +44,8 @@ function create_effect(type, fn, sync, schedule) {
out: null, out: null,
dom: null, dom: null,
ran: false, ran: false,
parent: current_effect parent: current_effect,
children: null
}; };
if (DEV) { if (DEV) {
@ -55,7 +55,12 @@ function create_effect(type, fn, sync, schedule) {
if (current_effect !== null) { if (current_effect !== null) {
signal.l = current_effect.l + 1; signal.l = current_effect.l + 1;
push_reference(current_effect, signal);
if (current_effect.children === null) {
current_effect.children = [signal];
} else {
current_effect.children.push(signal);
}
} }
if (schedule) { if (schedule) {
@ -240,8 +245,8 @@ function pause_children(effect, transitions, local) {
} }
} }
if (effect.r) { if (effect.children) {
for (const child of effect.r) { for (const child of effect.children) {
pause_children(child, transitions, false); // TODO separate child effects from child deriveds pause_children(child, transitions, false); // TODO separate child effects from child deriveds
} }
} }
@ -263,8 +268,8 @@ export function destroy_effect(effect) {
remove(effect.dom); remove(effect.dom);
} }
if (effect.r) { if (effect.children) {
for (const child of effect.r) { for (const child of effect.children) {
destroy_effect(child); destroy_effect(child);
} }
} }
@ -286,8 +291,8 @@ function resume_children(effect, local) {
execute_effect(/** @type {import('#client').Effect} */ (effect)); execute_effect(/** @type {import('#client').Effect} */ (effect));
} }
if (effect.r) { if (effect.children) {
for (const child of effect.r) { for (const child of effect.children) {
resume_children(child, false); resume_children(child, false);
} }
} }

@ -67,8 +67,8 @@ export interface Effect {
f: SignalFlags; f: SignalFlags;
/** init: The function that we invoke for effects and computeds */ /** init: The function that we invoke for effects and computeds */
i: null | (() => void | (() => void)); i: null | (() => void | (() => void));
/** references: Anything that a signal owns */ /** deriveds belonging to this effect */
r: null | Reaction[]; r: null | Derived[];
/** teardown */ /** teardown */
v: null | (() => void); v: null | (() => void);
/** level: the depth from the root signal, used for ordering render/pre-effects topologically **/ /** level: the depth from the root signal, used for ordering render/pre-effects topologically **/
@ -83,8 +83,8 @@ export interface Effect {
dom: null | TemplateNode | Array<TemplateNode>; dom: null | TemplateNode | Array<TemplateNode>;
/** Whether the effect ran or not */ /** Whether the effect ran or not */
ran: boolean; ran: boolean;
/** The parent effect */
parent: null | Effect; parent: null | Effect;
children: null | Effect[];
} }
export type Reaction = Derived | Effect; export type Reaction = Derived | Effect;

@ -1,13 +0,0 @@
/**
* @param {import('#client').Reaction} target_signal
* @param {import('#client').Reaction} ref_signal
* @returns {void}
*/
export function push_reference(target_signal, ref_signal) {
const references = target_signal.r;
if (references === null) {
target_signal.r = [ref_signal];
} else {
references.push(ref_signal);
}
}

@ -356,16 +356,16 @@ function remove_consumers(signal, start_index) {
} }
/** /**
* @param {import('#client').Reaction} signal * @param {import('#client').Effect} effect
* @returns {void} * @returns {void}
*/ */
function destroy_references(signal) { function destroy_references(effect) {
const references = signal.r; const deriveds = effect.r;
signal.r = null; effect.r = null;
if (references !== null) { if (deriveds !== null) {
let i; let i;
for (i = 0; i < references.length; i++) { for (i = 0; i < deriveds.length; i++) {
destroy_signal(references[i]); destroy_signal(deriveds[i]);
} }
} }
} }
@ -656,7 +656,6 @@ export async function tick() {
function update_derived(signal, force_schedule) { function update_derived(signal, force_schedule) {
const previous_updating_derived = updating_derived; const previous_updating_derived = updating_derived;
updating_derived = true; updating_derived = true;
destroy_references(signal);
const value = execute_signal_fn(signal); const value = execute_signal_fn(signal);
updating_derived = previous_updating_derived; updating_derived = previous_updating_derived;
const status = const status =

Loading…
Cancel
Save