@abide/abide 0.123.3 → 0.124.0
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/ABIDE.md +8 -5
- package/CHANGELOG.md +31 -0
- package/docs/REGISTRY.md +45 -12
- package/docs/RULEBOOK.md +24 -14
- package/docs/abide.md +999 -459
- package/package.json +1 -1
- package/src/compiler/ARRAY_MUTATORS.ts +20 -0
- package/src/compiler/LoweredFile.ts +609 -0
- package/src/compiler/Lowering.ts +17 -0
- package/src/compiler/SHARED_NAMES.ts +2 -0
- package/src/compiler/ShadowHost.ts +670 -0
- package/src/compiler/ShadowMap.ts +1 -1
- package/src/compiler/TypeSession.ts +71 -1715
- package/src/compiler/appLints.ts +109 -0
- package/src/compiler/checkedShadow.ts +1 -1
- package/src/compiler/classifyRead.ts +16 -1
- package/src/compiler/compileApp.ts +2 -2
- package/src/compiler/declaredExports.ts +44 -17
- package/src/compiler/diagnoseSources.ts +232 -0
- package/src/compiler/formatAbide.ts +5 -6
- package/src/compiler/handlersUnder.ts +16 -35
- package/src/compiler/reactiveReads.ts +235 -0
- package/src/compiler/reactiveTypes.ts +13 -0
- package/src/compiler/readsIn.ts +180 -81
- package/src/compiler/routesDeclaration.ts +46 -0
- package/src/compiler/scaffold.ts +7 -2
- package/src/compiler/serveLanguage.ts +26 -20
- package/src/compiler/splitImports.ts +2 -2
- package/src/server/DesktopSession.ts +213 -0
- package/src/server/Followers.ts +399 -0
- package/src/server/MODULE_QUERIES.ts +6 -2
- package/src/server/PageRender.ts +201 -0
- package/src/server/abideModules.ts +7 -7
- package/src/server/answerFailure.ts +3 -2
- package/src/server/answerRequest.ts +6 -70
- package/src/server/answerRpc.ts +48 -260
- package/src/server/answerSocket.ts +41 -463
- package/src/server/appKit.ts +1 -1
- package/src/server/argsContract.ts +1 -1
- package/src/server/createApp.ts +8 -2
- package/src/server/csp.ts +1 -1
- package/src/server/deferredBuilds.ts +3 -16
- package/src/server/faceOf.ts +1 -1
- package/src/server/generatedSurfaces.ts +2 -1
- package/src/server/handlerFileMount.ts +1 -1
- package/src/server/index.ts +1 -1
- package/src/server/installServer.ts +5 -9
- package/src/server/invokeHandler.ts +230 -0
- package/src/server/mountHandlers.ts +184 -0
- package/src/server/openDesktopWindow.ts +308 -0
- package/src/server/preload.ts +18 -0
- package/src/server/principal.ts +1 -1
- package/src/server/remote.ts +1 -1
- package/src/server/render.ts +31 -59
- package/src/server/requestScope.ts +5 -36
- package/src/server/runDesktop.ts +19 -447
- package/src/server/seedBuffer.ts +11 -11
- package/src/server/servedApp.ts +1 -1
- package/src/server/shell.ts +1 -1
- package/src/server/surfaceOf.ts +1 -1
- package/src/server/versionOf.ts +1 -1
- package/src/shared/RPC_SERVER.ts +27 -31
- package/src/shared/Schema.ts +1 -2
- package/src/shared/index.ts +1 -1
- package/src/shared/{note.ts → issueReport.ts} +22 -0
- package/src/shared/loadCall.ts +66 -0
- package/src/shared/reactive/Keyed.ts +23 -15
- package/src/shared/reactive/Reactive.ts +34 -1001
- package/src/shared/reactive/byOf.ts +2 -5
- package/src/shared/reactive/callLoad.ts +8 -14
- package/src/shared/reactive/cellShape.ts +734 -0
- package/src/shared/reactive/index.ts +12 -24
- package/src/shared/reactive/pairReactive.ts +5 -3
- package/src/shared/reactive/producer.ts +121 -0
- package/src/shared/reactive/scoped.ts +3 -2
- package/src/shared/reactive/selections.ts +209 -0
- package/src/shared/reactive/watch.ts +3 -4
- package/src/shared/rpc.ts +8 -5
- package/src/shared/validateJson.ts +1 -2
- package/src/shared/writePath.ts +29 -0
- package/src/ui/Router.ts +53 -69
- package/src/ui/outboxQueue.ts +2 -8
- package/src/ui/outcomeOf.ts +120 -0
- package/src/ui/socketWire.ts +3 -3
- package/src/ui/wire.ts +9 -10
- package/src/shared/LOAD_OFFLINE.ts +0 -15
- package/src/shared/LOAD_SIGNAL.ts +0 -10
- package/src/shared/issuesOf.ts +0 -18
- package/src/shared/reactive/ENTRY_LIVES.ts +0 -7
package/src/shared/RPC_SERVER.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* What an `Rpc` asks of the server it runs on, as slots the server fills.
|
|
3
3
|
*
|
|
4
|
-
* Filled by `#server/installServer.ts`,
|
|
5
|
-
* the app a `raw` call is answered by in process (16.42),
|
|
6
|
-
* reached, so a page's render can leave it for the browser's own call
|
|
4
|
+
* Filled by `#server/installServer.ts`, `raw` by `bootApp` and `following` by each app's followers:
|
|
5
|
+
* the request a rung is handed (16.11), the app a `raw` call is answered by in process (16.42), where
|
|
6
|
+
* a call reports the value it reached, so a page's render can leave it for the browser's own call
|
|
7
|
+
* (41.13), and who a trigger reaches (18.3). A leaf, for
|
|
7
8
|
* `CURRENT_ROUTER`'s reason: the isomorphic `Rpc` reads these and a browser bundle must not reach
|
|
8
9
|
* what fills them.
|
|
9
10
|
*/
|
|
@@ -18,33 +19,30 @@ export const RPC_SERVER: {
|
|
|
18
19
|
*/
|
|
19
20
|
timeout: () => number | undefined
|
|
20
21
|
/**
|
|
21
|
-
*
|
|
22
|
+
* Every app's followers while anyone follows (`#server/Followers.ts`), which a trigger reaches.
|
|
22
23
|
*
|
|
23
|
-
*
|
|
24
|
+
* Empty in a browser, where a trigger is the copy's own.
|
|
24
25
|
*/
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
* from this one.
|
|
46
|
-
*/
|
|
47
|
-
served: ((rpc: object, serving: unknown, key: string) => void) | null
|
|
26
|
+
following: Set<{
|
|
27
|
+
/** A trigger on an `Rpc`, sent to every browser following what its pattern names. 7.10, 7.18. */
|
|
28
|
+
broadcast(
|
|
29
|
+
rpc: object,
|
|
30
|
+
member: 'invalidate' | 'refresh',
|
|
31
|
+
pattern: unknown,
|
|
32
|
+
): void
|
|
33
|
+
/**
|
|
34
|
+
* A free trigger, sent to every followed copy carrying one of `tags`, or to every one where
|
|
35
|
+
* `tags` is `null`. 13.15.
|
|
36
|
+
*/
|
|
37
|
+
sweep(member: 'invalidate' | 'refresh', tags: string[] | null): void
|
|
38
|
+
/**
|
|
39
|
+
* The `global` entry an answer came from, and the key it is filed under (`GLOBAL_GETS`).
|
|
40
|
+
*
|
|
41
|
+
* 18.8 — so a follower subscribed before it existed, or fed from one since evicted, is
|
|
42
|
+
* fed from this one.
|
|
43
|
+
*/
|
|
44
|
+
served(rpc: object, serving: unknown, key: string): void
|
|
45
|
+
}>
|
|
48
46
|
/**
|
|
49
47
|
* How long a handler's own body took inside its rungs.
|
|
50
48
|
*
|
|
@@ -60,8 +58,6 @@ export const RPC_SERVER: {
|
|
|
60
58
|
raw: null,
|
|
61
59
|
reached: null,
|
|
62
60
|
timeout: () => undefined,
|
|
63
|
-
|
|
64
|
-
swept: null,
|
|
65
|
-
served: null,
|
|
61
|
+
following: new Set(),
|
|
66
62
|
handled: null,
|
|
67
63
|
}
|
package/src/shared/Schema.ts
CHANGED
|
@@ -11,9 +11,8 @@
|
|
|
11
11
|
// 19.6 IS THE OTHER HALF: coercion belongs to the pipeline and is never asked of a schema.
|
|
12
12
|
// Together they are what lets 19.3 be enforced at all — see `runSchema`.
|
|
13
13
|
|
|
14
|
+
import { issuesOf, note } from './issueReport.ts'
|
|
14
15
|
import type { Issues } from './Issues.ts'
|
|
15
|
-
import { issuesOf } from './issuesOf.ts'
|
|
16
|
-
import { note } from './note.ts'
|
|
17
16
|
import { isThenable } from './reactive/isThenable.ts'
|
|
18
17
|
import { untracked } from './reactive/tracking.ts'
|
|
19
18
|
|
package/src/shared/index.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
// AN ISSUES RECORD — what a refusal found, keyed by path (`Issues`, 15.8): filled one issue at a time
|
|
2
|
+
// by `note`, and handed out by `issuesOf` in the shape the value refused calls for.
|
|
3
|
+
|
|
1
4
|
import { putOwn } from './putOwn.ts'
|
|
2
5
|
|
|
3
6
|
/**
|
|
@@ -22,3 +25,22 @@ export function note(
|
|
|
22
25
|
if (Object.hasOwn(found, path)) (found[path] as string[]).push(said)
|
|
23
26
|
else putOwn(found, path, [said])
|
|
24
27
|
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Issues in the shape `Issues<T>` gives them for the value refused: by path for an object or an
|
|
31
|
+
* array, the bare list for anything else.
|
|
32
|
+
*
|
|
33
|
+
* DECIDED BY THE VALUE, because the value is all the runtime holds — `T` is erased. A scalar has
|
|
34
|
+
* no path to key by, so every issue about one stands on `''`, and handing back `{ '': [...] }`
|
|
35
|
+
* there is the wrapper `Issues<T>` says a reader never unwraps: `error().data[0]` read `undefined`.
|
|
36
|
+
*/
|
|
37
|
+
export function issuesOf(
|
|
38
|
+
found: Record<string, string[]>,
|
|
39
|
+
value: unknown,
|
|
40
|
+
): Record<string, string[]> | string[] {
|
|
41
|
+
if (typeof value === 'object' && value !== null) return found
|
|
42
|
+
const listed: string[] = []
|
|
43
|
+
for (const path in found)
|
|
44
|
+
for (const said of found[path] as string[]) listed.push(said)
|
|
45
|
+
return listed
|
|
46
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// THE CALL STARTING A LOAD, while it starts (16.49, 16.81, 46.7). `callLoad` opens it around the
|
|
2
|
+
// synchronous reach and closes it after, and a transport's body — the browser's wire — reads it as
|
|
3
|
+
// it starts: the core runs a body's first step inside the reach, so the call is still open there
|
|
4
|
+
// and closed by the time anything the body awaits comes back.
|
|
5
|
+
//
|
|
6
|
+
// THE ORDER IS THE INTERFACE. A body asks once, with `startingLoadCall`, and is handed what the call
|
|
7
|
+
// carried rather than the live record, so a read made after an await cannot see a closed call — it
|
|
8
|
+
// holds what it was handed. The writer's three verbs are the only way the record moves.
|
|
9
|
+
//
|
|
10
|
+
// A module of its own because `callLoad` (shared) opens it and the wire (ui) reads it.
|
|
11
|
+
|
|
12
|
+
const STARTING: {
|
|
13
|
+
signal: AbortSignal | undefined
|
|
14
|
+
offline: ((args: unknown) => unknown) | undefined
|
|
15
|
+
/**
|
|
16
|
+
* Where the body that queues the call asks for the value the call reached, filled once the reach
|
|
17
|
+
* returns: what the delivered answer lands in (46.7).
|
|
18
|
+
*/
|
|
19
|
+
standing: { value: unknown } | undefined
|
|
20
|
+
} = { signal: undefined, offline: undefined, standing: undefined }
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Opens the call starting a load: the load's own abort `signal` (16.49) and the call's `offline`
|
|
24
|
+
* (16.81), for the body the reach runs.
|
|
25
|
+
*/
|
|
26
|
+
export function beginLoadCall(
|
|
27
|
+
signal: AbortSignal | undefined,
|
|
28
|
+
offline: ((args: unknown) => unknown) | undefined,
|
|
29
|
+
): void {
|
|
30
|
+
STARTING.signal = signal
|
|
31
|
+
STARTING.offline = offline
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** Hands what the reach returned to a body that queued the call (46.7), where one asked. */
|
|
35
|
+
export function reachedInLoadCall(reached: unknown): void {
|
|
36
|
+
const standing = STARTING.standing
|
|
37
|
+
if (standing !== undefined) standing.value = reached
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** Closes the call: a body started after this reads no signal, no `offline` and no stand. */
|
|
41
|
+
export function endLoadCall(): void {
|
|
42
|
+
STARTING.signal = undefined
|
|
43
|
+
STARTING.offline = undefined
|
|
44
|
+
STARTING.standing = undefined
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* What the call starting this load carries, read by the body before anything awaits — both
|
|
49
|
+
* `undefined` for a load no call started (a refresh, a reload).
|
|
50
|
+
*/
|
|
51
|
+
export function startingLoadCall(): {
|
|
52
|
+
signal: AbortSignal | undefined
|
|
53
|
+
offline: ((args: unknown) => unknown) | undefined
|
|
54
|
+
} {
|
|
55
|
+
return { signal: STARTING.signal, offline: STARTING.offline }
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Where the value the call reaches will land, for a body that queues the call (46.7) — filled by
|
|
60
|
+
* `reachedInLoadCall` once the reach returns.
|
|
61
|
+
*/
|
|
62
|
+
export function standForLoadCall(): { value: unknown } {
|
|
63
|
+
const standing = { value: undefined }
|
|
64
|
+
STARTING.standing = standing
|
|
65
|
+
return standing
|
|
66
|
+
}
|
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
PARAMETER_DEFAULTS,
|
|
18
18
|
} from './argsContract.ts'
|
|
19
19
|
import { CELL } from './CELL.ts'
|
|
20
|
-
import {
|
|
20
|
+
import { type Callable, type Cell, refuseBothCaps } from './cellShape.ts'
|
|
21
21
|
import { armTimer } from './Expiry.ts'
|
|
22
22
|
import { KEYED_BRAND } from './KEYED_BRAND.ts'
|
|
23
23
|
import { matchesPattern } from './matchesPattern.ts'
|
|
@@ -28,14 +28,13 @@ import {
|
|
|
28
28
|
createReactive,
|
|
29
29
|
failedTransiently,
|
|
30
30
|
isStreamBody,
|
|
31
|
-
leaveSelections,
|
|
32
31
|
type Reactive,
|
|
33
32
|
type ReactiveOptions,
|
|
34
|
-
refuseBothCaps,
|
|
35
33
|
signalMoved,
|
|
36
34
|
startDeferred,
|
|
37
35
|
unwatchStore,
|
|
38
36
|
} from './Reactive.ts'
|
|
37
|
+
import { leaveSelections } from './selections.ts'
|
|
39
38
|
import {
|
|
40
39
|
detach,
|
|
41
40
|
detachProbes,
|
|
@@ -43,7 +42,6 @@ import {
|
|
|
43
42
|
newSubscriber,
|
|
44
43
|
newTracked,
|
|
45
44
|
type Subscriber,
|
|
46
|
-
type Tracked,
|
|
47
45
|
TRACKING,
|
|
48
46
|
trackProbe,
|
|
49
47
|
} from './tracking.ts'
|
|
@@ -89,7 +87,7 @@ export function isKeyed(
|
|
|
89
87
|
* The args are the entry's body argument and its cell already holds them for every run.
|
|
90
88
|
*/
|
|
91
89
|
function argsOf(entry: unknown): unknown {
|
|
92
|
-
return (entry as
|
|
90
|
+
return (entry as Callable)[CELL].args
|
|
93
91
|
}
|
|
94
92
|
|
|
95
93
|
// One entry of `Lifetime.followed`, which is in recency order: what an eviction needs beside when
|
|
@@ -97,11 +95,25 @@ function argsOf(entry: unknown): unknown {
|
|
|
97
95
|
type Follower = {
|
|
98
96
|
at: number
|
|
99
97
|
ms: number
|
|
100
|
-
cell:
|
|
98
|
+
cell: Cell
|
|
101
99
|
reader: Subscriber
|
|
102
100
|
evict: () => void
|
|
103
101
|
}
|
|
104
102
|
|
|
103
|
+
/**
|
|
104
|
+
* Each followed entry's `Follower`, by its cell: when it last produced, and how long it lives (11.45).
|
|
105
|
+
*/
|
|
106
|
+
const ENTRY_LIVES = new WeakMap<Cell, Follower>()
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* When the entry `cell` is stops being servable, by its `Keyed`'s `ttl` — infinity where it is no
|
|
110
|
+
* followed entry. What `deadlineOf` reads beside the value's own `ttl` (21.8).
|
|
111
|
+
*/
|
|
112
|
+
export function entryDeadline(cell: Cell): number {
|
|
113
|
+
const entry = ENTRY_LIVES.get(cell)
|
|
114
|
+
return entry === undefined ? Number.POSITIVE_INFINITY : entry.at + entry.ms
|
|
115
|
+
}
|
|
116
|
+
|
|
105
117
|
/**
|
|
106
118
|
* The life of every entry of one `Keyed`, evicting each once `ttl` passes without a production.
|
|
107
119
|
*
|
|
@@ -138,10 +150,10 @@ class Lifetime {
|
|
|
138
150
|
this.timer = null
|
|
139
151
|
}
|
|
140
152
|
|
|
141
|
-
follow(key: string, entry:
|
|
153
|
+
follow(key: string, entry: Callable, evict: () => void): void {
|
|
142
154
|
// 11.33: `Infinity` is the life of the scope, which no timer here can reach.
|
|
143
155
|
if (this.ms === Number.POSITIVE_INFINITY) return
|
|
144
|
-
const cell = entry[CELL]
|
|
156
|
+
const cell = entry[CELL]
|
|
145
157
|
// A MIRROR WITH NO ADOPTER — `Subscriber.isMirror` says why.
|
|
146
158
|
const reader = newSubscriber([cell], null, true)
|
|
147
159
|
const follower: Follower = { at: 0, ms: this.ms, cell, reader, evict }
|
|
@@ -424,13 +436,9 @@ export function createKeyed<
|
|
|
424
436
|
)
|
|
425
437
|
entries.set(key, created)
|
|
426
438
|
if (lifetime !== null)
|
|
427
|
-
lifetime.follow(
|
|
428
|
-
key,
|
|
429
|
-
|
|
430
|
-
() => {
|
|
431
|
-
release(key, created)
|
|
432
|
-
},
|
|
433
|
-
)
|
|
439
|
+
lifetime.follow(key, created as unknown as Callable, () => {
|
|
440
|
+
release(key, created)
|
|
441
|
+
})
|
|
434
442
|
if (starts !== null)
|
|
435
443
|
starts.reached(created, () => {
|
|
436
444
|
// 5.20: superseded before it started — not held, so a later reach starts afresh.
|