# @absolutejs/isolated-jsc 中文文档

规范地址：https://npmcn.com/package/%40absolutejs/isolated-jsc/

版本：0\.15\.0
npm 元数据更新时间：2026-11-03T09:30:08.813Z
中文译文更新时间：2026-11-06T14:07:00.204Z
软件包许可：BSL-1\.1

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40absolutejs/isolated-jsc
原文对照：https://npmcn.com/package/%40absolutejs/isolated-jsc/?lang=original
项目主页：https://github.com/absolutejs/isolated-jsc
源码仓库：https://github.com/absolutejs/isolated-jsc

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：860 kB，43 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- 运行依赖：1 个
- 首次发布：2026-05-27T08:11:14.853Z
- 最新版本发布：2026-11-03T09:30:08.442Z
- 近 30 天下载量：3052（2026-10-05 至 2026-11-03，npm 官方下载统计）
- 已发布版本数：54（近 12 个月 54 个）

## 中文简介

JavaScript Core-native sandbox for Bun – 大量同位化执行不可信代码,孤立-vm-形状的 API

## 安装

```sh
npm install @absolutejs/isolated-jsc
```

也可以使用：`pnpm add @absolutejs/isolated-jsc`、`yarn add @absolutejs/isolated-jsc`、`bun add @absolutejs/isolated-jsc`

## README

# @absolutejs/同化-jsc

> JavaScript Core-native sandbox for Bun. 中国植物物种信息数据库. 无信任代码的重同位化执行,带有 `isolated-vm`\- 形状的API.

```ts
import { createIsolate, Reference } from "@absolutejs/isolated-jsc";

const isolate = await createIsolate({ memoryLimit: 64 });
const context = await isolate.createContext();

await context.setGlobal(
  "log",
  new Reference((msg) => console.log("[tenant]", msg)),
);

const script = await isolate.compileScript('await log("hello"); 1 + 1');
const result = await script.run(context, { timeout: 500 });
// result === 2

await isolate.dispose();
```

## 为什么会这样

