[Web Audio] createScriptProcessor throws IndexSizeError for valid arguments
authorjer.noble@apple.com <jer.noble@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 8 Jun 2017 04:31:31 +0000 (04:31 +0000)
committerjer.noble@apple.com <jer.noble@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 8 Jun 2017 04:31:31 +0000 (04:31 +0000)
https://bugs.webkit.org/show_bug.cgi?id=173022

Reviewed by Sam Weinig.

Source/WebCore:

Updated test: webaudio/javascriptaudionode.html

The Web Audio spec (<https://webaudio.github.io/web-audio-api/>, 06 June 2017) defines a default behavior when
clients pass in a value of 0 for bufferSize to the createScriptProcessor() method.

* Modules/webaudio/AudioContext.cpp:
(WebCore::AudioContext::createScriptProcessor):
* Modules/webaudio/AudioContext.idl:
* Modules/webaudio/ScriptProcessorNode.cpp:
(WebCore::ScriptProcessorNode::create):
* Modules/webaudio/ScriptProcessorNode.h:

LayoutTests:

* webaudio/javascriptaudionode-expected.txt:
* webaudio/javascriptaudionode.html:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@217919 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/webaudio/javascriptaudionode-expected.txt
LayoutTests/webaudio/javascriptaudionode.html
Source/WebCore/ChangeLog
Source/WebCore/Modules/webaudio/AudioContext.cpp
Source/WebCore/Modules/webaudio/AudioContext.idl
Source/WebCore/Modules/webaudio/ScriptProcessorNode.cpp
Source/WebCore/Modules/webaudio/ScriptProcessorNode.h

index 35a7734..2463cdb 100644 (file)
@@ -1,3 +1,13 @@
+2017-06-07  Jer Noble  <jer.noble@apple.com>
+
+        [Web Audio] createScriptProcessor throws IndexSizeError for valid arguments
+        https://bugs.webkit.org/show_bug.cgi?id=173022
+
+        Reviewed by Sam Weinig.
+
+        * webaudio/javascriptaudionode-expected.txt:
+        * webaudio/javascriptaudionode.html:
+
 2017-06-07  Chris Dumez  <cdumez@apple.com>
 
         CSSStyleRule.style / CSSPageRule.style / CSSKeyframeRule.style should be settable
index ed4bf82..7f1aad8 100644 (file)
@@ -8,6 +8,7 @@ PASS Successfully created ScriptProcessorNode with numberOfInputChannels = 2 and
 PASS Successfully created ScriptProcessorNode with numberOfInputChannels = 0 and numberOfOutputChannels = 1.
 PASS Successfully created ScriptProcessorNode with numberOfInputChannels = 0 and numberOfOutputChannels = 2.
 PASS Exception was thrown for illegal bufferSize.
+PASS Successfully created ScriptProcessorNode with bufferSize = 0.
 PASS Successfully created ScriptProcessorNode with bufferSize = 256.
 PASS Successfully created ScriptProcessorNode with bufferSize = 512.
 PASS Successfully created ScriptProcessorNode with bufferSize = 1024.
index 66a2e10..6dd4ecd 100644 (file)
@@ -123,6 +123,7 @@ function runTest() {
         testPassed("Exception was thrown for illegal bufferSize.");
     }
 
+    doBufferSizeTest(0);
     doBufferSizeTest(256);
     doBufferSizeTest(512);
     doBufferSizeTest(1024);
index d047e71..c3c72c8 100644 (file)
@@ -1,3 +1,22 @@
+2017-06-07  Jer Noble  <jer.noble@apple.com>
+
+        [Web Audio] createScriptProcessor throws IndexSizeError for valid arguments
+        https://bugs.webkit.org/show_bug.cgi?id=173022
+
+        Reviewed by Sam Weinig.
+
+        Updated test: webaudio/javascriptaudionode.html
+
+        The Web Audio spec (<https://webaudio.github.io/web-audio-api/>, 06 June 2017) defines a default behavior when
+        clients pass in a value of 0 for bufferSize to the createScriptProcessor() method.
+
+        * Modules/webaudio/AudioContext.cpp:
+        (WebCore::AudioContext::createScriptProcessor):
+        * Modules/webaudio/AudioContext.idl:
+        * Modules/webaudio/ScriptProcessorNode.cpp:
+        (WebCore::ScriptProcessorNode::create):
+        * Modules/webaudio/ScriptProcessorNode.h:
+
 2017-06-07  Chris Dumez  <cdumez@apple.com>
 
         CSSStyleRule.style / CSSPageRule.style / CSSKeyframeRule.style should be settable
index 884d62c..64727d5 100644 (file)
@@ -37,6 +37,7 @@
 #include "AudioListener.h"
 #include "AudioNodeInput.h"
 #include "AudioNodeOutput.h"
+#include "AudioSession.h"
 #include "BiquadFilterNode.h"
 #include "ChannelMergerNode.h"
 #include "ChannelSplitterNode.h"
@@ -488,13 +489,58 @@ ExceptionOr<Ref<ScriptProcessorNode>> AudioContext::createScriptProcessor(size_t
 {
     ASSERT(isMainThread());
     lazyInitialize();
-    auto node = ScriptProcessorNode::create(*this, m_destinationNode->sampleRate(), bufferSize, numberOfInputChannels, numberOfOutputChannels);
 
-    if (!node)
+    // W3C Editor's Draft 06 June 2017
+    //  https://webaudio.github.io/web-audio-api/#widl-BaseAudioContext-createScriptProcessor-ScriptProcessorNode-unsigned-long-bufferSize-unsigned-long-numberOfInputChannels-unsigned-long-numberOfOutputChannels
+
+    // The bufferSize parameter determines the buffer size in units of sample-frames. If it's not passed in,
+    // or if the value is 0, then the implementation will choose the best buffer size for the given environment,
+    // which will be constant power of 2 throughout the lifetime of the node. ... If the value of this parameter
+    // is not one of the allowed power-of-2 values listed above, an IndexSizeError must be thrown.
+    switch (bufferSize) {
+    case 0:
+#if USE(AUDIO_SESSION)
+        // Pick a value between 256 (2^8) and 16384 (2^14), based on the buffer size of the current AudioSession:
+        bufferSize = 1 << std::max<size_t>(8, std::min<size_t>(14, std::log2(AudioSession::sharedSession().bufferSize())));
+#else
+        bufferSize = 2048;
+#endif
+        break;
+    case 256:
+    case 512:
+    case 1024:
+    case 2048:
+    case 4096:
+    case 8192:
+    case 16384:
+        break;
+    default:
         return Exception { INDEX_SIZE_ERR };
+    }
 
-    refNode(*node); // context keeps reference until we stop making javascript rendering callbacks
-    return node.releaseNonNull();
+    // An IndexSizeError exception must be thrown if bufferSize or numberOfInputChannels or numberOfOutputChannels
+    // are outside the valid range. It is invalid for both numberOfInputChannels and numberOfOutputChannels to be zero.
+    // In this case an IndexSizeError must be thrown.
+
+    if (!numberOfInputChannels && !numberOfOutputChannels)
+        return Exception { NOT_SUPPORTED_ERR };
+
+    // This parameter [numberOfInputChannels] determines the number of channels for this node's input. Values of
+    // up to 32 must be supported. A NotSupportedError must be thrown if the number of channels is not supported.
+
+    if (numberOfInputChannels > maxNumberOfChannels())
+        return Exception { NOT_SUPPORTED_ERR };
+
+    // This parameter [numberOfOutputChannels] determines the number of channels for this node's output. Values of
+    // up to 32 must be supported. A NotSupportedError must be thrown if the number of channels is not supported.
+
+    if (numberOfOutputChannels > maxNumberOfChannels())
+        return Exception { NOT_SUPPORTED_ERR };
+
+    auto node = ScriptProcessorNode::create(*this, m_destinationNode->sampleRate(), bufferSize, numberOfInputChannels, numberOfOutputChannels);
+
+    refNode(node); // context keeps reference until we stop making javascript rendering callbacks
+    return WTFMove(node);
 }
 
 Ref<BiquadFilterNode> AudioContext::createBiquadFilter()
index e5226a3..a114202 100644 (file)
@@ -85,7 +85,7 @@ enum AudioContextState {
     ConvolverNode createConvolver();
     DynamicsCompressorNode createDynamicsCompressor();
     AnalyserNode createAnalyser();
-    [MayThrowException] ScriptProcessorNode createScriptProcessor(unsigned long bufferSize, optional unsigned long numberOfInputChannels = 2, optional unsigned long numberOfOutputChannels = 2);
+    [MayThrowException] ScriptProcessorNode createScriptProcessor(optional unsigned long bufferSize = 0, optional unsigned long numberOfInputChannels = 2, optional unsigned long numberOfOutputChannels = 2);
     OscillatorNode createOscillator();
     [MayThrowException] PeriodicWave createPeriodicWave(Float32Array real, Float32Array imag);
 
index b95e093..250f83e 100644 (file)
 
 namespace WebCore {
 
-RefPtr<ScriptProcessorNode> ScriptProcessorNode::create(AudioContext& context, float sampleRate, size_t bufferSize, unsigned numberOfInputChannels, unsigned numberOfOutputChannels)
+Ref<ScriptProcessorNode> ScriptProcessorNode::create(AudioContext& context, float sampleRate, size_t bufferSize, unsigned numberOfInputChannels, unsigned numberOfOutputChannels)
 {
-    // Check for valid buffer size.
-    switch (bufferSize) {
-    case 256:
-    case 512:
-    case 1024:
-    case 2048:
-    case 4096:
-    case 8192:
-    case 16384:
-        break;
-    default:
-        return nullptr;
-    }
-
-    if (!numberOfInputChannels && !numberOfOutputChannels)
-        return nullptr;
-
-    if (numberOfInputChannels > AudioContext::maxNumberOfChannels())
-        return nullptr;
-
-    if (numberOfOutputChannels > AudioContext::maxNumberOfChannels())
-        return nullptr;
-
     return adoptRef(*new ScriptProcessorNode(context, sampleRate, bufferSize, numberOfInputChannels, numberOfOutputChannels));
 }
 
index 4c6bafe..67c144f 100644 (file)
@@ -51,7 +51,7 @@ public:
     // This value controls how frequently the onaudioprocess event handler is called and how many sample-frames need to be processed each call.
     // Lower numbers for bufferSize will result in a lower (better) latency. Higher numbers will be necessary to avoid audio breakup and glitches.
     // The value chosen must carefully balance between latency and audio quality.
-    static RefPtr<ScriptProcessorNode> create(AudioContext&, float sampleRate, size_t bufferSize, unsigned numberOfInputChannels, unsigned numberOfOutputChannels);
+    static Ref<ScriptProcessorNode> create(AudioContext&, float sampleRate, size_t bufferSize, unsigned numberOfInputChannels, unsigned numberOfOutputChannels);
 
     virtual ~ScriptProcessorNode();