Skip to content

Commit

Permalink
Fix passing large arrays with JS values into Wasm detaching memory (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
daxpedda authored Dec 15, 2024
1 parent 37f0aa1 commit 033e50a
Show file tree
Hide file tree
Showing 7 changed files with 45 additions and 11 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@
3. The name of an imported function if the function is not a method and does not have a `js_namespace` or `module` attribute.
- Using JS keywords on imports in places other than the above will no longer cause the keywords to be escaped as `_{keyword}`.

* Fixed passing large arrays into Rust failing because of internal memory allocations invalidating the memory buffer.
[#4353](https://github.com/rustwasm/wasm-bindgen/pull/4353)

--------------------------------------------------------------------------------

## [0.2.99](https://github.com/rustwasm/wasm-bindgen/compare/0.2.98...0.2.99)
Expand Down
12 changes: 5 additions & 7 deletions crates/cli-support/src/js/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1641,34 +1641,32 @@ __wbg_set_wasm(wasm);"
let add = self.expose_add_to_externref_table(table, alloc)?;
self.global(&format!(
"
function {}(array, malloc) {{
function {ret}(array, malloc) {{
const ptr = malloc(array.length * 4, 4) >>> 0;
const mem = {}();
for (let i = 0; i < array.length; i++) {{
mem.setUint32(ptr + 4 * i, {}(array[i]), true);
const add = {add}(array[i]);
{mem}().setUint32(ptr + 4 * i, add, true);
}}
WASM_VECTOR_LEN = array.length;
return ptr;
}}
",
ret, mem, add,
));
}
_ => {
self.expose_add_heap_object();
self.global(&format!(
"
function {}(array, malloc) {{
function {ret}(array, malloc) {{
const ptr = malloc(array.length * 4, 4) >>> 0;
const mem = {}();
const mem = {mem}();
for (let i = 0; i < array.length; i++) {{
mem.setUint32(ptr + 4 * i, addHeapObject(array[i]), true);
}}
WASM_VECTOR_LEN = array.length;
return ptr;
}}
",
ret, mem,
));
}
}
Expand Down
4 changes: 2 additions & 2 deletions crates/cli/tests/reference/echo.js
Original file line number Diff line number Diff line change
Expand Up @@ -666,9 +666,9 @@ function addToExternrefTable0(obj) {

function passArrayJsValueToWasm0(array, malloc) {
const ptr = malloc(array.length * 4, 4) >>> 0;
const mem = getDataViewMemory0();
for (let i = 0; i < array.length; i++) {
mem.setUint32(ptr + 4 * i, addToExternrefTable0(array[i]), true);
const add = addToExternrefTable0(array[i]);
getDataViewMemory0().setUint32(ptr + 4 * i, add, true);
}
WASM_VECTOR_LEN = array.length;
return ptr;
Expand Down
4 changes: 2 additions & 2 deletions crates/cli/tests/reference/typescript-type.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@ function addToExternrefTable0(obj) {

function passArrayJsValueToWasm0(array, malloc) {
const ptr = malloc(array.length * 4, 4) >>> 0;
const mem = getDataViewMemory0();
for (let i = 0; i < array.length; i++) {
mem.setUint32(ptr + 4 * i, addToExternrefTable0(array[i]), true);
const add = addToExternrefTable0(array[i]);
getDataViewMemory0().setUint32(ptr + 4 * i, add, true);
}
WASM_VECTOR_LEN = array.length;
return ptr;
Expand Down
8 changes: 8 additions & 0 deletions tests/wasm/js_vec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
const assert = require('assert');
const wasm = require('wasm-bindgen-test');

// Test if passing large arrays which cause allocation in Wasm are properly handled.
exports.pass_array_with_allocation = () => {
const values = new Array(10_000).fill(1)
assert.strictEqual(wasm.test_sum(values), 10_000);
};
24 changes: 24 additions & 0 deletions tests/wasm/js_vec.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
use js_sys::Number;
use wasm_bindgen::prelude::wasm_bindgen;
use wasm_bindgen_test::wasm_bindgen_test;

#[wasm_bindgen(module = "tests/wasm/js_vec.js")]
extern "C" {
fn pass_array_with_allocation();
}

#[wasm_bindgen]
pub fn test_sum(param: Vec<Number>) -> f64 {
let mut sum = 0.;

for data in param {
sum += data.value_of();
}

sum
}

#[wasm_bindgen_test]
fn test() {
pass_array_with_allocation();
}
1 change: 1 addition & 0 deletions tests/wasm/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ pub mod inner_self;
pub mod intrinsics;
pub mod js_keywords;
pub mod js_objects;
pub mod js_vec;
pub mod jscast;
pub mod link_to;
pub mod macro_rules;
Expand Down

0 comments on commit 033e50a

Please sign in to comment.