Help us shape the future of Go! Take the 2026 Go Developer Survey

Gox

command module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 17, 2026 License: Apache-2.0 Imports: 9 Imported by: 0

README

Gox

用 Go 从零实现的 JavaScript 运行时:词法分析 → 语法分析 → 字节码编译 → 栈式虚拟机执行。 单二进制、零外部依赖,还能把 JS 脚本打包成独立可执行文件。

特性一览

  • 完整编译管线 — 自研 lexer / parser / compiler / bytecode VM,108 个操作码,定长 3 字节指令编码([操作码 1B][操作数 2B 大端]),解码即取即用
  • ES6+ 语言子集 — let/const(不支持 var)、函数与箭头函数、闭包、class、async/await、解构赋值、剩余/默认参数、展开、模板字符串、for...of、try/catch/throw、可选链 ?.、空值合并 ??、ES 模块 import/export,以及 JSX 语法(编译期降级为 h(tag, props, ...children) 调用)
  • 丰富的内置对象 — Array / String / Number / Object / Boolean / Math / JSON / Map / Set / WeakMap / WeakSet / Symbol / BigInt / RegExp / Proxy / Reflect / Iterator / Promise / ArrayBuffer / DataView(TypedArray 家族)/ WeakRef / FinalizationRegistry / 完整错误类型族 / Temporal(取代 Date 的现代日期时间 API)
  • 宿主能力模块 — fs(Node 风格,同步 + 异步两套)、http(客户端 get/request + 服务端 createServer)、fetch、path、process、stats
  • 自研 GUI 渲染层 — gx/gfx 模块:纯 Go 软件光栅化,flex 风格布局(column/row/gap/padding)、命中测试、脏矩形局部重绘;win32(纯 syscall 无 cgo)与 X11 窗口后端,产物为无动态库依赖的静态单文件
  • 事件循环 — setTimeout / setInterval / requestIdleCallback,以及精度可控的严格定时器变体(setStrictTimeout 等);GUI 模式下事件循环接入窗口消息泵
  • 响应式编程 — Dart GetX 风格的 obs / computed / ever / once,以及 SolidJS 风格的 gx/solid 信号(createSignal / createEffect / createMemo)
  • npm 分发 — goxjs 包内置 Windows/Linux/macOS × x64/arm64 五个平台的预编译二进制,npm i -g goxjs 即得 goxjs 命令
  • 工具链 — 交互式 REPL、jsbuild 打包器(JS → 独立 .exe,支持 GUI 应用与纯 Go 交叉编译)、dbgtool 词法调试器

快速开始

方式一:从源码构建(环境要求 Go 1.26+)

git clone https://github.com/14752222/Gox.git
cd Gox
go build          # Windows 下生成 Gox.exe

方式二:npm 安装预编译二进制(无需 Go 环境)

npm i -g goxjs    # 或不安装直接跑: npx goxjs app.js

REPL:

./Gox
Gox REPL (ES6 subset, no var)
Type :exit to quit, :help for help

> let x = 10
> let y = 20
> x + y
  30
> [1, 2, 3].map(v => v * 2)
  [2, 4, 6]

REPL 命令::help 查看帮助、:clear 重置环境、:exit 退出。

运行脚本:

./Gox example.js    # npm 安装的 goxjs 命令用法相同

脚本执行完毕后会回显最后一个顶层表达式的值(undefined 除外),并等待定时器与异步回调全部执行完再退出。

语言示例

以下示例均实际运行验证过。

基础语法:

let x = 10
let y = 20
console.log(x + y)                                                 // 30
console.log([1, 2, 3].map(v => v * 2))                             // [2, 4, 6]
console.log([1, 2, 3].filter(v => v > 1).reduce((a, b) => a + b))  // 5
console.log(Math.hypot(3, 4))                                      // 5

let name = "Gox"
console.log(`Hello, ${name}!`)                                     // Hello, Gox!

let [a, b] = [1, 2]                                                // 解构赋值
console.log(a + b)                                                 // 3

class 与异步:

class Point {
  constructor(x, y) { this.x = x; this.y = y }
  norm() { return Math.hypot(this.x, this.y) }
}
console.log(new Point(3, 4).norm())       // 5

