【问题标题】:A single-file WebAssembly html demo一个单文件的 WebAssembly html 演示
【发布时间】:2019-03-06 01:08:00
【问题描述】:

我在哪里可以找到一个最简单的单文件演示,显示在 html 中使用 WebAssembly?

JavaScript 示例很简单:

<script>
function hw() { console.log("Hello, world."); }
</script>
<button onclick="hw()">HW</button>

有类似 WebAssembly 的吗?

我希望它具有类似于硬编码字节缓冲区的东西,带有一个 wasm 二进制文件,它被加载并执行它的一些微不足道的功能。以下是我期望的概要:

<script>
function hw() { 
    var wasm_code = [255, 0, 128, ..., whatever, ...];
    var magic = give_me_wasm(wasm_code);
    var x = magic.my_add(2,2);
    console.log("2 + 2 = ", x); 
}
</script>
<button onclick="hw()">HW</button>

这样的demo可以做吗,一个简单的表格,可以粘贴到开发者控制台中试一试,不需要设置任何框架和工具?

【问题讨论】:

  • 您希望它在哪里运行?在客户端?这将是一个毁灭性的安全漏洞。允许任何页面在客户端计算机上运行任意代码。顺便说一句:如果这是您尝试做的事情,那么请把我算在这个项目中:)
  • 我希望它可以在浏览器中运行(例如,来自file:// html 文件)。或者只是从开发者控制台,比如 JavaScript sn-ps。我不认为它是一个“毁灭性的安全漏洞”,因为 webasm 至少应该像 javascript 本身一样被沙盒化。
  • @TomerW WebAssembly 不是任意的可执行代码。请阅读:en.wikipedia.org/wiki/WebAssembly
  • 不知道该技术...我正在阅读它...就像在 vm 中运行...

标签: javascript html webassembly


【解决方案1】:

自己做的:

<script>
var wasm_base64;
var wasm_buffer;
var wasm;
var wasm_instance;
function hw() {
    wasm_base64 = "AGFzbQEAAAABBwFgAnx8AXwDAgEABwoBBm15X2FkZAAACgkBBwAgACABoAs=";
    wasm_buffer = Uint8Array.from(atob(wasm_base64), c => c.charCodeAt(0)).buffer;
    WebAssembly.compile(wasm_buffer).then(x => {
        wasm = x;
        wasm_instance = new WebAssembly.Instance(wasm);
        var x = wasm_instance.exports.my_add(2,2);
        console.log("2+2 = ",x);
    });
}
</script>
<button onclick="hw()">HW</button>

这是嵌入的 WebAssembly 文本表单 (q.wat):

(module
  (type (;0;) (func (param f64 f64) (result f64)))
  (func $myadd (type 0) (param f64 f64) (result f64)
    get_local 0
    get_local 1
    f64.add)
  (export "my_add" (func $myadd))
)

以下是生成 base64 缓冲区的命令行:

$ wat2wasm q.wat -o w.wasm
$ base64 -w0 w.wasm ;echo
AGFzbQEAAAABBwFgAnx8AXwDAgEABwoBBm15X2FkZAAACgkBBwAgACABoAs=

wasmwasm_instance 对象可以使用开发者控制台进行探索。

已在 Firefox 63.0b9 中检查。

【讨论】:

    【解决方案2】:

    This 是我在 Gist 上找到的一个注释很好的示例。将代码嵌入到您的 &lt;script&gt; 标记中,您将获得“单文件 WebAssembly html 演示”

    为了方便,复制到这里:

    // this code is from a simple add function in c:
    //
    // // hello.c
    // int add(int a, int b) {
    //    return a + b;
    // }
    
    //
    // compiles it with emcc (http://webassembly.org/getting-started/developers-guide/)
    // $ git clone https://github.com/juj/emsdk.git
    // $ cd emsdk
    // $ ./emsdk install latest
    // $ ./emsdk activate latest
    // $ source ./emsdk_env.sh --build=Release
    //
    // once installed:
    //
    // $ emcc hello.c -s ONLY_MY_CODE=1 -s WASM=1 -s EXPORTED_FUNCTIONS="['_add']" -o hello.js
    //
    // yes, not sure why we have to add '_' in front of the exported function.
    // take the hello.wasm and serialize it to base64, e.g. using node
    
    // const code = fs.readFileSync('./hello.wasm')
    // code.toString('base64')
    // AGFzbQEAAAABCwJgAX8AYAJ/fwF/An4HA2VudgZtZW1vcnkCAYACgAIDZW52BXRhYmxlAXABAAADZW52Cm1lbW9yeUJhc2UDfwADZW52CXRhYmxlQmFzZQN/AANlbnYIU1RBQ0tUT1ADfwADZW52CVNUQUNLX01BWAN/AANlbnYSYWJvcnRTdGFja092ZXJmbG93AAADAgEBBhMDfwEjAgt/ASMDC30BQwAAAAALBwgBBF9hZGQAAQkBAAo7ATkBB38jBCEIIwRBEGokBCMEIwVOBEBBEBAACyAAIQIgASEDIAIhBCADIQUgBCAFaiEGIAgkBCAGDws=
    
    
    // https://www.npmjs.com/package/base64-arraybuffer
    const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    
    // Use a lookup table to find the index.
    const lookup = new Uint8Array(256);
    for (let i = 0; i < chars.length; i++) {
        lookup[chars.charCodeAt(i)] = i;
    }
    
    function decode(base64) {
      var bufferLength = base64.length * 0.75,
          len = base64.length, i, p = 0,
          encoded1, encoded2, encoded3, encoded4;
    
      if (base64[base64.length - 1] === "=") {
        bufferLength--;
        if (base64[base64.length - 2] === "=") {
          bufferLength--;
        }
      }
    
      var arraybuffer = new ArrayBuffer(bufferLength),
          bytes = new Uint8Array(arraybuffer);
    
      for (i = 0; i < len; i+=4) {
        encoded1 = lookup[base64.charCodeAt(i)];
        encoded2 = lookup[base64.charCodeAt(i+1)];
        encoded3 = lookup[base64.charCodeAt(i+2)];
        encoded4 = lookup[base64.charCodeAt(i+3)];
    
        bytes[p++] = (encoded1 << 2) | (encoded2 >> 4);
        bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2);
        bytes[p++] = ((encoded3 & 3) << 6) | (encoded4 & 63);
      }
    
      return arraybuffer;
    } 
    
    // this is the serialized code.
    const code = 'AGFzbQEAAAABCwJgAX8AYAJ/fwF/An4HA2VudgZtZW1vcnkCAYACgAIDZW52BXRhYmxlAXABAAADZW52Cm1lbW9yeUJhc2UDfwADZW52CXRhYmxlQmFzZQN/AANlbnYIU1RBQ0tUT1ADfwADZW52CVNUQUNLX01BWAN/AANlbnYSYWJvcnRTdGFja092ZXJmbG93AAADAgEBBhMDfwEjAgt/ASMDC30BQwAAAAALBwgBBF9hZGQAAQkBAAo7ATkBB38jBCEIIwRBEGokBCMEIwVOBEBBEBAACyAAIQIgASEDIAIhBCADIQUgBCAFaiEGIAgkBCAGDws='
    const buffer = decode(code)
    
    // bootstrap the env.
    const memory = new WebAssembly.Memory({ initial: 256, maximum: 256 })
    const importObj = {
        env: {
            abortStackOverflow: () => { throw new Error('overflow'); },
            table: new WebAssembly.Table({ initial: 0, maximum: 0, element: 'anyfunc' }),
            tableBase: 0,
            memory: memory,
            memoryBase: 1024,
            STACKTOP: 0,
            STACK_MAX: memory.buffer.byteLength,
        }
    }
    
    // instantiate
    WebAssembly.instantiate(buffer, importObj)
      // take a look at that _add.
      .then(({module, instance}) => { console.log(instance.exports._add(1, 2)) })
      .catch((err) => { console.log(err.message) })
    

    【讨论】:

      猜你喜欢
      • 2017-03-30
      • 2021-09-20
      • 1970-01-01
      • 2019-08-30
      • 2020-04-11
      • 2010-09-07
      • 1970-01-01
      • 2014-09-08
      • 1970-01-01
      相关资源
      最近更新 更多