@nimbus-sh/core 0.6.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/README.md +47 -26
- package/dist/_shared/byte-stream.d.ts +5 -4
- package/dist/_shared/byte-stream.d.ts.map +1 -1
- package/dist/_shared/real-node-imports.d.ts +7 -0
- package/dist/_shared/real-node-imports.d.ts.map +1 -1
- package/dist/_shared/real-node-imports.js +8 -0
- package/dist/_shared/tarball.d.ts +24 -5
- package/dist/_shared/tarball.d.ts.map +1 -1
- package/dist/_shared/tarball.js +42 -5
- package/dist/_shared/vfs-write-ledger.d.ts.map +1 -1
- package/dist/_shared/vfs-write-ledger.js +22 -16
- package/dist/runtime/comment-strip.d.ts +32 -29
- package/dist/runtime/comment-strip.d.ts.map +1 -1
- package/dist/runtime/comment-strip.js +273 -51
- 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 +38 -42
- package/dist/runtime/esbuild-service.d.ts.map +1 -1
- package/dist/runtime/esbuild-service.js +500 -388
- package/dist/runtime/javascript-ast.d.ts.map +1 -1
- package/dist/runtime/javascript-ast.js +45 -7
- package/dist/runtime/opentui-wasm-backend.d.ts.map +1 -1
- package/dist/runtime/opentui-wasm-backend.js +18 -16
- package/dist/runtime/port-registry.d.ts +4 -2
- package/dist/runtime/port-registry.d.ts.map +1 -1
- package/dist/runtime/port-registry.js +60 -8
- 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/shell/stdin-adapter.d.ts +11 -0
- package/dist/shell/stdin-adapter.d.ts.map +1 -0
- package/dist/shell/stdin-adapter.js +59 -0
- package/dist/shell/unix-commands.d.ts +2 -1
- package/dist/shell/unix-commands.d.ts.map +1 -1
- package/dist/shell/unix-commands.js +1078 -50
- package/dist/substrate/lifo/commands/io/dd.js +1 -1
- package/dist/substrate/lifo/commands/net/curl.d.ts.map +1 -1
- package/dist/substrate/lifo/commands/net/curl.js +270 -54
- package/dist/substrate/lifo/commands/system/npm.d.ts +18 -1
- package/dist/substrate/lifo/commands/system/npm.d.ts.map +1 -1
- package/dist/substrate/lifo/commands/system/npm.js +25 -43
- package/dist/substrate/lifo/commands/text/head.d.ts.map +1 -1
- package/dist/substrate/lifo/commands/text/head.js +2 -1
- package/dist/substrate/lifo/commands/text/sed.d.ts.map +1 -1
- package/dist/substrate/lifo/commands/text/sed.js +499 -117
- package/dist/substrate/lifo/commands/types.d.ts +8 -4
- package/dist/substrate/lifo/commands/types.d.ts.map +1 -1
- package/dist/substrate/lifo/node-compat/zlib.d.ts +37 -18
- package/dist/substrate/lifo/node-compat/zlib.d.ts.map +1 -1
- package/dist/substrate/lifo/node-compat/zlib.js +122 -23
- package/dist/substrate/lifo/shell/interpreter.d.ts +9 -1
- package/dist/substrate/lifo/shell/interpreter.d.ts.map +1 -1
- package/dist/substrate/lifo/shell/interpreter.js +79 -29
- package/dist/substrate/lifo/shell/pipe.d.ts +16 -0
- package/dist/substrate/lifo/shell/pipe.d.ts.map +1 -1
- package/dist/substrate/lifo/shell/pipe.js +62 -18
- package/dist/substrate/lifo/shell/terminal-stdin.d.ts +20 -3
- package/dist/substrate/lifo/shell/terminal-stdin.d.ts.map +1 -1
- package/dist/substrate/lifo/shell/terminal-stdin.js +60 -24
- package/dist/vfs/sqlite-vfs.d.ts +19 -0
- package/dist/vfs/sqlite-vfs.d.ts.map +1 -1
- package/dist/vfs/sqlite-vfs.js +106 -23
- package/dist/workspace/nimbus-workspace.d.ts +22 -1
- package/dist/workspace/nimbus-workspace.d.ts.map +1 -1
- package/dist/workspace/nimbus-workspace.js +19 -3
- package/dist/workspace/supervisor-op.d.ts +107 -0
- package/dist/workspace/supervisor-op.d.ts.map +1 -0
- package/dist/workspace/supervisor-op.js +224 -0
- package/package.json +2 -2
- package/src/_shared/byte-stream.ts +5 -4
- package/src/_shared/real-node-imports.ts +8 -0
- package/src/_shared/tarball.ts +60 -5
- package/src/_shared/vfs-write-ledger.ts +22 -16
- package/src/runtime/comment-strip.ts +218 -52
- package/src/runtime/cpython-runner.ts +2 -1
- package/src/runtime/esbuild-service.ts +572 -372
- package/src/runtime/javascript-ast.ts +40 -9
- package/src/runtime/opentui-wasm-backend.ts +19 -17
- package/src/runtime/port-registry.ts +66 -8
- package/src/runtime/ruby-runner.ts +2 -0
- package/src/shell/stdin-adapter.ts +58 -0
- package/src/shell/unix-commands.ts +1054 -50
- package/src/substrate/lifo/commands/io/dd.ts +2 -2
- package/src/substrate/lifo/commands/net/curl.ts +310 -58
- package/src/substrate/lifo/commands/system/npm.ts +55 -38
- package/src/substrate/lifo/commands/text/head.ts +2 -1
- package/src/substrate/lifo/commands/text/sed.ts +519 -109
- package/src/substrate/lifo/commands/types.ts +8 -5
- package/src/substrate/lifo/node-compat/zlib.ts +155 -26
- package/src/substrate/lifo/shell/interpreter.ts +74 -27
- package/src/substrate/lifo/shell/pipe.ts +65 -24
- package/src/substrate/lifo/shell/terminal-stdin.ts +66 -30
- package/src/vfs/sqlite-vfs.ts +104 -23
- package/src/workspace/nimbus-workspace.ts +30 -3
- package/src/workspace/supervisor-op.ts +309 -0
|
@@ -317,26 +317,32 @@ async function __nimbusPersistVfsWrite(supervisor, path, content, snapshot) {
|
|
|
317
317
|
}
|
|
318
318
|
|
|
319
319
|
/**
|
|
320
|
-
* Write back
|
|
320
|
+
* Write back the cells parked at THIS instant, and only those.
|
|
321
321
|
*
|
|
322
|
-
*
|
|
323
|
-
*
|
|
324
|
-
*
|
|
325
|
-
*
|
|
326
|
-
*
|
|
327
|
-
*
|
|
328
|
-
*
|
|
322
|
+
* Bounded on purpose, and deliberately not routed through
|
|
323
|
+
* \`__nimbusDrainVfsWrites\`, whose \`while (pending > 0)\` waits for the mutation
|
|
324
|
+
* queue to be EMPTY. That wait is correct at process exit, where no new writes
|
|
325
|
+
* are coming. Anywhere else it is a livelock: a facet unpacking a tarball adds
|
|
326
|
+
* mutations faster than the loop retires them, so the loop never returns.
|
|
327
|
+
* Sited ahead of egress — where it was — that stopped the request from ever
|
|
328
|
+
* leaving the facet, and \`npx sv create\` ran, printed its intro, and then
|
|
329
|
+
* never reported an exit at all. A barrier may delay a request; it may not
|
|
330
|
+
* wait on a condition a busy process never reaches.
|
|
331
|
+
*
|
|
332
|
+
* Failures are retained rather than thrown. The two callers — the debounce
|
|
333
|
+
* below, and the RELEASE barrier ahead of egress — have no frame that could
|
|
334
|
+
* act on one: rejecting the fetch that happened to trigger the flush would
|
|
335
|
+
* blame the wrong operation. The exit drain reports what is retained, so a
|
|
336
|
+
* lost write is loud exactly once and never silent.
|
|
329
337
|
*/
|
|
330
338
|
async function __nimbusFlushVfsWriteBack(supervisor) {
|
|
331
339
|
if (!supervisor) return;
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
+
const paths = Object.keys(__vfsWrites);
|
|
341
|
+
if (paths.length === 0) return;
|
|
342
|
+
await Promise.allSettled(paths.map((path) => __nimbusFlushVfsWrite(
|
|
343
|
+
path,
|
|
344
|
+
(content, snapshot) => __nimbusPersistVfsWrite(supervisor, path, content, snapshot),
|
|
345
|
+
)));
|
|
340
346
|
}
|
|
341
347
|
|
|
342
348
|
/**
|
|
@@ -1,73 +1,239 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* One JavaScript source scanner shared by the two comment-stripping
|
|
3
|
+
* call sites — prefetch's import detection and the esbuild transform
|
|
4
|
+
* pipeline's classifiers.
|
|
3
5
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* comment
|
|
7
|
-
*
|
|
8
|
-
* `
|
|
9
|
-
* pipeline).
|
|
6
|
+
* `scanJsSource(src, literals)` walks `src` once and returns a
|
|
7
|
+
* byte-aligned copy in which `//` and `/* … *\/` comments are blanked
|
|
8
|
+
* (each comment becomes a space; newlines inside a block comment are
|
|
9
|
+
* preserved so line numbers still match the input). String, template
|
|
10
|
+
* and regex literals are what `literals` decides:
|
|
10
11
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
12
|
+
* - `'blank'`: literal content is replaced too — templates keep their
|
|
13
|
+
* `${…}` interpolation expression as code so a depth-tracked caller
|
|
14
|
+
* sees `await` etc. inside it. This is the transform pipeline's
|
|
15
|
+
* classification view: nothing quoted can read as an `import`.
|
|
16
|
+
* - `'keep'`: literals are copied verbatim. This is prefetch's
|
|
17
|
+
* import-detection view: IMPORT_RE/REQUIRE_RE must see the
|
|
18
|
+
* specifier string, and a `//` or `/*` inside a literal must NOT
|
|
19
|
+
* open a comment that swallows a following real import.
|
|
17
20
|
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
21
|
+
* The output is assembled from input slices and joined once. It used to
|
|
22
|
+
* be built one character at a time (`stripped += c`), which V8 keeps as
|
|
23
|
+
* a rope of one node per append — ~30 bytes of heap per character, all
|
|
24
|
+
* live until the string is first read. On typescript's 6.15 MB
|
|
25
|
+
* `lib/_tsc.js` that rope measured 174 MB against a 128 MB isolate —
|
|
26
|
+
* the session Durable Object was killed inside `tsc`'s spawn before the
|
|
27
|
+
* facet existed. Spans hold the input, the output and a short array.
|
|
23
28
|
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
* so it's a minor wasted-work cost — see IMPORT_RE header comment in
|
|
28
|
-
* `require-resolver.ts:84-86`.
|
|
29
|
-
*
|
|
30
|
-
* TODO(CLN-X): when the `src/runtime/esbuild-service.ts` anti-touch
|
|
31
|
-
* window opens, unify with the canonical
|
|
32
|
-
* `stripCommentsAndStrings(src)` helper there. Both implement the
|
|
33
|
-
* same logical pass over comments; only the string/regex-literal
|
|
34
|
-
* handling differs.
|
|
29
|
+
* Serialized by name: `generateEsbuildTransformRuntimeSource` embeds
|
|
30
|
+
* this function's `.toString()` in the transform runtime, so every
|
|
31
|
+
* constant it reads is declared inside the body.
|
|
35
32
|
*/
|
|
36
|
-
export function
|
|
37
|
-
|
|
33
|
+
export function scanJsSource(src: string, literals: 'keep' | 'blank'): string {
|
|
34
|
+
const NEWLINE = 0x0a;
|
|
35
|
+
// Identifier-suffix detection: `/` after one of these is division;
|
|
36
|
+
// after anything else (operators, punctuators, keywords, start-of-file)
|
|
37
|
+
// it opens a regex literal. Word chars + `)` + `]` cover `foo()/x` and
|
|
38
|
+
// `a[i]/y`; the quote characters cover `'…' /re/` and `` `…` /re/ ``.
|
|
39
|
+
const DIVISION_AFTER = /[A-Za-z0-9_$\)\]'\"`]/;
|
|
40
|
+
|
|
41
|
+
const parts: string[] = [];
|
|
42
|
+
// Start of the span not yet copied to `parts`.
|
|
43
|
+
let spanStart = 0;
|
|
38
44
|
let i = 0;
|
|
39
45
|
const N = src.length;
|
|
46
|
+
let lastNonWs = '';
|
|
47
|
+
const record = (ch: string) => {
|
|
48
|
+
if (ch !== ' ' && ch !== '\t' && ch !== '\n' && ch !== '\r') lastNonWs = ch;
|
|
49
|
+
};
|
|
50
|
+
// The division/regex discriminator needs the last non-ws char the loop
|
|
51
|
+
// has passed — stepped chars record themselves; spans already landed in
|
|
52
|
+
// `parts` only need their final char re-derived.
|
|
53
|
+
const step = () => { record(src[i]); i++; };
|
|
54
|
+
const copy = (end: number) => {
|
|
55
|
+
if (end > spanStart) parts.push(src.slice(spanStart, end));
|
|
56
|
+
};
|
|
57
|
+
const emit = (ch: string) => { parts.push(ch); };
|
|
58
|
+
|
|
59
|
+
// A shebang is the file's first line and never a comment or a regex —
|
|
60
|
+
// `#!/` at offset 0 is copied whole before the loop sees the `/`.
|
|
61
|
+
if (src.charCodeAt(0) === 0x23 && src.charCodeAt(1) === 0x21) {
|
|
62
|
+
i = 2;
|
|
63
|
+
while (i < N && src.charCodeAt(i) !== NEWLINE) i++;
|
|
64
|
+
record('!');
|
|
65
|
+
}
|
|
66
|
+
|
|
40
67
|
while (i < N) {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
68
|
+
if (src.charCodeAt(i) === 0x2f /* / */) {
|
|
69
|
+
const next = src.charCodeAt(i + 1);
|
|
70
|
+
if (next === 0x2f) {
|
|
71
|
+
// Line comment: to end-of-line, one space. The newline itself is
|
|
72
|
+
// not part of the comment and stays in the next span.
|
|
73
|
+
copy(i);
|
|
74
|
+
i += 2;
|
|
75
|
+
while (i < N && src.charCodeAt(i) !== NEWLINE) i++;
|
|
76
|
+
emit(' ');
|
|
77
|
+
spanStart = i;
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
if (next === 0x2a) {
|
|
81
|
+
// Block comment: replaced by its own newlines plus one space; an
|
|
82
|
+
// unterminated one runs to the end of input and gets no space.
|
|
83
|
+
copy(i);
|
|
84
|
+
i += 2;
|
|
85
|
+
let newlines = 0;
|
|
86
|
+
let closed = false;
|
|
87
|
+
while (i < N) {
|
|
88
|
+
const bc = src.charCodeAt(i);
|
|
89
|
+
if (bc === NEWLINE) newlines++;
|
|
90
|
+
else if (bc === 0x2a && src.charCodeAt(i + 1) === 0x2f) { i += 2; closed = true; break; }
|
|
91
|
+
i++;
|
|
92
|
+
}
|
|
93
|
+
if (newlines > 0) parts.push('\n'.repeat(newlines));
|
|
94
|
+
if (closed) emit(' ');
|
|
95
|
+
spanStart = i;
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
// Regex literal when the previous non-ws char can't end a value.
|
|
99
|
+
if (!DIVISION_AFTER.test(lastNonWs)) {
|
|
100
|
+
// A regex needs its closing `/` on the same line; without one the
|
|
101
|
+
// slash is division (or a lone `/`), and treating the rest of the
|
|
102
|
+
// line as a literal would drop real code — imports included.
|
|
103
|
+
let j = i + 1;
|
|
104
|
+
let closes = false;
|
|
105
|
+
while (j < N) {
|
|
106
|
+
const rc = src.charCodeAt(j);
|
|
107
|
+
if (rc === 0x5c) { j += 2; continue; }
|
|
108
|
+
if (rc === 0x5b) {
|
|
109
|
+
j++;
|
|
110
|
+
while (j < N && src.charCodeAt(j) !== 0x5d) {
|
|
111
|
+
if (src.charCodeAt(j) === 0x5c) { j += 2; continue; }
|
|
112
|
+
j++;
|
|
113
|
+
}
|
|
114
|
+
if (j < N) j++;
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
if (rc === 0x2f) { closes = true; break; }
|
|
118
|
+
if (rc === NEWLINE) break;
|
|
119
|
+
j++;
|
|
120
|
+
}
|
|
121
|
+
if (!closes) { step(); continue; }
|
|
122
|
+
copy(i);
|
|
123
|
+
emit(' ');
|
|
124
|
+
i++;
|
|
125
|
+
while (i < N) {
|
|
126
|
+
const rc = src.charCodeAt(i);
|
|
127
|
+
if (rc === 0x5c) { i += 2; continue; }
|
|
128
|
+
if (rc === 0x5b) {
|
|
129
|
+
// Character class: `/` inside it is content.
|
|
130
|
+
i++;
|
|
131
|
+
while (i < N && src.charCodeAt(i) !== 0x5d) {
|
|
132
|
+
if (src.charCodeAt(i) === 0x5c) { i += 2; continue; }
|
|
133
|
+
i++;
|
|
134
|
+
}
|
|
135
|
+
if (i < N) i++;
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
if (rc === 0x2f) { i++; break; }
|
|
139
|
+
i++;
|
|
140
|
+
}
|
|
141
|
+
// Flags: g, i, m, s, u, y, d.
|
|
142
|
+
while (i < N && /[gimsuyd]/.test(src[i])) i++;
|
|
143
|
+
record('/');
|
|
144
|
+
spanStart = i;
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
// Division or a lone slash — plain source.
|
|
148
|
+
step();
|
|
48
149
|
continue;
|
|
49
150
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
151
|
+
|
|
152
|
+
const ch = src[i];
|
|
153
|
+
if (ch === '"' || ch === "'" || ch === '`') {
|
|
154
|
+
if (literals === 'keep') {
|
|
155
|
+
i++;
|
|
156
|
+
while (i < N) {
|
|
157
|
+
const cc = src[i];
|
|
158
|
+
if (cc === '\\') { i += 2; continue; }
|
|
159
|
+
if (cc === ch) { i++; break; }
|
|
57
160
|
i++;
|
|
58
|
-
continue;
|
|
59
161
|
}
|
|
60
|
-
|
|
162
|
+
// The literal ends a value: a following `/` is division.
|
|
163
|
+
record(ch);
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
// blank: the delimiters and content become one space; a template's
|
|
167
|
+
// `${…}` interpolation keeps its expression as code.
|
|
168
|
+
copy(i);
|
|
169
|
+
emit(' ');
|
|
170
|
+
i++;
|
|
171
|
+
while (i < N) {
|
|
172
|
+
const cc = src[i];
|
|
173
|
+
if (cc === '\\') { i += 2; continue; }
|
|
174
|
+
if (cc === ch) { i++; break; }
|
|
175
|
+
if (ch === '`' && cc === '$' && src[i + 1] === '{') {
|
|
176
|
+
emit('${');
|
|
61
177
|
i += 2;
|
|
62
|
-
|
|
63
|
-
|
|
178
|
+
let depth = 1;
|
|
179
|
+
while (i < N && depth > 0) {
|
|
180
|
+
const ic = src[i];
|
|
181
|
+
// Nested string inside the interpolation: blank its content
|
|
182
|
+
// so a `}` inside it doesn't drop the depth early.
|
|
183
|
+
if (ic === '"' || ic === "'" || ic === '`') {
|
|
184
|
+
const iq = ic;
|
|
185
|
+
emit(' ');
|
|
186
|
+
i++;
|
|
187
|
+
while (i < N) {
|
|
188
|
+
const icc = src[i];
|
|
189
|
+
if (icc === '\\') { i += 2; continue; }
|
|
190
|
+
if (icc === iq) { i++; break; }
|
|
191
|
+
// A nested template's own ${…} recurses once more —
|
|
192
|
+
// deeper nesting falls back to brace counting.
|
|
193
|
+
if (iq === '`' && icc === '$' && src[i + 1] === '{') {
|
|
194
|
+
emit('${');
|
|
195
|
+
i += 2;
|
|
196
|
+
let d2 = 1;
|
|
197
|
+
while (i < N && d2 > 0) {
|
|
198
|
+
const i2 = src[i];
|
|
199
|
+
if (i2 === '{') d2++;
|
|
200
|
+
else if (i2 === '}') d2--;
|
|
201
|
+
if (d2 > 0) emit(i2);
|
|
202
|
+
i++;
|
|
203
|
+
}
|
|
204
|
+
emit('}');
|
|
205
|
+
continue;
|
|
206
|
+
}
|
|
207
|
+
if (icc === '\n') emit('\n');
|
|
208
|
+
i++;
|
|
209
|
+
}
|
|
210
|
+
continue;
|
|
211
|
+
}
|
|
212
|
+
if (ic === '{') depth++;
|
|
213
|
+
else if (ic === '}') depth--;
|
|
214
|
+
if (depth > 0) emit(ic);
|
|
215
|
+
i++;
|
|
216
|
+
}
|
|
217
|
+
emit('}');
|
|
218
|
+
continue;
|
|
64
219
|
}
|
|
220
|
+
if (cc === '\n') emit('\n');
|
|
65
221
|
i++;
|
|
66
222
|
}
|
|
223
|
+
spanStart = i;
|
|
67
224
|
continue;
|
|
68
225
|
}
|
|
69
|
-
|
|
70
|
-
i++;
|
|
226
|
+
step();
|
|
71
227
|
}
|
|
72
|
-
|
|
228
|
+
copy(N);
|
|
229
|
+
return parts.join('');
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Strip comments for import/require detection. Literals are kept: the
|
|
234
|
+
* specifier the regexes extract lives inside a string, and a comment
|
|
235
|
+
* marker inside a string must not swallow the code that follows it.
|
|
236
|
+
*/
|
|
237
|
+
export function stripCommentsForImports(src: string): string {
|
|
238
|
+
return scanJsSource(src, 'keep');
|
|
73
239
|
}
|
|
@@ -230,6 +230,7 @@ async function cpythonRunFacetFn(
|
|
|
230
230
|
* that has none does not get a degraded version — it gets none, and says so.
|
|
231
231
|
*/
|
|
232
232
|
export type CPythonResidentStart = (spawn: {
|
|
233
|
+
argv: string[];
|
|
233
234
|
/** VFS path of the interpreter. By path, not by value: it is 10.6 MiB. */
|
|
234
235
|
wasmVfsPath: string;
|
|
235
236
|
startArgs: Record<string, unknown>;
|
|
@@ -474,7 +475,7 @@ export function makeCPythonRunnerFactory(deps: {
|
|
|
474
475
|
const command = [binName, ...argv].map((part) =>
|
|
475
476
|
(/^[A-Za-z0-9_./:=@+-]+$/.test(part) ? part : JSON.stringify(part))).join(' ');
|
|
476
477
|
const spawnResult = await deps.startResident(
|
|
477
|
-
{ wasmVfsPath: wasmVfs, startArgs: facetArgs, cwd, command });
|
|
478
|
+
{ wasmVfsPath: wasmVfs, startArgs: facetArgs, cwd, command, argv: [binName, ...argv] });
|
|
478
479
|
if (spawnResult.stdout) ctx.stdout.write(spawnResult.stdout);
|
|
479
480
|
if (spawnResult.stderr) ctx.stderr.write(spawnResult.stderr);
|
|
480
481
|
return spawnResult.exitCode;
|