@volter/browser-substrate 0.1.103 → 0.1.105
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/catalog/demand-input.json +133 -0
- package/dist/boot-screen.d.ts +2 -0
- package/dist/boot-screen.d.ts.map +1 -1
- package/dist/boot-screen.js +1 -1
- package/dist/boot-screen.js.map +1 -1
- package/dist/cli/archive.d.ts +1 -0
- package/dist/cli/archive.d.ts.map +1 -1
- package/dist/cli/archive.js +4 -4
- package/dist/cli/archive.js.map +1 -1
- package/dist/cli/build.d.ts +5 -1
- package/dist/cli/build.d.ts.map +1 -1
- package/dist/cli/build.js +21 -2
- package/dist/cli/build.js.map +1 -1
- package/dist/cli/cache-root.d.ts +7 -0
- package/dist/cli/cache-root.d.ts.map +1 -0
- package/dist/cli/cache-root.js +24 -0
- package/dist/cli/cache-root.js.map +1 -0
- package/dist/cli/companions.d.ts +1 -1
- package/dist/cli/companions.d.ts.map +1 -1
- package/dist/cli/companions.js +30 -16
- package/dist/cli/companions.js.map +1 -1
- package/dist/cli/dependency-plan-build.d.ts +4 -0
- package/dist/cli/dependency-plan-build.d.ts.map +1 -1
- package/dist/cli/dependency-plan-build.js +111 -30
- package/dist/cli/dependency-plan-build.js.map +1 -1
- package/dist/cli/docker-build.d.ts +1 -0
- package/dist/cli/docker-build.d.ts.map +1 -1
- package/dist/cli/docker-build.js +4 -4
- package/dist/cli/docker-build.js.map +1 -1
- package/dist/cli/dry-run.d.ts +4 -4
- package/dist/cli/dry-run.d.ts.map +1 -1
- package/dist/cli/dry-run.js +10 -9
- package/dist/cli/dry-run.js.map +1 -1
- package/dist/cli/generated-code.d.ts +2 -1
- package/dist/cli/generated-code.d.ts.map +1 -1
- package/dist/cli/generated-code.js +46 -16
- package/dist/cli/generated-code.js.map +1 -1
- package/dist/cli/host-build.d.ts +1 -0
- package/dist/cli/host-build.d.ts.map +1 -1
- package/dist/cli/host-build.js +10 -9
- package/dist/cli/host-build.js.map +1 -1
- package/dist/cli/host-managers.d.ts +3 -1
- package/dist/cli/host-managers.d.ts.map +1 -1
- package/dist/cli/host-managers.js +7 -3
- package/dist/cli/host-managers.js.map +1 -1
- package/dist/cli/image-layers.d.ts.map +1 -1
- package/dist/cli/image-layers.js +5 -2
- package/dist/cli/image-layers.js.map +1 -1
- package/dist/cli/main.d.ts +5 -1
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/main.js +97 -34
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/pack-publication.d.ts +2 -2
- package/dist/cli/pack-publication.d.ts.map +1 -1
- package/dist/cli/pack-publication.js +3 -3
- package/dist/cli/pack-publication.js.map +1 -1
- package/dist/cli/package-pack.d.ts +1 -1
- package/dist/cli/package-pack.d.ts.map +1 -1
- package/dist/cli/package-pack.js +7 -4
- package/dist/cli/package-pack.js.map +1 -1
- package/dist/cli/package-packs.d.ts +1 -0
- package/dist/cli/package-packs.d.ts.map +1 -1
- package/dist/cli/package-packs.js +84 -14
- package/dist/cli/package-packs.js.map +1 -1
- package/dist/cli/plan-tarballs.d.ts +1 -0
- package/dist/cli/plan-tarballs.d.ts.map +1 -1
- package/dist/cli/plan-tarballs.js +6 -3
- package/dist/cli/plan-tarballs.js.map +1 -1
- package/dist/cli/preparation-memory.d.ts +17 -0
- package/dist/cli/preparation-memory.d.ts.map +1 -0
- package/dist/cli/preparation-memory.js +367 -0
- package/dist/cli/preparation-memory.js.map +1 -0
- package/dist/cli/project-build.d.ts +1 -0
- package/dist/cli/project-build.d.ts.map +1 -1
- package/dist/cli/project-build.js +100 -71
- package/dist/cli/project-build.js.map +1 -1
- package/dist/cli/provision-catalog.d.ts +49 -0
- package/dist/cli/provision-catalog.d.ts.map +1 -0
- package/dist/cli/provision-catalog.js +72 -0
- package/dist/cli/provision-catalog.js.map +1 -0
- package/dist/cli/provision-demand.d.ts +45 -0
- package/dist/cli/provision-demand.d.ts.map +1 -0
- package/dist/cli/provision-demand.js +208 -0
- package/dist/cli/provision-demand.js.map +1 -0
- package/dist/cli/rolldown-binding.d.ts +1 -1
- package/dist/cli/rolldown-binding.d.ts.map +1 -1
- package/dist/cli/rolldown-binding.js +8 -4
- package/dist/cli/rolldown-binding.js.map +1 -1
- package/dist/cli/serve.d.ts +3 -0
- package/dist/cli/serve.d.ts.map +1 -1
- package/dist/cli/serve.js +9 -2
- package/dist/cli/serve.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +75 -31
- package/dist/index.js.map +1 -1
- package/dist/origin-reset.d.ts +4 -0
- package/dist/origin-reset.d.ts.map +1 -0
- package/dist/origin-reset.js +76 -0
- package/dist/origin-reset.js.map +1 -0
- package/dist/program-dom.d.ts +2 -0
- package/dist/program-dom.d.ts.map +1 -1
- package/dist/program-dom.js +11 -1
- package/dist/program-dom.js.map +1 -1
- package/dist/program-types.d.ts +2 -0
- package/dist/program-types.d.ts.map +1 -1
- package/dist/shell/assets/browser-opfs-filesystem-worker-CmF6UKMW.js +3 -0
- package/dist/shell/assets/browser-sandbox-bridge-C8nlSsT2.js +237 -0
- package/dist/shell/assets/{filesystem-host-DJbFuokb.js → filesystem-host-BzPlXSri.js} +1 -1
- package/dist/shell/assets/filesystem-host-Pq9IHKRx.js +3 -0
- package/dist/shell/assets/filesystem-worker-CC3pSXUP.js +5 -0
- package/dist/shell/assets/{fork-worker-BXY2kfdX.js → fork-worker-4YKQ4KTo.js} +1 -1
- package/dist/shell/assets/{node-execution-worker-7e8e0c5321ca0d10.js → node-execution-worker-3ddf5efbaa427e9d.js} +8 -8
- package/dist/shell/assets/{sandbox-bMeKqKBn.js → sandbox-mhFzIWaQ.js} +1 -1
- package/dist/shell/assets/{shell-DLIQ6jHu.js → shell-BZbhxnju.js} +763 -757
- package/dist/shell/assets/worker-BmHEnCyv.js +816 -0
- package/dist/shell/assets/{worker-program-worker-B4OcKVtV.js → worker-program-worker-DueMwljE.js} +10 -10
- package/dist/shell/brand/fonts/Geist-Variable.woff2 +0 -0
- package/dist/shell/brand/fonts/GeistMono-Variable.woff2 +0 -0
- package/dist/shell/brand/fonts/InstrumentSerif-Italic.woff2 +0 -0
- package/dist/shell/brand/fonts/InstrumentSerif-Regular.woff2 +0 -0
- package/dist/shell/brand/icons/app-window.svg +1 -0
- package/dist/shell/brand/icons/at-sign.svg +1 -0
- package/dist/shell/brand/icons/box.svg +1 -0
- package/dist/shell/brand/icons/chevron-right.svg +1 -0
- package/dist/shell/brand/icons/folder.svg +1 -0
- package/dist/shell/brand/icons/info.svg +1 -0
- package/dist/shell/brand/icons/key-round.svg +1 -0
- package/dist/shell/brand/icons/link.svg +1 -0
- package/dist/shell/brand/icons/monitor.svg +1 -0
- package/dist/shell/brand/icons/plus.svg +1 -0
- package/dist/shell/brand/icons/rotate-ccw.svg +1 -0
- package/dist/shell/brand/icons/share-2.svg +1 -0
- package/dist/shell/brand/icons/square-arrow-out-up-right.svg +1 -0
- package/dist/shell/brand/icons/terminal.svg +1 -0
- package/dist/shell/brand/icons/x.svg +1 -0
- package/dist/shell/brand/substrate.svg +1 -0
- package/dist/shell/brand/tokens.css +211 -0
- package/dist/shell/brand/wordmark.svg +1 -0
- package/dist/shell/index.html +5 -3
- package/dist/shell/node-execution-worker.js +16 -13
- package/dist/shell/node-host.html +2 -0
- package/dist/shell/python-execution-worker.js +15 -12
- package/dist/shell/python-host.html +2 -0
- package/dist/shell/python-runtime-snapshot.bin +0 -0
- package/dist/shell/python-runtime-snapshot.json +1 -1
- package/dist/shell/sandbox.html +4 -2
- package/dist/toolbar-styles.generated.d.ts +1 -1
- package/dist/toolbar-styles.generated.d.ts.map +1 -1
- package/dist/toolbar-styles.generated.js +1 -1
- package/dist/toolbar-styles.generated.js.map +1 -1
- package/dist/toolbar.d.ts.map +1 -1
- package/dist/toolbar.js +3 -1
- package/dist/toolbar.js.map +1 -1
- package/package.json +1 -1
- package/dist/shell/assets/browser-opfs-filesystem-worker-k2CPzPBU.js +0 -3
- package/dist/shell/assets/browser-sandbox-bridge-BJbQoc4f.js +0 -237
- package/dist/shell/assets/filesystem-host-yMcJuvmT.js +0 -3
- package/dist/shell/assets/filesystem-worker-BbsBhZ9p.js +0 -5
- package/dist/shell/assets/worker-Ce8bBwSJ.js +0 -816
package/dist/index.js
CHANGED
|
@@ -10,6 +10,7 @@ import { validateImageCacheEntries } from "./image-packs.js";
|
|
|
10
10
|
import { PROGRAM_ARCHIVE_RECEIPT, imageProgramLayerRoot, programArchiveReceipt } from "@volter/browser-runtime/browser-image-layers.js";
|
|
11
11
|
import { attachLocalPreviewSockets, injectLoopbackIntoPreviews } from "./local-preview.js";
|
|
12
12
|
import { exposeBrowserCookieJar, openPersistentBrowserCookieJar } from "@volter/browser-runtime/browser-cookie-jar.js";
|
|
13
|
+
import { holdOriginForProject } from "./origin-reset.js";
|
|
13
14
|
import { attachTabnodeCookieJar } from "@volter/browser-node/tabnode-cookie-jar.js";
|
|
14
15
|
import { browserProjectId, buildContainerFile, classifyContainerFile, clearVirtualFileSystem, containerLaneTableForRuntime, parseContainerFile, probeBrowserCapabilities, loadProgramHttpTransportPolicies, rebaseCommandPaths, resolveRelayService, stagePath, syncContainerBuild, BrowserSandboxBridge, HostFetchServiceRegistry, browserRegisteredServer, HOST_FETCH_DEFAULT_MAX_REQUEST_BYTES, } from "@volter/browser-runtime";
|
|
15
16
|
import { createIsolatedBrowserNodeRuntime, createWorkerBrowserNodeRuntime, registerPackageManagerAliases, withTabnodeHttpStreaming, prepareBrowserNodeProgram, VIRTUAL_HOST_PARAMETER, warmPreparedImage, } from "@volter/browser-node";
|
|
@@ -144,16 +145,36 @@ function rejectedReady(reason) {
|
|
|
144
145
|
ready.catch(() => undefined);
|
|
145
146
|
return ready;
|
|
146
147
|
}
|
|
148
|
+
async function fetchImageManifest(name, url) {
|
|
149
|
+
const response = await nativeFetch(url, { cache: "no-store" });
|
|
150
|
+
const type = response.headers.get("content-type")?.split(";")[0]?.trim().toLowerCase() ?? "";
|
|
151
|
+
if (!response.ok || !/^(?:application|text)\/(?:[\w.+-]+\+)?json$/u.test(type)) {
|
|
152
|
+
throw new Error(`image ${name} not found at ${url} (HTTP ${response.status}, ${type || "no content type"}). Build one with browser-substrate build.`);
|
|
153
|
+
}
|
|
154
|
+
let source;
|
|
155
|
+
try {
|
|
156
|
+
source = await response.json();
|
|
157
|
+
}
|
|
158
|
+
catch (cause) {
|
|
159
|
+
throw new Error(`image ${name} at ${url} is invalid JSON`, { cause });
|
|
160
|
+
}
|
|
161
|
+
return validateImageManifest(source);
|
|
162
|
+
}
|
|
147
163
|
export async function openProject(nameOrOptions = {}) {
|
|
148
164
|
// An open that fails after starting the engine's worker leaves nothing
|
|
149
165
|
// running: what it started is disposed before the failure is reported.
|
|
150
166
|
const started = [];
|
|
167
|
+
const releaseOrigin = await holdOriginForProject();
|
|
151
168
|
try {
|
|
152
|
-
|
|
169
|
+
const project = await openProjectTracking(nameOrOptions, (node) => { started.push(node); });
|
|
170
|
+
const dispose = project.dispose.bind(project);
|
|
171
|
+
project.dispose = async () => { await dispose(); await releaseOrigin(); };
|
|
172
|
+
return project;
|
|
153
173
|
}
|
|
154
174
|
catch (cause) {
|
|
155
|
-
|
|
156
|
-
|
|
175
|
+
const cleanup = await Promise.allSettled(started.map((node) => node.runtime.dispose()));
|
|
176
|
+
if (cleanup.every((result) => result.status === "fulfilled"))
|
|
177
|
+
await releaseOrigin();
|
|
157
178
|
throw cause;
|
|
158
179
|
}
|
|
159
180
|
}
|
|
@@ -167,10 +188,7 @@ async function openProjectTracking(nameOrOptions, track) {
|
|
|
167
188
|
throw new Error(`Browser runtime unsupported: ${capabilities.missing.join(", ")}`);
|
|
168
189
|
const name = options.name ?? "app";
|
|
169
190
|
const manifestUrl = options.manifestUrl ?? imageManifestPath(name);
|
|
170
|
-
const
|
|
171
|
-
if (!response.ok)
|
|
172
|
-
throw new Error(`No image named ${name}: ${manifestUrl} answered ${response.status}. Build one with browser-substrate build.`);
|
|
173
|
-
const read = validateImageManifest(await response.json());
|
|
191
|
+
const read = await fetchImageManifest(name, manifestUrl);
|
|
174
192
|
// A caller's command in place of the image's own: the project, its packages
|
|
175
193
|
// and its programs as the image places them, and this run in them.
|
|
176
194
|
const manifest = options.command === undefined || read.setup.kind === "dockerfile" ? read : { ...read, setup: { ...read.setup, dev: options.command } };
|
|
@@ -199,8 +217,9 @@ async function openProjectTracking(nameOrOptions, track) {
|
|
|
199
217
|
};
|
|
200
218
|
// Begun before anything else: nothing waits for it, and whatever asks for
|
|
201
219
|
// an entry first finds it kept, or fetches it as it would have.
|
|
202
|
-
|
|
203
|
-
|
|
220
|
+
const restoringCaches = manifest.caches && !isDryRun()
|
|
221
|
+
? restoreImageCaches(manifest.caches.url, browserProjectId(manifest.project ?? `substrate-${options.name ?? "app"}`), nativeFetch).catch((cause) => console.warn(`[caches] ${cause instanceof Error ? cause.message : String(cause)}`))
|
|
222
|
+
: Promise.resolve();
|
|
204
223
|
const output = options.onOutput ?? (() => undefined);
|
|
205
224
|
// A step that held the page a while says so when the next begins: a boot
|
|
206
225
|
// that stalls is found in its own log, not by guessing which step it was.
|
|
@@ -266,6 +285,7 @@ async function openProjectTracking(nameOrOptions, track) {
|
|
|
266
285
|
bundler: { workerUrl: "/bundler-worker.js", rollupModuleUrl: "/rollup/rollup.browser.js", esbuildModuleUrl: "/esbuild/browser.min.js", esbuildWasmUrl: "/esbuild/esbuild.wasm" },
|
|
267
286
|
// The shell's own Rolldown binding, or the project's, built for its version at image time.
|
|
268
287
|
rolldownModuleUrl: manifest.rolldown?.url ?? "/rolldown/factory.mjs",
|
|
288
|
+
...(manifest.rolldown ? { rolldownVersion: manifest.rolldown.version } : {}),
|
|
269
289
|
// Node's type stripper, amaro, served from this origin: a `.ts` entry runs as Node runs one.
|
|
270
290
|
typeStripperModuleUrl: "/amaro/amaro.js",
|
|
271
291
|
// What the module stand-ins compute with, served from this origin: Prisma's schema parser.
|
|
@@ -307,6 +327,7 @@ async function openProjectTracking(nameOrOptions, track) {
|
|
|
307
327
|
status(`The runtime started in ${Math.round(performance.now() - runtimeStartedAt)} ms`);
|
|
308
328
|
bootStage({ id: "machine", label: "Starting the machine", state: "done", detail: isolated ? "isolated runtime" : "runtime and store" });
|
|
309
329
|
const { runtime, container } = node;
|
|
330
|
+
let closeCookies;
|
|
310
331
|
const preparedProject = Boolean(node.workspaceStore?.preparedImage && node.workspaceStore.preparedImage === manifest.layers?.digest);
|
|
311
332
|
/** Whether this open's prepared install already placed this archive at this root (ADR-0085). */
|
|
312
333
|
const preparedTree = (root, integrity) => preparedProject
|
|
@@ -326,27 +347,16 @@ async function openProjectTracking(nameOrOptions, track) {
|
|
|
326
347
|
}
|
|
327
348
|
// Once the app has answered its first page, what a first boot read is the
|
|
328
349
|
// image's startup set: the host keeps it for the next first boot. A repeat
|
|
329
|
-
// boot holds every range earlier boots read, so it records nothing.
|
|
330
|
-
//
|
|
331
|
-
//
|
|
350
|
+
// boot holds every range earlier boots read, so it records nothing. Every
|
|
351
|
+
// reader stamps a range's first read, so one read of the set at the end
|
|
352
|
+
// gives the order the boot first needed each range.
|
|
332
353
|
let startupRecorded = false;
|
|
333
|
-
const startupOrder = new Set();
|
|
334
|
-
const sampleStartup = async () => { for (const range of await imageStartup.imageStartupSet())
|
|
335
|
-
startupOrder.add(range); };
|
|
336
|
-
const startupSampler = startupUrl && imageStartup.imageStartupSet
|
|
337
|
-
? setInterval(() => { if (!preparedProject || startupRecorded)
|
|
338
|
-
clearInterval(startupSampler);
|
|
339
|
-
else
|
|
340
|
-
void sampleStartup(); }, 250)
|
|
341
|
-
: undefined;
|
|
342
354
|
const recordStartup = () => {
|
|
343
|
-
if (startupSampler !== undefined)
|
|
344
|
-
clearInterval(startupSampler);
|
|
345
355
|
if (!startupUrl || !preparedProject || !imageStartup.imageStartupSet || startupRecorded)
|
|
346
356
|
return;
|
|
347
357
|
startupRecorded = true;
|
|
348
|
-
void
|
|
349
|
-
: nativeFetch(startupUrl, { method: "PUT", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ version: 1, ranges
|
|
358
|
+
void imageStartup.imageStartupSet().then((ranges) => ranges.length === 0 ? undefined
|
|
359
|
+
: nativeFetch(startupUrl, { method: "PUT", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ version: 1, ranges }) }))
|
|
350
360
|
.catch((cause) => console.warn(`[startup] ${cause instanceof Error ? cause.message : String(cause)}`));
|
|
351
361
|
};
|
|
352
362
|
// An image that links a Node install runs Node: its worker loads the
|
|
@@ -435,6 +445,7 @@ async function openProjectTracking(nameOrOptions, track) {
|
|
|
435
445
|
// before the worker is, which binds the bridge's message handler.
|
|
436
446
|
if (bridge.initServiceWorker) {
|
|
437
447
|
const cookies = await openPersistentBrowserCookieJar(projectId);
|
|
448
|
+
closeCookies = () => cookies.dispose();
|
|
438
449
|
attachTabnodeCookieJar(container.serverBridge, cookies);
|
|
439
450
|
exposeBrowserCookieJar(window, cookies);
|
|
440
451
|
}
|
|
@@ -852,6 +863,7 @@ async function openProjectTracking(nameOrOptions, track) {
|
|
|
852
863
|
* re-applied. Then the World's own runtime brings its twins up. Answers
|
|
853
864
|
* the way to run a command attached to the World.
|
|
854
865
|
*/
|
|
866
|
+
let stopWorld;
|
|
855
867
|
const attachWorld = async (world, preparedBodies) => {
|
|
856
868
|
const root = `${WORLDS_ROOT}/${world.name}`;
|
|
857
869
|
const record = `${root}/.substrate-world.json`;
|
|
@@ -923,6 +935,24 @@ async function openProjectTracking(nameOrOptions, track) {
|
|
|
923
935
|
const cli = /^node "([^"]+)"/mu.exec(stub)?.[1];
|
|
924
936
|
if (!cli)
|
|
925
937
|
throw new Error(`World ${world.name}: node_modules/.bin/volter-world is not a stub naming the CLI.`);
|
|
938
|
+
stopWorld = async (say) => {
|
|
939
|
+
const run = async (verb) => {
|
|
940
|
+
say(`World ${world.name}: ${verb}`);
|
|
941
|
+
const command = `node ${cli} ${verb} ${world.name} --root ${root} --json`;
|
|
942
|
+
const result = await runtime.start(command, { cwd: root, env }).result;
|
|
943
|
+
if (result.exitCode !== 0)
|
|
944
|
+
throw new Error(`World ${world.name}: ${verb} refused shutdown (exit ${result.exitCode}). ${result.stderr.trim()}`);
|
|
945
|
+
say(`World ${world.name}: ${verb} finished`);
|
|
946
|
+
return result.stdout;
|
|
947
|
+
};
|
|
948
|
+
// Retire only consumers the CLI proves no longer live; down retains data.
|
|
949
|
+
await run("consumers retire");
|
|
950
|
+
await run("down");
|
|
951
|
+
const stopped = JSON.parse(await run("status"));
|
|
952
|
+
if (stopped.running !== false || !Array.isArray(stopped.livePids) || stopped.livePids.length) {
|
|
953
|
+
throw new Error(`World ${world.name}: shutdown was not verified. Saved state has not been cleared.`);
|
|
954
|
+
}
|
|
955
|
+
};
|
|
926
956
|
// The World's data is its account: an instance here boots over it, never from nothing.
|
|
927
957
|
const up = `node ${cli} up ${root}/${world.config} --name ${world.name} ${world.environmentOutputFlag ?? "--env-file"} ${root}/world.env --root ${root} --keep-state`;
|
|
928
958
|
status(`$ ${up}`);
|
|
@@ -1397,9 +1427,6 @@ async function openProjectTracking(nameOrOptions, track) {
|
|
|
1397
1427
|
await worldAttachment.catch(() => undefined);
|
|
1398
1428
|
await Promise.allSettled(preparation);
|
|
1399
1429
|
setupFailure = error;
|
|
1400
|
-
// A boot whose app never answered read no startup set.
|
|
1401
|
-
if (startupSampler !== undefined)
|
|
1402
|
-
clearInterval(startupSampler);
|
|
1403
1430
|
// The page's log says why, in full, the moment setup stops.
|
|
1404
1431
|
output({ stream: "stderr", text: `\nsetup stopped: ${describeFailure(error)}\n\n` });
|
|
1405
1432
|
}
|
|
@@ -1516,7 +1543,7 @@ async function openProjectTracking(nameOrOptions, track) {
|
|
|
1516
1543
|
try {
|
|
1517
1544
|
// A source edit may move preparation to the host. Keep that fact even
|
|
1518
1545
|
// if a later edit returns to a browser-buildable image.
|
|
1519
|
-
const latest =
|
|
1546
|
+
const latest = await fetchImageManifest(name, manifestUrl);
|
|
1520
1547
|
recordPreparation(execution, latest.preparation);
|
|
1521
1548
|
// A lockfile edit is another plan; the setup that runs again reads the current one.
|
|
1522
1549
|
if (latest.dependencies)
|
|
@@ -1854,6 +1881,24 @@ async function openProjectTracking(nameOrOptions, track) {
|
|
|
1854
1881
|
close: async () => { unlisten?.(); unlisten = undefined; await handle.close(); },
|
|
1855
1882
|
};
|
|
1856
1883
|
},
|
|
1884
|
+
async shutdown(say = () => undefined) {
|
|
1885
|
+
// Startup must settle before issuing lifecycle commands against its World.
|
|
1886
|
+
await project.ready.catch(() => undefined);
|
|
1887
|
+
await restoringCaches;
|
|
1888
|
+
setupAbort.abort(new Error("The project is shutting down."));
|
|
1889
|
+
await feed?.close();
|
|
1890
|
+
await feed?.idle;
|
|
1891
|
+
say("Stopping the application");
|
|
1892
|
+
await stack?.stop();
|
|
1893
|
+
process?.kill();
|
|
1894
|
+
await process?.result.catch(() => undefined);
|
|
1895
|
+
if (stopWorld) {
|
|
1896
|
+
say("Stopping the World");
|
|
1897
|
+
await stopWorld(say);
|
|
1898
|
+
}
|
|
1899
|
+
say("Closing runtime and storage workers");
|
|
1900
|
+
await project.dispose();
|
|
1901
|
+
},
|
|
1857
1902
|
dispose() {
|
|
1858
1903
|
if (disposePromise)
|
|
1859
1904
|
return disposePromise;
|
|
@@ -1869,8 +1914,6 @@ async function openProjectTracking(nameOrOptions, track) {
|
|
|
1869
1914
|
}
|
|
1870
1915
|
};
|
|
1871
1916
|
setupAbort.abort(new Error("The project was closed."));
|
|
1872
|
-
if (startupSampler !== undefined)
|
|
1873
|
-
clearInterval(startupSampler);
|
|
1874
1917
|
await release(() => feed?.close());
|
|
1875
1918
|
await release(async () => { await feed?.idle; });
|
|
1876
1919
|
await release(async () => { await stack?.stop(); });
|
|
@@ -1883,6 +1926,7 @@ async function openProjectTracking(nameOrOptions, track) {
|
|
|
1883
1926
|
await release(() => { stopUnavailableChromium?.(); });
|
|
1884
1927
|
await release(() => bridge?.dispose());
|
|
1885
1928
|
await release(() => runtime.dispose());
|
|
1929
|
+
await release(async () => { await closeCookies?.(); });
|
|
1886
1930
|
if (failures.length === 1)
|
|
1887
1931
|
throw failures[0];
|
|
1888
1932
|
if (failures.length > 1)
|