diff options
author | bors-servo <lbergstrom+bors@mozilla.com> | 2018-09-19 04:07:04 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-09-19 04:07:04 -0400 |
commit | 0866dabc425307c992e6d13d34e4a2cb8109d874 (patch) | |
tree | af4e0847790d5f414534682c3edfb5ea9adfb416 /components/script | |
parent | 3889041cc657940b9a60d16987a4746ed7a860a3 (diff) | |
parent | 9b356334d5c33ffd703b9f7836af905365b0c61e (diff) | |
download | servo-0866dabc425307c992e6d13d34e4a2cb8109d874.tar.gz servo-0866dabc425307c992e6d13d34e4a2cb8109d874.zip |
Auto merge of #21602 - ferjm:audiobuffer.crash, r=Manishearth
Fix all AudioBuffer WPTs
- [X] `./mach build -d` does not report any errors
- [x] `./mach test-tidy` does not report any errors
- [X] There are tests for these changes
<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/21602)
<!-- Reviewable:end -->
Diffstat (limited to 'components/script')
-rw-r--r-- | components/script/dom/audiobuffer.rs | 98 | ||||
-rw-r--r-- | components/script/dom/audiobuffersourcenode.rs | 46 | ||||
-rw-r--r-- | components/script/dom/webidls/AudioBufferSourceNode.webidl | 2 |
3 files changed, 89 insertions, 57 deletions
diff --git a/components/script/dom/audiobuffer.rs b/components/script/dom/audiobuffer.rs index 761bcde404b..a7b7467f14c 100644 --- a/components/script/dom/audiobuffer.rs +++ b/components/script/dom/audiobuffer.rs @@ -77,7 +77,9 @@ impl AudioBuffer { window: &Window, options: &AudioBufferOptions, ) -> Fallible<DomRoot<AudioBuffer>> { - if options.numberOfChannels > MAX_CHANNEL_COUNT || + if options.length <= 0 || + options.numberOfChannels <= 0 || + options.numberOfChannels > MAX_CHANNEL_COUNT || *options.sampleRate < MIN_SAMPLE_RATE || *options.sampleRate > MAX_SAMPLE_RATE { @@ -92,51 +94,46 @@ impl AudioBuffer { )) } + // Initialize the underlying channels data with initial data provided by + // the user or silence otherwise. #[allow(unsafe_code)] pub fn set_channels(&self, initial_data: Option<&[Vec<f32>]>) { - let global = self.global(); - let cx = global.get_cx(); - let _ac = JSAutoCompartment::new(cx, global.reflector().get_jsobject().get()); - let chans = self.js_channels.borrow_mut(); for channel in 0..self.number_of_channels { - rooted!(in (cx) let mut array = ptr::null_mut::<JSObject>()); - match initial_data { - Some(data) => { - let _ = unsafe { - Float32Array::create( - cx, - CreateWith::Slice(data[channel as usize].as_slice()), - array.handle_mut(), - ) - }; - }, - None => { - let _ = unsafe { - Float32Array::create( - cx, - CreateWith::Slice(&vec![0.; self.length as usize]), - array.handle_mut(), - ) - }; - }, - } - chans[channel as usize].set(array.get()); + (*self.shared_channels.borrow_mut()).buffers[channel as usize] = match initial_data { + Some(data) => data[channel as usize].clone(), + None => vec![0.; self.length as usize], + }; } } + pub fn get_channels(&self) -> ServoMediaAudioBuffer { + self.shared_channels.borrow().clone() + } + #[allow(unsafe_code)] unsafe fn restore_js_channel_data(&self, cx: *mut JSContext) -> bool { + let global = self.global(); + let _ac = JSAutoCompartment::new(cx, global.reflector().get_jsobject().get()); for (i, channel) in self.js_channels.borrow_mut().iter().enumerate() { if !channel.get().is_null() { // Already have data in JS array. + // We may have called GetChannelData, and web content may have modified + // js_channels. So make sure that shared_channels contains the same data as + // js_channels. + typedarray!(in(cx) let array: Float32Array = channel.get()); + if let Ok(array) = array { + (*self.shared_channels.borrow_mut()).buffers[i] = array.to_vec(); + } continue; } - // Move the channel data from shared_channels to js_channels. + // Copy the channel data from shared_channels to js_channels. rooted!(in (cx) let mut array = ptr::null_mut::<JSObject>()); - let shared_channel = (*self.shared_channels.borrow_mut()).buffers.remove(i); - if Float32Array::create(cx, CreateWith::Slice(&shared_channel), array.handle_mut()) - .is_err() + if Float32Array::create( + cx, + CreateWith::Slice(&(*self.shared_channels.borrow_mut()).buffers[i]), + array.handle_mut(), + ).is_err() { return false; } @@ -182,8 +179,6 @@ impl AudioBuffer { // data into js_channels ArrayBuffers in restore_js_channel_data. } - self.js_channels.borrow_mut().clear(); - Some((*self.shared_channels.borrow()).clone()) } } @@ -237,7 +232,11 @@ impl AudioBufferMethods for AudioBuffer { channel_number: u32, start_in_channel: u32, ) -> Fallible<()> { - if channel_number >= self.number_of_channels || start_in_channel > self.length { + if destination.is_shared() { + return Err(Error::Type("Cannot copy to shared buffer".to_owned())); + } + + if channel_number >= self.number_of_channels || start_in_channel >= self.length { return Err(Error::IndexSize); } @@ -248,18 +247,16 @@ impl AudioBufferMethods for AudioBuffer { let mut dest = Vec::with_capacity(destination.len()); // We either copy form js_channels or shared_channels. - let js_channel = self.js_channels.borrow()[channel_number].get(); if !js_channel.is_null() { typedarray!(in(cx) let array: Float32Array = js_channel); if let Ok(array) = array { let data = unsafe { array.as_slice() }; dest.extend_from_slice(&data[offset..offset + bytes_to_copy]); - return Ok(()); } - } - - if let Some(shared_channel) = self.shared_channels.borrow().buffers.get(channel_number) { + } else if let Some(shared_channel) = + self.shared_channels.borrow().buffers.get(channel_number) + { dest.extend_from_slice(&shared_channel.as_slice()[offset..offset + bytes_to_copy]); } @@ -278,6 +275,10 @@ impl AudioBufferMethods for AudioBuffer { channel_number: u32, start_in_channel: u32, ) -> Fallible<()> { + if source.is_shared() { + return Err(Error::Type("Cannot copy from shared buffer".to_owned())); + } + if channel_number >= self.number_of_channels || start_in_channel > (source.len() as u32) { return Err(Error::IndexSize); } @@ -293,12 +294,23 @@ impl AudioBufferMethods for AudioBuffer { return Err(Error::IndexSize); } - typedarray!(in(cx) let array: Float32Array = js_channel); - if let Ok(mut array) = array { + typedarray!(in(cx) let js_channel: Float32Array = js_channel); + if let Ok(mut js_channel) = js_channel { let bytes_to_copy = min(self.length - start_in_channel, source.len() as u32) as usize; - let offset = start_in_channel as usize; unsafe { - array.update(&source.as_slice()[offset..offset + bytes_to_copy]); + let data = &source.as_slice()[0..bytes_to_copy]; + // Update shared channel. + { + let mut shared_channels = self.shared_channels.borrow_mut(); + let shared_channel = shared_channels.data_chan_mut(channel_number as u8); + let (_, mut shared_channel) = + shared_channel.split_at_mut(start_in_channel as usize); + shared_channel[0..bytes_to_copy].copy_from_slice(data); + } + // Update js channel. + js_channel.update( + self.shared_channels.borrow().buffers[channel_number as usize].as_slice(), + ); } } else { return Err(Error::IndexSize); diff --git a/components/script/dom/audiobuffersourcenode.rs b/components/script/dom/audiobuffersourcenode.rs index 3e7948fdb3e..e2056535386 100644 --- a/components/script/dom/audiobuffersourcenode.rs +++ b/components/script/dom/audiobuffersourcenode.rs @@ -72,7 +72,7 @@ impl AudioBufferSourceNode { f32::MIN, f32::MAX, ); - Ok(AudioBufferSourceNode { + let node = AudioBufferSourceNode { source_node, buffer: Default::default(), playback_rate: Dom::from_ref(&playback_rate), @@ -80,7 +80,15 @@ impl AudioBufferSourceNode { loop_enabled: Cell::new(options.loop_), loop_start: Cell::new(*options.loopStart), loop_end: Cell::new(*options.loopEnd), - }) + }; + if let Some(ref buffer) = options.buffer { + if let Some(ref buffer) = buffer { + if let Err(err) = node.SetBuffer(Some(&**buffer)) { + return Err(err); + } + } + } + Ok(node) } #[allow(unrooted_must_root)] @@ -119,11 +127,13 @@ impl AudioBufferSourceNodeMethods for AudioBufferSourceNode { if self.source_node.started() { if let Some(buffer) = self.buffer.get() { let buffer = buffer.acquire_contents(); - self.source_node - .node() - .message(AudioNodeMessage::AudioBufferSourceNode( - AudioBufferSourceNodeMessage::SetBuffer(buffer), - )); + if buffer.is_some() { + self.source_node + .node() + .message(AudioNodeMessage::AudioBufferSourceNode( + AudioBufferSourceNodeMessage::SetBuffer(buffer), + )); + } } } @@ -197,11 +207,13 @@ impl AudioBufferSourceNodeMethods for AudioBufferSourceNode { if let Some(buffer) = self.buffer.get() { let buffer = buffer.acquire_contents(); - self.source_node - .node() - .message(AudioNodeMessage::AudioBufferSourceNode( - AudioBufferSourceNodeMessage::SetBuffer(buffer), - )); + if buffer.is_some() { + self.source_node + .node() + .message(AudioNodeMessage::AudioBufferSourceNode( + AudioBufferSourceNodeMessage::SetBuffer(buffer), + )); + } } self.source_node .upcast::<AudioScheduledSourceNode>() @@ -212,7 +224,15 @@ impl AudioBufferSourceNodeMethods for AudioBufferSourceNode { impl<'a> From<&'a AudioBufferSourceOptions> for AudioBufferSourceNodeOptions { fn from(options: &'a AudioBufferSourceOptions) -> Self { Self { - buffer: None, + buffer: if let Some(ref buffer) = options.buffer { + if let Some(ref buffer) = buffer { + Some(buffer.get_channels()) + } else { + None + } + } else { + None + }, detune: *options.detune, loop_enabled: options.loop_, loop_end: Some(*options.loopEnd), diff --git a/components/script/dom/webidls/AudioBufferSourceNode.webidl b/components/script/dom/webidls/AudioBufferSourceNode.webidl index a91a6afc393..bd8b4f5b0ae 100644 --- a/components/script/dom/webidls/AudioBufferSourceNode.webidl +++ b/components/script/dom/webidls/AudioBufferSourceNode.webidl @@ -7,7 +7,7 @@ */ dictionary AudioBufferSourceOptions { -// AudioBuffer? buffer; + AudioBuffer? buffer; float detune = 0; boolean loop = false; double loopEnd = 0; |