diff --git a/.gitignore b/.gitignore index aedc2d91aed..4bc7132ff97 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ yarn.lock *.d.ts /publish /publish.exe +.vscode diff --git a/crates/js-sys/src/lib.rs b/crates/js-sys/src/lib.rs index edb8bbe4e5f..61cf8ccfc1a 100644 --- a/crates/js-sys/src/lib.rs +++ b/crates/js-sys/src/lib.rs @@ -4792,6 +4792,31 @@ macro_rules! arrays { ) } + /// Creates a JS typed array which is a view into wasm's linear + /// memory at the specified pointer with specified length. + /// + /// This function returns a new typed array which is a view into + /// wasm's memory. This view does not copy the underlying data. + /// + /// # Unsafety + /// + /// Views into WebAssembly memory are only valid so long as the + /// backing buffer isn't resized in JS. Once this function is called + /// any future calls to `Box::new` (or malloc of any form) may cause + /// the returned value here to be invalidated. Use with caution! + /// + /// Additionally the returned object can be safely mutated, + /// the changes are guranteed to be reflected in the input array. + pub unsafe fn view_mut_raw(ptr: *mut $ty, length: usize) -> $name { + let buf = wasm_bindgen::memory(); + let mem = buf.unchecked_ref::(); + $name::new_with_byte_offset_and_length( + &mem.buffer(), + ptr as u32, + length as u32 + ) + } + fn raw_copy_to(&self, dst: &mut [$ty]) { let buf = wasm_bindgen::memory(); let mem = buf.unchecked_ref::(); diff --git a/crates/js-sys/tests/wasm/Array.js b/crates/js-sys/tests/wasm/Array.js new file mode 100644 index 00000000000..8810bd9db88 --- /dev/null +++ b/crates/js-sys/tests/wasm/Array.js @@ -0,0 +1,6 @@ +// Used for `Array.rs` tests +exports.populate_array = function(arr, start, len) { + for (i = 0; i < len; i++) { + arr[i] = start + i; + } +}; diff --git a/crates/js-sys/tests/wasm/Array.rs b/crates/js-sys/tests/wasm/Array.rs index 46e6f1d6736..44050325d86 100644 --- a/crates/js-sys/tests/wasm/Array.rs +++ b/crates/js-sys/tests/wasm/Array.rs @@ -1,5 +1,6 @@ use js_sys::*; use std::iter::FromIterator; +use wasm_bindgen::prelude::*; use wasm_bindgen::JsCast; use wasm_bindgen::JsValue; use wasm_bindgen_test::*; @@ -466,3 +467,87 @@ fn array_inheritance() { assert!(array.is_instance_of::()); let _: &Object = array.as_ref(); } + +#[wasm_bindgen(module = "tests/wasm/Array.js")] +extern "C" { + fn populate_array(arr: JsValue, start: JsValue, len: JsValue) -> JsValue; +} + +fn test_array_view_mut_raw( + sut: unsafe fn(*mut ElemT, usize) -> ArrT, + u8ToElem: fn(u8) -> ElemT, + arrToJsValue: fn(ArrT) -> JsValue, +) { + let start: u8 = 10; + let len: usize = 32; + let end: u8 = start + len as u8; + let mut buffer: Vec = Vec::new(); + buffer.reserve(len); + unsafe { + let array: ArrT = sut(buffer.as_mut_ptr(), len); + populate_array( + arrToJsValue(array), + JsValue::from(start), + JsValue::from(len as u32), + ); + buffer.set_len(len); + } + let expected: Vec = (start..end).map(u8ToElem).collect(); + assert_eq!(buffer, expected) +} + +#[wasm_bindgen_test] +fn Int8Array_view_mut_raw() { + fn u8Toi8_unsafe(x: u8) -> i8 { + x as i8 + } + test_array_view_mut_raw( + js_sys::Int8Array::view_mut_raw, + u8Toi8_unsafe, + JsValue::from, + ); +} + +#[wasm_bindgen_test] +fn Int16Array_view_mut_raw() { + test_array_view_mut_raw(js_sys::Int16Array::view_mut_raw, i16::from, JsValue::from); +} + +#[wasm_bindgen_test] +fn Int32Array_view_mut_raw() { + test_array_view_mut_raw(js_sys::Int32Array::view_mut_raw, i32::from, JsValue::from); +} + +#[wasm_bindgen_test] +fn Uint8Array_view_mut_raw() { + test_array_view_mut_raw(js_sys::Uint8Array::view_mut_raw, u8::from, JsValue::from); +} + +#[wasm_bindgen_test] +fn Uint8ClampedArray_view_mut_raw() { + test_array_view_mut_raw( + js_sys::Uint8ClampedArray::view_mut_raw, + u8::from, + JsValue::from, + ); +} + +#[wasm_bindgen_test] +fn Uint16Array_view_mut_raw() { + test_array_view_mut_raw(js_sys::Uint16Array::view_mut_raw, u16::from, JsValue::from); +} + +#[wasm_bindgen_test] +fn Uint32Array_view_mut_raw() { + test_array_view_mut_raw(js_sys::Uint32Array::view_mut_raw, u32::from, JsValue::from); +} + +#[wasm_bindgen_test] +fn Float32Array_view_mut_raw() { + test_array_view_mut_raw(js_sys::Float32Array::view_mut_raw, f32::from, JsValue::from); +} + +#[wasm_bindgen_test] +fn Float64Array_view_mut_raw() { + test_array_view_mut_raw(js_sys::Float64Array::view_mut_raw, f64::from, JsValue::from); +}