Skip to content

Commit 0c4ce5a

Browse files
misc improvements
1 parent d36894a commit 0c4ce5a

File tree

13 files changed

+170
-122
lines changed

13 files changed

+170
-122
lines changed

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

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -236,35 +236,35 @@ export function set_hydratable_key(key) {
236236
* @template T
237237
* @overload
238238
* @param {string} key
239-
* @param {() => T} fn
239+
* @param {() => Promise<T>} fn
240240
* @param {{ transport?: Transport<T> }} [options]
241-
* @returns {Promise<Awaited<T>>}
241+
* @returns {Promise<T>}
242242
*/
243243
/**
244244
* @template T
245245
* @overload
246-
* @param {() => T} fn
246+
* @param {() => Promise<T>} fn
247247
* @param {{ transport?: Transport<T> }} [options]
248-
* @returns {Promise<Awaited<T>>}
248+
* @returns {Promise<T>}
249249
*/
250250
/**
251251
* @template T
252-
* @param {string | (() => T)} key_or_fn
253-
* @param {(() => T) | { transport?: Transport<T> }} [fn_or_options]
252+
* @param {string | (() => Promise<T>)} key_or_fn
253+
* @param {(() => Promise<T>) | { transport?: Transport<T> }} [fn_or_options]
254254
* @param {{ transport?: Transport<T> }} [maybe_options]
255-
* @returns {Promise<Awaited<T>>}
255+
* @returns {Promise<T>}
256256
*/
257257
export function hydratable(key_or_fn, fn_or_options = {}, maybe_options = {}) {
258258
/** @type {string} */
259259
let key;
260-
/** @type {() => T} */
260+
/** @type {() => Promise<T>} */
261261
let fn;
262262
/** @type {{ transport?: Transport<T> }} */
263263
let options;
264264

265265
if (typeof key_or_fn === 'string') {
266266
key = key_or_fn;
267-
fn = /** @type {() => T} */ (fn_or_options);
267+
fn = /** @type {() => Promise<T>} */ (fn_or_options);
268268
options = /** @type {{ transport?: Transport<T> }} */ (maybe_options);
269269
} else {
270270
if (hydratable_key === null) {
@@ -274,7 +274,7 @@ export function hydratable(key_or_fn, fn_or_options = {}, maybe_options = {}) {
274274
} else {
275275
key = hydratable_key;
276276
}
277-
fn = /** @type {() => T} */ (key_or_fn);
277+
fn = /** @type {() => Promise<T>} */ (key_or_fn);
278278
options = /** @type {{ transport?: Transport<T> }} */ (fn_or_options);
279279
}
280280

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

Lines changed: 4 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { BaseCacheObserver } from '../../shared/cache-observer.js';
12
import { set_hydratable_key } from '../context.js';
23
import { tick } from '../runtime.js';
34
import { render_effect } from './effects.js';
@@ -67,58 +68,8 @@ function create_remover(key) {
6768
});
6869
}
6970

70-
/** @implements {ReadonlyMap<string, any>} */
71-
class ReadonlyCache {
72-
/** @type {ReadonlyMap<string, any>['get']} */
73-
get(key) {
74-
const entry = client_cache.get(key);
75-
return entry?.item;
76-
}
77-
78-
/** @type {ReadonlyMap<string, any>['has']} */
79-
has(key) {
80-
return client_cache.has(key);
81-
}
82-
83-
/** @type {ReadonlyMap<string, any>['size']} */
84-
get size() {
85-
return client_cache.size;
86-
}
87-
88-
/** @type {ReadonlyMap<string, any>['forEach']} */
89-
forEach(cb) {
90-
client_cache.forEach((entry, key) => cb(entry.item, key, this));
91-
}
92-
93-
/** @type {ReadonlyMap<string, any>['entries']} */
94-
*entries() {
95-
for (const [key, entry] of client_cache.entries()) {
96-
yield [key, entry.item];
97-
}
71+
export class CacheObserver extends BaseCacheObserver {
72+
constructor() {
73+
super(client_cache);
9874
}
99-
100-
/** @type {ReadonlyMap<string, any>['keys']} */
101-
*keys() {
102-
for (const key of client_cache.keys()) {
103-
yield key;
104-
}
105-
}
106-
107-
/** @type {ReadonlyMap<string, any>['values']} */
108-
*values() {
109-
for (const entry of client_cache.values()) {
110-
yield entry.item;
111-
}
112-
}
113-
114-
[Symbol.iterator]() {
115-
return this.entries();
116-
}
117-
}
118-
119-
const readonly_cache = new ReadonlyCache();
120-
121-
/** @returns {ReadonlyMap<string, any>} */
122-
export function get_cache() {
123-
return readonly_cache;
12475
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { deferred } from '../../shared/utils.js';
99
* @returns {ResourceType<T>}
1010
*/
1111
export function resource(fn) {
12-
return /** @type {ResourceType<T>} */ (/** @type {unknown} */ (new Resource(fn)));
12+
return /** @type {ResourceType<T>} */ (new Resource(fn));
1313
}
1414

1515
/**

packages/svelte/src/internal/server/context.js

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/** @import { ALSContext, SSRContext } from '#server' */
1+
/** @import { RenderContext, SSRContext } from '#server' */
22
/** @import { AsyncLocalStorage } from 'node:async_hooks' */
33
/** @import { Transport } from '#shared' */
44
import { DEV } from 'esm-env';
@@ -137,36 +137,36 @@ export function set_hydratable_key(key) {
137137
* @template T
138138
* @overload
139139
* @param {string} key
140-
* @param {() => T} fn
140+
* @param {() => Promise<T>} fn
141141
* @param {{ transport?: Transport<T> }} [options]
142-
* @returns {Promise<Awaited<T>>}
142+
* @returns {Promise<T>}
143143
*/
144144
/**
145145
* @template T
146146
* @overload
147-
* @param {() => T} fn
147+
* @param {() => Promise<T>} fn
148148
* @param {{ transport?: Transport<T> }} [options]
149-
* @returns {Promise<Awaited<T>>}
149+
* @returns {Promise<T>}
150150
*/
151151
/**
152152
* @template T
153-
* @param {string | (() => T)} key_or_fn
154-
* @param {(() => T) | { transport?: Transport<T> }} [fn_or_options]
153+
* @param {string | (() => Promise<T>)} key_or_fn
154+
* @param {(() => Promise<T>) | { transport?: Transport<T> }} [fn_or_options]
155155
* @param {{ transport?: Transport<T> }} [maybe_options]
156-
* @returns {Promise<Awaited<T>>}
156+
* @returns {Promise<T>}
157157
*/
158158
export function hydratable(key_or_fn, fn_or_options = {}, maybe_options = {}) {
159159
// TODO DRY out with #shared
160160
/** @type {string} */
161161
let key;
162-
/** @type {() => T} */
162+
/** @type {() => Promise<T>} */
163163
let fn;
164164
/** @type {{ transport?: Transport<T> }} */
165165
let options;
166166

167167
if (typeof key_or_fn === 'string') {
168168
key = key_or_fn;
169-
fn = /** @type {() => T} */ (fn_or_options);
169+
fn = /** @type {() => Promise<T>} */ (fn_or_options);
170170
options = /** @type {{ transport?: Transport<T> }} */ (maybe_options);
171171
} else {
172172
if (hydratable_key === null) {
@@ -176,7 +176,7 @@ export function hydratable(key_or_fn, fn_or_options = {}, maybe_options = {}) {
176176
} else {
177177
key = hydratable_key;
178178
}
179-
fn = /** @type {() => T} */ (key_or_fn);
179+
fn = /** @type {() => Promise<T>} */ (key_or_fn);
180180
options = /** @type {{ transport?: Transport<T> }} */ (fn_or_options);
181181
}
182182
const store = get_render_store();
@@ -191,15 +191,15 @@ export function hydratable(key_or_fn, fn_or_options = {}, maybe_options = {}) {
191191
return Promise.resolve(result);
192192
}
193193

194-
/** @type {ALSContext | null} */
194+
/** @type {RenderContext | null} */
195195
export let sync_store = null;
196196

197-
/** @param {ALSContext | null} store */
197+
/** @param {RenderContext | null} store */
198198
export function set_sync_store(store) {
199199
sync_store = store;
200200
}
201201

202-
/** @type {AsyncLocalStorage<ALSContext | null> | null} */
202+
/** @type {AsyncLocalStorage<RenderContext | null> | null} */
203203
let als = null;
204204

205205
import('node:async_hooks')
@@ -209,12 +209,12 @@ import('node:async_hooks')
209209
return null;
210210
});
211211

212-
/** @returns {ALSContext | null} */
212+
/** @returns {RenderContext | null} */
213213
function try_get_render_store() {
214214
return sync_store ?? als?.getStore() ?? null;
215215
}
216216

217-
/** @returns {ALSContext} */
217+
/** @returns {RenderContext} */
218218
export function get_render_store() {
219219
const store = try_get_render_store();
220220

@@ -238,7 +238,7 @@ export function get_render_store() {
238238

239239
/**
240240
* @template T
241-
* @param {ALSContext} store
241+
* @param {RenderContext} store
242242
* @param {() => Promise<T>} fn
243243
* @returns {Promise<T>}
244244
*/

packages/svelte/src/internal/server/reactivity/cache.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { BaseCacheObserver } from '../../shared/cache-observer';
12
import { get_render_store, set_hydratable_key } from '../context';
23

34
/**
@@ -19,6 +20,8 @@ export function cache(key, fn) {
1920
return new_entry;
2021
}
2122

22-
export function get_cache() {
23-
throw new Error('TODO: cannot get cache on the server');
23+
export class CacheObserver extends BaseCacheObserver {
24+
constructor() {
25+
super(get_render_store().cache);
26+
}
2427
}

packages/svelte/src/internal/server/reactivity/resource.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* @returns {ResourceType<T>}
77
*/
88
export function resource(fn) {
9-
return /** @type {ResourceType<T>} */ (/** @type {unknown} */ (new Resource(fn)));
9+
return /** @type {ResourceType<T>} */ (new Resource(fn));
1010
}
1111

1212
/**

packages/svelte/src/internal/server/types.d.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { MaybePromise, Transport } from '#shared';
1+
import type { Transport } from '#shared';
22
import type { Element } from './dev';
33
import type { Renderer } from './renderer';
44

@@ -15,11 +15,11 @@ export interface SSRContext {
1515
element?: Element;
1616
}
1717

18-
export interface ALSContext {
18+
export interface RenderContext {
1919
hydratables: Map<
2020
string,
2121
{
22-
value: MaybePromise<unknown>;
22+
value: Promise<unknown>;
2323
transport: Transport<any> | undefined;
2424
}
2525
>;
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/** @implements {ReadonlyMap<string, any>} */
2+
export class BaseCacheObserver {
3+
/** @type {ReadonlyMap<string, any>} */
4+
#cache;
5+
6+
/** @param {Map<string, any>} cache */
7+
constructor(cache) {
8+
this.#cache = cache;
9+
}
10+
11+
/** @type {ReadonlyMap<string, any>['get']} */
12+
get(key) {
13+
const entry = this.#cache.get(key);
14+
return entry?.item;
15+
}
16+
17+
/** @type {ReadonlyMap<string, any>['has']} */
18+
has(key) {
19+
return this.#cache.has(key);
20+
}
21+
22+
/** @type {ReadonlyMap<string, any>['size']} */
23+
get size() {
24+
return this.#cache.size;
25+
}
26+
27+
/** @type {ReadonlyMap<string, any>['forEach']} */
28+
forEach(cb) {
29+
this.#cache.forEach((entry, key) => cb(entry.item, key, this));
30+
}
31+
32+
/** @type {ReadonlyMap<string, any>['entries']} */
33+
*entries() {
34+
for (const [key, entry] of this.#cache.entries()) {
35+
yield [key, entry.item];
36+
}
37+
}
38+
39+
/** @type {ReadonlyMap<string, any>['keys']} */
40+
*keys() {
41+
for (const key of this.#cache.keys()) {
42+
yield key;
43+
}
44+
}
45+
46+
/** @type {ReadonlyMap<string, any>['values']} */
47+
*values() {
48+
for (const entry of this.#cache.values()) {
49+
yield entry.item;
50+
}
51+
}
52+
53+
[Symbol.iterator]() {
54+
return this.entries();
55+
}
56+
}

packages/svelte/src/internal/shared/types.d.ts

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,15 @@ export type Snapshot<T> = ReturnType<typeof $state.snapshot<T>>;
1111

1212
export type MaybePromise<T> = T | Promise<T>;
1313

14-
export type Transport<T> = {
15-
stringify: (value: T) => string;
16-
parse: (value: string) => T;
17-
};
14+
export type Transport<T> =
15+
| {
16+
stringify: (value: T) => string;
17+
parse?: undefined;
18+
}
19+
| {
20+
stringify?: undefined;
21+
parse: (value: string) => T;
22+
};
1823

1924
export type Resource<T> = {
2025
then: Promise<T>['then'];
@@ -23,16 +28,15 @@ export type Resource<T> = {
2328
refresh: () => Promise<void>;
2429
set: (value: T) => void;
2530
loading: boolean;
31+
error: any;
2632
} & (
2733
| {
2834
ready: false;
29-
value: undefined;
30-
error: undefined;
35+
current: undefined;
3136
}
3237
| {
3338
ready: true;
34-
value: T;
35-
error: any;
39+
current: T;
3640
}
3741
);
3842

packages/svelte/src/internal/shared/utils.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ export function run_all(arr) {
5050

5151
/**
5252
* TODO replace with Promise.withResolvers once supported widely enough
53-
* @template T
53+
* @template [T=void]
5454
*/
5555
export function deferred() {
5656
/** @type {(value: T) => void} */
@@ -120,8 +120,10 @@ export function to_array(value, n) {
120120
}
121121

122122
/**
123+
* @template [TReturn=any]
123124
* @param {string | URL} url
124125
* @param {GetRequestInit} [init]
126+
* @returns {Promise<TReturn>}
125127
*/
126128
export async function fetch_json(url, init) {
127129
const response = await fetch(url, init);

0 commit comments

Comments
 (0)