ripple 0.4.2 → 0.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +164 -0
- package/package.json +10 -4
- package/src/constants.js +6 -0
- package/src/jsx-runtime.d.ts +2 -1
- package/src/runtime/array.js +15 -9
- package/src/runtime/index-client.js +25 -7
- package/src/runtime/index-server.js +1 -0
- package/src/runtime/internal/client/attributes.js +439 -0
- package/src/runtime/internal/client/blocks.js +20 -20
- package/src/runtime/internal/client/component.js +2 -5
- package/src/runtime/internal/client/composite.js +295 -95
- package/src/runtime/internal/client/constants.js +14 -6
- package/src/runtime/internal/client/context.js +3 -2
- package/src/runtime/internal/client/css.js +11 -26
- package/src/runtime/internal/client/errors.js +188 -0
- package/src/runtime/internal/client/events.js +79 -34
- package/src/runtime/internal/client/expression.js +25 -120
- package/src/runtime/internal/client/for.js +113 -262
- package/src/runtime/internal/client/head.js +4 -3
- package/src/runtime/internal/client/html.js +5 -3
- package/src/runtime/internal/client/hydrate.js +484 -0
- package/src/runtime/internal/client/hydration-enabled.js +7 -0
- package/src/runtime/internal/client/hydration.js +16 -81
- package/src/runtime/internal/client/if.js +69 -10
- package/src/runtime/internal/client/index.js +18 -10
- package/src/runtime/internal/client/operations.js +11 -7
- package/src/runtime/internal/client/portal.js +3 -2
- package/src/runtime/internal/client/render.js +42 -325
- package/src/runtime/internal/client/root-boundary-enabled.js +7 -0
- package/src/runtime/internal/client/runtime.js +157 -371
- package/src/runtime/internal/client/template-ns.js +88 -0
- package/src/runtime/internal/client/template.js +118 -139
- package/src/runtime/internal/client/track-async.js +356 -0
- package/src/runtime/internal/client/try.js +133 -319
- package/src/runtime/internal/client/types.d.ts +48 -24
- package/src/runtime/internal/server/index.js +31 -29
- package/src/runtime/internal/server/prerender.js +27 -0
- package/src/server/index.js +1 -0
- package/src/utils/class-name.js +28 -0
- package/tests/client/basic/basic.errors.test.tsrx +3 -3
- package/tests/client/compiler/__snapshots__/compiler.typescript.test.tsrx.snap +0 -2
- package/tests/client/compiler/compiler.basic.test.tsrx +2 -2
- package/tests/client/compiler/compiler.tracked-access.test.tsrx +3 -3
- package/tests/client/composite/composite.dynamic-components.test.tsrx +40 -0
- package/tests/client/composite/composite.props.test.tsrx +10 -10
- package/tests/client/css/scoped-styles.test.tsrx +3 -1
- package/tests/client/derived-release.test.tsrx +3 -3
- package/tests/client/for-item.test.tsrx +39 -0
- package/tests/client/for-selector.test.tsrx +95 -0
- package/tests/client/svg.test.tsrx +273 -1
- package/tests/hydration/compiled/client/basic.js +88 -87
- package/tests/hydration/compiled/client/composite.js +15 -6
- package/tests/hydration/compiled/client/events.js +40 -48
- package/tests/hydration/compiled/client/for.js +191 -199
- package/tests/hydration/compiled/client/fragment-cursor.js +633 -334
- package/tests/hydration/compiled/client/head.js +22 -22
- package/tests/hydration/compiled/client/hmr.js +14 -5
- package/tests/hydration/compiled/client/html-in-template.js +5 -5
- package/tests/hydration/compiled/client/html.js +195 -177
- package/tests/hydration/compiled/client/if-children.js +136 -63
- package/tests/hydration/compiled/client/if-fragment-controlflow.js +63 -43
- package/tests/hydration/compiled/client/if.js +78 -30
- package/tests/hydration/compiled/client/mixed-control-flow.js +90 -72
- package/tests/hydration/compiled/client/nested-control-flow.js +266 -307
- package/tests/hydration/compiled/client/portal.js +20 -11
- package/tests/hydration/compiled/client/reactivity.js +29 -29
- package/tests/hydration/compiled/client/return.js +2 -2
- package/tests/hydration/compiled/client/streaming.js +33 -35
- package/tests/hydration/compiled/client/switch.js +25 -25
- package/tests/hydration/compiled/client/track-async-serialization.js +41 -41
- package/tests/hydration/compiled/client/try.js +15 -15
- package/tests/hydration/compiled/client/typed-text.js +8 -7
- package/tests/hydration/compiled/server/basic.js +6 -6
- package/tests/hydration/compiled/server/events.js +8 -8
- package/tests/hydration/compiled/server/for.js +22 -22
- package/tests/hydration/compiled/server/fragment-cursor.js +188 -52
- package/tests/hydration/compiled/server/head.js +6 -6
- package/tests/hydration/compiled/server/hmr.js +1 -1
- package/tests/hydration/compiled/server/html.js +1 -1
- package/tests/hydration/compiled/server/if-children.js +9 -9
- package/tests/hydration/compiled/server/if.js +5 -5
- package/tests/hydration/compiled/server/mixed-control-flow.js +4 -4
- package/tests/hydration/compiled/server/portal.js +1 -1
- package/tests/hydration/compiled/server/reactivity.js +9 -9
- package/tests/hydration/compiled/server/streaming.js +9 -9
- package/tests/hydration/compiled/server/switch.js +4 -4
- package/tests/hydration/compiled/server/track-async-serialization.js +16 -16
- package/tests/hydration/compiled/server/try.js +4 -4
- package/tests/hydration/compiled/server/typed-text.js +1 -1
- package/tests/hydration/components/fragment-cursor.tsrx +60 -0
- package/tests/hydration/components/track-async-serialization.tsrx +2 -2
- package/tests/hydration/fragment-cursor.test.js +34 -1
- package/tests/hydration/track-async-serialization.test.js +1 -1
- package/tests/server/basic.components.test.tsrx +3 -3
- package/tests/server/track-async-serialization.test.tsrx +6 -6
- package/tests/utils/tracked-types.test.js +3 -3
- package/types/index.d.ts +8 -8
- package/types/server.d.ts +17 -0
|
@@ -4,13 +4,7 @@
|
|
|
4
4
|
/** @typedef {DerivedValue} Derived */
|
|
5
5
|
|
|
6
6
|
import { DEV } from 'esm-env';
|
|
7
|
-
import {
|
|
8
|
-
destroy_block,
|
|
9
|
-
destroy_non_branch_children,
|
|
10
|
-
effect,
|
|
11
|
-
pause_block,
|
|
12
|
-
pre_effect,
|
|
13
|
-
} from './blocks.js';
|
|
7
|
+
import { destroy_block, destroy_non_branch_children, effect } from './blocks.js';
|
|
14
8
|
import {
|
|
15
9
|
ASYNC_DERIVED_READ_THROWN,
|
|
16
10
|
BLOCK_HAS_RUN,
|
|
@@ -28,30 +22,21 @@ import {
|
|
|
28
22
|
UNINITIALIZED,
|
|
29
23
|
REF_PROP,
|
|
30
24
|
DEFAULT_NAMESPACE,
|
|
31
|
-
TRACKED_UPDATED,
|
|
32
25
|
SUSPENSE_PENDING,
|
|
33
26
|
SUSPENSE_REJECTED,
|
|
34
|
-
TRY_BLOCK,
|
|
35
|
-
DIRECT_CHILD_BLOCK,
|
|
36
27
|
SCHEDULED,
|
|
37
28
|
SELECTOR,
|
|
38
29
|
IF_BLOCK,
|
|
30
|
+
COMPOSITE_BLOCK,
|
|
39
31
|
ITEM_BLOCK,
|
|
40
32
|
RELEASED,
|
|
41
33
|
RENDER_ENTRY,
|
|
42
34
|
CREATES_DERIVEDS,
|
|
35
|
+
NAMESPACE_BLOCK,
|
|
36
|
+
SVG_BLOCK,
|
|
43
37
|
} from './constants.js';
|
|
44
|
-
import {
|
|
45
|
-
begin_boundary_request,
|
|
46
|
-
complete_boundary_request,
|
|
47
|
-
get_boundary_with_catch,
|
|
48
|
-
get_pending_boundary,
|
|
49
|
-
handle_boundary_error,
|
|
50
|
-
register_boundary_deferred,
|
|
51
|
-
register_boundary_paused_block,
|
|
52
|
-
replace_boundary_request,
|
|
53
|
-
} from './try.js';
|
|
54
38
|
import { is_ripple_object } from './utils.js';
|
|
39
|
+
import { scope_orphan, set_in_derived, track_orphan, update_depth_exceeded } from './errors.js';
|
|
55
40
|
import { render_value } from './expression.js';
|
|
56
41
|
import { throw_invalid_component_type } from './component.js';
|
|
57
42
|
|
|
@@ -61,10 +46,8 @@ import {
|
|
|
61
46
|
is_array,
|
|
62
47
|
object_keys,
|
|
63
48
|
} from '@tsrx/core/runtime/language-helpers';
|
|
64
|
-
import { get_async_track_result } from '../../../utils/async.js';
|
|
65
|
-
import { get_track_async_script_id } from '../../../utils/track-async-serialization.js';
|
|
66
|
-
import { revive } from './transport.js';
|
|
67
49
|
import { hydrating, track_hash_reference } from './hydration.js';
|
|
50
|
+
import { HYDRATION } from 'ripple/internal/client/hydration-enabled';
|
|
68
51
|
import { create_ref_prop as create_core_ref_prop } from '@tsrx/core/runtime/ref';
|
|
69
52
|
|
|
70
53
|
const FLUSH_MICROTASK = 0;
|
|
@@ -130,7 +113,7 @@ let flush_count = 0;
|
|
|
130
113
|
/** @type {(() => void)[]} */
|
|
131
114
|
var queued_post_block_flush = [];
|
|
132
115
|
/** @type {null | Dependency} */
|
|
133
|
-
let active_dependency = null;
|
|
116
|
+
export let active_dependency = null;
|
|
134
117
|
|
|
135
118
|
export let tracking = false;
|
|
136
119
|
export let teardown = false;
|
|
@@ -170,6 +153,28 @@ export function set_tracking(value) {
|
|
|
170
153
|
tracking = value;
|
|
171
154
|
}
|
|
172
155
|
|
|
156
|
+
/**
|
|
157
|
+
* @param {boolean} value
|
|
158
|
+
*/
|
|
159
|
+
export function set_mutating_allowed(value) {
|
|
160
|
+
is_mutating_allowed = value;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Handles a block whose run read a pending async value (see
|
|
165
|
+
* `track-async.js`). Installed by the first `trackAsync()`, so an application
|
|
166
|
+
* without one carries none of the boundary request machinery.
|
|
167
|
+
* @type {((block: Block) => void) | null}
|
|
168
|
+
*/
|
|
169
|
+
let pending_read = null;
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* @param {(block: Block) => void} fn
|
|
173
|
+
*/
|
|
174
|
+
export function set_pending_read_handler(fn) {
|
|
175
|
+
pending_read = fn;
|
|
176
|
+
}
|
|
177
|
+
|
|
173
178
|
/**
|
|
174
179
|
* @param {Block} block
|
|
175
180
|
*/
|
|
@@ -236,7 +241,7 @@ function update_derived(computed) {
|
|
|
236
241
|
* @param {Tracked} tracked
|
|
237
242
|
* @param {any} value
|
|
238
243
|
*/
|
|
239
|
-
function update_tracked_value_clock(tracked, value) {
|
|
244
|
+
export function update_tracked_value_clock(tracked, value) {
|
|
240
245
|
tracked.__v = value;
|
|
241
246
|
tracked.c = increment_clock();
|
|
242
247
|
mark_subscribers(tracked);
|
|
@@ -306,76 +311,51 @@ function run_derived(computed) {
|
|
|
306
311
|
}
|
|
307
312
|
}
|
|
308
313
|
|
|
314
|
+
/**
|
|
315
|
+
* Routes an error thrown by a block into the nearest boundary with a catch
|
|
316
|
+
* branch (see `try.js`). Installed by the first `try_block`, so a bundle whose
|
|
317
|
+
* mount and components create no boundary carries no catch machinery.
|
|
318
|
+
* @type {((error: unknown, block: Block) => BlockWithTryBoundaryAndCatch | null) | null}
|
|
319
|
+
*/
|
|
320
|
+
let catch_router = null;
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* @param {(error: unknown, block: Block) => BlockWithTryBoundaryAndCatch | null} fn
|
|
324
|
+
*/
|
|
325
|
+
export function set_catch_router(fn) {
|
|
326
|
+
catch_router = fn;
|
|
327
|
+
}
|
|
328
|
+
|
|
309
329
|
/**
|
|
310
330
|
* @param {unknown} error
|
|
311
331
|
* @param {Block} block
|
|
312
332
|
* @returns {BlockWithTryBoundaryAndCatch}
|
|
313
333
|
*/
|
|
314
334
|
export function handle_error(error, block) {
|
|
315
|
-
var boundary_with_catch =
|
|
316
|
-
if (boundary_with_catch
|
|
317
|
-
|
|
318
|
-
return boundary_with_catch;
|
|
335
|
+
var boundary_with_catch = catch_router === null ? null : catch_router(error, block);
|
|
336
|
+
if (boundary_with_catch === null) {
|
|
337
|
+
throw error;
|
|
319
338
|
}
|
|
320
|
-
|
|
321
|
-
throw error;
|
|
339
|
+
return boundary_with_catch;
|
|
322
340
|
}
|
|
323
341
|
|
|
324
342
|
/**
|
|
325
343
|
* The error path of {@link run_block}, kept out of that hot function so a
|
|
326
344
|
* healthy mount never compiles it: routes real errors to the nearest catch
|
|
327
|
-
* boundary and
|
|
328
|
-
*
|
|
345
|
+
* boundary, and a read of a pending async value to the handler `trackAsync`
|
|
346
|
+
* installs (the read is registered as a dependency, so the block re-runs once
|
|
347
|
+
* the value settles).
|
|
329
348
|
* @param {unknown} error
|
|
330
349
|
* @param {Block} block
|
|
331
350
|
*/
|
|
332
351
|
function handle_run_error(error, block) {
|
|
333
|
-
var is_component_direct = false;
|
|
334
|
-
var is_try_fn_block = false;
|
|
335
352
|
finish_dependencies(block, active_dependency);
|
|
336
|
-
// When a derived read throws ASYNC_DERIVED_READ_THROWN, it means the
|
|
337
|
-
// derived is still SUSPENSE_PENDING. The dependency was already registered,
|
|
338
|
-
// so we swallow the throw and let the parent continue processing. When
|
|
339
|
-
// the derived settles, the block will be dirty and rerun automatically.
|
|
340
353
|
if (error !== ASYNC_DERIVED_READ_THROWN) {
|
|
341
354
|
handle_error(error, block);
|
|
342
|
-
} else if (
|
|
343
|
-
|
|
344
|
-
(is_component_direct = active_component?.b === block) ||
|
|
345
|
-
(is_try_fn_block =
|
|
346
|
-
block.p !== null && (block.p.f & TRY_BLOCK) !== 0 && (block.f & DIRECT_CHILD_BLOCK) !== 0)
|
|
347
|
-
) {
|
|
348
|
-
throw new Error(
|
|
349
|
-
`Reads on pending tracked values directly inside ${is_component_direct ? 'component' : 'try/pending/catch'} body are prohibited. Use trackPending() test or peek() for safe access or create another derived instead.`,
|
|
350
|
-
);
|
|
355
|
+
} else if (pending_read !== null) {
|
|
356
|
+
pending_read(block);
|
|
351
357
|
} else {
|
|
352
|
-
|
|
353
|
-
var boundary = get_pending_boundary(block);
|
|
354
|
-
if (boundary !== null) {
|
|
355
|
-
pause_block(block);
|
|
356
|
-
register_boundary_paused_block(boundary, block);
|
|
357
|
-
|
|
358
|
-
// Register deferred boundary completions for async tracked deps.
|
|
359
|
-
// This handles the case where a child boundary reads a tracked value
|
|
360
|
-
// whose resolution is managed by a different (parent) boundary.
|
|
361
|
-
var dep = block.d;
|
|
362
|
-
while (dep !== null) {
|
|
363
|
-
var dep_tracked = /** @type {Tracked} */ (dep.t);
|
|
364
|
-
if (
|
|
365
|
-
(dep_tracked.__v === SUSPENSE_PENDING || dep_tracked.__v === SUSPENSE_REJECTED) &&
|
|
366
|
-
(dep_tracked.f & TRACKED) !== 0
|
|
367
|
-
) {
|
|
368
|
-
var deferred_req = begin_boundary_request(boundary);
|
|
369
|
-
var entry = /** @type {DeferredTrackedEntry} */ ({ b: boundary, r: deferred_req });
|
|
370
|
-
if (dep_tracked.d === null) {
|
|
371
|
-
dep_tracked.d = [entry];
|
|
372
|
-
} else {
|
|
373
|
-
dep_tracked.d.push(entry);
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
dep = dep.n;
|
|
377
|
-
}
|
|
378
|
-
}
|
|
358
|
+
throw error;
|
|
379
359
|
}
|
|
380
360
|
}
|
|
381
361
|
|
|
@@ -390,9 +370,10 @@ function handle_run_error(error, block) {
|
|
|
390
370
|
* @returns {Derived[] | null}
|
|
391
371
|
*/
|
|
392
372
|
function prepare_rerun(block) {
|
|
393
|
-
// A list, an if, and a list item re-run only their own logic;
|
|
394
|
-
// blocks (items, the branch's blocks,
|
|
395
|
-
|
|
373
|
+
// A list, an if, a composite and a list item re-run only their own logic;
|
|
374
|
+
// their child blocks (items, the branch's blocks, a dynamic element's
|
|
375
|
+
// children, an item body's nested blocks) stay.
|
|
376
|
+
if ((block.f & (FOR_BLOCK | IF_BLOCK | ITEM_BLOCK | COMPOSITE_BLOCK)) === 0) {
|
|
396
377
|
destroy_non_branch_children(block);
|
|
397
378
|
}
|
|
398
379
|
run_teardown(block);
|
|
@@ -416,16 +397,18 @@ function register_teardown(block, teardown) {
|
|
|
416
397
|
|
|
417
398
|
/**
|
|
418
399
|
* Runs the body of a branch block that was just created, in place of a first
|
|
419
|
-
* `run_block`: a branch renders untracked
|
|
420
|
-
*
|
|
421
|
-
*
|
|
422
|
-
* `run_block` handles them.
|
|
400
|
+
* `run_block`: a branch renders untracked, so the only bookkeeping its first
|
|
401
|
+
* run needs is the globals the body reads and the dependencies a nested
|
|
402
|
+
* `item` records on it (a list item re-runs through `run_block`, see
|
|
403
|
+
* `run_item`). Errors are handled as `run_block` handles them.
|
|
423
404
|
* @param {Block} block
|
|
424
|
-
* @param {(anchor: any, value: any) => void} fn
|
|
405
|
+
* @param {(anchor: any, value: any, index?: any, key?: any) => void} fn
|
|
425
406
|
* @param {any} anchor
|
|
426
|
-
* @param {any} value
|
|
407
|
+
* @param {any} value a list item's value, or its tracked
|
|
408
|
+
* @param {any} [index] a list item's tracked index (see `create_item`)
|
|
409
|
+
* @param {any} [key] a keyed list item's key
|
|
427
410
|
*/
|
|
428
|
-
export function run_branch(block, fn, anchor, value) {
|
|
411
|
+
export function run_branch(block, fn, anchor, value, index, key) {
|
|
429
412
|
var previous_block = active_block;
|
|
430
413
|
var previous_reaction = active_reaction;
|
|
431
414
|
var previous_tracking = tracking;
|
|
@@ -438,7 +421,7 @@ export function run_branch(block, fn, anchor, value) {
|
|
|
438
421
|
active_component = block.co;
|
|
439
422
|
tracking = false;
|
|
440
423
|
active_dependency = null;
|
|
441
|
-
fn(anchor, value);
|
|
424
|
+
fn(anchor, value, index, key);
|
|
442
425
|
if (active_dependency !== null) {
|
|
443
426
|
block.d = active_dependency;
|
|
444
427
|
}
|
|
@@ -453,6 +436,43 @@ export function run_branch(block, fn, anchor, value) {
|
|
|
453
436
|
}
|
|
454
437
|
}
|
|
455
438
|
|
|
439
|
+
/**
|
|
440
|
+
* Runs `fn(block.s, arg)` as a rerun of `block` driven from outside it: an if
|
|
441
|
+
* whose condition the enclosing render function evaluates renders its branch
|
|
442
|
+
* this way. The function runs under the block, in the block's namespace, and
|
|
443
|
+
* the deriveds the block's previous run created are released afterwards
|
|
444
|
+
* unless still read, as `run_block` does for a rerun. An error propagates to
|
|
445
|
+
* the caller's block.
|
|
446
|
+
* @template S, A
|
|
447
|
+
* @param {Block} block
|
|
448
|
+
* @param {(state: S, arg: A) => void} fn
|
|
449
|
+
* @param {A} arg
|
|
450
|
+
*/
|
|
451
|
+
export function run_in_block(block, fn, arg) {
|
|
452
|
+
var previous_block = active_block;
|
|
453
|
+
var previous_reaction = active_reaction;
|
|
454
|
+
var previous_component = active_component;
|
|
455
|
+
var previous_namespace = active_namespace;
|
|
456
|
+
var previous_deriveds = (block.f & CREATES_DERIVEDS) !== 0 ? take_created_deriveds(block) : null;
|
|
457
|
+
|
|
458
|
+
try {
|
|
459
|
+
active_block = block;
|
|
460
|
+
active_reaction = block;
|
|
461
|
+
active_component = block.co;
|
|
462
|
+
var ns = block.f & NAMESPACE_BLOCK;
|
|
463
|
+
active_namespace = ns === 0 ? DEFAULT_NAMESPACE : ns === SVG_BLOCK ? 'svg' : 'mathml';
|
|
464
|
+
fn(/** @type {S} */ (block.s), arg);
|
|
465
|
+
} finally {
|
|
466
|
+
active_block = previous_block;
|
|
467
|
+
active_reaction = previous_reaction;
|
|
468
|
+
active_component = previous_component;
|
|
469
|
+
active_namespace = previous_namespace;
|
|
470
|
+
if (previous_deriveds !== null) {
|
|
471
|
+
keep_deriveds(block, release_deriveds(previous_deriveds));
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
|
|
456
476
|
/**
|
|
457
477
|
* @param {Block} block
|
|
458
478
|
* @param {boolean} [first_run] true when the block has no children, teardown,
|
|
@@ -464,6 +484,7 @@ export function run_block(block, first_run = false) {
|
|
|
464
484
|
var previous_tracking = tracking;
|
|
465
485
|
var previous_dependency = active_dependency;
|
|
466
486
|
var previous_component = active_component;
|
|
487
|
+
var previous_namespace = active_namespace;
|
|
467
488
|
/** @type {Derived[] | null} */
|
|
468
489
|
var previous_deriveds = null;
|
|
469
490
|
|
|
@@ -471,6 +492,10 @@ export function run_block(block, first_run = false) {
|
|
|
471
492
|
active_block = block;
|
|
472
493
|
active_reaction = block;
|
|
473
494
|
active_component = block.co;
|
|
495
|
+
// The namespace the block was created in (see `create_block`): a rerun
|
|
496
|
+
// from a flush is outside the `with_ns()` call that established it.
|
|
497
|
+
var ns = block.f & NAMESPACE_BLOCK;
|
|
498
|
+
active_namespace = ns === 0 ? DEFAULT_NAMESPACE : ns === SVG_BLOCK ? 'svg' : 'mathml';
|
|
474
499
|
|
|
475
500
|
if (!first_run) {
|
|
476
501
|
previous_deriveds = prepare_rerun(block);
|
|
@@ -500,6 +525,7 @@ export function run_block(block, first_run = false) {
|
|
|
500
525
|
tracking = previous_tracking;
|
|
501
526
|
active_dependency = previous_dependency;
|
|
502
527
|
active_component = previous_component;
|
|
528
|
+
active_namespace = previous_namespace;
|
|
503
529
|
|
|
504
530
|
// The previous run's deriveds, whether this run finished or threw, and
|
|
505
531
|
// after this run's dependencies replaced the old ones (so a derived the
|
|
@@ -514,21 +540,6 @@ export function run_block(block, first_run = false) {
|
|
|
514
540
|
|
|
515
541
|
var empty_get_set = { get: undefined, set: undefined };
|
|
516
542
|
|
|
517
|
-
/**
|
|
518
|
-
* Complete all deferred boundary requests registered on a tracked value.
|
|
519
|
-
* @param {Tracked} t
|
|
520
|
-
* @param {boolean} [show_resolved=true]
|
|
521
|
-
*/
|
|
522
|
-
function complete_deferred_boundaries(t, show_resolved = true) {
|
|
523
|
-
if (t.d !== null) {
|
|
524
|
-
for (var i = 0; i < t.d.length; i++) {
|
|
525
|
-
var entry = t.d[i];
|
|
526
|
-
complete_boundary_request(entry.b, entry.r, show_resolved);
|
|
527
|
-
}
|
|
528
|
-
t.d = null;
|
|
529
|
-
}
|
|
530
|
-
}
|
|
531
|
-
|
|
532
543
|
class TrackedValue {
|
|
533
544
|
/**
|
|
534
545
|
* @param {any} v
|
|
@@ -564,17 +575,6 @@ class TrackedValue {
|
|
|
564
575
|
set value(v) {
|
|
565
576
|
set(this, v);
|
|
566
577
|
}
|
|
567
|
-
/**
|
|
568
|
-
* A read-only view: a derived over this value, for a receiver that should
|
|
569
|
-
* read but not write it. Equivalent to `track(() => tracked.value)`. The
|
|
570
|
-
* view is owned by the block that creates it, not by this value's block, so
|
|
571
|
-
* a view made in a component is released with that component even when the
|
|
572
|
-
* value outlives it.
|
|
573
|
-
* @returns {Derived}
|
|
574
|
-
*/
|
|
575
|
-
readOnly() {
|
|
576
|
-
return derived(() => get_tracked(this), /** @type {Block} */ (active_block));
|
|
577
|
-
}
|
|
578
578
|
}
|
|
579
579
|
|
|
580
580
|
class DerivedValue {
|
|
@@ -618,17 +618,6 @@ class DerivedValue {
|
|
|
618
618
|
set value(v) {
|
|
619
619
|
set(this, v);
|
|
620
620
|
}
|
|
621
|
-
/**
|
|
622
|
-
* A read-only view (see `TrackedValue#readOnly`). A derived without a
|
|
623
|
-
* setter is already read-only and is returned as is; a writable one is
|
|
624
|
-
* wrapped in a derived that follows it.
|
|
625
|
-
* @returns {Derived}
|
|
626
|
-
*/
|
|
627
|
-
readOnly() {
|
|
628
|
-
return this.a.set === undefined
|
|
629
|
-
? this
|
|
630
|
-
: derived(() => get_derived(this), /** @type {Block} */ (active_block));
|
|
631
|
-
}
|
|
632
621
|
}
|
|
633
622
|
|
|
634
623
|
if (DEV) {
|
|
@@ -649,7 +638,7 @@ export function tracked(v, block, hash, get, set) {
|
|
|
649
638
|
var t = /** @type {Tracked} */ (
|
|
650
639
|
new TrackedValue(v, block || active_block, get || set ? { get, set } : empty_get_set, hash)
|
|
651
640
|
);
|
|
652
|
-
if (hydrating && hash !== undefined) {
|
|
641
|
+
if (HYDRATION && hydrating && hash !== undefined) {
|
|
653
642
|
track_hash_reference.set(hash, t);
|
|
654
643
|
}
|
|
655
644
|
return t;
|
|
@@ -680,7 +669,7 @@ export function derived(fn, block, hash, get, set) {
|
|
|
680
669
|
created.push(d);
|
|
681
670
|
}
|
|
682
671
|
}
|
|
683
|
-
if (hydrating && hash !== undefined) {
|
|
672
|
+
if (HYDRATION && hydrating && hash !== undefined) {
|
|
684
673
|
track_hash_reference.set(hash, d);
|
|
685
674
|
}
|
|
686
675
|
return d;
|
|
@@ -774,6 +763,30 @@ function keep_deriveds(block, kept) {
|
|
|
774
763
|
block.f |= CREATES_DERIVEDS;
|
|
775
764
|
}
|
|
776
765
|
|
|
766
|
+
/**
|
|
767
|
+
* A read-only view of a tracked or derived value, for a receiver that should
|
|
768
|
+
* read but not write it: a derived over a tracked (or a writable derived),
|
|
769
|
+
* equivalent to `track(() => value.value)`; a read-only derived as it is; a
|
|
770
|
+
* plain value as it is, like `get`. The view is owned by the block that
|
|
771
|
+
* creates it, not by the value's block, so a view made in a component is
|
|
772
|
+
* released with that component even when the value outlives it.
|
|
773
|
+
* @param {any} value
|
|
774
|
+
* @param {Block} [block]
|
|
775
|
+
* @returns {any}
|
|
776
|
+
*/
|
|
777
|
+
export function track_read_only(value, block) {
|
|
778
|
+
if (!is_ripple_object(value)) {
|
|
779
|
+
return value;
|
|
780
|
+
}
|
|
781
|
+
var owner = block || /** @type {Block} */ (active_block);
|
|
782
|
+
if ((value.f & DERIVED) !== 0) {
|
|
783
|
+
var d = /** @type {Derived} */ (value);
|
|
784
|
+
return d.a.set === undefined ? d : derived(() => get_derived(d), owner);
|
|
785
|
+
}
|
|
786
|
+
var t = /** @type {Tracked} */ (value);
|
|
787
|
+
return derived(() => get_tracked(t), owner);
|
|
788
|
+
}
|
|
789
|
+
|
|
777
790
|
/**
|
|
778
791
|
* @param {any} v
|
|
779
792
|
* @param {Block} b
|
|
@@ -787,7 +800,7 @@ export function track(v, b, hash, get, set) {
|
|
|
787
800
|
return v;
|
|
788
801
|
}
|
|
789
802
|
if (b === null) {
|
|
790
|
-
|
|
803
|
+
track_orphan();
|
|
791
804
|
}
|
|
792
805
|
|
|
793
806
|
if (typeof v === 'function') {
|
|
@@ -796,243 +809,6 @@ export function track(v, b, hash, get, set) {
|
|
|
796
809
|
return tracked(v, b, hash, get, set);
|
|
797
810
|
}
|
|
798
811
|
|
|
799
|
-
/**
|
|
800
|
-
* @param {any} fn
|
|
801
|
-
* @param {Block} b
|
|
802
|
-
* @param {string} hash - Unique hash for SSR serialization/hydration
|
|
803
|
-
* @returns {Tracked | void}
|
|
804
|
-
*/
|
|
805
|
-
export function track_async(fn, b, hash) {
|
|
806
|
-
if (is_ripple_object(fn)) {
|
|
807
|
-
return fn;
|
|
808
|
-
}
|
|
809
|
-
|
|
810
|
-
var target_block = b || active_block;
|
|
811
|
-
if (target_block === null) {
|
|
812
|
-
throw new TypeError('trackAsync() requires a valid component context');
|
|
813
|
-
}
|
|
814
|
-
|
|
815
|
-
if (typeof fn !== 'function') {
|
|
816
|
-
throw new TypeError(
|
|
817
|
-
'trackAsync() only accepts function arguments that return a promise or an object with a promise property',
|
|
818
|
-
);
|
|
819
|
-
}
|
|
820
|
-
|
|
821
|
-
// During hydration, attempt to read serialized data from SSR
|
|
822
|
-
var had_hydration_data = false;
|
|
823
|
-
var hydration_value;
|
|
824
|
-
/** @type {string[] | undefined} */
|
|
825
|
-
var hydration_deps;
|
|
826
|
-
|
|
827
|
-
if (hydrating) {
|
|
828
|
-
var script_id = get_track_async_script_id(hash);
|
|
829
|
-
var script_el = document.getElementById(script_id);
|
|
830
|
-
if (script_el) {
|
|
831
|
-
var envelope = JSON.parse(/** @type {string} */ (script_el.textContent));
|
|
832
|
-
script_el.remove();
|
|
833
|
-
|
|
834
|
-
if (envelope.ok) {
|
|
835
|
-
had_hydration_data = true;
|
|
836
|
-
hydration_value =
|
|
837
|
-
envelope.payload === undefined ? envelope.value : revive(envelope.payload);
|
|
838
|
-
hydration_deps = envelope.deps;
|
|
839
|
-
} else {
|
|
840
|
-
// trigger the catch block
|
|
841
|
-
throw new Error(envelope.error?.message ?? 'Unknown server error');
|
|
842
|
-
}
|
|
843
|
-
}
|
|
844
|
-
}
|
|
845
|
-
|
|
846
|
-
var t = tracked(had_hydration_data ? hydration_value : SUSPENSE_PENDING, target_block, hash);
|
|
847
|
-
|
|
848
|
-
// Capture the call-site block for boundary lookups. target_block is the
|
|
849
|
-
// component's block (passed by compiler), but the actual try/pending/catch
|
|
850
|
-
// boundary is an ancestor of active_block (the block executing trackAsync).
|
|
851
|
-
var call_site_block = /** @type {Block} */ (active_block);
|
|
852
|
-
|
|
853
|
-
var version = 0;
|
|
854
|
-
/** @type {AbortController | null} */
|
|
855
|
-
var abort_controller = null;
|
|
856
|
-
var request_id = 0;
|
|
857
|
-
/** @type {Block | null} */
|
|
858
|
-
var boundary = null;
|
|
859
|
-
|
|
860
|
-
// TODO: decide if instead of insisting on pending, we create our own boundary
|
|
861
|
-
// we currently require a pending block upstream but we could also
|
|
862
|
-
// create a try/pending/catch boundary at mount and hydration like
|
|
863
|
-
// we do on the server so that there is always a boundary present.
|
|
864
|
-
// It can handle global pending when none were provided.
|
|
865
|
-
// Not sure about the catch boundary because if none were provided,
|
|
866
|
-
// the whole app for any error will be unmounted with the catch block rendered
|
|
867
|
-
|
|
868
|
-
// Find boundary from the call-site block.
|
|
869
|
-
boundary = get_pending_boundary(active_block);
|
|
870
|
-
if (boundary === null) {
|
|
871
|
-
throw new Error('Missing parent `try { ... } pending { ... }` statement');
|
|
872
|
-
}
|
|
873
|
-
|
|
874
|
-
// If we hydrated with resolved data, the SSR already completed this request.
|
|
875
|
-
// Otherwise mark a pending request on the boundary for the client-side run.
|
|
876
|
-
if (!had_hydration_data) {
|
|
877
|
-
request_id = begin_boundary_request(boundary);
|
|
878
|
-
}
|
|
879
|
-
|
|
880
|
-
pre_effect(() => {
|
|
881
|
-
if (had_hydration_data) {
|
|
882
|
-
// First run after hydration: skip fn() entirely (the SSR already
|
|
883
|
-
// produced the resolved value) and instead register the direct
|
|
884
|
-
// dependencies from the serialized deps list so future dep changes
|
|
885
|
-
// trigger a re-run via the normal async path.
|
|
886
|
-
had_hydration_data = false;
|
|
887
|
-
if (hydration_deps !== undefined) {
|
|
888
|
-
for (var i = 0; i < hydration_deps.length; i++) {
|
|
889
|
-
var dep_ref = track_hash_reference.get(hydration_deps[i]);
|
|
890
|
-
if (dep_ref !== undefined) {
|
|
891
|
-
get(dep_ref);
|
|
892
|
-
}
|
|
893
|
-
}
|
|
894
|
-
}
|
|
895
|
-
return;
|
|
896
|
-
}
|
|
897
|
-
|
|
898
|
-
var current_version = ++version;
|
|
899
|
-
|
|
900
|
-
// Abort previous in-flight request
|
|
901
|
-
if (abort_controller !== null && abort_controller.signal.aborted === false) {
|
|
902
|
-
abort_controller.abort(TRACKED_UPDATED);
|
|
903
|
-
}
|
|
904
|
-
abort_controller = null;
|
|
905
|
-
|
|
906
|
-
// Manage boundary request: replace if in-flight, or begin new if previous completed
|
|
907
|
-
if (request_id > 0 && boundary !== null) {
|
|
908
|
-
request_id = replace_boundary_request(boundary, request_id);
|
|
909
|
-
} else if (boundary !== null) {
|
|
910
|
-
request_id = begin_boundary_request(boundary);
|
|
911
|
-
}
|
|
912
|
-
|
|
913
|
-
// Set to pending before calling fn() in case it's sync.
|
|
914
|
-
if (t.__v !== SUSPENSE_PENDING) {
|
|
915
|
-
update_tracked_value_clock(t, SUSPENSE_PENDING);
|
|
916
|
-
}
|
|
917
|
-
|
|
918
|
-
// Temporarily allow mutations so set() doesn't throw inside the pre-effect
|
|
919
|
-
var previous_is_mutating_allowed = is_mutating_allowed;
|
|
920
|
-
is_mutating_allowed = true;
|
|
921
|
-
|
|
922
|
-
var result;
|
|
923
|
-
try {
|
|
924
|
-
result = fn();
|
|
925
|
-
} catch (e) {
|
|
926
|
-
is_mutating_allowed = previous_is_mutating_allowed;
|
|
927
|
-
if (e === ASYNC_DERIVED_READ_THROWN) {
|
|
928
|
-
// A dependency is still pending or rejected (e.g. chained trackAsync).
|
|
929
|
-
// Check if any dependency is rejected — if so, propagate rejection.
|
|
930
|
-
var dep = active_dependency;
|
|
931
|
-
while (dep !== null) {
|
|
932
|
-
if (dep.t.__v === SUSPENSE_REJECTED) {
|
|
933
|
-
update_tracked_value_clock(t, SUSPENSE_REJECTED);
|
|
934
|
-
complete_deferred_boundaries(t, false);
|
|
935
|
-
if (request_id > 0 && boundary !== null) {
|
|
936
|
-
complete_boundary_request(boundary, request_id, false);
|
|
937
|
-
request_id = 0;
|
|
938
|
-
}
|
|
939
|
-
return;
|
|
940
|
-
}
|
|
941
|
-
dep = dep.n;
|
|
942
|
-
}
|
|
943
|
-
// Dependencies are pending, not rejected — register deferred
|
|
944
|
-
// rejection so that if the boundary goes to catch mode, this
|
|
945
|
-
// tracked value is also set to REJECTED.
|
|
946
|
-
if (request_id > 0 && boundary !== null) {
|
|
947
|
-
register_boundary_deferred(boundary, request_id, () => {
|
|
948
|
-
update_tracked_value_clock(t, SUSPENSE_REJECTED);
|
|
949
|
-
});
|
|
950
|
-
}
|
|
951
|
-
return;
|
|
952
|
-
}
|
|
953
|
-
throw e;
|
|
954
|
-
}
|
|
955
|
-
is_mutating_allowed = previous_is_mutating_allowed;
|
|
956
|
-
|
|
957
|
-
// Check if the result is async
|
|
958
|
-
var previous_tracking = tracking;
|
|
959
|
-
tracking = false;
|
|
960
|
-
var async_result = get_async_track_result(result);
|
|
961
|
-
tracking = previous_tracking;
|
|
962
|
-
|
|
963
|
-
if (async_result === null) {
|
|
964
|
-
// Sync result
|
|
965
|
-
update_tracked_value_clock(t, result);
|
|
966
|
-
if (request_id > 0 && boundary !== null) {
|
|
967
|
-
complete_boundary_request(boundary, request_id);
|
|
968
|
-
request_id = 0;
|
|
969
|
-
}
|
|
970
|
-
return;
|
|
971
|
-
}
|
|
972
|
-
|
|
973
|
-
// Capture per-invocation so async closures (rejection handler, teardown)
|
|
974
|
-
// have a stable reference. The shared abort_controller is only read
|
|
975
|
-
// synchronously at the top of the pre_effect to abort the previous request.
|
|
976
|
-
var current_abort_controller = async_result.abort_controller;
|
|
977
|
-
abort_controller = current_abort_controller;
|
|
978
|
-
|
|
979
|
-
async_result.promise.then(
|
|
980
|
-
(resolved) => {
|
|
981
|
-
if (current_version !== version) {
|
|
982
|
-
// stale
|
|
983
|
-
return;
|
|
984
|
-
}
|
|
985
|
-
update_tracked_value_clock(t, resolved);
|
|
986
|
-
complete_deferred_boundaries(t);
|
|
987
|
-
if (request_id > 0 && boundary !== null) {
|
|
988
|
-
complete_boundary_request(boundary, request_id);
|
|
989
|
-
request_id = 0;
|
|
990
|
-
}
|
|
991
|
-
},
|
|
992
|
-
(error) => {
|
|
993
|
-
if (current_version !== version) return; // stale
|
|
994
|
-
|
|
995
|
-
var is_internal_abort =
|
|
996
|
-
error === TRACKED_UPDATED || current_abort_controller?.signal?.reason === TRACKED_UPDATED;
|
|
997
|
-
if (is_internal_abort) {
|
|
998
|
-
// Internal abort (superseded by a new request) — don't set rejected
|
|
999
|
-
if (request_id > 0 && boundary !== null) {
|
|
1000
|
-
complete_boundary_request(boundary, request_id, false);
|
|
1001
|
-
request_id = 0;
|
|
1002
|
-
}
|
|
1003
|
-
complete_deferred_boundaries(t, false);
|
|
1004
|
-
return;
|
|
1005
|
-
}
|
|
1006
|
-
|
|
1007
|
-
update_tracked_value_clock(t, SUSPENSE_REJECTED);
|
|
1008
|
-
complete_deferred_boundaries(t, false);
|
|
1009
|
-
|
|
1010
|
-
// Route error to catch boundary
|
|
1011
|
-
var boundary_with_catch = get_boundary_with_catch(call_site_block);
|
|
1012
|
-
if (boundary_with_catch !== null) {
|
|
1013
|
-
handle_boundary_error(boundary_with_catch, error);
|
|
1014
|
-
}
|
|
1015
|
-
|
|
1016
|
-
if (request_id > 0 && boundary !== null) {
|
|
1017
|
-
var should_show_resolved =
|
|
1018
|
-
boundary_with_catch === boundary || boundary === null ? false : true;
|
|
1019
|
-
complete_boundary_request(boundary, request_id, should_show_resolved);
|
|
1020
|
-
request_id = 0;
|
|
1021
|
-
}
|
|
1022
|
-
},
|
|
1023
|
-
);
|
|
1024
|
-
|
|
1025
|
-
return () => {
|
|
1026
|
-
// Teardown: abort in-flight request when block is destroyed
|
|
1027
|
-
if (current_abort_controller !== null && current_abort_controller.signal.aborted === false) {
|
|
1028
|
-
current_abort_controller.abort(TRACKED_UPDATED);
|
|
1029
|
-
}
|
|
1030
|
-
};
|
|
1031
|
-
});
|
|
1032
|
-
|
|
1033
|
-
return t;
|
|
1034
|
-
}
|
|
1035
|
-
|
|
1036
812
|
/**
|
|
1037
813
|
* @param {(Derived | Tracked) | (() => any)} t
|
|
1038
814
|
* @returns {boolean}
|
|
@@ -1463,9 +1239,7 @@ function flush_microtasks() {
|
|
|
1463
1239
|
|
|
1464
1240
|
flush_count++;
|
|
1465
1241
|
if (flush_count > 1001) {
|
|
1466
|
-
|
|
1467
|
-
'Maximum update depth exceeded. This typically indicates that an effect reads and writes the same piece of state.',
|
|
1468
|
-
);
|
|
1242
|
+
update_depth_exceeded();
|
|
1469
1243
|
}
|
|
1470
1244
|
var pending = queue;
|
|
1471
1245
|
queue = create_queue();
|
|
@@ -1627,9 +1401,7 @@ export function get_tracked(tracked) {
|
|
|
1627
1401
|
*/
|
|
1628
1402
|
export function set(tracked, value) {
|
|
1629
1403
|
if (!is_mutating_allowed) {
|
|
1630
|
-
|
|
1631
|
-
'Assignments or updates to tracked values are not allowed during computed "track(() => ...)" evaluation',
|
|
1632
|
-
);
|
|
1404
|
+
set_in_derived();
|
|
1633
1405
|
}
|
|
1634
1406
|
|
|
1635
1407
|
var old_value = tracked.__v;
|
|
@@ -1894,9 +1666,9 @@ export function scope() {
|
|
|
1894
1666
|
* @param {string} [err]
|
|
1895
1667
|
* @returns {Block | never}
|
|
1896
1668
|
*/
|
|
1897
|
-
export function safe_scope(err
|
|
1669
|
+
export function safe_scope(err) {
|
|
1898
1670
|
if (active_scope === null) {
|
|
1899
|
-
|
|
1671
|
+
scope_orphan(err);
|
|
1900
1672
|
}
|
|
1901
1673
|
|
|
1902
1674
|
return /** @type {Block} */ (active_scope);
|
|
@@ -2103,6 +1875,20 @@ export function with_ns(namespace, fn) {
|
|
|
2103
1875
|
}
|
|
2104
1876
|
}
|
|
2105
1877
|
|
|
1878
|
+
/**
|
|
1879
|
+
* Sets the active namespace and returns the previous one, for setup code that
|
|
1880
|
+
* switches namespace part-way through a render function (the children of a
|
|
1881
|
+
* `foreignObject`), where a `with_ns()` thunk would hide its declarations.
|
|
1882
|
+
* `run_block` restores the namespace after the render function either way.
|
|
1883
|
+
* @param {keyof typeof NAMESPACE_URI} namespace
|
|
1884
|
+
* @returns {keyof typeof NAMESPACE_URI}
|
|
1885
|
+
*/
|
|
1886
|
+
export function set_ns(namespace) {
|
|
1887
|
+
var previous_namespace = active_namespace;
|
|
1888
|
+
active_namespace = namespace;
|
|
1889
|
+
return previous_namespace;
|
|
1890
|
+
}
|
|
1891
|
+
|
|
2106
1892
|
/**
|
|
2107
1893
|
* @returns {symbol}
|
|
2108
1894
|
*/
|