feat(code-runtime): execute Node programs through confined processes

This commit is contained in:
Tianyi Cui committed 2026-09-12 15:03:01 +08:00
1 parent f95f7ec8dc
commit 75ed8da3e0
54 files changed
+1933 -2277

No files matched your search

@@ -146,10 +146,10 @@ describe('PythonCodeRuntime — controlled subprocess pipes', () => {
const ctx = new Context()
const fiber = await ctx.plugin(PythonCodeRuntime)
const runtime = ctx.codeRuntime as InstanceType<typeof PythonCodeRuntime>
const run = runtime.run({
const run = runtime.run(runtime.resolve({
program: 'return 1',
bindings: [{ global: 'tools', functions: { echo: async (value: unknown) => value as number } }],
})
}))
onTestFinished(async () => {
await fiber.dispose()
await run
@@ -210,7 +210,7 @@ describe('PythonCodeRuntime — controlled subprocess pipes', () => {
const fiber = await ctx.plugin(PythonCodeRuntime)
const runtime = ctx.codeRuntime as InstanceType<typeof PythonCodeRuntime>
const result = await runtime.run({ program: 'return 1', bindings: [] })
const result = await runtime.run(runtime.resolve({ program: 'return 1', bindings: [] }))
expect(result.error?.kind).toBe('worker-exit')
expect(result.error?.message).toContain('failed to boot python subprocess')
@@ -240,7 +240,7 @@ describe('PythonCodeRuntime — controlled subprocess pipes', () => {
const fiber = await ctx.plugin(PythonCodeRuntime)
const runtime = ctx.codeRuntime as InstanceType<typeof PythonCodeRuntime>
const result = await runtime.run({ program: 'return 1', bindings: [] })
const result = await runtime.run(runtime.resolve({ program: 'return 1', bindings: [] }))
expect(result.error?.kind).toBe('worker-exit')
expect(result.error?.message).toContain('python spawn error')
@@ -258,7 +258,7 @@ describe('PythonCodeRuntime — controlled subprocess pipes', () => {
const fiber = await ctx.plugin(PythonCodeRuntime)
const runtime = ctx.codeRuntime as InstanceType<typeof PythonCodeRuntime>
const result = await runtime.run({ program: 'return 1', bindings: [] })
const result = await runtime.run(runtime.resolve({ program: 'return 1', bindings: [] }))
expect(result.error?.kind).toBe('worker-exit')
expect(result.error?.message).toContain('failed to boot python subprocess')
@@ -275,7 +275,7 @@ describe('PythonCodeRuntime — controlled subprocess pipes', () => {
const fiber = await ctx.plugin(PythonCodeRuntime)
const runtime = ctx.codeRuntime as InstanceType<typeof PythonCodeRuntime>
const result = await runtime.run({ program: 'return 1', bindings: [] })
const result = await runtime.run(runtime.resolve({ program: 'return 1', bindings: [] }))
expect(result.error?.kind).toBe('worker-exit')
expect(result.error?.message).toContain('python spawn error')
@@ -302,10 +302,10 @@ describe('PythonCodeRuntime — controlled subprocess pipes', () => {
const fiber = await ctx.plugin(PythonCodeRuntime, { maxWallMs: 3000 })
const runtime = ctx.codeRuntime as InstanceType<typeof PythonCodeRuntime>
const result = await runtime.run({
const result = await runtime.run(runtime.resolve({
program: 'return 1',
bindings: [{ global: 'tools', functions: { f: async () => 'x'.repeat(4 * 1024 * 1024) } }],
})
}))
expect(result.error?.kind).toBe('timeout')
// The drain wait settled on `close` and cleaned up after itself. The
File diff suppressed because it is too large. Load diff
@@ -39,10 +39,10 @@ it('seals stray fragments without recopying the sealed prefix', async () => {
return realConcat(list, total)
})
try {
const result = await ctx.codeRuntime.run({
const result = await ctx.codeRuntime.run(ctx.codeRuntime.resolve({
program: 'import os\nos.write(1, b"x" * 60000 + b"\\n")\nreturn "done"',
bindings: [],
})
}))
expect(result.error).toBeUndefined()
expect(result.value).toBe('done')
expect(result.logs).toEqual(['x'.repeat(60_000)])
@@ -70,10 +70,10 @@ it.each([
return merged
})
try {
const result = await ctx.codeRuntime.run({
const result = await ctx.codeRuntime.run(ctx.codeRuntime.resolve({
program: `import os\nos.write(1, ${payload})\nreturn None`,
bindings: [],
})
}))
expect(result.error).toBeUndefined()
expect(result.logs.at(-1)).toBe(logTruncationMarker(3072))
// Each raw byte decodes to U+FFFD (three UTF-8 bytes), so a 3072-byte