WebAssembly Polyfill (prototype)

实验性的 WebAssembly polyfill 库和工具。「Experimental WebAssembly polyfill library and tools」

  • Owner: lukewagner/polyfill-prototype-1
  • Platform: Linux, Mac, Windows
  • License:: Apache License 2.0
  • Category::
  • Topic:
  • Like:
    0
      Compare:

Github stars Tracking Chart

WebAssembly Polyfill(原型)

这个仓库包含了一个原型,用来展示 WebAssembly polyfill 的可行性。其他仓库的工作正在进行中,以设计实际的标准二进制格式。这个原型也没有尝试调用本地浏览器解码,所以从技术上讲,它不是一个 polyfill,而是一个纯 JS 库。

演示

请参阅 FAQ 条目

(目前)如何运作

一个真正的(非原型)polyfill 将挂到 ES6模块加载器 polyfill 中,这样加载一个 WebAssembly 模块就会正常工作。这里描述的方案只是一个概念证明,说明 polyfill 如何避免大量复制、字符串操作和垃圾。

  1. 在主线程上,客户端通过调用来启动URL的加载 loadWebAssembly 并接收 Promise<Function>。
  2. polyfill 库启动一个包含 asm.js 代码的工作程序 unpack.cpp 连接在 glue 代码中 load-wasm-worker.js
  3. Worker glue 代码通过 XHR 获取二进制文件,然后将结果复制到 asm.js 堆中。
  4. asm.js 代码在 asm.js 堆的单独区域中以 UTF8 字节的形式将二进制解码为 asm.js。
  5. Worker glue 代码仅从 asm.js UTF8 字节的视图创建 Blob (只读副本)。
  6. Blob 是 postMessage() 回到主线程(非复制操作),它用 script.src = URL.getObjectURL(blob)作为脚本元素加载。
  7. 当 asm.js 脚本被执行时,它将 asm.js 模块函数对象传递给一个回调,该回调解析了步骤1中的承诺。

构建说明

jslib/ 中的库应该已经可以使用了,只需要复制这两个文件,然后调用loadWebAssembly()。

运行 make 将 C++ 实现编译成 jslib/ 中的 JS 文件,再编译成 tools/ 中的本地可执行文件。(Makefile目前超级不方便移植,抱歉!欢迎打补丁。)

将 asm.js 打包成二进制格式

polyfill 还附带了一个工具(tools/pack-asmjs),可以将一个 JS 文件(只包含 asm.js)编译成由库解码的(实验性的) WebAssembly 格式。给定一个现有的 asm.js 应用程序,可以通过以下步骤来试验这种多级填充(执行直接的大小/加载时间比较):

  1. 将 asm.js 模块分成单独的文件。
  2. 运行 tools/pack-asmjs 生成 .wasm 文件。
  3. 重构调用 asm.js 模块的代码,而不是调用 loadWebAssembly() (它返回一个承诺,解析到未链接的 asm.js 模块函数)。

未来的工作

  • 下载时解码(使用HTTP Range 请求或分割成单独的文件)
  • 在 .wasm 文件之上执行通用压缩(例如, lzham 比 gzip 提供了24%的提升)。


Main metrics

Overview
Name With Ownerlukewagner/polyfill-prototype-1
Primary LanguageC++
Program languageMakefile (Language Count: 6)
PlatformLinux, Mac, Windows
License:Apache License 2.0
所有者活动
Created At2015-04-29 17:40:11
Pushed At2016-05-06 14:44:32
Last Commit At2016-05-06 09:44:31
Release Count0
用户参与
Stargazers Count241
Watchers Count52
Fork Count42
Commits Count40
Has Issues Enabled
Issues Count6
Issue Open Count5
Pull Requests Count8
Pull Requests Open Count1
Pull Requests Close Count4
项目设置
Has Wiki Enabled
Is Archived
Is Fork
Is Locked
Is Mirror
Is Private

WebAssembly Polyfill (prototype)

This repo contains a prototype built to demonstrate the
viability of a WebAssembly polyfill. Work is ongoing in other repos to design
the actual standard binary format. This prototype also makes no attempt to call
native browser decoding and so it is not, technically, a polyfill but rather a
pure JS library.

Demos

See FAQ entry.

How it (currently) works

A real (non-prototype) polyfill would hook into an ES6 Module loader
polyfill
so that loading a
WebAssembly module will Just Work. The scheme described here is just a proof of
concept for how the polyfill can avoid massive copying, string manipulation and
garbage.

  1. On the main thread, the client kicks off a load of a URL by calling
    loadWebAssembly
    and receives a Promise<Function>.
  2. The polyfill library starts up a worker containing asm.js code compiled from
    unpack.cpp
    concatenated with the glue code in
    load-wasm-worker.js.
  3. The worker glue code fetches the binary via XHR then copies the result into the asm.js heap.
  4. The asm.js code decodes the binary into asm.js in the form of UTF8 bytes in a separate region of the asm.js heap.
  5. The worker glue code creates a Blob (a read-only copy) from a view of just the asm.js UTF8 bytes.
  6. The Blob is postMessage()ed back to the main thread (a non-copying
    operation) where it is loaded as a script element with script.src = URL.getObjectURL(blob).
  7. When the asm.js script is executed, it passes the asm.js module function
    object to a callback which resolves the promise in step 1.

Build instructions

The library in jslib/ should be ready to use, just copy both files and call loadWebAssembly().

Running make compiles the C++ implementation into the JS files in jslib/ and
into native executables in tools/. (The Makefile is currently super-unportable.
Sorry! Patches welcome.)

Packing asm.js into the binary format

The polyfill also comes with a tool (tools/pack-asmjs) that compiles a single JS
file (containing only asm.js) into the (experimental) WebAssembly format decoded by
the library. Given an existing asm.js application, one can experiment with this
polyfill (perform direct size/load-time comparisons) by following the steps:

  1. Separate the asm.js module out into a separate file.
  2. Run tools/pack-asmjs to produce a .wasm file.
  3. Refactor the code that called the asm.js module to instead call loadWebAssembly()
    (which returns a promise that resolves to the unlinked asm.js module function).

Future work

  • Decode while downloading (using HTTP Range requests or splitting into separate files)
  • Perform generic compression on top of the .wasm file (e.g.,
    lzham gives a further 24% boost over gzip).