pull/10582/head
Rich Harris 2 years ago
parent c7895db461
commit 34dbee71fc

@ -1,6 +1,6 @@
import { createClassComponent } from '../../legacy/legacy-client.js';
import { destroy_signal } from './runtime.js';
import { render_effect } from './reactivity/effects.js';
import { render_effect } from './reactivity/computations.js';
import { open, close } from './render.js';
import { define_property } from './utils.js';

@ -10,7 +10,7 @@ import {
flushSync,
push_destroy_fn
} from '../../runtime.js';
import { render_effect } from '../../reactivity/effects.js';
import { render_effect } from '../../reactivity/computations.js';
import { trigger_transitions } from '../../transitions.js';
/** @returns {import('../../types.js').AwaitBlock} */

@ -24,7 +24,7 @@ import {
push_destroy_fn,
set_signal_value
} from '../../runtime.js';
import { render_effect } from '../../reactivity/effects.js';
import { render_effect } from '../../reactivity/computations.js';
import { source, mutable_source } from '../../reactivity/sources.js';
import { trigger_transitions } from '../../transitions.js';
import { is_array } from '../../utils.js';

@ -7,7 +7,7 @@ import {
} from '../../hydration.js';
import { remove } from '../../reconciler.js';
import { current_block, destroy_signal, execute_effect, push_destroy_fn } from '../../runtime.js';
import { render_effect } from '../../reactivity/effects.js';
import { render_effect } from '../../reactivity/computations.js';
import { trigger_transitions } from '../../transitions.js';
/** @returns {import('../../types.js').IfBlock} */

@ -8,7 +8,7 @@ import {
execute_effect,
push_destroy_fn
} from '../../runtime.js';
import { render_effect } from '../../reactivity/effects.js';
import { render_effect } from '../../reactivity/computations.js';
import { trigger_transitions } from '../../transitions.js';
import { safe_not_equal } from '../../reactivity/equality.js';

@ -8,7 +8,7 @@ import {
batch_inspect,
current_component_context
} from './runtime.js';
import { effect_active } from './reactivity/effects.js';
import { effect_active } from './reactivity/computations.js';
import {
array_prototype,
define_property,

@ -1,19 +1,25 @@
import { DEV } from 'esm-env';
import {
CLEAN,
DERIVED,
DIRTY,
EFFECT,
MANAGED,
PRE_EFFECT,
RENDER_EFFECT,
UNINITIALIZED,
UNOWNED,
create_computation_signal,
current_block,
current_component_context,
current_consumer,
current_effect,
destroy_signal,
flush_local_render_effects,
push_reference,
schedule_effect
} from '../runtime.js';
import { default_equals, safe_equal } from './equality.js';
/**
* @param {import('../types.js').EffectType} type
@ -178,3 +184,35 @@ export function managed_render_effect(init, block = current_block, sync = true)
const flags = RENDER_EFFECT | MANAGED;
return internal_create_effect(flags, /** @type {any} */ (init), sync, block, true);
}
/**
* @template V
* @param {() => V} init
* @returns {import('../types.js').ComputationSignal<V>}
*/
/*#__NO_SIDE_EFFECTS__*/
export function derived(init) {
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 = init;
signal.e = default_equals;
if (current_consumer !== null) {
push_reference(current_consumer, signal);
}
return signal;
}
/**
* @template V
* @param {() => V} init
* @returns {import('../types.js').ComputationSignal<V>}
*/
/*#__NO_SIDE_EFFECTS__*/
export function derived_safe_equal(init) {
const signal = derived(init);
signal.e = safe_equal;
return signal;
}

