@nimbus-sh/core 0.7.0 → 0.8.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/dist/_shared/tarball.d.ts +2 -1
- package/dist/_shared/tarball.d.ts.map +1 -1
- package/dist/_shared/tarball.js +5 -1
- package/dist/runtime/comment-strip.d.ts +38 -0
- package/dist/runtime/comment-strip.d.ts.map +1 -1
- package/dist/runtime/comment-strip.js +270 -76
- package/dist/runtime/cpython-runner.d.ts +1 -0
- package/dist/runtime/cpython-runner.d.ts.map +1 -1
- package/dist/runtime/cpython-runner.js +1 -1
- package/dist/runtime/esbuild-service.d.ts.map +1 -1
- package/dist/runtime/esbuild-service.js +10 -195
- package/dist/runtime/ruby-runner.d.ts +1 -0
- package/dist/runtime/ruby-runner.d.ts.map +1 -1
- package/dist/runtime/ruby-runner.js +1 -0
- package/dist/substrate/lifo/commands/system/npm.d.ts.map +1 -1
- package/dist/substrate/lifo/commands/system/npm.js +3 -4
- package/dist/workspace/nimbus-workspace.d.ts +7 -1
- package/dist/workspace/nimbus-workspace.d.ts.map +1 -1
- package/dist/workspace/nimbus-workspace.js +1 -2
- package/dist/workspace/supervisor-op.d.ts +88 -4
- package/dist/workspace/supervisor-op.d.ts.map +1 -1
- package/dist/workspace/supervisor-op.js +146 -14
- package/package.json +2 -2
- package/src/_shared/tarball.ts +5 -1
- package/src/runtime/comment-strip.ts +216 -69
- package/src/runtime/cpython-runner.ts +2 -1
- package/src/runtime/esbuild-service.ts +10 -159
- package/src/runtime/ruby-runner.ts +2 -0
- package/src/substrate/lifo/commands/system/npm.ts +3 -6
- package/src/workspace/nimbus-workspace.ts +6 -3
- package/src/workspace/supervisor-op.ts +212 -20
|
@@ -21,6 +21,7 @@ import { normalizeVfsPath, stripLeadingSlashes } from '../vfs/path.js';
|
|
|
21
21
|
import { errorText } from '../_shared/error-text.js';
|
|
22
22
|
import { tokenizer, tokTypes } from 'acorn';
|
|
23
23
|
import { literalStringValue, nodeList, nodeName, nodeProp, parseJavaScriptModule, } from './javascript-ast.js';
|
|
24
|
+
import { scanJsSource } from './comment-strip.js';
|
|
24
25
|
/**
|
|
25
26
|
* Bundler version tag. BUMP THIS whenever bundling semantics change —
|
|
26
27
|
* the esbuild plugin's resolver logic, the shared-externals rules, the
|
|
@@ -195,203 +196,14 @@ function hasEsmExports(src) {
|
|
|
195
196
|
return /^[ \t]*export\b/m.test(stripped);
|
|
196
197
|
}
|
|
197
198
|
/**
|
|
198
|
-
* Strip `//` and `/*
|
|
199
|
-
* source
|
|
200
|
-
*
|
|
201
|
-
*
|
|
202
|
-
*
|
|
203
|
-
* for the small entry points that reach the true-TLA fallback.
|
|
199
|
+
* Strip `//` and `/* *\/` comments and string / template literals from
|
|
200
|
+
* source for the import/export classifiers — one scanner shared with
|
|
201
|
+
* prefetch's import detection in `comment-strip.ts`. The result is
|
|
202
|
+
* byte-aligned with the input per line (comment and literal newlines are
|
|
203
|
+
* preserved), so error line numbers still match the original.
|
|
204
204
|
*/
|
|
205
205
|
function stripCommentsAndStrings(src) {
|
|
206
|
-
|
|
207
|
-
let i = 0;
|
|
208
|
-
const N = src.length;
|
|
209
|
-
// Track the last non-whitespace non-comment output character so we
|
|
210
|
-
// can disambiguate `/` as division (after identifier/literal/`)`/`]`)
|
|
211
|
-
// vs regex-literal opener (after operator / punctuator / keyword /
|
|
212
|
-
// start-of-file). Pre-fix the stripper had no regex awareness, so
|
|
213
|
-
// patterns like `var X = /^(?:'…)/` contained an unmatched `'` that
|
|
214
|
-
// bit it as a string opener that didn't close until many lines
|
|
215
|
-
// later — corrupting the import/export classifiers. Real-world bite:
|
|
216
|
-
// sv-utils@0.0.3 index.mjs has dozens of these regex literals.
|
|
217
|
-
let lastNonWsChar = '';
|
|
218
|
-
const recordOut = (ch) => {
|
|
219
|
-
if (ch !== ' ' && ch !== '\t' && ch !== '\n' && ch !== '\r') {
|
|
220
|
-
lastNonWsChar = ch;
|
|
221
|
-
}
|
|
222
|
-
};
|
|
223
|
-
// Identifier-suffix detection on lastNonWsChar: any of these means
|
|
224
|
-
// `/` is division. Anything else means `/` opens a regex.
|
|
225
|
-
// Includes ascii word chars + `)` `]` to cover `foo()/x` `a[i]/y`.
|
|
226
|
-
const DIVISION_AFTER = /[A-Za-z0-9_$\)\]]/;
|
|
227
|
-
while (i < N) {
|
|
228
|
-
const c = src[i];
|
|
229
|
-
if (c === '/' && src[i + 1] === '/') {
|
|
230
|
-
while (i < N && src[i] !== '\n')
|
|
231
|
-
i++;
|
|
232
|
-
stripped += ' ';
|
|
233
|
-
continue;
|
|
234
|
-
}
|
|
235
|
-
if (c === '/' && src[i + 1] === '*') {
|
|
236
|
-
i += 2;
|
|
237
|
-
while (i < N && !(src[i] === '*' && src[i + 1] === '/')) {
|
|
238
|
-
// Preserve newlines so line numbers stay aligned.
|
|
239
|
-
if (src[i] === '\n')
|
|
240
|
-
stripped += '\n';
|
|
241
|
-
i++;
|
|
242
|
-
}
|
|
243
|
-
i += 2;
|
|
244
|
-
stripped += ' ';
|
|
245
|
-
continue;
|
|
246
|
-
}
|
|
247
|
-
// Regex literal: `/` not followed by `/` or `*` (already handled
|
|
248
|
-
// above), AND preceded by something that makes regex valid here.
|
|
249
|
-
// The classifier looks at lastNonWsChar — for `(`, `,`, `=`, `;`,
|
|
250
|
-
// `{`, `[`, `:`, `!`, `&`, `|`, `?`, operators, or start-of-file,
|
|
251
|
-
// a slash is a regex opener.
|
|
252
|
-
if (c === '/' && !DIVISION_AFTER.test(lastNonWsChar)) {
|
|
253
|
-
stripped += ' ';
|
|
254
|
-
i++;
|
|
255
|
-
while (i < N) {
|
|
256
|
-
const rc = src[i];
|
|
257
|
-
if (rc === '\\') {
|
|
258
|
-
i += 2;
|
|
259
|
-
continue;
|
|
260
|
-
}
|
|
261
|
-
// Regex character class [...]: `/` inside it is content.
|
|
262
|
-
if (rc === '[') {
|
|
263
|
-
i++;
|
|
264
|
-
while (i < N && src[i] !== ']') {
|
|
265
|
-
if (src[i] === '\\') {
|
|
266
|
-
i += 2;
|
|
267
|
-
continue;
|
|
268
|
-
}
|
|
269
|
-
if (src[i] === '\n') {
|
|
270
|
-
stripped += '\n';
|
|
271
|
-
}
|
|
272
|
-
i++;
|
|
273
|
-
}
|
|
274
|
-
if (i < N)
|
|
275
|
-
i++; // consume ']'
|
|
276
|
-
continue;
|
|
277
|
-
}
|
|
278
|
-
if (rc === '/') {
|
|
279
|
-
i++;
|
|
280
|
-
break;
|
|
281
|
-
}
|
|
282
|
-
if (rc === '\n') {
|
|
283
|
-
// Regex literals can't span newlines. If we hit one without
|
|
284
|
-
// finding the closing `/`, this was probably NOT a regex —
|
|
285
|
-
// bail out gracefully (rare in practice; better than getting
|
|
286
|
-
// stuck in a wrong state).
|
|
287
|
-
break;
|
|
288
|
-
}
|
|
289
|
-
i++;
|
|
290
|
-
}
|
|
291
|
-
// Skip regex flags (g, i, m, s, u, y, d).
|
|
292
|
-
while (i < N && /[gimsuyd]/.test(src[i]))
|
|
293
|
-
i++;
|
|
294
|
-
recordOut('/');
|
|
295
|
-
continue;
|
|
296
|
-
}
|
|
297
|
-
if (c === '"' || c === "'" || c === '`') {
|
|
298
|
-
const q = c;
|
|
299
|
-
stripped += ' ';
|
|
300
|
-
i++;
|
|
301
|
-
while (i < N) {
|
|
302
|
-
const cc = src[i];
|
|
303
|
-
if (cc === '\\') {
|
|
304
|
-
i += 2;
|
|
305
|
-
continue;
|
|
306
|
-
}
|
|
307
|
-
if (cc === q) {
|
|
308
|
-
i++;
|
|
309
|
-
break;
|
|
310
|
-
}
|
|
311
|
-
// Template interpolation: ${...} — preserve the inner
|
|
312
|
-
// expression as raw code so the caller's depth-tracker can
|
|
313
|
-
// see `await` etc. inside it. Strip the wrapping `${`/`}`
|
|
314
|
-
// (those don't affect brace-depth from the caller's POV).
|
|
315
|
-
//
|
|
316
|
-
// CRITICAL: inside the interpolation expression, we must
|
|
317
|
-
// recognise NESTED strings (`'}'`, `"}"`, `` `${...}` ``) so
|
|
318
|
-
// their internal `}` characters don't decrement the depth
|
|
319
|
-
// counter — otherwise we exit the interpolation early and
|
|
320
|
-
// start consuming code as string content, eventually parsing
|
|
321
|
-
// the rest of the file as one massive unclosed string. This
|
|
322
|
-
// bit sv-utils/dist/index.mjs: multi-line backticks with
|
|
323
|
-
// `${url.replace('}', '_')}`-style interpolations corrupted
|
|
324
|
-
// line classification downstream. Recursive-by-loop here.
|
|
325
|
-
if (q === '`' && cc === '$' && src[i + 1] === '{') {
|
|
326
|
-
stripped += '${';
|
|
327
|
-
i += 2;
|
|
328
|
-
let depth = 1;
|
|
329
|
-
while (i < N && depth > 0) {
|
|
330
|
-
const ic = src[i];
|
|
331
|
-
// Nested string inside interpolation: skip its content.
|
|
332
|
-
if (ic === '"' || ic === "'" || ic === '`') {
|
|
333
|
-
const iq = ic;
|
|
334
|
-
stripped += ' ';
|
|
335
|
-
i++;
|
|
336
|
-
while (i < N) {
|
|
337
|
-
const icc = src[i];
|
|
338
|
-
if (icc === '\\') {
|
|
339
|
-
i += 2;
|
|
340
|
-
continue;
|
|
341
|
-
}
|
|
342
|
-
if (icc === iq) {
|
|
343
|
-
i++;
|
|
344
|
-
break;
|
|
345
|
-
}
|
|
346
|
-
// Nested template inside interpolation can also have its
|
|
347
|
-
// own ${...} — recurse once more (the practical depth
|
|
348
|
-
// observed in real code never exceeds 2; deeper nesting
|
|
349
|
-
// falls back to brace counting which is a best-effort).
|
|
350
|
-
if (iq === '`' && icc === '$' && src[i + 1] === '{') {
|
|
351
|
-
stripped += '${';
|
|
352
|
-
i += 2;
|
|
353
|
-
let d2 = 1;
|
|
354
|
-
while (i < N && d2 > 0) {
|
|
355
|
-
const i2 = src[i];
|
|
356
|
-
if (i2 === '{')
|
|
357
|
-
d2++;
|
|
358
|
-
else if (i2 === '}')
|
|
359
|
-
d2--;
|
|
360
|
-
if (d2 > 0)
|
|
361
|
-
stripped += i2;
|
|
362
|
-
i++;
|
|
363
|
-
}
|
|
364
|
-
stripped += '}';
|
|
365
|
-
continue;
|
|
366
|
-
}
|
|
367
|
-
if (icc === '\n')
|
|
368
|
-
stripped += '\n';
|
|
369
|
-
i++;
|
|
370
|
-
}
|
|
371
|
-
continue;
|
|
372
|
-
}
|
|
373
|
-
if (ic === '{')
|
|
374
|
-
depth++;
|
|
375
|
-
else if (ic === '}')
|
|
376
|
-
depth--;
|
|
377
|
-
if (depth > 0)
|
|
378
|
-
stripped += ic;
|
|
379
|
-
i++;
|
|
380
|
-
}
|
|
381
|
-
stripped += '}';
|
|
382
|
-
continue;
|
|
383
|
-
}
|
|
384
|
-
if (cc === '\n')
|
|
385
|
-
stripped += '\n';
|
|
386
|
-
i++;
|
|
387
|
-
}
|
|
388
|
-
continue;
|
|
389
|
-
}
|
|
390
|
-
stripped += c;
|
|
391
|
-
recordOut(c);
|
|
392
|
-
i++;
|
|
393
|
-
}
|
|
394
|
-
return stripped;
|
|
206
|
+
return scanJsSource(src, 'blank');
|
|
395
207
|
}
|
|
396
208
|
/**
|
|
397
209
|
* Convert ESM `import` statements at the top of `src` to CJS
|
|
@@ -1196,6 +1008,9 @@ async function transformWithEsbuild(esbuildApi, source, options) {
|
|
|
1196
1008
|
/** Source needed by the slim Worker Loader transform isolate. */
|
|
1197
1009
|
export function generateEsbuildTransformRuntimeSource() {
|
|
1198
1010
|
return [
|
|
1011
|
+
// scanJsSource is self-contained — its constants live in the body —
|
|
1012
|
+
// so this serialized copy carries the whole scanner.
|
|
1013
|
+
scanJsSource.toString(),
|
|
1199
1014
|
stripCommentsAndStrings.toString(),
|
|
1200
1015
|
hasEsmImports.toString(),
|
|
1201
1016
|
hasEsmExports.toString(),
|
|
@@ -88,6 +88,7 @@ export interface RubyFacetResult {
|
|
|
88
88
|
* no degraded version — it gets none, and says so.
|
|
89
89
|
*/
|
|
90
90
|
export type RubyResidentStart = (spawn: {
|
|
91
|
+
argv: string[];
|
|
91
92
|
/** VFS path of the interpreter. By path, not by value: it is 34.3 MiB. */
|
|
92
93
|
wasmVfsPath: string;
|
|
93
94
|
startArgs: RubyFacetCallArgs;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ruby-runner.d.ts","sourceRoot":"","sources":["../../src/runtime/ruby-runner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAmB,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACvE,OAAO,KAAK,EAAE,OAAO,EAAkB,MAAM,qCAAqC,CAAC;AAGnF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEjD,OAAO,EAA8B,KAAK,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAiBrF,KAAK,iBAAiB,GAAG,CACvB,QAAQ,EAAE,eAAe,EACzB,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,GAAG,SAAS,KACxB,OAAO,CAAC;AAEb;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE;IAC1C,MAAM,EAAE,SAAS,CAAC;IAClB,GAAG,EAAE,SAAS,CAAC;IACf,QAAQ,CAAC,EAAE;QACT,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;QAC/C,OAAO,CAAC,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,GAAG,SAAS,CAAC,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,CAAC;KAC1F,CAAC;IACF,8EAA8E;IAC9E,aAAa,CAAC,EAAE,iBAAiB,CAAC;CACnC,GAAG,iBAAiB,
|
|
1
|
+
{"version":3,"file":"ruby-runner.d.ts","sourceRoot":"","sources":["../../src/runtime/ruby-runner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAmB,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACvE,OAAO,KAAK,EAAE,OAAO,EAAkB,MAAM,qCAAqC,CAAC;AAGnF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEjD,OAAO,EAA8B,KAAK,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAiBrF,KAAK,iBAAiB,GAAG,CACvB,QAAQ,EAAE,eAAe,EACzB,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,GAAG,SAAS,KACxB,OAAO,CAAC;AAEb;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE;IAC1C,MAAM,EAAE,SAAS,CAAC;IAClB,GAAG,EAAE,SAAS,CAAC;IACf,QAAQ,CAAC,EAAE;QACT,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;QAC/C,OAAO,CAAC,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,GAAG,SAAS,CAAC,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,CAAC;KAC1F,CAAC;IACF,8EAA8E;IAC9E,aAAa,CAAC,EAAE,iBAAiB,CAAC;CACnC,GAAG,iBAAiB,CA8LpB;AA2TD,2EAA2E;AAC3E,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,cAAc,CAAC;CAC5B;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;GAQG;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,KAAK,EAAE;IACtC,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,0EAA0E;IAC1E,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,iBAAiB,CAAC;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;CACjB,KAAK,OAAO,CAAC,eAAe,CAAC,CAAC;AAS/B;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,OAAO,GAAG,eAAe,GAAG,IAAI,CAS7E;AAgGD;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CA2B1C;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,yBAAyB,q4kCAgrBrC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"npm.d.ts","sourceRoot":"","sources":["../../../../../src/substrate/lifo/commands/system/npm.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAuB,MAAM,aAAa,CAAC;AAChF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEtD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAapD,eAAO,MAAM,WAAW,WAAW,CAAC;AAIpC,UAAU,WAAW;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,GAAG;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CACnC;AAED,MAAM,MAAM,cAAc,GAAG,CAC5B,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,cAAc,KACf,OAAO,CAAC,MAAM,CAAC,CAAC;AAErB,kFAAkF;AAClF,MAAM,WAAW,cAAc;IAC9B,OAAO,CACN,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,UAAU,CAAC,EAAE,OAAO,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,GAClE,OAAO,CAAC;QACV,SAAS,EAAE,MAAM,EAAE,CAAC;QACpB,MAAM,EAAE,MAAM,EAAE,CAAC;QACjB,UAAU,EAAE,MAAM,CAAC;QACnB,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,CAAC,EAAE,MAAM,CAAC;KACpB,CAAC,CAAC;CACH;AAED,MAAM,WAAW,cAAc;IAC9B,QAAQ,CAAC,SAAS,CAAC,EAAE,cAAc,CAAC;CACpC;AAuLD,wBAAgB,aAAa,CAAC,GAAG,EAAE,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAMtE;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAaxH;
|
|
1
|
+
{"version":3,"file":"npm.d.ts","sourceRoot":"","sources":["../../../../../src/substrate/lifo/commands/system/npm.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAuB,MAAM,aAAa,CAAC;AAChF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEtD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAapD,eAAO,MAAM,WAAW,WAAW,CAAC;AAIpC,UAAU,WAAW;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,GAAG;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CACnC;AAED,MAAM,MAAM,cAAc,GAAG,CAC5B,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,cAAc,KACf,OAAO,CAAC,MAAM,CAAC,CAAC;AAErB,kFAAkF;AAClF,MAAM,WAAW,cAAc;IAC9B,OAAO,CACN,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,UAAU,CAAC,EAAE,OAAO,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,GAClE,OAAO,CAAC;QACV,SAAS,EAAE,MAAM,EAAE,CAAC;QACpB,MAAM,EAAE,MAAM,EAAE,CAAC;QACjB,UAAU,EAAE,MAAM,CAAC;QACnB,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,CAAC,EAAE,MAAM,CAAC;KACpB,CAAC,CAAC;CACH;AAED,MAAM,WAAW,cAAc;IAC9B,QAAQ,CAAC,SAAS,CAAC,EAAE,cAAc,CAAC;CACpC;AAuLD,wBAAgB,aAAa,CAAC,GAAG,EAAE,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAMtE;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAaxH;AAimBD,wBAAgB,gBAAgB,CAC/B,QAAQ,EAAE,eAAe,EACzB,YAAY,CAAC,EAAE,cAAc,EAC7B,MAAM,CAAC,EAAE,MAAM,EACf,IAAI,CAAC,EAAE,cAAc,GACnB,OAAO,CA+CT;AAiCD,wBAAgB,gBAAgB,CAC/B,QAAQ,EAAE,eAAe,EACzB,YAAY,CAAC,EAAE,cAAc,GAC3B,OAAO,CAyGT;AAED,wBAAsB,gBAAgB,CACrC,WAAW,EAAE,MAAM,EACnB,GAAG,EAAE,cAAc,EACnB,QAAQ,EAAE,eAAe,EACzB,MAAM,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,MAAM,CAAC,CA2BjB"}
|
|
@@ -186,10 +186,9 @@ async function installSinglePackage(name, version, targetBase, vfs, npmRegistry,
|
|
|
186
186
|
}
|
|
187
187
|
stdout.write(` ${name}${version ? '@' + version : ''}...\n`);
|
|
188
188
|
const info = await fetchPackageInfo(npmRegistry, name, version, signal);
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
}
|
|
189
|
+
// writeTarballStream throws when the archive carried no manifest and writes
|
|
190
|
+
// package.json last, so a return here is a complete package on disk.
|
|
191
|
+
await fetchAndStreamPackage(info.dist.tarball, targetDir, vfs, signal);
|
|
193
192
|
let installed = 1;
|
|
194
193
|
// Global install: link binaries
|
|
195
194
|
if (isGlobal) {
|
|
@@ -41,8 +41,14 @@ export interface NimbusWorkspaceOptions {
|
|
|
41
41
|
* Every atomic write in the filesystem rests on this being a real
|
|
42
42
|
* transaction. An implementation that merely calls the callback converts
|
|
43
43
|
* each one into a torn write that reports success.
|
|
44
|
+
*
|
|
45
|
+
* `NimbusWorkspace.create` is a first-write-wins composition root beside
|
|
46
|
+
* `worker/index.ts` and `loom/actor.ts`: when `ctxExports` is absent the
|
|
47
|
+
* host's ctx `exports` bag is adopted as the isolate's.
|
|
44
48
|
*/
|
|
45
|
-
readonly transactions?: TransactionHost
|
|
49
|
+
readonly transactions?: TransactionHost & {
|
|
50
|
+
readonly exports?: CtxExports;
|
|
51
|
+
};
|
|
46
52
|
/**
|
|
47
53
|
* The filesystem already open over `sql`, for a host that has one.
|
|
48
54
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nimbus-workspace.d.ts","sourceRoot":"","sources":["../../src/workspace/nimbus-workspace.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,mCAAmC,CAAC;AAC3D,OAAO,EAAE,KAAK,EAAE,MAAM,kCAAkC,CAAC;AACzD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAC;AAE7E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wCAAwC,CAAC;AAI9E,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,oCAAoC,CAAC;AAC/F,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,EAAE,SAAS,EAAqB,MAAM,sBAAsB,CAAC;AAMpE,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAE/E,OAAO,EAAE,wBAAwB,EAAE,MAAM,0CAA0C,CAAC;AACpF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAK1D,OAAO,EAAsB,KAAK,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAIxF,OAAO,EAAkC,KAAK,UAAU,EAAE,KAAK,iBAAiB,EAAE,MAAM,oCAAoC,CAAC;AAC7H,OAAO,EAA6B,KAAK,oBAAoB,EAAE,KAAK,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAEpH,MAAM,WAAW,sBAAsB;IACrC,iEAAiE;IACjE,QAAQ,CAAC,GAAG,EAAE,WAAW,CAAC;IAC1B
|
|
1
|
+
{"version":3,"file":"nimbus-workspace.d.ts","sourceRoot":"","sources":["../../src/workspace/nimbus-workspace.ts"],"names":[],"mappings":"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"}
|
|
@@ -86,8 +86,7 @@ export class NimbusWorkspace {
|
|
|
86
86
|
static async create(options) {
|
|
87
87
|
if (options.fabric)
|
|
88
88
|
composeFabric(options.fabric);
|
|
89
|
-
const exports = options.ctxExports
|
|
90
|
-
?? options.transactions?.exports;
|
|
89
|
+
const exports = options.ctxExports ?? options.transactions?.exports;
|
|
91
90
|
if (exports)
|
|
92
91
|
adoptCtxExports(exports);
|
|
93
92
|
const vfs = options.vfs ?? openFilesystem(options);
|
|
@@ -1,23 +1,107 @@
|
|
|
1
1
|
import type { SqliteVFS } from '../vfs/sqlite-vfs.js';
|
|
2
|
+
import { type VfsCred } from '../runtime/os-contracts.js';
|
|
3
|
+
import { SqliteRuntimeFsBridge } from '../runtime/sqlite-runtime-fs-bridge.js';
|
|
2
4
|
import type { SessionProcessSupervisor } from '../runtime/session-process-supervisor.js';
|
|
3
5
|
/** Identity comes from the supervisor binding, never from facet arguments. */
|
|
4
6
|
export interface SupervisorOpEnvelope {
|
|
5
|
-
readonly op:
|
|
7
|
+
readonly op: SupervisorOpName;
|
|
6
8
|
readonly args?: readonly unknown[];
|
|
7
9
|
readonly pid?: number;
|
|
8
10
|
readonly writerId?: string;
|
|
9
11
|
readonly mutationOwner?: string;
|
|
10
12
|
readonly stream?: ReadableStream<Uint8Array>;
|
|
11
13
|
}
|
|
12
|
-
export type SupervisorOpHandler = (envelope: SupervisorOpEnvelope) => unknown;
|
|
14
|
+
export type SupervisorOpHandler = (envelope: SupervisorOpEnvelope, tools: SupervisorOpTools) => unknown;
|
|
13
15
|
export interface SupervisorOpDeps {
|
|
14
16
|
readonly vfs: SqliteVFS;
|
|
15
17
|
/** Absent a process table, operations use the unprivileged session user. */
|
|
16
18
|
readonly processes?: SessionProcessSupervisor;
|
|
17
19
|
readonly output?: (stream: 'stdout' | 'stderr', pid: number, data: string) => void;
|
|
18
|
-
/**
|
|
19
|
-
|
|
20
|
+
/**
|
|
21
|
+
* The host's `_rpc*` surface for ops beyond the native set — an in-process
|
|
22
|
+
* workspace's dispatch record, or the session itself for
|
|
23
|
+
* `sessionSupervisorOps`. A native op never consults it.
|
|
24
|
+
*/
|
|
25
|
+
readonly host?: SupervisorOpHost;
|
|
26
|
+
/**
|
|
27
|
+
* A pid-keyed bridge cache to serve the native ops from. Supplied by the
|
|
28
|
+
* session so `supervisorBridge` hands callers the same bridges the handler
|
|
29
|
+
* uses; in-process workspaces let the handler build its own.
|
|
30
|
+
*/
|
|
31
|
+
readonly bridge?: SupervisorOpBridgeStore;
|
|
32
|
+
readonly extend?: Partial<Record<SupervisorOpName, SupervisorOpHandler>>;
|
|
20
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* One slot in an op's argument plan: a number takes `envelope.args[n]`, a
|
|
36
|
+
* name takes the envelope's identity field (`pid`, `writerId`, `stream`,
|
|
37
|
+
* `mutationOwner`). The envelope is always the shape — a host never
|
|
38
|
+
* re-parses it.
|
|
39
|
+
*/
|
|
40
|
+
export type SupervisorOpArg = number | 'pid' | 'writerId' | 'stream' | 'mutationOwner';
|
|
41
|
+
export interface SupervisorOpRoute {
|
|
42
|
+
/** The host method this op dispatches to. */
|
|
43
|
+
readonly method: string;
|
|
44
|
+
/** Positional plan for the host call — envelope fields, not raw args. */
|
|
45
|
+
readonly args: readonly SupervisorOpArg[];
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* The embedder's dispatch surface — the `_rpc*` methods SUPERVISOR_OP_ROUTES
|
|
49
|
+
* names. The session satisfies it with its own class; an in-process
|
|
50
|
+
* workspace supplies its host object.
|
|
51
|
+
*/
|
|
52
|
+
export interface SupervisorOpHost {
|
|
53
|
+
readonly [method: string]: unknown;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* The canonical supervisor op set — every operation the supervisor RPC
|
|
57
|
+
* serves. Three consumers key on these names:
|
|
58
|
+
*
|
|
59
|
+
* - `sessionSupervisorOp` (worker): the DO's host — `extend` overrides for
|
|
60
|
+
* hosted accounting plus the non-filesystem ops it answers itself.
|
|
61
|
+
* - `createSupervisorOpHandler`: an in-process workspace — filesystem ops
|
|
62
|
+
* run against the VFS directly; every other op dispatches to
|
|
63
|
+
* `deps.host` through SUPERVISOR_OP_ROUTES, the embedder's `_rpc*`
|
|
64
|
+
* surface.
|
|
65
|
+
* - `supervisor-host-dispatch`: the test — derives every case's delegate
|
|
66
|
+
* and expected arguments from SUPERVISOR_OP_ROUTES, not a copied list.
|
|
67
|
+
*
|
|
68
|
+
* An op absent here is not served, on any host.
|
|
69
|
+
*/
|
|
70
|
+
export declare const SUPERVISOR_OPS: readonly ["readFile", "readFileBytes", "writeFile", "stat", "lstat", "hasLegacySymlinkUnder", "utimes", "chmod", "access", "chown", "setUmask", "readdir", "exists", "mkdir", "rmdir", "rename", "unlink", "readlink", "symlink", "fsAcquire", "fsRevision", "fsList", "wsOpen", "wsPoll", "wsSend", "wsClose", "fsOpen", "fsRead", "fsWrite", "fsClose", "fsReadRange", "fsReadRangeUncached", "fsReadBatch", "fsWriteRange", "fsAppend", "fsAppendAck", "fsTruncate", "writeBatch", "writeBatchStream", "putRegistryEntries", "stdout", "stderr", "prefetch", "registerPort", "unregisterPort", "reportExit", "routeLoopback", "transform", "cpSpawn", "cpStdinWrite", "cpStdinEnd", "cpReadStdin", "cpReadOutput", "cpDrainOutput", "cpKill", "cpWait", "cpDispatchInline"];
|
|
71
|
+
export type SupervisorOpName = (typeof SUPERVISOR_OPS)[number];
|
|
72
|
+
/**
|
|
73
|
+
* What the shared handler hands a host override: the pid-keyed bridge and
|
|
74
|
+
* the deps it was built with, so an override that wraps a filesystem op
|
|
75
|
+
* (read-allocation accounting, stream-drain timing) reuses the same bridge
|
|
76
|
+
* the default handler would have used instead of caching its own.
|
|
77
|
+
*/
|
|
78
|
+
export interface SupervisorOpTools {
|
|
79
|
+
readonly bridge: (pid?: number) => SqliteRuntimeFsBridge;
|
|
80
|
+
readonly vfs: SqliteVFS;
|
|
81
|
+
readonly cred: (pid?: number) => VfsCred;
|
|
82
|
+
readonly output?: (stream: 'stdout' | 'stderr', pid: number, data: string) => void;
|
|
83
|
+
}
|
|
84
|
+
/** The host-side argument plan per op — how an envelope becomes an _rpc* call. */
|
|
85
|
+
export declare const SUPERVISOR_OP_ROUTES: Readonly<Record<SupervisorOpName, SupervisorOpRoute>>;
|
|
86
|
+
/**
|
|
87
|
+
* The ops `createSupervisorOpHandler` serves natively — one pid-keyed
|
|
88
|
+
* filesystem bridge, plus the output stream. A session's `extend` overrides
|
|
89
|
+
* never cover these by accident: `sessionSupervisorOps` builds its delegate
|
|
90
|
+
* set from this name list, not a hand-copied table.
|
|
91
|
+
*/
|
|
92
|
+
export declare const SUPERVISOR_NATIVE_OPS: ReadonlySet<string>;
|
|
93
|
+
/** The pid-keyed bridge cache behind the native filesystem ops. */
|
|
94
|
+
export interface SupervisorOpBridgeStore {
|
|
95
|
+
readonly bridge: (pid?: number) => SqliteRuntimeFsBridge;
|
|
96
|
+
/** Drop a pid's bridge — a process exit ends its credential's validity. */
|
|
97
|
+
readonly forget: (pid: number) => void;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Exported so the session's `supervisorBridge` — used by RPC bodies the
|
|
101
|
+
* envelope delegates back to (fsOpen, fsAppend, writeBatch, …) — is the
|
|
102
|
+
* same cache the handler's native ops serve from, never a second one.
|
|
103
|
+
*/
|
|
104
|
+
export declare function createSupervisorBridgeStore(deps: Pick<SupervisorOpDeps, 'vfs' | 'processes'>): SupervisorOpBridgeStore;
|
|
21
105
|
/** One dispatch method lets any host serve its workspace to process facets. */
|
|
22
106
|
export declare function createSupervisorOpHandler(deps: SupervisorOpDeps): (envelope: SupervisorOpEnvelope) => Promise<unknown>;
|
|
23
107
|
//# sourceMappingURL=supervisor-op.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"supervisor-op.d.ts","sourceRoot":"","sources":["../../src/workspace/supervisor-op.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"supervisor-op.d.ts","sourceRoot":"","sources":["../../src/workspace/supervisor-op.ts"],"names":[],"mappings":"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"}
|
|
@@ -31,20 +31,138 @@ function credFor(deps, pid) {
|
|
|
31
31
|
}
|
|
32
32
|
return deps.processes ? deps.processes.cred(pid) : CRED_SESSION_USER;
|
|
33
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* The canonical supervisor op set — every operation the supervisor RPC
|
|
36
|
+
* serves. Three consumers key on these names:
|
|
37
|
+
*
|
|
38
|
+
* - `sessionSupervisorOp` (worker): the DO's host — `extend` overrides for
|
|
39
|
+
* hosted accounting plus the non-filesystem ops it answers itself.
|
|
40
|
+
* - `createSupervisorOpHandler`: an in-process workspace — filesystem ops
|
|
41
|
+
* run against the VFS directly; every other op dispatches to
|
|
42
|
+
* `deps.host` through SUPERVISOR_OP_ROUTES, the embedder's `_rpc*`
|
|
43
|
+
* surface.
|
|
44
|
+
* - `supervisor-host-dispatch`: the test — derives every case's delegate
|
|
45
|
+
* and expected arguments from SUPERVISOR_OP_ROUTES, not a copied list.
|
|
46
|
+
*
|
|
47
|
+
* An op absent here is not served, on any host.
|
|
48
|
+
*/
|
|
49
|
+
export const SUPERVISOR_OPS = [
|
|
50
|
+
'readFile', 'readFileBytes', 'writeFile', 'stat', 'lstat',
|
|
51
|
+
'hasLegacySymlinkUnder', 'utimes', 'chmod', 'access', 'chown', 'setUmask',
|
|
52
|
+
'readdir', 'exists', 'mkdir', 'rmdir', 'rename', 'unlink', 'readlink',
|
|
53
|
+
'symlink', 'fsAcquire', 'fsRevision', 'fsList', 'wsOpen', 'wsPoll',
|
|
54
|
+
'wsSend', 'wsClose', 'fsOpen', 'fsRead', 'fsWrite', 'fsClose',
|
|
55
|
+
'fsReadRange', 'fsReadRangeUncached', 'fsReadBatch', 'fsWriteRange',
|
|
56
|
+
'fsAppend', 'fsAppendAck', 'fsTruncate', 'writeBatch', 'writeBatchStream',
|
|
57
|
+
'putRegistryEntries', 'stdout', 'stderr', 'prefetch', 'registerPort',
|
|
58
|
+
'unregisterPort', 'reportExit', 'routeLoopback', 'transform', 'cpSpawn',
|
|
59
|
+
'cpStdinWrite', 'cpStdinEnd', 'cpReadStdin', 'cpReadOutput',
|
|
60
|
+
'cpDrainOutput', 'cpKill', 'cpWait', 'cpDispatchInline',
|
|
61
|
+
];
|
|
62
|
+
/** The host-side argument plan per op — how an envelope becomes an _rpc* call. */
|
|
63
|
+
export const SUPERVISOR_OP_ROUTES = {
|
|
64
|
+
readFile: { method: '_rpcReadFile', args: [0, 'pid'] },
|
|
65
|
+
readFileBytes: { method: '_rpcReadFileBytes', args: [0, 'pid'] },
|
|
66
|
+
writeFile: { method: '_rpcWriteFile', args: [0, 1, 'pid'] },
|
|
67
|
+
stat: { method: '_rpcStat', args: [0, 'pid'] },
|
|
68
|
+
lstat: { method: '_rpcLstat', args: [0, 'pid'] },
|
|
69
|
+
hasLegacySymlinkUnder: { method: '_rpcHasLegacySymlinkUnder', args: [0, 'pid'] },
|
|
70
|
+
utimes: { method: '_rpcUtimes', args: [0, 1, 2, 'pid'] },
|
|
71
|
+
chmod: { method: '_rpcChmod', args: [0, 1, 'pid'] },
|
|
72
|
+
access: { method: '_rpcAccess', args: [0, 1, 'pid'] },
|
|
73
|
+
chown: { method: '_rpcChown', args: [0, 1, 2, 'pid', 3] },
|
|
74
|
+
setUmask: { method: '_rpcSetUmask', args: [0, 'pid'] },
|
|
75
|
+
readdir: { method: '_rpcReaddir', args: [0, 'pid'] },
|
|
76
|
+
exists: { method: '_rpcExists', args: [0, 'pid'] },
|
|
77
|
+
mkdir: { method: '_rpcMkdir', args: [0, 'pid'] },
|
|
78
|
+
rmdir: { method: '_rpcRmdir', args: [0, 'pid'] },
|
|
79
|
+
rename: { method: '_rpcRename', args: [0, 1, 'pid'] },
|
|
80
|
+
unlink: { method: '_rpcUnlink', args: [0, 'pid'] },
|
|
81
|
+
readlink: { method: '_rpcReadlink', args: [0, 'pid'] },
|
|
82
|
+
symlink: { method: '_rpcSymlink', args: [0, 1, 'pid'] },
|
|
83
|
+
fsAcquire: { method: '_rpcFsAcquire', args: [0, 1, 'pid'] },
|
|
84
|
+
fsRevision: { method: '_rpcFsRevision', args: [0, 'pid'] },
|
|
85
|
+
fsList: { method: '_rpcFsList', args: [0, 1, 'pid'] },
|
|
86
|
+
wsOpen: { method: '_rpcWsOpen', args: [0, 1, 'pid'] },
|
|
87
|
+
wsPoll: { method: '_rpcWsPoll', args: [0, 1, 'pid'] },
|
|
88
|
+
wsSend: { method: '_rpcWsSend', args: [0, 1, 2, 'pid'] },
|
|
89
|
+
wsClose: { method: '_rpcWsClose', args: [0, 1, 2, 'pid'] },
|
|
90
|
+
fsOpen: { method: '_rpcFsOpen', args: [0, 1, 'pid'] },
|
|
91
|
+
fsRead: { method: '_rpcFsRead', args: [0, 1, 2, 'pid'] },
|
|
92
|
+
fsWrite: { method: '_rpcFsWrite', args: [0, 1, 2, 'pid'] },
|
|
93
|
+
fsClose: { method: '_rpcFsClose', args: [0, 'pid'] },
|
|
94
|
+
fsReadRange: { method: '_rpcFsReadRange', args: [0, 1, 2, 'pid'] },
|
|
95
|
+
fsReadRangeUncached: { method: '_rpcFsReadRangeUncached', args: [0, 1, 2, 'pid'] },
|
|
96
|
+
fsReadBatch: { method: '_rpcFsReadBatch', args: [0, 'pid'] },
|
|
97
|
+
fsWriteRange: { method: '_rpcFsWriteRange', args: [0, 1, 2, 'pid'] },
|
|
98
|
+
fsAppend: { method: '_rpcFsAppend', args: [0, 'writerId', 1, 2, 3, 'pid'] },
|
|
99
|
+
fsAppendAck: { method: '_rpcFsAppendAck', args: ['writerId', 0, 1, 'pid'] },
|
|
100
|
+
fsTruncate: { method: '_rpcFsTruncate', args: [0, 1, 'pid'] },
|
|
101
|
+
writeBatch: { method: '_rpcWriteBatch', args: [0, 'pid'] },
|
|
102
|
+
writeBatchStream: { method: '_rpcWriteBatchStream', args: ['stream', 'mutationOwner', 'pid'] },
|
|
103
|
+
putRegistryEntries: { method: '_rpcPutRegistryEntries', args: [0] },
|
|
104
|
+
stdout: { method: '_rpcStdout', args: ['pid', 0] },
|
|
105
|
+
stderr: { method: '_rpcStderr', args: ['pid', 0] },
|
|
106
|
+
prefetch: { method: '_rpcPrefetch', args: [0, 1] },
|
|
107
|
+
registerPort: { method: '_rpcRegisterPort', args: ['pid', 0] },
|
|
108
|
+
unregisterPort: { method: '_rpcUnregisterPort', args: [0] },
|
|
109
|
+
reportExit: { method: '_rpcReportExit', args: ['pid', 0, 1] },
|
|
110
|
+
routeLoopback: { method: '_rpcRouteLoopback', args: [0, 1] },
|
|
111
|
+
transform: { method: '_rpcTransform', args: [0, 1] },
|
|
112
|
+
cpSpawn: { method: '_rpcCpSpawn', args: [0] },
|
|
113
|
+
cpStdinWrite: { method: '_rpcCpStdinWrite', args: [0, 1] },
|
|
114
|
+
cpStdinEnd: { method: '_rpcCpStdinEnd', args: [0] },
|
|
115
|
+
cpReadStdin: { method: '_rpcCpReadStdin', args: [0, 1] },
|
|
116
|
+
cpReadOutput: { method: '_rpcCpReadOutput', args: [0, 1, 2, 3] },
|
|
117
|
+
cpDrainOutput: { method: '_rpcCpDrainOutput', args: [0] },
|
|
118
|
+
cpKill: { method: '_rpcCpKill', args: [0, 1] },
|
|
119
|
+
cpWait: { method: '_rpcCpWait', args: [0, 1] },
|
|
120
|
+
cpDispatchInline: { method: '_rpcCpDispatchInline', args: [0, 1] },
|
|
121
|
+
};
|
|
122
|
+
/**
|
|
123
|
+
* The ops `createSupervisorOpHandler` serves natively — one pid-keyed
|
|
124
|
+
* filesystem bridge, plus the output stream. A session's `extend` overrides
|
|
125
|
+
* never cover these by accident: `sessionSupervisorOps` builds its delegate
|
|
126
|
+
* set from this name list, not a hand-copied table.
|
|
127
|
+
*/
|
|
128
|
+
export const SUPERVISOR_NATIVE_OPS = new Set([
|
|
129
|
+
'readFile', 'readFileBytes', 'stat', 'lstat', 'exists', 'readdir',
|
|
130
|
+
'readlink', 'fsReadRange', 'fsReadRangeUncached', 'fsRevision',
|
|
131
|
+
'hasLegacySymlinkUnder', 'writeFile', 'mkdir', 'rmdir', 'unlink',
|
|
132
|
+
'rename', 'symlink', 'chmod', 'utimes', 'fsTruncate',
|
|
133
|
+
'writeBatchStream', 'stdout', 'stderr',
|
|
134
|
+
]);
|
|
135
|
+
/**
|
|
136
|
+
* Exported so the session's `supervisorBridge` — used by RPC bodies the
|
|
137
|
+
* envelope delegates back to (fsOpen, fsAppend, writeBatch, …) — is the
|
|
138
|
+
* same cache the handler's native ops serve from, never a second one.
|
|
139
|
+
*/
|
|
140
|
+
export function createSupervisorBridgeStore(deps) {
|
|
141
|
+
const bridges = new Map();
|
|
142
|
+
return {
|
|
143
|
+
bridge: (pid) => {
|
|
144
|
+
const key = pid ?? 0;
|
|
145
|
+
const credentialed = deps.vfs.as(credFor(deps, pid));
|
|
146
|
+
const held = bridges.get(key);
|
|
147
|
+
if (held) {
|
|
148
|
+
held.updateCredential(credentialed);
|
|
149
|
+
return held;
|
|
150
|
+
}
|
|
151
|
+
const built = new SqliteRuntimeFsBridge(credentialed, deps.vfs);
|
|
152
|
+
bridges.set(key, built);
|
|
153
|
+
return built;
|
|
154
|
+
},
|
|
155
|
+
forget: (pid) => { bridges.delete(pid); },
|
|
156
|
+
};
|
|
157
|
+
}
|
|
34
158
|
/** One dispatch method lets any host serve its workspace to process facets. */
|
|
35
159
|
export function createSupervisorOpHandler(deps) {
|
|
36
|
-
const
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
held.updateCredential(credentialed);
|
|
43
|
-
return held;
|
|
44
|
-
}
|
|
45
|
-
const built = new SqliteRuntimeFsBridge(credentialed, deps.vfs);
|
|
46
|
-
bridges.set(key, built);
|
|
47
|
-
return built;
|
|
160
|
+
const bridgeFor = deps.bridge?.bridge ?? createSupervisorBridgeStore(deps).bridge;
|
|
161
|
+
const tools = {
|
|
162
|
+
bridge: bridgeFor,
|
|
163
|
+
vfs: deps.vfs,
|
|
164
|
+
cred: (pid) => credFor(deps, pid),
|
|
165
|
+
output: deps.output,
|
|
48
166
|
};
|
|
49
167
|
const ops = {
|
|
50
168
|
readFile: async (e) => {
|
|
@@ -83,10 +201,24 @@ export function createSupervisorOpHandler(deps) {
|
|
|
83
201
|
if (!envelope || typeof envelope.op !== 'string') {
|
|
84
202
|
throw new Error('supervisor op: envelope names no operation');
|
|
85
203
|
}
|
|
204
|
+
// Priority: the embedder's own handler → the native filesystem op → the
|
|
205
|
+
// canonical route table onto the host's _rpc* methods. An op in none of
|
|
206
|
+
// these is not served by this host.
|
|
86
207
|
const handler = Object.hasOwn(extend, envelope.op) ? extend[envelope.op]
|
|
87
208
|
: Object.hasOwn(ops, envelope.op) ? ops[envelope.op] : undefined;
|
|
88
|
-
if (
|
|
209
|
+
if (handler)
|
|
210
|
+
return handler(envelope, tools);
|
|
211
|
+
const route = Object.hasOwn(SUPERVISOR_OP_ROUTES, envelope.op)
|
|
212
|
+
? SUPERVISOR_OP_ROUTES[envelope.op] : undefined;
|
|
213
|
+
if (!route)
|
|
89
214
|
throw new Error(`supervisor op: '${envelope.op}' is not served by this host`);
|
|
90
|
-
|
|
215
|
+
const host = deps.host;
|
|
216
|
+
if (!host)
|
|
217
|
+
throw new Error(`supervisor op: '${envelope.op}' needs a host that this workspace does not have`);
|
|
218
|
+
const method = host[route.method];
|
|
219
|
+
if (typeof method !== 'function')
|
|
220
|
+
throw new Error(`supervisor op: missing host method ${route.method}`);
|
|
221
|
+
const args = route.args.map((slot) => typeof slot === 'number' ? envelope.args?.[slot] : envelope[slot]);
|
|
222
|
+
return Reflect.apply(method, host, args);
|
|
91
223
|
};
|
|
92
224
|
}
|