Bug 11130010 - Backout new AudioNode.disconnect methods; r=mreavy,karlt,smaug, a=ritu
authorDan Minor <dminor@mozilla.com>
Tue, 16 Aug 2016 15:26:35 -0400
changeset 348154 1514a037b750bffb09b86b585f487269210bf1af
parent 348153 9f8472060b5eaad0bc976f07b932981366a938dd
child 348155 f2fee5c32af52323cb91b977f9b4e56f81036a0d
push id6389
push userraliiev@mozilla.com
push dateMon, 19 Sep 2016 13:38:22 +0000
treeherdermozilla-beta@01d67bfe6c81 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmreavy, karlt, smaug, ritu
bugs11130010
milestone50.0a2
Bug 11130010 - Backout new AudioNode.disconnect methods; r=mreavy,karlt,smaug, a=ritu MozReview-Commit-ID: AgHScRbICYU
dom/media/webaudio/AudioNode.cpp
dom/media/webaudio/AudioNode.h
dom/media/webaudio/ScriptProcessorNode.h
dom/media/webaudio/test/mochitest.ini
dom/media/webaudio/test/test_disconnectAll.html
dom/media/webaudio/test/test_disconnectAudioParam.html
dom/media/webaudio/test/test_disconnectAudioParamFromOutput.html
dom/media/webaudio/test/test_disconnectExceptions.html
dom/media/webaudio/test/test_disconnectFromAudioNode.html
dom/media/webaudio/test/test_disconnectFromAudioNodeAndOutput.html
dom/media/webaudio/test/test_disconnectFromAudioNodeAndOutputAndInput.html
dom/media/webaudio/test/test_disconnectFromOutput.html
dom/webidl/AudioNode.webidl
--- a/dom/media/webaudio/AudioNode.cpp
+++ b/dom/media/webaudio/AudioNode.cpp
@@ -286,19 +286,24 @@ void
 AudioNode::SendChannelMixingParametersToStream()
 {
   if (mStream) {
     mStream->SetChannelMixingParameters(mChannelCount, mChannelCountMode,
                                         mChannelInterpretation);
   }
 }
 
-bool
-AudioNode::DisconnectFromOutputIfConnected(AudioNode& aDestination, uint32_t aOutputIndex, uint32_t aInputIndex)
+void
+AudioNode::Disconnect(uint32_t aOutput, ErrorResult& aRv)
 {
+  if (aOutput >= NumberOfOutputs()) {
+    aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
+    return;
+  }
+
   WEB_AUDIO_API_LOG("%f: %s %u Disconnect()", Context()->CurrentTime(),
                     NodeType(), Id());
 
   // An upstream node may be starting to play on the graph thread, and the
   // engine for a downstream node may be sending a PlayingRefChangeHandler
   // ADDREF message to this (main) thread.  Wait for a round trip before
   // releasing nodes, to give engines receiving sound now time to keep their
   // nodes alive.
@@ -312,233 +317,60 @@ AudioNode::DisconnectFromOutputIfConnect
     {
       mNode = nullptr;
       return NS_OK;
     }
   private:
     RefPtr<AudioNode> mNode;
   };
 