async function main() {
  let v = await delay(10, "timer done")   // delay(ms, value) 返回 Promise
  console.log(v)
}
main()
5
Promise { <pending> }     ← 顶层回显:main() 调用的返回值
timer done                ← 定时器到期后,await 继续执行

ES 模块 — lib.js:

export const PI = 3.14
export function double(x) { return x * 2 }

main.js:

import { PI, double } from "./lib.js"
setTimeout(() => console.log("tick"), 10)
console.log(double(PI))
6.28
tick

响应式(GetX 风格):

let count = obs(0)
ever(count, v => console.log("count =", v))   // 订阅时立即以当前值回调一次
count.value = 1
count.value = 2
count.value = 2   // 值未变化,不触发通知
count = 0
count = 1
count = 2
2                  ← 顶层回显:最后一条赋值表达式的值

GUI 桌面应用

gx/gfx + gx/solid 提供 JSX 声明式 UI 与信号驱动的响应式更新,渲染器为纯 Go 软件光栅化(无 cgo、无动态库依赖):

import { createSignal } from "gx/solid"
import { h, window, render } from "gx/gfx"

const [count, setCount] = createSignal(0)

render(
  <column gap={8} padding={16}>
    <text font={20}>{() => `count: ${count()}`}</text>
    <button onClick={() => setCount(c => c + 1)}>加一</button>
  </column>,
  window({ title: "Counter", width: 400, height: 300 })
)
./Gox counter.js          # 直接运行,弹出 400x300 窗口
  • 点击按钮 → setCount 更新信号 → 依赖该信号的属性/文本节点自动标脏 → 脏矩形合并后只重绘受影响区域
  • 内置元素:column / row / text / rect / button;布局属性 gap / padding / width / height
  • 窗口后端:Windows(纯 syscall win32)与 Linux(X11,Wayland 下走 XWayland);macOS GUI 后端尚未实现
  • 完整示例见 testdata/counter_demo.js、testdata/gui_demo.js

打包成独立可执行文件

jsbuild(packager 目录)把入口脚本及其相对 import 的模块嵌入一个生成的 Go 工程,编译成单文件可执行程序,自带完整运行时:

go run ./packager app.js -o app.exe                    # CLI 应用
go run ./packager counter.js --gui -o counter.exe      # GUI 应用
go run ./packager app.js --gui --target linux/amd64    # 纯 Go 交叉编译,无需目标机工具链
Usage: jsbuild <input.js> [options]

Options:
  -o, --out <path>     输出文件路径 (默认: <输入文件名>.exe)
      --name <name>    应用名 (用于错误信息显示, 默认取输入文件名)
      --windowed       窗口模式: 不显示控制台窗口 (仅 Windows)
      --gui            GUI 应用: 窗口消息泵事件循环 (配合 gx/gfx render)
      --target <os>/<arch>  交叉编译目标 (windows|linux|darwin / amd64|arm64|386)
  -v, --verbose        显示构建过程输出

各平台的分发注意事项(Windows 图标与签名、Linux 打包格式、macOS .app bundle)见 docs/desktop-distribution.md。

架构

 .js 源码
    │  lexer        词法分析
    ▼
 Token 流
    │  parser       语法分析
    ▼
 AST (ast/)
    │  compiler     符号表解析 + 字节码生成 (常量池)
    ▼
 字节码 (bytecode/)   定长 3 字节: [opcode 1B][operand 2B 大端]
    │  vm           栈式调用帧执行 + 定时器事件循环 + 模块加载
    ▼
 结果
  • 无 GC 的显式内存管理 — 对象生命周期由运行时显式控制,循环引用有专门处理
  • 单线程 VM + 跨 goroutine 调度 — http.createServer 等网络回调跨 goroutine 捕获后调度回 VM 单线程执行,无需锁
