foldkit 0.82.7 → 0.82.8
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/dist/runtime/hmrProtocol.d.ts +2 -1
- package/dist/runtime/hmrProtocol.d.ts.map +1 -1
- package/dist/runtime/hmrProtocol.js +2 -1
- package/dist/runtime/preserveScheduler.d.ts +29 -0
- package/dist/runtime/preserveScheduler.d.ts.map +1 -0
- package/dist/runtime/preserveScheduler.js +36 -0
- package/dist/runtime/runtime.d.ts.map +1 -1
- package/dist/runtime/runtime.js +65 -20
- package/package.json +1 -1
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { Schema as S } from 'effect';
|
|
2
|
-
/** Browser → plugin: the runtime preserves its current Model under a stable id so it can be restored after a full reload. */
|
|
2
|
+
/** Browser → plugin: the runtime preserves its current Model under a stable id so it can be restored after a full reload. `isHmrReload` is set by the runtime when flushing on `vite:beforeFullReload` to mark the entry as eligible for restoration; absent or `false` for ordinary debounced preserves. */
|
|
3
3
|
export declare const PreserveModelMessage: S.Struct<{
|
|
4
4
|
readonly id: S.String;
|
|
5
5
|
readonly model: S.Unknown;
|
|
6
|
+
readonly isHmrReload: S.optional<S.Boolean>;
|
|
6
7
|
}>;
|
|
7
8
|
/** Browser → plugin: the runtime preserves its current Model under a stable id. */
|
|
8
9
|
export type PreserveModelMessage = typeof PreserveModelMessage.Type;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hmrProtocol.d.ts","sourceRoot":"","sources":["../../src/runtime/hmrProtocol.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC,EAAE,MAAM,QAAQ,CAAA;AAEpC,
|
|
1
|
+
{"version":3,"file":"hmrProtocol.d.ts","sourceRoot":"","sources":["../../src/runtime/hmrProtocol.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC,EAAE,MAAM,QAAQ,CAAA;AAEpC,6SAA6S;AAC7S,eAAO,MAAM,oBAAoB;;;;EAI/B,CAAA;AACF,mFAAmF;AACnF,MAAM,MAAM,oBAAoB,GAAG,OAAO,oBAAoB,CAAC,IAAI,CAAA;AAEnE,sGAAsG;AACtG,eAAO,MAAM,mBAAmB;;EAE9B,CAAA;AACF,wFAAwF;AACxF,MAAM,MAAM,mBAAmB,GAAG,OAAO,mBAAmB,CAAC,IAAI,CAAA;AAEjE,kKAAkK;AAClK,eAAO,MAAM,mBAAmB;;;EAG9B,CAAA;AACF,uFAAuF;AACvF,MAAM,MAAM,mBAAmB,GAAG,OAAO,mBAAmB,CAAC,IAAI,CAAA"}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { Schema as S } from 'effect';
|
|
2
|
-
/** Browser → plugin: the runtime preserves its current Model under a stable id so it can be restored after a full reload. */
|
|
2
|
+
/** Browser → plugin: the runtime preserves its current Model under a stable id so it can be restored after a full reload. `isHmrReload` is set by the runtime when flushing on `vite:beforeFullReload` to mark the entry as eligible for restoration; absent or `false` for ordinary debounced preserves. */
|
|
3
3
|
export const PreserveModelMessage = S.Struct({
|
|
4
4
|
id: S.String,
|
|
5
5
|
model: S.Unknown,
|
|
6
|
+
isHmrReload: S.optional(S.Boolean),
|
|
6
7
|
});
|
|
7
8
|
/** Browser → plugin: the runtime requests its previously-preserved Model on startup, scoped by id. */
|
|
8
9
|
export const RequestModelMessage = S.Struct({
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { type Duration, Effect, type Scope } from 'effect';
|
|
2
|
+
/**
|
|
3
|
+
* Defers a `preserve(model)` call so that bursts of dispatches do not pay the
|
|
4
|
+
* encoding cost on the hot path. `schedule` stashes the latest model and
|
|
5
|
+
* (re)starts a debounce timer; only one `onDebounce` runs per quiet window.
|
|
6
|
+
*
|
|
7
|
+
* `flush` runs `onFlush` with the latest pending model synchronously: it
|
|
8
|
+
* clears the pending slot atomically and invokes the callback, leaving any
|
|
9
|
+
* in-flight timer fiber to wake up, observe an empty pending slot, and exit
|
|
10
|
+
* as a no-op. Synchronous semantics let the runtime call this from
|
|
11
|
+
* `vite:beforeFullReload` via `Effect.runSync`, with no race against Vite's
|
|
12
|
+
* `location.reload()`. The two-callback split lets the flush path send
|
|
13
|
+
* `isHmrReload: true` while debounced calls send `false`.
|
|
14
|
+
*
|
|
15
|
+
* `cancel` drops the pending model and interrupts the in-flight fiber.
|
|
16
|
+
* Forked fibers are tied to the construction scope via `forkIn`, so scope
|
|
17
|
+
* closure interrupts them too. `cancel` covers manual teardown.
|
|
18
|
+
*/
|
|
19
|
+
export type PreserveScheduler<Model> = Readonly<{
|
|
20
|
+
schedule: (model: Model) => Effect.Effect<void>;
|
|
21
|
+
flush: Effect.Effect<void>;
|
|
22
|
+
cancel: Effect.Effect<void>;
|
|
23
|
+
}>;
|
|
24
|
+
export type PreserveSchedulerCallbacks<Model> = Readonly<{
|
|
25
|
+
onDebounce: (model: Model) => Effect.Effect<void>;
|
|
26
|
+
onFlush: (model: Model) => Effect.Effect<void>;
|
|
27
|
+
}>;
|
|
28
|
+
export declare const makePreserveScheduler: <Model>(callbacks: PreserveSchedulerCallbacks<Model>, delay: Duration.Input) => Effect.Effect<PreserveScheduler<Model>, never, Scope.Scope>;
|
|
29
|
+
//# sourceMappingURL=preserveScheduler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preserveScheduler.d.ts","sourceRoot":"","sources":["../../src/runtime/preserveScheduler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,EAAsB,KAAK,KAAK,EAAE,MAAM,QAAQ,CAAA;AAE9E;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,MAAM,iBAAiB,CAAC,KAAK,IAAI,QAAQ,CAAC;IAC9C,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IAC/C,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IAC1B,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;CAC5B,CAAC,CAAA;AAEF,MAAM,MAAM,0BAA0B,CAAC,KAAK,IAAI,QAAQ,CAAC;IACvD,UAAU,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IACjD,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;CAC/C,CAAC,CAAA;AAEF,eAAO,MAAM,qBAAqB,GAAI,KAAK,EACzC,WAAW,0BAA0B,CAAC,KAAK,CAAC,EAC5C,OAAO,QAAQ,CAAC,KAAK,KACpB,MAAM,CAAC,MAAM,CAAC,iBAAiB,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,CAgDzD,CAAA"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { Effect, Fiber, Option, Ref } from 'effect';
|
|
2
|
+
export const makePreserveScheduler = (callbacks, delay) => Effect.gen(function* () {
|
|
3
|
+
const scope = yield* Effect.scope;
|
|
4
|
+
const pendingRef = yield* Ref.make(Option.none());
|
|
5
|
+
const fiberRef = yield* Ref.make(Option.none());
|
|
6
|
+
const interruptPending = Effect.gen(function* () {
|
|
7
|
+
const maybeFiber = yield* Ref.get(fiberRef);
|
|
8
|
+
yield* Option.match(maybeFiber, {
|
|
9
|
+
onNone: () => Effect.void,
|
|
10
|
+
onSome: Fiber.interrupt,
|
|
11
|
+
});
|
|
12
|
+
yield* Ref.set(fiberRef, Option.none());
|
|
13
|
+
});
|
|
14
|
+
const runPending = (callback) => Effect.gen(function* () {
|
|
15
|
+
const maybePending = yield* Ref.getAndSet(pendingRef, Option.none());
|
|
16
|
+
yield* Option.match(maybePending, {
|
|
17
|
+
onNone: () => Effect.void,
|
|
18
|
+
onSome: callback,
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
const schedule = (model) => Effect.gen(function* () {
|
|
22
|
+
yield* Ref.set(pendingRef, Option.some(model));
|
|
23
|
+
yield* interruptPending;
|
|
24
|
+
const fiber = yield* Effect.forkIn(Effect.gen(function* () {
|
|
25
|
+
yield* Effect.sleep(delay);
|
|
26
|
+
yield* runPending(callbacks.onDebounce);
|
|
27
|
+
}), scope);
|
|
28
|
+
yield* Ref.set(fiberRef, Option.some(fiber));
|
|
29
|
+
});
|
|
30
|
+
const flush = runPending(callbacks.onFlush);
|
|
31
|
+
const cancel = Effect.gen(function* () {
|
|
32
|
+
yield* interruptPending;
|
|
33
|
+
yield* Ref.set(pendingRef, Option.none());
|
|
34
|
+
});
|
|
35
|
+
return { schedule, flush, cancel };
|
|
36
|
+
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/runtime/runtime.ts"],"names":[],"mappings":"AACA,OAAO,EAGL,OAAO,
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/runtime/runtime.ts"],"names":[],"mappings":"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"}
|
package/dist/runtime/runtime.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { BrowserRuntime } from '@effect/platform-browser';
|
|
2
|
-
import { Array, Cause, Context, Effect, Exit, Function, Layer, Match, Option, Predicate, PubSub, Queue, Record, Ref, Scheduler, Schema, Stream, SubscriptionRef, pipe, } from 'effect';
|
|
2
|
+
import { Array, Cause, Context, Duration, Effect, Exit, Function, Layer, Match, Option, Predicate, PubSub, Queue, Record, Ref, Scheduler, Schema, Stream, SubscriptionRef, pipe, } from 'effect';
|
|
3
3
|
import { h } from 'snabbdom';
|
|
4
4
|
import { createOverlay } from '../devTools/overlay.js';
|
|
5
5
|
import { createDevToolsStore } from '../devTools/store.js';
|
|
@@ -11,6 +11,7 @@ import { defaultCrashView, noOpDispatch } from './crashUI.js';
|
|
|
11
11
|
import { deepFreeze } from './deepFreeze.js';
|
|
12
12
|
import { PreserveModelMessage, RequestModelMessage, RestoreModelMessage, } from './hmrProtocol.js';
|
|
13
13
|
import { orderByPriority } from './messagePriority.js';
|
|
14
|
+
import { makePreserveScheduler } from './preserveScheduler.js';
|
|
14
15
|
import { makeRenderLoop } from './renderLoop.js';
|
|
15
16
|
const DEFAULT_DEV_TOOLS_SHOW = 'Development';
|
|
16
17
|
const DEFAULT_DEV_TOOLS_POSITION = 'BottomRight';
|
|
@@ -98,12 +99,40 @@ const makeRuntime = ({ Model, flags: resolveFlags, init, update, view, subscript
|
|
|
98
99
|
});
|
|
99
100
|
};
|
|
100
101
|
const flags = yield* resolveFlags;
|
|
101
|
-
const modelEquivalence = Schema.toEquivalence(Model);
|
|
102
102
|
const ModelJsonCodec = Schema.toCodecJson(
|
|
103
103
|
/* eslint-disable-next-line @typescript-eslint/consistent-type-assertions */
|
|
104
104
|
Model);
|
|
105
105
|
const decodeHmrModel = Schema.decodeUnknownExit(ModelJsonCodec);
|
|
106
106
|
const encodeHmrModel = Schema.encodeUnknownSync(ModelJsonCodec);
|
|
107
|
+
// NOTE: keep `encodeHmrModel` off the dispatch hot path. It walks
|
|
108
|
+
// the entire Model graph (O(modelSize) per call) and blocks input
|
|
109
|
+
// on large Models. The scheduler defers encoding to a quiet window
|
|
110
|
+
// and the `vite:beforeFullReload` flush covers the HMR boundary.
|
|
111
|
+
const PRESERVE_DEBOUNCE = Duration.millis(200);
|
|
112
|
+
const preserveScheduler = yield* makePreserveScheduler({
|
|
113
|
+
onDebounce: model => Effect.sync(() => preserveModel(runtimeId, encodeHmrModel(model), false)),
|
|
114
|
+
onFlush: model => Effect.sync(() => preserveModel(runtimeId, encodeHmrModel(model), true)),
|
|
115
|
+
}, PRESERVE_DEBOUNCE);
|
|
116
|
+
const hot = import.meta.hot;
|
|
117
|
+
if (hot) {
|
|
118
|
+
yield* Effect.acquireRelease(Effect.sync(() => {
|
|
119
|
+
// NOTE: Effect.runSync requires `flush` to have no async
|
|
120
|
+
// suspensions. The scheduler is built to satisfy that: flush
|
|
121
|
+
// clears pending atomically and runs `onFlush` without
|
|
122
|
+
// interrupting the in-flight timer fiber, which keeps the
|
|
123
|
+
// whole effect synchronous. If a future change adds an async
|
|
124
|
+
// step (interrupt-await, sleep, fork) on this path, Vite may
|
|
125
|
+
// race ahead to location.reload() before the encoded model
|
|
126
|
+
// reaches the plugin.
|
|
127
|
+
const handler = () => {
|
|
128
|
+
Effect.runSync(preserveScheduler.flush);
|
|
129
|
+
};
|
|
130
|
+
hot.on('vite:beforeFullReload', handler);
|
|
131
|
+
return handler;
|
|
132
|
+
}), handler => Effect.sync(() => hot.off('vite:beforeFullReload', handler)));
|
|
133
|
+
yield* Effect.addFinalizer(() => preserveScheduler.cancel);
|
|
134
|
+
}
|
|
135
|
+
const schedulePreserveModel = (model) => hot ? preserveScheduler.schedule(model) : Effect.void;
|
|
107
136
|
// NOTE: Each enqueued Message carries a priority. Within a single
|
|
108
137
|
// takeAll batch the drain loop processes all High before any Normal,
|
|
109
138
|
// so user input (view dispatch, navigation, subscription events,
|
|
@@ -160,10 +189,8 @@ const makeRuntime = ({ Model, flags: resolveFlags, init, update, view, subscript
|
|
|
160
189
|
yield* Ref.set(modelRef, nextModel);
|
|
161
190
|
yield* SubscriptionRef.set(isRenderPendingRef, true);
|
|
162
191
|
yield* Ref.set(lastDirtyMessageRef, Option.some(message));
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
preserveModel(runtimeId, encodeHmrModel(nextModel));
|
|
166
|
-
}
|
|
192
|
+
PubSub.publishUnsafe(modelPubSub, nextModel);
|
|
193
|
+
yield* schedulePreserveModel(nextModel);
|
|
167
194
|
}
|
|
168
195
|
yield* Effect.forEach(
|
|
169
196
|
/* eslint-disable-next-line @typescript-eslint/consistent-type-assertions */
|
|
@@ -260,22 +287,26 @@ const makeRuntime = ({ Model, flags: resolveFlags, init, update, view, subscript
|
|
|
260
287
|
yield* Effect.forkDetach(renderLoop);
|
|
261
288
|
addBfcacheRestoreListener();
|
|
262
289
|
if (subscriptions) {
|
|
263
|
-
yield* pipe(subscriptions, Record.toEntries, Effect.forEach(([_key, { schema, modelToDependencies, equivalence: customEquivalence, dependenciesToStream, },]) => {
|
|
264
|
-
|
|
290
|
+
yield* pipe(subscriptions, Record.toEntries, Effect.forEach(([_key, { schema, modelToDependencies, equivalence: customEquivalence, dependenciesToStream, },]) => Effect.gen(function* () {
|
|
291
|
+
const latestDependenciesRef = yield* Ref.make(modelToDependencies(initModel));
|
|
265
292
|
const equivalence = customEquivalence ?? Schema.toEquivalence(schema);
|
|
266
293
|
const modelStream = Stream.concat(Stream.make(initModel), Stream.fromPubSub(modelPubSub));
|
|
267
|
-
|
|
268
|
-
// NOTE:
|
|
269
|
-
// readDependencies() returns
|
|
270
|
-
//
|
|
271
|
-
|
|
294
|
+
yield* Effect.forkDetach(modelStream.pipe(
|
|
295
|
+
// NOTE: Ref.set runs upstream of Stream.changesWith on
|
|
296
|
+
// every model change, so readDependencies() returns
|
|
297
|
+
// current values even when the equivalence filter
|
|
298
|
+
// doesn't emit. Moving this into a tap after
|
|
299
|
+
// changesWith would silently break subscribers whose
|
|
300
|
+
// dependencies are equivalence-stable across model
|
|
301
|
+
// changes.
|
|
302
|
+
Stream.mapEffect(model => Effect.gen(function* () {
|
|
272
303
|
const dependencies = modelToDependencies(model);
|
|
273
|
-
|
|
304
|
+
yield* Ref.set(latestDependenciesRef, dependencies);
|
|
274
305
|
return dependencies;
|
|
275
|
-
}), Stream.changesWith(equivalence), Stream.switchMap(dependencies => dependenciesToStream(dependencies, () =>
|
|
306
|
+
})), Stream.changesWith(equivalence), Stream.switchMap(dependencies => dependenciesToStream(dependencies, () => Ref.getUnsafe(latestDependenciesRef))), Stream.runForEach(message =>
|
|
276
307
|
/* eslint-disable-next-line @typescript-eslint/consistent-type-assertions */
|
|
277
308
|
enqueueHigh(message)), provideAllResources));
|
|
278
|
-
}, {
|
|
309
|
+
}), {
|
|
279
310
|
concurrency: 'unbounded',
|
|
280
311
|
discard: true,
|
|
281
312
|
}));
|
|
@@ -346,10 +377,24 @@ const makeRuntime = ({ Model, flags: resolveFlags, init, update, view, subscript
|
|
|
346
377
|
yield* processBatch(batch);
|
|
347
378
|
yield* drainQueue;
|
|
348
379
|
});
|
|
380
|
+
// NOTE: only reset the burst timer when `Queue.take` actually blocked
|
|
381
|
+
// (queue was empty). With Command-chained dispatches each forever
|
|
382
|
+
// iteration handles a single message, so resetting unconditionally
|
|
383
|
+
// would keep the per-iteration cost under FRAME_BUDGET_MS forever
|
|
384
|
+
// and the runtime would never yield to the browser. Polling first
|
|
385
|
+
// distinguishes "continuing a burst" (poll returns Some) from
|
|
386
|
+
// "waking from idle" (poll returns None, take blocks).
|
|
349
387
|
yield* pipe(Effect.forever(Effect.gen(function* () {
|
|
350
|
-
const
|
|
388
|
+
const maybeFirst = yield* Queue.poll(messageQueue);
|
|
389
|
+
const first = yield* Option.match(maybeFirst, {
|
|
390
|
+
onNone: () => Effect.gen(function* () {
|
|
391
|
+
const message = yield* Queue.take(messageQueue);
|
|
392
|
+
yield* Ref.set(burstStartedAtRef, performance.now());
|
|
393
|
+
return message;
|
|
394
|
+
}),
|
|
395
|
+
onSome: Effect.succeed,
|
|
396
|
+
});
|
|
351
397
|
const rest = yield* pollAvailable;
|
|
352
|
-
yield* Ref.set(burstStartedAtRef, performance.now());
|
|
353
398
|
yield* processBatch(Array.prepend(rest, first));
|
|
354
399
|
yield* drainQueue;
|
|
355
400
|
})), Effect.catchCause(cause => Effect.sync(() => {
|
|
@@ -497,9 +542,9 @@ export function makeProgram(config) {
|
|
|
497
542
|
const encodePreserveModelMessage = Schema.encodeUnknownSync(PreserveModelMessage);
|
|
498
543
|
const encodeRequestModelMessage = Schema.encodeUnknownSync(RequestModelMessage);
|
|
499
544
|
const decodeRestoreModelMessage = Schema.decodeUnknownExit(RestoreModelMessage);
|
|
500
|
-
const preserveModel = (id,
|
|
545
|
+
const preserveModel = (id, encodedModel, isHmrReload) => {
|
|
501
546
|
if (import.meta.hot) {
|
|
502
|
-
import.meta.hot.send('foldkit:preserve-model', encodePreserveModelMessage(PreserveModelMessage.make({ id, model })));
|
|
547
|
+
import.meta.hot.send('foldkit:preserve-model', encodePreserveModelMessage(PreserveModelMessage.make({ id, model: encodedModel, isHmrReload })));
|
|
503
548
|
}
|
|
504
549
|
};
|
|
505
550
|
const PLUGIN_RESPONSE_TIMEOUT_MS = 500;
|