@graview/guest 0.1.9 → 0.1.12
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 +353 -3
- 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 +75 -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 +10 -0
- package/dist/host/view-source.d.ts.map +1 -0
- package/dist/host/view-source.js +44 -0
- package/dist/host/view-source.js.map +1 -0
- package/dist/host/view.d.ts +138 -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 +57 -0
- package/dist/host/worker-react.d.ts.map +1 -0
- package/dist/host/worker-react.js +129 -0
- package/dist/host/worker-react.js.map +1 -0
- package/dist/host/worker-start.d.ts +66 -0
- package/dist/host/worker-start.d.ts.map +1 -0
- package/dist/host/worker-start.js +188 -0
- package/dist/host/worker-start.js.map +1 -0
- package/dist/host/worker.d.ts +28 -19
- package/dist/host/worker.d.ts.map +1 -1
- package/dist/host/worker.js +60 -119
- 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,66 @@
|
|
|
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 a script the host serves from its own origin),
|
|
5
|
+
* or the script's text, which the host makes into a `blob:` URL itself. A
|
|
6
|
+
* chat's widget receives the text through a tool call and never fetches it.
|
|
7
|
+
*/
|
|
8
|
+
export type GuestWorkerSource = {
|
|
9
|
+
readonly url: string;
|
|
10
|
+
} | {
|
|
11
|
+
readonly script: string;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Why the worker is not running, as the start and the watchdog say it.
|
|
15
|
+
* `start`: it never said ready — the page's policy refused it, it failed
|
|
16
|
+
* before its first line ran, or `readyMs` passed. `silent`: it said ready,
|
|
17
|
+
* then went `silentMs` without answering the heartbeat.
|
|
18
|
+
*/
|
|
19
|
+
export type WorkerStop = "start" | "silent";
|
|
20
|
+
export interface StartedWorker {
|
|
21
|
+
readonly worker: Worker | undefined;
|
|
22
|
+
/** Whether a port message was the runtime's answer to a heartbeat (and so not the session's). */
|
|
23
|
+
answer(data: unknown): boolean;
|
|
24
|
+
/** Terminate it, close the port, and stop watching. */
|
|
25
|
+
stop(): void;
|
|
26
|
+
}
|
|
27
|
+
export interface StartWorkerOptions {
|
|
28
|
+
readonly source: GuestWorkerSource;
|
|
29
|
+
/** The worker's name: the view's. */
|
|
30
|
+
readonly name: string;
|
|
31
|
+
readonly limiter: GuestLimiter;
|
|
32
|
+
/** How long it has to say ready. */
|
|
33
|
+
readonly readyMs: number;
|
|
34
|
+
/** How long its runtime may go without answering a heartbeat, once ready. */
|
|
35
|
+
readonly silentMs: number;
|
|
36
|
+
/** A message to the worker's owner that was not one ready: dropped, and counted. */
|
|
37
|
+
readonly onDropped: () => void;
|
|
38
|
+
/** It said ready: here is its nonce and the host's end of its port, the hello already sent. */
|
|
39
|
+
readonly onReady: (nonce: string, port: MessagePort) => void;
|
|
40
|
+
/**
|
|
41
|
+
* It never started (`start`), or stopped answering (`silent`): it has
|
|
42
|
+
* been stopped, and this is said once. `detail` says why it did not
|
|
43
|
+
* start: the directive the page's policy lacks, the engine's own words,
|
|
44
|
+
* or the time it was given.
|
|
45
|
+
*/
|
|
46
|
+
readonly onStop: (reason: WorkerStop, detail?: string) => void;
|
|
47
|
+
/** It threw, uncaught, after it said ready: the engine's words for it. */
|
|
48
|
+
readonly onError?: (detail: string) => void;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* START A CLASSIC WORKER AND WATCH IT (FR-68): never `type: "module"`,
|
|
52
|
+
* which a `blob:` URL in an opaque origin cannot start; one `guest-ready`,
|
|
53
|
+
* answered with a fresh nonce and a MessageChannel; and, once it is ready,
|
|
54
|
+
* a heartbeat its runtime must answer, so a worker whose event loop is
|
|
55
|
+
* blocked is stopped. Shared by the kit's guest (`mountGuestWorker`) and the
|
|
56
|
+
* open kit's view (`mountWorkerView`).
|
|
57
|
+
*
|
|
58
|
+
* A WORKER THAT DOES NOT START SAYS `start` (FR-102), once: `new Worker`
|
|
59
|
+
* threw, it erred before it said ready, or `readyMs` passed with no ready.
|
|
60
|
+
* Each runtime says ready before a line of the guest runs, so no ready is
|
|
61
|
+
* no start. When the page's policy was the cause — a SecurityError, or a
|
|
62
|
+
* `securitypolicyviolation` the page reported for it — the sentence names
|
|
63
|
+
* the directive it lacks.
|
|
64
|
+
*/
|
|
65
|
+
export declare function startWorker(window: Window & typeof globalThis, options: StartWorkerOptions): StartedWorker;
|
|
66
|
+
//# 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;;;;;GAKG;AACH,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,QAAQ,CAAC;AAE5C,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;;;;;OAKG;IACH,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;AA0CD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,UAAU,EAAE,OAAO,EAAE,kBAAkB,GAAG,aAAa,CAqI1G"}
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import { GUEST_PROTOCOL, isGuestReady } from "../protocol.js";
|
|
2
|
+
import { mintNonce } from "./nonce.js";
|
|
3
|
+
/*
|
|
4
|
+
* WHAT A PAGE'S POLICY MUST ALLOW (FR-102). The engines refuse a worker
|
|
5
|
+
* three ways: Chromium and WebKit throw a SecurityError from `new Worker`;
|
|
6
|
+
* Firefox makes the worker, fires `securitypolicyviolation` on the document
|
|
7
|
+
* and then `error` on the worker with no message. The directive is
|
|
8
|
+
* `worker-src`, or `script-src` on a page with no `worker-src`, or
|
|
9
|
+
* `default-src` on a page with neither.
|
|
10
|
+
*/
|
|
11
|
+
const warned = new WeakSet();
|
|
12
|
+
/** The source a refused URL needed: `blob:` for a `blob:` URL, else the URL's origin. */
|
|
13
|
+
function sourceOf(url, window) {
|
|
14
|
+
if (url.startsWith("blob:"))
|
|
15
|
+
return "blob:";
|
|
16
|
+
try {
|
|
17
|
+
return new URL(url, window.location.href).origin;
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
return url;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
/** The sentence for a start the page's policy refused; the page's console is told once, however many views it refuses. */
|
|
24
|
+
function refusedByPolicy(window, url, directive) {
|
|
25
|
+
const source = sourceOf(url, window);
|
|
26
|
+
const said = `this page's Content-Security-Policy${directive ? ` (${directive})` : ""} does not allow a worker from ${source}: it needs worker-src ${source}`;
|
|
27
|
+
if (!warned.has(window)) {
|
|
28
|
+
warned.add(window);
|
|
29
|
+
window.console?.warn?.(`Graview: worker views cannot start on this page, because ${said}. A host that will not allow ${source} serves each view's whole script from its own origin and passes worker: { url } (the @graview/guest README, "What the host page allows").`);
|
|
30
|
+
}
|
|
31
|
+
return said;
|
|
32
|
+
}
|
|
33
|
+
/** Whether a policy violation is about this worker's URL: a `blob:` URL is reported as its scheme alone. */
|
|
34
|
+
function aboutUrl(blocked, url) {
|
|
35
|
+
if (blocked === "")
|
|
36
|
+
return true;
|
|
37
|
+
if (url.startsWith("blob:"))
|
|
38
|
+
return blocked.startsWith("blob");
|
|
39
|
+
return url.startsWith(blocked) || blocked.startsWith(url);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* START A CLASSIC WORKER AND WATCH IT (FR-68): never `type: "module"`,
|
|
43
|
+
* which a `blob:` URL in an opaque origin cannot start; one `guest-ready`,
|
|
44
|
+
* answered with a fresh nonce and a MessageChannel; and, once it is ready,
|
|
45
|
+
* a heartbeat its runtime must answer, so a worker whose event loop is
|
|
46
|
+
* blocked is stopped. Shared by the kit's guest (`mountGuestWorker`) and the
|
|
47
|
+
* open kit's view (`mountWorkerView`).
|
|
48
|
+
*
|
|
49
|
+
* A WORKER THAT DOES NOT START SAYS `start` (FR-102), once: `new Worker`
|
|
50
|
+
* threw, it erred before it said ready, or `readyMs` passed with no ready.
|
|
51
|
+
* Each runtime says ready before a line of the guest runs, so no ready is
|
|
52
|
+
* no start. When the page's policy was the cause — a SecurityError, or a
|
|
53
|
+
* `securitypolicyviolation` the page reported for it — the sentence names
|
|
54
|
+
* the directive it lacks.
|
|
55
|
+
*/
|
|
56
|
+
export function startWorker(window, options) {
|
|
57
|
+
const made = "script" in options.source ? window.URL.createObjectURL(new window.Blob([options.source.script], { type: "text/javascript" })) : undefined;
|
|
58
|
+
const url = "script" in options.source ? made : options.source.url;
|
|
59
|
+
let worker;
|
|
60
|
+
let port;
|
|
61
|
+
let ready = false;
|
|
62
|
+
let stopped = false;
|
|
63
|
+
let silence = 0;
|
|
64
|
+
let watchdog = 0;
|
|
65
|
+
let nonce = "";
|
|
66
|
+
let beat = 0;
|
|
67
|
+
let answered = 0;
|
|
68
|
+
const clock = window.performance;
|
|
69
|
+
let heard = clock.now();
|
|
70
|
+
/* A policy violation on the page while this worker starts: Firefox's one sign that the policy, not the script, refused it. */
|
|
71
|
+
let violated;
|
|
72
|
+
const violation = (event) => {
|
|
73
|
+
const said = event;
|
|
74
|
+
const directive = String(said.effectiveDirective || said.violatedDirective || "").split(" ")[0];
|
|
75
|
+
if (!/^(worker-src|script-src|script-src-elem|child-src|default-src)$/.test(directive))
|
|
76
|
+
return;
|
|
77
|
+
if (aboutUrl(String(said.blockedURI ?? ""), url))
|
|
78
|
+
violated = directive;
|
|
79
|
+
};
|
|
80
|
+
const page = window.document;
|
|
81
|
+
page?.addEventListener("securitypolicyviolation", violation);
|
|
82
|
+
const unhear = () => page?.removeEventListener("securitypolicyviolation", violation);
|
|
83
|
+
const stop = () => {
|
|
84
|
+
if (stopped)
|
|
85
|
+
return;
|
|
86
|
+
stopped = true;
|
|
87
|
+
port?.close();
|
|
88
|
+
worker?.terminate();
|
|
89
|
+
worker = undefined;
|
|
90
|
+
window.clearTimeout(silence);
|
|
91
|
+
window.clearInterval(watchdog);
|
|
92
|
+
unhear();
|
|
93
|
+
if (made)
|
|
94
|
+
window.URL.revokeObjectURL(made);
|
|
95
|
+
};
|
|
96
|
+
const halt = (reason, detail) => {
|
|
97
|
+
if (stopped)
|
|
98
|
+
return;
|
|
99
|
+
stop();
|
|
100
|
+
options.onStop(reason, detail);
|
|
101
|
+
};
|
|
102
|
+
const begin = () => {
|
|
103
|
+
window.clearTimeout(silence);
|
|
104
|
+
unhear();
|
|
105
|
+
nonce = mintNonce();
|
|
106
|
+
const channel = new window.MessageChannel();
|
|
107
|
+
port = channel.port1;
|
|
108
|
+
/*
|
|
109
|
+
* THE WATCHDOG. The host asks on an interval, and the worker's runtime
|
|
110
|
+
* answers with the beat and the nonce. An answer is not a request: it
|
|
111
|
+
* spends none of the guest's message allowance.
|
|
112
|
+
*/
|
|
113
|
+
const silentMs = Math.max(1, options.silentMs);
|
|
114
|
+
const every = Math.max(10, Math.min(1_000, Math.floor(silentMs / 4)));
|
|
115
|
+
heard = clock.now();
|
|
116
|
+
let ticked = heard;
|
|
117
|
+
watchdog = window.setInterval(() => {
|
|
118
|
+
const at = clock.now();
|
|
119
|
+
/* The host's own page was held up: that time is not the guest's silence. */
|
|
120
|
+
if (at - ticked > every * 2)
|
|
121
|
+
heard += at - ticked - every;
|
|
122
|
+
ticked = at;
|
|
123
|
+
if (at - heard >= silentMs)
|
|
124
|
+
return halt("silent");
|
|
125
|
+
beat += 1;
|
|
126
|
+
channel.port1.postMessage({ type: "heartbeat", beat });
|
|
127
|
+
}, every);
|
|
128
|
+
const hello = { graview: "host-hello", protocol: GUEST_PROTOCOL, nonce, view: options.name };
|
|
129
|
+
worker.postMessage(hello, [channel.port2]);
|
|
130
|
+
options.onReady(nonce, channel.port1);
|
|
131
|
+
};
|
|
132
|
+
try {
|
|
133
|
+
/* 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. */
|
|
134
|
+
worker = new window.Worker(url, { name: options.name });
|
|
135
|
+
}
|
|
136
|
+
catch (error) {
|
|
137
|
+
worker = undefined;
|
|
138
|
+
const thrown = error;
|
|
139
|
+
const detail = thrown?.name === "SecurityError" ? refusedByPolicy(window, url, violated) : `the worker could not be made: ${String(thrown?.message ?? error)}`;
|
|
140
|
+
queueMicrotask(() => halt("start", detail));
|
|
141
|
+
}
|
|
142
|
+
if (worker) {
|
|
143
|
+
silence = window.setTimeout(() => halt("start", `it never said it was ready in ${options.readyMs.toLocaleString("en-US")} ms`), options.readyMs);
|
|
144
|
+
worker.onerror = (event) => {
|
|
145
|
+
const said = typeof event.message === "string" && event.message !== "" ? event.message : undefined;
|
|
146
|
+
if (ready)
|
|
147
|
+
return void options.onError?.(said ?? "an error");
|
|
148
|
+
window.clearTimeout(silence);
|
|
149
|
+
/* Decided a task later, so a violation the page reports after the error (the order is the engine's) is heard. */
|
|
150
|
+
window.setTimeout(() => !ready &&
|
|
151
|
+
halt("start", violated
|
|
152
|
+
? refusedByPolicy(window, url, violated)
|
|
153
|
+
: said
|
|
154
|
+
? `it failed before it said ready: ${said}`
|
|
155
|
+
: "it failed before it said ready, and the engine gave no reason (a page policy that refuses it, or a script that does not load)"), 0);
|
|
156
|
+
};
|
|
157
|
+
worker.onmessage = (event) => {
|
|
158
|
+
/*
|
|
159
|
+
* A worker's messages come from that worker alone. Its one message
|
|
160
|
+
* here is `guest-ready`, said once: a worker is one realm for its
|
|
161
|
+
* whole life, so a second ready is not a reload but a forgery.
|
|
162
|
+
*/
|
|
163
|
+
if (!options.limiter.message() || ready || !isGuestReady(event.data) || event.data.protocol !== GUEST_PROTOCOL) {
|
|
164
|
+
options.onDropped();
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
ready = true;
|
|
168
|
+
begin();
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
return {
|
|
172
|
+
get worker() {
|
|
173
|
+
return worker;
|
|
174
|
+
},
|
|
175
|
+
answer(data) {
|
|
176
|
+
const said = data;
|
|
177
|
+
if (typeof said !== "object" || said === null || said.type !== "heartbeat" || said.nonce !== nonce)
|
|
178
|
+
return false;
|
|
179
|
+
if (typeof said.beat === "number" && said.beat > answered && said.beat <= beat) {
|
|
180
|
+
answered = said.beat;
|
|
181
|
+
heard = clock.now();
|
|
182
|
+
}
|
|
183
|
+
return true;
|
|
184
|
+
},
|
|
185
|
+
stop,
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
//# 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,29 +2,26 @@ 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
|
-
/** The page's policy refused the worker, or it failed before it said ready. */
|
|
19
|
-
"refused"
|
|
20
9
|
/**
|
|
21
|
-
* It never
|
|
22
|
-
*
|
|
23
|
-
*
|
|
10
|
+
* It never started (FR-102): the page's policy refused the worker (its
|
|
11
|
+
* Content-Security-Policy needs `worker-src blob:`), it failed before it
|
|
12
|
+
* said ready, or it did not say ready in `readyMs`. The detail says which.
|
|
13
|
+
*/
|
|
14
|
+
"start"
|
|
15
|
+
/**
|
|
16
|
+
* It said ready, then its runtime went `silentMs` without answering the
|
|
17
|
+
* host's heartbeat: its event loop is blocked (a `while (true)`), and it
|
|
18
|
+
* was stopped.
|
|
24
19
|
*/
|
|
25
20
|
| "silent"
|
|
26
21
|
/** It drew more than `maxNodes`; it was stopped. */
|
|
27
|
-
| "budget"
|
|
22
|
+
| "budget"
|
|
23
|
+
/** What it sent took the page longer than `drawMs` of a second to draw; it was stopped, and the rest left undrawn. */
|
|
24
|
+
| "slow";
|
|
28
25
|
export interface MountGuestWorkerOptions<S extends AnySchema> {
|
|
29
26
|
readonly worker: GuestWorkerSource;
|
|
30
27
|
/** The view's registered name: what the rail says an act came through (`via: "view:<name>"`). */
|
|
@@ -52,9 +49,15 @@ export interface MountGuestWorkerOptions<S extends AnySchema> {
|
|
|
52
49
|
* up (a long task, a throttled background tab) is not counted.
|
|
53
50
|
*/
|
|
54
51
|
readonly silentMs?: number;
|
|
52
|
+
/**
|
|
53
|
+
* The most of any one second the host's page may spend drawing what the
|
|
54
|
+
* guest sent, in milliseconds: past it the batch is left undrawn, the
|
|
55
|
+
* worker is stopped and `onFailure` hears `slow`. 100 by default.
|
|
56
|
+
*/
|
|
57
|
+
readonly drawMs?: number;
|
|
55
58
|
};
|
|
56
|
-
/** The guest is not going to be shown, and why: the host can show something else in its place. */
|
|
57
|
-
readonly onFailure?: (reason: GuestWorkerFailure) => void;
|
|
59
|
+
/** The guest is not going to be shown, and why, once: the host can show something else in its place. `detail` says why it did not start. */
|
|
60
|
+
readonly onFailure?: (reason: GuestWorkerFailure, detail?: string) => void;
|
|
58
61
|
/** The kit it may draw from. `GUEST_KIT` by default. */
|
|
59
62
|
readonly kit?: Kit;
|
|
60
63
|
/**
|
|
@@ -93,4 +96,10 @@ export { createKitRenderer, GUEST_KIT_CSS, hostAttribute, kitValue } from "./kit
|
|
|
93
96
|
export type { KitLinks, KitRefusal, KitRefusalReason, KitRenderer, KitRendererOptions } from "./kit.js";
|
|
94
97
|
export { GUEST_KIT, KIT_LINK_TARGETS, KIT_TONES } from "../kit.js";
|
|
95
98
|
export type { GuestKitElement, Kit, KitComponent, KitEvent, KitProperty, KitPropertyType, KitTone } from "../kit.js";
|
|
99
|
+
export { mountWorkerView } from "./view.js";
|
|
100
|
+
export type { MountWorkerViewOptions, WorkerView, WorkerViewCode, WorkerViewFailure, WorkerViewLimits } from "./view.js";
|
|
101
|
+
export type { ViewRefusal } from "./open-draw.js";
|
|
102
|
+
export type { OpenRefusal, OpenRefusalReason } from "./open-judge.js";
|
|
103
|
+
export type { CssRefusal, CssRefusalReason } from "./css.js";
|
|
104
|
+
export type { Destination } from "./links.js";
|
|
96
105
|
//# 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":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AACjE,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAoC,KAAK,QAAQ,EAAE,KAAK,UAAU,EAAoB,MAAM,UAAU,CAAC;AAC9G,OAAO,EAAuD,KAAK,WAAW,EAAE,KAAK,UAAU,EAAE,KAAK,cAAc,EAAE,MAAM,cAAc,CAAC;AAC3I,OAAO,EAAe,KAAK,iBAAiB,EAAsB,MAAM,mBAAmB,CAAC;AAG5F,YAAY,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAE3D,qFAAqF;AACrF,MAAM,MAAM,kBAAkB;AAC5B;;;;GAIG;AACD,OAAO;AACT;;;;GAIG;GACD,QAAQ;AACV,oDAAoD;GAClD,QAAQ;AACV,sHAAsH;GACpH,MAAM,CAAC;AAEX,MAAM,WAAW,uBAAuB,CAAC,CAAC,SAAS,SAAS;IAC1D,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAC;IACnC,iGAAiG;IACjG,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;IACzB,iGAAiG;IACjG,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;IAC9B,wCAAwC;IACxC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,cAAc,CAAC;IACtC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,oFAAoF;IACpF,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG;QAC9B,kGAAkG;QAClG,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAC3B,8EAA8E;QAC9E,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;QAC1B;;;;;;;;WAQG;QACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAC3B;;;;WAIG;QACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;KAC1B,CAAC;IACF,4IAA4I;IAC5I,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,kBAAkB,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3E,wDAAwD;IACxD,QAAQ,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC;IACnB;;;;;OAKG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,QAAQ,CAAC;IAC1B,mEAAmE;IACnE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,WAAW;IAC1B,iDAAiD;IACjD,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAC9B,2EAA2E;IAC3E,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,0CAA0C;IAC1C,MAAM,IAAI,IAAI,CAAC;IACf,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,UAAU,CAAC,CAAC;IACrC,8DAA8D;IAC9D,QAAQ,CAAC,OAAO,EAAE,SAAS,UAAU,EAAE,CAAC;IACxC,OAAO,IAAI,IAAI,CAAC;CACjB;AAID;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,SAAS,EAAE,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,uBAAuB,CAAC,CAAC,CAAC,GAAG,WAAW,CA+G5H;AAED,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACrF,YAAY,EAAE,QAAQ,EAAE,UAAU,EAAE,gBAAgB,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AACxG,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACnE,YAAY,EAAE,eAAe,EAAE,GAAG,EAAE,YAAY,EAAE,QAAQ,EAAE,WAAW,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOrH,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC5C,YAAY,EAAE,sBAAsB,EAAE,UAAU,EAAE,cAAc,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AACzH,YAAY,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAClD,YAAY,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACtE,YAAY,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAC7D,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC"}
|
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,135 +44,69 @@ 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
|
-
const fail = (reason) => {
|
|
53
|
+
const fail = (reason, detail) => {
|
|
65
54
|
if (failed)
|
|
66
55
|
return;
|
|
67
56
|
failed = true;
|
|
68
57
|
stop();
|
|
69
58
|
renderer?.dispose();
|
|
70
|
-
options.onFailure?.(reason);
|
|
59
|
+
options.onFailure?.(reason, detail);
|
|
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, detail) => fail(reason, detail),
|
|
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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"}
|