toiljs 0.0.116 → 0.0.118
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/CHANGELOG.md +14 -0
- package/README.md +16 -7
- package/build/backend/.tsbuildinfo +1 -1
- package/build/cli/.tsbuildinfo +1 -1
- package/build/cli/index.js +2375 -258
- package/build/client/.tsbuildinfo +1 -1
- package/build/client/auth.d.ts +3 -0
- package/build/client/auth.js +19 -10
- package/build/client/dev/devtools.js +1 -1
- package/build/client/dev/error-overlay.js +1 -1
- package/build/client/index.d.ts +1 -1
- package/build/client/index.js +1 -1
- package/build/client/navigation/navigation.js +28 -3
- package/build/client/routing/Router.js +5 -2
- package/build/client/routing/mount.js +1 -1
- package/build/compiler/.tsbuildinfo +1 -1
- package/build/compiler/auth-emails.js +7 -3
- package/build/compiler/emails.js +1 -1
- package/build/compiler/index.d.ts +1 -0
- package/build/compiler/index.js +26 -5
- package/build/compiler/pages.js +2 -3
- package/build/compiler/prerender.d.ts +3 -8
- package/build/compiler/prerender.js +88 -127
- package/build/compiler/ssg.js +3 -4
- package/build/compiler/template-build.js +3 -4
- package/build/compiler/toil-docs.generated.js +8 -7
- package/build/compiler/vite.js +4 -6
- package/build/devserver/.tsbuildinfo +1 -1
- package/build/devserver/db/database.js +7 -3
- package/build/devserver/db/types.js +1 -1
- package/build/devserver/production.js +4 -3
- package/build/devserver/runtime/crypto.d.ts +1 -1
- package/build/io/.tsbuildinfo +1 -1
- package/build/logger/.tsbuildinfo +1 -1
- package/build/shared/.tsbuildinfo +1 -1
- package/examples/basic/client/routes/analytics.tsx +7 -5
- package/examples/basic/client/routes/pq.tsx +2 -1
- package/examples/basic/server/tsconfig.json +1 -3
- package/package.json +45 -44
- package/presets/no-uint8array-tostring.js +120 -153
- package/presets/oxlint.d.ts +5 -0
- package/presets/oxlint.js +224 -0
- package/server/auth/AuthController.ts +53 -14
- package/server/auth/FactorSettings.ts +41 -0
- package/server/auth/SessionEpochs.ts +58 -0
- package/server/auth/SessionRevocations.ts +13 -0
- package/server/globals/auth.ts +27 -2
- package/server/runtime/tsconfig.json +1 -3
- package/tsconfig.json +2 -11
- package/.github/ISSUE_TEMPLATE/bug_report.md +0 -38
- package/.github/ISSUE_TEMPLATE/bug_report.yml +0 -90
- package/.github/ISSUE_TEMPLATE/config.yml +0 -8
- package/.github/ISSUE_TEMPLATE/feature_request.md +0 -20
- package/.github/PULL_REQUEST_TEMPLATE.md +0 -43
- package/.github/changelog-config.json +0 -45
- package/.github/dependabot.yml +0 -27
- package/.github/workflows/ci.yml +0 -222
- package/.vscode/settings.json +0 -10
- package/docs/README.md +0 -107
- package/docs/auth/README.md +0 -104
- package/docs/auth/configuration.md +0 -105
- package/docs/auth/emails.md +0 -92
- package/docs/auth/extending.md +0 -202
- package/docs/auth/how-it-works.md +0 -138
- package/docs/auth/usage.md +0 -188
- package/docs/backend/README.md +0 -143
- package/docs/backend/data.md +0 -351
- package/docs/backend/rest.md +0 -402
- package/docs/backend/rpc.md +0 -226
- package/docs/background/README.md +0 -114
- package/docs/background/daemons.md +0 -276
- package/docs/background/derive.md +0 -179
- package/docs/cli/README.md +0 -379
- package/docs/concepts/ai-guide.md +0 -132
- package/docs/concepts/config.md +0 -416
- package/docs/concepts/decorators.md +0 -127
- package/docs/concepts/security.md +0 -108
- package/docs/concepts/tiers.md +0 -166
- package/docs/concepts/types.md +0 -216
- package/docs/database/README.md +0 -143
- package/docs/database/capacity.md +0 -350
- package/docs/database/counters.md +0 -174
- package/docs/database/documents.md +0 -277
- package/docs/database/events.md +0 -307
- package/docs/database/membership.md +0 -246
- package/docs/database/setup.md +0 -155
- package/docs/database/unique.md +0 -216
- package/docs/database/views.md +0 -246
- package/docs/frontend/README.md +0 -104
- package/docs/frontend/components.md +0 -286
- package/docs/frontend/data-fetching.md +0 -260
- package/docs/frontend/images.md +0 -148
- package/docs/frontend/metadata.md +0 -344
- package/docs/frontend/navigation.md +0 -296
- package/docs/frontend/rendering.md +0 -236
- package/docs/frontend/routing.md +0 -346
- package/docs/frontend/scripts.md +0 -118
- package/docs/frontend/search.md +0 -191
- package/docs/frontend/styling.md +0 -147
- package/docs/frontend/toil-global.md +0 -216
- package/docs/getting-started/README.md +0 -81
- package/docs/getting-started/create-project.md +0 -131
- package/docs/getting-started/deploy.md +0 -101
- package/docs/getting-started/first-app.md +0 -215
- package/docs/getting-started/installation.md +0 -124
- package/docs/getting-started/migrating.md +0 -125
- package/docs/getting-started/project-structure.md +0 -163
- package/docs/introduction/README.md +0 -66
- package/docs/introduction/design-principles.md +0 -81
- package/docs/introduction/distributed.md +0 -91
- package/docs/introduction/how-it-works.md +0 -121
- package/docs/introduction/hyperscale.md +0 -70
- package/docs/introduction/modern-stack.md +0 -85
- package/docs/introduction/vs-other-frameworks.md +0 -64
- package/docs/introduction/why-toil.md +0 -99
- package/docs/llms.txt +0 -95
- package/docs/realtime/README.md +0 -102
- package/docs/realtime/channels.md +0 -211
- package/docs/realtime/streams.md +0 -369
- package/docs/services/README.md +0 -60
- package/docs/services/analytics.md +0 -279
- package/docs/services/caching.md +0 -175
- package/docs/services/cookies.md +0 -235
- package/docs/services/crypto.md +0 -209
- package/docs/services/email.md +0 -289
- package/docs/services/environment.md +0 -141
- package/docs/services/ratelimit.md +0 -174
- package/docs/services/time.md +0 -85
- package/eslint.config.js +0 -57
- package/examples/basic/client/routes/docs/[...slug].tsx +0 -12
- package/presets/eslint.js +0 -88
- package/src/backend/index.ts +0 -204
- package/src/cli/configure.ts +0 -363
- package/src/cli/create.ts +0 -924
- package/src/cli/db.ts +0 -158
- package/src/cli/diagnostics.ts +0 -665
- package/src/cli/doctor.ts +0 -982
- package/src/cli/features.ts +0 -170
- package/src/cli/index.ts +0 -326
- package/src/cli/notify.ts +0 -120
- package/src/cli/proc.ts +0 -56
- package/src/cli/ui.ts +0 -169
- package/src/cli/update.ts +0 -248
- package/src/cli/updates.ts +0 -92
- package/src/cli/validate.ts +0 -31
- package/src/cli/version-check.ts +0 -125
- package/src/client/auth.ts +0 -869
- package/src/client/channel/channel.ts +0 -146
- package/src/client/components/Form.tsx +0 -65
- package/src/client/components/Image.tsx +0 -160
- package/src/client/components/Script.tsx +0 -113
- package/src/client/components/Slot.tsx +0 -21
- package/src/client/dev/devtools.tsx +0 -1089
- package/src/client/dev/error-overlay.tsx +0 -225
- package/src/client/errors.ts +0 -11
- package/src/client/head/head.ts +0 -182
- package/src/client/head/metadata.ts +0 -110
- package/src/client/index.ts +0 -130
- package/src/client/navigation/Link.tsx +0 -108
- package/src/client/navigation/NavLink.tsx +0 -86
- package/src/client/navigation/navigation.ts +0 -235
- package/src/client/navigation/prefetch.ts +0 -169
- package/src/client/navigation/scroll.ts +0 -53
- package/src/client/routing/Router.tsx +0 -216
- package/src/client/routing/action.ts +0 -122
- package/src/client/routing/error-boundary.tsx +0 -43
- package/src/client/routing/hooks.ts +0 -140
- package/src/client/routing/lazy.ts +0 -77
- package/src/client/routing/loader.ts +0 -381
- package/src/client/routing/match.ts +0 -47
- package/src/client/routing/mount.tsx +0 -90
- package/src/client/routing/params-context.ts +0 -10
- package/src/client/routing/slot-context.ts +0 -7
- package/src/client/rpc.ts +0 -97
- package/src/client/search/search.ts +0 -189
- package/src/client/search/use-page-search.ts +0 -73
- package/src/client/ssr/markers.tsx +0 -172
- package/src/client/stream/client.ts +0 -237
- package/src/client/types.ts +0 -73
- package/src/compiler/auth-emails.ts +0 -312
- package/src/compiler/config.ts +0 -369
- package/src/compiler/docs.ts +0 -127
- package/src/compiler/email-preview.ts +0 -314
- package/src/compiler/emails.ts +0 -404
- package/src/compiler/fonts.ts +0 -89
- package/src/compiler/generate.ts +0 -471
- package/src/compiler/image-blur.ts +0 -42
- package/src/compiler/image-report.ts +0 -88
- package/src/compiler/index.ts +0 -1362
- package/src/compiler/pages.ts +0 -49
- package/src/compiler/plugin.ts +0 -391
- package/src/compiler/prerender.ts +0 -263
- package/src/compiler/routes.ts +0 -170
- package/src/compiler/seo.ts +0 -415
- package/src/compiler/sri.ts +0 -144
- package/src/compiler/ssg.ts +0 -177
- package/src/compiler/ssr-codegen.ts +0 -85
- package/src/compiler/template-build.ts +0 -676
- package/src/compiler/template.ts +0 -262
- package/src/compiler/toil-docs.generated.ts +0 -77
- package/src/compiler/vite.ts +0 -245
- package/src/devserver/analytics/index.ts +0 -317
- package/src/devserver/config/dotenv.ts +0 -102
- package/src/devserver/config/env.ts +0 -30
- package/src/devserver/config/ratelimit.ts +0 -123
- package/src/devserver/daemon/catalog.ts +0 -120
- package/src/devserver/daemon/cron.ts +0 -87
- package/src/devserver/daemon/host.ts +0 -134
- package/src/devserver/daemon/index.ts +0 -369
- package/src/devserver/daemon/runtime.ts +0 -48
- package/src/devserver/db/catalog.ts +0 -109
- package/src/devserver/db/database.ts +0 -1834
- package/src/devserver/db/derives.ts +0 -121
- package/src/devserver/db/index.ts +0 -20
- package/src/devserver/db/routeKinds.ts +0 -191
- package/src/devserver/db/types.ts +0 -168
- package/src/devserver/email/caps.ts +0 -0
- package/src/devserver/email/config.ts +0 -141
- package/src/devserver/email/console.ts +0 -348
- package/src/devserver/email/index.ts +0 -155
- package/src/devserver/email/providers.ts +0 -131
- package/src/devserver/email/status.ts +0 -23
- package/src/devserver/email/validate.ts +0 -37
- package/src/devserver/email/wire.ts +0 -55
- package/src/devserver/http/cache.ts +0 -0
- package/src/devserver/http/envelope.ts +0 -157
- package/src/devserver/http/proxy.ts +0 -172
- package/src/devserver/http/runtime.ts +0 -387
- package/src/devserver/index.ts +0 -43
- package/src/devserver/production-ipc.ts +0 -63
- package/src/devserver/production-worker.ts +0 -83
- package/src/devserver/production.ts +0 -718
- package/src/devserver/runtime/crypto.ts +0 -587
- package/src/devserver/runtime/host.ts +0 -427
- package/src/devserver/runtime/module.ts +0 -442
- package/src/devserver/server.ts +0 -251
- package/src/devserver/ssr.ts +0 -208
- package/src/devserver/stream/catalog.ts +0 -106
- package/src/devserver/stream/host.ts +0 -42
- package/src/devserver/stream/index.ts +0 -301
- package/src/devserver/stream/manager.ts +0 -167
- package/src/devserver/stream/router.ts +0 -101
- package/src/devserver/stream/wire.ts +0 -58
- package/src/devserver/stream/ws.ts +0 -78
- package/src/devserver/wasm/sections.ts +0 -59
- package/src/devserver/wasm/surface.ts +0 -115
- package/src/io/FastMap.ts +0 -151
- package/src/io/FastSet.ts +0 -113
- package/src/io/codec.ts +0 -362
- package/src/io/index.ts +0 -10
- package/src/io/lengths.ts +0 -14
- package/src/io/types.ts +0 -19
- package/src/logger/index.ts +0 -22
- package/src/shared/index.ts +0 -46
- package/test/analytics-dev.test.ts +0 -113
- package/test/assembly/aspect-shim.ts +0 -33
- package/test/assembly/cookie.spec.ts +0 -303
- package/test/assembly/example.spec.ts +0 -22
- package/test/assembly/ssr.spec.ts +0 -95
- package/test/assembly.test.ts +0 -59
- package/test/auth-emails.test.ts +0 -118
- package/test/built-ssr.test.ts +0 -148
- package/test/channel.test.ts +0 -21
- package/test/config-host-port.test.ts +0 -59
- package/test/configure.test.ts +0 -94
- package/test/daemon-build.test.ts +0 -278
- package/test/daemon-catalog.test.ts +0 -349
- package/test/daemon-emulation.test.ts +0 -256
- package/test/db.test.ts +0 -0
- package/test/devserver-database.test.ts +0 -1102
- package/test/devserver-email.test.ts +0 -306
- package/test/devserver-pqauth.test.ts +0 -93
- package/test/devserver-secrets.test.ts +0 -63
- package/test/devserver.test.ts +0 -259
- package/test/doctor.test.ts +0 -298
- package/test/dom/Image.test.tsx +0 -144
- package/test/dom/Link.test.tsx +0 -67
- package/test/dom/NavLink.test.tsx +0 -37
- package/test/dom/Script.test.tsx +0 -48
- package/test/dom/action.test.tsx +0 -146
- package/test/dom/error-overlay.test.tsx +0 -44
- package/test/dom/loader.test.tsx +0 -121
- package/test/dom/navigation.test.ts +0 -59
- package/test/dom/revalidate.test.tsx +0 -38
- package/test/dom/route-head.test.tsx +0 -56
- package/test/dom/router-loading.test.tsx +0 -44
- package/test/dom/scroll.test.ts +0 -56
- package/test/dom/slot.test.tsx +0 -131
- package/test/dom/use-metadata.test.tsx +0 -58
- package/test/dom/view-transitions.test.tsx +0 -53
- package/test/dynamic-routing.test.ts +0 -132
- package/test/email-console.test.ts +0 -86
- package/test/email-preview.test.ts +0 -73
- package/test/emails.test.ts +0 -58
- package/test/errors.test.ts +0 -21
- package/test/example-guestbook.test.ts +0 -123
- package/test/features.test.ts +0 -149
- package/test/fixtures/bignum-wire/spec.ts +0 -25
- package/test/fixtures/daemon-app.ts +0 -65
- package/test/fixtures/stream-echo.ts +0 -26
- package/test/fixtures/stream-gate.ts +0 -28
- package/test/fixtures/stream-trap.ts +0 -18
- package/test/fixtures/stream-typed.ts +0 -41
- package/test/fonts.test.ts +0 -28
- package/test/global-setup.ts +0 -17
- package/test/head.test.ts +0 -42
- package/test/image-blur.test.ts +0 -50
- package/test/io.test.ts +0 -117
- package/test/metadata.test.ts +0 -40
- package/test/navlink.test.ts +0 -28
- package/test/pages.test.ts +0 -105
- package/test/placeholder.test.ts +0 -9
- package/test/pqauth-e2e.test.ts +0 -216
- package/test/pqauth-email.test.ts +0 -801
- package/test/prerender.test.ts +0 -116
- package/test/prettier-plugin.test.ts +0 -46
- package/test/routes.test.ts +0 -76
- package/test/rpc-bignum-wire.test.ts +0 -164
- package/test/rpc-dispatch.test.ts +0 -132
- package/test/rpc-kinds.test.ts +0 -18
- package/test/rpc.test.ts +0 -66
- package/test/search.test.ts +0 -114
- package/test/seo.test.ts +0 -175
- package/test/slot-layouts.test.ts +0 -69
- package/test/sri.test.ts +0 -129
- package/test/ssg.test.ts +0 -36
- package/test/ssr-hydration.test.tsx +0 -122
- package/test/ssr-render.test.ts +0 -197
- package/test/ssr-template.test.tsx +0 -482
- package/test/stream-emulation.test.ts +0 -479
- package/test/ui.test.ts +0 -40
- package/test/update.test.ts +0 -58
- package/test/validate.test.ts +0 -42
- package/test/version-check.test.ts +0 -130
- package/tests/data-parity/generated-parity.ts +0 -99
- package/tests/data-parity/parity.ts +0 -80
- package/tests/data-parity/spec.ts +0 -46
package/src/compiler/template.ts
DELETED
|
@@ -1,262 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Build-time edge-SSR template extraction.
|
|
3
|
-
*
|
|
4
|
-
* After a route component is rendered to HTML with the marker components in
|
|
5
|
-
* sentinel mode (`__setSsrBuild(true)`), the output carries PUA sentinel tokens
|
|
6
|
-
* at every hole. This module scans that HTML, strips the tokens, records their
|
|
7
|
-
* BYTE offsets, and emits:
|
|
8
|
-
*
|
|
9
|
-
* - `<route>.tmpl` — the stripped static scaffold (React's own bytes, holes
|
|
10
|
-
* removed); the edge mmaps this.
|
|
11
|
-
* - `<route>.slots` — the binary manifest the Rust host parses
|
|
12
|
-
* (`toil-backend/src/host/template/manifest.rs`).
|
|
13
|
-
*
|
|
14
|
-
* The repeat-region row sub-template + the holes' binding metadata are also
|
|
15
|
-
* captured (for the guest `render()` codegen), but those do NOT go in `.slots`
|
|
16
|
-
* (the host only needs insertion points; the guest pre-stamps repeat rows).
|
|
17
|
-
*
|
|
18
|
-
* The pure functions here (`extractFromHtml`, `encodeSlots`, `coherenceHash`,
|
|
19
|
-
* `reactEscapeHtml`, `spliceTemplate`) are deterministic and unit-tested; the
|
|
20
|
-
* `extractTemplates` orchestration drives a short-lived Vite SSR server, the
|
|
21
|
-
* same pattern as `ssg.ts`.
|
|
22
|
-
*/
|
|
23
|
-
|
|
24
|
-
import { createHash } from 'node:crypto';
|
|
25
|
-
|
|
26
|
-
/** PUA sentinel framing, mirroring `src/client/ssr/markers.tsx`. */
|
|
27
|
-
const START = String.fromCharCode(0xe000);
|
|
28
|
-
const END = String.fromCharCode(0xe002);
|
|
29
|
-
|
|
30
|
-
export type SlotKind = 'text' | 'raw' | 'attr' | 'repeat';
|
|
31
|
-
|
|
32
|
-
/** Byte value of a kind on the wire / in `.slots`. Mirrors host `SlotKind`. */
|
|
33
|
-
export function kindByte(kind: SlotKind): number {
|
|
34
|
-
switch (kind) {
|
|
35
|
-
case 'text':
|
|
36
|
-
return 0;
|
|
37
|
-
case 'raw':
|
|
38
|
-
return 1;
|
|
39
|
-
case 'attr':
|
|
40
|
-
return 2;
|
|
41
|
-
case 'repeat':
|
|
42
|
-
return 3;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/** One extracted hole. `offset` is a byte offset into the enclosing template
|
|
47
|
-
* (the `.tmpl` for top-level slots, or the row sub-template for nested ones). */
|
|
48
|
-
export interface SlotRecord {
|
|
49
|
-
id: string;
|
|
50
|
-
kind: SlotKind;
|
|
51
|
-
offset: number;
|
|
52
|
-
/** Repeat only: the captured single-row scaffold (bytes) ... */
|
|
53
|
-
rowTemplate?: Buffer;
|
|
54
|
-
/** ... and the holes inside that row, offsets relative to `rowTemplate`. */
|
|
55
|
-
rowSlots?: SlotRecord[];
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
export interface Extracted {
|
|
59
|
-
/** Stripped static scaffold; the mmap'd `.tmpl`. */
|
|
60
|
-
tmpl: Buffer;
|
|
61
|
-
/** Top-level holes in document order, byte offsets into `tmpl`. */
|
|
62
|
-
slots: SlotRecord[];
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
interface ScanResult {
|
|
66
|
-
text: string;
|
|
67
|
-
byteLen: number;
|
|
68
|
-
slots: SlotRecord[];
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/** Scan one HTML string, stripping sentinel tokens and recording hole offsets.
|
|
72
|
-
* Recurses into repeat regions to capture the row sub-template. */
|
|
73
|
-
function scan(html: string): ScanResult {
|
|
74
|
-
let out = '';
|
|
75
|
-
let byteLen = 0;
|
|
76
|
-
const slots: SlotRecord[] = [];
|
|
77
|
-
let i = 0;
|
|
78
|
-
|
|
79
|
-
const emit = (chunk: string): void => {
|
|
80
|
-
out += chunk;
|
|
81
|
-
byteLen += Buffer.byteLength(chunk, 'utf8');
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
while (i < html.length) {
|
|
85
|
-
const start = html.indexOf(START, i);
|
|
86
|
-
if (start === -1) {
|
|
87
|
-
emit(html.slice(i));
|
|
88
|
-
break;
|
|
89
|
-
}
|
|
90
|
-
if (start > i) emit(html.slice(i, start));
|
|
91
|
-
|
|
92
|
-
const kindChar = html[start + 1];
|
|
93
|
-
const tokEnd = html.indexOf(END, start + 2);
|
|
94
|
-
if (tokEnd === -1) throw new Error('toil ssr: unterminated sentinel token');
|
|
95
|
-
const id = html.slice(start + 2, tokEnd);
|
|
96
|
-
const afterTok = tokEnd + 1;
|
|
97
|
-
|
|
98
|
-
if (kindChar === 'R') {
|
|
99
|
-
// Repeat region: collect everything up to the matching close token.
|
|
100
|
-
const closeTok = START + 'r' + id + END;
|
|
101
|
-
const closeIdx = html.indexOf(closeTok, afterTok);
|
|
102
|
-
if (closeIdx === -1) {
|
|
103
|
-
throw new Error(`toil ssr: unterminated repeat region "${id}"`);
|
|
104
|
-
}
|
|
105
|
-
const innerHtml = html.slice(afterTok, closeIdx);
|
|
106
|
-
const inner = scan(innerHtml);
|
|
107
|
-
slots.push({
|
|
108
|
-
id,
|
|
109
|
-
kind: 'repeat',
|
|
110
|
-
offset: byteLen, // region collapses to a zero-width insertion point
|
|
111
|
-
rowTemplate: Buffer.from(inner.text, 'utf8'),
|
|
112
|
-
rowSlots: inner.slots,
|
|
113
|
-
});
|
|
114
|
-
i = closeIdx + closeTok.length;
|
|
115
|
-
continue;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
const kind: SlotKind | null =
|
|
119
|
-
kindChar === 't' ? 'text' : kindChar === 'h' ? 'raw' : kindChar === 'a' ? 'attr' : null;
|
|
120
|
-
if (kind === null) {
|
|
121
|
-
throw new Error(`toil ssr: unknown sentinel kind "${kindChar ?? ''}"`);
|
|
122
|
-
}
|
|
123
|
-
slots.push({ id, kind, offset: byteLen });
|
|
124
|
-
i = afterTok;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
return { text: out, byteLen, slots };
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
/** Strip sentinels from a rendered-with-markers HTML string into a `.tmpl` +
|
|
131
|
-
* ordered slot records. */
|
|
132
|
-
export function extractFromHtml(html: string): Extracted {
|
|
133
|
-
const r = scan(html);
|
|
134
|
-
return { tmpl: Buffer.from(r.text, 'utf8'), slots: r.slots };
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
/** Assign stable numeric slot ids to top-level holes in document order. These
|
|
138
|
-
* are the ids the host `.slots` and the guest `Slot` enum share. */
|
|
139
|
-
export function assignSlotIds(slots: SlotRecord[]): Map<string, number> {
|
|
140
|
-
const ids = new Map<string, number>();
|
|
141
|
-
let next = 0;
|
|
142
|
-
for (const s of slots) {
|
|
143
|
-
if (!ids.has(s.id)) ids.set(s.id, next++);
|
|
144
|
-
}
|
|
145
|
-
return ids;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
/** Encode the `.slots` binary manifest the Rust host parses. Only top-level
|
|
149
|
-
* slots are emitted (the host's insertion points); repeat row data is for the
|
|
150
|
-
* guest codegen, not the host. */
|
|
151
|
-
export function encodeSlots(
|
|
152
|
-
tmplLen: number,
|
|
153
|
-
hash: Buffer,
|
|
154
|
-
slots: SlotRecord[],
|
|
155
|
-
slotIds: Map<string, number>,
|
|
156
|
-
): Buffer {
|
|
157
|
-
if (hash.length !== 32) throw new Error('toil ssr: coherence hash must be 32 bytes');
|
|
158
|
-
const buf = Buffer.alloc(4 + 2 + 2 + 4 + 32 + 2 + slots.length * 8);
|
|
159
|
-
let o = 0;
|
|
160
|
-
buf.write('TSLT', o, 'ascii'); // magic, read as u32 LE on the host
|
|
161
|
-
o += 4;
|
|
162
|
-
buf.writeUInt16LE(1, o); // version
|
|
163
|
-
o += 2;
|
|
164
|
-
buf.writeUInt16LE(0, o); // flags
|
|
165
|
-
o += 2;
|
|
166
|
-
buf.writeUInt32LE(tmplLen, o);
|
|
167
|
-
o += 4;
|
|
168
|
-
hash.copy(buf, o);
|
|
169
|
-
o += 32;
|
|
170
|
-
buf.writeUInt16LE(slots.length, o);
|
|
171
|
-
o += 2;
|
|
172
|
-
for (const s of slots) {
|
|
173
|
-
const id = slotIds.get(s.id);
|
|
174
|
-
if (id === undefined) throw new Error(`toil ssr: no slot id for "${s.id}"`);
|
|
175
|
-
buf.writeUInt32LE(s.offset, o);
|
|
176
|
-
o += 4;
|
|
177
|
-
buf.writeUInt16LE(id, o);
|
|
178
|
-
o += 2;
|
|
179
|
-
buf.writeUInt8(kindByte(s.kind), o);
|
|
180
|
-
o += 1;
|
|
181
|
-
buf.writeUInt8(0, o); // reserved
|
|
182
|
-
o += 1;
|
|
183
|
-
}
|
|
184
|
-
return buf;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
/** Canonical serialisation of the slot structure (recursive), used by the
|
|
188
|
-
* coherence hash so a change to any hole, kind, or nesting rotates it. */
|
|
189
|
-
function canonicalManifest(slots: SlotRecord[]): string {
|
|
190
|
-
return JSON.stringify(
|
|
191
|
-
slots.map((s) => ({
|
|
192
|
-
id: s.id,
|
|
193
|
-
kind: s.kind,
|
|
194
|
-
offset: s.offset,
|
|
195
|
-
row: s.rowSlots ? canonicalManifest(s.rowSlots) : undefined,
|
|
196
|
-
rowLen: s.rowTemplate ? s.rowTemplate.length : undefined,
|
|
197
|
-
})),
|
|
198
|
-
);
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
/** Coherence hash binding the `.tmpl` + slot structure. Stored in `.slots` and
|
|
202
|
-
* baked into the guest; the host 500s on a mismatch (deploy skew). */
|
|
203
|
-
export function coherenceHash(tmpl: Buffer, slots: SlotRecord[]): Buffer {
|
|
204
|
-
return createHash('sha256')
|
|
205
|
-
.update(tmpl)
|
|
206
|
-
.update('\0')
|
|
207
|
-
.update(canonicalManifest(slots), 'utf8')
|
|
208
|
-
.digest();
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
/**
|
|
212
|
-
* React-exact HTML escape (`react-dom/server` `escapeTextForBrowser`, regex
|
|
213
|
-
* `/["'&<>]/`). The SAME function React uses for text AND attributes. Must stay
|
|
214
|
-
* byte-identical to the guest's `server/runtime/ssr/escape.ts`, or hydration
|
|
215
|
-
* mismatches. Used by the golden byte-identity test to simulate the guest.
|
|
216
|
-
*/
|
|
217
|
-
export function reactEscapeHtml(s: string): string {
|
|
218
|
-
let out = '';
|
|
219
|
-
let last = 0;
|
|
220
|
-
for (let i = 0; i < s.length; i++) {
|
|
221
|
-
let rep: string;
|
|
222
|
-
switch (s.charCodeAt(i)) {
|
|
223
|
-
case 34:
|
|
224
|
-
rep = '"';
|
|
225
|
-
break;
|
|
226
|
-
case 38:
|
|
227
|
-
rep = '&';
|
|
228
|
-
break;
|
|
229
|
-
case 39:
|
|
230
|
-
rep = ''';
|
|
231
|
-
break;
|
|
232
|
-
case 60:
|
|
233
|
-
rep = '<';
|
|
234
|
-
break;
|
|
235
|
-
case 62:
|
|
236
|
-
rep = '>';
|
|
237
|
-
break;
|
|
238
|
-
default:
|
|
239
|
-
continue;
|
|
240
|
-
}
|
|
241
|
-
out += s.slice(last, i) + rep;
|
|
242
|
-
last = i + 1;
|
|
243
|
-
}
|
|
244
|
-
return last === 0 ? s : out + s.slice(last);
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
/** Generic splice: interleave template slices with hole values at ascending
|
|
248
|
-
* byte offsets. Mirrors the Rust host `assemble`; used by the golden test (and
|
|
249
|
-
* any tooling that needs to materialise a full page from a template + values).
|
|
250
|
-
* `values` maps a byte offset to the bytes inserted there (offsets may repeat
|
|
251
|
-
* is not allowed; pass them in `slots` order). */
|
|
252
|
-
export function spliceTemplate(tmpl: Buffer, inserts: { offset: number; value: Buffer }[]): Buffer {
|
|
253
|
-
const parts: Buffer[] = [];
|
|
254
|
-
let prev = 0;
|
|
255
|
-
for (const ins of inserts) {
|
|
256
|
-
if (ins.offset > prev) parts.push(tmpl.subarray(prev, ins.offset));
|
|
257
|
-
if (ins.value.length > 0) parts.push(ins.value);
|
|
258
|
-
prev = ins.offset;
|
|
259
|
-
}
|
|
260
|
-
if (tmpl.length > prev) parts.push(tmpl.subarray(prev));
|
|
261
|
-
return Buffer.concat(parts);
|
|
262
|
-
}
|