diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b54342ea..84a3bc21 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,11 +50,14 @@ jobs: # We're using Windows rather than Ubuntu to run the wasm tests because caching cargo-web # doesn't currently work on Linux. - { target: wasm32-unknown-unknown, os: windows-latest, } + include: + - rust_version: nightly + - { target: wasm32-unknown-unknown, os: windows-latest, options: -Zbuild-std=panic_abort,std, rustflags: -Ctarget-feature=+atomics } env: RUST_BACKTRACE: 1 CARGO_INCREMENTAL: 0 - RUSTFLAGS: "-C debuginfo=0 --deny warnings" + RUSTFLAGS: "-C debuginfo=0 --deny warnings ${{ matrix.platform.rustflags }}" OPTIONS: ${{ matrix.platform.options }} FEATURES: ${{ format(',{0}', matrix.platform.features ) }} CMD: ${{ matrix.platform.cmd }} diff --git a/Cargo.toml b/Cargo.toml index 11f7db2d..0ec287d6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -48,6 +48,7 @@ foreign-types = "0.3.0" objc = "0.2.7" [target.'cfg(target_arch = "wasm32")'.dependencies] +js-sys = "0.3.55" wasm-bindgen = "0.2.78" [target.'cfg(target_arch = "wasm32")'.dependencies.web-sys] diff --git a/src/web.rs b/src/web.rs index 49df5e79..9f371960 100644 --- a/src/web.rs +++ b/src/web.rs @@ -3,7 +3,6 @@ #![allow(clippy::uninlined_format_args)] use raw_window_handle::WebWindowHandle; -use wasm_bindgen::Clamped; use wasm_bindgen::JsCast; use web_sys::CanvasRenderingContext2d; use web_sys::HtmlCanvasElement; @@ -142,9 +141,33 @@ impl<'a> BufferImpl<'a> { .flat_map(|pixel| [(pixel >> 16) as u8, (pixel >> 8) as u8, pixel as u8, 255]) .collect(); + #[cfg(target_feature = "atomics")] + let result = { + use js_sys::{Uint8Array, Uint8ClampedArray}; + use wasm_bindgen::prelude::wasm_bindgen; + use wasm_bindgen::JsValue; + + #[wasm_bindgen] + extern "C" { + #[wasm_bindgen(js_name = ImageData)] + type ImageDataExt; + + #[wasm_bindgen(catch, constructor, js_class = ImageData)] + fn new(array: Uint8ClampedArray, sw: u32) -> Result; + } + + let array = Uint8Array::new_with_length(bitmap.len() as u32); + array.copy_from(&bitmap); + let array = Uint8ClampedArray::new(&array); + ImageDataExt::new(array, self.imp.width) + .map(JsValue::from) + .map(ImageData::unchecked_from_js) + }; + #[cfg(not(target_feature = "atomics"))] + let result = + ImageData::new_with_u8_clamped_array(wasm_bindgen::Clamped(&bitmap), self.imp.width); // This should only throw an error if the buffer we pass's size is incorrect. - let image_data = - ImageData::new_with_u8_clamped_array(Clamped(&bitmap), self.imp.width).unwrap(); + let image_data = result.unwrap(); // This can only throw an error if `data` is detached, which is impossible. self.imp.ctx.put_image_data(&image_data, 0.0, 0.0).unwrap();