diff --git a/swf/src/string.rs b/swf/src/string.rs index c14ee5cc9..2acb37c83 100644 --- a/swf/src/string.rs +++ b/swf/src/string.rs @@ -19,11 +19,12 @@ pub struct SwfStr { } impl SwfStr { - /// Create a new `SwfStr` from a byte slice with a given encoding. - /// The string will be truncated if a null byte is encountered. + /// Create a new `SwfStr` from a byte slice. /// The data is not required to be valid for the given encoding. #[inline] pub fn from_bytes(string: &[u8]) -> &Self { + // SAFETY: Casting is safe because internal representations are + // the same, see repr(transparent). unsafe { &*(string as *const [u8] as *const Self) } } diff --git a/web/src/audio.rs b/web/src/audio.rs index 7e85d8bb5..10bb0da2b 100644 --- a/web/src/audio.rs +++ b/web/src/audio.rs @@ -689,11 +689,18 @@ impl WebAudioBackend { .unwrap(); let audio_buffer = Rc::new(RefCell::new(audio_buffer)); - let data_array = unsafe { js_sys::Uint8Array::view(&audio_data[..]) }; - let array_buffer = data_array.buffer().slice_with_end( - data_array.byte_offset(), - data_array.byte_offset() + data_array.byte_length(), - ); + // Clone the audio data into an ArrayBuffer + // SAFETY: (compare with the docs for `Uint8Array::view`) + // - We don't resize WASMs backing buffer before the view is cloned + // - We don't mutate `data_array` + // - Since we clone the buffer, its lifetime is correctly disconnected from `audio_data` + let array_buffer = { + let data_array = unsafe { js_sys::Uint8Array::view(audio_data) }; + data_array.buffer().slice_with_end( + data_array.byte_offset(), + data_array.byte_offset() + data_array.byte_length(), + ) + }; NUM_SOUNDS_LOADING.with(|n| n.set(n.get() + 1));