@graview/guest 0.1.8 → 0.1.10
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/README.md +301 -2
- package/client.js +2 -0
- package/dist/channel.d.ts +11 -3
- package/dist/channel.d.ts.map +1 -1
- package/dist/channel.js +5 -1
- package/dist/channel.js.map +1 -1
- package/dist/cli.d.ts +16 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +75 -0
- package/dist/cli.js.map +1 -0
- package/dist/client-script.d.ts +3 -0
- package/dist/client-script.d.ts.map +1 -0
- package/dist/client-script.js +21 -0
- package/dist/client-script.js.map +1 -0
- package/dist/client.d.ts +2 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.generated.d.ts +4 -0
- package/dist/client.generated.d.ts.map +1 -0
- package/dist/client.generated.js +9 -0
- package/dist/client.generated.js.map +1 -0
- package/dist/client.js +12 -0
- package/dist/client.js.map +1 -0
- package/dist/headless/describe.d.ts +19 -0
- package/dist/headless/describe.d.ts.map +1 -0
- package/dist/headless/describe.js +255 -0
- package/dist/headless/describe.js.map +1 -0
- package/dist/headless/draw.d.ts +17 -0
- package/dist/headless/draw.d.ts.map +1 -0
- package/dist/headless/draw.js +25 -0
- package/dist/headless/draw.js.map +1 -0
- package/dist/headless/index.d.ts +99 -0
- package/dist/headless/index.d.ts.map +1 -0
- package/dist/headless/index.js +143 -0
- package/dist/headless/index.js.map +1 -0
- package/dist/headless/judge.d.ts +16 -0
- package/dist/headless/judge.d.ts.map +1 -0
- package/dist/headless/judge.js +52 -0
- package/dist/headless/judge.js.map +1 -0
- package/dist/headless/node.d.ts +8 -0
- package/dist/headless/node.d.ts.map +1 -0
- package/dist/headless/node.js +80 -0
- package/dist/headless/node.js.map +1 -0
- package/dist/headless/protocol.d.ts +71 -0
- package/dist/headless/protocol.d.ts.map +1 -0
- package/dist/headless/protocol.js +14 -0
- package/dist/headless/protocol.js.map +1 -0
- package/dist/headless/runtime.d.ts +2 -0
- package/dist/headless/runtime.d.ts.map +1 -0
- package/dist/headless/runtime.generated.d.ts +2 -0
- package/dist/headless/runtime.generated.d.ts.map +1 -0
- package/dist/headless/runtime.generated.js +8 -0
- package/dist/headless/runtime.generated.js.map +1 -0
- package/dist/headless/runtime.js +171 -0
- package/dist/headless/runtime.js.map +1 -0
- package/dist/headless/tree.d.ts +54 -0
- package/dist/headless/tree.d.ts.map +1 -0
- package/dist/headless/tree.js +128 -0
- package/dist/headless/tree.js.map +1 -0
- package/dist/host/css.d.ts +118 -0
- package/dist/host/css.d.ts.map +1 -0
- package/dist/host/css.js +963 -0
- package/dist/host/css.js.map +1 -0
- package/dist/host/draw-budget.d.ts +10 -0
- package/dist/host/draw-budget.d.ts.map +1 -0
- package/dist/host/draw-budget.js +29 -0
- package/dist/host/draw-budget.js.map +1 -0
- package/dist/host/frame.d.ts +19 -1
- package/dist/host/frame.d.ts.map +1 -1
- package/dist/host/frame.js +21 -2
- package/dist/host/frame.js.map +1 -1
- package/dist/host/index.d.ts +4 -3
- package/dist/host/index.d.ts.map +1 -1
- package/dist/host/index.js +7 -1
- package/dist/host/index.js.map +1 -1
- package/dist/host/kit.d.ts +6 -2
- package/dist/host/kit.d.ts.map +1 -1
- package/dist/host/kit.js +12 -5
- package/dist/host/kit.js.map +1 -1
- package/dist/host/links.d.ts +24 -0
- package/dist/host/links.d.ts.map +1 -0
- package/dist/host/links.js +35 -0
- package/dist/host/links.js.map +1 -0
- package/dist/host/manifest.d.ts +50 -0
- package/dist/host/manifest.d.ts.map +1 -0
- package/dist/host/manifest.js +103 -0
- package/dist/host/manifest.js.map +1 -0
- package/dist/host/open-draw.d.ts +44 -0
- package/dist/host/open-draw.d.ts.map +1 -0
- package/dist/host/open-draw.js +108 -0
- package/dist/host/open-draw.js.map +1 -0
- package/dist/host/open-judge.d.ts +53 -0
- package/dist/host/open-judge.d.ts.map +1 -0
- package/dist/host/open-judge.js +95 -0
- package/dist/host/open-judge.js.map +1 -0
- package/dist/host/open-render.d.ts +32 -0
- package/dist/host/open-render.d.ts.map +1 -0
- package/dist/host/open-render.js +262 -0
- package/dist/host/open-render.js.map +1 -0
- package/dist/host/press.d.ts +15 -0
- package/dist/host/press.d.ts.map +1 -0
- package/dist/host/press.js +156 -0
- package/dist/host/press.js.map +1 -0
- package/dist/host/react.d.ts +15 -2
- package/dist/host/react.d.ts.map +1 -1
- package/dist/host/react.js +13 -5
- package/dist/host/react.js.map +1 -1
- package/dist/host/session.d.ts +94 -1
- package/dist/host/session.d.ts.map +1 -1
- package/dist/host/session.js +103 -14
- package/dist/host/session.js.map +1 -1
- package/dist/host/theme.d.ts +14 -0
- package/dist/host/theme.d.ts.map +1 -0
- package/dist/host/theme.js +51 -0
- package/dist/host/theme.js.map +1 -0
- package/dist/host/view-runtime.generated.d.ts +2 -0
- package/dist/host/view-runtime.generated.d.ts.map +1 -0
- package/dist/host/view-runtime.generated.js +7 -0
- package/dist/host/view-runtime.generated.js.map +1 -0
- package/dist/host/view-source.d.ts +5 -0
- package/dist/host/view-source.d.ts.map +1 -0
- package/dist/host/view-source.js +39 -0
- package/dist/host/view-source.js.map +1 -0
- package/dist/host/view.d.ts +134 -0
- package/dist/host/view.d.ts.map +1 -0
- package/dist/host/view.js +381 -0
- package/dist/host/view.js.map +1 -0
- package/dist/host/views.d.ts +10 -0
- package/dist/host/views.d.ts.map +1 -0
- package/dist/host/views.js +15 -0
- package/dist/host/views.js.map +1 -0
- package/dist/host/worker-react.d.ts +51 -0
- package/dist/host/worker-react.d.ts.map +1 -0
- package/dist/host/worker-react.js +123 -0
- package/dist/host/worker-react.js.map +1 -0
- package/dist/host/worker-start.d.ts +49 -0
- package/dist/host/worker-start.d.ts.map +1 -0
- package/dist/host/worker-start.js +122 -0
- package/dist/host/worker-start.js.map +1 -0
- package/dist/host/worker.d.ts +17 -12
- package/dist/host/worker.d.ts.map +1 -1
- package/dist/host/worker.js +58 -117
- package/dist/host/worker.js.map +1 -1
- package/dist/host/writes.d.ts +49 -0
- package/dist/host/writes.d.ts.map +1 -0
- package/dist/host/writes.js +76 -0
- package/dist/host/writes.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/open-kit.d.ts +148 -0
- package/dist/open-kit.d.ts.map +1 -0
- package/dist/open-kit.js +321 -0
- package/dist/open-kit.js.map +1 -0
- package/dist/protocol.d.ts +109 -3
- package/dist/protocol.d.ts.map +1 -1
- package/dist/protocol.js +13 -0
- package/dist/protocol.js.map +1 -1
- package/dist/worker/harden.d.ts +13 -2
- package/dist/worker/harden.d.ts.map +1 -1
- package/dist/worker/harden.js +10 -4
- package/dist/worker/harden.js.map +1 -1
- package/dist/worker/natives.d.ts +1 -0
- package/dist/worker/natives.d.ts.map +1 -1
- package/dist/worker/natives.js +4 -0
- package/dist/worker/natives.js.map +1 -1
- package/dist/worker/view-global.d.ts +70 -0
- package/dist/worker/view-global.d.ts.map +1 -0
- package/dist/worker/view-global.js +264 -0
- package/dist/worker/view-global.js.map +1 -0
- package/dist/worker/view.d.ts +14 -0
- package/dist/worker/view.d.ts.map +1 -0
- package/dist/worker/view.js +64 -0
- package/dist/worker/view.js.map +1 -0
- package/package.json +30 -4
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { GuestLimiter } from "./session.js";
|
|
2
|
+
/**
|
|
3
|
+
* Where a worker guest's code comes from: a URL the host already holds (a
|
|
4
|
+
* `blob:` URL, typically), or the script's text, which the host makes into
|
|
5
|
+
* a `blob:` URL itself. A chat's widget receives the text through a tool
|
|
6
|
+
* call and never fetches it.
|
|
7
|
+
*/
|
|
8
|
+
export type GuestWorkerSource = {
|
|
9
|
+
readonly url: string;
|
|
10
|
+
} | {
|
|
11
|
+
readonly script: string;
|
|
12
|
+
};
|
|
13
|
+
/** Why the worker is not running, as the watchdog and the start say it. */
|
|
14
|
+
export type WorkerStop = "refused" | "silent";
|
|
15
|
+
export interface StartedWorker {
|
|
16
|
+
readonly worker: Worker | undefined;
|
|
17
|
+
/** Whether a port message was the runtime's answer to a heartbeat (and so not the session's). */
|
|
18
|
+
answer(data: unknown): boolean;
|
|
19
|
+
/** Terminate it, close the port, and stop watching. */
|
|
20
|
+
stop(): void;
|
|
21
|
+
}
|
|
22
|
+
export interface StartWorkerOptions {
|
|
23
|
+
readonly source: GuestWorkerSource;
|
|
24
|
+
/** The worker's name: the view's. */
|
|
25
|
+
readonly name: string;
|
|
26
|
+
readonly limiter: GuestLimiter;
|
|
27
|
+
/** How long it has to say ready. */
|
|
28
|
+
readonly readyMs: number;
|
|
29
|
+
/** How long its runtime may go without answering a heartbeat, once ready. */
|
|
30
|
+
readonly silentMs: number;
|
|
31
|
+
/** A message to the worker's owner that was not one ready: dropped, and counted. */
|
|
32
|
+
readonly onDropped: () => void;
|
|
33
|
+
/** It said ready: here is its nonce and the host's end of its port, the hello already sent. */
|
|
34
|
+
readonly onReady: (nonce: string, port: MessagePort) => void;
|
|
35
|
+
/** It never started, or stopped answering: it has been stopped. `detail` is the engine's own words, when it gave some. */
|
|
36
|
+
readonly onStop: (reason: WorkerStop, detail?: string) => void;
|
|
37
|
+
/** It threw, uncaught, after it said ready: the engine's words for it. */
|
|
38
|
+
readonly onError?: (detail: string) => void;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* START A CLASSIC WORKER AND WATCH IT (FR-68): never `type: "module"`,
|
|
42
|
+
* which a `blob:` URL in an opaque origin cannot start; one `guest-ready`,
|
|
43
|
+
* answered with a fresh nonce and a MessageChannel; and, once it is ready,
|
|
44
|
+
* a heartbeat its runtime must answer, so a worker whose event loop is
|
|
45
|
+
* blocked is stopped. Shared by the kit's guest (`mountGuestWorker`) and the
|
|
46
|
+
* open kit's view (`mountWorkerView`).
|
|
47
|
+
*/
|
|
48
|
+
export declare function startWorker(window: Window & typeof globalThis, options: StartWorkerOptions): StartedWorker;
|
|
49
|
+
//# sourceMappingURL=worker-start.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worker-start.d.ts","sourceRoot":"","sources":["../../src/host/worker-start.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjD;;;;;GAKG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvF,2EAA2E;AAC3E,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,QAAQ,CAAC;AAE9C,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,iGAAiG;IACjG,MAAM,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC;IAC/B,uDAAuD;IACvD,IAAI,IAAI,IAAI,CAAC;CACd;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAC;IACnC,qCAAqC;IACrC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC;IAC/B,oCAAoC;IACpC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,6EAA6E;IAC7E,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,oFAAoF;IACpF,QAAQ,CAAC,SAAS,EAAE,MAAM,IAAI,CAAC;IAC/B,+FAA+F;IAC/F,QAAQ,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,KAAK,IAAI,CAAC;IAC7D,0HAA0H;IAC1H,QAAQ,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/D,0EAA0E;IAC1E,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7C;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,UAAU,EAAE,OAAO,EAAE,kBAAkB,GAAG,aAAa,CAwG1G"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { GUEST_PROTOCOL, isGuestReady } from "../protocol.js";
|
|
2
|
+
import { mintNonce } from "./nonce.js";
|
|
3
|
+
/**
|
|
4
|
+
* START A CLASSIC WORKER AND WATCH IT (FR-68): never `type: "module"`,
|
|
5
|
+
* which a `blob:` URL in an opaque origin cannot start; one `guest-ready`,
|
|
6
|
+
* answered with a fresh nonce and a MessageChannel; and, once it is ready,
|
|
7
|
+
* a heartbeat its runtime must answer, so a worker whose event loop is
|
|
8
|
+
* blocked is stopped. Shared by the kit's guest (`mountGuestWorker`) and the
|
|
9
|
+
* open kit's view (`mountWorkerView`).
|
|
10
|
+
*/
|
|
11
|
+
export function startWorker(window, options) {
|
|
12
|
+
const made = "script" in options.source ? window.URL.createObjectURL(new window.Blob([options.source.script], { type: "text/javascript" })) : undefined;
|
|
13
|
+
const url = "script" in options.source ? made : options.source.url;
|
|
14
|
+
let worker;
|
|
15
|
+
let port;
|
|
16
|
+
let ready = false;
|
|
17
|
+
let stopped = false;
|
|
18
|
+
let silence = 0;
|
|
19
|
+
let watchdog = 0;
|
|
20
|
+
let nonce = "";
|
|
21
|
+
let beat = 0;
|
|
22
|
+
let answered = 0;
|
|
23
|
+
const clock = window.performance;
|
|
24
|
+
let heard = clock.now();
|
|
25
|
+
const stop = () => {
|
|
26
|
+
if (stopped)
|
|
27
|
+
return;
|
|
28
|
+
stopped = true;
|
|
29
|
+
port?.close();
|
|
30
|
+
worker?.terminate();
|
|
31
|
+
worker = undefined;
|
|
32
|
+
window.clearTimeout(silence);
|
|
33
|
+
window.clearInterval(watchdog);
|
|
34
|
+
if (made)
|
|
35
|
+
window.URL.revokeObjectURL(made);
|
|
36
|
+
};
|
|
37
|
+
const halt = (reason, detail) => {
|
|
38
|
+
if (stopped)
|
|
39
|
+
return;
|
|
40
|
+
stop();
|
|
41
|
+
options.onStop(reason, detail);
|
|
42
|
+
};
|
|
43
|
+
const begin = () => {
|
|
44
|
+
window.clearTimeout(silence);
|
|
45
|
+
nonce = mintNonce();
|
|
46
|
+
const channel = new window.MessageChannel();
|
|
47
|
+
port = channel.port1;
|
|
48
|
+
/*
|
|
49
|
+
* THE WATCHDOG. The host asks on an interval, and the worker's runtime
|
|
50
|
+
* answers with the beat and the nonce. An answer is not a request: it
|
|
51
|
+
* spends none of the guest's message allowance.
|
|
52
|
+
*/
|
|
53
|
+
const silentMs = Math.max(1, options.silentMs);
|
|
54
|
+
const every = Math.max(10, Math.min(1_000, Math.floor(silentMs / 4)));
|
|
55
|
+
heard = clock.now();
|
|
56
|
+
let ticked = heard;
|
|
57
|
+
watchdog = window.setInterval(() => {
|
|
58
|
+
const at = clock.now();
|
|
59
|
+
/* The host's own page was held up: that time is not the guest's silence. */
|
|
60
|
+
if (at - ticked > every * 2)
|
|
61
|
+
heard += at - ticked - every;
|
|
62
|
+
ticked = at;
|
|
63
|
+
if (at - heard >= silentMs)
|
|
64
|
+
return halt("silent");
|
|
65
|
+
beat += 1;
|
|
66
|
+
channel.port1.postMessage({ type: "heartbeat", beat });
|
|
67
|
+
}, every);
|
|
68
|
+
const hello = { graview: "host-hello", protocol: GUEST_PROTOCOL, nonce, view: options.name };
|
|
69
|
+
worker.postMessage(hello, [channel.port2]);
|
|
70
|
+
options.onReady(nonce, channel.port1);
|
|
71
|
+
};
|
|
72
|
+
try {
|
|
73
|
+
/* Classic, on purpose: a module worker from a blob: URL is refused in an opaque origin (Chromium), which is where a chat's widget runs. */
|
|
74
|
+
worker = new window.Worker(url, { name: options.name });
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
worker = undefined;
|
|
78
|
+
}
|
|
79
|
+
if (!worker) {
|
|
80
|
+
queueMicrotask(() => halt("refused"));
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
silence = window.setTimeout(() => halt("silent"), options.readyMs);
|
|
84
|
+
worker.onerror = (event) => {
|
|
85
|
+
const said = typeof event.message === "string" && event.message !== "" ? event.message : undefined;
|
|
86
|
+
if (!ready)
|
|
87
|
+
halt("refused", said);
|
|
88
|
+
else
|
|
89
|
+
options.onError?.(said ?? "an error");
|
|
90
|
+
};
|
|
91
|
+
worker.onmessage = (event) => {
|
|
92
|
+
/*
|
|
93
|
+
* A worker's messages come from that worker alone. Its one message
|
|
94
|
+
* here is `guest-ready`, said once: a worker is one realm for its
|
|
95
|
+
* whole life, so a second ready is not a reload but a forgery.
|
|
96
|
+
*/
|
|
97
|
+
if (!options.limiter.message() || ready || !isGuestReady(event.data) || event.data.protocol !== GUEST_PROTOCOL) {
|
|
98
|
+
options.onDropped();
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
ready = true;
|
|
102
|
+
begin();
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
return {
|
|
106
|
+
get worker() {
|
|
107
|
+
return worker;
|
|
108
|
+
},
|
|
109
|
+
answer(data) {
|
|
110
|
+
const said = data;
|
|
111
|
+
if (typeof said !== "object" || said === null || said.type !== "heartbeat" || said.nonce !== nonce)
|
|
112
|
+
return false;
|
|
113
|
+
if (typeof said.beat === "number" && said.beat > answered && said.beat <= beat) {
|
|
114
|
+
answered = said.beat;
|
|
115
|
+
heard = clock.now();
|
|
116
|
+
}
|
|
117
|
+
return true;
|
|
118
|
+
},
|
|
119
|
+
stop,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=worker-start.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worker-start.js","sourceRoot":"","sources":["../../src/host/worker-start.ts"],"names":[],"mappings":"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"}
|
package/dist/host/worker.d.ts
CHANGED
|
@@ -2,17 +2,8 @@ import type { AnySchema, Principal, Store } from "@graview/core";
|
|
|
2
2
|
import type { Kit } from "../kit.js";
|
|
3
3
|
import { type KitLinks, type KitRefusal } from "./kit.js";
|
|
4
4
|
import { type GuestLimits, type GuestStats, type GuestViewInput } from "./session.js";
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
* `blob:` URL, typically), or the script's text, which the host makes into
|
|
8
|
-
* a `blob:` URL itself. A chat's widget receives the text through a tool
|
|
9
|
-
* call and never fetches it.
|
|
10
|
-
*/
|
|
11
|
-
export type GuestWorkerSource = {
|
|
12
|
-
readonly url: string;
|
|
13
|
-
} | {
|
|
14
|
-
readonly script: string;
|
|
15
|
-
};
|
|
5
|
+
import { type GuestWorkerSource } from "./worker-start.js";
|
|
6
|
+
export type { GuestWorkerSource } from "./worker-start.js";
|
|
16
7
|
/** Why a worker guest is not shown, for a host that falls back to something else. */
|
|
17
8
|
export type GuestWorkerFailure =
|
|
18
9
|
/** The page's policy refused the worker, or it failed before it said ready. */
|
|
@@ -24,7 +15,9 @@ export type GuestWorkerFailure =
|
|
|
24
15
|
*/
|
|
25
16
|
| "silent"
|
|
26
17
|
/** It drew more than `maxNodes`; it was stopped. */
|
|
27
|
-
| "budget"
|
|
18
|
+
| "budget"
|
|
19
|
+
/** What it sent took the page longer than `drawMs` of a second to draw; it was stopped, and the rest left undrawn. */
|
|
20
|
+
| "slow";
|
|
28
21
|
export interface MountGuestWorkerOptions<S extends AnySchema> {
|
|
29
22
|
readonly worker: GuestWorkerSource;
|
|
30
23
|
/** The view's registered name: what the rail says an act came through (`via: "view:<name>"`). */
|
|
@@ -52,6 +45,12 @@ export interface MountGuestWorkerOptions<S extends AnySchema> {
|
|
|
52
45
|
* up (a long task, a throttled background tab) is not counted.
|
|
53
46
|
*/
|
|
54
47
|
readonly silentMs?: number;
|
|
48
|
+
/**
|
|
49
|
+
* The most of any one second the host's page may spend drawing what the
|
|
50
|
+
* guest sent, in milliseconds: past it the batch is left undrawn, the
|
|
51
|
+
* worker is stopped and `onFailure` hears `slow`. 100 by default.
|
|
52
|
+
*/
|
|
53
|
+
readonly drawMs?: number;
|
|
55
54
|
};
|
|
56
55
|
/** The guest is not going to be shown, and why: the host can show something else in its place. */
|
|
57
56
|
readonly onFailure?: (reason: GuestWorkerFailure) => void;
|
|
@@ -93,4 +92,10 @@ export { createKitRenderer, GUEST_KIT_CSS, hostAttribute, kitValue } from "./kit
|
|
|
93
92
|
export type { KitLinks, KitRefusal, KitRefusalReason, KitRenderer, KitRendererOptions } from "./kit.js";
|
|
94
93
|
export { GUEST_KIT, KIT_LINK_TARGETS, KIT_TONES } from "../kit.js";
|
|
95
94
|
export type { GuestKitElement, Kit, KitComponent, KitEvent, KitProperty, KitPropertyType, KitTone } from "../kit.js";
|
|
95
|
+
export { mountWorkerView } from "./view.js";
|
|
96
|
+
export type { MountWorkerViewOptions, WorkerView, WorkerViewCode, WorkerViewFailure, WorkerViewLimits } from "./view.js";
|
|
97
|
+
export type { ViewRefusal } from "./open-draw.js";
|
|
98
|
+
export type { OpenRefusal, OpenRefusalReason } from "./open-judge.js";
|
|
99
|
+
export type { CssRefusal, CssRefusalReason } from "./css.js";
|
|
100
|
+
export type { Destination } from "./links.js";
|
|
96
101
|
//# sourceMappingURL=worker.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../../src/host/worker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AACjE,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../../src/host/worker.ts"],"names":[],"mappings":"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"}
|
package/dist/host/worker.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { GUEST_PROTOCOL, isGuestReady } from "../protocol.js";
|
|
2
1
|
import { createKitRenderer, GUEST_KIT_CSS } from "./kit.js";
|
|
3
|
-
import { mintNonce } from "./nonce.js";
|
|
4
2
|
import { createGuestHost, createGuestLimiter } from "./session.js";
|
|
3
|
+
import { startWorker } from "./worker-start.js";
|
|
4
|
+
import { createDrawBudget } from "./draw-budget.js";
|
|
5
5
|
const STYLE_ID = "graview-guest-kit";
|
|
6
6
|
/**
|
|
7
7
|
* MOUNT A GUEST VIEW IN A WORKER (FR-68): a classic Web Worker — never
|
|
@@ -29,10 +29,10 @@ export function mountGuestWorker(element, options) {
|
|
|
29
29
|
element.appendChild(container);
|
|
30
30
|
const stats = { applied: 0, refused: 0, dropped: 0 };
|
|
31
31
|
const limiter = createGuestLimiter(options.limits);
|
|
32
|
+
const budget = createDrawBudget(options.limits?.drawMs ?? 100, () => window.performance.now());
|
|
32
33
|
let session;
|
|
33
|
-
let port;
|
|
34
34
|
let renderer;
|
|
35
|
-
let
|
|
35
|
+
let started;
|
|
36
36
|
let failed = false;
|
|
37
37
|
let counted = { applied: 0, refused: 0, dropped: 0 };
|
|
38
38
|
const tally = () => {
|
|
@@ -44,22 +44,11 @@ export function mountGuestWorker(element, options) {
|
|
|
44
44
|
stats.dropped += now.dropped - counted.dropped;
|
|
45
45
|
counted = { ...now };
|
|
46
46
|
};
|
|
47
|
-
const made = "script" in options.worker ? window.URL.createObjectURL(new window.Blob([options.worker.script], { type: "text/javascript" })) : undefined;
|
|
48
|
-
const url = "script" in options.worker ? made : options.worker.url;
|
|
49
|
-
let silence = 0;
|
|
50
|
-
let watchdog = 0;
|
|
51
47
|
const stop = () => {
|
|
52
48
|
tally();
|
|
53
49
|
session?.dispose();
|
|
54
|
-
port?.close();
|
|
55
|
-
worker?.terminate();
|
|
56
50
|
session = undefined;
|
|
57
|
-
|
|
58
|
-
worker = undefined;
|
|
59
|
-
window.clearTimeout(silence);
|
|
60
|
-
window.clearInterval(watchdog);
|
|
61
|
-
if (made)
|
|
62
|
-
window.URL.revokeObjectURL(made);
|
|
51
|
+
started?.stop();
|
|
63
52
|
};
|
|
64
53
|
const fail = (reason) => {
|
|
65
54
|
if (failed)
|
|
@@ -69,110 +58,55 @@ export function mountGuestWorker(element, options) {
|
|
|
69
58
|
renderer?.dispose();
|
|
70
59
|
options.onFailure?.(reason);
|
|
71
60
|
};
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
ticked = at;
|
|
118
|
-
if (at - heard >= silentMs)
|
|
119
|
-
return fail("silent");
|
|
120
|
-
beat += 1;
|
|
121
|
-
channel.port1.postMessage({ type: "heartbeat", beat });
|
|
122
|
-
}, every);
|
|
123
|
-
const answer = (data) => {
|
|
124
|
-
const said = data;
|
|
125
|
-
if (typeof said !== "object" || said === null || said.type !== "heartbeat" || said.nonce !== nonce)
|
|
126
|
-
return false;
|
|
127
|
-
if (typeof said.beat === "number" && said.beat > answered && said.beat <= beat) {
|
|
128
|
-
answered = said.beat;
|
|
129
|
-
heard = clock.now();
|
|
130
|
-
}
|
|
131
|
-
return true;
|
|
132
|
-
};
|
|
133
|
-
channel.port1.onmessage = (message) => {
|
|
134
|
-
if (answer(message.data))
|
|
135
|
-
return;
|
|
136
|
-
live.receive(message.data);
|
|
137
|
-
tally();
|
|
138
|
-
};
|
|
139
|
-
const hello = { graview: "host-hello", protocol: GUEST_PROTOCOL, nonce, view: options.view };
|
|
140
|
-
worker.postMessage(hello, [channel.port2]);
|
|
141
|
-
live.push();
|
|
142
|
-
};
|
|
143
|
-
try {
|
|
144
|
-
/* Classic, on purpose: a module worker from a blob: URL is refused in an opaque origin (Chromium), which is where a chat's widget runs. */
|
|
145
|
-
worker = new window.Worker(url, { name: options.view });
|
|
146
|
-
}
|
|
147
|
-
catch {
|
|
148
|
-
worker = undefined;
|
|
149
|
-
}
|
|
150
|
-
if (!worker) {
|
|
151
|
-
queueMicrotask(() => fail("refused"));
|
|
152
|
-
}
|
|
153
|
-
else {
|
|
154
|
-
silence = window.setTimeout(() => fail("silent"), options.limits?.readyMs ?? 5_000);
|
|
155
|
-
worker.onerror = () => {
|
|
156
|
-
if (!session)
|
|
157
|
-
fail("refused");
|
|
158
|
-
};
|
|
159
|
-
worker.onmessage = (event) => {
|
|
160
|
-
/*
|
|
161
|
-
* A worker's messages come from that worker alone. Its one message
|
|
162
|
-
* here is `guest-ready`, said once: a worker is one realm for its
|
|
163
|
-
* whole life, so a second ready is not a reload but a forgery.
|
|
164
|
-
*/
|
|
165
|
-
if (!limiter.message() || session || !isGuestReady(event.data) || event.data.protocol !== GUEST_PROTOCOL) {
|
|
166
|
-
stats.dropped += 1;
|
|
167
|
-
return;
|
|
168
|
-
}
|
|
169
|
-
ready();
|
|
170
|
-
};
|
|
171
|
-
}
|
|
61
|
+
started = startWorker(window, {
|
|
62
|
+
source: options.worker,
|
|
63
|
+
name: options.view,
|
|
64
|
+
limiter,
|
|
65
|
+
readyMs: options.limits?.readyMs ?? 5_000,
|
|
66
|
+
silentMs: options.limits?.silentMs ?? 5_000,
|
|
67
|
+
onDropped: () => (stats.dropped += 1),
|
|
68
|
+
onStop: (reason) => fail(reason),
|
|
69
|
+
onReady: (nonce, port) => {
|
|
70
|
+
const draw = createKitRenderer(container, {
|
|
71
|
+
...(options.kit ? { kit: options.kit } : {}),
|
|
72
|
+
...(options.links ? { links: options.links } : {}),
|
|
73
|
+
onEvent: (listener, detail) => port.postMessage({ type: "event", listener, ...(detail !== undefined ? { detail } : {}) }),
|
|
74
|
+
...(options.limits?.maxNodes !== undefined ? { maxNodes: options.limits.maxNodes } : {}),
|
|
75
|
+
onOverBudget: () => fail("budget"),
|
|
76
|
+
});
|
|
77
|
+
renderer = draw;
|
|
78
|
+
const live = createGuestHost({
|
|
79
|
+
store: options.store,
|
|
80
|
+
principal: options.principal,
|
|
81
|
+
view: options.view,
|
|
82
|
+
nonce,
|
|
83
|
+
send: (message) => port.postMessage(message),
|
|
84
|
+
/* The host's own time drawing the guest, at most `drawMs` of any second (draw-budget.ts). */
|
|
85
|
+
onRender: (records) => {
|
|
86
|
+
if (!budget.draw((spent) => draw.apply(records, spent)))
|
|
87
|
+
fail("slow");
|
|
88
|
+
},
|
|
89
|
+
...(options.input ? { input: options.input } : {}),
|
|
90
|
+
...(options.onNavigate ? { onNavigate: options.onNavigate } : {}),
|
|
91
|
+
onSize: options.onSize ?? ((height) => (container.style.minHeight = `${height}px`)),
|
|
92
|
+
...(options.limits ? { limits: options.limits } : {}),
|
|
93
|
+
limiter,
|
|
94
|
+
});
|
|
95
|
+
session = live;
|
|
96
|
+
/* An answer to the watchdog is the runtime's, not a request; one with any other nonce goes to the session, which drops it. */
|
|
97
|
+
port.onmessage = (message) => {
|
|
98
|
+
if (started?.answer(message.data))
|
|
99
|
+
return;
|
|
100
|
+
live.receive(message.data);
|
|
101
|
+
tally();
|
|
102
|
+
};
|
|
103
|
+
live.push();
|
|
104
|
+
},
|
|
105
|
+
});
|
|
172
106
|
return {
|
|
173
107
|
element: container,
|
|
174
108
|
get worker() {
|
|
175
|
-
return worker;
|
|
109
|
+
return started?.worker;
|
|
176
110
|
},
|
|
177
111
|
update: () => session?.push(),
|
|
178
112
|
get stats() {
|
|
@@ -192,4 +126,11 @@ export function mountGuestWorker(element, options) {
|
|
|
192
126
|
}
|
|
193
127
|
export { createKitRenderer, GUEST_KIT_CSS, hostAttribute, kitValue } from "./kit.js";
|
|
194
128
|
export { GUEST_KIT, KIT_LINK_TARGETS, KIT_TONES } from "../kit.js";
|
|
129
|
+
/*
|
|
130
|
+
* A worker view on the open kit (FR-90): HTML, SVG and CSS drawn into a
|
|
131
|
+
* shadow root of the host's, with what could fetch or escape not drawn.
|
|
132
|
+
* Its sanitiser and renderer are a chunk of their own, fetched the first
|
|
133
|
+
* time a view draws.
|
|
134
|
+
*/
|
|
135
|
+
export { mountWorkerView } from "./view.js";
|
|
195
136
|
//# sourceMappingURL=worker.js.map
|
package/dist/host/worker.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"worker.js","sourceRoot":"","sources":["../../src/host/worker.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"worker.js","sourceRoot":"","sources":["../../src/host/worker.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { AnySchema, Store } from "@graview/core";
|
|
2
|
+
import type { GuestRefusal } from "../protocol.js";
|
|
3
|
+
import { type ManifestAct, type WorkerViewManifest } from "./manifest.js";
|
|
4
|
+
/** Whether every member of the app sees every record: no sight is declared, or every kind is seen by everybody, whole. */
|
|
5
|
+
export declare function sightIsTotal<S extends AnySchema>(store: Store<S>): boolean;
|
|
6
|
+
/** A field the host read, at the moment of a press. */
|
|
7
|
+
export interface PressedField {
|
|
8
|
+
readonly name: string;
|
|
9
|
+
readonly value: string | number | boolean;
|
|
10
|
+
/** The viewer typed it: the last change was theirs, and the view has not set it since. */
|
|
11
|
+
readonly typed: boolean;
|
|
12
|
+
/** It holds nothing, and nobody has touched it. */
|
|
13
|
+
readonly empty: boolean;
|
|
14
|
+
/**
|
|
15
|
+
* It is a pick — a radio, a select — whose value is the view's own words:
|
|
16
|
+
* the viewer chose it, but did not write it. Taken only as a value the
|
|
17
|
+
* app itself declares for the argument, or a record the view was shown.
|
|
18
|
+
*/
|
|
19
|
+
readonly chosen?: true;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* The values the app's own declaration allows an argument — an enum's
|
|
23
|
+
* options or a literal's values, through `optional()`, `default()` and the
|
|
24
|
+
* like — or undefined when it declares no such list.
|
|
25
|
+
*/
|
|
26
|
+
export declare function declaredValues(schema: unknown): readonly unknown[] | undefined;
|
|
27
|
+
/** A press the host saw on an element bound to an act. */
|
|
28
|
+
export interface Press {
|
|
29
|
+
/** What the view called the act (`data-act`). */
|
|
30
|
+
readonly as: string;
|
|
31
|
+
/** The record the element is bound to (`data-record`), if any. */
|
|
32
|
+
readonly record?: string;
|
|
33
|
+
/** The fields in the press's scope, read by the host. */
|
|
34
|
+
readonly fields: readonly PressedField[];
|
|
35
|
+
}
|
|
36
|
+
export type Judged = {
|
|
37
|
+
readonly ok: true;
|
|
38
|
+
readonly name: string;
|
|
39
|
+
readonly args: Record<string, unknown>;
|
|
40
|
+
} | {
|
|
41
|
+
readonly ok: false;
|
|
42
|
+
readonly reason: GuestRefusal;
|
|
43
|
+
readonly message: string;
|
|
44
|
+
};
|
|
45
|
+
export declare const refuse: (reason: GuestRefusal, message: string) => Judged;
|
|
46
|
+
export declare function entryFor(manifest: WorkerViewManifest, asked: string): ManifestAct | undefined;
|
|
47
|
+
/** An act the view asked for from its own code (`graview.act`). */
|
|
48
|
+
export declare function judgeCodeAct<S extends AnySchema>(store: Store<S>, manifest: WorkerViewManifest, name: string, args: Readonly<Record<string, unknown>>): Judged;
|
|
49
|
+
//# sourceMappingURL=writes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"writes.d.ts","sourceRoot":"","sources":["../../src/host/writes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAgB,KAAK,WAAW,EAAE,KAAK,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAsCxF,0HAA0H;AAC1H,wBAAgB,YAAY,CAAC,CAAC,SAAS,SAAS,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,OAAO,CAI1E;AAED,uDAAuD;AACvD,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;IAC1C,0FAA0F;IAC1F,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,mDAAmD;IACnD,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB;;;;OAIG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC;CACxB;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,OAAO,GAAG,SAAS,OAAO,EAAE,GAAG,SAAS,CAU9E;AAED,0DAA0D;AAC1D,MAAM,WAAW,KAAK;IACpB,iDAAiD;IACjD,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,kEAAkE;IAClE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,yDAAyD;IACzD,QAAQ,CAAC,MAAM,EAAE,SAAS,YAAY,EAAE,CAAC;CAC1C;AAED,MAAM,MAAM,MAAM,GAAG;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,GAAG;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAE5L,eAAO,MAAM,MAAM,GAAI,QAAQ,YAAY,EAAE,SAAS,MAAM,KAAG,MAA0C,CAAC;AAE1G,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,kBAAkB,EAAE,KAAK,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAE7F;AAED,mEAAmE;AACnE,wBAAgB,YAAY,CAAC,CAAC,SAAS,SAAS,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,kBAAkB,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,MAAM,CAK9J"}
|