WebAssembly,也称为 WASM,是一种标准,定义了一种低级编程语言,适合 (A) 作为从许多其他语言交叉编译的目标,以及 (B) 通过浏览器中的虚拟机运行。它考虑到通过 JavaScript 进行脚本编写,提供了一种将 C 代码(以及其他代码)编译为 WASM 并通过 JavaScript 对其进行脚本编写的方法,尽管 JavaScript 和 C 之间存在巨大差异,但摩擦相对较小。
人们从 早在 2012 年就开始为 Web 构建 sqlite3,但此子项目是第一个“正式”与 SQLite 项目相关的努力,其目标是使库的 WASM 构建成为受支持的 SQLite 可交付成果系列中的一等成员。
此项目的具体目标
此项目的具体目标包括…
除非在非目标中另有说明,否则在 WASM 与 C 的功能奇偶校验允许的范围内,提供一个或多或少功能齐全的 sqlite3 C API 包装器。事实上,提供 至少以下 API…
- 绑定一个低级 sqlite3 API,该 API 在使用方面尽可能接近原生 API。
- 一个更高级别的 OO API,更类似于 sql.js 和 node.js 风格的实现。此 API 直接与低级 API 交互。此 API 必须从与低级 API 相同的线程中使用。
- 一个基于 Worker 的 API,通过 Worker 消息与之前的 API 交互。此 API 旨在在主线程中使用,将较低级别的 API 安装在 Worker 线程中,并通过 Worker 消息与它们进行通信。因为 Worker 是异步的并且只有一个消息通道,所以这里需要一些杂技来将异步工作结果反馈给客户端(因为我们不能简单地在主线程和 Worker 线程之间传递回调)。
- 一个基于 Promise 的 Worker API 变体(上述第 3 点),完全隐藏了跨线程通信方面的内容。
在可能的情况下,使用可用的 JS API 支持持久客户端存储。在撰写本文时,这包括 Origin-Private 文件系统 (OPFS) 和通过
window.localStorage
和window.sessionStorage
后端 进行的(非常有限的)存储。
具体非目标
我们特别不打算实现的目标
由于 WASM 是一种以 Web 为中心的技术,而 UTF-8 是该领域中的编码之王,因此目前没有计划支持与 UTF16 相关的 sqlite3 API。它们会增加绑定的复杂性,而不会带来任何明显的益处。
尽管对浏览器外 WASM 运行时的支持很广泛,但此项目目前仅专注于浏览器目标。虽然与 Web 相关的实现细节优先,并且 API 的 JavaScript 组件专门针对浏览器客户端,但较低级别的 WASM 模块“应该”可以在非 Web WASM 环境中工作,假设环境可以提供 WASM 文件需要的“导入”。
支持旧平台或利基市场平台。WASM是为现代 Web 构建的,需要现代平台。同样,已弃用的 sqlite3 库选项不包含在 WASM 接口中。
归属
一些项目在我们的发展道路上给予了极大的帮助。我们非常感谢(按照我们调查的顺序)…
Emscripten
截至撰写本文时,Emscripten WASM 工具链是唯一可用的功能齐全的 WASM 工具链。尽管存在其他工具链,但 Emscripten 提供了一些其他工具链没有的“杀手级特性”,最值得注意的是对 POSIX 文件 I/O API 的透明仿真,这允许 sqlite3 在 WASM 构建中按原样运行,无需任何更改或调整。
此外,Emscripten 开发人员在 基于 OPFS 的功能的开发过程中提供了宝贵的支持。
sql.js
https://github.com/sql-js/sql.js
Alon Zakai 的 sql.js
是此代码开发中的一个重要垫脚石,因为它演示了如何处理一些与 WASM 相关的“巫术”(例如处理指向指针的指针和添加 C 绑定回调函数的 JS 实现)。但是,这些 API 的形状与 sql.js
大不相同。
据我们所知,sql.js
是 第一个发布的用于 Web 的 sqlite3。
absurd-sql
https://github.com/jlongster/absurd-sql
James Long 的恰如其分地命名为 absurd-sql
通过将数据库存储在 IndexedDB 存储中来演示持久化的浏览器端 sqlite3。我们尝试过这种方法,但它不适合我们。即便如此,它也是一个有趣的实验。
wa-sqlite
https://github.com/rhashimoto/wa-sqlite
Roy Hashimoto 的 wa-sqlite
是第一个公开 sqlite3 的 OPFS 存储选项的项目。它还全面演示了如何使用其他方面很大程度上未记录的 OPFS API。