@mostra/protocol 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +202 -0
- package/README.md +38 -2
- package/dist/actions.d.ts +273 -0
- package/dist/actions.d.ts.map +1 -0
- package/dist/actions.js +154 -0
- package/dist/actions.js.map +1 -0
- package/dist/artifact.d.ts +113 -0
- package/dist/artifact.d.ts.map +1 -0
- package/dist/artifact.js +79 -0
- package/dist/artifact.js.map +1 -0
- package/dist/bridge.d.ts +295 -0
- package/dist/bridge.d.ts.map +1 -0
- package/dist/bridge.js +343 -0
- package/dist/bridge.js.map +1 -0
- package/dist/browser.d.ts +195 -0
- package/dist/browser.d.ts.map +1 -0
- package/dist/browser.js +156 -0
- package/dist/browser.js.map +1 -0
- package/dist/bundle.d.ts +155 -0
- package/dist/bundle.d.ts.map +1 -0
- package/dist/bundle.js +130 -0
- package/dist/bundle.js.map +1 -0
- package/dist/canonical.d.ts +23 -0
- package/dist/canonical.d.ts.map +1 -0
- package/dist/canonical.js +45 -0
- package/dist/canonical.js.map +1 -0
- package/dist/capability.d.ts +38 -0
- package/dist/capability.d.ts.map +1 -0
- package/dist/capability.js +61 -0
- package/dist/capability.js.map +1 -0
- package/dist/diagnostics/codes/a11y.d.ts +8 -0
- package/dist/diagnostics/codes/a11y.d.ts.map +1 -0
- package/dist/diagnostics/codes/a11y.js +30 -0
- package/dist/diagnostics/codes/a11y.js.map +1 -0
- package/dist/diagnostics/codes/action.d.ts +8 -0
- package/dist/diagnostics/codes/action.d.ts.map +1 -0
- package/dist/diagnostics/codes/action.js +110 -0
- package/dist/diagnostics/codes/action.js.map +1 -0
- package/dist/diagnostics/codes/artifact.d.ts +8 -0
- package/dist/diagnostics/codes/artifact.d.ts.map +1 -0
- package/dist/diagnostics/codes/artifact.js +121 -0
- package/dist/diagnostics/codes/artifact.js.map +1 -0
- package/dist/diagnostics/codes/build.d.ts +8 -0
- package/dist/diagnostics/codes/build.d.ts.map +1 -0
- package/dist/diagnostics/codes/build.js +55 -0
- package/dist/diagnostics/codes/build.js.map +1 -0
- package/dist/diagnostics/codes/cli.d.ts +8 -0
- package/dist/diagnostics/codes/cli.d.ts.map +1 -0
- package/dist/diagnostics/codes/cli.js +44 -0
- package/dist/diagnostics/codes/cli.js.map +1 -0
- package/dist/diagnostics/codes/console.d.ts +8 -0
- package/dist/diagnostics/codes/console.d.ts.map +1 -0
- package/dist/diagnostics/codes/console.js +30 -0
- package/dist/diagnostics/codes/console.js.map +1 -0
- package/dist/diagnostics/codes/dep.d.ts +8 -0
- package/dist/diagnostics/codes/dep.d.ts.map +1 -0
- package/dist/diagnostics/codes/dep.js +88 -0
- package/dist/diagnostics/codes/dep.js.map +1 -0
- package/dist/diagnostics/codes/env.d.ts +8 -0
- package/dist/diagnostics/codes/env.d.ts.map +1 -0
- package/dist/diagnostics/codes/env.js +132 -0
- package/dist/diagnostics/codes/env.js.map +1 -0
- package/dist/diagnostics/codes/field.d.ts +8 -0
- package/dist/diagnostics/codes/field.d.ts.map +1 -0
- package/dist/diagnostics/codes/field.js +99 -0
- package/dist/diagnostics/codes/field.js.map +1 -0
- package/dist/diagnostics/codes/home.d.ts +8 -0
- package/dist/diagnostics/codes/home.d.ts.map +1 -0
- package/dist/diagnostics/codes/home.js +132 -0
- package/dist/diagnostics/codes/home.js.map +1 -0
- package/dist/diagnostics/codes/host.d.ts +8 -0
- package/dist/diagnostics/codes/host.d.ts.map +1 -0
- package/dist/diagnostics/codes/host.js +176 -0
- package/dist/diagnostics/codes/host.js.map +1 -0
- package/dist/diagnostics/codes/hygiene.d.ts +8 -0
- package/dist/diagnostics/codes/hygiene.d.ts.map +1 -0
- package/dist/diagnostics/codes/hygiene.js +154 -0
- package/dist/diagnostics/codes/hygiene.js.map +1 -0
- package/dist/diagnostics/codes/index.d.ts +51 -0
- package/dist/diagnostics/codes/index.d.ts.map +1 -0
- package/dist/diagnostics/codes/index.js +72 -0
- package/dist/diagnostics/codes/index.js.map +1 -0
- package/dist/diagnostics/codes/live.d.ts +8 -0
- package/dist/diagnostics/codes/live.d.ts.map +1 -0
- package/dist/diagnostics/codes/live.js +30 -0
- package/dist/diagnostics/codes/live.js.map +1 -0
- package/dist/diagnostics/codes/manifest.d.ts +8 -0
- package/dist/diagnostics/codes/manifest.d.ts.map +1 -0
- package/dist/diagnostics/codes/manifest.js +44 -0
- package/dist/diagnostics/codes/manifest.js.map +1 -0
- package/dist/diagnostics/codes/network.d.ts +8 -0
- package/dist/diagnostics/codes/network.d.ts.map +1 -0
- package/dist/diagnostics/codes/network.js +30 -0
- package/dist/diagnostics/codes/network.js.map +1 -0
- package/dist/diagnostics/codes/platform.d.ts +8 -0
- package/dist/diagnostics/codes/platform.d.ts.map +1 -0
- package/dist/diagnostics/codes/platform.js +18 -0
- package/dist/diagnostics/codes/platform.js.map +1 -0
- package/dist/diagnostics/codes/publish.d.ts +8 -0
- package/dist/diagnostics/codes/publish.d.ts.map +1 -0
- package/dist/diagnostics/codes/publish.js +44 -0
- package/dist/diagnostics/codes/publish.js.map +1 -0
- package/dist/diagnostics/codes/regression.d.ts +8 -0
- package/dist/diagnostics/codes/regression.d.ts.map +1 -0
- package/dist/diagnostics/codes/regression.js +77 -0
- package/dist/diagnostics/codes/regression.js.map +1 -0
- package/dist/diagnostics/codes/runtime.d.ts +8 -0
- package/dist/diagnostics/codes/runtime.d.ts.map +1 -0
- package/dist/diagnostics/codes/runtime.js +66 -0
- package/dist/diagnostics/codes/runtime.js.map +1 -0
- package/dist/diagnostics/codes/secret.d.ts +8 -0
- package/dist/diagnostics/codes/secret.d.ts.map +1 -0
- package/dist/diagnostics/codes/secret.js +18 -0
- package/dist/diagnostics/codes/secret.js.map +1 -0
- package/dist/diagnostics/codes/smoke.d.ts +8 -0
- package/dist/diagnostics/codes/smoke.d.ts.map +1 -0
- package/dist/diagnostics/codes/smoke.js +30 -0
- package/dist/diagnostics/codes/smoke.js.map +1 -0
- package/dist/diagnostics/codes/submit.d.ts +8 -0
- package/dist/diagnostics/codes/submit.d.ts.map +1 -0
- package/dist/diagnostics/codes/submit.js +99 -0
- package/dist/diagnostics/codes/submit.js.map +1 -0
- package/dist/diagnostics/codes/target.d.ts +8 -0
- package/dist/diagnostics/codes/target.d.ts.map +1 -0
- package/dist/diagnostics/codes/target.js +18 -0
- package/dist/diagnostics/codes/target.js.map +1 -0
- package/dist/diagnostics/codes/type.d.ts +8 -0
- package/dist/diagnostics/codes/type.d.ts.map +1 -0
- package/dist/diagnostics/codes/type.js +30 -0
- package/dist/diagnostics/codes/type.js.map +1 -0
- package/dist/diagnostics/codes/verify.d.ts +8 -0
- package/dist/diagnostics/codes/verify.d.ts.map +1 -0
- package/dist/diagnostics/codes/verify.js +99 -0
- package/dist/diagnostics/codes/verify.js.map +1 -0
- package/dist/diagnostics/diagnostic.d.ts +79 -0
- package/dist/diagnostics/diagnostic.d.ts.map +1 -0
- package/dist/diagnostics/diagnostic.js +131 -0
- package/dist/diagnostics/diagnostic.js.map +1 -0
- package/dist/diagnostics/spec.d.ts +49 -0
- package/dist/diagnostics/spec.d.ts.map +1 -0
- package/dist/diagnostics/spec.js +31 -0
- package/dist/diagnostics/spec.js.map +1 -0
- package/dist/hygiene.d.ts +66 -0
- package/dist/hygiene.d.ts.map +1 -0
- package/dist/hygiene.js +134 -0
- package/dist/hygiene.js.map +1 -0
- package/dist/ids.d.ts +119 -0
- package/dist/ids.d.ts.map +1 -0
- package/dist/ids.js +135 -0
- package/dist/ids.js.map +1 -0
- package/dist/index.d.ts +86 -0
- package/dist/index.js +86 -0
- package/dist/interaction.d.ts +391 -0
- package/dist/interaction.d.ts.map +1 -0
- package/dist/interaction.js +306 -0
- package/dist/interaction.js.map +1 -0
- package/dist/manifest.d.ts +97 -0
- package/dist/manifest.d.ts.map +1 -0
- package/dist/manifest.js +101 -0
- package/dist/manifest.js.map +1 -0
- package/dist/method.d.ts +26 -0
- package/dist/method.d.ts.map +1 -0
- package/dist/method.js +10 -0
- package/dist/method.js.map +1 -0
- package/dist/methods/artifact/create.d.ts +29 -0
- package/dist/methods/artifact/create.d.ts.map +1 -0
- package/dist/methods/artifact/create.js +31 -0
- package/dist/methods/artifact/create.js.map +1 -0
- package/dist/methods/artifact/get.d.ts +17 -0
- package/dist/methods/artifact/get.d.ts.map +1 -0
- package/dist/methods/artifact/get.js +21 -0
- package/dist/methods/artifact/get.js.map +1 -0
- package/dist/methods/artifact/list.d.ts +22 -0
- package/dist/methods/artifact/list.d.ts.map +1 -0
- package/dist/methods/artifact/list.js +19 -0
- package/dist/methods/artifact/list.js.map +1 -0
- package/dist/methods/artifact/publish.d.ts +28 -0
- package/dist/methods/artifact/publish.d.ts.map +1 -0
- package/dist/methods/artifact/publish.js +28 -0
- package/dist/methods/artifact/publish.js.map +1 -0
- package/dist/methods/artifact/verify.d.ts +29 -0
- package/dist/methods/artifact/verify.d.ts.map +1 -0
- package/dist/methods/artifact/verify.js +27 -0
- package/dist/methods/artifact/verify.js.map +1 -0
- package/dist/methods/deps/add.d.ts +43 -0
- package/dist/methods/deps/add.d.ts.map +1 -0
- package/dist/methods/deps/add.js +40 -0
- package/dist/methods/deps/add.js.map +1 -0
- package/dist/methods/dev/start.d.ts +52 -0
- package/dist/methods/dev/start.d.ts.map +1 -0
- package/dist/methods/dev/start.js +56 -0
- package/dist/methods/dev/start.js.map +1 -0
- package/dist/methods/dev/stop.d.ts +16 -0
- package/dist/methods/dev/stop.d.ts.map +1 -0
- package/dist/methods/dev/stop.js +21 -0
- package/dist/methods/dev/stop.js.map +1 -0
- package/dist/methods/events/ack.d.ts +20 -0
- package/dist/methods/events/ack.d.ts.map +1 -0
- package/dist/methods/events/ack.js +26 -0
- package/dist/methods/events/ack.js.map +1 -0
- package/dist/methods/events/read.d.ts +40 -0
- package/dist/methods/events/read.d.ts.map +1 -0
- package/dist/methods/events/read.js +35 -0
- package/dist/methods/events/read.js.map +1 -0
- package/dist/methods/events/subscribe.d.ts +54 -0
- package/dist/methods/events/subscribe.d.ts.map +1 -0
- package/dist/methods/events/subscribe.js +44 -0
- package/dist/methods/events/subscribe.js.map +1 -0
- package/dist/methods/events/unsubscribe.d.ts +16 -0
- package/dist/methods/events/unsubscribe.d.ts.map +1 -0
- package/dist/methods/events/unsubscribe.js +21 -0
- package/dist/methods/events/unsubscribe.js.map +1 -0
- package/dist/methods/gc/run.d.ts +76 -0
- package/dist/methods/gc/run.d.ts.map +1 -0
- package/dist/methods/gc/run.js +56 -0
- package/dist/methods/gc/run.js.map +1 -0
- package/dist/methods/index.d.ts +6 -0
- package/dist/methods/index.d.ts.map +1 -0
- package/dist/methods/index.js +78 -0
- package/dist/methods/index.js.map +1 -0
- package/dist/methods/instance/check.d.ts +30 -0
- package/dist/methods/instance/check.d.ts.map +1 -0
- package/dist/methods/instance/check.js +34 -0
- package/dist/methods/instance/check.js.map +1 -0
- package/dist/methods/instance/status.d.ts +102 -0
- package/dist/methods/instance/status.d.ts.map +1 -0
- package/dist/methods/instance/status.js +83 -0
- package/dist/methods/instance/status.js.map +1 -0
- package/dist/methods/live/push.d.ts +28 -0
- package/dist/methods/live/push.d.ts.map +1 -0
- package/dist/methods/live/push.js +35 -0
- package/dist/methods/live/push.js.map +1 -0
- package/dist/methods/mostra/initialize.d.ts +143 -0
- package/dist/methods/mostra/initialize.d.ts.map +1 -0
- package/dist/methods/mostra/initialize.js +97 -0
- package/dist/methods/mostra/initialize.js.map +1 -0
- package/dist/methods/mostra/shutdown.d.ts +14 -0
- package/dist/methods/mostra/shutdown.d.ts.map +1 -0
- package/dist/methods/mostra/shutdown.js +22 -0
- package/dist/methods/mostra/shutdown.js.map +1 -0
- package/dist/methods/port/drafts-mirror.d.ts +30 -0
- package/dist/methods/port/drafts-mirror.d.ts.map +1 -0
- package/dist/methods/port/drafts-mirror.js +33 -0
- package/dist/methods/port/drafts-mirror.js.map +1 -0
- package/dist/methods/port/secrets-get.d.ts +19 -0
- package/dist/methods/port/secrets-get.d.ts.map +1 -0
- package/dist/methods/port/secrets-get.js +31 -0
- package/dist/methods/port/secrets-get.js.map +1 -0
- package/dist/methods/port/submissions-deliver.d.ts +38 -0
- package/dist/methods/port/submissions-deliver.d.ts.map +1 -0
- package/dist/methods/port/submissions-deliver.js +38 -0
- package/dist/methods/port/submissions-deliver.js.map +1 -0
- package/dist/methods/port/trusted-controls-activated.d.ts +27 -0
- package/dist/methods/port/trusted-controls-activated.d.ts.map +1 -0
- package/dist/methods/port/trusted-controls-activated.js +33 -0
- package/dist/methods/port/trusted-controls-activated.js.map +1 -0
- package/dist/methods/port/trusted-controls-policy.d.ts +21 -0
- package/dist/methods/port/trusted-controls-policy.d.ts.map +1 -0
- package/dist/methods/port/trusted-controls-policy.js +27 -0
- package/dist/methods/port/trusted-controls-policy.js.map +1 -0
- package/dist/methods/results/get.d.ts +32 -0
- package/dist/methods/results/get.d.ts.map +1 -0
- package/dist/methods/results/get.js +36 -0
- package/dist/methods/results/get.js.map +1 -0
- package/dist/methods/secret/delete.d.ts +22 -0
- package/dist/methods/secret/delete.d.ts.map +1 -0
- package/dist/methods/secret/delete.js +32 -0
- package/dist/methods/secret/delete.js.map +1 -0
- package/dist/methods/secret/list.d.ts +21 -0
- package/dist/methods/secret/list.d.ts.map +1 -0
- package/dist/methods/secret/list.js +29 -0
- package/dist/methods/secret/list.js.map +1 -0
- package/dist/methods/secret/set.d.ts +37 -0
- package/dist/methods/secret/set.d.ts.map +1 -0
- package/dist/methods/secret/set.js +41 -0
- package/dist/methods/secret/set.js.map +1 -0
- package/dist/methods/state/get.d.ts +25 -0
- package/dist/methods/state/get.d.ts.map +1 -0
- package/dist/methods/state/get.js +29 -0
- package/dist/methods/state/get.js.map +1 -0
- package/dist/methods/state/patch.d.ts +32 -0
- package/dist/methods/state/patch.d.ts.map +1 -0
- package/dist/methods/state/patch.js +29 -0
- package/dist/methods/state/patch.js.map +1 -0
- package/dist/methods/view/default.d.ts +19 -0
- package/dist/methods/view/default.d.ts.map +1 -0
- package/dist/methods/view/default.js +23 -0
- package/dist/methods/view/default.js.map +1 -0
- package/dist/methods/view/launch.d.ts +27 -0
- package/dist/methods/view/launch.d.ts.map +1 -0
- package/dist/methods/view/launch.js +30 -0
- package/dist/methods/view/launch.js.map +1 -0
- package/dist/methods/view/revoke.d.ts +19 -0
- package/dist/methods/view/revoke.d.ts.map +1 -0
- package/dist/methods/view/revoke.js +26 -0
- package/dist/methods/view/revoke.js.map +1 -0
- package/dist/methods/view/rotate.d.ts +21 -0
- package/dist/methods/view/rotate.d.ts.map +1 -0
- package/dist/methods/view/rotate.js +27 -0
- package/dist/methods/view/rotate.js.map +1 -0
- package/dist/methods/view/url.d.ts +52 -0
- package/dist/methods/view/url.d.ts.map +1 -0
- package/dist/methods/view/url.js +43 -0
- package/dist/methods/view/url.js.map +1 -0
- package/dist/methods/wait/wait.d.ts +37 -0
- package/dist/methods/wait/wait.d.ts.map +1 -0
- package/dist/methods/wait/wait.js +39 -0
- package/dist/methods/wait/wait.js.map +1 -0
- package/dist/revision.d.ts +43 -0
- package/dist/revision.d.ts.map +1 -0
- package/dist/revision.js +69 -0
- package/dist/revision.js.map +1 -0
- package/dist/rpc/error.d.ts +47 -0
- package/dist/rpc/error.d.ts.map +1 -0
- package/dist/rpc/error.js +77 -0
- package/dist/rpc/error.js.map +1 -0
- package/dist/rpc/lines.d.ts +30 -0
- package/dist/rpc/lines.d.ts.map +1 -0
- package/dist/rpc/lines.js +63 -0
- package/dist/rpc/lines.js.map +1 -0
- package/dist/rpc/messages.d.ts +92 -0
- package/dist/rpc/messages.d.ts.map +1 -0
- package/dist/rpc/messages.js +133 -0
- package/dist/rpc/messages.js.map +1 -0
- package/dist/rpc/peer.d.ts +81 -0
- package/dist/rpc/peer.d.ts.map +1 -0
- package/dist/rpc/peer.js +208 -0
- package/dist/rpc/peer.js.map +1 -0
- package/dist/serializer.d.ts +178 -0
- package/dist/serializer.d.ts.map +1 -0
- package/dist/serializer.js +929 -0
- package/dist/serializer.js.map +1 -0
- package/dist/verify.d.ts +254 -0
- package/dist/verify.d.ts.map +1 -0
- package/dist/verify.js +243 -0
- package/dist/verify.js.map +1 -0
- package/dist/view.d.ts +103 -0
- package/dist/view.d.ts.map +1 -0
- package/dist/view.js +110 -0
- package/dist/view.js.map +1 -0
- package/dist/wire-registry.js +11 -0
- package/dist/wire-registry.js.map +1 -0
- package/dist/worker.d.ts +249 -0
- package/dist/worker.d.ts.map +1 -0
- package/dist/worker.js +158 -0
- package/dist/worker.js.map +1 -0
- package/package.json +114 -3
- package/schemas/protocol.draft-07.json +5120 -0
- package/schemas/protocol.schema.json +4964 -0
- package/src/actions.ts +418 -0
- package/src/artifact.ts +187 -0
- package/src/bridge.ts +618 -0
- package/src/browser.ts +374 -0
- package/src/bundle.ts +264 -0
- package/src/canonical.ts +49 -0
- package/src/capability.ts +92 -0
- package/src/diagnostics/codes/a11y.ts +41 -0
- package/src/diagnostics/codes/action.ts +125 -0
- package/src/diagnostics/codes/artifact.ts +137 -0
- package/src/diagnostics/codes/build.ts +65 -0
- package/src/diagnostics/codes/cli.ts +53 -0
- package/src/diagnostics/codes/console.ts +41 -0
- package/src/diagnostics/codes/dep.ts +101 -0
- package/src/diagnostics/codes/env.ts +149 -0
- package/src/diagnostics/codes/field.ts +113 -0
- package/src/diagnostics/codes/home.ts +150 -0
- package/src/diagnostics/codes/host.ts +197 -0
- package/src/diagnostics/codes/hygiene.ts +175 -0
- package/src/diagnostics/codes/index.ts +142 -0
- package/src/diagnostics/codes/live.ts +41 -0
- package/src/diagnostics/codes/manifest.ts +53 -0
- package/src/diagnostics/codes/network.ts +41 -0
- package/src/diagnostics/codes/platform.ts +30 -0
- package/src/diagnostics/codes/publish.ts +53 -0
- package/src/diagnostics/codes/regression.ts +89 -0
- package/src/diagnostics/codes/runtime.ts +77 -0
- package/src/diagnostics/codes/secret.ts +29 -0
- package/src/diagnostics/codes/smoke.ts +41 -0
- package/src/diagnostics/codes/submit.ts +113 -0
- package/src/diagnostics/codes/target.ts +29 -0
- package/src/diagnostics/codes/type.ts +41 -0
- package/src/diagnostics/codes/verify.ts +113 -0
- package/src/diagnostics/diagnostic.ts +240 -0
- package/src/diagnostics/spec.ts +90 -0
- package/src/hygiene.ts +224 -0
- package/src/ids.ts +279 -0
- package/src/index.ts +576 -0
- package/src/interaction.ts +728 -0
- package/src/manifest.ts +206 -0
- package/src/method.ts +42 -0
- package/src/methods/artifact/create.ts +56 -0
- package/src/methods/artifact/get.ts +30 -0
- package/src/methods/artifact/list.ts +42 -0
- package/src/methods/artifact/publish.ts +46 -0
- package/src/methods/artifact/verify.ts +46 -0
- package/src/methods/deps/add.ts +72 -0
- package/src/methods/dev/start.ts +84 -0
- package/src/methods/dev/stop.ts +32 -0
- package/src/methods/events/ack.ts +41 -0
- package/src/methods/events/read.ts +67 -0
- package/src/methods/events/subscribe.ts +91 -0
- package/src/methods/events/unsubscribe.ts +35 -0
- package/src/methods/gc/run.ts +125 -0
- package/src/methods/index.ts +81 -0
- package/src/methods/instance/check.ts +61 -0
- package/src/methods/instance/status.ts +172 -0
- package/src/methods/live/push.ts +54 -0
- package/src/methods/mostra/initialize.ts +249 -0
- package/src/methods/mostra/shutdown.ts +31 -0
- package/src/methods/port/drafts-mirror.ts +52 -0
- package/src/methods/port/secrets-get.ts +40 -0
- package/src/methods/port/submissions-deliver.ts +70 -0
- package/src/methods/port/trusted-controls-activated.ts +51 -0
- package/src/methods/port/trusted-controls-policy.ts +38 -0
- package/src/methods/results/get.ts +59 -0
- package/src/methods/secret/delete.ts +43 -0
- package/src/methods/secret/list.ts +40 -0
- package/src/methods/secret/set.ts +69 -0
- package/src/methods/state/get.ts +44 -0
- package/src/methods/state/patch.ts +51 -0
- package/src/methods/view/default.ts +32 -0
- package/src/methods/view/launch.ts +47 -0
- package/src/methods/view/revoke.ts +39 -0
- package/src/methods/view/rotate.ts +37 -0
- package/src/methods/view/url.ts +84 -0
- package/src/methods/wait/wait.ts +58 -0
- package/src/revision.ts +101 -0
- package/src/rpc/error.ts +107 -0
- package/src/rpc/lines.ts +70 -0
- package/src/rpc/messages.ts +188 -0
- package/src/rpc/peer.ts +341 -0
- package/src/serializer.ts +1217 -0
- package/src/timers.d.ts +8 -0
- package/src/verify.ts +458 -0
- package/src/view.ts +200 -0
- package/src/web-crypto.d.ts +9 -0
- package/src/web-platform.d.ts +35 -0
- package/src/wire-registry.ts +14 -0
- package/src/worker.ts +374 -0
|
@@ -0,0 +1,929 @@
|
|
|
1
|
+
//#region src/serializer.ts
|
|
2
|
+
/**
|
|
3
|
+
* The most digits a bigint argument may have. A page's arguments are decoded before the action
|
|
4
|
+
* runs, and parsing a bigint takes time that grows faster than its length: 16 M digits held a
|
|
5
|
+
* worker's event loop for seconds. Results aren't limited; server code writes them.
|
|
6
|
+
*/
|
|
7
|
+
const ARGUMENT_BIGINT_DIGITS_MAX = 1e4;
|
|
8
|
+
/** The diagnostic code of a value outside the type set (INTERFACES §2.4). */
|
|
9
|
+
const UNSERIALIZABLE_CODE = "MOSTRA_ACTION_UNSERIALIZABLE";
|
|
10
|
+
/** A value outside the type set, or a malformed written value. */
|
|
11
|
+
var SerializationError = class extends Error {
|
|
12
|
+
/** Always `MOSTRA_ACTION_UNSERIALIZABLE`. */
|
|
13
|
+
code = UNSERIALIZABLE_CODE;
|
|
14
|
+
/** Where in the value: `.items[2].when`, or empty for the value itself. */
|
|
15
|
+
path;
|
|
16
|
+
constructor(message, path = "") {
|
|
17
|
+
super(path === "" ? message : `${where(path)} ${message}`);
|
|
18
|
+
this.name = "SerializationError";
|
|
19
|
+
this.path = path;
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
/** A path as people read it: `[1].when` is "argument 2's .when". */
|
|
23
|
+
function where(path) {
|
|
24
|
+
const argument = /^\[(\d+)\](.*)$/.exec(path);
|
|
25
|
+
if (argument) {
|
|
26
|
+
const rest = argument[2] ?? "";
|
|
27
|
+
return `Argument ${Number(argument[1]) + 1}${rest === "" ? "" : ` at ${rest}`}`;
|
|
28
|
+
}
|
|
29
|
+
return path.startsWith("result") ? `The ${path}` : `The value at ${path}`;
|
|
30
|
+
}
|
|
31
|
+
/** The error a rejected promise or a failed iteration carries on the wire. */
|
|
32
|
+
function wireError(error) {
|
|
33
|
+
if (error instanceof Error) {
|
|
34
|
+
const code = error.code;
|
|
35
|
+
return {
|
|
36
|
+
message: error.message,
|
|
37
|
+
...typeof code === "string" ? { code } : {}
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
return { message: String(error) };
|
|
41
|
+
}
|
|
42
|
+
/** An error read back from the wire, as the reader's promises and iterables reject with it. */
|
|
43
|
+
var RemoteError = class extends Error {
|
|
44
|
+
/** The diagnostic code the error carried, if any. */
|
|
45
|
+
code;
|
|
46
|
+
constructor(error) {
|
|
47
|
+
super(error.message);
|
|
48
|
+
this.name = "RemoteError";
|
|
49
|
+
this.code = error.code;
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
const ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
53
|
+
const LOOKUP = (/* @__PURE__ */ new Int16Array(128)).fill(-1);
|
|
54
|
+
for (let index = 0; index < 64; index += 1) LOOKUP[ALPHABET.charCodeAt(index)] = index;
|
|
55
|
+
/** Standard base64 of `bytes`, with padding. */
|
|
56
|
+
function toBase64(bytes) {
|
|
57
|
+
let out = "";
|
|
58
|
+
let index = 0;
|
|
59
|
+
for (; index + 2 < bytes.length; index += 3) {
|
|
60
|
+
const n = (bytes[index] ?? 0) << 16 | (bytes[index + 1] ?? 0) << 8 | (bytes[index + 2] ?? 0);
|
|
61
|
+
out += ALPHABET.charAt(n >> 18 & 63) + ALPHABET.charAt(n >> 12 & 63) + ALPHABET.charAt(n >> 6 & 63) + ALPHABET.charAt(n & 63);
|
|
62
|
+
}
|
|
63
|
+
const rest = bytes.length - index;
|
|
64
|
+
if (rest === 1) {
|
|
65
|
+
const n = (bytes[index] ?? 0) << 16;
|
|
66
|
+
out += `${ALPHABET[n >> 18 & 63]}${ALPHABET[n >> 12 & 63]}==`;
|
|
67
|
+
} else if (rest === 2) {
|
|
68
|
+
const n = (bytes[index] ?? 0) << 16 | (bytes[index + 1] ?? 0) << 8;
|
|
69
|
+
out += `${ALPHABET[n >> 18 & 63]}${ALPHABET[n >> 12 & 63]}${ALPHABET[n >> 6 & 63]}=`;
|
|
70
|
+
}
|
|
71
|
+
return out;
|
|
72
|
+
}
|
|
73
|
+
/** The bytes of standard base64 text; throws a {@link SerializationError} on anything else. */
|
|
74
|
+
function fromBase64(text) {
|
|
75
|
+
if (text.length % 4 !== 0) throw new SerializationError("Malformed base64 bytes.");
|
|
76
|
+
const padding = text.endsWith("==") ? 2 : text.endsWith("=") ? 1 : 0;
|
|
77
|
+
const out = new Uint8Array(text.length / 4 * 3 - padding);
|
|
78
|
+
let at = 0;
|
|
79
|
+
for (let index = 0; index < text.length; index += 4) {
|
|
80
|
+
const quad = [
|
|
81
|
+
0,
|
|
82
|
+
1,
|
|
83
|
+
2,
|
|
84
|
+
3
|
|
85
|
+
].map((offset) => {
|
|
86
|
+
const char = text.charCodeAt(index + offset);
|
|
87
|
+
if (char === 61 && index + offset >= text.length - padding) return 0;
|
|
88
|
+
const value = char < 128 ? LOOKUP[char] ?? -1 : -1;
|
|
89
|
+
if (value < 0) throw new SerializationError("Malformed base64 bytes.");
|
|
90
|
+
return value;
|
|
91
|
+
});
|
|
92
|
+
const n = (quad[0] ?? 0) << 18 | (quad[1] ?? 0) << 12 | (quad[2] ?? 0) << 6 | (quad[3] ?? 0);
|
|
93
|
+
if (at < out.length) out[at++] = n >> 16 & 255;
|
|
94
|
+
if (at < out.length) out[at++] = n >> 8 & 255;
|
|
95
|
+
if (at < out.length) out[at++] = n & 255;
|
|
96
|
+
}
|
|
97
|
+
return out;
|
|
98
|
+
}
|
|
99
|
+
/** The typed-array kinds, by the tag the wire uses. */
|
|
100
|
+
const TYPED_ARRAYS = {
|
|
101
|
+
Int8Array: "i8",
|
|
102
|
+
Uint8Array: "u8",
|
|
103
|
+
Uint8ClampedArray: "u8c",
|
|
104
|
+
Int16Array: "i16",
|
|
105
|
+
Uint16Array: "u16",
|
|
106
|
+
Int32Array: "i32",
|
|
107
|
+
Uint32Array: "u32",
|
|
108
|
+
Float32Array: "f32",
|
|
109
|
+
Float64Array: "f64",
|
|
110
|
+
BigInt64Array: "i64",
|
|
111
|
+
BigUint64Array: "u64",
|
|
112
|
+
DataView: "dv"
|
|
113
|
+
};
|
|
114
|
+
const TYPED_CONSTRUCTORS = {
|
|
115
|
+
i8: (b) => new Int8Array(b),
|
|
116
|
+
u8: (b) => new Uint8Array(b),
|
|
117
|
+
u8c: (b) => new Uint8ClampedArray(b),
|
|
118
|
+
i16: (b) => new Int16Array(b),
|
|
119
|
+
u16: (b) => new Uint16Array(b),
|
|
120
|
+
i32: (b) => new Int32Array(b),
|
|
121
|
+
u32: (b) => new Uint32Array(b),
|
|
122
|
+
f32: (b) => new Float32Array(b),
|
|
123
|
+
f64: (b) => new Float64Array(b),
|
|
124
|
+
i64: (b) => new BigInt64Array(b),
|
|
125
|
+
u64: (b) => new BigUint64Array(b),
|
|
126
|
+
dv: (b) => new DataView(b)
|
|
127
|
+
};
|
|
128
|
+
/**
|
|
129
|
+
* The wire tag of a typed array or `DataView`, or `undefined` for anything else. A subclass is
|
|
130
|
+
* its built-in base (Node's `Buffer` is a `Uint8Array`), found along the prototype chain, so
|
|
131
|
+
* what Node's file and crypto APIs return crosses as the bytes it holds.
|
|
132
|
+
*/
|
|
133
|
+
function typedKind(value) {
|
|
134
|
+
if (!ArrayBuffer.isView(value)) return void 0;
|
|
135
|
+
for (let proto = Object.getPrototypeOf(value); proto !== null; proto = Object.getPrototypeOf(proto)) {
|
|
136
|
+
const name = Object.hasOwn(proto, "constructor") ? proto.constructor?.name : void 0;
|
|
137
|
+
if (name !== void 0 && name in TYPED_ARRAYS) return TYPED_ARRAYS[name];
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
const isPlainObject = (value) => Object.getPrototypeOf(value) === Object.prototype;
|
|
141
|
+
const isBlob = (value) => typeof Blob !== "undefined" && value instanceof Blob;
|
|
142
|
+
const isFormData = (value) => typeof FormData !== "undefined" && value instanceof FormData;
|
|
143
|
+
const isPromiseLike = (value) => value instanceof Promise || typeof value.then === "function" && !isPlainObject(value);
|
|
144
|
+
const isAsyncIterable = (value) => typeof value[Symbol.asyncIterator] === "function";
|
|
145
|
+
/** React's element marker: elements are refused (they belong to the `rsc` mode, D19). */
|
|
146
|
+
const REACT_ELEMENT = Symbol.for("react.transitional.element");
|
|
147
|
+
const REACT_LEGACY_ELEMENT = Symbol.for("react.element");
|
|
148
|
+
function describe(value) {
|
|
149
|
+
const proto = Object.getPrototypeOf(value);
|
|
150
|
+
if (proto === null) return "an object with a null prototype";
|
|
151
|
+
const name = proto.constructor?.name;
|
|
152
|
+
return name ? `an instance of ${name}` : "an object that isn't plain";
|
|
153
|
+
}
|
|
154
|
+
const pathKey = (key) => /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key) ? `.${key}` : `[${JSON.stringify(key)}]`;
|
|
155
|
+
/**
|
|
156
|
+
* Writes one value as batches. `write` throws a {@link SerializationError} when the value, or
|
|
157
|
+
* anything it holds synchronously, is outside the type set; a promise that later settles with such
|
|
158
|
+
* a value is written as rejected with that error. `done` settles once every promise and iterable
|
|
159
|
+
* in the value has settled or ended; `abort` stops iterables early (the reader went away).
|
|
160
|
+
*/
|
|
161
|
+
var ValueWriter = class {
|
|
162
|
+
#options;
|
|
163
|
+
#nextId = 1;
|
|
164
|
+
#pending = 0;
|
|
165
|
+
#aborted = false;
|
|
166
|
+
#cutShort = false;
|
|
167
|
+
#wroteRoot = false;
|
|
168
|
+
#rootPath;
|
|
169
|
+
#queue = Promise.resolve();
|
|
170
|
+
#iterators = /* @__PURE__ */ new Set();
|
|
171
|
+
#resolveDone;
|
|
172
|
+
#rejectDone;
|
|
173
|
+
/** Settles once every async part of the value has been written. */
|
|
174
|
+
done;
|
|
175
|
+
constructor(options) {
|
|
176
|
+
this.#options = options;
|
|
177
|
+
this.#rootPath = options.mode === "result" ? "result" : "";
|
|
178
|
+
this.done = new Promise((resolve, reject) => {
|
|
179
|
+
this.#resolveDone = resolve;
|
|
180
|
+
this.#rejectDone = reject;
|
|
181
|
+
});
|
|
182
|
+
this.done.catch(() => {});
|
|
183
|
+
}
|
|
184
|
+
/** Writes the value's first batch; async parts follow in later batches. */
|
|
185
|
+
async write(value) {
|
|
186
|
+
if (this.#wroteRoot) throw new Error("A ValueWriter writes one value.");
|
|
187
|
+
this.#wroteRoot = true;
|
|
188
|
+
this.#pending += 1;
|
|
189
|
+
const root = this.#encodeBatch(value, this.#rootPath, (json, frames) => {
|
|
190
|
+
frames.unshift({
|
|
191
|
+
c: 0,
|
|
192
|
+
v: json
|
|
193
|
+
});
|
|
194
|
+
});
|
|
195
|
+
this.#queue = root.then((batch) => this.#emit(batch), () => {});
|
|
196
|
+
try {
|
|
197
|
+
await root;
|
|
198
|
+
} catch (error) {
|
|
199
|
+
this.#aborted = true;
|
|
200
|
+
this.#rejectDone(error);
|
|
201
|
+
throw error;
|
|
202
|
+
} finally {
|
|
203
|
+
this.#pending -= 1;
|
|
204
|
+
}
|
|
205
|
+
await this.#queue;
|
|
206
|
+
this.#settleIfIdle();
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Whether {@link ValueWriter.abort} stopped the value before all of it was written: a promise
|
|
210
|
+
* still unsettled, an iterable not yet ended.
|
|
211
|
+
*/
|
|
212
|
+
get cutShort() {
|
|
213
|
+
return this.#cutShort;
|
|
214
|
+
}
|
|
215
|
+
/** Stops every iterable still being read, and settles `done`. */
|
|
216
|
+
abort() {
|
|
217
|
+
if (this.#aborted) return;
|
|
218
|
+
this.#cutShort = this.#pending > 0;
|
|
219
|
+
this.#aborted = true;
|
|
220
|
+
for (const iterator of this.#iterators) iterator.return?.()?.catch?.(() => {});
|
|
221
|
+
this.#iterators.clear();
|
|
222
|
+
this.#resolveDone();
|
|
223
|
+
}
|
|
224
|
+
#emit(batch) {
|
|
225
|
+
if (this.#aborted) return;
|
|
226
|
+
this.#options.onBatch(batch);
|
|
227
|
+
}
|
|
228
|
+
#settleIfIdle() {
|
|
229
|
+
if (this.#pending === 0) this.#resolveDone();
|
|
230
|
+
}
|
|
231
|
+
/** Runs batch production one at a time, so batches leave in the order they were started. */
|
|
232
|
+
#serial(task) {
|
|
233
|
+
this.#pending += 1;
|
|
234
|
+
this.#queue = this.#queue.then(async () => {
|
|
235
|
+
const batch = await task();
|
|
236
|
+
if (batch) this.#emit(batch);
|
|
237
|
+
}).catch((error) => {
|
|
238
|
+
this.#aborted = true;
|
|
239
|
+
this.#rejectDone(error);
|
|
240
|
+
}).finally(() => {
|
|
241
|
+
this.#pending -= 1;
|
|
242
|
+
this.#settleIfIdle();
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Encodes `value` into a batch: `place` puts the encoded root into the batch, whose other
|
|
247
|
+
* frames are the chunks it needs.
|
|
248
|
+
*/
|
|
249
|
+
async #encodeBatch(value, path, place) {
|
|
250
|
+
const frames = [];
|
|
251
|
+
const shared = countShared(value);
|
|
252
|
+
const outlined = /* @__PURE__ */ new Map();
|
|
253
|
+
const blobs = [];
|
|
254
|
+
const encode = (item, at, depth) => {
|
|
255
|
+
if (depth > MAX_DEPTH) throw new SerializationError("The value nests too deeply.", at);
|
|
256
|
+
switch (typeof item) {
|
|
257
|
+
case "string": return item.startsWith("$") ? `$${item}` : item;
|
|
258
|
+
case "number":
|
|
259
|
+
if (Number.isNaN(item)) return "$NaN";
|
|
260
|
+
if (item === Number.POSITIVE_INFINITY) return "$Infinity";
|
|
261
|
+
if (item === Number.NEGATIVE_INFINITY) return "$-Infinity";
|
|
262
|
+
if (Object.is(item, -0)) return "$-0";
|
|
263
|
+
return item;
|
|
264
|
+
case "boolean": return item;
|
|
265
|
+
case "undefined": return "$undefined";
|
|
266
|
+
case "bigint": {
|
|
267
|
+
const digits = item.toString();
|
|
268
|
+
if (this.#options.mode === "argument" && digits.replace("-", "").length > 1e4) throw new SerializationError(`is a bigint of more than ${ARGUMENT_BIGINT_DIGITS_MAX} digits; send a larger number as a string.`, at);
|
|
269
|
+
return `$n${digits}`;
|
|
270
|
+
}
|
|
271
|
+
case "symbol": {
|
|
272
|
+
if (this.#options.mode === "argument") throw new SerializationError("is a symbol; an argument can't be one, only a result can (a registered symbol).", at);
|
|
273
|
+
const key = Symbol.keyFor(item);
|
|
274
|
+
if (key === void 0) throw new SerializationError("is a symbol not registered with Symbol.for; only registered symbols can be sent.", at);
|
|
275
|
+
return `$S${key}`;
|
|
276
|
+
}
|
|
277
|
+
case "function": {
|
|
278
|
+
const id = this.#options.serverFunctionId?.(item);
|
|
279
|
+
if (id === void 0) throw new SerializationError("is a function that isn't a Server Function; only Server Functions can be sent.", at);
|
|
280
|
+
return `$h${id}`;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
if (item === null) return null;
|
|
284
|
+
const object = item;
|
|
285
|
+
const known = outlined.get(object);
|
|
286
|
+
if (known !== void 0) return `$${known}`;
|
|
287
|
+
if (object.$$typeof === REACT_ELEMENT || object.$$typeof === REACT_LEGACY_ELEMENT) throw new SerializationError("is a React element; JSX can't cross a server call in the SPA render mode.", at);
|
|
288
|
+
if (object instanceof Date) return Number.isNaN(object.getTime()) ? "$DInvalid" : `$D${object.toISOString()}`;
|
|
289
|
+
if (isPromiseLike(object)) {
|
|
290
|
+
const id = this.#nextId++;
|
|
291
|
+
this.#watchPromise(id, object, `${at}.then`);
|
|
292
|
+
return `$@${id}`;
|
|
293
|
+
}
|
|
294
|
+
if (isFormData(object)) {
|
|
295
|
+
const id = this.#nextId++;
|
|
296
|
+
const entries = [];
|
|
297
|
+
for (const [name, entry] of object.entries()) if (typeof entry === "string") entries.push([name, encode(entry, at, depth + 1)]);
|
|
298
|
+
else {
|
|
299
|
+
const blobId = this.#nextId++;
|
|
300
|
+
blobs.push({
|
|
301
|
+
id: blobId,
|
|
302
|
+
blob: entry
|
|
303
|
+
});
|
|
304
|
+
entries.push([name, `$B${blobId}`]);
|
|
305
|
+
}
|
|
306
|
+
frames.push({
|
|
307
|
+
c: id,
|
|
308
|
+
v: entries
|
|
309
|
+
});
|
|
310
|
+
return `$K${id}`;
|
|
311
|
+
}
|
|
312
|
+
if (object instanceof ArrayBuffer) {
|
|
313
|
+
const id = this.#nextId++;
|
|
314
|
+
frames.push({
|
|
315
|
+
c: id,
|
|
316
|
+
v: toBase64(new Uint8Array(object))
|
|
317
|
+
});
|
|
318
|
+
return `$A${id}`;
|
|
319
|
+
}
|
|
320
|
+
const typed = typedKind(object);
|
|
321
|
+
if (typed !== void 0) {
|
|
322
|
+
const view = object;
|
|
323
|
+
const id = this.#nextId++;
|
|
324
|
+
const bytes = new Uint8Array(view.buffer, view.byteOffset, view.byteLength);
|
|
325
|
+
frames.push({
|
|
326
|
+
c: id,
|
|
327
|
+
v: [typed, toBase64(bytes)]
|
|
328
|
+
});
|
|
329
|
+
return `$T${id}`;
|
|
330
|
+
}
|
|
331
|
+
const outline = (encoded, tag) => {
|
|
332
|
+
const id = this.#nextId++;
|
|
333
|
+
outlined.set(object, id);
|
|
334
|
+
const frame = {
|
|
335
|
+
c: id,
|
|
336
|
+
v: null
|
|
337
|
+
};
|
|
338
|
+
frames.push(frame);
|
|
339
|
+
frame.v = encoded();
|
|
340
|
+
return `${tag}${id}`;
|
|
341
|
+
};
|
|
342
|
+
if (object instanceof Map) return outline(() => [...object.entries()].map(([key, entry], index) => [encode(key, `${at}.<map key ${index}>`, depth + 1), encode(entry, `${at}.<map value ${index}>`, depth + 1)]), "$Q");
|
|
343
|
+
if (object instanceof Set) return outline(() => [...object].map((entry, index) => encode(entry, `${at}.<set item ${index}>`, depth + 1)), "$W");
|
|
344
|
+
if (Array.isArray(object)) {
|
|
345
|
+
const build = () => {
|
|
346
|
+
const out = [];
|
|
347
|
+
for (let index = 0; index < object.length; index += 1) out.push(encode(object[index], `${at}[${index}]`, depth + 1));
|
|
348
|
+
return out;
|
|
349
|
+
};
|
|
350
|
+
return shared.has(object) ? outline(build, "$") : build();
|
|
351
|
+
}
|
|
352
|
+
if (this.#options.mode === "result" && isAsyncIterable(object)) {
|
|
353
|
+
const id = this.#nextId++;
|
|
354
|
+
this.#watchIterable(id, object, at);
|
|
355
|
+
return `$x${id}`;
|
|
356
|
+
}
|
|
357
|
+
if (isBlob(object)) throw new SerializationError("is a Blob or File; send files inside a FormData, as React's Server Functions take them.", at);
|
|
358
|
+
if (!isPlainObject(object)) {
|
|
359
|
+
if (isAsyncIterable(object)) throw new SerializationError("is an async iterable; only a result may be one, never an argument.", at);
|
|
360
|
+
throw new SerializationError(`is ${describe(object)}; only plain objects and the built-ins React's Server Functions accept can be sent.`, at);
|
|
361
|
+
}
|
|
362
|
+
const build = () => {
|
|
363
|
+
const out = {};
|
|
364
|
+
for (const key of Object.keys(object)) {
|
|
365
|
+
const encoded = encode(object[key], `${at}${pathKey(key)}`, depth + 1);
|
|
366
|
+
Object.defineProperty(out, key, {
|
|
367
|
+
value: encoded,
|
|
368
|
+
enumerable: true,
|
|
369
|
+
writable: true,
|
|
370
|
+
configurable: true
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
return out;
|
|
374
|
+
};
|
|
375
|
+
return shared.has(object) ? outline(build, "$") : build();
|
|
376
|
+
};
|
|
377
|
+
const root = encode(value, path, 0);
|
|
378
|
+
for (const { id, blob } of blobs) {
|
|
379
|
+
const bytes = new Uint8Array(await blob.arrayBuffer());
|
|
380
|
+
const file = blob;
|
|
381
|
+
frames.push({
|
|
382
|
+
c: id,
|
|
383
|
+
v: {
|
|
384
|
+
type: blob.type,
|
|
385
|
+
data: toBase64(bytes),
|
|
386
|
+
...typeof file.name === "string" ? { name: file.name } : {},
|
|
387
|
+
...typeof file.lastModified === "number" ? { lastModified: file.lastModified } : {}
|
|
388
|
+
}
|
|
389
|
+
});
|
|
390
|
+
}
|
|
391
|
+
place(root, frames);
|
|
392
|
+
return frames;
|
|
393
|
+
}
|
|
394
|
+
#watchPromise(id, promise, path) {
|
|
395
|
+
this.#pending += 1;
|
|
396
|
+
Promise.resolve(promise).then((settled) => {
|
|
397
|
+
this.#serial(() => this.#encodeBatch(settled, path, (json, frames) => frames.push({
|
|
398
|
+
p: id,
|
|
399
|
+
v: json
|
|
400
|
+
})).catch((error) => [{
|
|
401
|
+
p: id,
|
|
402
|
+
e: wireError(error)
|
|
403
|
+
}]));
|
|
404
|
+
this.#pending -= 1;
|
|
405
|
+
}, (error) => {
|
|
406
|
+
if (this.#options.mode === "argument") this.#serial(async () => {
|
|
407
|
+
throw error;
|
|
408
|
+
});
|
|
409
|
+
else this.#serial(async () => [{
|
|
410
|
+
p: id,
|
|
411
|
+
e: wireError(error)
|
|
412
|
+
}]);
|
|
413
|
+
this.#pending -= 1;
|
|
414
|
+
});
|
|
415
|
+
}
|
|
416
|
+
#watchIterable(id, iterable, path) {
|
|
417
|
+
let iterator;
|
|
418
|
+
try {
|
|
419
|
+
iterator = iterable[Symbol.asyncIterator]();
|
|
420
|
+
} catch (error) {
|
|
421
|
+
this.#serial(async () => [{
|
|
422
|
+
i: id,
|
|
423
|
+
e: wireError(error)
|
|
424
|
+
}]);
|
|
425
|
+
return;
|
|
426
|
+
}
|
|
427
|
+
this.#iterators.add(iterator);
|
|
428
|
+
this.#pending += 1;
|
|
429
|
+
const step = async () => {
|
|
430
|
+
for (let index = 0;; index += 1) {
|
|
431
|
+
if (this.#aborted) return;
|
|
432
|
+
let next;
|
|
433
|
+
try {
|
|
434
|
+
next = await iterator.next();
|
|
435
|
+
} catch (error) {
|
|
436
|
+
this.#serial(async () => [{
|
|
437
|
+
i: id,
|
|
438
|
+
e: wireError(error)
|
|
439
|
+
}]);
|
|
440
|
+
return;
|
|
441
|
+
}
|
|
442
|
+
if (next.done) {
|
|
443
|
+
this.#serial(async () => [{
|
|
444
|
+
i: id,
|
|
445
|
+
end: true
|
|
446
|
+
}]);
|
|
447
|
+
return;
|
|
448
|
+
}
|
|
449
|
+
const item = next.value;
|
|
450
|
+
const at = `${path}<item ${index}>`;
|
|
451
|
+
let failed = false;
|
|
452
|
+
this.#serial(() => this.#encodeBatch(item, at, (json, frames) => frames.push({
|
|
453
|
+
i: id,
|
|
454
|
+
v: json
|
|
455
|
+
})).catch((error) => {
|
|
456
|
+
failed = true;
|
|
457
|
+
return [{
|
|
458
|
+
i: id,
|
|
459
|
+
e: wireError(error)
|
|
460
|
+
}];
|
|
461
|
+
}));
|
|
462
|
+
await this.#queue;
|
|
463
|
+
if (failed) {
|
|
464
|
+
iterator.return?.()?.catch?.(() => {});
|
|
465
|
+
return;
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
};
|
|
469
|
+
step().finally(() => {
|
|
470
|
+
this.#iterators.delete(iterator);
|
|
471
|
+
this.#pending -= 1;
|
|
472
|
+
this.#settleIfIdle();
|
|
473
|
+
});
|
|
474
|
+
}
|
|
475
|
+
};
|
|
476
|
+
/** The deepest nesting a value may have, so a hostile value can't exhaust the stack. */
|
|
477
|
+
const MAX_DEPTH = 512;
|
|
478
|
+
/** The objects and arrays `value` reaches more than once (shared, or part of a cycle). */
|
|
479
|
+
function countShared(value) {
|
|
480
|
+
const seen = /* @__PURE__ */ new Set();
|
|
481
|
+
const shared = /* @__PURE__ */ new Set();
|
|
482
|
+
const stack = [value];
|
|
483
|
+
while (stack.length > 0) {
|
|
484
|
+
const item = stack.pop();
|
|
485
|
+
if (typeof item !== "object" || item === null) continue;
|
|
486
|
+
if (seen.has(item)) {
|
|
487
|
+
shared.add(item);
|
|
488
|
+
continue;
|
|
489
|
+
}
|
|
490
|
+
seen.add(item);
|
|
491
|
+
if (Array.isArray(item)) for (const entry of item) stack.push(entry);
|
|
492
|
+
else if (item instanceof Map) for (const [key, entry] of item) stack.push(key, entry);
|
|
493
|
+
else if (item instanceof Set) for (const entry of item) stack.push(entry);
|
|
494
|
+
else if (Object.getPrototypeOf(item) === Object.prototype) for (const key of Object.keys(item)) stack.push(item[key]);
|
|
495
|
+
}
|
|
496
|
+
return shared;
|
|
497
|
+
}
|
|
498
|
+
/**
|
|
499
|
+
* Writes `value` completely: every promise settled, so the batches can be sent at once. For
|
|
500
|
+
* arguments, which a browser sends in one request.
|
|
501
|
+
*/
|
|
502
|
+
async function serializeAll(value, options) {
|
|
503
|
+
const batches = [];
|
|
504
|
+
const writer = new ValueWriter({
|
|
505
|
+
...options,
|
|
506
|
+
onBatch: (batch) => batches.push(batch)
|
|
507
|
+
});
|
|
508
|
+
await writer.write(value);
|
|
509
|
+
await writer.done;
|
|
510
|
+
return batches;
|
|
511
|
+
}
|
|
512
|
+
function deferred() {
|
|
513
|
+
let resolve;
|
|
514
|
+
let reject;
|
|
515
|
+
const promise = new Promise((res, rej) => {
|
|
516
|
+
resolve = res;
|
|
517
|
+
reject = rej;
|
|
518
|
+
});
|
|
519
|
+
promise.catch(() => {});
|
|
520
|
+
const entry = {
|
|
521
|
+
promise,
|
|
522
|
+
resolve: (value) => {
|
|
523
|
+
entry.settled = true;
|
|
524
|
+
resolve(value);
|
|
525
|
+
},
|
|
526
|
+
reject: (error) => {
|
|
527
|
+
entry.settled = true;
|
|
528
|
+
reject(error);
|
|
529
|
+
},
|
|
530
|
+
settled: false
|
|
531
|
+
};
|
|
532
|
+
return entry;
|
|
533
|
+
}
|
|
534
|
+
/** An async iterable fed by frames: one reader, items buffered until taken. */
|
|
535
|
+
var FedIterable = class {
|
|
536
|
+
#items = [];
|
|
537
|
+
#ended = false;
|
|
538
|
+
#error;
|
|
539
|
+
#wake;
|
|
540
|
+
#taken = false;
|
|
541
|
+
push(value) {
|
|
542
|
+
this.#items.push(value);
|
|
543
|
+
this.#wake?.();
|
|
544
|
+
}
|
|
545
|
+
end() {
|
|
546
|
+
this.#ended = true;
|
|
547
|
+
this.#wake?.();
|
|
548
|
+
}
|
|
549
|
+
fail(error) {
|
|
550
|
+
if (this.#ended) return;
|
|
551
|
+
this.#error = error;
|
|
552
|
+
this.#ended = true;
|
|
553
|
+
this.#wake?.();
|
|
554
|
+
}
|
|
555
|
+
get ended() {
|
|
556
|
+
return this.#ended;
|
|
557
|
+
}
|
|
558
|
+
[Symbol.asyncIterator]() {
|
|
559
|
+
if (this.#taken) throw new Error("This async iterable can be read once.");
|
|
560
|
+
this.#taken = true;
|
|
561
|
+
return {
|
|
562
|
+
next: async () => {
|
|
563
|
+
for (;;) {
|
|
564
|
+
if (this.#items.length > 0) return {
|
|
565
|
+
done: false,
|
|
566
|
+
value: this.#items.shift()
|
|
567
|
+
};
|
|
568
|
+
if (this.#ended) {
|
|
569
|
+
if (this.#error !== void 0) throw this.#error;
|
|
570
|
+
return {
|
|
571
|
+
done: true,
|
|
572
|
+
value: void 0
|
|
573
|
+
};
|
|
574
|
+
}
|
|
575
|
+
await new Promise((resolve) => {
|
|
576
|
+
this.#wake = resolve;
|
|
577
|
+
});
|
|
578
|
+
this.#wake = void 0;
|
|
579
|
+
}
|
|
580
|
+
},
|
|
581
|
+
return: async () => {
|
|
582
|
+
this.#ended = true;
|
|
583
|
+
this.#items.length = 0;
|
|
584
|
+
return {
|
|
585
|
+
done: true,
|
|
586
|
+
value: void 0
|
|
587
|
+
};
|
|
588
|
+
}
|
|
589
|
+
};
|
|
590
|
+
}
|
|
591
|
+
};
|
|
592
|
+
const malformed = (what) => new SerializationError(`The written value is malformed: ${what}.`);
|
|
593
|
+
const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
594
|
+
/**
|
|
595
|
+
* Reads batches back into a value. `root` resolves once the first batch arrived; promises and
|
|
596
|
+
* async iterables in it settle and yield as later batches arrive. A malformed batch throws a
|
|
597
|
+
* {@link SerializationError} from `push`; `fail` rejects everything still open, for a stream that
|
|
598
|
+
* broke before its end.
|
|
599
|
+
*/
|
|
600
|
+
var ValueReader = class {
|
|
601
|
+
#options;
|
|
602
|
+
/** Raw chunks by ID, and what each became. */
|
|
603
|
+
#raw = /* @__PURE__ */ new Map();
|
|
604
|
+
#decoded = /* @__PURE__ */ new Map();
|
|
605
|
+
#promises = /* @__PURE__ */ new Map();
|
|
606
|
+
#iterables = /* @__PURE__ */ new Map();
|
|
607
|
+
/** Frames for promises or iterables not referenced yet. */
|
|
608
|
+
#early = [];
|
|
609
|
+
#root = deferred();
|
|
610
|
+
#hasRoot = false;
|
|
611
|
+
/** The value, once the first batch arrived. */
|
|
612
|
+
root = this.#root.promise;
|
|
613
|
+
constructor(options = {}) {
|
|
614
|
+
this.#options = options;
|
|
615
|
+
}
|
|
616
|
+
/** Whether every promise and iterable read so far has settled or ended. */
|
|
617
|
+
get complete() {
|
|
618
|
+
return this.#hasRoot && [...this.#promises.values()].every((entry) => entry.settled) && [...this.#iterables.values()].every((entry) => entry.ended);
|
|
619
|
+
}
|
|
620
|
+
/** Takes one batch. */
|
|
621
|
+
push(batch) {
|
|
622
|
+
if (!Array.isArray(batch)) throw malformed("a batch isn't an array");
|
|
623
|
+
const ordered = [];
|
|
624
|
+
for (const frame of batch) {
|
|
625
|
+
if (!isRecord(frame)) throw malformed("a frame isn't an object");
|
|
626
|
+
if (typeof frame["c"] === "number") {
|
|
627
|
+
if (!Number.isSafeInteger(frame["c"]) || frame["c"] < 0) throw malformed("a chunk ID");
|
|
628
|
+
if (this.#raw.has(frame["c"])) throw malformed(`chunk ${frame["c"]} was written twice`);
|
|
629
|
+
this.#raw.set(frame["c"], frame["v"]);
|
|
630
|
+
} else if (typeof frame["p"] === "number" || typeof frame["i"] === "number") ordered.push(frame);
|
|
631
|
+
else throw malformed("a frame has no chunk, promise or iterable ID");
|
|
632
|
+
}
|
|
633
|
+
if (!this.#hasRoot && this.#raw.has(0)) {
|
|
634
|
+
this.#hasRoot = true;
|
|
635
|
+
try {
|
|
636
|
+
this.#root.resolve(this.#decode(this.#raw.get(0), 0));
|
|
637
|
+
} catch (error) {
|
|
638
|
+
this.#root.reject(error);
|
|
639
|
+
throw error;
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
for (const frame of ordered) this.#apply(frame);
|
|
643
|
+
}
|
|
644
|
+
/**
|
|
645
|
+
* Ends the value: every frame taken so far is applied, and the value must be complete. Throws a
|
|
646
|
+
* {@link SerializationError} when a promise or iterable it holds is still open or a frame names
|
|
647
|
+
* one the value never refers to, so a reader that has all the batches (a page's arguments)
|
|
648
|
+
* never hands on a promise that can't settle.
|
|
649
|
+
*/
|
|
650
|
+
finish() {
|
|
651
|
+
if (!this.#hasRoot) throw malformed("the value has no root");
|
|
652
|
+
for (;;) {
|
|
653
|
+
const before = this.#early.length;
|
|
654
|
+
if (before === 0) break;
|
|
655
|
+
this.#flush();
|
|
656
|
+
if (this.#early.length === before) break;
|
|
657
|
+
}
|
|
658
|
+
if (this.#early.length > 0) throw malformed("a frame names a promise the value doesn't hold");
|
|
659
|
+
if (!this.complete) throw malformed("the value ended before its promises settled");
|
|
660
|
+
}
|
|
661
|
+
/** Rejects every promise and iterable still open: the stream broke. */
|
|
662
|
+
fail(error) {
|
|
663
|
+
if (!this.#hasRoot) this.#root.reject(error);
|
|
664
|
+
for (const entry of this.#promises.values()) if (!entry.settled) entry.reject(error);
|
|
665
|
+
for (const entry of this.#iterables.values()) entry.fail(error);
|
|
666
|
+
}
|
|
667
|
+
#apply(frame) {
|
|
668
|
+
if ("p" in frame) {
|
|
669
|
+
const entry = this.#promises.get(frame.p);
|
|
670
|
+
if (!entry) {
|
|
671
|
+
this.#early.push(frame);
|
|
672
|
+
return;
|
|
673
|
+
}
|
|
674
|
+
if (entry.settled) throw malformed(`promise ${frame.p} settled twice`);
|
|
675
|
+
if ("e" in frame) entry.reject(new RemoteError(readError(frame.e)));
|
|
676
|
+
else entry.resolve(this.#decode(frame.v, 0));
|
|
677
|
+
return;
|
|
678
|
+
}
|
|
679
|
+
const entry = this.#iterables.get(frame.i);
|
|
680
|
+
if (!entry) {
|
|
681
|
+
this.#early.push(frame);
|
|
682
|
+
return;
|
|
683
|
+
}
|
|
684
|
+
if ("e" in frame) entry.fail(new RemoteError(readError(frame.e)));
|
|
685
|
+
else if ("end" in frame) entry.end();
|
|
686
|
+
else entry.push(this.#decode(frame.v, 0));
|
|
687
|
+
}
|
|
688
|
+
#chunk(id) {
|
|
689
|
+
if (!this.#raw.has(id)) throw malformed(`chunk ${id} is missing`);
|
|
690
|
+
return this.#raw.get(id);
|
|
691
|
+
}
|
|
692
|
+
#take(id, build) {
|
|
693
|
+
if (this.#decoded.has(id)) return this.#decoded.get(id);
|
|
694
|
+
const value = build(this.#chunk(id));
|
|
695
|
+
if (!this.#decoded.has(id)) this.#decoded.set(id, value);
|
|
696
|
+
return value;
|
|
697
|
+
}
|
|
698
|
+
#flush() {
|
|
699
|
+
const early = this.#early.splice(0);
|
|
700
|
+
for (const frame of early) this.#apply(frame);
|
|
701
|
+
}
|
|
702
|
+
#decode(json, depth) {
|
|
703
|
+
if (depth > MAX_DEPTH) throw malformed("the value nests too deeply");
|
|
704
|
+
if (json === null || typeof json === "boolean") return json;
|
|
705
|
+
if (typeof json === "number") {
|
|
706
|
+
if (!Number.isFinite(json)) throw malformed("a number isn't finite");
|
|
707
|
+
return json;
|
|
708
|
+
}
|
|
709
|
+
if (typeof json === "string") return this.#string(json, depth);
|
|
710
|
+
if (Array.isArray(json)) return json.map((item) => this.#decode(item, depth + 1));
|
|
711
|
+
if (isRecord(json)) {
|
|
712
|
+
const out = {};
|
|
713
|
+
for (const key of Object.keys(json)) Object.defineProperty(out, key, {
|
|
714
|
+
value: this.#decode(json[key], depth + 1),
|
|
715
|
+
enumerable: true,
|
|
716
|
+
writable: true,
|
|
717
|
+
configurable: true
|
|
718
|
+
});
|
|
719
|
+
return out;
|
|
720
|
+
}
|
|
721
|
+
throw malformed("a value isn't JSON");
|
|
722
|
+
}
|
|
723
|
+
#id(text, at) {
|
|
724
|
+
const id = Number(text.slice(at));
|
|
725
|
+
if (!/^[0-9]+$/.test(text.slice(at)) || !Number.isSafeInteger(id)) throw malformed(`the reference ${JSON.stringify(text.slice(0, 40))}`);
|
|
726
|
+
return id;
|
|
727
|
+
}
|
|
728
|
+
#string(text, depth) {
|
|
729
|
+
if (!text.startsWith("$")) return text;
|
|
730
|
+
if (text.startsWith("$$")) return text.slice(1);
|
|
731
|
+
switch (text) {
|
|
732
|
+
case "$undefined": return;
|
|
733
|
+
case "$NaN": return NaN;
|
|
734
|
+
case "$Infinity": return Number.POSITIVE_INFINITY;
|
|
735
|
+
case "$-Infinity": return Number.NEGATIVE_INFINITY;
|
|
736
|
+
case "$-0": return -0;
|
|
737
|
+
case "$DInvalid": return /* @__PURE__ */ new Date(NaN);
|
|
738
|
+
}
|
|
739
|
+
switch (text[1]) {
|
|
740
|
+
case "n":
|
|
741
|
+
if (!/^-?[0-9]+$/.test(text.slice(2))) throw malformed("a bigint");
|
|
742
|
+
if (this.#options.mode === "argument" && text.replace("-", "").length - 2 > 1e4) throw malformed(`a bigint argument has more than ${ARGUMENT_BIGINT_DIGITS_MAX} digits`);
|
|
743
|
+
return BigInt(text.slice(2));
|
|
744
|
+
case "S":
|
|
745
|
+
if (this.#options.mode === "argument") throw malformed("an argument is a symbol");
|
|
746
|
+
return Symbol.for(text.slice(2));
|
|
747
|
+
case "D": {
|
|
748
|
+
const date = new Date(text.slice(2));
|
|
749
|
+
if (Number.isNaN(date.getTime())) throw malformed("a date");
|
|
750
|
+
return date;
|
|
751
|
+
}
|
|
752
|
+
case "h": {
|
|
753
|
+
const id = text.slice(2);
|
|
754
|
+
if (!this.#options.serverFunction) throw malformed(`a Server Function reference ${id}`);
|
|
755
|
+
return this.#options.serverFunction(id);
|
|
756
|
+
}
|
|
757
|
+
case "@": {
|
|
758
|
+
const id = this.#id(text, 2);
|
|
759
|
+
let entry = this.#promises.get(id);
|
|
760
|
+
if (!entry) {
|
|
761
|
+
entry = deferred();
|
|
762
|
+
this.#promises.set(id, entry);
|
|
763
|
+
queueMicrotask(() => this.#flushSafely());
|
|
764
|
+
}
|
|
765
|
+
return entry.promise;
|
|
766
|
+
}
|
|
767
|
+
case "x": {
|
|
768
|
+
if (this.#options.mode === "argument") throw malformed("an argument is an async iterable");
|
|
769
|
+
const id = this.#id(text, 2);
|
|
770
|
+
let entry = this.#iterables.get(id);
|
|
771
|
+
if (!entry) {
|
|
772
|
+
entry = new FedIterable();
|
|
773
|
+
this.#iterables.set(id, entry);
|
|
774
|
+
queueMicrotask(() => this.#flushSafely());
|
|
775
|
+
}
|
|
776
|
+
return entry;
|
|
777
|
+
}
|
|
778
|
+
case "Q": {
|
|
779
|
+
const id = this.#id(text, 2);
|
|
780
|
+
if (this.#decoded.has(id)) return this.#decoded.get(id);
|
|
781
|
+
const map = /* @__PURE__ */ new Map();
|
|
782
|
+
this.#decoded.set(id, map);
|
|
783
|
+
const raw = this.#chunk(id);
|
|
784
|
+
if (!Array.isArray(raw)) throw malformed("a map");
|
|
785
|
+
for (const pair of raw) {
|
|
786
|
+
if (!Array.isArray(pair) || pair.length !== 2) throw malformed("a map entry");
|
|
787
|
+
map.set(this.#decode(pair[0], depth + 1), this.#decode(pair[1], depth + 1));
|
|
788
|
+
}
|
|
789
|
+
return map;
|
|
790
|
+
}
|
|
791
|
+
case "W": {
|
|
792
|
+
const id = this.#id(text, 2);
|
|
793
|
+
if (this.#decoded.has(id)) return this.#decoded.get(id);
|
|
794
|
+
const set = /* @__PURE__ */ new Set();
|
|
795
|
+
this.#decoded.set(id, set);
|
|
796
|
+
const raw = this.#chunk(id);
|
|
797
|
+
if (!Array.isArray(raw)) throw malformed("a set");
|
|
798
|
+
for (const item of raw) set.add(this.#decode(item, depth + 1));
|
|
799
|
+
return set;
|
|
800
|
+
}
|
|
801
|
+
case "A": return this.#take(this.#id(text, 2), (raw) => {
|
|
802
|
+
if (typeof raw !== "string") throw malformed("an ArrayBuffer");
|
|
803
|
+
const bytes = fromBase64(raw);
|
|
804
|
+
return bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength);
|
|
805
|
+
});
|
|
806
|
+
case "T": return this.#take(this.#id(text, 2), (raw) => {
|
|
807
|
+
if (!Array.isArray(raw) || typeof raw[1] !== "string") throw malformed("a typed array");
|
|
808
|
+
const make = TYPED_CONSTRUCTORS[raw[0]];
|
|
809
|
+
if (!make) throw malformed("a typed array's kind");
|
|
810
|
+
const bytes = fromBase64(raw[1]);
|
|
811
|
+
const buffer = bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength);
|
|
812
|
+
try {
|
|
813
|
+
return make(buffer);
|
|
814
|
+
} catch {
|
|
815
|
+
throw malformed("a typed array's length");
|
|
816
|
+
}
|
|
817
|
+
});
|
|
818
|
+
case "B": return this.#take(this.#id(text, 2), (raw) => {
|
|
819
|
+
if (!isRecord(raw) || typeof raw["data"] !== "string" || typeof raw["type"] !== "string") throw malformed("a file");
|
|
820
|
+
const parts = [fromBase64(raw["data"])];
|
|
821
|
+
if (typeof raw["name"] === "string" && typeof File !== "undefined") return new File(parts, raw["name"], {
|
|
822
|
+
type: raw["type"],
|
|
823
|
+
...typeof raw["lastModified"] === "number" ? { lastModified: raw["lastModified"] } : {}
|
|
824
|
+
});
|
|
825
|
+
return new Blob(parts, { type: raw["type"] });
|
|
826
|
+
});
|
|
827
|
+
case "K": return this.#take(this.#id(text, 2), (raw) => {
|
|
828
|
+
if (!Array.isArray(raw)) throw malformed("a FormData");
|
|
829
|
+
const form = new FormData();
|
|
830
|
+
for (const entry of raw) {
|
|
831
|
+
if (!Array.isArray(entry) || typeof entry[0] !== "string") throw malformed("a FormData entry");
|
|
832
|
+
const value = this.#decode(entry[1], depth + 1);
|
|
833
|
+
if (typeof value === "string") form.append(entry[0], value);
|
|
834
|
+
else if (isBlob(value)) form.append(entry[0], value);
|
|
835
|
+
else throw malformed("a FormData value");
|
|
836
|
+
}
|
|
837
|
+
return form;
|
|
838
|
+
});
|
|
839
|
+
default: {
|
|
840
|
+
const id = this.#id(text, 1);
|
|
841
|
+
if (this.#decoded.has(id)) return this.#decoded.get(id);
|
|
842
|
+
const raw = this.#chunk(id);
|
|
843
|
+
if (Array.isArray(raw)) {
|
|
844
|
+
const array = [];
|
|
845
|
+
this.#decoded.set(id, array);
|
|
846
|
+
for (const item of raw) array.push(this.#decode(item, depth + 1));
|
|
847
|
+
return array;
|
|
848
|
+
}
|
|
849
|
+
if (!isRecord(raw)) throw malformed("a shared object");
|
|
850
|
+
const object = {};
|
|
851
|
+
this.#decoded.set(id, object);
|
|
852
|
+
for (const key of Object.keys(raw)) Object.defineProperty(object, key, {
|
|
853
|
+
value: this.#decode(raw[key], depth + 1),
|
|
854
|
+
enumerable: true,
|
|
855
|
+
writable: true,
|
|
856
|
+
configurable: true
|
|
857
|
+
});
|
|
858
|
+
return object;
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
#flushSafely() {
|
|
863
|
+
try {
|
|
864
|
+
this.#flush();
|
|
865
|
+
} catch (error) {
|
|
866
|
+
this.fail(error);
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
};
|
|
870
|
+
function readError(value) {
|
|
871
|
+
if (!isRecord(value) || typeof value["message"] !== "string") throw malformed("an error");
|
|
872
|
+
return {
|
|
873
|
+
message: value["message"],
|
|
874
|
+
...typeof value["code"] === "string" ? { code: value["code"] } : {}
|
|
875
|
+
};
|
|
876
|
+
}
|
|
877
|
+
/**
|
|
878
|
+
* Reads complete batches back into a value: every promise in it settled from the batches, every
|
|
879
|
+
* async iterable replaying its items. For arguments and stored results.
|
|
880
|
+
*/
|
|
881
|
+
async function deserializeAll(batches, options = {}) {
|
|
882
|
+
const reader = new ValueReader(options);
|
|
883
|
+
for (const batch of batches) reader.push(batch);
|
|
884
|
+
if (options.mode === "argument") reader.finish();
|
|
885
|
+
if (!reader.complete) queueMicrotask(() => reader.fail(new SerializationError("The written value ended early.")));
|
|
886
|
+
return reader.root;
|
|
887
|
+
}
|
|
888
|
+
/**
|
|
889
|
+
* Checks a page's argument batches without decoding them, before they reach server code: no
|
|
890
|
+
* symbol (`$S`), no async iterable (`$x`), no bigint of more than
|
|
891
|
+
* {@link ARGUMENT_BIGINT_DIGITS_MAX} digits. The supervisor runs it so such arguments are refused
|
|
892
|
+
* before any worker sees them (Opus review 1); the worker's reader refuses them again.
|
|
893
|
+
*
|
|
894
|
+
* @throws SerializationError naming what was found.
|
|
895
|
+
*/
|
|
896
|
+
function checkArgumentFrames(batches) {
|
|
897
|
+
const check = (text) => {
|
|
898
|
+
if (text.length < 2 || text[0] !== "$" || text[1] === "$") return;
|
|
899
|
+
if (text[1] === "S") throw malformed("an argument is a symbol");
|
|
900
|
+
if (text[1] === "x") throw malformed("an argument is an async iterable");
|
|
901
|
+
if (text[1] === "n" && text.replace("-", "").length - 2 > 1e4) throw malformed(`a bigint argument has more than ${ARGUMENT_BIGINT_DIGITS_MAX} digits`);
|
|
902
|
+
};
|
|
903
|
+
const scan = (value, visit) => {
|
|
904
|
+
const stack = [value];
|
|
905
|
+
while (stack.length > 0) {
|
|
906
|
+
const item = stack.pop();
|
|
907
|
+
if (typeof item === "string") visit(item);
|
|
908
|
+
else if (Array.isArray(item)) for (const entry of item) stack.push(entry);
|
|
909
|
+
else if (item !== null && typeof item === "object") for (const entry of Object.values(item)) stack.push(entry);
|
|
910
|
+
}
|
|
911
|
+
};
|
|
912
|
+
const forms = /* @__PURE__ */ new Set();
|
|
913
|
+
scan(batches, (text) => {
|
|
914
|
+
const match = /^\$K([0-9]+)$/.exec(text);
|
|
915
|
+
if (match) forms.add(Number(match[1]));
|
|
916
|
+
});
|
|
917
|
+
for (const batch of batches) {
|
|
918
|
+
if (!Array.isArray(batch)) continue;
|
|
919
|
+
for (const frame of batch) {
|
|
920
|
+
const record = frame;
|
|
921
|
+
if (record !== null && typeof record === "object" && typeof record.c === "number" && forms.has(record.c) && Array.isArray(record.v)) for (const entry of record.v) scan(Array.isArray(entry) ? entry[1] : entry, check);
|
|
922
|
+
else scan(frame, check);
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
}
|
|
926
|
+
//#endregion
|
|
927
|
+
export { ARGUMENT_BIGINT_DIGITS_MAX, RemoteError, SerializationError, UNSERIALIZABLE_CODE, ValueReader, ValueWriter, checkArgumentFrames, deserializeAll, fromBase64, serializeAll, toBase64, wireError };
|
|
928
|
+
|
|
929
|
+
//# sourceMappingURL=serializer.js.map
|