原文连接:https://fanmingfei.com/posts/...html
这是系列文章第二篇:git
WebAssembly中的内存与JavaScript中的内存有所不一样。使用WebAssembly,您能够直接访问原始字节码...这可能使人担心。可是,它的确比你想象中的要安全。浏览器
当 WebAssembly 模块被实例化时,它须要一个 memory 对象。你能够建立一个新的WebAssembly.Memory并传递该对象。若是没有建立 memory 对象,在模块实例化的时候将会自动建立,而且传递给实例。安全
JS引擎建立一个ArrayBuffer(我在另外一篇文章中解释)来作这件事情。ArrayBuffer 是 JS 引用的 JavaScript 对象。JS 为你分配内存。你告诉它须要多少内存,它会建立一个对应大小的ArrayBuffer。函数
数组的索引能够视为内存地址。若是你须要增长它的内存,你可使用 grow
方法让数组变大。post
ArrayBuffer 作了两件事情,一件是作 WebAssembly 的内存,另一件是作 JavaScript 的对象。编码
它使 JS 和 WebAssembly 之间传递内容更方便。
使内存管理更安全。
由于 ArrayBuffer 是一个 JavaScript 对象,这意味着 JavaScript 也能够获取到这个 memory 中的字节。因此经过这种方式, WebAssembly 和 JavaScript 能够共享内存,而且相互传值。
使用数组索引来访问每一个字节,而不是使用内存地址。
好比,WebAssembly 想将一个字符串写入内存。它须要将字符串转换成字节码。
而后把这些字节码放进数组。
而后将字符串所在的内存位置的第一个位置,也就是数组的某个索引,传递给 JavaScript。JavaScript 能够根据索引从 ArrayBuffer 中拿到字符串
如今,不少人并不知道如何在 JavaScript 中使用字节码。你须要将字节码转换为有用的内容,好比说字符串。
在一些浏览器中,你可使用TextDecoder和TextEncoderAPI来处理。或者你能够在你的js文件里添加一些帮助函数。好比,Emscripten就能够帮你添加编码和解码的方法。
因此,WebAssembly memory 最好的地方就是它是一个 JS 对象。WebAssembly 和 JavaScript 能够直接使用 memory 互相传值。
另一个好处是,WebAssembly memory 只是一个 JavaScript 对象:安全。经过防止浏览器级内存泄漏并提供内存隔离,使事情变得更安全。
正如我在内存管理的文章中提到的,当你管理本身的内存时,你可能会忘记清除它。这可能致使系统内存不足。
若是 WebAssembly 模块实例直接访问内存,而且若是在超出范围以前忘记清除该内存,那么浏览器可能会泄漏内存。
由于内存对象只是一个JavaScript对象,因此它自己就被垃圾回收器跟踪(尽管它的内容不会垃圾回收)。
也就是说,WebAssembly 实例被移除之后,全部的内存数组将会被回收。
当人们听到WebAssembly让你直接访问内存时,他们可能有点紧张。他们认为,一个恶意的 WebAssembly 模块可能会进入并在内存中干坏事,这是绝对不容许的。但事实并不是如此。
ArrayBuffer 提供了边界。WebAssembly 模块能够直接管理的内存是受限制的。
它能够直接管理该数组内部的字节,但它看不到任何超出此数组范围的内容。
例如,内存中的任何其它 JS 对象,如 window 对象,WebAssembly没法访问。这对安全性很是重要。
每当 WebAssembly 中有操做内存时,引擎会进行数组限制检查,以确保该地址位于 WebAssembly 实例的内存中。
若是代码尝试访问超出范围的地址,引擎将抛出异常。这保护了其它的内存。
因此这就是 memory 相关的内容。在下一篇文章中,咱们将看研究一些关于安全性的其它类型的 import 数据:table import。
Lin 是Mozilla Developer Relations团队的工程师。她使用 JavaScript、WebAssembly、Rust 和 Servo,也画一些漫画。