Skip to content

Commit c80d165

Browse files
committed
local effect pending
1 parent da5b74a commit c80d165

File tree

7 files changed

+49
-44
lines changed

7 files changed

+49
-44
lines changed

packages/svelte/src/compiler/phases/3-transform/client/visitors/CallExpression.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ export function CallExpression(node, context) {
6464
);
6565

6666
case '$effect.pending':
67-
return b.call('$.get', b.id('$.pending'));
67+
return b.call(b.id('$.pending'));
6868

6969
case '$inspect':
7070
case '$inspect().with':

packages/svelte/src/internal/client/dom/blocks/async.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ export async function async(node, expressions, fn) {
1717
var restore = capture();
1818
var boundary = get_pending_boundary();
1919

20-
boundary.increment();
20+
boundary.update_pending_count(1);
2121

2222
try {
2323
const result = await Promise.all(expressions.map((fn) => async_derived(fn)));
@@ -29,6 +29,6 @@ export async function async(node, expressions, fn) {
2929
} catch (error) {
3030
boundary.error(error);
3131
} finally {
32-
boundary.decrement();
32+
boundary.update_pending_count(-1);
3333
}
3434
}

packages/svelte/src/internal/client/dom/blocks/boundary.js

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { block, branch, destroy_effect, pause_effect } from '../../reactivity/ef
77
import {
88
active_effect,
99
active_reaction,
10+
get,
1011
set_active_effect,
1112
set_active_reaction
1213
} from '../../runtime.js';
@@ -24,6 +25,8 @@ import * as e from '../../../shared/errors.js';
2425
import { DEV } from 'esm-env';
2526
import { from_async_derived, set_from_async_derived } from '../../reactivity/deriveds.js';
2627
import { Batch } from '../../reactivity/batch.js';
28+
import { source, update } from '../../reactivity/sources.js';
29+
import { tag } from '../../dev/tracing.js';
2730

2831
/**
2932
* @typedef {{
@@ -82,6 +85,8 @@ export class Boundary {
8285
#pending_count = 0;
8386
#is_creating_fallback = false;
8487

88+
effect_pending = source(0);
89+
8590
/**
8691
* @param {TemplateNode} node
8792
* @param {BoundaryProps} props
@@ -98,6 +103,10 @@ export class Boundary {
98103

99104
this.pending = !!this.#props.pending;
100105

106+
if (DEV) {
107+
tag(this.effect_pending, '$effect.pending()');
108+
}
109+
101110
this.#effect = block(() => {
102111
/** @type {Effect} */ (active_effect).b = this;
103112

@@ -210,19 +219,26 @@ export class Boundary {
210219
}
211220
}
212221

213-
increment() {
214-
this.#pending_count++;
215-
}
222+
/** @param {1 | -1} d */
223+
#update_pending_count(d) {
224+
this.#pending_count += d;
216225

