Skip to content

Commit 033e50a

Browse files
authored
Fix passing large arrays with JS values into Wasm detaching memory (#4353)
1 parent 37f0aa1 commit 033e50a

File tree

7 files changed

+45
-11
lines changed

7 files changed

+45
-11
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@
3737
3. The name of an imported function if the function is not a method and does not have a `js_namespace` or `module` attribute.
3838
- Using JS keywords on imports in places other than the above will no longer cause the keywords to be escaped as `_{keyword}`.
3939

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

4245
## [0.2.99](https://github.com/rustwasm/wasm-bindgen/compare/0.2.98...0.2.99)

crates/cli-support/src/js/mod.rs

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1641,34 +1641,32 @@ __wbg_set_wasm(wasm);"
16411641
let add = self.expose_add_to_externref_table(table, alloc)?;
16421642
self.global(&format!(
16431643
"
1644-
function {}(array, malloc) {{
1644+
function {ret}(array, malloc) {{
16451645
const ptr = malloc(array.length * 4, 4) >>> 0;
1646-
const mem = {}();
16471646
for (let i = 0; i < array.length; i++) {{
1648-
mem.setUint32(ptr + 4 * i, {}(array[i]), true);
1647+
const add = {add}(array[i]);
1648+
{mem}().setUint32(ptr + 4 * i, add, true);
16491649
}}
16501650
WASM_VECTOR_LEN = array.length;
16511651
return ptr;
16521652
}}
16531653
",
1654-
ret, mem, add,
16551654
));
16561655
}
16571656
_ => {
16581657
self.expose_add_heap_object();
16591658
self.global(&format!(
16601659
"
1661-
function {}(array, malloc) {{
1660+
function {ret}(array, malloc) {{
16621661
const ptr = malloc(array.length * 4, 4) >>> 0;
1663-
const mem = {}();
1662+
const mem = {mem}();
16641663
for (let i = 0; i < array.length; i++) {{
16651664
mem.setUint32(ptr + 4 * i, addHeapObject(array[i]), true);
16661665
}}
16671666
WASM_VECTOR_LEN = array.length;
16681667
return ptr;
16691668
}}
16701669
",
1671-
ret, mem,
16721670
));
16731671
}
16741672
}

crates/cli/tests/reference/echo.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -666,9 +666,9 @@ function addToExternrefTable0(obj) {
666666

667667
function passArrayJsValueToWasm0(array, malloc) {
668668
const ptr = malloc(array.length * 4, 4) >>> 0;
669-
const mem = getDataViewMemory0();
670669
for (let i = 0; i < array.length; i++) {
671-
mem.setUint32(ptr + 4 * i, addToExternrefTable0(array[i]), true);
670+
const add = addToExternrefTable0(array[i]);
671+
getDataViewMemory0().setUint32(ptr + 4 * i, add, true);
672672
}
673673
WASM_VECTOR_LEN = array.length;
674674
return ptr;

crates/cli/tests/reference/typescript-type.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,9 @@ function addToExternrefTable0(obj) {
4949

5050
function passArrayJsValueToWasm0(array, malloc) {
5151
const ptr = malloc(array.length * 4, 4) >>> 0;
52-
const mem = getDataViewMemory0();
5352
for (let i = 0; i < array.length; i++) {
54-
mem.setUint32(ptr + 4 * i, addToExternrefTable0(array[i]), true);
53+
const add = addToExternrefTable0(array[i]);
54+
getDataViewMemory0().setUint32(ptr + 4 * i, add, true);
5555
}
5656
WASM_VECTOR_LEN = array.length;
5757
return ptr;

tests/wasm/js_vec.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
const assert = require('assert');
2+
const wasm = require('wasm-bindgen-test');
3+
4+
// Test if passing large arrays which cause allocation in Wasm are properly handled.
5+
exports.pass_array_with_allocation = () => {
6+
const values = new Array(10_000).fill(1)
7+
assert.strictEqual(wasm.test_sum(values), 10_000);
8+
};

tests/wasm/js_vec.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
use js_sys::Number;
2+
use wasm_bindgen::prelude::wasm_bindgen;
3+
use wasm_bindgen_test::wasm_bindgen_test;
4+
5+
#[wasm_bindgen(module = "tests/wasm/js_vec.js")]
6+
extern "C" {
7+
fn pass_array_with_allocation();
8+
}
9+
10+
#[wasm_bindgen]
11+
pub fn test_sum(param: Vec<Number>) -> f64 {
12+
let mut sum = 0.;
13+
14+
for data in param {
15+
sum += data.value_of();
16+
}
17+
18+
sum
19+
}
20+
21+
#[wasm_bindgen_test]
22+
fn test() {
23+
pass_array_with_allocation();
24+
}

tests/wasm/main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ pub mod inner_self;
4040
pub mod intrinsics;
4141
pub mod js_keywords;
4242
pub mod js_objects;
43+
pub mod js_vec;
4344
pub mod jscast;
4445
pub mod link_to;
4546
pub mod macro_rules;

0 commit comments

Comments
 (0)