@markless/runtime 0.1.1 → 0.2.1
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/{graph-B7awrnzg.js → graph-P12yh-2u.js} +96 -42
- package/dist/graph.d.ts +8 -3
- package/dist/graph.js +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/package.json +4 -3
|
@@ -161,9 +161,7 @@ function createRuntimeAsyncComputedNodes(asyncComputedInput) {
|
|
|
161
161
|
};
|
|
162
162
|
asyncComputedNodes.set(asyncComputed.graphNodeId, {
|
|
163
163
|
...asyncComputed,
|
|
164
|
-
|
|
165
|
-
keyValue: "key" in initialSnapshot ? initialSnapshot.key : void 0,
|
|
166
|
-
pendingSnapshotNeedsRunner: initialSnapshot.status === "pending",
|
|
164
|
+
gate: initialSnapshot.status === "pending" ? 1 : 0,
|
|
167
165
|
snapshot: initialSnapshot,
|
|
168
166
|
version: initialSnapshot.version
|
|
169
167
|
});
|
|
@@ -177,41 +175,75 @@ function readAsyncComputedNode(node, path, demand) {
|
|
|
177
175
|
return readPath(node.snapshot.value, path);
|
|
178
176
|
}
|
|
179
177
|
function demandAsyncComputed(input) {
|
|
180
|
-
if (
|
|
181
|
-
input
|
|
182
|
-
startAsyncComputed({
|
|
183
|
-
...input,
|
|
184
|
-
key: input.node.key(input.readGraph)
|
|
185
|
-
});
|
|
178
|
+
if (input.node.gate !== 1 && input.node.snapshot.status !== "idle") return;
|
|
179
|
+
advanceAsyncComputed(input);
|
|
186
180
|
}
|
|
187
181
|
function invalidateAsyncComputed(input) {
|
|
188
|
-
if (
|
|
182
|
+
if (input.node.snapshot.status === "idle") return;
|
|
183
|
+
advanceAsyncComputed(input);
|
|
184
|
+
}
|
|
185
|
+
function advanceAsyncComputed(input) {
|
|
186
|
+
const visited = new Set([input.node.graphNodeId]);
|
|
187
|
+
let blocked;
|
|
188
|
+
const visit = (graphNodeId) => {
|
|
189
|
+
if (visited.has(graphNodeId)) return;
|
|
190
|
+
visited.add(graphNodeId);
|
|
191
|
+
const dependency = input.asyncComputedNodes.get(graphNodeId);
|
|
192
|
+
if (dependency) {
|
|
193
|
+
if (dependency.snapshot.status === "idle" || dependency.snapshot.status === "pending") {
|
|
194
|
+
blocked = dependency;
|
|
195
|
+
input.demandAsyncComputed(dependency);
|
|
196
|
+
} else if (!blocked && dependency.snapshot.status === "rejected") blocked = dependency;
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
for (const dependency of input.computedNodes.get(graphNodeId)?.dependencies ?? []) visit(dependency.graphNodeId);
|
|
200
|
+
};
|
|
201
|
+
for (const dependency of input.node.dependencies) visit(dependency.graphNodeId);
|
|
202
|
+
if (blocked) {
|
|
203
|
+
commitDependencyBlock(input, blocked.snapshot.status === "rejected" ? "rejected" : "pending", blocked.snapshot.error);
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
189
206
|
const nextKey = input.node.key(input.readGraph);
|
|
190
|
-
if (input.node.snapshot.status !== "idle" && Object.is(input.node.
|
|
207
|
+
if (!input.node.gate && input.node.snapshot.status !== "idle" && Object.is(input.node.snapshot.key, nextKey)) return;
|
|
191
208
|
startAsyncComputed({
|
|
192
209
|
...input,
|
|
193
210
|
key: nextKey
|
|
194
211
|
});
|
|
195
212
|
}
|
|
213
|
+
function commitDependencyBlock(input, status, error) {
|
|
214
|
+
if (input.node.gate === 2 && (status === "pending" || input.node.snapshot.status === "rejected" && Object.is(input.node.snapshot.error, error))) return;
|
|
215
|
+
input.node.controller?.abort();
|
|
216
|
+
input.node.controller = void 0;
|
|
217
|
+
input.node.gate = 2;
|
|
218
|
+
const version = ++input.node.version;
|
|
219
|
+
const key = input.node.snapshot.key;
|
|
220
|
+
publish(input, status === "pending" ? {
|
|
221
|
+
status,
|
|
222
|
+
version,
|
|
223
|
+
key,
|
|
224
|
+
value: input.node.snapshot.value
|
|
225
|
+
} : {
|
|
226
|
+
status,
|
|
227
|
+
version,
|
|
228
|
+
key,
|
|
229
|
+
error
|
|
230
|
+
});
|
|
231
|
+
}
|
|
196
232
|
function startAsyncComputed(input) {
|
|
197
233
|
input.node.controller?.abort();
|
|
198
|
-
input.node.
|
|
234
|
+
input.node.gate = 0;
|
|
199
235
|
const controller = new AbortController();
|
|
200
|
-
const version = input.node.version
|
|
236
|
+
const version = ++input.node.version;
|
|
201
237
|
input.node.controller = controller;
|
|
202
|
-
input
|
|
203
|
-
input.node.version = version;
|
|
204
|
-
input.node.snapshot = {
|
|
238
|
+
publish(input, {
|
|
205
239
|
status: "pending",
|
|
206
240
|
version,
|
|
207
241
|
key: input.key,
|
|
208
242
|
value: input.node.snapshot.value
|
|
209
|
-
};
|
|
243
|
+
});
|
|
210
244
|
const commit = (snapshot) => {
|
|
211
|
-
if (input.node.version !== version
|
|
212
|
-
input
|
|
213
|
-
input.markDirtyPath(input.node.graphNodeId, []);
|
|
214
|
-
input.scheduleFlush();
|
|
245
|
+
if (input.node.version !== version) return;
|
|
246
|
+
publish(input, snapshot);
|
|
215
247
|
};
|
|
216
248
|
const commitRejected = (error) => commit({
|
|
217
249
|
status: "rejected",
|
|
@@ -233,6 +265,9 @@ function startAsyncComputed(input) {
|
|
|
233
265
|
} catch (error) {
|
|
234
266
|
commitRejected(error);
|
|
235
267
|
}
|
|
268
|
+
}
|
|
269
|
+
function publish(input, snapshot) {
|
|
270
|
+
input.node.snapshot = snapshot;
|
|
236
271
|
input.markDirtyPath(input.node.graphNodeId, []);
|
|
237
272
|
input.scheduleFlush();
|
|
238
273
|
}
|
|
@@ -258,19 +293,20 @@ function markComputedDirty(input) {
|
|
|
258
293
|
if (input.visited.has(input.graphNodeId)) return;
|
|
259
294
|
input.visited.add(input.graphNodeId);
|
|
260
295
|
const computed = input.computedNodes.get(input.graphNodeId);
|
|
261
|
-
if (computed)
|
|
296
|
+
if (!computed?.compute) return;
|
|
297
|
+
computed.dirty = true;
|
|
262
298
|
input.dirtyPaths.push({
|
|
263
299
|
graphNodeId: input.graphNodeId,
|
|
264
300
|
path: []
|
|
265
301
|
});
|
|
266
|
-
for (const dependent of input.computedNodes.values()) if (dependent.dependencies.some((dependency) => dependency.graphNodeId === input.graphNodeId)) markComputedDirty({
|
|
302
|
+
for (const dependent of input.computedNodes.values()) if (dependent.dependencies.some((dependency) => dependency.graphNodeId === input.graphNodeId) && dependent.compute) markComputedDirty({
|
|
267
303
|
...input,
|
|
268
304
|
graphNodeId: dependent.graphNodeId
|
|
269
305
|
});
|
|
270
306
|
for (const dependent of input.asyncComputedNodes.values()) if (dependent.dependencies.some((dependency) => dependency.graphNodeId === input.graphNodeId)) input.invalidateAsyncComputed(dependent);
|
|
271
307
|
}
|
|
272
308
|
function markDirtyComputedDependencies(input) {
|
|
273
|
-
for (const computed of input.computedNodes.values()) if (computed.dependencies.some((dependency) => dependency.graphNodeId === input.graphNodeId && pathsIntersect(input.path, dependency.path ?? []))) markComputedDirty({
|
|
309
|
+
for (const computed of input.computedNodes.values()) if (computed.dependencies.some((dependency) => dependency.graphNodeId === input.graphNodeId && pathsIntersect(input.path, dependency.path ?? [])) && computed.compute) markComputedDirty({
|
|
274
310
|
...input,
|
|
275
311
|
graphNodeId: computed.graphNodeId,
|
|
276
312
|
visited: /* @__PURE__ */ new Set()
|
|
@@ -394,6 +430,7 @@ function createSharedGraphPlane(input) {
|
|
|
394
430
|
//#region src/graph.ts
|
|
395
431
|
function createRuntimeGraph(input) {
|
|
396
432
|
const cells = /* @__PURE__ */ new Map();
|
|
433
|
+
const readInitializers = /* @__PURE__ */ new Map();
|
|
397
434
|
const computedNodes = createRuntimeComputedNodes(input.computed);
|
|
398
435
|
const asyncComputedNodes = createRuntimeAsyncComputedNodes(input.asyncComputed);
|
|
399
436
|
const subscriptions = [];
|
|
@@ -403,12 +440,28 @@ function createRuntimeGraph(input) {
|
|
|
403
440
|
let flushScheduled = false;
|
|
404
441
|
let flushing = false;
|
|
405
442
|
let activeFlush;
|
|
406
|
-
for (const cell of input.cells)
|
|
443
|
+
for (const cell of input.cells) {
|
|
444
|
+
cells.set(cell.graphNodeId, cell.value);
|
|
445
|
+
if (cell.readInitializer) readInitializers.set(cell.graphNodeId, cell.readInitializer);
|
|
446
|
+
}
|
|
407
447
|
const readGraph = (graphNodeId, path = []) => {
|
|
408
448
|
const computed = computedNodes.get(graphNodeId);
|
|
409
|
-
if (computed) return readComputedNode(computed, readGraph, path);
|
|
449
|
+
if (computed?.compute) return readComputedNode(computed, readGraph, path);
|
|
410
450
|
const asyncComputed = asyncComputedNodes.get(graphNodeId);
|
|
411
451
|
if (asyncComputed) return readAsyncComputedNode(asyncComputed, path, () => demandAsyncComputed$1(asyncComputed));
|
|
452
|
+
const initialize = readInitializers.get(graphNodeId);
|
|
453
|
+
if (initialize) {
|
|
454
|
+
readInitializers.delete(graphNodeId);
|
|
455
|
+
const current = cells.get(graphNodeId);
|
|
456
|
+
try {
|
|
457
|
+
const value = initialize();
|
|
458
|
+
if (!Object.is(current, value)) {
|
|
459
|
+
cells.set(graphNodeId, value);
|
|
460
|
+
markDirtyPath(graphNodeId, dirtyPathForGraphWrite(current, []));
|
|
461
|
+
scheduleFlush();
|
|
462
|
+
}
|
|
463
|
+
} catch {}
|
|
464
|
+
}
|
|
412
465
|
return readPath(cells.get(graphNodeId), path);
|
|
413
466
|
};
|
|
414
467
|
const markDirtyPath = (graphNodeId, path) => {
|
|
@@ -432,22 +485,22 @@ function createRuntimeGraph(input) {
|
|
|
432
485
|
flush();
|
|
433
486
|
});
|
|
434
487
|
};
|
|
435
|
-
const
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
};
|
|
443
|
-
const
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
};
|
|
488
|
+
const asyncComputedInput = () => ({
|
|
489
|
+
computedNodes,
|
|
490
|
+
asyncComputedNodes,
|
|
491
|
+
demandAsyncComputed: demandAsyncComputed$1,
|
|
492
|
+
readGraph,
|
|
493
|
+
markDirtyPath,
|
|
494
|
+
scheduleFlush
|
|
495
|
+
});
|
|
496
|
+
const demandAsyncComputed$1 = (node) => demandAsyncComputed({
|
|
497
|
+
node,
|
|
498
|
+
...asyncComputedInput()
|
|
499
|
+
});
|
|
500
|
+
const invalidateAsyncComputed$1 = (node) => invalidateAsyncComputed({
|
|
501
|
+
node,
|
|
502
|
+
...asyncComputedInput()
|
|
503
|
+
});
|
|
451
504
|
const sharedGraph = createSharedGraphPlane({
|
|
452
505
|
cells,
|
|
453
506
|
sharedDefinitionsInput: input.sharedDefinitions,
|
|
@@ -491,6 +544,7 @@ function createRuntimeGraph(input) {
|
|
|
491
544
|
};
|
|
492
545
|
return {
|
|
493
546
|
read: readGraph,
|
|
547
|
+
...typeof __MARKLESS_DEBUG_ENABLED__ !== "undefined" && __MARKLESS_DEBUG_ENABLED__ ? { peekAsyncSnapshot: (graphNodeId) => asyncComputedNodes.get(graphNodeId)?.snapshot } : {},
|
|
494
548
|
readShared: sharedGraph.readShared,
|
|
495
549
|
writeShared: sharedGraph.writeShared,
|
|
496
550
|
getSharedDefinition: sharedGraph.getSharedDefinition,
|
package/dist/graph.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { ProtocolStatePayload } from "@markless/serializer";
|
|
|
4
4
|
type RuntimeGraphCell = {
|
|
5
5
|
readonly graphNodeId: string;
|
|
6
6
|
readonly value: unknown;
|
|
7
|
+
readonly readInitializer?: () => unknown;
|
|
7
8
|
};
|
|
8
9
|
type RuntimeGraphRead = (graphNodeId: string, path?: ReadonlyArray<string>) => unknown;
|
|
9
10
|
type RuntimeGraphComputedDependency = {
|
|
@@ -15,6 +16,9 @@ type RuntimeGraphComputed = {
|
|
|
15
16
|
readonly dependencies: ReadonlyArray<RuntimeGraphComputedDependency>;
|
|
16
17
|
readonly compute: (read: RuntimeGraphRead) => unknown;
|
|
17
18
|
};
|
|
19
|
+
type RuntimeGraphComputedDependencyNode = Omit<RuntimeGraphComputed, 'compute'> & {
|
|
20
|
+
readonly compute?: never;
|
|
21
|
+
};
|
|
18
22
|
type RuntimeGraphAsyncSnapshot = {
|
|
19
23
|
readonly status: 'idle';
|
|
20
24
|
readonly version: 0;
|
|
@@ -73,7 +77,7 @@ type DomJournalResult = DomJournalEntry | ReadonlyArray<DomJournalEntry>;
|
|
|
73
77
|
type DomJournalListener = (entries: ReadonlyArray<DomJournalEntry>) => void | Promise<void>;
|
|
74
78
|
type RuntimeGraphInput = {
|
|
75
79
|
readonly cells: ReadonlyArray<RuntimeGraphCell>;
|
|
76
|
-
readonly computed?: ReadonlyArray<RuntimeGraphComputed>;
|
|
80
|
+
readonly computed?: ReadonlyArray<RuntimeGraphComputed | RuntimeGraphComputedDependencyNode>;
|
|
77
81
|
readonly asyncComputed?: ReadonlyArray<RuntimeGraphAsyncComputed>;
|
|
78
82
|
readonly sharedDefinitions?: ProtocolStatePayload['sharedDefinitions'];
|
|
79
83
|
};
|
|
@@ -118,7 +122,8 @@ type RuntimeGraphSubscription = {
|
|
|
118
122
|
readonly run: (value: unknown) => DomJournalResult | void | Promise<DomJournalResult | void>;
|
|
119
123
|
};
|
|
120
124
|
type RuntimeGraph = {
|
|
121
|
-
readonly read: (graphNodeId: string, path?: ReadonlyArray<string>) => unknown;
|
|
125
|
+
readonly read: (graphNodeId: string, path?: ReadonlyArray<string>) => unknown; /** Available only in debug-enabled builds (`__MARKLESS_DEBUG_ENABLED__`). */
|
|
126
|
+
readonly peekAsyncSnapshot?: (graphNodeId: string) => RuntimeGraphAsyncSnapshot | undefined;
|
|
122
127
|
readonly readShared: (definitionId: string, propertyName: string, path?: ReadonlyArray<string>) => unknown;
|
|
123
128
|
readonly writeShared: (write: RuntimeGraphSharedWrite) => boolean;
|
|
124
129
|
readonly getSharedDefinition: (definitionId: string) => NonNullable<ProtocolStatePayload['sharedDefinitions']>[number] | undefined;
|
|
@@ -137,4 +142,4 @@ type RuntimeGraph = {
|
|
|
137
142
|
type RuntimeSharedDefinition = NonNullable<ProtocolStatePayload['sharedDefinitions']>[number];
|
|
138
143
|
declare function createRuntimeGraph(input: RuntimeGraphInput): RuntimeGraph;
|
|
139
144
|
//#endregion
|
|
140
|
-
export { DomJournalEntry, DomJournalListener, DomJournalResult, RuntimeGraph, RuntimeGraphAsyncComputed, RuntimeGraphAsyncSnapshot, RuntimeGraphCall, RuntimeGraphCell, RuntimeGraphComputed, RuntimeGraphComputedDependency, RuntimeGraphDelete, RuntimeGraphInput, RuntimeGraphRead, RuntimeGraphSharedPatch, RuntimeGraphSharedPatchOperation, RuntimeGraphSharedWrite, RuntimeGraphSubscription, RuntimeGraphUpdate, RuntimeGraphWrite, createRuntimeGraph };
|
|
145
|
+
export { DomJournalEntry, DomJournalListener, DomJournalResult, RuntimeGraph, RuntimeGraphAsyncComputed, RuntimeGraphAsyncSnapshot, RuntimeGraphCall, RuntimeGraphCell, RuntimeGraphComputed, RuntimeGraphComputedDependency, RuntimeGraphComputedDependencyNode, RuntimeGraphDelete, RuntimeGraphInput, RuntimeGraphRead, RuntimeGraphSharedPatch, RuntimeGraphSharedPatchOperation, RuntimeGraphSharedWrite, RuntimeGraphSubscription, RuntimeGraphUpdate, RuntimeGraphWrite, createRuntimeGraph };
|
package/dist/graph.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as createRuntimeGraph } from "./graph-
|
|
1
|
+
import { t as createRuntimeGraph } from "./graph-P12yh-2u.js";
|
|
2
2
|
export { createRuntimeGraph };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { DomJournalEntry, DomJournalListener, DomJournalResult, RuntimeGraph, RuntimeGraphAsyncComputed, RuntimeGraphAsyncSnapshot, RuntimeGraphCall, RuntimeGraphCell, RuntimeGraphComputed, RuntimeGraphComputedDependency, RuntimeGraphDelete, RuntimeGraphInput, RuntimeGraphRead, RuntimeGraphSharedPatch, RuntimeGraphSharedPatchOperation, RuntimeGraphSharedWrite, RuntimeGraphSubscription, RuntimeGraphUpdate, RuntimeGraphWrite, createRuntimeGraph } from "./graph.js";
|
|
2
|
-
export { DomJournalEntry, DomJournalListener, DomJournalResult, RuntimeGraph, RuntimeGraphAsyncComputed, RuntimeGraphAsyncSnapshot, RuntimeGraphCall, RuntimeGraphCell, RuntimeGraphComputed, RuntimeGraphComputedDependency, RuntimeGraphDelete, RuntimeGraphInput, RuntimeGraphRead, RuntimeGraphSharedPatch, RuntimeGraphSharedPatchOperation, RuntimeGraphSharedWrite, RuntimeGraphSubscription, RuntimeGraphUpdate, RuntimeGraphWrite, createRuntimeGraph };
|
|
1
|
+
import { DomJournalEntry, DomJournalListener, DomJournalResult, RuntimeGraph, RuntimeGraphAsyncComputed, RuntimeGraphAsyncSnapshot, RuntimeGraphCall, RuntimeGraphCell, RuntimeGraphComputed, RuntimeGraphComputedDependency, RuntimeGraphComputedDependencyNode, RuntimeGraphDelete, RuntimeGraphInput, RuntimeGraphRead, RuntimeGraphSharedPatch, RuntimeGraphSharedPatchOperation, RuntimeGraphSharedWrite, RuntimeGraphSubscription, RuntimeGraphUpdate, RuntimeGraphWrite, createRuntimeGraph } from "./graph.js";
|
|
2
|
+
export { DomJournalEntry, DomJournalListener, DomJournalResult, RuntimeGraph, RuntimeGraphAsyncComputed, RuntimeGraphAsyncSnapshot, RuntimeGraphCall, RuntimeGraphCell, RuntimeGraphComputed, RuntimeGraphComputedDependency, RuntimeGraphComputedDependencyNode, RuntimeGraphDelete, RuntimeGraphInput, RuntimeGraphRead, RuntimeGraphSharedPatch, RuntimeGraphSharedPatchOperation, RuntimeGraphSharedWrite, RuntimeGraphSubscription, RuntimeGraphUpdate, RuntimeGraphWrite, createRuntimeGraph };
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as createRuntimeGraph } from "./graph-
|
|
1
|
+
import { t as createRuntimeGraph } from "./graph-P12yh-2u.js";
|
|
2
2
|
export { createRuntimeGraph };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@markless/runtime",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Markless state graph runtime: reads, writes, computed invalidation, flush journal.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
"directory": "packages/runtime"
|
|
10
10
|
},
|
|
11
11
|
"publishConfig": {
|
|
12
|
-
"access": "public"
|
|
12
|
+
"access": "public",
|
|
13
|
+
"provenance": true
|
|
13
14
|
},
|
|
14
15
|
"type": "module",
|
|
15
16
|
"sideEffects": false,
|
|
@@ -24,7 +25,7 @@
|
|
|
24
25
|
}
|
|
25
26
|
},
|
|
26
27
|
"dependencies": {
|
|
27
|
-
"@markless/serializer": "0.
|
|
28
|
+
"@markless/serializer": "0.2.1"
|
|
28
29
|
},
|
|
29
30
|
"files": [
|
|
30
31
|
"dist"
|