217-
decrement() {
218-
if (--this.#pending_count === 0) {
226+
if (this.#pending_count === 0) {
219227
this.commit();
228+
}
229+
}
220230

221-
if (this.#main_effect !== null) {
222-
// TODO do we also need to `resume_effect` here?
223-
// schedule_effect(this.#main_effect);
224-
}
231+
/** @param {1 | -1} d */
232+
update_pending_count(d) {
233+
if (this.has_pending_snippet()) {
234+
this.#update_pending_count(d);
235+
} else if (this.parent) {
236+
this.parent.#update_pending_count(d);
225237
}
238+
239+
queueMicrotask(() => {
240+
update(this.effect_pending, d);
241+
});
226242
}
227243

228244
/** @param {unknown} error */
@@ -373,10 +389,10 @@ export function capture(track = true) {
373389
export function suspend() {
374390
let boundary = get_pending_boundary();
375391

376-
boundary.increment();
392+
boundary.update_pending_count(-1);
377393

378394
return function unsuspend() {
379-
boundary.decrement();
395+
boundary.update_pending_count(-1);
380396
};
381397
}
382398

@@ -401,3 +417,14 @@ function exit() {
401417
set_active_reaction(null);
402418
set_component_context(null);
403419
}
420+
421+
export function pending() {
422+
// TODO throw helpful error if called outside an effect
423+
const boundary = /** @type {Effect} */ (active_effect).b;
424+
425+
if (boundary === null) {
426+
return 0; // TODO eventually we will need this to be global
427+
}
428+
429+
return get(boundary.effect_pending);
430+
}

packages/svelte/src/internal/client/index.js

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -115,15 +115,7 @@ export {
115115
user_effect,
116116
user_pre_effect
117117
} from './reactivity/effects.js';
118-
export {
119-
mutable_source,
120-
mutate,
121-
pending,
122-
set,
123-
state,
124-
update,
125-
update_pre
126-
} from './reactivity/sources.js';
118+
export { mutable_source, mutate, set, state, update, update_pre } from './reactivity/sources.js';
127119
export {
128120
prop,
129121
rest_props,
@@ -143,7 +135,7 @@ export {
143135
update_store,
144136
mark_store_binding
145137
} from './reactivity/store.js';
146-
export { boundary, save, suspend } from './dom/blocks/boundary.js';
138+
export { boundary, pending, save, suspend } from './dom/blocks/boundary.js';
147139
export { set_text } from './render.js';
148140
export {
149141
get,

packages/svelte/src/internal/client/reactivity/batch.js

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,13 @@ import {
1010
set_signal_status,
1111
update_effect
1212
} from '../runtime.js';
13-
import { raf } from '../timing.js';
14-
import { internal_set, pending } from './sources.js';
1513

1614
/** @type {Set<Batch>} */
1715
const batches = new Set();
1816

1917
/** @type {Batch | null} */
2018
export let current_batch = null;
2119

22-
/** Update `$effect.pending()` */
23-
function update_pending() {
24-
internal_set(pending, batches.size > 0);
25-
}
26-
2720
/** @type {Map<Derived, any> | null} */
2821
export let batch_deriveds = null;
2922

@@ -239,8 +232,6 @@ export class Batch {
239232
}
240233

241234
this.#callbacks.clear();
242-
243-
raf.tick(update_pending);
244235
}
245236

246237
increment() {
@@ -295,10 +286,6 @@ export class Batch {
295286

296287
static ensure() {
297288
if (current_batch === null) {
298-
if (batches.size === 0) {
299-
raf.tick(update_pending);
300-
}
301-
302289
const batch = (current_batch = new Batch());
303290
batches.add(current_batch);
304291

packages/svelte/src/internal/client/reactivity/deriveds.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import { destroy_effect, render_effect } from './effects.js';
3131
import { inspect_effects, internal_set, set_inspect_effects, source } from './sources.js';
3232
import { get_stack } from '../dev/tracing.js';
3333
import { tracing_mode_flag } from '../../flags/index.js';
34-
import { get_pending_boundary } from '../dom/blocks/boundary.js';
34+
import { Boundary, get_pending_boundary } from '../dom/blocks/boundary.js';
3535
import { component_context } from '../context.js';
3636
import { UNINITIALIZED } from '../../../constants.js';
3737
import { current_batch } from './batch.js';
@@ -105,7 +105,7 @@ export function async_derived(fn, location) {
105105
throw new Error('TODO cannot create unowned async derived');
106106
}
107107

108-
let boundary = get_pending_boundary();
108+
var boundary = /** @type {Boundary} */ (parent.b);
109109

110110
var promise = /** @type {Promise<V>} */ (/** @type {unknown} */ (undefined));
111111
var signal = source(/** @type {V} */ (UNINITIALIZED));
@@ -135,7 +135,8 @@ export function async_derived(fn, location) {
135135
var pending = boundary.pending;
136136

137137
if (should_suspend) {
138-
(pending ? boundary : batch).increment();
138+
boundary.update_pending_count(1);
139+
if (!pending) batch.increment();
139140
}
140141

141142
/**
@@ -148,7 +149,8 @@ export function async_derived(fn, location) {
148149
from_async_derived = null;
149150

150151
if (should_suspend) {
151-
(pending ? boundary : batch).decrement();
152+
boundary.update_pending_count(-1);
153+
if (!pending) batch.decrement();
152154
}
153155

154156
if (!pending) batch.restore();

packages/svelte/src/internal/client/reactivity/sources.js

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,6 @@ export let inspect_effects = new Set();
4343
/** @type {Map<Source, any>} */
4444
export const old_values = new Map();
4545

46-
/** Internal representation of `$effect.pending()` */
47-
export let pending = source(false);
48-
4946
/**
5047
* @param {Set<any>} v
5148
*/

0 commit comments

Comments
 (0)