Bun没有相当于Node的 [`isolated-vm`](https://github.com/laverdet/isolated-vm). 节点库是 V8 的特异性——它与 V8 的链接 `HasCustomHostObject` ABI 符号——和 Bun 使用 [Java 脚本公司](https://trac.webkit.org/wiki/JavaScriptCore),而不是 V8 键。 这么说吧 `bun install isolated-vm` 成功,则 `import` 失败 `undefined symbol: HasCustomHostObject`。 。 。 .

这使得整个类别的应用程序被困于节点:

-   **AI特工代码执行.** 安东尼 `code_execution`,OpenAI代码解释器,每个"运行这个 LLM 生成的片段"工具——它们都需要一个堆积同位化的运行时间,硬资源限制. ()[烤箱-sh/bun#25929](https://github.com/oven-sh/bun/issues/25929)(中文(简体) )
-   **多租借书写.** Cloudflare -Workers风格的"你的客户写了一些JS,运行范围到他们的账户"
-   **对不可信插件的构建时间评价.** (单位:千美元)[烤箱/箱# 23653](https://github.com/oven-sh/bun/issues/23653)(中文(简体) )
-   **沙箱一般许可.** (单位:千美元)[烤箱-sh/bun#6617](https://github.com/oven-sh/bun/issues/6617)(中文(简体) )

`@absolutejs/isolated-jsc` 填补了这一空白。 见 [(原始内容存档于2018-10-21) (英语). BUN POLING. md](https://npmcn.com/package/%40absolutejs/isolated-jsc/BUN_POSITIONING.md) 以邦为重点的战略框架, [二、结 论](https://npmcn.com/package/%40absolutejs/isolated-jsc/ISSUES_WILL_CLOSE.md) 该图书馆的上游问题 _关闭_,以及 [(原始内容存档于2012-10-21). UPSTREAM ISSUES.md](https://npmcn.com/package/%40absolutejs/isolated-jsc/UPSTREAM_ISSUES.md) 对于上游 Bun bugs 此库 _工作周围_ (每件被固定时有清理指示). 见 [缩写 FROM 标准化 VM.md](https://npmcn.com/package/%40absolutejs/isolated-jsc/MIGRATING_FROM_ISOLATED_VM.md) 用于节点 `isolated-vm` 到 Bun 迁移路径 。 见 [警卫](https://npmcn.com/package/%40absolutejs/isolated-jsc/SECURITY.md) 威胁模型 和更硬化的指导。 见 [科学与研究](https://npmcn.com/package/%40absolutejs/isolated-jsc/SNAPSHOT_RESEARCH.md) 用于JavaScriptCore检查站研究. 见 [变动情况](https://npmcn.com/package/%40absolutejs/isolated-jsc/CHANGELOG.md) 用于发行笔记.

## 快速回答

**为什么不是节点 `isolated-vm`? 吗?** 它对于Node/V8来说是正确的形状,但Bun是JavaScriptCore. `isolated-jsc` 将隔离形状的 API 移植到 Bun/JSC ,而不是试图加载一个 V8 加通 .

**为什么不用邦工人?** 工人是可移植底物和倒置后端. 此套件添加了沙盒产品层:硬化的全局,堆积限制,超时,度量,错误的忠诚度,TypeScript帮助器,池,以及明确的主机能力经纪人.

**我什么时候需要FFI?** 需求 `backend: "ffi"` 用于在 macOS 或 Linux 有 JavaScriptCore 的敌对代码生产路径。 使用 `backend: "auto"` 用于便携式默认、演示和CI。 当沙盒出逃会暴露有意义的主机秘密时,添加进程/容器/界面/网络边界.

## 今天的什么船(v0.12.2)

`@absolutejs/isolated-jsc` 运行在一个API后的两个可互换后端上:

-   **FFI 后端( 当 libJSC 可达时默认)** - 谈话 `libJavaScriptCore` 直接通过 `bun:ffi`. Cold heap ~ 300 KB, CPU 超时使用 JSC 中断驱动的监视器( 超时 Error 后隔离持续运行),以及 `(0, eval)('X')` 编号 : `new Function('return X')()` 完全通过 `JSGlobalContextSetEvalEnabled`。在 macOS (系统框架) + Linux 上可用 `libjavascriptcoregtk-4.1-0` 或者说 `libjavascriptcoregtk-6.0-1` 已安装.
    
-   **工人后端( 后退)** - 一个邦 `Worker` 每个隔离。 其工人-当地JSC群起于1.3.x号机上大约1MB;工人全过程足迹较大. 超时终止整个隔离. 总是可用的( 不依赖系统) 。 在Windows和任何没有 libJSC 的 Linux 上默认 .
    

二者各分大众相. 明确选择 `createIsolate({ backend: 'ffi' | 'worker' | 'auto' })`,或让 `'auto'` (默认)LibJSC探测器并倒回工人. 两个后端:

-   **收缩隔离.** 每个 `Isolate` 经营自己的Bun Worker – 自己的JSC VM – 自己的GC堆积. 不与主机或对等隔离共享内存 .
-   **`isolated-vm`\- 形状的API.** `Isolate`, (中文(简体) ), `Context`, (中文(简体) ), `Script`, (中文(简体) ), `Reference`, (中文(简体) ), `ExternalCopy`方便港务.
-   **长城超时.** `script.run(context, { timeout: 500 })` 毫秒精度,通过主机执行 `Worker.terminate()`.v1取舍:超时终止了整个隔离(如果需要再生的话在应用层集合).
-   **内存极限.** 软盖通过工人——当地——每50 ms投票 `bun:jsc.heapSize()`不包括东道国和同行工作者的分配。 违反命令会致命且自我终止;主机拒绝等待执行的行动 `MemoryLimitError`。 。 。 .
-   **硬化沙盒默认(T2.1,0.1中为新).** 东道主能力全球- `fetch`, (中文(简体) ), `Bun`, (中文(简体) ), `process`, (中文(简体) ), `Worker`, (中文(简体) ), `WebSocket`编辑器 `postMessage` 编号 : `addEventListener`, (中文(简体) ), `navigator`贮藏室 从沙盒取出 用户代码无法通过赤裸的检查到达它们, `globalThis.X`, (中文(简体) ), `this.X`,或直接 `eval('X')` (关于工人后端, 间接 eval 和动态 `import()` 仍然到达主机权限, 除非运行时间可以锁定隔离; 见 [警卫](https://npmcn.com/package/%40absolutejs/isolated-jsc/SECURITY.md#the-worker-backend-is-not-a-boundary-for-hostile-code) 财务报告和审定财务报表 `requireLockdown`)),纯JS内置(Math,JSON,承诺,打入阵列的套房)和安全的Web原始人(URL,Text Encoder,Web Crypto, setTimeout, Cope)仍然可以接触. 通过 `harden: false` ,或通过 `unsafelyExposeGlobals: ['fetch']`。 。 。 .
-   **可调用 `Reference`编号.** 向隔离区显示主机功能 。 工人后端: 通过 Async 消息传递( 使用) 拨打总是往返 `await` 在孤立的一侧。 FFI 后端 (0. 3+):同步主机 fns 直接通过 per Reference 返回其值 `JSCallback`. Async(承诺返回)主机fns在FFI(0.4+)上也工作——跑者交替向 Bun 事件回路发售,并排出 JSC 的微任务排队,直到承诺实现为止,以 `Script.run`是因为 `timeout`。 。 。 .
-   **`ExternalCopy`** 用于标出大型主机侧值,用于便宜的通过.
-   **可选的受限控制台抓取.** `onConsole` 路由隔离 `console.log` 唤回主机. `maxConsoleEntries` 财务报告和审定财务报表 `maxConsoleBytes` 已发送日志,收据报告过多.
-   **一级隔离池(T2.2,0.1中新增).** `createIsolatePool({ isolate, maxSize, idleMs, recycleAfter })` 返回一个按键池——每个按键懒惰的产卵,跨呼号的再利用,LRU在上限下被驱出,隔离自灭后透明再生,可配置后N召回来捆绑JSC堆积物. 更换每张消费卷的按租户计价的明细图.
-   **上下文种子+数据检查点(T2.3,0.1为新;0.8.19为扩展;收件增加为0.8.21).** `createContext({ seed, snapshot })` 仍然恢复旧的平地快照,和 `createContext({ seed, checkpoint })` 从 `context.checkpoint({ maxBytes, include, exclude })`. 检查站携带 `schemaVersion`,后端,字节长度,包含/已删除的计数,以及跳过的关键原因. `context.checkpointWithReceipt()` 财务报告和审定财务报表 `isolate.createContextWithReceipt()` 生产 schema-v1 `CheckpointReceipt`编号 - `operation: "create" | "restore"`, (中文(简体) ), `executionId`, (中文(简体) ), `durationMs`合计 `skippedReasons`选择 `purpose`编号 :`tenant`编号 :`policy` 审计工作流程的标签。 这是一个数据检查点, 不是 JSC 堆积暂停/ 重现图像 ; 见 [科学与研究](https://npmcn.com/package/%40absolutejs/isolated-jsc/SNAPSHOT_RESEARCH.md)。 。 。 .
-   **忠诚错误( T2.4, 0.1 有新内容) .** 向隔开的回合中抛出错误 `error.cause` (倒行逆施)和可自有地产完整. 自定义错误子类实例数据( E)`HttpError` 与 `.statusCode`等)活下来. `instanceof` 无法跨越边界; 使用 `.name` 编号 : `.code` 检查.
-   **人均运行遥测(T2.4,0.1中为新).** `script.runWithMetrics(ctx, opts)` 返回时 `{ result, metrics: { backend, cpuMs, heapBytes } }` 用于计费/仪表板/每个呼叫监测。 平面 `run()` 仍然返回赤色值.
-   **处决收据.** `script.runWithReceipt()`, (中文(简体) ), `callable.callWithReceipt()`, (中文(简体) ), `runIsolated(..., { withReceipt: true })`中,运行者接收模式将本地审计记录与 `schemaVersion: 1`,执行 id,后端,政策,资源设置,时间,输出大小,限值能力调用摘要,以及空出事件计数.
-   **能力审计编辑.** 经纪人支持默认 `redactAuditInput` 编号 : `redactAuditOutput` 钩子,每个工具都可以在审计事件击中日志或收据之前覆盖它们.
-   **能力审计缓冲器.** `createCapabilityAuditBuffer({ maxEvents })` 给应用程序一个接收准备 `onAudit` 下沉中带有明显的切换元数据,避免当沙盒代码垃圾邮件主机工具时进行未绑定的内置审计阵列.
-   **能力输出限制.** 设定 `maxOutputBytes` 每个能力或 `defaultMaxOutputBytes` 一个经纪人拒绝超大的主机工具输出 `CapabilityError` 在他们回到沙盒代码之前.
-   **结果大小限制.** 过 `maxResultBytes` 在运行的选项中拒绝超大的成功产出 `ResultSizeError` 在应用代码接受之前.
-   **控制台输出限制 .** 过 `maxConsoleEntries` 编号 : `maxConsoleBytes` 当创建隔离点时,可以将捕获到的超量控制台事件和表面溢出旗子降入收款.
-   **后端可观察.** `isolate.backend` 报告已解决的后端( e)`"ffi"` 或者说 `"worker"`, (中文(简体) ), `runWithMetrics()` 编号 : `callWithMetrics()` 包含 `metrics.backend`,以及 `isolated-jsc doctor --json` 发布机器可读后端探测器细节.
-   **政策方略.** `createIsolate({ policy: "ai-tool" | "tenant-script" | "plugin" | "trusted" })` 应用标准化隔离/运行默认值. `resolveIsolatePolicy(name, overrides?)` 返回相同的策略对象加一 `recipe` 带有建议的结果限制、控制台限制、审计缓冲盖、经纪人盖和跑道池设置。 帮助构建者, 如 `policyAuditOptions(policy)`, (中文(简体) ), `policyBrokerOptions(policy)`, (中文(简体) ), `policyConsoleOptions(policy)`, (中文(简体) ), `policyRunOptions(policy)`,以及 `policyRunnerOptions(policy)` 将这些建议变成周边API的防复制选项.
-   **一发一枪处死.** `runIsolated(source, { policy, globals, context, run, withMetrics })` 覆盖不需要直接管理隔离生命周期的请求/响应路径.
-   **可重复使用的跑道.** `createIsolatedRunner({ policy, globals, pool })` 用钥匙隔离热租户/会议/谈判路径的再利用。 使用 `runner.run()` 用于新文本源执行, `runner.precompile()` 以温和的饮料盟誓, `runner.call()` 每次按密钥/名称编译一次并反复拨打 `runner.stats()` 检查池子/笼子大小.

### Bun沙箱决策指南

| 使用大小写 | 选择 | 为什么 |
| --- | --- | --- |
| 本地开发、演示、CI烟雾测试或没有libJSC的平台 | `backend: "auto"` | 可用时使用FFI,不可用时使用Worker,因此,同一代码到处运行. |
| 在 macOS 或 Linux 在其中安装 JavaScript Core 的不可信代码 | `backend: "ffi"` | 最低的冷堆积,中断驱动的CPU超时,隔离活生生的超时,并关闭了eval / 函数构件残存. |
| 在没有系统JavaScriptCore的 Windows 或主机上生产不可信代码 | 工人落后于进程/容器边界 | 工人保持堆积隔离和资源封顶,但敌对的工作量不应共享主机机密或广泛的网络/文件权限. |
| 需要明确主机权限的用户插件 | FFI 加上 `Reference` /能力经纪人 | 保留"沙盒"全球小并只曝光经验证,经审计的主机工具. |
| 高价值机密、任意第三方代码或网络相邻工作量 | FFI + 工艺、容器、设备、分包和网络入侵政策 | JavaScript隔离是一层;OS隔离仍然拥有爆炸-辐射控制. |
| 仅需要取消或租户级集合的可信应用代码 | 工人或FFI人才库 | 安全态势较少重要;优化部署范围和业务简单. |

拇指规则:使用 `backend: "ffi"` 用于敌对码生产路径, `backend: "auto"` 对于便携式默认值,当沙盒出逃会暴露有意义的主机机密时,则加入OS/处理隔离.

### 它是什么ISN't(诚实限制每后端)

| 路径 | FFI 后端 | 工人后端 |
| --- | --- | --- |
| `fetch(url)` (空地) | **未定义** | **未定义** |
| `Bun.spawn(...)` (空地) | **未定义** | **未定义** |
| `globalThis.fetch` 编号 : `globalThis.Bun` | **未定义** | **未定义** |
| `this.Bun` | **未定义** | **未定义** |
| `eval('Bun')` (直接) | **块** (eval 已禁用文本) | **未定义** |
| `(0, eval)('Bun')` (间接) | **块** | 已锁定: 已丢失; 库存 Bun: 可达到 |
| `new Function('return Bun')()` | **块** | 已锁定: 已丢失; 库存 Bun: 可达到 |
| `import('node:child_process')` 编号 : `import('bun:ffi')` | **无模块加载器** | 已锁定: 拒绝; 库存 Bun : **可达到,即使没有 eval** (见 [警卫](https://npmcn.com/package/%40absolutejs/isolated-jsc/SECURITY.md#the-worker-backend-is-not-a-boundary-for-hostile-code)(中文(简体) ) |
| `Math.PI` 编号 : `JSON.stringify` 编号 : `Promise` 编号 : `crypto.randomUUID` | 可达到 | 可达到 |
| `URL` 编号 : `TextEncoder` 编号 : `WebSocket` | **未见** (只有JSC API,没有Web API) | 可达( Bun Worker 曝光 Web API) |
| 冷JSC堆积 | ~300 KB 键 | ~1 MB 键 |
| 超时行为 | (a) 将例外情形列入文字; **隔离持续运行** | 隔离死亡,必须重生 |
| 内存盖 | 监督者 `heapCapacity`; 过期终止 | 调查50 ms;终止整个隔离 |
| 通过引用同步主机 fns | **支持** (直接返回) | 总是包裹在 `await` |
| 阿辛克语( A)`Promise`(通过引用)主机 fns | **支持** (0.4+)——被泵入安置地,以 `timeout` | 支持通过 `await` |
| 不同背景的原型隔离 | 每个租户一个隔离 | 每个租户一个隔离 |

### FFI 后端安装注释

-   **马科斯**:零安装. JavaScript Core 是一个系统框架,位于 `/System/Library/Frameworks/JavaScriptCore.framework`。 。 。 .
-   **链接** (德比安/乌本图: `sudo apt install libjavascriptcoregtk-4.1-0` (8 MB / 31 MB 已安装).
-   **链接** (费多拉): `sudo dnf install webkit2gtk4.1`。 。 。 .
-   **已安装 Playwright 的 Linux**我们接受Playwright的捆绑 `libjavascriptcoregtk-6.0.so.1` - 没有额外安装.
-   **窗口**:不支持(没有系统 JSC,没有现实的分发路径). `createIsolate({ backend: 'auto' })` 自动返回工人; `backend: 'ffi'` 掷出 `JscLibraryNotFoundError`。 。 。 .

## API 密码

```ts
import {
  createCapabilityAuditBuffer,
  createCapabilityBroker,
  defineCapabilityTool,
  compileTypeScriptCallable,
  compileTypeScriptCallableFile,
  compileTypeScriptFile,
  createIsolate,
  createIsolatedRunner,
  policyAuditOptions,
  policyBrokerOptions,
  policyConsoleOptions,
  policyRunnerOptions,
  resolveIsolatePolicy,
  runIsolated,
  runIsolatedFile,
  Reference,
  ExternalCopy,
  validateContextCheckpoint,
  type Isolate,
  type Context,
  type Script,
} from "@absolutejs/isolated-jsc";

// Create an isolate (one per untrusted tenant).
const isolate: Isolate = await createIsolate({
  memoryLimit: 256, // MB; default 256
  bootstrap: "var foo = 1", // optional — runs once in the worker
  maxConsoleEntries: 100,
  maxConsoleBytes: 64_000,
  onConsole: (level, args) => console.log(`[iso/${level}]`, ...args),
});

// One or more contexts (fresh global scopes) per isolate.
const context: Context = await isolate.createContext();

// Expose a host function callable from inside the isolate.
const dbQuery = new Reference(async (sql: string) => {
  return await myDb.query(sql); // host-side call, tenant-scoped
});
await context.setGlobal("db", dbQuery);

// Compile + run.
const script: Script = await isolate.compileScript(`
    (async () => {
        const rows = await db('SELECT * FROM users');
        return rows.length;
    })()
`);

const count = await script.run(context, { timeout: 500 });
// count === number of rows

// TypeScript source: transpiled with Bun before execution in the isolate.
const handler = await compileTypeScriptCallable(
  context,
  "async (name: string): Promise<string> => name.trim().toUpperCase()",
);
await handler.call([" alex "]); // "ALEX"

// Real files work too. Keep generics, types, and complex tenant/plugin code in
// normal `.ts`, `.tsx`, `.js`, or `.jsx` files instead of string literals.
const typedScript = await compileTypeScriptFile(
  isolate,
  "./tenant-code/score.ts",
);
await typedScript.run(context);

// Callable files use a default export:
//
//   type Box<T> = { value: T };
//   export default function unwrap<T>(box: Box<T>): T {
//     return box.value;
//   }
//
const unwrap = await compileTypeScriptCallableFile(
  context,
  "./tenant-code/unwrap.ts",
);
await unwrap.call([{ value: "typed file" }]); // "typed file"

// Explicit data checkpoints for turn/session handoff. These capture
// structured-cloneable own globals only, not a JSC heap image.
const checkpoint = await context.checkpoint({
  exclude: ["scratch"],
  maxBytes: 64 * 1024,
});
const persisted = JSON.stringify(checkpoint);
const restoredCheckpoint = JSON.parse(persisted);
validateContextCheckpoint(restoredCheckpoint);
const resumed = await isolate.createContext({
  checkpoint: restoredCheckpoint,
  seed: "this.double = (n) => n * 2",
});
// checkpoint.schemaVersion === 1
// checkpoint.skipped === [{ key, reason, bytes? }, ...]

// Versioned checkpoint receipts for operational evidence. Mirrors the
// ExecutionReceipt shape: schemaVersion:1, durationMs, startedAt/endedAt,
// executionId, plus operation:"create"|"restore" and aggregated
// skippedReasons counts. Pass purpose/tenant for audit-log workflows;
// errors rethrow with `.receipt` attached.
const audited = await context.checkpointWithReceipt({
  exclude: ["scratch"],
  maxBytes: 64 * 1024,
  purpose: "turn-handoff",
  tenant: "tenant-a",
});
// audited.receipt.operation === "create"
// audited.receipt.skippedReasons === { excluded, notClonable, overMaxBytes }
const restored = await isolate.createContextWithReceipt({
  checkpoint: audited.checkpoint,
  purpose: "turn-handoff",
  tenant: "tenant-a",
});
// restored.receipt.operation === "restore"
// restored.receipt.sourceBackend === "ffi" | "worker"

type TenantContext = { id: string };
type LookupOrderInput = { id: string };
type Order = {
  cardLast4: string;
  customerEmail: string;
  id: string;
  status: string;
};
const policy = resolveIsolatePolicy("ai-tool", {
  maxResultBytes: 32 * 1024,
  timeout: 750,
});
const audit = createCapabilityAuditBuffer<TenantContext>({
  ...policyAuditOptions(policy),
});
const redactEmail = (email: string) => {
  const [name, domain] = email.split("@");
  return domain === undefined
    ? "[email redacted]"
    : `${name.slice(0, 2)}***@${domain}`;
};

const broker = createCapabilityBroker(
  {
    lookupOrder: defineCapabilityTool<
      LookupOrderInput,
      Order | null,
      TenantContext
    >({
      description: "Read one order by id for the current tenant",
      risk: "read-only",
      input: { name: "LookupOrderInput" },
      output: "Order | null",
      maxOutputBytes: 16_384,
      redactAuditInput: (input) => ({ id: (input as { id?: unknown }).id }),
      redactAuditOutput: (output) => {
        if (output === null) return null;
        const order = output as Order;
        return {
          cardLast4: order.cardLast4,
          customerEmail: redactEmail(order.customerEmail),
          id: order.id,
          status: order.status,
        };
      },
      timeoutMs: 250,
      validateInput: (input) => {
        if (input === null || typeof input !== "object") {
          throw new Error("lookupOrder input must be an object");
        }
        const id = (input as { id?: unknown }).id;
        if (typeof id !== "string") {
          throw new Error("lookupOrder input requires a string id");
        }
        return { id };
      },
      handler: async ({ id }, tenant) => await lookupOrder(tenant.id, id),
    }),
    chargeCard: defineCapabilityTool<
      { cardToken: string; orderId: string },
      { authorizationId: string; processorTraceId: string },
      TenantContext
    >({
      description: "Charge an opaque card token for one tenant order",
      input: "ChargeInput",
      output: "ChargeResult",
      risk: "write",
      redactAuditInput: (input) => ({
        cardToken: "[token redacted]",
        orderId: (input as { orderId?: unknown }).orderId,
      }),
      redactAuditOutput: (output) => ({
        authorizationId: (output as { authorizationId?: unknown })
          .authorizationId,
        processorTraceId: "[trace redacted]",
      }),
      validateInput: (input) => input as { cardToken: string; orderId: string },
      handler: async (input, tenant) => await chargeCard(tenant.id, input),
    }),
  },
  {
    context: { id: "tenant_123" },
    ...policyBrokerOptions(policy),
    onAudit: audit.onAudit,
    redactAuditInput: () => "[input redacted by default]",
    redactAuditOutput: () => "[output redacted by default]",
  },
);

// Host-side direct calls are typed from the tool map.
const order = await broker.call("lookupOrder", { id: "ord_123" });
//    ^? Order | null

// Reviewable capability manifest for docs, audits, and agent/tool UIs.
broker.manifest();
// [{
//   name: "lookupOrder",
//   schemaVersion: 1,
//   description: "Read one order by id for the current tenant",
//   risk: "read-only",
//   input: { name: "LookupOrderInput" },
//   output: "Order | null",
//   maxOutputBytes: 16384,
//   timeoutMs: 250,
//   hasInputValidator: true,
//   hasOutputValidator: false,
//   redactsInput: true,
//   redactsOutput: true
// }]

// Audit events and receipts retain the operational proof, not raw secrets:
//   order ids stay visible
//   emails become ad***@example.com
//   card tokens become [token redacted]
//   processor trace ids become [trace redacted]

// Sandbox calls still use an untrusted-code-safe Reference.
await context.setGlobal("tools", broker.reference);

// Policy recipes standardize isolate construction, default timeout, default
// result-size limits, and recommended audit/broker/runner settings.
const policyIsolate = await createIsolate({
  policy,
  ...policyConsoleOptions(policy),
});
const policyContext = await policyIsolate.createContext();
const policyScript = await policyIsolate.compileScript("1 + 1");
await policyScript.run(policyContext);
await policyIsolate.dispose();

// One-shot execution for request/response paths.
const oneShot = await runIsolated<number>("input.n * 2", {
  policy,
  globals: { input: { n: 21 } },
});
// oneShot === 42

const oneShotFile = await runIsolatedFile<number>("./tenant-code/score.ts", {
  policy,
  globals: { input: { n: 21 } },
});
// oneShotFile === 42

const measured = await runIsolated<number>("input.n + 1", {
  policy: "tenant-script",
  globals: { input: { n: 41 } },
  withMetrics: true,
});
// measured.result === 42; measured.metrics.backend === "ffi" | "worker"

const receipted = await runIsolated<number>("input.n + 1", {
  policy: "tenant-script",
  globals: { input: { n: 41 } },
  run: {
    ...audit.receiptOptions(),
    executionId: "exec_123",
    purpose: "ai-tool-call",
    tenant: "tenant_123",
  },
  withReceipt: true,
});
// receipted.result === 42
// receipted.receipt.status === "success"
// receipted.receipt.backend === "ffi" | "worker"

// Reusable runner for repeated request/response paths.
const runner = createIsolatedRunner({
  ...policyRunnerOptions(policy),
  policy,
  globals: { tools: broker.reference },
});

const tenantResult = await runner.run<number>("input.n * 2", {
  key: "tenant_123",
  globals: { input: { n: 21 } },
});
// tenantResult === 42

const tenantFileResult = await runner.runFile<number>(
  "./tenant-code/score.ts",
  {
    key: "tenant_123",
    globals: { input: { n: 21 } },
  },
);
// tenantFileResult === 42

await runner.precompile(
  "scoreFormula",
  "(input) => input.base * 2 + input.bonus",
  { key: "tenant_123" },
);

const callableResult = await runner.call<number>(
  "scoreFormula",
  "(input) => input.base * 2 + input.bonus",
  [{ base: 20, bonus: 2 }],
  { key: "tenant_123" },
);
// callableResult === 42

await runner.precompileFile("unwrap", "./tenant-code/unwrap.ts", {
  key: "tenant_123",
});

const callableFileResult = await runner.callFile<string>(
  "unwrap",
  "./tenant-code/unwrap.ts",
  [{ value: "typed file" }],
  { key: "tenant_123" },
);
// callableFileResult === "typed file"
// runner.stats() === { poolSize: 1, callableCacheSize: 1, callablesByKey: { tenant_123: 1 } }

await runner.dispose();
await isolate.dispose();
```

### 获取处理器

运行一个 Web 标准应用( E)`export default { fetch(request, env, ctx) }`,则 工人们, `Bun.serve` 以主机称呼它 `Request`s. 仅限工人后端.

```ts
import {
  bundleFetchHandler,
  createFetchHandler,
  createIsolate,
  Reference,
} from "@absolutejs/isolated-jsc";

const source = await bundleFetchHandler("./app.ts"); // one CommonJS bundle, Web APIs only
const isolate = await createIsolate({
  backend: "worker",
  requireLockdown: true,
});
const handler = await createFetchHandler(
  await isolate.createContext(),
  source,
  {
    env: { region: "nyc1", lookup: new Reference(async (id) => db.user(id)) },
  },
);

const response = await handler.fetch(
  new Request("https://app.example/users/7"),
);
const { metrics } = await handler.fetchWithMetrics(request); // cpuMs is thread CPU time
```

-   `env` 保存数据 `Reference` 能力(每个合成函数) 呼唤回住持.
-   `ctx.state` (一) 在请求之间保持上下文; `context.checkpoint({ include: ["state"] })` 捕取来冬眠.
-   `ctx.waitUntil(promise)` 让我们在回复后完成工作.
-   车体以1米B为缓冲并封顶(`maxRequestBytes`, (中文(简体) ), `maxResponseBytes`(三); `FetchBodyTooLargeError` 说哪边溢出.
-   `bundleFetchHandler` 拒绝孤立者不能提供的东西`node:` 财务报告和审定财务报表 `bun:` 进口、无已安装软件包的节点内置、原生加通) ,并将每个此类导入列表于 a `FetchHandlerBundleError`. Bundling 罐头 运行应用程序的宏, 所以运行它在哪里 你会运行应用程序自己的构建.
-   Elysia 2 的应用程序没有改变: `export default { fetch: (request) => app.handle(request) }`。 。 。 .

### 错误

-   `FetchBodyTooLargeError` ——采集处理者的请求或响应机构超过其极限.
-   `FetchHandlerBundleError` ——一个应用导入了Bun或Node APIs或本地的加通.
-   `TimeoutError` ——一站一站预算用完.
-   `MemoryLimitError` ——堆积超过所配置的盖.
-   `ResultSizeError` 成功产出超过 `maxResultBytes`。 。 。 .
-   `IsolateDisposedError` 处理隔离物.
-   `CompileError` ——脚本出处的语法错误.

## 安装

```bash
bun add @absolutejs/isolated-jsc
```

要求装有 1.3.

## 医生

```bash
bunx @absolutejs/isolated-jsc
bunx @absolutejs/isolated-jsc --json
# or, from this repo:
bun src/doctor.ts
```

博士会打印 Bun/平面细节, FFI 后端可用性, JavaScriptCore f味/ path 当找到时, 检查缺少的库路径, 以及当前平台的安装提示 。 过 `--json` 用于机器可读CI或部署检查.

## 实例

```bash
bun run example:agent-tool
bun run example:checkpoint
```

代理工具的例子结合了TypeScript可调用编译,一种能力经纪人,租户背景,工具超时,审计事件,以及按调用的标准. 检查站的例子显示,JSON检查站持续存在,恢复验证和种子恢复.

## 基准

```bash
bun run bench:proof
```

这个写着 `BENCHMARKS.md` 与 FFI 后端、 工人后端、 Bun 流程喷出基线和节点的本地测量数据相匹配 `isolated-vm` 当选择本地软件包安装在节点环境中时.

## 测试

```bash
bun install
bun test
```

测试套件包括编译/运行、环境、, `Reference` 通过电话, `ExternalCopy`,超时,内存封顶,处置一能,池行为,TypeScript帮助者,能力经纪人,FFI行为,主机可达性文件,以及敌对租借人压力案件.

## 释放检查

```bash
bun run check:release
```

发布检查会运行套件类型检查、构建、单元测试、代理工具示例以及兄弟会中的浏览器烟雾 `../examples/isolated-jsc` 应用 `absolutejs/examples` 剪切发布时, repo 检查了此套件的旁边 repo, 因此在发布前会覆盖演示路径 .

## 相关

-   [`@absolutejs/sync`](https://github.com/absolutejs/sync) - 反应同步引擎。 最终会利用这个库在主机"PaaS"中用于沙盒每租户变异处理器.
-   [Bun 文档 : `bun:jsc`](https://bun.sh/docs/api/utils#bun-jsc) ——JSC原始人 这个图书馆建立在.
-   [`isolated-vm`](https://github.com/laverdet/isolated-vm) ——V8/Node等同于这个库镜(我们欠安德鲁·拉弗德特的API形状).

## 许可证

商业来源许可证1.1——生产使用是免费的,但作为相互竞争的主机沙盒/同位素服务提供除外(见2000年12月31日的附加用途赠款) [自由主义](https://npmcn.com/package/%40absolutejs/isolated-jsc/LICENSE). 2030年5月29日转换为Apache 2.0. 现有商业许可证——联系人 `l@nagy.vc`。 。 。 .

## 常见问题

### @absolutejs/isolated-jsc 是什么？

JavaScript Core-native sandbox for Bun – 大量同位化执行不可信代码,孤立-vm-形状的 API

### 如何安装 @absolutejs/isolated-jsc？

在项目目录运行 npm install @absolutejs/isolated-jsc，或使用 pnpm add / yarn add / bun add。它还提供命令行工具 isolated-jsc、isolated-jsc-doctor，可以用 npx isolated-jsc 直接运行。

### @absolutejs/isolated-jsc 支持 TypeScript 吗？

支持。包内自带 TypeScript 类型声明（package\.json 声明了 types 入口），安装后即可获得类型提示，无需再安装 @types 包。

### @absolutejs/isolated-jsc 支持 ESM 还是 CommonJS？

以 ES Module 形式发布，推荐使用 import 引入。在 CommonJS 项目中，Node\.js 20\.19\+ / 22\.12\+ 可以直接 require\(\) 不含顶层 await 的 ES Module，更早的版本需要改用动态 import\(\)。

### @absolutejs/isolated-jsc 可以商用吗？

@absolutejs/isolated-jsc 使用 BSL-1\.1 许可。声明的许可为 BSL-1\.1，请阅读许可原文确认使用条件。以上为概括，不构成法律意见，请以许可原文为准。

### @absolutejs/isolated-jsc 的下载量有多少？

根据 npm 官方下载统计，@absolutejs/isolated-jsc 在 2026/10/05 – 2026/11/03 这 30 天内被下载 3,052 次，日均约 102 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @absolutejs/isolated-jsc 还在维护吗？

最新版本 0\.15\.0 发布于 2026/11/03（4 天前）；至今共发布 54 个版本，其中过去 12 个月发布了 54 个；首次发布于 2026/05/27。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

