原文連接: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,也畫一些漫畫。