当绝大多数开发者将目光投向 WebAssembly 与边缘计算时,一个名为 MacSurf 的项目却在做一件看似 "逆行" 的事:为 1999 年发布的 Classic Mac OS 9 构建一款能够渲染现代网页的浏览器。这款基于 NetSurf 分支的浏览器不仅支持 CSS Grid、Flexbox 等 150 余个 CSS 属性,更在 2026 年 5 月实现了原生 TLS 1.3 支持 —— 这是首个在 Classic Mac OS 上完整实现 RFC 8446 的浏览器项目。
协议栈移植:BearSSL 与 TLS 1.3 的 Carbon 化
现代 HTTPS 的门槛在 2016 年后迅速抬高,TLS 1.0/1.1 的废弃让 Classic Mac OS 上的旧版浏览器几乎无法访问任何生产环境网站。MacSurf 的解决方案是引入 BearSSL 作为底层密码学库,并在其之上构建 macTLS—— 一个专为 OS 9 设计的原生 TLS 层。
移植工作的核心挑战在于将 BearSSL 的纯 C 实现与 Classic Mac OS 的编程范式对接。项目采用 CodeWarrior 8 Pro 作为编译器,严格遵循 C89 标准以确保与 1999 年开发环境的兼容性。在 TLS 1.3 实现中,macTLS 支持 X25519、secp256r1 (P-256) 和 secp384r1 (P-384) 三种椭圆曲线,通过 supported_groups 扩展在 ClientHello 中通告能力。
关键工程决策在于对 HelloRetryRequest 的处理。当服务器仅支持 NIST 曲线(如 68kmla.org 的 XenForum 配置)时,macTLS 能够正确接收 HRR 消息并重新协商密钥交换参数,最终通过 P-384 完成握手。这一机制使得 MacSurf 能够直接访问现代 HTTPS 站点,无需依赖 TLS 剥离代理。
可落地参数:
- 曲线优先级:X25519 > P-256 > P-384(兼顾性能与兼容性)
- 密码套件:ChaCha20-Poly1305 与 AES-128-GCM 双支持
- 根证书:内置 121 个 Mozilla CA 证书锚点
- 内存占用:TLS 握手期间堆分配控制在 512KB 以内
JavaScript 引擎裁剪:Duktape 在 64MB 内存中的生存策略
在 233MHz PowerPC G3 处理器与 64MB 内存的硬件约束下运行现代 JavaScript 需要精确的裁剪策略。MacSurf 选用 Duktape 2.7.0 作为脚本引擎,这是一个专为嵌入式环境设计的 ES5 实现,默认配置即可在 256KB 堆内存中运行。
项目对 Duktape 的配置优化集中在三个维度:
内存池管理:通过 DUK_USE_POOL_ALLOC 启用内存池分配器,将频繁的 malloc/free 调用替换为固定大小的池分配。在 Mac OS 9 的协作式多任务环境中,这避免了内存碎片导致的堆增长。
功能子集选择:关闭 ES6+ 特性、禁用 Proxy 和 Reflect、限制正则表达式引擎的递归深度。最终保留的核心功能包括闭包、原型链、JSON 解析与 Promise(通过 polyfill 实现)。
执行超时机制:在 JavaScript 执行循环中插入检查点,当单脚本执行超过 5 秒时触发终止。这防止了复杂页面的脚本阻塞整个浏览器。
性能基准显示,Ackermann 函数 ackermann(3, 7) 在 233MHz G3 上执行耗时约 6 秒 —— 这一数据为开发者提供了脚本复杂度的直观参考。
Carbon API 到 Web 标准的映射层
MacSurf 的渲染管线需要将现代 Web 标准映射到 Classic Mac OS 的原生 API。这一映射层由三个核心组件构成:
QuickDraw 绘图抽象:NetSurf 的 plotter 接口被适配到 QuickDraw 的 GWorld 双缓冲机制。CSS 变换(rotate、scale、translate)通过整数 Q15 正弦 / 余弦查表实现,避免了对 FPU 的依赖,支持任意角度旋转而无需硬件浮点单元。
Open Transport 网络层:HTTP/1.1 协议栈基于 Open Transport 的 TCP 实现,支持 chunked 编码、keep-alive 连接与 3xx 重定向。连接池管理 15 秒无进度超时,在单线程环境中实现并发请求调度。
Carbon UI 集成:浏览器外壳使用 Carbon API 构建,支持多窗口、工具栏、状态栏与下载管理器。地址栏与导航按钮采用原生控件,确保与 OS 9 界面风格一致。
CSS 布局引擎支持约 150 个属性,包括 CSS Grid V1(含 grid-template-columns/rows 与 gap)、Flexbox、自定义属性(var())、渐变、变换与层叠上下文。PNG 透明通道通过 QuickTime Graphics Importer 解码,结合 CopyMask 实现 per-pixel alpha 混合。
工程启示与限制边界
MacSurf 的技术路线为遗留系统现代化提供了可复用的方法论:
协议栈降级策略:当完整 TLS 1.3 实现不可行时,可保留 TLS 1.2 核心并仅升级密钥交换组件。BearSSL 的模块化设计允许按需裁剪算法实现。
内存预算分配:在 64MB 总内存中,建议按以下比例划分:渲染引擎 24MB、JavaScript 堆 16MB、图像缓存 12MB、TLS / 网络 8MB、系统预留 4MB。
渐进式特性交付:项目采用版本化里程碑(v0.1a1 至 v1.3.1),每个版本聚焦单一核心能力(如 v1.3 专注 TLS 1.3,v1.3.1 扩展多曲线支持)。
然而,项目也存在明确的限制边界:React 等重型 SPA 框架因 JavaScript 执行效率与内存占用问题无法运行;视频、音频、WebGL 等多媒体特性未在路线图内;现代 CSS 的某些高级特性(如容器查询)仍在开发中。
对于需要在类似受限环境(如工业控制系统的旧版嵌入式 Linux)部署 Web 能力的开发者,MacSurf 的三重移植工程 —— 协议栈、脚本引擎、渲染层 —— 提供了经过验证的参考实现。
资料来源
- GitHub: mplsllc/macsurf — A modern web browser for Classic Mac OS 9 PowerPC
- 68kmla.org 论坛讨论帖:MacSurf — a real NetSurf-based browser for Mac OS 9
内容声明:本文无广告投放、无付费植入。
如有事实性问题,欢迎发送勘误至 i@hotdrydog.com。