-  InputNode& input = aDestination.mInputNodes[aInputIndex];
-  if (input.mInputNode != this) {
-    return false;
-  }
-  // RunAfterPendingUpdates() call below.
-  aDestination.mInputNodes.RemoveElementAt(aInputIndex);
-  // Remove one instance of 'dest' from mOutputNodes. There could be
-  // others, and it's not correct to remove them all since some of them
-  // could be for different output ports.
-  RefPtr<AudioNode> output = mOutputNodes[aOutputIndex].forget();
-  mOutputNodes.RemoveElementAt(aOutputIndex);
-  if (mStream) {
-    nsCOMPtr<nsIRunnable> runnable = new RunnableRelease(output.forget());
-    mStream->RunAfterPendingUpdates(runnable.forget());
-  }
-  return true;
-}
-
-bool
-AudioNode::DisconnectFromParamIfConnected(AudioParam& aDestination, uint32_t aOutputIndex, uint32_t aInputIndex)
-{
-  MOZ_ASSERT(aOutputIndex < mOutputParams.Length());
-  MOZ_ASSERT(aInputIndex < aDestination.InputNodes().Length());
-
-  const InputNode& input = aDestination.InputNodes()[aInputIndex];
-  if (input.mInputNode != this) {
-    return false;
-  }
-  aDestination.RemoveInputNode(aInputIndex);
-  // Remove one instance of 'dest' from mOutputParams. There could be
-  // others, and it's not correct to remove them all since some of them
-  // could be for different output ports.
-  mOutputParams.RemoveElementAt(aOutputIndex);
-  return true;
-}
-
-void
-AudioNode::Disconnect(ErrorResult& aRv)
-{
-  for (int32_t outputIndex = mOutputNodes.Length() - 1; outputIndex >= 0; --outputIndex) {
-    AudioNode* dest = mOutputNodes[outputIndex];
-    for (int32_t inputIndex = dest->mInputNodes.Length() - 1; inputIndex >= 0; --inputIndex) {
-      DisconnectFromOutputIfConnected(*dest, outputIndex, inputIndex);
-    }
-  }
-
-  for (int32_t outputIndex = mOutputParams.Length() - 1; outputIndex >= 0; --outputIndex) {
-    AudioParam* dest = mOutputParams[outputIndex];
-    for (int32_t inputIndex = dest->InputNodes().Length() - 1; inputIndex >= 0; --inputIndex) {
-      DisconnectFromParamIfConnected(*dest, outputIndex, inputIndex);
-    }
-  }
-
-  // This disconnection may have disconnected a panner and a source.
-  Context()->UpdatePannerSource();
-}
-
-void
-AudioNode::Disconnect(uint32_t aOutput, ErrorResult& aRv)
-{
-  if (aOutput >= NumberOfOutputs()) {
-    aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
-    return;
-  }
-
-  for (int32_t outputIndex = mOutputNodes.Length() - 1; outputIndex >= 0; --outputIndex) {
-    AudioNode* dest = mOutputNodes[outputIndex];
-    for (int32_t inputIndex = dest->mInputNodes.Length() - 1; inputIndex >= 0; --inputIndex) {
-      InputNode& input = dest->mInputNodes[inputIndex];
-      if (input.mOutputPort == aOutput) {
-        DisconnectFromOutputIfConnected(*dest, outputIndex, inputIndex);
+  for (int32_t i = mOutputNodes.Length() - 1; i >= 0; --i) {
+    AudioNode* dest = mOutputNodes[i];
+    for (int32_t j = dest->mInputNodes.Length() - 1; j >= 0; --j) {
+      InputNode& input = dest->mInputNodes[j];
+      if (input.mInputNode == this && input.mOutputPort == aOutput) {
+        // Destroying the InputNode here sends a message to the graph thread
+        // to disconnect the streams, which should be sent before the
+        // RunAfterPendingUpdates() call below.
+        dest->mInputNodes.RemoveElementAt(j);
+        // Remove one instance of 'dest' from mOutputNodes. There could be
+        // others, and it's not correct to remove them all since some of them
+        // could be for different output ports.
+        RefPtr<AudioNode> output = mOutputNodes[i].forget();
+        mOutputNodes.RemoveElementAt(i);
+        output->NotifyInputsChanged();
+        if (mStream) {
+          RefPtr<nsIRunnable> runnable = new RunnableRelease(output.forget());
+          mStream->RunAfterPendingUpdates(runnable.forget());
+        }
+        break;
       }
     }
   }
 
-  for (int32_t outputIndex = mOutputParams.Length() - 1; outputIndex >= 0; --outputIndex) {
-    AudioParam* dest = mOutputParams[outputIndex];
-    for (int32_t inputIndex = dest->InputNodes().Length() - 1; inputIndex >= 0; --inputIndex) {
-      const InputNode& input = dest->InputNodes()[inputIndex];
-      if (input.mOutputPort == aOutput) {
-        DisconnectFromParamIfConnected(*dest, outputIndex, inputIndex);
+  for (int32_t i = mOutputParams.Length() - 1; i >= 0; --i) {
+    AudioParam* dest = mOutputParams[i];
+    for (int32_t j = dest->InputNodes().Length() - 1; j >= 0; --j) {
+      const InputNode& input = dest->InputNodes()[j];
+      if (input.mInputNode == this && input.mOutputPort == aOutput) {
+        dest->RemoveInputNode(j);
+        // Remove one instance of 'dest' from mOutputParams. There could be
+        // others, and it's not correct to remove them all since some of them
+        // could be for different output ports.
+        mOutputParams.RemoveElementAt(i);
+        break;
       }
     }
   }
 
   // This disconnection may have disconnected a panner and a source.
   Context()->UpdatePannerSource();
 }
 
 void
-AudioNode::Disconnect(AudioNode& aDestination, ErrorResult& aRv)
-{
-  bool wasConnected = false;
-
-  size_t outputIndex = mOutputNodes.IndexOf(&aDestination);
-  if (outputIndex == nsTArray<InputNode>::NoIndex) {
-    aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
-    return;
-  }
-  for (int32_t inputIndex = aDestination.mInputNodes.Length() - 1; inputIndex >= 0; --inputIndex) {
-    wasConnected |= DisconnectFromOutputIfConnected(aDestination, outputIndex, inputIndex);
-  }
-
-  if (!wasConnected) {
-    aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
-    return;
-  }
-
-  // This disconnection may have disconnected a panner and a source.
-  Context()->UpdatePannerSource();
-}
-
-void
-AudioNode::Disconnect(AudioNode& aDestination, uint32_t aOutput, ErrorResult& aRv)
-{
-  if (aOutput >= NumberOfOutputs()) {
-    aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
-    return;
-  }
-
-  bool wasConnected = false;
-
-  for (int32_t outputIndex = mOutputNodes.Length() - 1; outputIndex >= 0; --outputIndex) {
-    for (int32_t inputIndex = aDestination.mInputNodes.Length() - 1; inputIndex >= 0; --inputIndex) {
-      InputNode& input = aDestination.mInputNodes[inputIndex];
-      if (input.mOutputPort == aOutput) {
-        wasConnected |= DisconnectFromOutputIfConnected(aDestination, outputIndex, inputIndex);
-      }
-    }
-  }
-
-  if (!wasConnected) {
-    aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
-    return;
-  }
-
-  // This disconnection may have disconnected a panner and a source.
-  Context()->UpdatePannerSource();
-}
-
-void
-AudioNode::Disconnect(AudioNode& aDestination, uint32_t aOutput, uint32_t aInput, ErrorResult& aRv)
-{
-  if (aOutput >= NumberOfOutputs()) {
-    aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
-    return;
-  }
-
-  if (aInput >= aDestination.NumberOfInputs()) {
-    aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
-    return;
-  }
-
-  bool wasConnected = false;
-
-  for (int32_t outputIndex = mOutputNodes.Length() - 1; outputIndex >= 0; --outputIndex) {
-    for (int32_t inputIndex = aDestination.mInputNodes.Length() - 1; inputIndex >= 0; --inputIndex) {
-      InputNode& input = aDestination.mInputNodes[inputIndex];
-      if (input.mOutputPort == aOutput && input.mInputPort == aInput) {
-        wasConnected |= DisconnectFromOutputIfConnected(aDestination, outputIndex, inputIndex);
-        break;
-      }
-    }
-  }
-
-  if (!wasConnected) {
-    aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
-    return;
-  }
-
-  // This disconnection may have disconnected a panner and a source.
-  Context()->UpdatePannerSource();
-}
-
-void
-AudioNode::Disconnect(AudioParam& aDestination, ErrorResult& aRv)
-{
-  bool wasConnected = false;
-
-  for (int32_t outputIndex = mOutputParams.Length() - 1; outputIndex >= 0; --outputIndex) {
-    for (int32_t inputIndex = aDestination.InputNodes().Length() - 1; inputIndex >= 0; --inputIndex) {
-        wasConnected |= DisconnectFromParamIfConnected(aDestination, outputIndex, inputIndex);
-    }
-  }
-
-  if (!wasConnected) {
-    aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
-    return;
-  }
-}
-
-void
-AudioNode::Disconnect(AudioParam& aDestination, uint32_t aOutput, ErrorResult& aRv)
-{
-  if (aOutput >= NumberOfOutputs()) {
-    aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
-    return;
-  }
-
-  bool wasConnected = false;
-
-  for (int32_t outputIndex = mOutputParams.Length() - 1; outputIndex >= 0; --outputIndex) {
-    for (int32_t inputIndex = aDestination.InputNodes().Length() - 1; inputIndex >= 0; --inputIndex) {
-      const InputNode& input = aDestination.InputNodes()[inputIndex];
-      if (input.mOutputPort == aOutput) {
-        wasConnected |= DisconnectFromParamIfConnected(aDestination, outputIndex, inputIndex);
-      }
-    }
-  }
-
-  if (!wasConnected) {
-    aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
-    return;
-  }
-}
-
-void
 AudioNode::DestroyMediaStream()
 {
   if (mStream) {
     // Remove the node pointer on the engine.
     AudioNodeStream* ns = mStream;
     MOZ_ASSERT(ns, "How come we don't have a stream here?");
     MOZ_ASSERT(ns->Engine()->NodeMainThread() == this,
                "Invalid node reference");
--- a/dom/media/webaudio/AudioNode.h
+++ b/dom/media/webaudio/AudioNode.h
@@ -89,27 +89,17 @@ public:
   }
 
   virtual AudioNode* Connect(AudioNode& aDestination, uint32_t aOutput,
                              uint32_t aInput, ErrorResult& aRv);
 
   virtual void Connect(AudioParam& aDestination, uint32_t aOutput,
                        ErrorResult& aRv);
 
-  virtual void Disconnect(ErrorResult& aRv);
   virtual void Disconnect(uint32_t aOutput, ErrorResult& aRv);
-  virtual void Disconnect(AudioNode& aDestination, ErrorResult& aRv);
-  virtual void Disconnect(AudioNode& aDestination, uint32_t aOutput,
-                          ErrorResult& aRv);
-  virtual void Disconnect(AudioNode& aDestination,
-                          uint32_t aOutput, uint32_t aInput,
-                          ErrorResult& aRv);
-  virtual void Disconnect(AudioParam& aDestination, ErrorResult& aRv);
-  virtual void Disconnect(AudioParam& aDestination, uint32_t aOutput,
-                          ErrorResult& aRv);
 
   // Called after input nodes have been explicitly added or removed through
   // the Connect() or Disconnect() methods.
   virtual void NotifyInputsChanged() {}
   // Indicate that the node should continue indefinitely to behave as if an
   // input is connected, even though there is no longer a corresponding entry
   // in mInputNodes.  Called after an input node has been removed because it
   // is being garbage collected.
@@ -225,18 +215,16 @@ private:
   virtual void LastRelease() override
   {
     // We are about to be deleted, disconnect the object from the graph before
     // the derived type is destroyed.
     DisconnectFromGraph();
   }
   // Callers must hold a reference to 'this'.
   void DisconnectFromGraph();
-  bool DisconnectFromOutputIfConnected(AudioNode& aDestination, uint32_t aOutputIndex, uint32_t aInputIndex);
-  bool DisconnectFromParamIfConnected(AudioParam& aDestination, uint32_t aOutputIndex, uint32_t aInputIndex);
 
 protected:
   // Helpers for sending different value types to streams
   void SendDoubleParameterToStream(uint32_t aIndex, double aValue);
   void SendInt32ParameterToStream(uint32_t aIndex, int32_t aValue);
   void SendThreeDPointParameterToStream(uint32_t aIndex, const ThreeDPoint& aValue);
   void SendChannelMixingParametersToStream();
 
--- a/dom/media/webaudio/ScriptProcessorNode.h
+++ b/dom/media/webaudio/ScriptProcessorNode.h
@@ -45,61 +45,35 @@ public:
   void Connect(AudioParam& aDestination, uint32_t aOutput,
                ErrorResult& aRv) override
   {
     AudioNode::Connect(aDestination, aOutput, aRv);
     if (!aRv.Failed()) {
       UpdateConnectedStatus();
     }
   }
-  void Disconnect(ErrorResult& aRv) override
-  {
-    AudioNode::Disconnect(aRv);
-    UpdateConnectedStatus();
-  }
+
   void Disconnect(uint32_t aOutput, ErrorResult& aRv) override
   {
     AudioNode::Disconnect(aOutput, aRv);
-    UpdateConnectedStatus();
+    if (!aRv.Failed()) {
+      UpdateConnectedStatus();
+    }
   }
   void NotifyInputsChanged() override
   {
     UpdateConnectedStatus();
   }
   void NotifyHasPhantomInput() override
   {
     mHasPhantomInput = true;
     // No need to UpdateConnectedStatus() because there was previously an
     // input in InputNodes().
   }
-  void Disconnect(AudioNode& aDestination, ErrorResult& aRv) override
-  {
-    AudioNode::Disconnect(aDestination, aRv);
-    UpdateConnectedStatus();
-  }
-  void Disconnect(AudioNode& aDestination, uint32_t aOutput, ErrorResult& aRv) override
-  {
-    AudioNode::Disconnect(aDestination, aOutput, aRv);
-    UpdateConnectedStatus();
-  }
-  void Disconnect(AudioNode& aDestination, uint32_t aOutput, uint32_t aInput, ErrorResult& aRv) override
-  {
-    AudioNode::Disconnect(aDestination, aOutput, aInput, aRv);
-    UpdateConnectedStatus();
-  }
-  void Disconnect(AudioParam& aDestination, ErrorResult& aRv) override
-  {
-    AudioNode::Disconnect(aDestination, aRv);
-    UpdateConnectedStatus();
-  }
-  void Disconnect(AudioParam& aDestination, uint32_t aOutput, ErrorResult& aRv) override
-  {
-    AudioNode::Disconnect(aDestination, aOutput, aRv);
-    UpdateConnectedStatus();
-  }
+
   void SetChannelCount(uint32_t aChannelCount, ErrorResult& aRv) override
   {
     if (aChannelCount != ChannelCount()) {
       aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
     }
     return;
   }
   void SetChannelCountModeValue(ChannelCountMode aMode, ErrorResult& aRv) override
--- a/dom/media/webaudio/test/mochitest.ini
+++ b/dom/media/webaudio/test/mochitest.ini
@@ -117,24 +117,16 @@ skip-if = toolkit == 'android' # bug 105
 [test_delayNodeCycles.html]
 [test_delayNodePassThrough.html]
 [test_delayNodeSmallMaxDelay.html]
 [test_delayNodeTailIncrease.html]
 [test_delayNodeTailWithDisconnect.html]
 [test_delayNodeTailWithGain.html]
 [test_delayNodeTailWithReconnect.html]
 [test_delayNodeWithGain.html]
-[test_disconnectAll.html]
-[test_disconnectAudioParam.html]
-[test_disconnectAudioParamFromOutput.html]
-[test_disconnectExceptions.html]
-[test_disconnectFromAudioNode.html]
-[test_disconnectFromAudioNodeAndOutput.html]
-[test_disconnectFromAudioNodeAndOutputAndInput.html]
-[test_disconnectFromOutput.html]
 [test_dynamicsCompressorNode.html]
 [test_dynamicsCompressorNodePassThrough.html]
 [test_dynamicsCompressorNodeWithGain.html]
 [test_gainNode.html]
 [test_gainNodeInLoop.html]
 [test_gainNodePassThrough.html]
 [test_iirFilterNodePassThrough.html]
 [test_maxChannelCount.html]
deleted file mode 100644
--- a/dom/media/webaudio/test/test_disconnectAll.html
+++ /dev/null
@@ -1,51 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-  <head>
-    <title>Test whether we can disconnect an AudioNode</title>
-    <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-    <script type="text/javascript" src="webaudio.js"></script>
-    <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-  </head>
-  <body>
-    <pre id="test">
-      <script class="testbody" type="text/javascript">
-      var gTest = {
-        length: 256,
-        numberOfChannels: 1,
-        createGraph: function(context) {
-          var sourceBuffer = context.createBuffer(1, 256, context.sampleRate);
-          var data = sourceBuffer.getChannelData(0);
-          for (var j = 0; j < data.length; j++) {
-              data[j] = 1;
-          }
-
-          var source = context.createBufferSource();
-          source.buffer = sourceBuffer;
-
-          var source = context.createBufferSource();
-          source.buffer = sourceBuffer;
-
-          var gain1 = context.createGain();
-          var gain2 = context.createGain();
-          var gain3 = context.createGain();
-          var merger = context.createChannelMerger(3);
-
-          source.connect(gain1);
-          source.connect(gain2);
-          source.connect(gain3);
-          gain1.connect(merger);
-          gain2.connect(merger);
-          gain3.connect(merger);
-          source.start();
-
-          source.disconnect();
-
-          return merger;
-        }
-      };
-
-      runTest();
-      </script>
-    </pre>
-  </body>
-</html>
\ No newline at end of file
deleted file mode 100644
--- a/dom/media/webaudio/test/test_disconnectAudioParam.html
+++ /dev/null
@@ -1,58 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-  <head>
-    <title>Test whether we can disconnect an AudioParam</title>
-    <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-    <script type="text/javascript" src="webaudio.js"></script>
-    <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-  </head>
-  <body>
-    <pre id="test">
-      <script class="testbody" type="text/javascript">
-      var gTest = {
-        length: 256,
-        numberOfChannels: 1,
-        createGraph: function(context) {
-          var sourceBuffer = context.createBuffer(1, 256, context.sampleRate);
-          var data = sourceBuffer.getChannelData(0);
-          for (var j = 0; j < data.length; j++) {
-              data[j] = 1;
-          }
-
-          var source = context.createBufferSource();
-          source.buffer = sourceBuffer;
-
-          var half = context.createGain();
-          var gain1 = context.createGain();
-          var gain2 = context.createGain();
-
-          half.gain.value = 0.5;
-
-          source.connect(gain1);
-          gain1.connect(gain2);
-          source.connect(half);
-
-          half.connect(gain1.gain);
-          half.connect(gain2.gain);
-
-          half.disconnect(gain2.gain);
-
-          source.start();
-
-          return gain2;
-        },
-        createExpectedBuffers: function(context) {
-          expectedBuffer = context.createBuffer(1, 256, context.sampleRate);
-          for (var i = 0; i < 256; ++i) {
-            expectedBuffer.getChannelData(0)[i] = 1.5;
-          }
-
-          return expectedBuffer;
-        }
-      };
-
-      runTest();
-      </script>
-    </pre>
-  </body>
-</html>
deleted file mode 100644
--- a/dom/media/webaudio/test/test_disconnectAudioParamFromOutput.html
+++ /dev/null
@@ -1,67 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-  <head>
-    <title>Test whether we can disconnect an AudioParam</title>
-    <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-    <script type="text/javascript" src="webaudio.js"></script>
-    <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-  </head>
-  <body>
-    <pre id="test">
-      <script class="testbody" type="text/javascript">
-      var gTest = {
-        length: 256,
-        numberOfChannels: 2,
-        createGraph: function(context) {
-          var sourceBuffer = context.createBuffer(2, 256, context.sampleRate);
-          for (var i = 1; i <= 2; i++) {
-            var data = sourceBuffer.getChannelData(i-1);
-            for (var j = 0; j < data.length; j++) {
-                data[j] = i;
-            }
-          }
-
-          var source = context.createBufferSource();
-          source.buffer = sourceBuffer;
-
-          var source = context.createBufferSource();
-          source.buffer = sourceBuffer;
-
-          var half = context.createGain();
-          var gain1 = context.createGain();
-          var gain2 = context.createGain();
-          var splitter = context.createChannelSplitter(2);
-
-          half.gain.value = 0.5;
-
-          source.connect(gain1);
-          gain1.connect(gain2);
-          source.connect(half);
-          half.connect(splitter);
-          splitter.connect(gain1.gain, 0);
-          splitter.connect(gain2.gain, 1);
-
-          splitter.disconnect(gain2.gain, 1);
-
-          source.start();
-
-          return gain2;
-        },
-        createExpectedBuffers: function(context) {
-          var expectedBuffer = context.createBuffer(2, 256, context.sampleRate);
-          for (var i = 1; i <= 2; i++) {
-            var data = expectedBuffer.getChannelData(i-1);
-            for (var j = 0; j < data.length; j++) {
-              data[j] = (i == 1) ? 1.5 : 3.0;
-            }
-          }
-
-          return expectedBuffer;
-        }
-      };
-
-      runTest();
-      </script>
-    </pre>
-  </body>
-</html>
deleted file mode 100644
--- a/dom/media/webaudio/test/test_disconnectExceptions.html
+++ /dev/null
@@ -1,75 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-  <head>
-    <title>Test whether we can disconnect an AudioNode</title>
-    <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-    <script type="text/javascript" src="webaudio.js"></script>
-    <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-  </head>
-  <body>
-    <pre id="test">
-      <script class="testbody" type="text/javascript">
-      var ctx = new AudioContext();
-      var sourceBuffer = ctx.createBuffer(2, 256, ctx.sampleRate);
-      for (var i = 1; i <= 2; i++) {
-        var data = sourceBuffer.getChannelData(i-1);
-        for (var j = 0; j < data.length; j++) {
-            data[j] = i;
-        }
-      }
-
-      var source = ctx.createBufferSource();
-      source.buffer = sourceBuffer;
-
-      var gain1 = ctx.createGain();
-      var splitter = ctx.createChannelSplitter(2);
-      var merger = ctx.createChannelMerger(2);
-      var gain2 = ctx.createGain();
-      var gain3 = ctx.createGain();
-
-      gain1.connect(splitter);
-      splitter.connect(gain2, 0);
-      splitter.connect(gain3, 1);
-      splitter.connect(merger, 0, 0);
-      splitter.connect(merger, 1, 1);
-      gain2.connect(gain3);
-      gain3.connect(ctx.destination);
-      merger.connect(ctx.destination);
-
-      expectException(function() {
-          splitter.disconnect(2);
-      }, DOMException.INDEX_SIZE_ERR);
-
-      expectNoException(function() {
-        splitter.disconnect(1);
-        splitter.disconnect(1);
-      });
-
-      expectException(function() {
-        gain1.disconnect(gain2);
-      }, DOMException.INVALID_ACCESS_ERR);
-
-      expectException(function() {
-        gain1.disconnect(gain3);
-        ok(false, 'Should get InvalidAccessError exception');
-      }, DOMException.INVALID_ACCESS_ERR);
-
-      expectException(function() {
-        splitter.disconnect(gain2, 2);
-      }, DOMException.INDEX_SIZE_ERR);
-
-      expectException(function() {
-        splitter.disconnect(gain1, 0);
-      }, DOMException.INVALID_ACCESS_ERR);
-
-      expectException(function() {
-        splitter.disconnect(gain3, 0, 0);
-      }, DOMException.INVALID_ACCESS_ERR);
-
-      expectException(function() {
-        splitter.disconnect(merger, 3, 0);
-      }, DOMException.INDEX_SIZE_ERR);
-      </script>
-    </pre>
-  </body>
-</html>
deleted file mode 100644
--- a/dom/media/webaudio/test/test_disconnectFromAudioNode.html
+++ /dev/null
@@ -1,55 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-  <head>
-    <title>Test whether we can disconnect an AudioNode</title>
-    <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-    <script type="text/javascript" src="webaudio.js"></script>
-    <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-  </head>
-  <body>
-    <pre id="test">
-      <script class="testbody" type="text/javascript">
-      var gTest = {
-        length: 256,
-        numberOfChannels: 1,
-        createGraph: function(context) {
-          var sourceBuffer = context.createBuffer(1, 256, context.sampleRate);
-          var data = sourceBuffer.getChannelData(0);
-          for (var j = 0; j < data.length; j++) {
-              data[j] = 1;
-          }
-
-          var source = context.createBufferSource();
-          source.buffer = sourceBuffer;
-
-          var gain1 = context.createGain();
-          var gain2 = context.createGain();
-          var gain3 = context.createGain();
-
-          source.connect(gain1);
-          source.connect(gain2);
-
-          gain1.connect(gain3);
-          gain2.connect(gain3);
-
-          source.start();
-
-          source.disconnect(gain2);
-
-          return gain3;
-        },
-        createExpectedBuffers: function(context) {
-          expectedBuffer = context.createBuffer(1, 256, context.sampleRate);
-          for (var i = 0; i < 256; ++i) {
-            expectedBuffer.getChannelData(0)[i] = 1.0;
-          }
-
-          return expectedBuffer;
-        }
-      };
-
-      runTest();
-      </script>
-    </pre>
-  </body>
-</html>
deleted file mode 100644
--- a/dom/media/webaudio/test/test_disconnectFromAudioNodeAndOutput.html
+++ /dev/null
@@ -1,59 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-  <head>
-    <title>Test whether we can disconnect an AudioNode</title>
-    <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-    <script type="text/javascript" src="webaudio.js"></script>
-    <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-  </head>
-  <body>
-    <pre id="test">
-      <script class="testbody" type="text/javascript">
-      var gTest = {
-        length: 256,
-        numberOfChannels: 2,
-        createGraph: function(context) {
-          var sourceBuffer = context.createBuffer(2, 256, context.sampleRate);
-          for (var i = 1; i <= 2; i++) {
-            var data = sourceBuffer.getChannelData(i-1);
-            for (var j = 0; j < data.length; j++) {
-                data[j] = i;
-            }
-          }
-
-          var source = context.createBufferSource();
-          source.buffer = sourceBuffer;
-
-          var splitter = context.createChannelSplitter(2);
-          var gain1 = context.createGain();
-          var gain2 = context.createGain();
-          var merger = context.createChannelMerger(2);
-
-          source.connect(splitter);
-          splitter.connect(gain1, 0);
-          splitter.connect(gain2, 0);
-          splitter.connect(gain2, 1);
-          gain1.connect(merger, 0, 1);
-          gain2.connect(merger, 0, 1);
-          source.start();
-
-          splitter.disconnect(gain2, 0);
-
-          return merger;
-        },
-        createExpectedBuffers: function(context) {
-          expectedBuffer = context.createBuffer(2, 256, context.sampleRate);
-          for (var i = 0; i < 256; ++i) {
-            expectedBuffer.getChannelData(0)[i] = 0;
-            expectedBuffer.getChannelData(1)[i] = 3;
-          }
-
-          return expectedBuffer;
-        }
-      };
-
-      runTest();
-      </script>
-    </pre>
-  </body>
-</html>
deleted file mode 100644
--- a/dom/media/webaudio/test/test_disconnectFromAudioNodeAndOutputAndInput.html
+++ /dev/null
@@ -1,57 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-  <head>
-    <title>Test whether we can disconnect an AudioNode</title>
-    <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-    <script type="text/javascript" src="webaudio.js"></script>
-    <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-  </head>
-  <body>
-    <pre id="test">
-      <script class="testbody" type="text/javascript">
-      var gTest = {
-        length: 256,
-        numberOfChannels: 3,
-        createGraph: function(context) {
-          var sourceBuffer = context.createBuffer(3, 256, context.sampleRate);
-          for (var i = 1; i <= 3; i++) {
-            var data = sourceBuffer.getChannelData(i-1);
-            for (var j = 0; j < data.length; j++) {
-                data[j] = i;
-            }
-          }
-
-          var source = context.createBufferSource();
-          source.buffer = sourceBuffer;
-
-          var splitter = context.createChannelSplitter(3);
-          var merger = context.createChannelMerger(3);
-
-          source.connect(splitter);
-          splitter.connect(merger, 0, 0);
-          splitter.connect(merger, 1, 1);
-          splitter.connect(merger, 2, 2);
-          source.start();
-
-          splitter.disconnect(merger, 2, 2);
-
-          return merger;
-        },
-        createExpectedBuffers: function(context) {
-          var expectedBuffer = context.createBuffer(3, 256, context.sampleRate);
-          for (var i = 1; i <= 3; i++) {
-            var data = expectedBuffer.getChannelData(i-1);
-            for (var j = 0; j < data.length; j++) {
-              data[j] = (i == 3) ? 0 : i;
-            }
-          }
-
-          return expectedBuffer;
-        }
-      };
-
-      runTest();
-      </script>
-    </pre>
-  </body>
-</html>
\ No newline at end of file
deleted file mode 100644
--- a/dom/media/webaudio/test/test_disconnectFromOutput.html
+++ /dev/null
@@ -1,54 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-  <head>
-    <title>Test whether we can disconnect an AudioNode</title>
-    <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-    <script type="text/javascript" src="webaudio.js"></script>
-    <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-  </head>
-  <body>
-    <pre id="test">
-      <script class="testbody" type="text/javascript">
-      var gTest = {
-        length: 256,
-        numberOfChannels: 1,
-        createGraph: function(context) {
-          var sourceBuffer = context.createBuffer(3, 256, context.sampleRate);
-          for (var i = 1; i <= 3; i++) {
-            var data = sourceBuffer.getChannelData(i-1);
-            for (var j = 0; j < data.length; j++) {
-                data[j] = i;
-            }
-          }
-
-          var source = context.createBufferSource();
-          source.buffer = sourceBuffer;
-
-          var splitter = context.createChannelSplitter(3);
-          var sum = context.createGain();
-
-          source.connect(splitter);
-          splitter.connect(sum, 0);
-          splitter.connect(sum, 1);
-          splitter.connect(sum, 2);
-          source.start();
-
-          splitter.disconnect(1);
-
-          return sum;
-        },
-        createExpectedBuffers: function(context) {
-          expectedBuffer = context.createBuffer(1, 256, context.sampleRate);
-          for (var i = 0; i < 256; ++i) {
-            expectedBuffer.getChannelData(0)[i] = 4;
-          }
-
-          return expectedBuffer;
-        },
-      };
-
-      runTest();
-      </script>
-    </pre>
-  </body>
-</html>
\ No newline at end of file
--- a/dom/webidl/AudioNode.webidl
+++ b/dom/webidl/AudioNode.webidl
@@ -23,29 +23,17 @@ enum ChannelInterpretation {
 
 interface AudioNode : EventTarget {
 
     [Throws]
     AudioNode connect(AudioNode destination, optional unsigned long output = 0, optional unsigned long input = 0);
     [Throws]
     void connect(AudioParam destination, optional unsigned long output = 0);
     [Throws]
-    void disconnect();
-    [Throws]
-    void disconnect(unsigned long output);
-    [Throws]
-    void disconnect(AudioNode destination);
-    [Throws]
-    void disconnect(AudioNode destination, unsigned long output);
-    [Throws]
-    void disconnect(AudioNode destination, unsigned long output, unsigned long input);
-    [Throws]
-    void disconnect(AudioParam destination);
-    [Throws]
-    void disconnect(AudioParam destination, unsigned long output);
+    void disconnect(optional unsigned long output = 0);
 
     readonly attribute AudioContext context;
     readonly attribute unsigned long numberOfInputs;
     readonly attribute unsigned long numberOfOutputs;
 
     // Channel up-mixing and down-mixing rules for all inputs.
     [SetterThrows]
     attribute unsigned long channelCount;