资讯动态

CodexBar 的 CQuickJS:在 SwiftPM 包中植入 quickjs-ng 最小可嵌入 JavaScript 引擎的完整指南

发布时间:2026/9/13 7:11:21 来源:尧图企业网站定制
CodexBar 的 CQuickJS在 SwiftPM 包中植入 quickjs-ng 最小可嵌入 JavaScript 引擎的完整指南【免费下载链接】CodexBarShow usage stats for OpenAI Codex and Claude Code, without having to login.项目地址: https://gitcode.com/GitHub_Trending/co/CodexBar本篇技术指南围绕 CodexBar 仓库中的 Sources/CQuickJS/README.md 展开系统讲解该项目如何在 Swift Package ManagerSwiftPMC target 中 vendor内置第三方源码一个最小可嵌入的 quickjs-ng 引擎包括版本与校验和溯源、文件清单与排除策略、Package.swift中的编译与链接配置、宿主层 C 封装看门狗与宿主函数分派、以及它在用户 Provider 插件执行与 TypeScript 转译中的真实用途。读完你既能独立复现该 vendor 流程也能理解 CodexBar 插件运行时为何需要一个受控、可限制资源、可超时中断的嵌入式 JS 引擎。一、CQuickJS 在 CodexBar 中的定位CodexBar 是一个用于展示 OpenAI Codex 与 Claude Code 用量统计的菜单栏应用其用户 Provider 插件机制允许以 JavaScript/TypeScript 编写自定义用量抓取逻辑。为了保证这类第三方代码运行在隔离、可限流、可被强制中断的沙箱内而不是直接放进应用主进程CodexBar 需要一个可嵌入、轻量、单线程友好的 JavaScript 引擎——这正是 CQuickJS 存在的理由。从依赖关系可以清晰看到这一角色Package.swift 定义了CQuickJS这个 C target而CodexBarCoretarget 将其声明为首要依赖Package.swift随后CodexBarCore/Plugins目录下的QuickJSProviderPluginEngine、QuickJSTypeScriptTranspiler等 Swift 文件通过import CQuickJS直接调用其 C API。换言之CQuickJS 是整个插件子系统的底层执行引擎本身不携带任何业务逻辑。二、vendored 内容与版本溯源一个可校验的固定快照CQuickJS 的 README 明确说明它 vendor 的是quickjs-ng项目的v0.15.1发布版2026 年 6 月 4 日。为了让每一次构建都严格可复现项目固定了两项溯源信息源码归档地址quickjs-ng 官方发布的v0.15.1tar.gz 归档SHA-256 校验和c4e813951b7c46845096a948e978c620b11ab4cf5fd622ca09c727ec31f42623。该校验和同时被硬编码进 Scripts/regenerate-quickjs-vendor.shEXPECTED_SHA256变量下载归档后会先校验再解包任何与上游不一致的内容都会导致脚本失败从源头杜绝下载到被篡改的源码。文件清单4 个翻译单元 14 个头文件 1 份许可证README 给出的统计是19 个 vendored 文件共 2,694,082 字节。对照 Sources/CQuickJS 目录实际内容这一统计对应4 个上游引擎翻译单元.cquickjs.c核心解释器、dtoa.c浮点字符串转换、libregexp.c正则表达式、libunicode.cUnicode 表与处理14 个必需头文件quickjs.h、quickjs-atom.h、quickjs-opcode.h、quickjs-c-atomics.h、libregexp.h、libregexp-opcode.h、libunicode.h、libunicode-table.h、cutils.h、dtoa.h、list.h、builtin-array-fromasync.h、builtin-iterator-zip.h、builtin-iterator-zip-keyed.h1 份上游 MIT 许可证LICENSE。说明Sources/CQuickJS目录下还有两个不属于这 19 个上游文件的本地文件——CQuickJSHost.c与include/CQuickJSHost.h它们是 CodexBar 自研的宿主层封装详见第四节。有意排除的部件README 明确列出了故意不打包的内容qjs/qjsc两个命令行工具、REPL交互式解释器、libc 模块如os、std等内置模块、官方示例、测试以及上游构建系统文件。这是最小可嵌入定位的直接体现CodexBar 只关心引擎本身runtime/context/eval/内存限制/中断钩子不需要任何 CLI 外壳或构建脚本。源码保持未修改README 强调 The sources are unmodified——四个.c与 14 个头文件与上游v0.15.1逐字节一致这也是check模式用cmp逐文件比对的基础见第六节。所有适配工作都被隔离在 SwiftPM 的编译定义与链接设置中而不是直接改动上游源码这样既便于升级也便于审计本地到底改了什么。三、SwiftPM 集成C target 的编译与链接配置Package.swift中CQuickJStarget 的完整定义如下Package.swift.target( name: CQuickJS, path: Sources/CQuickJS, exclude: [README.md, LICENSE], publicHeadersPath: include, cSettings: [ .define(_GNU_SOURCE), ], linkerSettings: [ .linkedLibrary(m, .when(platforms: [.linux])), ]),各配置项的作用path: Sources/CQuickJS指定源码根目录SwiftPM 会编译该目录下的所有.c文件即 4 个上游翻译单元加CQuickJSHost.c。exclude: [README.md, LICENSE]README.md与LICENSE不属于编译单元显式排除可避免 SwiftPM 尝试将其作为资源处理同时保留文件在仓库中的可读性。publicHeadersPath: include声明Sources/CQuickJS/include为公开头文件目录Swift 代码通过import CQuickJS即可看到quickjs.h等全部 14 个上游头文件以及本地的CQuickJSHost.h。cSettings: [.define(_GNU_SOURCE)]为所有 C 编译单元定义_GNU_SOURCE宏确保在 glibc 环境下暴露 GNU 扩展接口如clock_gettime等这是跨 macOS/Linux 构建兼容性的关键一环。linkerSettings: [.linkedLibrary(m, .when(platforms: [.linux]))]仅在 Linux 上链接数学库libm。dtoa.c、quickjs.c等翻译单元依赖浮点数学函数而 macOS 上这些符号由系统库提供无需显式链接。值得注意的细节是该 target 属于无平台限制的通用 target未用#if os(macOS)包裹因此 CodexBar 的 Linuxglibc 与静态 muslCLI 构建与 macOS 应用构建共用同一份引擎源码这与仓库中 Both glibc and static-musl CLI builds use this target 的注释Package.swift相互印证。四、宿主层扩展CQuickJSHost 的看门狗与函数分派纯上游引擎只能执行脚本无法满足 CodexBar 对超时控制和宿主能力注入的需求。为此仓库在Sources/CQuickJS内新增了两个文件Sources/CQuickJS/include/CQuickJSHost.h公开 C API 声明Sources/CQuickJS/CQuickJSHost.c实现。4.1 看门狗Watchdog超时即中断CQuickJSHost的核心是一套基于原子变量与JS_SetInterruptHandler的看门狗机制CQuickJSHost.cCQJSWatchdogCreate/Destroy创建/销毁看门狗对象内部用calloc分配包含一个回调指针、不透明上下文指针以及两个_Atomic字段interrupted与deadline_nanosecondsCQJSWatchdogInstall通过JS_SetContextOpaque把看门狗挂到 context 上再通过JS_SetInterruptHandler(runtime, CQJSInterruptHandler, watchdog)注册中断处理器CQJSWatchdogArm(timeout_milliseconds)先清除中断标志再用clock_gettime(CLOCK_MONOTONIC, ...)取单调时钟并累加出截止时刻写入原子变量中断处理器每次被 QuickJS 调用时检查interrupted标志或当前时刻是否已过截止时刻命中即返回 1 触发引擎中断CQJSWatchdogInterrupt与CQJSWatchdogIsInterrupted前者允许外部线程如 Swift 侧主动设置中断标志——这是引擎在串行工作线程之外唯一的线程安全逃生口后者供 Swift 层在捕获异常时区分超时与普通脚本错误。4.2 宿主函数分派magic 编号桥接 Swift为了让 Swift 能向 JS 暴露任意宿主函数CQJSNewHostFunction使用 QuickJS 的JS_NewCFunctionMagicCQuickJSHost.c创建魔法函数每个函数绑定一个int32_t magic编号所有函数共享同一个 C 分发器CQJSHostDispatcherCQuickJSHost.c。分发器从 context 的 opaque 指针取回看门狗再把magic、argc、argv原样转交给 Swift 侧注册的回调。头文件中还提供了一组轻量值操作cqjs_undefined/cqjs_null/cqjs_bool/cqjs_dup_value/cqjs_free_value、类型判定is_exception/is_undefined/is_null/is_string/is_number/is_object以及cqjs_throw_error。头文件注释特别说明CQuickJSHost.h这些小写拼写的内联包装是为了避免 Clang 的 Swift importer 把CQJS当作可剥离的类型前缀从而保证 Swift 侧 API 名称稳定。五、引擎的真实用途Provider 插件运行时与 TypeScript 转译CQuickJS 不是孤立存在的 target它的消费方集中在 Sources/CodexBarCore/Plugins 目录。理解这些消费方式才能明白 README 中最小可嵌入的每一项取舍。5.1 插件执行引擎QuickJSProviderPluginEngineSources/CodexBarCore/Plugins/QuickJSProviderPluginEngine.swift 是核心消费方。它在专用的串行工作线程QuickJSSerialWorker上创建 runtime 与 contextJS_NewRuntime()→JS_SetMemoryLimit(runtime, 64MB)→JS_SetMaxStackSize(runtime, ...)→JS_NewContext(runtime)源码 L218-L229将内存上限固定为64 MiBstatic let memoryLimitBytes 64 * 1024 * 1024依据JS 栈预算必须远低于宿主原生栈的原则把 JS 栈限制设为工作线程栈的四分之一下限 64 KiB见QuickJSRuntimeLimits.javaScriptStackLimitBytes源码 L33-L35避免在栈余量不足时抛 RangeError 反而导致宿主崩溃创建并安装看门狗在加载脚本与每次fetchUsage执行前cqjs_watchdog_arm超时后由 Swift 侧映射为ProviderPluginError.timedOut通过cqjs_new_host_function向 JS 注入 11 个宿主函数QuickJSHostFunction枚举源码 L8-L20defineProvider、settingGet、http、cookieHeader、cacheGet、cacheSet、log、nextDailyReset、pct、amountFromPercent、isDetailLabel——涵盖配置读取、网络请求、浏览器 Cookie 桥接、进程内缓存、日志、时区重置计算与百分比换算插件若返回 Promise引擎会循环调用JS_ExecutePendingJob驱动微任务队列直至 settle源码 L429-L452实现宿主侧同步等待异步 JS 结果。仓库内置的 Provider 插件脚本位于 Sources/CodexBarCore/Resources/Plugins如openai.js、openrouter.js、zai.js、deepgram.js等它们正是运行在该引擎之上。5.2 TypeScript 转译Sucrase 跑在 QuickJS 里Sources/CodexBarCore/Plugins/QuickJSTypeScriptTranspiler.swift 展示了 CQuickJS 的第二个用途在引擎内加载打包好的SucraseSources/CodexBarCore/Resources/Plugins/sucrase-3.35.1.min.js把用户写的 TypeScript 插件源码即时转译为 JavaScript再交给上述执行引擎运行。转译过程同样套用看门狗超时保护并刻意用带自定义stackSize8 MiB的Thread子类承载因为 Dispatch 协程工作线程的原生栈可能小于 QuickJS 的 2 MiB 限制QuickJSTypeScriptTranspiler.swift 源码注释 L32。最终转译代码通过sucrase.transform(source, {transforms:[typescript]}).code求值获得源码 L111-L113。六、可复现的 vendor 流程check 与 write 两种模式README 给出的运维入口是 Scripts/regenerate-quickjs-vendor.sh。该脚本以仓库根为基准把整个下载 → 校验 → 挑选 → 落盘流程固化为两个模式校验模式默认Scripts/regenerate-quickjs-vendor.sh check脚本会下载归档、比对 SHA-256不匹配立即失败退出解包后在临时目录中按固定清单挑选 4 个.c、14 个.h与LICENSE然后用cmp逐文件与Sources/CQuickJS下已检入的文件比对。全部一致时输出ok: vendored quickjs-ng v0.15.1 matches c4e813951b7c46845096a948e978c620b11ab4cf5fd622ca09c727ec31f42623写入模式Scripts/regenerate-quickjs-vendor.sh write删除旧文件并按同一清单重新落盘输出wrote Sources/CQuickJS from quickjs-ng v0.15.1 (...)。由于write模式只覆盖清单内的文件任何本地新增文件如宿主层封装都不会被误删同时脚本对哈希与临时目录使用trap清理保证失败时不留脏状态。这一流程的价值在于任何人在任何机器上都能独立验证仓库里检入的引擎确实来自未被篡改的 quickjs-ng v0.15.1也便于日后升级到新版本——只需改QUICKJS_VERSION与EXPECTED_SHA256两个变量。七、测试与验证仓库用测试锁定了 CQuickJS 引擎的关键行为边界TestsPlugin/UserProviderPluginPortableTests.swift 验证 QuickJS 能执行打包的 Sucrase 转译、且超过堆上限的内存分配会被拒绝QuickJS rejects allocations beyond its heap capTestsPlugin/ProviderPluginEngineBenchmarkTests.swift 对同一批插件在 JavaScriptCore 与 QuickJS 两种引擎上分别计时对比输出| Plugin | JavaScriptCore | QuickJS |表格用于在 macOS 平台上做引擎性能回归观测。此外CodexBarCoretarget 在 macOS 平台还链接了系统 JavaScriptCorePackage.swift说明 QuickJS 主要服务于 Linux 与需要严格资源限制的场景macOS 上两套引擎并行存在并共享同一套插件协议——这也解释了为什么引擎边界内存、栈、超时的测试被单独抽出成可移植用例。八、小结一份最小可嵌入的工程范本从 Sources/CQuickJS/README.md 的寥寥数行出发可以看到 CodexBar 在引擎选型与 vendor 管理上的完整思路固定版本与校验和锁死 quickjs-ng v0.15.1 与 SHA-256构建可复现、内容可审计最小裁剪只保留 4 个翻译单元 14 个头文件19 个文件、约 2.6 MiB剔除 CLI、REPL、libc 模块、示例、测试与构建系统零修改 配置外置上游源码不改动编译宏_GNU_SOURCE与链接库Linux 的libm全部收敛在 Package.swift宿主层补齐缺口用CQuickJSHost的看门狗与 magic 分派把超时中断与宿主函数注入两大能力接到 Swift 侧消费端落实边界64 MiB 内存上限、按线程栈比例推导的 JS 栈上限、超时看门狗、串行工作线程约束共同构成用户插件运行的受控沙箱脚本化再生成check/write双模式让任何人在任何平台都能验证或更新这份 vendor。如果你需要在自有 Swift 包中嵌入一个轻量 JS 引擎尤其是需要强超时控制、内存限制与 Linux 支持的场景完全可以照此模式落地以固定校验和的归档为唯一事实来源把宿主扩展与上游源码物理隔离再配一个可复现的再生成脚本——这正是 CQuickJS 这份 README 及其仓库实现给出的最直接的工程答案。【免费下载链接】CodexBarShow usage stats for OpenAI Codex and Claude Code, without having to login.项目地址: https://gitcode.com/GitHub_Trending/co/CodexBar创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价