@daugasauron/dolly 0.1.5 → 0.1.6
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 +51 -78
- package/coi-serviceworker.js +23 -8
- package/dist/dolly-build-id.mjs +1 -1
- package/dist/dolly-image-build-id.mjs +1 -1
- package/dist/dolly-process-0.wasm +0 -0
- package/dist/dolly-process-abi.mjs +1 -1
- package/dist/dolly-process-dso.mjs +19 -11
- package/dist/dolly-process-worker.mjs +88 -33
- package/dist/dolly-runtime-worker.mjs +1544 -0
- package/dist/dolly.wasm +0 -0
- package/host/dso/dso.mjs +2 -2
- package/host/dso/module.json +4 -1
- package/host/http/abi.mjs +3 -1
- package/host/http/broker.mjs +17 -7
- package/host/http/http.mjs +19 -5
- package/host/http/module.json +3 -1
- package/host/http/policy.mjs +13 -6
- package/host/http/refusals.mjs +77 -0
- package/host/input/abi.mjs +1 -1
- package/host/modules.mjs +64 -23
- package/host/nena/module.json +2 -1
- package/host/nena/nena.mjs +2 -0
- package/host/packages/abi.mjs +27 -0
- package/host/packages/module.json +6 -4
- package/host/packages/packages.mjs +23 -8
- package/host/packages/service.mjs +46 -20
- package/host/packages/transport.mjs +123 -0
- package/host/packages/worker.mjs +13 -9
- package/host/requirements.mjs +1 -1
- package/host/runtime/abi.mjs +32 -0
- package/host/runtime/lease-bridge.mjs +13 -8
- package/host/runtime/module.json +3 -3
- package/host/runtime/runtime.mjs +3 -3
- package/host/snapshot/abi.mjs +2 -1
- package/host/snapshot/module.json +1 -1
- package/host/snapshot/snapshot.mjs +80 -57
- package/host/snapshot/transport.mjs +10 -3
- package/host/snapshot/ui.mjs +64 -39
- package/host/stack/module.json +1 -0
- package/host/stack/stack.mjs +1 -1
- package/host/threads/module.json +6 -1
- package/host/threads/threads.mjs +32 -13
- package/package.json +2 -2
- package/{src → page}/browser.mjs +37 -23
- package/page/generated.mjs +8 -0
- package/{src → page}/image-entry.mjs +10 -6
- package/{src → page}/image-inputs.mjs +11 -0
- package/{src → page}/image-names.mjs +2 -2
- package/{src → page}/kernel-plugin.mjs +1 -1
- package/{src → page}/pack-store.mjs +1 -1
- package/{src → page}/packaged-snapshot.mjs +56 -46
- package/{src → page}/process-constants.mjs +72 -15
- package/{src → page}/process-supervisor.mjs +155 -227
- package/{src → page}/snapshot-records.mjs +63 -44
- package/{src → page}/static-asset.mjs +36 -20
- package/{src → page}/version.mjs +1 -1
- package/{src → page}/worker-image.mjs +20 -9
- package/{src → site}/build-worker.mjs +36 -25
- package/{src → site}/custom-image.mjs +2 -10
- package/{src → site}/dollyfile-graph.mjs +1 -1
- package/{src → site}/dollyfile-view.mjs +1 -1
- package/{src → site}/image-artifact.mjs +9 -8
- package/{src → site}/image-build.mjs +4 -4
- package/{src → site}/image-builder.mjs +5 -4
- package/site/offline.mjs +53 -0
- package/{src → site}/session-store.mjs +47 -38
- package/src/runtime-worker.mjs +0 -57
- /package/{src → page}/build-log.mjs +0 -0
- /package/{src → page}/images.mjs +0 -0
- /package/{src → page}/page-chords.mjs +0 -0
- /package/{src → page}/page-indicators.mjs +0 -0
- /package/{src → page}/process-abi.mjs +0 -0
- /package/{src → page}/sha256.mjs +0 -0
- /package/{src → page}/terminal-text.mjs +0 -0
- /package/{src → page}/wasm-interface.mjs +0 -0
- /package/{src → site}/alphabetical.mjs +0 -0
package/README.md
CHANGED
|
@@ -2,16 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
Dolly is a POSIX-like userspace for wasm64 that runs in a browser tab: a Wasm
|
|
4
4
|
kernel, programs in private Wasm memories, and host modules that bridge it to
|
|
5
|
-
the browser. These npm packages put it in a page of your own
|
|
6
|
-
|
|
5
|
+
the browser. These npm packages put it in a page of your own: this document is
|
|
6
|
+
`boot()` and the page around it. [Dolly from npm](npm.md) is the guide to the
|
|
7
|
+
packages and to `dolly-build`, which builds an image of your own: a coding agent
|
|
8
|
+
with your tools and skills, as a static site.
|
|
7
9
|
|
|
8
10
|
| Package | What it holds |
|
|
9
11
|
| --- | --- |
|
|
10
12
|
| `@daugasauron/dolly` | The runtime: `boot()`, the kernel, the process runtime, its image builder, and the host modules that are its own machinery (`runtime`, `http`, `threads`, `dso`, `stack`, `nena`, `snapshot`, `packages`) |
|
|
11
13
|
| `@daugasauron/dolly-host-NAME` | One device host module each: `display` (Ghostty's terminal and programs' frames), `input`, `gpu`, `audio`, `microphone`, `touch`, `download` (as `dolly-host-save`: npm takes no new name with the word), `upload`, `html`, `sockets`, `pty` |
|
|
12
|
-
| `@daugasauron/dolly-image-NAME` | An image's directory for `boot()`: `default` (a shell, its text tools, the terminal, curl, `amy`, `nena`, `ps
|
|
13
|
-
| `@daugasauron/dolly-package-NAME` |
|
|
14
|
-
| `@daugasauron/dolly-build` | The `dolly-build` command: a project with an image of your own, `FROM` `pi-minimal` with the packages it `INSTALL`s, built in a browser into a site a static host serves ("Your own image" below) |
|
|
14
|
+
| `@daugasauron/dolly-image-NAME` | An image's directory for `boot()`: `default` (a shell, its text tools, the terminal, curl, `amy`, `nena`, `ps`), `pi-minimal` (the Pi coding agent with JavaScript, a shell, POSIX tools, curl, ripgrep and fd, on `display`, `input`, `download` and `html` alone: the README's "Pi with npm"), `python-data` (`default` with Python 3.14, pip, the C compiler, NumPy, pandas, Matplotlib and seaborn). Its README gives the install line and the `FROM` row of a recipe built on it. Its `amy-index.txt` lists the packages the image holds, so `amy list` and `amy info` describe them |
|
|
15
|
+
| `@daugasauron/dolly-package-NAME`, `@daugasauron/dolly-build` | Packages for an image of your own, and the command that builds it ([Dolly from npm](npm.md)) |
|
|
15
16
|
|
|
16
17
|
```sh
|
|
17
18
|
npm install @daugasauron/dolly @daugasauron/dolly-image-default \
|
|
@@ -33,7 +34,7 @@ in `.yarnrc.yml`: Plug'n'Play leaves no files to serve.
|
|
|
33
34
|
<meta charset="utf-8">
|
|
34
35
|
<main id="dolly" style="position:fixed;inset:0"></main>
|
|
35
36
|
<script type="module">
|
|
36
|
-
import { boot } from "./node_modules/@daugasauron/dolly/
|
|
37
|
+
import { boot } from "./node_modules/@daugasauron/dolly/page/browser.mjs";
|
|
37
38
|
import { images, image, modules } from "./node_modules/@daugasauron/dolly-image-default/index.mjs";
|
|
38
39
|
const dolly = await boot(document.querySelector("#dolly"), { images, image, modules });
|
|
39
40
|
</script>
|
|
@@ -50,7 +51,7 @@ the page's.
|
|
|
50
51
|
|
|
51
52
|
| Option | Meaning |
|
|
52
53
|
| --- | --- |
|
|
53
|
-
| `images` | URL of an image directory: `dist/dolly-images.json`, the images' metadata and packs, their recipes, all data. `@daugasauron/dolly-image-default`'s `index.mjs` exports its own. A page has one image directory. The packs an image reads stay in the origin's private storage, so it starts again without downloading them (`
|
|
54
|
+
| `images` | URL of an image directory: `dist/dolly-images.json`, the images' metadata and packs, their recipes, all data. `@daugasauron/dolly-image-default`'s `index.mjs` exports its own. A page has one image directory, which is also `amy`'s package server unless a session names another (`amy server URL`, [Dollyfile](dollyfile.md)). The packs an image reads stay in the origin's private storage, so it starts again without downloading them (`page/pack-store.mjs`) |
|
|
54
55
|
| `image` | The image to run, by name |
|
|
55
56
|
| `modules` | URLs of the `module.json` of each host module the page has. The registry loads these and no other; an image's `REQUIRES HOST` must be among them |
|
|
56
57
|
| `site` | Optional: the URL of a site that serves Dolly's own pages (`session/`, `sessions/`, `docs/`), as Dolly's site does. Given, a saved session names itself in the tab's URL as the site's session route and modules link to those pages |
|
|
@@ -80,9 +81,10 @@ WebGPU adapter, a device that fails to open with `ENODEV`.
|
|
|
80
81
|
|
|
81
82
|
## Colours
|
|
82
83
|
|
|
83
|
-
The terminal's colours
|
|
84
|
-
|
|
85
|
-
|
|
84
|
+
The terminal's colours, the popups' and those of the rest of Dolly's own UI in
|
|
85
|
+
the element (the boot log, the status line, the dialogs, the notices and the
|
|
86
|
+
indicators) are the page's, not the image's. Set these on the element (or above
|
|
87
|
+
it) in your style sheet to match your page; unset, they are Dolly's:
|
|
86
88
|
|
|
87
89
|
```css
|
|
88
90
|
#dolly {
|
|
@@ -98,7 +100,9 @@ and bright yellow (`-3`, `-11`) the accent, bright black (`-8`) `#77736c` and
|
|
|
98
100
|
the others the text's colour, so a program's red shows as its text does. A
|
|
99
101
|
value may be any CSS colour; one that is not counts as unset. The terminal
|
|
100
102
|
takes them at boot and whenever they change, by any rule or media query; a
|
|
101
|
-
popup as it opens.
|
|
103
|
+
popup as it opens. Dolly's UI draws its quieter lines in bright black (`-8`),
|
|
104
|
+
its raised and sunken parts in mixes of the background and the text, and an
|
|
105
|
+
alert in `#e98773`.
|
|
102
106
|
|
|
103
107
|
## Popups
|
|
104
108
|
|
|
@@ -121,6 +125,31 @@ the popup its bytes; without one, name fonts the system has. The page reads the
|
|
|
121
125
|
properties each time a popup opens. Dolly's site sets
|
|
122
126
|
`"Dolly IosevkaTerm SemiBold", monospace` and its font file.
|
|
123
127
|
|
|
128
|
+
## A terminal into the session
|
|
129
|
+
|
|
130
|
+
An image that declares `console@0` (`@daugasauron/dolly-host-console`) gives
|
|
131
|
+
boot()'s handle `openConsole({ columns, rows, argv })`: a terminal the page
|
|
132
|
+
holds, with `argv`'s program started on it, for something other than the
|
|
133
|
+
page's own terminal to use, such as a socket to another machine. It resolves
|
|
134
|
+
to `{ output, write(bytes), resize(columns, rows), close(), exited }`:
|
|
135
|
+
`output` is a `ReadableStream` of what the programs show, which ends when the
|
|
136
|
+
last of them lets go of the terminal; `write` takes bytes or text as typed,
|
|
137
|
+
Ctrl+C included, and resolves to how many it took, fewer while the input is
|
|
138
|
+
full; `exited` is the program's status. The terminal is a pseudo-terminal's
|
|
139
|
+
([process model](process-model.md#pseudo-terminals)). With `pipes: true` in
|
|
140
|
+
place of the size, the program's standard streams are pipes: `write` is its
|
|
141
|
+
input byte for byte, `endInput()` ends it, `interrupt()` is its Ctrl+C (SIGINT
|
|
142
|
+
to the program, as a terminal's interrupt key), and `output` and `errors` are
|
|
143
|
+
its standard output and error apart.
|
|
144
|
+
|
|
145
|
+
```js
|
|
146
|
+
const shell = await dolly.openConsole({ columns: 100, rows: 30, argv: ["/bin/slop"] });
|
|
147
|
+
await shell.write("echo hello\r");
|
|
148
|
+
const sort = await dolly.openConsole({ pipes: true, argv: ["/bin/sort"] });
|
|
149
|
+
await sort.write("b\na\n");
|
|
150
|
+
await sort.endInput();
|
|
151
|
+
```
|
|
152
|
+
|
|
124
153
|
## Serving
|
|
125
154
|
|
|
126
155
|
- Serve the installed packages as they lie: the runtime finds its own files
|
|
@@ -133,76 +162,20 @@ properties each time a popup opens. Dolly's site sets
|
|
|
133
162
|
as `application/json`: a browser imports a host module's manifest and an image
|
|
134
163
|
directory's catalog and metadata only with that type.
|
|
135
164
|
- No bundler is needed: these are ES modules, Workers and Wasm files.
|
|
165
|
+
- A Content-Security-Policy that Dolly runs under, with no `'unsafe-inline'` or
|
|
166
|
+
`'unsafe-eval'`: `default-src 'self'; script-src 'self' 'wasm-unsafe-eval' blob:;
|
|
167
|
+
worker-src 'self' blob:; img-src 'self' blob:; object-src 'none'; base-uri 'none'`,
|
|
168
|
+
with `connect-src` naming the origins the HTTP policy allows (or their relay).
|
|
169
|
+
WebAssembly needs `'wasm-unsafe-eval'`; processes start in Workers from `blob:` URLs
|
|
170
|
+
of code fetched once, so a program starts without a request. Neither boot() nor a
|
|
171
|
+
host module writes a script or style element (the popup is a frame in which no
|
|
172
|
+
script runs), so the page's own script and style, as files, are all the policy
|
|
173
|
+
admits ([test](../test/csp-browser.mjs)).
|
|
136
174
|
|
|
137
175
|
## Your own image
|
|
138
176
|
|
|
139
|
-
`dolly-build` builds a
|
|
140
|
-
|
|
141
|
-
installed beside it, into a site: a directory that any static host serves as it
|
|
142
|
-
lies. The build runs in a headless browser, with the installed runtime's own
|
|
143
|
-
builder, as the catalog's images are built; the command serves the packages to
|
|
144
|
-
it on 127.0.0.1 and writes what it hands back. Nothing of it, nor of the site,
|
|
145
|
-
the page or the image, fetches from the network: after `npm install`, the
|
|
146
|
-
packages hold every file. The build's browser reaches that server and the URLs
|
|
147
|
-
of the recipe's own `SOURCE` rows alone; its own requests (its vendor's updates,
|
|
148
|
-
clock and autofill) go to a proxy of the command's that refuses them.
|
|
149
|
-
|
|
150
|
-
```sh
|
|
151
|
-
npm install @daugasauron/dolly-build @daugasauron/dolly-package-git
|
|
152
|
-
npx dolly-build init my-pi git
|
|
153
|
-
npx dolly-build Dollyfile-my-pi my-pi
|
|
154
|
-
```
|
|
155
|
-
|
|
156
|
-
- `dolly-build init NAME [PACKAGE…]` writes a project where the packages are
|
|
157
|
-
installed, and refuses to write over a file: `Dollyfile-NAME` (the host modules
|
|
158
|
-
of `pi-minimal` and of each package, `FROM` `pi-minimal` and `INSTALL` of each
|
|
159
|
-
package at the installed pins, rows for Pi's instructions, a skill, an extension,
|
|
160
|
-
a tool and the script that starts Pi, and `pi-minimal`'s `ENTRY`) and `public/`,
|
|
161
|
-
the page's files: `index.html` (the policy, the popups' font, and the files of
|
|
162
|
-
`workspace/` and `theme.json` for `boot()`'s `files`, listed by `workspace.json`),
|
|
163
|
-
`theme.json` (the sandbox's colours: Pi's theme, written over the image's at
|
|
164
|
-
boot, whose background, text, accent and muted the page sets as the terminal's
|
|
165
|
-
and the popups') and `workspace/README.md`; and, unless the project has one, a
|
|
166
|
-
`.gitignore` for `node_modules/` and the site. It names the host module
|
|
167
|
-
package to install when a package needs one the page lacks (`python`'s `sockets`).
|
|
168
|
-
The repository README's "Pi with npm" says what each file is for.
|
|
169
|
-
- The recipe is the one place that declares the sandbox. Add rows before `ENTRY`:
|
|
170
|
-
`FILE` with a body (indented four spaces) for a file, `INSTALL` of a package
|
|
171
|
-
whose directory is installed (every package it needs comes with it, so `python`
|
|
172
|
-
brings `cc`), `SLOP` to run the image's tools at build time. `FROM` carries the
|
|
173
|
-
base's files, environment and exports but not its host modules or `ENTRY`, so the
|
|
174
|
-
recipe repeats those; a package's `REQUIRES HOST` rows must be among the recipe's,
|
|
175
|
-
and the build names a missing one. A recipe is at most 128 KiB; `/workspace` is
|
|
176
|
-
never part of an image (`boot()`'s `files` writes the project at each boot).
|
|
177
|
-
- `dolly-build Dollyfile-NAME OUT` writes the site `OUT`, replacing the one it
|
|
178
|
-
wrote there before: the files of `public/`, `workspace.json` (the files under
|
|
179
|
-
`public/workspace/`), the runtime (`dolly/`), the device host modules the recipe
|
|
180
|
-
declares (`dolly-host-NAME/`), `coi-serviceworker.js` and `image/`, the image's
|
|
181
|
-
directory as an image package lays it out (its catalog, metadata and packs, the
|
|
182
|
-
recipes it was built from, its `amy-index.txt` and an `index.mjs`). The page
|
|
183
|
-
imports `./dolly/src/browser.mjs` and `./image/index.mjs`. An image this recipe
|
|
184
|
-
built on this runtime is kept, so a change to `public/` alone takes seconds.
|
|
185
|
-
`--browser chrome` (the default: your Chrome), `chromium` or `firefox`
|
|
186
|
-
(Playwright's, after `npx playwright-core install chromium` or `firefox`).
|
|
187
|
-
Both commands run where the packages are installed: the directory whose
|
|
188
|
-
`node_modules/@daugasauron/` holds them (npm, pnpm and Yarn 1 alike). A row
|
|
189
|
-
that names an image no installed package holds at that pin fails naming the row.
|
|
190
|
-
- Serve `OUT` with any static file server, `python3 -m http.server -d OUT` on
|
|
191
|
-
your machine. Where the host sends the isolation headers ("Serving" above) the
|
|
192
|
-
page is isolated; where it does not, `init`'s page registers
|
|
193
|
-
`coi-serviceworker.js`, which adds them to the site's own responses, and loads
|
|
194
|
-
again under it.
|
|
195
|
-
- A recipe may start `FROM` another installed image instead, `python-data` say: its
|
|
196
|
-
package's README gives the `FROM` row, and the recipe repeats the image's `REQUIRES HOST`
|
|
197
|
-
rows (a FILE of the project's own script and a SLOP that runs it at build time, for
|
|
198
|
-
example). `init` writes Pi's project only; the page in `public/index.html` is then one
|
|
199
|
-
as in "A page" above that imports `./dolly/src/browser.mjs` and `./image/index.mjs`,
|
|
200
|
-
with the lines of `init`'s page that register `coi-serviceworker.js` for a host
|
|
201
|
-
without the headers.
|
|
202
|
-
- An image is built for the installed versions: after the packages update, the
|
|
203
|
-
rows' pins are others (`init` in an empty directory writes the new ones), and it
|
|
204
|
-
is built again. Packages of two versions in one `node_modules` fail the build,
|
|
205
|
-
naming both.
|
|
177
|
+
`dolly-build` (`@daugasauron/dolly-build`) builds a recipe of your own from
|
|
178
|
+
installed packages into a static site: [Dolly from npm](npm.md).
|
|
206
179
|
|
|
207
180
|
## Host modules
|
|
208
181
|
|
package/coi-serviceworker.js
CHANGED
|
@@ -1,15 +1,30 @@
|
|
|
1
|
-
//
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
// The site's service worker, for its own same-origin GET and HEAD responses; it
|
|
2
|
+
// holds no policy and reaches nothing a page's fetch does not. Cross-origin
|
|
3
|
+
// requests, including the explicit HTTP broker's, pass through unchanged.
|
|
4
|
+
// - GitHub Pages cannot configure COOP/COEP response headers: the worker adds
|
|
5
|
+
// them where a response lacks them, so shared wasm64 memory is available there.
|
|
6
|
+
// - Where the network fails, a GET is answered from this site's kept runtime: the
|
|
7
|
+
// files a saved session opens with, which the page stores when a session is
|
|
8
|
+
// saved, each checked against the site's list (site/offline.mjs). A response the
|
|
9
|
+
// server gives, an error among them, is never replaced.
|
|
10
|
+
const kept = `dolly-offline ${self.registration.scope} `;
|
|
11
|
+
async function keptResponse(request, failure) {
|
|
12
|
+
for (const name of request.method === "GET" ? await caches.keys() : []) {
|
|
13
|
+
const response = name.startsWith(kept) && await (await caches.open(name)).match(request, { ignoreSearch: true });
|
|
14
|
+
if (response) return response;
|
|
15
|
+
}
|
|
16
|
+
throw failure;
|
|
17
|
+
}
|
|
18
|
+
// It controls the pages loaded after it and never takes over a running one
|
|
19
|
+
// (no clients.claim, no skipWaiting): a page whose Workers wait in Atomics.wait
|
|
20
|
+
// stalls its fetches in Firefox while its controller changes.
|
|
7
21
|
self.addEventListener("fetch", (event) => {
|
|
8
22
|
const target = new URL(event.request.url);
|
|
9
23
|
if (target.origin !== self.location.origin) return;
|
|
10
24
|
event.respondWith((async () => {
|
|
11
|
-
const response = await fetch(event.request);
|
|
12
|
-
if (response.type === "opaque" || response.type === "opaqueredirect"
|
|
25
|
+
const response = await fetch(event.request).catch(failure => keptResponse(event.request, failure));
|
|
26
|
+
if (response.type === "opaque" || response.type === "opaqueredirect" ||
|
|
27
|
+
response.headers.has("Cross-Origin-Embedder-Policy")) return response;
|
|
13
28
|
const headers = new Headers(response.headers);
|
|
14
29
|
// Fetch exposes a decoded body while origin transport headers can still
|
|
15
30
|
// describe its compressed representation. A reconstructed Response must
|
package/dist/dolly-build-id.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const DOLLY_BUILD_ID = "sha256:
|
|
1
|
+
export const DOLLY_BUILD_ID = "sha256:d8f91a7526e31cfd010f30ba48cea8912e4aa9cdd6b1497fd9a96d46ea2eee52";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export const DOLLY_IMAGE_BUILD_ID = "sha256:
|
|
1
|
+
export const DOLLY_IMAGE_BUILD_ID = "sha256:87c272432c019ccd35bc35fd5576682681a35c1abdcd36f18e456f608d23b758";
|
|
Binary file
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export const DOLLY_PROCESS_ABI_DIGEST = "
|
|
1
|
+
export const DOLLY_PROCESS_ABI_DIGEST = "a193b87b75700fc2617daafe583c8693499f2c408124e6d8473d518cdf32c67b";
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
// dist/dolly-process-abi.mjs
|
|
2
|
-
var DOLLY_PROCESS_ABI_DIGEST = "
|
|
2
|
+
var DOLLY_PROCESS_ABI_DIGEST = "a193b87b75700fc2617daafe583c8693499f2c408124e6d8473d518cdf32c67b";
|
|
3
|
+
|
|
4
|
+
// dist/dolly-kernel-plugin-abi.mjs
|
|
5
|
+
var DOLLY_KERNEL_PLUGIN_IMPORTS = Object.freeze(["fopen", "fseek", "fclose", "ftell", "malloc", "fread", "free", "dolly_assert_fail", "realloc", "strcmp", "strncmp", "strlen", "memcmp", "bcmp", "write", "__errno_location", "lseek", "preadv", "close", "fstat", "unlinkat", "openat", "realpath", "readv", "dolly_input_decoder_install"]);
|
|
3
6
|
|
|
4
7
|
// host/dso/abi.mjs
|
|
5
8
|
var DOLLY_DSO_OPEN = 112;
|
|
@@ -16,7 +19,7 @@ var DOLLY_FFI_CLOSURE_FREE = 122;
|
|
|
16
19
|
var DOLLY_FFI_CLOSURE_PREP = 123;
|
|
17
20
|
var DOLLY_ERRNO = Object.freeze({ E2BIG: 1, EACCES: 2, EADDRINUSE: 3, EADDRNOTAVAIL: 4, EAFNOSUPPORT: 5, EAGAIN: 6, EALREADY: 7, EBADF: 8, EBADMSG: 9, EBUSY: 10, ECANCELED: 11, ECHILD: 12, ECONNABORTED: 13, ECONNREFUSED: 14, ECONNRESET: 15, EDEADLK: 16, EDESTADDRREQ: 17, EDOM: 18, EDQUOT: 19, EEXIST: 20, EFAULT: 21, EFBIG: 22, EHOSTUNREACH: 23, EIDRM: 24, EILSEQ: 25, EINPROGRESS: 26, EINTR: 27, EINVAL: 28, EIO: 29, EISCONN: 30, EISDIR: 31, ELOOP: 32, EMFILE: 33, EMLINK: 34, EMSGSIZE: 35, EMULTIHOP: 36, ENAMETOOLONG: 37, ENETDOWN: 38, ENETRESET: 39, ENETUNREACH: 40, ENFILE: 41, ENOBUFS: 42, ENODEV: 43, ENOENT: 44, ENOEXEC: 45, ENOLCK: 46, ENOLINK: 47, ENOMEM: 48, ENOMSG: 49, ENOPROTOOPT: 50, ENOSPC: 51, ENOSYS: 52, ENOTCONN: 53, ENOTDIR: 54, ENOTEMPTY: 55, ENOTRECOVERABLE: 56, ENOTSOCK: 57, ENOTTY: 59, ENXIO: 60, EOVERFLOW: 61, EOWNERDEAD: 62, EPERM: 63, EPIPE: 64, EPROTO: 65, EPROTONOSUPPORT: 66, EPROTOTYPE: 67, ERANGE: 68, EROFS: 69, ESPIPE: 70, ESRCH: 71, ESTALE: 72, ETIMEDOUT: 73, ETXTBSY: 74, EXDEV: 75, ENODATA: 116, ENOTSUP: 138 });
|
|
18
21
|
|
|
19
|
-
//
|
|
22
|
+
// page/wasm-interface.mjs
|
|
20
23
|
var decoder = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true });
|
|
21
24
|
var valueTypes = /* @__PURE__ */ new Map([
|
|
22
25
|
[127, "i32"],
|
|
@@ -386,15 +389,20 @@ var DOLLY_HOST_NAME_BYTES = 32;
|
|
|
386
389
|
var DOLLY_HOST_DIGEST_BYTES = 32;
|
|
387
390
|
var DOLLY_HOST_MAX_RECORDS = 64;
|
|
388
391
|
|
|
389
|
-
//
|
|
392
|
+
// host/runtime/abi.mjs
|
|
393
|
+
var DOLLY_SNAPSHOT_MAX_MEBIBYTES = 2048;
|
|
394
|
+
var DOLLY_ERRNO2 = Object.freeze({ E2BIG: 1, EACCES: 2, EADDRINUSE: 3, EADDRNOTAVAIL: 4, EAFNOSUPPORT: 5, EAGAIN: 6, EALREADY: 7, EBADF: 8, EBADMSG: 9, EBUSY: 10, ECANCELED: 11, ECHILD: 12, ECONNABORTED: 13, ECONNREFUSED: 14, ECONNRESET: 15, EDEADLK: 16, EDESTADDRREQ: 17, EDOM: 18, EDQUOT: 19, EEXIST: 20, EFAULT: 21, EFBIG: 22, EHOSTUNREACH: 23, EIDRM: 24, EILSEQ: 25, EINPROGRESS: 26, EINTR: 27, EINVAL: 28, EIO: 29, EISCONN: 30, EISDIR: 31, ELOOP: 32, EMFILE: 33, EMLINK: 34, EMSGSIZE: 35, EMULTIHOP: 36, ENAMETOOLONG: 37, ENETDOWN: 38, ENETRESET: 39, ENETUNREACH: 40, ENFILE: 41, ENOBUFS: 42, ENODEV: 43, ENOENT: 44, ENOEXEC: 45, ENOLCK: 46, ENOLINK: 47, ENOMEM: 48, ENOMSG: 49, ENOPROTOOPT: 50, ENOSPC: 51, ENOSYS: 52, ENOTCONN: 53, ENOTDIR: 54, ENOTEMPTY: 55, ENOTRECOVERABLE: 56, ENOTSOCK: 57, ENOTTY: 59, ENXIO: 60, EOVERFLOW: 61, EOWNERDEAD: 62, EPERM: 63, EPIPE: 64, EPROTO: 65, EPROTONOSUPPORT: 66, EPROTOTYPE: 67, ERANGE: 68, EROFS: 69, ESPIPE: 70, ESRCH: 71, ESTALE: 72, ETIMEDOUT: 73, ETXTBSY: 74, EXDEV: 75, ENODATA: 116, ENOTSUP: 138 });
|
|
395
|
+
|
|
396
|
+
// page/snapshot-records.mjs
|
|
390
397
|
var decoder2 = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true });
|
|
391
|
-
var
|
|
398
|
+
var encoder = new TextEncoder();
|
|
399
|
+
var MAX_SNAPSHOT_BYTES = DOLLY_SNAPSHOT_MAX_MEBIBYTES * 1024 * 1024;
|
|
392
400
|
var MAX_SNAPSHOT_PACKS = MAX_SNAPSHOT_BYTES / (1024 * 1024);
|
|
393
401
|
|
|
394
|
-
//
|
|
395
|
-
var DOLLY_VERSION = "0.1.
|
|
402
|
+
// page/version.mjs
|
|
403
|
+
var DOLLY_VERSION = "0.1.6";
|
|
396
404
|
|
|
397
|
-
//
|
|
405
|
+
// page/static-asset.mjs
|
|
398
406
|
var STATIC_PART_BYTES = 20 * 1024 * 1024;
|
|
399
407
|
var hex = (bytes) => Array.from(bytes instanceof Uint8Array ? bytes : new Uint8Array(bytes), (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
400
408
|
var sitePrefix = `/v${DOLLY_VERSION}`;
|
|
@@ -1176,7 +1184,7 @@ function createProcessFfi({
|
|
|
1176
1184
|
});
|
|
1177
1185
|
}
|
|
1178
1186
|
|
|
1179
|
-
//
|
|
1187
|
+
// page/process-abi.mjs
|
|
1180
1188
|
function unique(entries, key) {
|
|
1181
1189
|
const result = /* @__PURE__ */ new Map();
|
|
1182
1190
|
for (const entry of entries) {
|
|
@@ -1406,7 +1414,7 @@ function createThreadRecords({ memory, address, allocate, apply }) {
|
|
|
1406
1414
|
// host/dso/process.mjs
|
|
1407
1415
|
var DSO_RESPONSE_SIZE = 16 + DOLLY_DSO_ERROR_CAPACITY;
|
|
1408
1416
|
var LOAD_FAILED = 2147483648;
|
|
1409
|
-
var
|
|
1417
|
+
var encoder2 = new TextEncoder();
|
|
1410
1418
|
var decoder3 = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true });
|
|
1411
1419
|
var configuration;
|
|
1412
1420
|
var instance;
|
|
@@ -1704,7 +1712,7 @@ function symbolIndex(handle, name, value) {
|
|
|
1704
1712
|
return threadRecords.change((publish) => {
|
|
1705
1713
|
const indexed = functionIndices.get(value.value);
|
|
1706
1714
|
if (indexed !== void 0) return indexed;
|
|
1707
|
-
const bytes =
|
|
1715
|
+
const bytes = encoder2.encode(name);
|
|
1708
1716
|
const copy = keep(bytes);
|
|
1709
1717
|
const index = functionIndex(value.value);
|
|
1710
1718
|
publish({ kind: DOLLY_DSO_SYMBOL, values: [handle, copy, BigInt(bytes.length), index, 0n] }, true);
|
|
@@ -1756,7 +1764,7 @@ function futexWait(request) {
|
|
|
1756
1764
|
}
|
|
1757
1765
|
function writeDsoResponse(response, value = 0n, error = 0, message = "") {
|
|
1758
1766
|
if (response.size < DSO_RESPONSE_SIZE) return -BigInt(DOLLY_ERRNO.ENOBUFS);
|
|
1759
|
-
const bytes =
|
|
1767
|
+
const bytes = encoder2.encode(message);
|
|
1760
1768
|
const messageSize = Math.min(bytes.length, DOLLY_DSO_ERROR_CAPACITY);
|
|
1761
1769
|
const output = new Uint8Array(
|
|
1762
1770
|
configuration.memory.buffer,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
//
|
|
1
|
+
// page/process-constants.mjs
|
|
2
2
|
var DOLLY_PROCESS_PACKET_LIMIT = 1048576;
|
|
3
3
|
var DOLLY_PROCESS_EXIT = 5;
|
|
4
4
|
var DOLLY_PROCESS_CLOCK_TIME = 48;
|
|
@@ -85,51 +85,105 @@ var DOLLY_ERRNO = Object.freeze({
|
|
|
85
85
|
});
|
|
86
86
|
var DOLLY_PROCESS_SIZEOF = Object.freeze({
|
|
87
87
|
dolly_process_vector_sizes: 16,
|
|
88
|
+
dolly_process_exit_request: 8,
|
|
88
89
|
dolly_process_fd_io_request: 16,
|
|
89
90
|
dolly_process_fd_pread_request: 24,
|
|
90
91
|
dolly_process_fd_truncate_request: 16,
|
|
91
92
|
dolly_process_fd_request: 8,
|
|
92
93
|
dolly_process_timestamp: 16,
|
|
93
94
|
dolly_process_fd_times_request: 40,
|
|
95
|
+
dolly_process_io_result: 8,
|
|
94
96
|
dolly_process_fd_dup_request: 16,
|
|
97
|
+
dolly_process_fd_dup_response: 8,
|
|
95
98
|
dolly_process_fd_flags: 8,
|
|
96
99
|
dolly_process_fd_lock_request: 32,
|
|
97
100
|
dolly_process_fd_lock_response: 24,
|
|
101
|
+
dolly_process_pipe_request: 8,
|
|
102
|
+
dolly_process_pipe_response: 8,
|
|
98
103
|
dolly_process_poll_request: 16,
|
|
99
104
|
dolly_process_poll_query: 8,
|
|
100
105
|
dolly_process_poll_response: 16,
|
|
101
106
|
dolly_process_poll_result: 8,
|
|
102
|
-
dolly_process_directory_entry: 24,
|
|
103
107
|
dolly_process_directory_request: 24,
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
+
dolly_process_directory_entry: 24,
|
|
109
|
+
dolly_process_fd_seek_request: 16,
|
|
110
|
+
dolly_process_fd_seek_response: 8,
|
|
111
|
+
dolly_process_clock_request: 16,
|
|
112
|
+
dolly_process_clock_response: 8,
|
|
113
|
+
dolly_process_clock_sleep_request: 16,
|
|
108
114
|
dolly_process_exec_state: 16,
|
|
115
|
+
dolly_process_fd_mapping: 8,
|
|
116
|
+
dolly_process_spawn_request: 72,
|
|
117
|
+
dolly_process_spawn_response: 8,
|
|
109
118
|
dolly_process_exec_request: 48,
|
|
110
|
-
dolly_process_pipe_request: 8,
|
|
111
|
-
dolly_process_two_path_request: 16,
|
|
112
|
-
dolly_process_path_times_request: 48,
|
|
113
|
-
dolly_process_terminal_request: 24,
|
|
114
|
-
dolly_process_terminal_response: 16,
|
|
115
|
-
dolly_process_clock_sleep_request: 16,
|
|
116
|
-
dolly_process_exit_request: 8,
|
|
117
119
|
dolly_process_wait_request: 8,
|
|
118
120
|
dolly_process_wait_response: 16,
|
|
121
|
+
dolly_process_info_response: 8,
|
|
119
122
|
dolly_process_signal_request: 8,
|
|
120
|
-
dolly_process_alarm: 16,
|
|
121
123
|
dolly_process_signal_dispositions: 8,
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
124
|
+
dolly_process_alarm: 16,
|
|
125
|
+
dolly_process_terminal_request: 24,
|
|
126
|
+
dolly_process_terminal_response: 16,
|
|
127
|
+
dolly_process_path_request: 16,
|
|
128
|
+
dolly_process_path_times_request: 48,
|
|
129
|
+
dolly_process_path_open_response: 8,
|
|
130
|
+
dolly_process_stat_response: 88,
|
|
131
|
+
dolly_process_filesystem_stat_response: 96,
|
|
132
|
+
dolly_process_two_path_request: 16
|
|
133
|
+
});
|
|
134
|
+
var DOLLY_PROCESS_OFFSETOF = Object.freeze({
|
|
135
|
+
dolly_process_vector_sizes: Object.freeze({ "count": 0, "reserved": 4, "bytes": 8 }),
|
|
136
|
+
dolly_process_exit_request: Object.freeze({ "status": 0, "signal_number": 4 }),
|
|
137
|
+
dolly_process_fd_io_request: Object.freeze({ "descriptor": 0, "reserved": 4, "size": 8 }),
|
|
138
|
+
dolly_process_fd_pread_request: Object.freeze({ "descriptor": 0, "reserved": 4, "offset": 8, "size": 16 }),
|
|
139
|
+
dolly_process_fd_truncate_request: Object.freeze({ "descriptor": 0, "reserved": 4, "size": 8 }),
|
|
140
|
+
dolly_process_fd_request: Object.freeze({ "descriptor": 0, "reserved": 4 }),
|
|
141
|
+
dolly_process_timestamp: Object.freeze({ "seconds": 0, "nanoseconds": 8, "flags": 12 }),
|
|
142
|
+
dolly_process_fd_times_request: Object.freeze({ "descriptor": 0, "reserved": 4, "access": 8, "modification": 24 }),
|
|
143
|
+
dolly_process_io_result: Object.freeze({ "size": 0 }),
|
|
144
|
+
dolly_process_fd_dup_request: Object.freeze({ "source_descriptor": 0, "target_descriptor": 4, "flags": 8, "reserved": 12 }),
|
|
145
|
+
dolly_process_fd_dup_response: Object.freeze({ "descriptor": 0, "reserved": 4 }),
|
|
146
|
+
dolly_process_fd_flags: Object.freeze({ "descriptor": 0, "flags": 4 }),
|
|
147
|
+
dolly_process_fd_lock_request: Object.freeze({ "descriptor": 0, "flags": 4, "type": 8, "whence": 12, "start": 16, "length": 24 }),
|
|
148
|
+
dolly_process_fd_lock_response: Object.freeze({ "type": 0, "pid": 4, "start": 8, "length": 16 }),
|
|
149
|
+
dolly_process_pipe_request: Object.freeze({ "flags": 0, "reserved": 4 }),
|
|
150
|
+
dolly_process_pipe_response: Object.freeze({ "read_descriptor": 0, "write_descriptor": 4 }),
|
|
151
|
+
dolly_process_poll_request: Object.freeze({ "deadline_nanoseconds": 0, "count": 8, "reserved": 12 }),
|
|
152
|
+
dolly_process_poll_query: Object.freeze({ "descriptor": 0, "events": 4, "reserved": 6 }),
|
|
153
|
+
dolly_process_poll_response: Object.freeze({ "ready": 0, "count": 4, "reserved": 8 }),
|
|
154
|
+
dolly_process_poll_result: Object.freeze({ "events": 0, "reserved": 2, "reserved2": 4 }),
|
|
155
|
+
dolly_process_directory_request: Object.freeze({ "descriptor": 0, "maximum_entries": 4, "cookie": 8, "reserved": 16 }),
|
|
156
|
+
dolly_process_directory_entry: Object.freeze({ "inode": 0, "next_cookie": 8, "file_type": 16, "name_size": 20 }),
|
|
157
|
+
dolly_process_fd_seek_request: Object.freeze({ "descriptor": 0, "whence": 4, "offset": 8 }),
|
|
158
|
+
dolly_process_fd_seek_response: Object.freeze({ "offset": 0 }),
|
|
159
|
+
dolly_process_clock_request: Object.freeze({ "clock_id": 0, "reserved": 4, "precision_nanoseconds": 8 }),
|
|
160
|
+
dolly_process_clock_response: Object.freeze({ "nanoseconds": 0 }),
|
|
161
|
+
dolly_process_clock_sleep_request: Object.freeze({ "clock_id": 0, "flags": 4, "deadline_nanoseconds": 8 }),
|
|
162
|
+
dolly_process_exec_state: Object.freeze({ "blocked_signals": 0, "ignored_signals": 4, "pending_signals": 8, "reserved": 12 }),
|
|
163
|
+
dolly_process_fd_mapping: Object.freeze({ "source_descriptor": 0, "target_descriptor": 4 }),
|
|
164
|
+
dolly_process_spawn_request: Object.freeze({ "flags": 0, "argument_count": 4, "environment_count": 8, "cwd_size": 12, "mapping_count": 16, "descriptor_inheritance": 20, "reserved": 24, "path_size": 28, "argument_bytes": 32, "environment_bytes": 40, "deadline_nanoseconds": 48, "signals": 56 }),
|
|
165
|
+
dolly_process_spawn_response: Object.freeze({ "pid": 0, "reserved": 4 }),
|
|
166
|
+
dolly_process_exec_request: Object.freeze({ "signals": 0, "argument_count": 16, "environment_count": 20, "path_size": 24, "reserved": 28, "argument_bytes": 32, "environment_bytes": 40 }),
|
|
167
|
+
dolly_process_wait_request: Object.freeze({ "pid": 0, "flags": 4 }),
|
|
168
|
+
dolly_process_wait_response: Object.freeze({ "pid": 0, "status": 4, "signal_number": 8, "reserved": 12 }),
|
|
169
|
+
dolly_process_info_response: Object.freeze({ "pid": 0, "parent_pid": 4 }),
|
|
170
|
+
dolly_process_signal_request: Object.freeze({ "pid": 0, "signal_number": 4 }),
|
|
171
|
+
dolly_process_signal_dispositions: Object.freeze({ "ignored_signals": 0, "handled_signals": 4 }),
|
|
172
|
+
dolly_process_alarm: Object.freeze({ "value_nanoseconds": 0, "interval_nanoseconds": 8 }),
|
|
173
|
+
dolly_process_terminal_request: Object.freeze({ "operation": 0, "descriptor": 4, "flags": 8, "reserved": 12, "deadline_nanoseconds": 16 }),
|
|
174
|
+
dolly_process_terminal_response: Object.freeze({ "value": 0, "columns": 8, "rows": 12 }),
|
|
175
|
+
dolly_process_path_request: Object.freeze({ "directory_descriptor": 0, "flags": 4, "reserved": 8, "path_size": 12 }),
|
|
176
|
+
dolly_process_path_times_request: Object.freeze({ "directory_descriptor": 0, "flags": 4, "reserved": 8, "path_size": 12, "access": 16, "modification": 32 }),
|
|
177
|
+
dolly_process_path_open_response: Object.freeze({ "descriptor": 0, "reserved": 4 }),
|
|
178
|
+
dolly_process_stat_response: Object.freeze({ "device": 0, "inode": 8, "size": 16, "access_nanoseconds": 24, "modification_nanoseconds": 32, "change_nanoseconds": 40, "blocks": 48, "mode": 56, "link_count": 60, "user": 64, "group": 68, "block_size": 72, "file_type": 76, "reserved": 80 }),
|
|
179
|
+
dolly_process_filesystem_stat_response: Object.freeze({ "type": 0, "block_size": 8, "blocks": 16, "blocks_free": 24, "blocks_available": 32, "files": 40, "files_free": 48, "maximum_name_length": 56, "fragment_size": 64, "flags": 72, "filesystem_id": 80, "reserved": 88 }),
|
|
180
|
+
dolly_process_two_path_request: Object.freeze({ "old_directory_descriptor": 0, "new_directory_descriptor": 4, "old_path_size": 8, "new_path_size": 12 })
|
|
125
181
|
});
|
|
126
182
|
|
|
127
|
-
//
|
|
128
|
-
var
|
|
129
|
-
var
|
|
130
|
-
var
|
|
131
|
-
|
|
132
|
-
// src/process-worker.mjs
|
|
183
|
+
// page/process-worker.mjs
|
|
184
|
+
var clockField = DOLLY_PROCESS_OFFSETOF.dolly_process_clock_request;
|
|
185
|
+
var clockRequestSize = DOLLY_PROCESS_SIZEOF.dolly_process_clock_request;
|
|
186
|
+
var clockResponseSize = DOLLY_PROCESS_SIZEOF.dolly_process_clock_response;
|
|
133
187
|
var PROCESS_EXIT = Symbol("Dolly process exit");
|
|
134
188
|
var THREAD_EXIT = Symbol("Dolly thread exit");
|
|
135
189
|
var UNSTARTED = Symbol("Dolly thread ended before it started");
|
|
@@ -148,7 +202,8 @@ var configuration = await new Promise((resolve, reject) => {
|
|
|
148
202
|
resolve(event.data);
|
|
149
203
|
});
|
|
150
204
|
});
|
|
151
|
-
|
|
205
|
+
var threadOperations = configuration.threaded ? configuration.threadOperations : {};
|
|
206
|
+
if (!(configuration.module instanceof WebAssembly.Module || configuration.module instanceof MessagePort) || !(configuration.gateModule instanceof WebAssembly.Module) || !(configuration.kernelMemory instanceof WebAssembly.Memory) || !(configuration.control instanceof SharedArrayBuffer) || !Array.isArray(configuration.local) || configuration.control.byteLength !== 32 || !Number.isFinite(configuration.clockOrigin) || !Number.isSafeInteger(configuration.mailbox) || configuration.mailbox <= 0 || typeof configuration.memory?.initial !== "bigint" || typeof configuration.memory?.maximum !== "bigint" || configuration.port !== void 0 && !(configuration.port instanceof MessagePort) || !Number.isInteger(configuration.pid) || configuration.pid <= 0 || configuration.threaded && !(Number.isInteger(configuration.threadOperations?.spawn) && Number.isInteger(configuration.threadOperations?.exit))) {
|
|
152
207
|
throw new Error("Dolly process received an invalid configuration");
|
|
153
208
|
}
|
|
154
209
|
var control = new Int32Array(configuration.control);
|
|
@@ -245,8 +300,8 @@ function clockResponse(clock, response, now) {
|
|
|
245
300
|
const nanoseconds = Math.round(
|
|
246
301
|
(clock === DOLLY_PROCESS_CLOCK_REALTIME ? Date.now() : now + clockOffset) * 1e6
|
|
247
302
|
);
|
|
248
|
-
new DataView(memory.buffer, response.address,
|
|
249
|
-
return
|
|
303
|
+
new DataView(memory.buffer, response.address, clockResponseSize).setBigUint64(DOLLY_PROCESS_OFFSETOF.dolly_process_clock_response.nanoseconds, BigInt(nanoseconds), true);
|
|
304
|
+
return BigInt(clockResponseSize);
|
|
250
305
|
}
|
|
251
306
|
function copyRequest(request) {
|
|
252
307
|
if (Atomics.compareExchange(control, 4, 0, 1) !== 0) return false;
|
|
@@ -276,12 +331,12 @@ function call(operation, requestAddressValue, requestSizeValue, responseAddressV
|
|
|
276
331
|
for (const module of localModules) {
|
|
277
332
|
if (module.handles(operation)) return module.call(operation, request, response);
|
|
278
333
|
}
|
|
279
|
-
const exitingResult = operation ===
|
|
334
|
+
const exitingResult = operation === threadOperations.exit && request.size === 8 ? new DataView(memory.buffer, request.address, 8).getBigUint64(0, true) : void 0;
|
|
280
335
|
let clock;
|
|
281
|
-
if (operation === DOLLY_PROCESS_CLOCK_TIME && request.size ===
|
|
282
|
-
const packet = new DataView(memory.buffer, request.address,
|
|
283
|
-
const id = packet.getUint32(
|
|
284
|
-
if ((id === DOLLY_PROCESS_CLOCK_REALTIME || id === DOLLY_PROCESS_CLOCK_MONOTONIC) && packet.getUint32(
|
|
336
|
+
if (operation === DOLLY_PROCESS_CLOCK_TIME && request.size === clockRequestSize && response.size >= clockResponseSize && response.size <= DOLLY_PROCESS_PACKET_LIMIT) {
|
|
337
|
+
const packet = new DataView(memory.buffer, request.address, clockRequestSize);
|
|
338
|
+
const id = packet.getUint32(clockField.clock_id, true);
|
|
339
|
+
if ((id === DOLLY_PROCESS_CLOCK_REALTIME || id === DOLLY_PROCESS_CLOCK_MONOTONIC) && packet.getUint32(clockField.reserved, true) === 0) clock = id;
|
|
285
340
|
const now = performance.now();
|
|
286
341
|
if (clock !== void 0 && now - lastSignalCheck < 1) return clockResponse(clock, response, now);
|
|
287
342
|
}
|
|
@@ -295,7 +350,7 @@ function call(operation, requestAddressValue, requestSizeValue, responseAddressV
|
|
|
295
350
|
const memoryBytes = memory.buffer.byteLength;
|
|
296
351
|
let channel;
|
|
297
352
|
if (openChannels.length) closeReceivedChannels();
|
|
298
|
-
if (operation ===
|
|
353
|
+
if (operation === threadOperations.spawn && configuration.threaded) {
|
|
299
354
|
if (!reserveMaximum()) return -BigInt(DOLLY_ERRNO.EAGAIN);
|
|
300
355
|
channel = new MessageChannel();
|
|
301
356
|
}
|
|
@@ -334,7 +389,7 @@ function call(operation, requestAddressValue, requestSizeValue, responseAddressV
|
|
|
334
389
|
if (result === deferredResult) return ended(PROCESS_EXIT);
|
|
335
390
|
if (result > 0n) gate.exports.response(mailbox, BigInt(response.address), result);
|
|
336
391
|
lastSignalCheck = result === -BigInt(DOLLY_ERRNO.EINTR) ? -Infinity : performance.now();
|
|
337
|
-
if (operation ===
|
|
392
|
+
if (operation === threadOperations.exit && result >= 0n) {
|
|
338
393
|
threadResult = exitingResult;
|
|
339
394
|
for (const module of localModules) module.leaving?.();
|
|
340
395
|
return ended(THREAD_EXIT);
|