decouple from boundaries

state-eager-derived-block
Rich Harris 4 days ago
parent 7c0fef4c61
commit 4fa2be67ee

@ -51,7 +51,7 @@ export function CallExpression(node, context) {
case '$state.eager': case '$state.eager':
return b.call( return b.call(
'$.pending', '$.eager',
b.thunk(/** @type {Expression} */ (context.visit(node.arguments[0]))) b.thunk(/** @type {Expression} */ (context.visit(node.arguments[0])))
); );

@ -13,10 +13,8 @@ import {
active_effect, active_effect,
active_reaction, active_reaction,
get, get,
read_pending,
set_active_effect, set_active_effect,
set_active_reaction, set_active_reaction
set_read_pending
} from '../../runtime.js'; } from '../../runtime.js';
import { import {
hydrate_next, hydrate_next,
@ -449,10 +447,7 @@ export function get_boundary() {
return /** @type {Boundary} */ (/** @type {Effect} */ (active_effect).b); return /** @type {Boundary} */ (/** @type {Effect} */ (active_effect).b);
} }
/** export function pending() {
* @param {() => any} [fn]
*/
export function pending(fn) {
if (active_effect === null) { if (active_effect === null) {
e.effect_pending_outside_reaction(); e.effect_pending_outside_reaction();
} }
@ -460,23 +455,8 @@ export function pending(fn) {
var boundary = active_effect.b; var boundary = active_effect.b;
if (boundary === null) { if (boundary === null) {
return fn ? fn() : 0; // TODO eventually we will need this to be global return 0; // TODO eventually we will need this to be global
} }
var pending = boundary.get_effect_pending(); return boundary.get_effect_pending();
if (fn) {
var value;
var prev_read_pending = read_pending;
set_read_pending(true);
try {
value = fn();
} finally {
set_read_pending(prev_read_pending);
}
return value;
} else {
return pending;
}
} }

@ -103,7 +103,7 @@ export {
save, save,
track_reactivity_loss track_reactivity_loss
} from './reactivity/async.js'; } from './reactivity/async.js';
export { flushSync as flush } from './reactivity/batch.js'; export { eager, flushSync as flush } from './reactivity/batch.js';
export { export {
async_derived, async_derived,
user_derived as derived, user_derived as derived,

@ -17,6 +17,7 @@ import { async_mode_flag } from '../../flags/index.js';
import { deferred, define_property } from '../../shared/utils.js'; import { deferred, define_property } from '../../shared/utils.js';
import { import {
active_effect, active_effect,
get,
is_dirty, is_dirty,
is_updating_effect, is_updating_effect,
set_is_updating_effect, set_is_updating_effect,
@ -27,8 +28,8 @@ import * as e from '../errors.js';
import { flush_tasks, queue_micro_task } from '../dom/task.js'; import { flush_tasks, queue_micro_task } from '../dom/task.js';
import { DEV } from 'esm-env'; import { DEV } from 'esm-env';
import { invoke_error_boundary } from '../error-handling.js'; import { invoke_error_boundary } from '../error-handling.js';
import { old_values } from './sources.js'; import { old_values, source, update } from './sources.js';
import { unlink_effect } from './effects.js'; import { inspect_effect, unlink_effect } from './effects.js';
/** @type {Set<Batch>} */ /** @type {Set<Batch>} */
const batches = new Set(); const batches = new Set();
@ -702,6 +703,48 @@ export function schedule_effect(signal) {
queued_root_effects.push(effect); queued_root_effects.push(effect);
} }
/** @type {Source<number>} */
let version;
let eager_flushing = false;
function eager_flush() {
try {
flushSync(() => {
update(version);
});
} finally {
eager_flushing = false;
}
}
/**
* @template T
* @param {() => T} fn
* @returns {T}
*/
export function eager(fn) {
const previous_batch_values = batch_values;
try {
get((version ??= source(0)));
inspect_effect(() => {
fn();
if (!eager_flushing) {
eager_flushing = true;
queueMicrotask(eager_flush);
}
});
batch_values = null;
return fn();
} finally {
batch_values = previous_batch_values;
}
}
/** /**
* Forcibly remove all current batches, to prevent cross-talk between tests * Forcibly remove all current batches, to prevent cross-talk between tests
*/ */

@ -144,17 +144,6 @@ export function increment_write_version() {
return ++write_version; return ++write_version;
} }
/**
* Whether or not we should get the latest value of a signal regardless of whether or not it is pending,
* i.e. inside a boundary with pending async work in which case normally a stale value might be shown.
*/
export let read_pending = false;
/** @param {boolean} value */
export function set_read_pending(value) {
read_pending = value;
}
/** /**
* Determines whether a derived or effect is dirty. * Determines whether a derived or effect is dirty.
* If it is MAYBE_DIRTY, will set the status to CLEAN * If it is MAYBE_DIRTY, will set the status to CLEAN
@ -691,7 +680,7 @@ export function get(signal) {
} }
} }
if (!read_pending && batch_values?.has(signal)) { if (batch_values?.has(signal)) {
return batch_values.get(signal); return batch_values.get(signal);
} }

Loading…
Cancel
Save