@ -43,7 +43,7 @@ import {
pop,
deep_read
} from './runtime.js';
import { render_effect, effect, managed_effect } from './reactivity/effects.js';
import { render_effect, effect, managed_effect } from './reactivity/computations.js';
import {
current_hydration_fragment,
get_hydration_fragment,

@ -19,9 +19,9 @@ import {
} from '../../constants.js';
import { STATE_SYMBOL, unstate } from './proxy.js';
import { EACH_BLOCK, IF_BLOCK } from './block.js';
import { pre_effect, user_effect } from './reactivity/effects.js';
import { derived, pre_effect, user_effect } from './reactivity/computations.js';
import { mutable_source, source } from './reactivity/sources.js';
import { default_equals, safe_equal, safe_not_equal } from './reactivity/equality.js';
import { safe_equal, safe_not_equal } from './reactivity/equality.js';
export const SOURCE = 1;
export const DERIVED = 1 << 1;
@ -29,7 +29,7 @@ export const EFFECT = 1 << 2;
export const PRE_EFFECT = 1 << 3;
export const RENDER_EFFECT = 1 << 4;
export const MANAGED = 1 << 6;
const UNOWNED = 1 << 7;
export const UNOWNED = 1 << 7;
export const CLEAN = 1 << 8;
export const DIRTY = 1 << 9;
export const MAYBE_DIRTY = 1 << 10;
@ -69,7 +69,7 @@ let flush_count = 0;
// Handle signal reactivity tree dependencies and consumer
/** @type {null | import('./types.js').ComputationSignal} */
let current_consumer = null;
export let current_consumer = null;
/** @type {null | import('./types.js').EffectSignal} */
export let current_effect = null;
@ -1252,38 +1252,6 @@ export function destroy_signal(signal) {
}
}
/**
* @template V
* @param {() => V} init
* @returns {import('./types.js').ComputationSignal<V>}
*/
/*#__NO_SIDE_EFFECTS__*/
export function derived(init) {
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 = init;
signal.e = default_equals;
if (current_consumer !== null) {
push_reference(current_consumer, signal);
}
return signal;
}
/**
* @template V
* @param {() => V} init
* @returns {import('./types.js').ComputationSignal<V>}
*/
/*#__NO_SIDE_EFFECTS__*/
export function derived_safe_equal(init) {
const signal = derived(init);
signal.e = safe_equal;
return signal;
}
/**
* Use `untrack` to prevent something from being treated as an `$effect`/`$derived` dependency.
*

@ -11,7 +11,7 @@ import {
} from './block.js';
import { destroy_each_item_block, get_first_element } from './dom/blocks/each.js';
import { append_child, empty } from './operations.js';
import { effect, managed_effect, managed_pre_effect } from './reactivity/effects.js';
import { effect, managed_effect, managed_pre_effect } from './reactivity/computations.js';
import {
current_block,
current_effect,

@ -4,8 +4,6 @@ export {
set,
set_sync,
invalidate_inner_signals,
derived,
derived_safe_equal,
prop,
flushSync,
bubble_event,
@ -37,7 +35,7 @@ export { await_block as await } from './client/dom/blocks/await.js';
export { if_block as if } from './client/dom/blocks/if.js';
export { key_block as key } from './client/dom/blocks/key.js';
export * from './client/dom/blocks/each.js';
export * from './client/reactivity/effects.js';
export * from './client/reactivity/computations.js';
export * from './client/reactivity/sources.js';
export * from './client/reactivity/equality.js';
export * from './client/render.js';

@ -1,6 +1,11 @@
import { describe, assert, it } from 'vitest';
import * as $ from '../../src/internal/client/runtime';
import { effect, render_effect, user_effect } from '../../src/internal/client/reactivity/effects';
import {
derived,
effect,
render_effect,
user_effect
} from '../../src/internal/client/reactivity/computations';
import { source } from '../../src/internal/client/reactivity/sources';
import type { ComputationSignal } from '../../src/internal/client/types';
@ -39,7 +44,7 @@ describe('signals', () => {
const log: string[] = [];
let count = source(0);
let double = $.derived(() => $.get(count) * 2);
let double = derived(() => $.get(count) * 2);
effect(() => {
log.push(`${$.get(count)}:${$.get(double)}`);
});
@ -56,7 +61,7 @@ describe('signals', () => {
const log: string[] = [];
let count = source(0);
let double = $.derived(() => $.get(count) * 2);
let double = derived(() => $.get(count) * 2);
effect(() => {
log.push(`A:${$.get(count)}:${$.get(double)}`);
@ -77,7 +82,7 @@ describe('signals', () => {
const log: string[] = [];
let count = source(0);
let double = $.derived(() => $.get(count) * 2);
let double = derived(() => $.get(count) * 2);
effect(() => {
log.push(`A:${$.get(double)}`);
@ -98,7 +103,7 @@ describe('signals', () => {
const log: number[] = [];
let count = source(0);
let double = $.derived(() => $.get(count) * 2);
let double = derived(() => $.get(count) * 2);
effect(() => {
log.push($.get(double));
@ -116,8 +121,8 @@ describe('signals', () => {
const log: number[] = [];
let count = source(0);
let double = $.derived(() => $.get(count) * 2);
let quadruple = $.derived(() => $.get(double) * 2);
let double = derived(() => $.get(count) * 2);
let quadruple = derived(() => $.get(double) * 2);
effect(() => {
log.push($.get(quadruple));
@ -140,11 +145,11 @@ describe('signals', () => {
const A = source(0);
const B = source(0);
const C = $.derived(() => ($.get(A) % 2) + ($.get(B) % 2));
const D = $.derived(() => numbers.map((i) => i + ($.get(A) % 2) - ($.get(B) % 2)));
const E = $.derived(() => hard($.get(C) + $.get(A) + $.get(D)[0]!, 'E'));
const F = $.derived(() => hard($.get(D)[0]! && $.get(B), 'F'));
const G = $.derived(() => $.get(C) + ($.get(C) || $.get(E) % 2) + $.get(D)[0]! + $.get(F));
const C = derived(() => ($.get(A) % 2) + ($.get(B) % 2));
const D = derived(() => numbers.map((i) => i + ($.get(A) % 2) - ($.get(B) % 2)));
const E = derived(() => hard($.get(C) + $.get(A) + $.get(D)[0]!, 'E'));
const F = derived(() => hard($.get(D)[0]! && $.get(B), 'F'));
const G = derived(() => $.get(C) + ($.get(C) || $.get(E) % 2) + $.get(D)[0]! + $.get(F));
effect(() => {
res.push(hard($.get(G), 'H'));
});
@ -180,10 +185,10 @@ describe('signals', () => {
let count = source(0);
const read = () => {
const x = $.derived(() => ({ count: $.get(count) }));
const x = derived(() => ({ count: $.get(count) }));
return $.get(x);
};
const derivedCount = $.derived(() => read().count);
const derivedCount = derived(() => read().count);
user_effect(() => {
log.push($.get(derivedCount));
});
@ -208,9 +213,9 @@ describe('signals', () => {
const a = source(0);
const b = source(0);
const c = $.derived(() => {
const a_2 = $.derived(() => $.get(a) + '!');
const b_2 = $.derived(() => $.get(b) + '?');
const c = derived(() => {
const a_2 = derived(() => $.get(a) + '!');
const b_2 = derived(() => $.get(b) + '?');
nested.push(a_2, b_2);
return { a: $.get(a_2), b: $.get(b_2) };
@ -236,7 +241,7 @@ describe('signals', () => {
// outside of test function so that they are unowned signals
let count = source(0);
let calc = $.derived(() => {
let calc = derived(() => {
if ($.get(count) >= 2) {
return 'limit';
}
@ -265,7 +270,7 @@ describe('signals', () => {
};
});
let no_deps = $.derived(() => {
let no_deps = derived(() => {
return [];
});
@ -287,7 +292,7 @@ describe('signals', () => {
});
let some_state = source({});
let some_deps = $.derived(() => {
let some_deps = derived(() => {
return [$.get(some_state)];
});

Loading…
Cancel
Save