aboutsummaryrefslogtreecommitdiffstats
path: root/components/script
diff options
context:
space:
mode:
authorbors-servo <lbergstrom+bors@mozilla.com>2018-09-19 04:07:04 -0400
committerGitHub <noreply@github.com>2018-09-19 04:07:04 -0400
commit0866dabc425307c992e6d13d34e4a2cb8109d874 (patch)
treeaf4e0847790d5f414534682c3edfb5ea9adfb416 /components/script
parent3889041cc657940b9a60d16987a4746ed7a860a3 (diff)
parent9b356334d5c33ffd703b9f7836af905365b0c61e (diff)
downloadservo-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.rs98
-rw-r--r--components/script/dom/audiobuffersourcenode.rs46
-rw-r--r--components/script/dom/webidls/AudioBufferSourceNode.webidl2
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;