目录结构
目录 职责
lexer/ 词法分析器(含 JSX 词法支持)
parser/ 语法分析器,生成 AST(含 JSX 语法降级)
ast/ AST 节点定义
compiler/ AST → 字节码编译器(含符号表)
bytecode/ 操作码与字节码格式定义
vm/ 栈式字节码虚拟机(调用帧、模块加载、定时器调度)
object/ 运行时对象系统(Number/Array/Map/Promise/Observable...)
runtime/ 全局环境 Environment
stdlib/ 标准库与宿主 API 实现(含 gx/solid 响应式信号)
gfx/ 自研 GUI 渲染层(软件光栅化、布局、命中测试、win32/X11 后端)
packager/ jsbuild 打包器(GUI 应用、交叉编译)
dbgtool/ 词法分析调试工具(打印 Token 流)
npm/ goxjs npm 包(跨平台二进制分发)
scripts/ 构建脚本(build-npm.sh:交叉编译 npm 包二进制)
.github/workflows/ CI(打 v* tag 自动构建并发布 npm 包)
docs/ 文档
test/ 测试相关:bench/ 性能剖析基准(fib、函数调用、对象操作、数值解析),testdata/ 示例与测试脚本

开发

go test ./...     # 运行全部测试 (bytecode/compiler/lexer/object/parser/runtime/vm)
go run ./test/bench   # 生成 cpu.prof 性能剖析
go run ./dbgtool     # 查看词法分析的 Token 流

深入参与开发(新增标准库 API、理解回调桥与内存管理)请阅读 docs/js-runtime-api-tutorial.md。

发版流程:修改 npm/package.json 的 version → 提交 → 打 tag(如 v0.1.0)→ push,CI 自动交叉编译全平台二进制并 npm publish(需在仓库 Secrets 配置 NPM_TOKEN)。

许可证

Apache License 2.0

Documentation

Overview

Package main 是 Gox 的入口点。 提供交互式 REPL 和脚本执行功能。

统一注册当前平台的 GUI 窗口后端 (gfx/backend 按构建标签选择: linux→x11, darwin→cocoa, 其余平台无后端)。

Directories

Path Synopsis
Package bytecode 定义了虚拟机的字节码指令集。
Package bytecode 定义了虚拟机的字节码指令集。
Package compiler 将 AST 编译为字节码。
Package compiler 将 AST 编译为字节码。
gfx
Package gfx 提供 Gox 的自研 GUI 渲染层 (P2: Windows 软件渲染)。
Package gfx 提供 Gox 的自研 GUI 渲染层 (P2: Windows 软件渲染)。
backend
Package backend 按构建平台选择窗口后端: 此文件在 Linux 构建时 注册 gfx/x11 (纯 Go X11 协议绑定 jezek/xgb, 无 cgo)。
Package backend 按构建平台选择窗口后端: 此文件在 Linux 构建时 注册 gfx/x11 (纯 Go X11 协议绑定 jezek/xgb, 无 cgo)。
cocoa
Package cocoa 是 gfx 的 macOS 窗口后端 —— 当前为**编译级占位实现** (Create 返回明确错误), 运行时路径分析与后备方案见 IDLE_TASK_REPORT_P4.md。
Package cocoa 是 gfx 的 macOS 窗口后端 —— 当前为**编译级占位实现** (Create 返回明确错误), 运行时路径分析与后备方案见 IDLE_TASK_REPORT_P4.md。
win32
Package win32 是 gfx 的 Windows 窗口后端: 纯标准库 syscall 调用 user32/gdi32, 不引入 cgo 与任何第三方依赖。
Package win32 是 gfx 的 Windows 窗口后端: 纯标准库 syscall 调用 user32/gdi32, 不引入 cgo 与任何第三方依赖。
x11
Package x11 是 gfx 的 Linux X11 窗口后端。
Package x11 是 gfx 的 Linux X11 窗口后端。
Package object 定义了 JavaScript 运行时中的所有值类型。
Package object 定义了 JavaScript 运行时中的所有值类型。
jsbuild 将 JavaScript 文件打包成独立的可执行程序。
jsbuild 将 JavaScript 文件打包成独立的可执行程序。
Package runtime 提供 JavaScript 运行时的基础组件: - Environment: 作用域环境链 (块作用域 + const 检查) - Iterator: 迭代器协议 (for...of)
Package runtime 提供 JavaScript 运行时的基础组件: - Environment: 作用域环境链 (块作用域 + const 检查) - Iterator: 迭代器协议 (for...of)
Package stdlib 提供 JavaScript 标准库实现。
Package stdlib 提供 JavaScript 标准库实现。
test
bench command
Package vm 实现了 JavaScript 的栈式字节码虚拟机。
Package vm 实现了 JavaScript 的栈式字节码虚拟机。

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL