24

有没有办法在没有 JavaScript 的情况下获得对 DOM 和/或 WebAPI(即全屏 API)的读/写访问权限?

我正在尝试用 C 构建一个基本应用程序(C 源代码实际上是从 GC 语言转换的结果)。我正在构建的应用程序将作为桌面应用程序运行(它还不打算在“真实”浏览器中运行),因此我可以在必要时调整环境(即布局引擎)。

4

4 回答 4

16

在 WebAssembly Minimal Viable Product 中,调用和调用 WebAssembly 的唯一方法是通过导入和导出。将来,WebAssembly 可能会获得允许嵌入器直接公开 API 的功能,在嵌入的浏览器中,这可能包括 DOM。

不过,导入导出并不是很复杂:从 C 代码的角度来看,它们只是一个extern调用,类似于 Windows 平台上的 DLL。您可能会使用 Emscripten 编译 C 代码,请参阅其文档“从 C/C++ 调用 JavaScript 函数”以了解有关其工作原理的详细信息(因为这不是您要问的问题,但我猜这是下一个问题)。


从您的问题中不清楚您是否:

  1. 想要编译 C 代码并在浏览器中的 WebAssembly 中运行
  2. 想要编译 C 代码并在浏览器外部的 WebAssembly 中运行它。

或两者。

于 2017-03-06T15:58:19.173 回答
7

这完全取决于编译器的能力。

目前无法直接访问 DOM 或任何其他浏览器 API。也无法将 JavaScript 引用存储在 Wasm 线性内存或 Wasm 表中。也不可能将 JavaScript 引用用作函数参数或返回值。它们只是不存在于 MVP 类型系统中。但是,有参考类型提案,它有朝一日可能成为 Wasm 运行时的一部分,但没有可用的官方发布日期。

那么,Wasm 到 Host Environment 的交互怎么做呢?好吧,事实证明,具有导入和导出功能的 Wasm 模块系统可用于创建仿真层。手动创建这一层很痛苦,因此编译器创建它是一项很好的任务。但是怎么做?

例如,我们想在当前浏览器窗口中设置文档标题。Wasm 需要访问当前窗口实例,选择文档,并设置它的 title 属性。由于 Wasm 运行时无法访问引用,我们需要在 JS 端创建一个映射表和一些具有映射逻辑的 JS 函数,并将它们导入到 Wasm 模块中。

因此,我们创建了一个名为 getWindow 的函数。此函数获取全局窗口引用,将其放入映射表并返回表中的索引。该索引将作为 Wasm 端的 I32 访问。这个函数被导入到 Wasm 模块中。

现在,我们创建一个名为 getDocumentFromWindow 的函数。此函数获取映射表的索引,并返回另一个索引。该实现从映射表中查找窗口引用并解析其文档属性,并将此文档放入映射表并将该索引返回给 Wasm。这个函数也被导入到 Wasm 模块中。

在 Wasm 方面,我们现在可以通过导入的函数间接操作 Wasm 主机引用。我们的映射表通过整数索引模拟 JS 引用。这是 Wasm Reference Type 提案可能附带的较慢版本。

所以这整个映射逻辑可以由编译器创建。一旦引用类型可用,就可以更改编译器并使用新的类型系统来获得更高效的代码。

如果您想看到这种编译器在运行,请查看https://github.com/mirkosertic/Bytecoder。它可以将 JVM 字节码编译为 JavaScript 和 WebAssembly,并为 DOM 和 Browser API 两种方式的交互提供透明的方式。可以从 Wasm 调用 DOM,也可以从 DOM 调用 Wasm,例如实现 click-listeners 和其他很酷的东西,例如与 vue.js 等高级框架的交互。

免责声明:我是 Bytecoder 的发明者,但所描述的逻辑可以适用于任何其他编译器。

于 2018-12-28T12:55:07.153 回答
4

对于 WebAssembly 中的 JS 对象会是什么样子,WebAssembly 的人似乎还没有任何明确的想法。

我会查看 PR #1080,这是关于垃圾收集规范现在被剥离到它自己的仓库中的。但是在发生这种情况的同时,他们正在删除唯一提到的 web 平台和与规范中存在的 JS 对象的互操作,这被描述为:

它比具体更令人向往,

于 2017-07-07T00:57:33.687 回答
3

我刚刚遇到 js_ffi
https://github.com/richardanaya/js_ffi
不确定它是否也适用于 C,但它是这样宣传的。

于 2020-07-15T08:21:24.457 回答