<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[199775] trunk</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/199775">199775</a></dd>
<dt>Author</dt> <dd>cdumez@apple.com</dd>
<dt>Date</dt> <dd>2016-04-20 10:27:37 -0700 (Wed, 20 Apr 2016)</dd>
</dl>
<h3>Log Message</h3>
<pre>Drop [UsePointersEvenForNonNullableObjectArguments] from WebAudio
https://bugs.webkit.org/show_bug.cgi?id=156777
Reviewed by Darin Adler.
Source/WebCore:
Drop [UsePointersEvenForNonNullableObjectArguments] from WebAudio and
modernize the interface a bit.
There is no major Web-exposed behavioral change except for
the exception type thrown when passing null (now always TypeError).
Tests were updated to add coverage for this.
* Modules/webaudio/AsyncAudioDecoder.cpp:
(WebCore::AsyncAudioDecoder::decodeAsync):
(WebCore::AsyncAudioDecoder::DecodingTask::DecodingTask):
(WebCore::AsyncAudioDecoder::DecodingTask::decode): Deleted.
* Modules/webaudio/AsyncAudioDecoder.h:
(WebCore::AsyncAudioDecoder::DecodingTask::audioData):
* Modules/webaudio/AudioContext.cpp:
(WebCore::AudioContext::lazyInitialize):
(WebCore::AudioContext::createBuffer):
(WebCore::AudioContext::decodeAudioData):
(WebCore::AudioContext::createBufferSource):
(WebCore::AudioContext::createMediaElementSource):
(WebCore::AudioContext::createMediaStreamSource):
(WebCore::AudioContext::createMediaStreamDestination):
(WebCore::AudioContext::createScriptProcessor):
(WebCore::AudioContext::createBiquadFilter):
(WebCore::AudioContext::createWaveShaper):
(WebCore::AudioContext::createPanner):
(WebCore::AudioContext::createConvolver):
(WebCore::AudioContext::createDynamicsCompressor):
(WebCore::AudioContext::createAnalyser):
(WebCore::AudioContext::createGain):
(WebCore::AudioContext::createDelay):
(WebCore::AudioContext::createChannelSplitter):
(WebCore::AudioContext::createChannelMerger):
(WebCore::AudioContext::createOscillator):
(WebCore::AudioContext::createPeriodicWave):
(WebCore::AudioContext::derefFinishedSourceNodes):
(WebCore::AudioContext::refNode):
(WebCore::AudioContext::derefNode):
(WebCore::AudioContext::notifyNodeFinishedProcessing): Deleted.
(WebCore::AudioContext::derefUnfinishedSourceNodes): Deleted.
(WebCore::AudioContext::lock): Deleted.
* Modules/webaudio/AudioContext.h:
* Modules/webaudio/AudioContext.idl:
* Modules/webaudio/MediaElementAudioSourceNode.cpp:
(WebCore::MediaElementAudioSourceNode::create):
(WebCore::MediaElementAudioSourceNode::MediaElementAudioSourceNode):
(WebCore::MediaElementAudioSourceNode::process):
* Modules/webaudio/MediaElementAudioSourceNode.h:
(WebCore::MediaElementAudioSourceNode::mediaElement):
* Modules/webaudio/OscillatorNode.idl:
LayoutTests:
Added test coverage for the type of the exception being thrown when
pasing null to various WebAudio API.
* webaudio/audiobuffer-expected.txt:
* webaudio/audiobuffer.html:
* webaudio/createMediaStreamSource-null-expected.txt: Added.
* webaudio/createMediaStreamSource-null.html: Added.
* webaudio/decode-audio-data-basic-expected.txt:
* webaudio/decode-audio-data-basic.html:
* webaudio/mediaelementaudiosourcenode-expected.txt:
* webaudio/mediaelementaudiosourcenode.html:</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestswebaudioaudiobufferexpectedtxt">trunk/LayoutTests/webaudio/audiobuffer-expected.txt</a></li>
<li><a href="#trunkLayoutTestswebaudioaudiobufferhtml">trunk/LayoutTests/webaudio/audiobuffer.html</a></li>
<li><a href="#trunkLayoutTestswebaudiodecodeaudiodatabasicexpectedtxt">trunk/LayoutTests/webaudio/decode-audio-data-basic-expected.txt</a></li>
<li><a href="#trunkLayoutTestswebaudiodecodeaudiodatabasichtml">trunk/LayoutTests/webaudio/decode-audio-data-basic.html</a></li>
<li><a href="#trunkLayoutTestswebaudiomediaelementaudiosourcenodeexpectedtxt">trunk/LayoutTests/webaudio/mediaelementaudiosourcenode-expected.txt</a></li>
<li><a href="#trunkLayoutTestswebaudiomediaelementaudiosourcenodehtml">trunk/LayoutTests/webaudio/mediaelementaudiosourcenode.html</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreModuleswebaudioAsyncAudioDecodercpp">trunk/Source/WebCore/Modules/webaudio/AsyncAudioDecoder.cpp</a></li>
<li><a href="#trunkSourceWebCoreModuleswebaudioAsyncAudioDecoderh">trunk/Source/WebCore/Modules/webaudio/AsyncAudioDecoder.h</a></li>
<li><a href="#trunkSourceWebCoreModuleswebaudioAudioContextcpp">trunk/Source/WebCore/Modules/webaudio/AudioContext.cpp</a></li>
<li><a href="#trunkSourceWebCoreModuleswebaudioAudioContexth">trunk/Source/WebCore/Modules/webaudio/AudioContext.h</a></li>
<li><a href="#trunkSourceWebCoreModuleswebaudioAudioContextidl">trunk/Source/WebCore/Modules/webaudio/AudioContext.idl</a></li>
<li><a href="#trunkSourceWebCoreModuleswebaudioMediaElementAudioSourceNodecpp">trunk/Source/WebCore/Modules/webaudio/MediaElementAudioSourceNode.cpp</a></li>
<li><a href="#trunkSourceWebCoreModuleswebaudioMediaElementAudioSourceNodeh">trunk/Source/WebCore/Modules/webaudio/MediaElementAudioSourceNode.h</a></li>
<li><a href="#trunkSourceWebCoreModuleswebaudioOscillatorNodeidl">trunk/Source/WebCore/Modules/webaudio/OscillatorNode.idl</a></li>
</ul>
<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestswebaudiocreateMediaStreamSourcenullexpectedtxt">trunk/LayoutTests/webaudio/createMediaStreamSource-null-expected.txt</a></li>
<li><a href="#trunkLayoutTestswebaudiocreateMediaStreamSourcenullhtml">trunk/LayoutTests/webaudio/createMediaStreamSource-null.html</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (199774 => 199775)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2016-04-20 16:14:14 UTC (rev 199774)
+++ trunk/LayoutTests/ChangeLog        2016-04-20 17:27:37 UTC (rev 199775)
</span><span class="lines">@@ -1,3 +1,22 @@
</span><ins>+2016-04-20 Chris Dumez <cdumez@apple.com>
+
+ Drop [UsePointersEvenForNonNullableObjectArguments] from WebAudio
+ https://bugs.webkit.org/show_bug.cgi?id=156777
+
+ Reviewed by Darin Adler.
+
+ Added test coverage for the type of the exception being thrown when
+ pasing null to various WebAudio API.
+
+ * webaudio/audiobuffer-expected.txt:
+ * webaudio/audiobuffer.html:
+ * webaudio/createMediaStreamSource-null-expected.txt: Added.
+ * webaudio/createMediaStreamSource-null.html: Added.
+ * webaudio/decode-audio-data-basic-expected.txt:
+ * webaudio/decode-audio-data-basic.html:
+ * webaudio/mediaelementaudiosourcenode-expected.txt:
+ * webaudio/mediaelementaudiosourcenode.html:
+
</ins><span class="cx"> 2016-04-20 Brady Eidson <beidson@apple.com>
</span><span class="cx">
</span><span class="cx"> Addressing additional review feedback for:
</span></span></pre></div>
<a id="trunkLayoutTestswebaudioaudiobufferexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/webaudio/audiobuffer-expected.txt (199774 => 199775)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/webaudio/audiobuffer-expected.txt        2016-04-20 16:14:14 UTC (rev 199774)
+++ trunk/LayoutTests/webaudio/audiobuffer-expected.txt        2016-04-20 17:27:37 UTC (rev 199775)
</span><span class="lines">@@ -12,6 +12,7 @@
</span><span class="cx"> PASS getChannelData(2) returns a Float32Array object.
</span><span class="cx"> PASS getChannelData(3) returns a Float32Array object.
</span><span class="cx"> PASS Exception has been thrown correctly when index is not less than numberOfChannels.
</span><ins>+PASS context.createBuffer(null, false) threw exception TypeError: Type error.
</ins><span class="cx"> PASS successfullyParsed is true
</span><span class="cx">
</span><span class="cx"> TEST COMPLETE
</span></span></pre></div>
<a id="trunkLayoutTestswebaudioaudiobufferhtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/webaudio/audiobuffer.html (199774 => 199775)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/webaudio/audiobuffer.html        2016-04-20 16:14:14 UTC (rev 199774)
+++ trunk/LayoutTests/webaudio/audiobuffer.html        2016-04-20 17:27:37 UTC (rev 199775)
</span><span class="lines">@@ -49,6 +49,8 @@
</span><span class="cx"> testPassed("Exception has been thrown correctly when index is not less than numberOfChannels.");
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+shouldThrow("context.createBuffer(null, false)", "'TypeError: Type error'");
+
</ins><span class="cx"> </script>
</span><span class="cx">
</span><span class="cx"> <script src="../resources/js-test-post.js"></script>
</span></span></pre></div>
<a id="trunkLayoutTestswebaudiocreateMediaStreamSourcenullexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/webaudio/createMediaStreamSource-null-expected.txt (0 => 199775)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/webaudio/createMediaStreamSource-null-expected.txt         (rev 0)
+++ trunk/LayoutTests/webaudio/createMediaStreamSource-null-expected.txt        2016-04-20 17:27:37 UTC (rev 199775)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+Tests that passing null to context.createMediaStreamSource() throws a TypeError.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS context.createMediaStreamSource(null) threw exception TypeError: Type error.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestswebaudiocreateMediaStreamSourcenullhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/webaudio/createMediaStreamSource-null.html (0 => 199775)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/webaudio/createMediaStreamSource-null.html         (rev 0)
+++ trunk/LayoutTests/webaudio/createMediaStreamSource-null.html        2016-04-20 17:27:37 UTC (rev 199775)
</span><span class="lines">@@ -0,0 +1,17 @@
</span><ins>+<!DOCTYPE html>
+<html>
+<head>
+<script src="../resources/js-test-pre.js"></script>
+<script src="resources/audio-testing.js"></script>
+</head>
+<body>
+<script>
+description("Tests that passing null to context.createMediaStreamSource() throws a TypeError.");
+
+var context = new webkitAudioContext();
+shouldThrow("context.createMediaStreamSource(null)", "'TypeError: Type error'");
+
+</script>
+<script src="../resources/js-test-post.js"></script>
+</body>
+</html>
</ins></span></pre></div>
<a id="trunkLayoutTestswebaudiodecodeaudiodatabasicexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/webaudio/decode-audio-data-basic-expected.txt (199774 => 199775)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/webaudio/decode-audio-data-basic-expected.txt        2016-04-20 16:14:14 UTC (rev 199774)
+++ trunk/LayoutTests/webaudio/decode-audio-data-basic-expected.txt        2016-04-20 17:27:37 UTC (rev 199775)
</span><span class="lines">@@ -3,7 +3,7 @@
</span><span class="cx"> On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
</span><span class="cx">
</span><span class="cx">
</span><del>-PASS decodeAudioData raises exception correctly when arraybuffer parameter is null.
</del><ins>+PASS context.decodeAudioData(null, function(){}, function(){}); threw exception TypeError: Type error.
</ins><span class="cx"> PASS The resources/media/24bit-44khz.wav test: successCallback has been called correctly.
</span><span class="cx"> PASS The resources/media/invalid-audio-file.txt test: errorCallback has been called correctly.
</span><span class="cx"> PASS successfullyParsed is true
</span></span></pre></div>
<a id="trunkLayoutTestswebaudiodecodeaudiodatabasichtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/webaudio/decode-audio-data-basic.html (199774 => 199775)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/webaudio/decode-audio-data-basic.html        2016-04-20 16:14:14 UTC (rev 199774)
+++ trunk/LayoutTests/webaudio/decode-audio-data-basic.html        2016-04-20 17:27:37 UTC (rev 199775)
</span><span class="lines">@@ -17,12 +17,8 @@
</span><span class="cx">
</span><span class="cx"> var context = new webkitAudioContext();
</span><span class="cx">
</span><del>-try {
- context.decodeAudioData(null, function(){}, function(){});
- testFailed("decodeAudioData should raise exception when arraybuffer parameter is null.");
-} catch(e) {
- testPassed("decodeAudioData raises exception correctly when arraybuffer parameter is null.");
-}
</del><ins>+// decodeAudioData should raise exception when arraybuffer parameter is null.
+shouldThrow("context.decodeAudioData(null, function(){}, function(){});", "'TypeError: Type error'");
</ins><span class="cx">
</span><span class="cx"> var decodeCaseArray = [{url: "resources/media/24bit-44khz.wav", result: true},
</span><span class="cx"> {url: "resources/media/invalid-audio-file.txt", result: false}];
</span></span></pre></div>
<a id="trunkLayoutTestswebaudiomediaelementaudiosourcenodeexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/webaudio/mediaelementaudiosourcenode-expected.txt (199774 => 199775)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/webaudio/mediaelementaudiosourcenode-expected.txt        2016-04-20 16:14:14 UTC (rev 199774)
+++ trunk/LayoutTests/webaudio/mediaelementaudiosourcenode-expected.txt        2016-04-20 17:27:37 UTC (rev 199775)
</span><span class="lines">@@ -9,6 +9,7 @@
</span><span class="cx"> PASS connect() exception thrown for illegal input index.
</span><span class="cx"> PASS audioNode.connect(context.destination) succeeded.
</span><span class="cx"> PASS createMediaElementSource() threw error when called twice on same HTMLMediaElement.
</span><ins>+PASS context.createMediaElementSource(null) threw exception TypeError: Type error.
</ins><span class="cx"> PASS successfullyParsed is true
</span><span class="cx">
</span><span class="cx"> TEST COMPLETE
</span></span></pre></div>
<a id="trunkLayoutTestswebaudiomediaelementaudiosourcenodehtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/webaudio/mediaelementaudiosourcenode.html (199774 => 199775)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/webaudio/mediaelementaudiosourcenode.html        2016-04-20 16:14:14 UTC (rev 199774)
+++ trunk/LayoutTests/webaudio/mediaelementaudiosourcenode.html        2016-04-20 17:27:37 UTC (rev 199775)
</span><span class="lines">@@ -79,6 +79,8 @@
</span><span class="cx"> testPassed("createMediaElementSource() threw error when called twice on same HTMLMediaElement.");
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+ shouldThrow("context.createMediaElementSource(null)", "'TypeError: Type error'");
+
</ins><span class="cx"> finishJSTest();
</span><span class="cx"> }
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (199774 => 199775)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-04-20 16:14:14 UTC (rev 199774)
+++ trunk/Source/WebCore/ChangeLog        2016-04-20 17:27:37 UTC (rev 199775)
</span><span class="lines">@@ -1,3 +1,60 @@
</span><ins>+2016-04-20 Chris Dumez <cdumez@apple.com>
+
+ Drop [UsePointersEvenForNonNullableObjectArguments] from WebAudio
+ https://bugs.webkit.org/show_bug.cgi?id=156777
+
+ Reviewed by Darin Adler.
+
+ Drop [UsePointersEvenForNonNullableObjectArguments] from WebAudio and
+ modernize the interface a bit.
+
+ There is no major Web-exposed behavioral change except for
+ the exception type thrown when passing null (now always TypeError).
+ Tests were updated to add coverage for this.
+
+ * Modules/webaudio/AsyncAudioDecoder.cpp:
+ (WebCore::AsyncAudioDecoder::decodeAsync):
+ (WebCore::AsyncAudioDecoder::DecodingTask::DecodingTask):
+ (WebCore::AsyncAudioDecoder::DecodingTask::decode): Deleted.
+ * Modules/webaudio/AsyncAudioDecoder.h:
+ (WebCore::AsyncAudioDecoder::DecodingTask::audioData):
+ * Modules/webaudio/AudioContext.cpp:
+ (WebCore::AudioContext::lazyInitialize):
+ (WebCore::AudioContext::createBuffer):
+ (WebCore::AudioContext::decodeAudioData):
+ (WebCore::AudioContext::createBufferSource):
+ (WebCore::AudioContext::createMediaElementSource):
+ (WebCore::AudioContext::createMediaStreamSource):
+ (WebCore::AudioContext::createMediaStreamDestination):
+ (WebCore::AudioContext::createScriptProcessor):
+ (WebCore::AudioContext::createBiquadFilter):
+ (WebCore::AudioContext::createWaveShaper):
+ (WebCore::AudioContext::createPanner):
+ (WebCore::AudioContext::createConvolver):
+ (WebCore::AudioContext::createDynamicsCompressor):
+ (WebCore::AudioContext::createAnalyser):
+ (WebCore::AudioContext::createGain):
+ (WebCore::AudioContext::createDelay):
+ (WebCore::AudioContext::createChannelSplitter):
+ (WebCore::AudioContext::createChannelMerger):
+ (WebCore::AudioContext::createOscillator):
+ (WebCore::AudioContext::createPeriodicWave):
+ (WebCore::AudioContext::derefFinishedSourceNodes):
+ (WebCore::AudioContext::refNode):
+ (WebCore::AudioContext::derefNode):
+ (WebCore::AudioContext::notifyNodeFinishedProcessing): Deleted.
+ (WebCore::AudioContext::derefUnfinishedSourceNodes): Deleted.
+ (WebCore::AudioContext::lock): Deleted.
+ * Modules/webaudio/AudioContext.h:
+ * Modules/webaudio/AudioContext.idl:
+ * Modules/webaudio/MediaElementAudioSourceNode.cpp:
+ (WebCore::MediaElementAudioSourceNode::create):
+ (WebCore::MediaElementAudioSourceNode::MediaElementAudioSourceNode):
+ (WebCore::MediaElementAudioSourceNode::process):
+ * Modules/webaudio/MediaElementAudioSourceNode.h:
+ (WebCore::MediaElementAudioSourceNode::mediaElement):
+ * Modules/webaudio/OscillatorNode.idl:
+
</ins><span class="cx"> 2016-04-20 Brady Eidson <beidson@apple.com>
</span><span class="cx">
</span><span class="cx"> Addressing additional review feedback for:
</span></span></pre></div>
<a id="trunkSourceWebCoreModuleswebaudioAsyncAudioDecodercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/webaudio/AsyncAudioDecoder.cpp (199774 => 199775)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/webaudio/AsyncAudioDecoder.cpp        2016-04-20 16:14:14 UTC (rev 199774)
+++ trunk/Source/WebCore/Modules/webaudio/AsyncAudioDecoder.cpp        2016-04-20 17:27:37 UTC (rev 199775)
</span><span class="lines">@@ -51,14 +51,11 @@
</span><span class="cx"> m_threadID = 0;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void AsyncAudioDecoder::decodeAsync(ArrayBuffer* audioData, float sampleRate, PassRefPtr<AudioBufferCallback> successCallback, PassRefPtr<AudioBufferCallback> errorCallback)
</del><ins>+void AsyncAudioDecoder::decodeAsync(Ref<ArrayBuffer>&& audioData, float sampleRate, RefPtr<AudioBufferCallback>&& successCallback, RefPtr<AudioBufferCallback>&& errorCallback)
</ins><span class="cx"> {
</span><span class="cx"> ASSERT(isMainThread());
</span><del>- ASSERT(audioData);
- if (!audioData)
- return;
</del><span class="cx">
</span><del>- auto decodingTask = std::make_unique<DecodingTask>(audioData, sampleRate, successCallback, errorCallback);
</del><ins>+ auto decodingTask = std::make_unique<DecodingTask>(WTFMove(audioData), sampleRate, WTFMove(successCallback), WTFMove(errorCallback));
</ins><span class="cx"> m_queue.append(WTFMove(decodingTask)); // note that ownership of the task is effectively taken by the queue.
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -87,20 +84,16 @@
</span><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><del>-AsyncAudioDecoder::DecodingTask::DecodingTask(ArrayBuffer* audioData, float sampleRate, PassRefPtr<AudioBufferCallback> successCallback, PassRefPtr<AudioBufferCallback> errorCallback)
- : m_audioData(audioData)
</del><ins>+AsyncAudioDecoder::DecodingTask::DecodingTask(Ref<ArrayBuffer>&& audioData, float sampleRate, RefPtr<AudioBufferCallback>&& successCallback, RefPtr<AudioBufferCallback>&& errorCallback)
+ : m_audioData(WTFMove(audioData))
</ins><span class="cx"> , m_sampleRate(sampleRate)
</span><del>- , m_successCallback(successCallback)
- , m_errorCallback(errorCallback)
</del><ins>+ , m_successCallback(WTFMove(successCallback))
+ , m_errorCallback(WTFMove(errorCallback))
</ins><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> void AsyncAudioDecoder::DecodingTask::decode()
</span><span class="cx"> {
</span><del>- ASSERT(m_audioData.get());
- if (!m_audioData.get())
- return;
-
</del><span class="cx"> // Do the actual decoding and invoke the callback.
</span><span class="cx"> m_audioBuffer = AudioBuffer::createFromAudioFileData(m_audioData->data(), m_audioData->byteLength(), false, sampleRate());
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceWebCoreModuleswebaudioAsyncAudioDecoderh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/webaudio/AsyncAudioDecoder.h (199774 => 199775)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/webaudio/AsyncAudioDecoder.h        2016-04-20 16:14:14 UTC (rev 199774)
+++ trunk/Source/WebCore/Modules/webaudio/AsyncAudioDecoder.h        2016-04-20 17:27:37 UTC (rev 199775)
</span><span class="lines">@@ -51,17 +51,17 @@
</span><span class="cx"> ~AsyncAudioDecoder();
</span><span class="cx">
</span><span class="cx"> // Must be called on the main thread.
</span><del>- void decodeAsync(JSC::ArrayBuffer* audioData, float sampleRate, PassRefPtr<AudioBufferCallback> successCallback, PassRefPtr<AudioBufferCallback> errorCallback);
</del><ins>+ void decodeAsync(Ref<JSC::ArrayBuffer>&& audioData, float sampleRate, RefPtr<AudioBufferCallback>&& successCallback, RefPtr<AudioBufferCallback>&& errorCallback);
</ins><span class="cx">
</span><span class="cx"> private:
</span><span class="cx"> class DecodingTask {
</span><span class="cx"> WTF_MAKE_NONCOPYABLE(DecodingTask);
</span><span class="cx"> public:
</span><del>- DecodingTask(JSC::ArrayBuffer* audioData, float sampleRate, PassRefPtr<AudioBufferCallback> successCallback, PassRefPtr<AudioBufferCallback> errorCallback);
</del><ins>+ DecodingTask(Ref<JSC::ArrayBuffer>&& audioData, float sampleRate, RefPtr<AudioBufferCallback>&& successCallback, RefPtr<AudioBufferCallback>&& errorCallback);
</ins><span class="cx"> void decode();
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- JSC::ArrayBuffer* audioData() { return m_audioData.get(); }
</del><ins>+ JSC::ArrayBuffer& audioData() { return m_audioData; }
</ins><span class="cx"> float sampleRate() const { return m_sampleRate; }
</span><span class="cx"> AudioBufferCallback* successCallback() { return m_successCallback.get(); }
</span><span class="cx"> AudioBufferCallback* errorCallback() { return m_errorCallback.get(); }
</span><span class="lines">@@ -69,7 +69,7 @@
</span><span class="cx">
</span><span class="cx"> void notifyComplete();
</span><span class="cx">
</span><del>- RefPtr<JSC::ArrayBuffer> m_audioData;
</del><ins>+ Ref<JSC::ArrayBuffer> m_audioData;
</ins><span class="cx"> float m_sampleRate;
</span><span class="cx"> RefPtr<AudioBufferCallback> m_successCallback;
</span><span class="cx"> RefPtr<AudioBufferCallback> m_errorCallback;
</span></span></pre></div>
<a id="trunkSourceWebCoreModuleswebaudioAudioContextcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/webaudio/AudioContext.cpp (199774 => 199775)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/webaudio/AudioContext.cpp        2016-04-20 16:14:14 UTC (rev 199774)
+++ trunk/Source/WebCore/Modules/webaudio/AudioContext.cpp        2016-04-20 17:27:37 UTC (rev 199775)
</span><span class="lines">@@ -1,5 +1,6 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2010, Google Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
</ins><span class="cx"> *
</span><span class="cx"> * Redistribution and use in source and binary forms, with or without
</span><span class="cx"> * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -212,7 +213,7 @@
</span><span class="cx"> if (m_isAudioThreadFinished)
</span><span class="cx"> return;
</span><span class="cx">
</span><del>- if (m_destinationNode.get()) {
</del><ins>+ if (m_destinationNode) {
</ins><span class="cx"> m_destinationNode->initialize();
</span><span class="cx">
</span><span class="cx"> if (!isOfflineContext()) {
</span><span class="lines">@@ -377,10 +378,10 @@
</span><span class="cx"> return downcast<Document>(m_scriptExecutionContext);
</span><span class="cx"> }
</span><span class="cx">
</span><del>-PassRefPtr<AudioBuffer> AudioContext::createBuffer(unsigned numberOfChannels, size_t numberOfFrames, float sampleRate, ExceptionCode& ec)
</del><ins>+RefPtr<AudioBuffer> AudioContext::createBuffer(unsigned numberOfChannels, size_t numberOfFrames, float sampleRate, ExceptionCode& ec)
</ins><span class="cx"> {
</span><span class="cx"> RefPtr<AudioBuffer> audioBuffer = AudioBuffer::create(numberOfChannels, numberOfFrames, sampleRate);
</span><del>- if (!audioBuffer.get()) {
</del><ins>+ if (!audioBuffer) {
</ins><span class="cx"> ec = NOT_SUPPORTED_ERR;
</span><span class="cx"> return nullptr;
</span><span class="cx"> }
</span><span class="lines">@@ -388,84 +389,62 @@
</span><span class="cx"> return audioBuffer;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-PassRefPtr<AudioBuffer> AudioContext::createBuffer(ArrayBuffer* arrayBuffer, bool mixToMono, ExceptionCode& ec)
</del><ins>+RefPtr<AudioBuffer> AudioContext::createBuffer(ArrayBuffer& arrayBuffer, bool mixToMono, ExceptionCode& ec)
</ins><span class="cx"> {
</span><del>- ASSERT(arrayBuffer);
- if (!arrayBuffer) {
</del><ins>+ RefPtr<AudioBuffer> audioBuffer = AudioBuffer::createFromAudioFileData(arrayBuffer.data(), arrayBuffer.byteLength(), mixToMono, sampleRate());
+ if (!audioBuffer) {
</ins><span class="cx"> ec = SYNTAX_ERR;
</span><span class="cx"> return nullptr;
</span><span class="cx"> }
</span><span class="cx">
</span><del>- RefPtr<AudioBuffer> audioBuffer = AudioBuffer::createFromAudioFileData(arrayBuffer->data(), arrayBuffer->byteLength(), mixToMono, sampleRate());
- if (!audioBuffer.get()) {
- ec = SYNTAX_ERR;
- return nullptr;
- }
-
</del><span class="cx"> return audioBuffer;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void AudioContext::decodeAudioData(ArrayBuffer* audioData, PassRefPtr<AudioBufferCallback> successCallback, PassRefPtr<AudioBufferCallback> errorCallback, ExceptionCode& ec)
</del><ins>+void AudioContext::decodeAudioData(Ref<ArrayBuffer>&& audioData, RefPtr<AudioBufferCallback>&& successCallback, RefPtr<AudioBufferCallback>&& errorCallback)
</ins><span class="cx"> {
</span><del>- if (!audioData) {
- ec = SYNTAX_ERR;
- return;
- }
- m_audioDecoder.decodeAsync(audioData, sampleRate(), successCallback, errorCallback);
</del><ins>+ m_audioDecoder.decodeAsync(WTFMove(audioData), sampleRate(), WTFMove(successCallback), WTFMove(errorCallback));
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-PassRefPtr<AudioBufferSourceNode> AudioContext::createBufferSource()
</del><ins>+Ref<AudioBufferSourceNode> AudioContext::createBufferSource()
</ins><span class="cx"> {
</span><span class="cx"> ASSERT(isMainThread());
</span><span class="cx"> lazyInitialize();
</span><del>- RefPtr<AudioBufferSourceNode> node = AudioBufferSourceNode::create(*this, m_destinationNode->sampleRate());
</del><ins>+ Ref<AudioBufferSourceNode> node = AudioBufferSourceNode::create(*this, m_destinationNode->sampleRate());
</ins><span class="cx">
</span><span class="cx"> // Because this is an AudioScheduledSourceNode, the context keeps a reference until it has finished playing.
</span><span class="cx"> // When this happens, AudioScheduledSourceNode::finish() calls AudioContext::notifyNodeFinishedProcessing().
</span><del>- refNode(node.get());
</del><ins>+ refNode(node);
</ins><span class="cx">
</span><span class="cx"> return node;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> #if ENABLE(VIDEO)
</span><del>-PassRefPtr<MediaElementAudioSourceNode> AudioContext::createMediaElementSource(HTMLMediaElement* mediaElement, ExceptionCode& ec)
</del><ins>+RefPtr<MediaElementAudioSourceNode> AudioContext::createMediaElementSource(HTMLMediaElement& mediaElement, ExceptionCode& ec)
</ins><span class="cx"> {
</span><del>- ASSERT(mediaElement);
- if (!mediaElement) {
- ec = INVALID_STATE_ERR;
- return nullptr;
- }
-
</del><span class="cx"> ASSERT(isMainThread());
</span><span class="cx"> lazyInitialize();
</span><span class="cx">
</span><span class="cx"> // First check if this media element already has a source node.
</span><del>- if (mediaElement->audioSourceNode()) {
</del><ins>+ if (mediaElement.audioSourceNode()) {
</ins><span class="cx"> ec = INVALID_STATE_ERR;
</span><span class="cx"> return nullptr;
</span><span class="cx"> }
</span><span class="cx">
</span><del>- RefPtr<MediaElementAudioSourceNode> node = MediaElementAudioSourceNode::create(*this, mediaElement);
</del><ins>+ Ref<MediaElementAudioSourceNode> node = MediaElementAudioSourceNode::create(*this, mediaElement);
</ins><span class="cx">
</span><del>- mediaElement->setAudioSourceNode(node.get());
</del><ins>+ mediaElement.setAudioSourceNode(node.ptr());
</ins><span class="cx">
</span><span class="cx"> refNode(node.get()); // context keeps reference until node is disconnected
</span><del>- return node;
</del><ins>+ return WTFMove(node);
</ins><span class="cx"> }
</span><span class="cx"> #endif
</span><span class="cx">
</span><span class="cx"> #if ENABLE(MEDIA_STREAM)
</span><del>-PassRefPtr<MediaStreamAudioSourceNode> AudioContext::createMediaStreamSource(MediaStream* mediaStream, ExceptionCode& ec)
</del><ins>+RefPtr<MediaStreamAudioSourceNode> AudioContext::createMediaStreamSource(MediaStream& mediaStream, ExceptionCode& ec)
</ins><span class="cx"> {
</span><span class="cx"> ASSERT(isMainThread());
</span><span class="cx">
</span><del>- ASSERT(mediaStream);
- if (!mediaStream) {
- ec = INVALID_STATE_ERR;
- return nullptr;
- }
-
- auto audioTracks = mediaStream->getAudioTracks();
</del><ins>+ auto audioTracks = mediaStream.getAudioTracks();
</ins><span class="cx"> if (audioTracks.isEmpty()) {
</span><span class="cx"> ec = INVALID_STATE_ERR;
</span><span class="cx"> return nullptr;
</span><span class="lines">@@ -486,14 +465,14 @@
</span><span class="cx">
</span><span class="cx"> lazyInitialize();
</span><span class="cx">
</span><del>- auto node = MediaStreamAudioSourceNode::create(*this, *mediaStream, *providerTrack);
</del><ins>+ auto node = MediaStreamAudioSourceNode::create(*this, mediaStream, *providerTrack);
</ins><span class="cx"> node->setFormat(2, sampleRate());
</span><span class="cx">
</span><del>- refNode(&node.get()); // context keeps reference until node is disconnected
- return &node.get();
</del><ins>+ refNode(node); // context keeps reference until node is disconnected
+ return WTFMove(node);
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-PassRefPtr<MediaStreamAudioDestinationNode> AudioContext::createMediaStreamDestination()
</del><ins>+Ref<MediaStreamAudioDestinationNode> AudioContext::createMediaStreamDestination()
</ins><span class="cx"> {
</span><span class="cx"> // FIXME: Add support for an optional argument which specifies the number of channels.
</span><span class="cx"> // FIXME: The default should probably be stereo instead of mono.
</span><span class="lines">@@ -502,112 +481,112 @@
</span><span class="cx">
</span><span class="cx"> #endif
</span><span class="cx">
</span><del>-PassRefPtr<ScriptProcessorNode> AudioContext::createScriptProcessor(size_t bufferSize, ExceptionCode& ec)
</del><ins>+RefPtr<ScriptProcessorNode> AudioContext::createScriptProcessor(size_t bufferSize, ExceptionCode& ec)
</ins><span class="cx"> {
</span><span class="cx"> // Set number of input/output channels to stereo by default.
</span><span class="cx"> return createScriptProcessor(bufferSize, 2, 2, ec);
</span><span class="cx"> }
</span><span class="cx">
</span><del>-PassRefPtr<ScriptProcessorNode> AudioContext::createScriptProcessor(size_t bufferSize, size_t numberOfInputChannels, ExceptionCode& ec)
</del><ins>+RefPtr<ScriptProcessorNode> AudioContext::createScriptProcessor(size_t bufferSize, size_t numberOfInputChannels, ExceptionCode& ec)
</ins><span class="cx"> {
</span><span class="cx"> // Set number of output channels to stereo by default.
</span><span class="cx"> return createScriptProcessor(bufferSize, numberOfInputChannels, 2, ec);
</span><span class="cx"> }
</span><span class="cx">
</span><del>-PassRefPtr<ScriptProcessorNode> AudioContext::createScriptProcessor(size_t bufferSize, size_t numberOfInputChannels, size_t numberOfOutputChannels, ExceptionCode& ec)
</del><ins>+RefPtr<ScriptProcessorNode> AudioContext::createScriptProcessor(size_t bufferSize, size_t numberOfInputChannels, size_t numberOfOutputChannels, ExceptionCode& ec)
</ins><span class="cx"> {
</span><span class="cx"> ASSERT(isMainThread());
</span><span class="cx"> lazyInitialize();
</span><span class="cx"> RefPtr<ScriptProcessorNode> node = ScriptProcessorNode::create(*this, m_destinationNode->sampleRate(), bufferSize, numberOfInputChannels, numberOfOutputChannels);
</span><span class="cx">
</span><del>- if (!node.get()) {
</del><ins>+ if (!node) {
</ins><span class="cx"> ec = INDEX_SIZE_ERR;
</span><span class="cx"> return nullptr;
</span><span class="cx"> }
</span><span class="cx">
</span><del>- refNode(node.get()); // context keeps reference until we stop making javascript rendering callbacks
</del><ins>+ refNode(*node); // context keeps reference until we stop making javascript rendering callbacks
</ins><span class="cx"> return node;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-PassRefPtr<BiquadFilterNode> AudioContext::createBiquadFilter()
</del><ins>+Ref<BiquadFilterNode> AudioContext::createBiquadFilter()
</ins><span class="cx"> {
</span><span class="cx"> ASSERT(isMainThread());
</span><span class="cx"> lazyInitialize();
</span><span class="cx"> return BiquadFilterNode::create(*this, m_destinationNode->sampleRate());
</span><span class="cx"> }
</span><span class="cx">
</span><del>-PassRefPtr<WaveShaperNode> AudioContext::createWaveShaper()
</del><ins>+Ref<WaveShaperNode> AudioContext::createWaveShaper()
</ins><span class="cx"> {
</span><span class="cx"> ASSERT(isMainThread());
</span><span class="cx"> lazyInitialize();
</span><span class="cx"> return WaveShaperNode::create(*this);
</span><span class="cx"> }
</span><span class="cx">
</span><del>-PassRefPtr<PannerNode> AudioContext::createPanner()
</del><ins>+Ref<PannerNode> AudioContext::createPanner()
</ins><span class="cx"> {
</span><span class="cx"> ASSERT(isMainThread());
</span><span class="cx"> lazyInitialize();
</span><span class="cx"> return PannerNode::create(*this, m_destinationNode->sampleRate());
</span><span class="cx"> }
</span><span class="cx">
</span><del>-PassRefPtr<ConvolverNode> AudioContext::createConvolver()
</del><ins>+Ref<ConvolverNode> AudioContext::createConvolver()
</ins><span class="cx"> {
</span><span class="cx"> ASSERT(isMainThread());
</span><span class="cx"> lazyInitialize();
</span><span class="cx"> return ConvolverNode::create(*this, m_destinationNode->sampleRate());
</span><span class="cx"> }
</span><span class="cx">
</span><del>-PassRefPtr<DynamicsCompressorNode> AudioContext::createDynamicsCompressor()
</del><ins>+Ref<DynamicsCompressorNode> AudioContext::createDynamicsCompressor()
</ins><span class="cx"> {
</span><span class="cx"> ASSERT(isMainThread());
</span><span class="cx"> lazyInitialize();
</span><span class="cx"> return DynamicsCompressorNode::create(*this, m_destinationNode->sampleRate());
</span><span class="cx"> }
</span><span class="cx">
</span><del>-PassRefPtr<AnalyserNode> AudioContext::createAnalyser()
</del><ins>+Ref<AnalyserNode> AudioContext::createAnalyser()
</ins><span class="cx"> {
</span><span class="cx"> ASSERT(isMainThread());
</span><span class="cx"> lazyInitialize();
</span><span class="cx"> return AnalyserNode::create(*this, m_destinationNode->sampleRate());
</span><span class="cx"> }
</span><span class="cx">
</span><del>-PassRefPtr<GainNode> AudioContext::createGain()
</del><ins>+Ref<GainNode> AudioContext::createGain()
</ins><span class="cx"> {
</span><span class="cx"> ASSERT(isMainThread());
</span><span class="cx"> lazyInitialize();
</span><span class="cx"> return GainNode::create(*this, m_destinationNode->sampleRate());
</span><span class="cx"> }
</span><span class="cx">
</span><del>-PassRefPtr<DelayNode> AudioContext::createDelay(ExceptionCode& ec)
</del><ins>+RefPtr<DelayNode> AudioContext::createDelay(ExceptionCode& ec)
</ins><span class="cx"> {
</span><span class="cx"> const double defaultMaxDelayTime = 1;
</span><span class="cx"> return createDelay(defaultMaxDelayTime, ec);
</span><span class="cx"> }
</span><span class="cx">
</span><del>-PassRefPtr<DelayNode> AudioContext::createDelay(double maxDelayTime, ExceptionCode& ec)
</del><ins>+RefPtr<DelayNode> AudioContext::createDelay(double maxDelayTime, ExceptionCode& ec)
</ins><span class="cx"> {
</span><span class="cx"> ASSERT(isMainThread());
</span><span class="cx"> lazyInitialize();
</span><del>- RefPtr<DelayNode> node = DelayNode::create(*this, m_destinationNode->sampleRate(), maxDelayTime, ec);
</del><ins>+ Ref<DelayNode> node = DelayNode::create(*this, m_destinationNode->sampleRate(), maxDelayTime, ec);
</ins><span class="cx"> if (ec)
</span><span class="cx"> return nullptr;
</span><del>- return node;
</del><ins>+ return WTFMove(node);
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-PassRefPtr<ChannelSplitterNode> AudioContext::createChannelSplitter(ExceptionCode& ec)
</del><ins>+RefPtr<ChannelSplitterNode> AudioContext::createChannelSplitter(ExceptionCode& ec)
</ins><span class="cx"> {
</span><span class="cx"> const unsigned ChannelSplitterDefaultNumberOfOutputs = 6;
</span><span class="cx"> return createChannelSplitter(ChannelSplitterDefaultNumberOfOutputs, ec);
</span><span class="cx"> }
</span><span class="cx">
</span><del>-PassRefPtr<ChannelSplitterNode> AudioContext::createChannelSplitter(size_t numberOfOutputs, ExceptionCode& ec)
</del><ins>+RefPtr<ChannelSplitterNode> AudioContext::createChannelSplitter(size_t numberOfOutputs, ExceptionCode& ec)
</ins><span class="cx"> {
</span><span class="cx"> ASSERT(isMainThread());
</span><span class="cx"> lazyInitialize();
</span><span class="cx">
</span><span class="cx"> RefPtr<ChannelSplitterNode> node = ChannelSplitterNode::create(*this, m_destinationNode->sampleRate(), numberOfOutputs);
</span><span class="cx">
</span><del>- if (!node.get()) {
</del><ins>+ if (!node) {
</ins><span class="cx"> ec = INDEX_SIZE_ERR;
</span><span class="cx"> return nullptr;
</span><span class="cx"> }
</span><span class="lines">@@ -615,20 +594,20 @@
</span><span class="cx"> return node;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-PassRefPtr<ChannelMergerNode> AudioContext::createChannelMerger(ExceptionCode& ec)
</del><ins>+RefPtr<ChannelMergerNode> AudioContext::createChannelMerger(ExceptionCode& ec)
</ins><span class="cx"> {
</span><span class="cx"> const unsigned ChannelMergerDefaultNumberOfInputs = 6;
</span><span class="cx"> return createChannelMerger(ChannelMergerDefaultNumberOfInputs, ec);
</span><span class="cx"> }
</span><span class="cx">
</span><del>-PassRefPtr<ChannelMergerNode> AudioContext::createChannelMerger(size_t numberOfInputs, ExceptionCode& ec)
</del><ins>+RefPtr<ChannelMergerNode> AudioContext::createChannelMerger(size_t numberOfInputs, ExceptionCode& ec)
</ins><span class="cx"> {
</span><span class="cx"> ASSERT(isMainThread());
</span><span class="cx"> lazyInitialize();
</span><span class="cx">
</span><span class="cx"> RefPtr<ChannelMergerNode> node = ChannelMergerNode::create(*this, m_destinationNode->sampleRate(), numberOfInputs);
</span><span class="cx">
</span><del>- if (!node.get()) {
</del><ins>+ if (!node) {
</ins><span class="cx"> ec = INDEX_SIZE_ERR;
</span><span class="cx"> return nullptr;
</span><span class="cx"> }
</span><span class="lines">@@ -636,21 +615,21 @@
</span><span class="cx"> return node;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-PassRefPtr<OscillatorNode> AudioContext::createOscillator()
</del><ins>+Ref<OscillatorNode> AudioContext::createOscillator()
</ins><span class="cx"> {
</span><span class="cx"> ASSERT(isMainThread());
</span><span class="cx"> lazyInitialize();
</span><span class="cx">
</span><del>- RefPtr<OscillatorNode> node = OscillatorNode::create(*this, m_destinationNode->sampleRate());
</del><ins>+ Ref<OscillatorNode> node = OscillatorNode::create(*this, m_destinationNode->sampleRate());
</ins><span class="cx">
</span><span class="cx"> // Because this is an AudioScheduledSourceNode, the context keeps a reference until it has finished playing.
</span><span class="cx"> // When this happens, AudioScheduledSourceNode::finish() calls AudioContext::notifyNodeFinishedProcessing().
</span><del>- refNode(node.get());
</del><ins>+ refNode(node);
</ins><span class="cx">
</span><span class="cx"> return node;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-PassRefPtr<PeriodicWave> AudioContext::createPeriodicWave(Float32Array* real, Float32Array* imag, ExceptionCode& ec)
</del><ins>+RefPtr<PeriodicWave> AudioContext::createPeriodicWave(Float32Array* real, Float32Array* imag, ExceptionCode& ec)
</ins><span class="cx"> {
</span><span class="cx"> ASSERT(isMainThread());
</span><span class="cx">
</span><span class="lines">@@ -674,28 +653,28 @@
</span><span class="cx"> ASSERT(isGraphOwner());
</span><span class="cx"> ASSERT(isAudioThread() || isAudioThreadFinished());
</span><span class="cx"> for (auto& node : m_finishedNodes)
</span><del>- derefNode(node);
</del><ins>+ derefNode(*node);
</ins><span class="cx">
</span><span class="cx"> m_finishedNodes.clear();
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void AudioContext::refNode(AudioNode* node)
</del><ins>+void AudioContext::refNode(AudioNode& node)
</ins><span class="cx"> {
</span><span class="cx"> ASSERT(isMainThread());
</span><span class="cx"> AutoLocker locker(*this);
</span><span class="cx">
</span><del>- node->ref(AudioNode::RefTypeConnection);
- m_referencedNodes.append(node);
</del><ins>+ node.ref(AudioNode::RefTypeConnection);
+ m_referencedNodes.append(&node);
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-void AudioContext::derefNode(AudioNode* node)
</del><ins>+void AudioContext::derefNode(AudioNode& node)
</ins><span class="cx"> {
</span><span class="cx"> ASSERT(isGraphOwner());
</span><span class="cx">
</span><del>- node->deref(AudioNode::RefTypeConnection);
</del><ins>+ node.deref(AudioNode::RefTypeConnection);
</ins><span class="cx">
</span><del>- ASSERT(m_referencedNodes.contains(node));
- m_referencedNodes.removeFirst(node);
</del><ins>+ ASSERT(m_referencedNodes.contains(&node));
+ m_referencedNodes.removeFirst(&node);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> void AudioContext::derefUnfinishedSourceNodes()
</span></span></pre></div>
<a id="trunkSourceWebCoreModuleswebaudioAudioContexth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/webaudio/AudioContext.h (199774 => 199775)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/webaudio/AudioContext.h        2016-04-20 16:14:14 UTC (rev 199774)
+++ trunk/Source/WebCore/Modules/webaudio/AudioContext.h        2016-04-20 17:27:37 UTC (rev 199775)
</span><span class="lines">@@ -1,5 +1,6 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2010, Google Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
</ins><span class="cx"> *
</span><span class="cx"> * Redistribution and use in source and binary forms, with or without
</span><span class="cx"> * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -38,7 +39,6 @@
</span><span class="cx"> #include <atomic>
</span><span class="cx"> #include <wtf/HashSet.h>
</span><span class="cx"> #include <wtf/MainThread.h>
</span><del>-#include <wtf/PassRefPtr.h>
</del><span class="cx"> #include <wtf/RefCounted.h>
</span><span class="cx"> #include <wtf/RefPtr.h>
</span><span class="cx"> #include <wtf/ThreadSafeRefCounted.h>
</span><span class="lines">@@ -101,11 +101,11 @@
</span><span class="cx"> void incrementActiveSourceCount();
</span><span class="cx"> void decrementActiveSourceCount();
</span><span class="cx">
</span><del>- PassRefPtr<AudioBuffer> createBuffer(unsigned numberOfChannels, size_t numberOfFrames, float sampleRate, ExceptionCode&);
- PassRefPtr<AudioBuffer> createBuffer(ArrayBuffer*, bool mixToMono, ExceptionCode&);
</del><ins>+ RefPtr<AudioBuffer> createBuffer(unsigned numberOfChannels, size_t numberOfFrames, float sampleRate, ExceptionCode&);
+ RefPtr<AudioBuffer> createBuffer(ArrayBuffer&, bool mixToMono, ExceptionCode&);
</ins><span class="cx">
</span><span class="cx"> // Asynchronous audio file data decoding.
</span><del>- void decodeAudioData(ArrayBuffer*, PassRefPtr<AudioBufferCallback>, PassRefPtr<AudioBufferCallback>, ExceptionCode& ec);
</del><ins>+ void decodeAudioData(Ref<ArrayBuffer>&&, RefPtr<AudioBufferCallback>&&, RefPtr<AudioBufferCallback>&&);
</ins><span class="cx">
</span><span class="cx"> AudioListener* listener() { return m_listener.get(); }
</span><span class="cx">
</span><span class="lines">@@ -121,32 +121,32 @@
</span><span class="cx"> const AtomicString& state() const;
</span><span class="cx">
</span><span class="cx"> // The AudioNode create methods are called on the main thread (from JavaScript).
</span><del>- PassRefPtr<AudioBufferSourceNode> createBufferSource();
</del><ins>+ Ref<AudioBufferSourceNode> createBufferSource();
</ins><span class="cx"> #if ENABLE(VIDEO)
</span><del>- PassRefPtr<MediaElementAudioSourceNode> createMediaElementSource(HTMLMediaElement*, ExceptionCode&);
</del><ins>+ RefPtr<MediaElementAudioSourceNode> createMediaElementSource(HTMLMediaElement&, ExceptionCode&);
</ins><span class="cx"> #endif
</span><span class="cx"> #if ENABLE(MEDIA_STREAM)
</span><del>- PassRefPtr<MediaStreamAudioSourceNode> createMediaStreamSource(MediaStream*, ExceptionCode&);
- PassRefPtr<MediaStreamAudioDestinationNode> createMediaStreamDestination();
</del><ins>+ RefPtr<MediaStreamAudioSourceNode> createMediaStreamSource(MediaStream&, ExceptionCode&);
+ Ref<MediaStreamAudioDestinationNode> createMediaStreamDestination();
</ins><span class="cx"> #endif
</span><del>- PassRefPtr<GainNode> createGain();
- PassRefPtr<BiquadFilterNode> createBiquadFilter();
- PassRefPtr<WaveShaperNode> createWaveShaper();
- PassRefPtr<DelayNode> createDelay(ExceptionCode&);
- PassRefPtr<DelayNode> createDelay(double maxDelayTime, ExceptionCode&);
- PassRefPtr<PannerNode> createPanner();
- PassRefPtr<ConvolverNode> createConvolver();
- PassRefPtr<DynamicsCompressorNode> createDynamicsCompressor();
- PassRefPtr<AnalyserNode> createAnalyser();
- PassRefPtr<ScriptProcessorNode> createScriptProcessor(size_t bufferSize, ExceptionCode&);
- PassRefPtr<ScriptProcessorNode> createScriptProcessor(size_t bufferSize, size_t numberOfInputChannels, ExceptionCode&);
- PassRefPtr<ScriptProcessorNode> createScriptProcessor(size_t bufferSize, size_t numberOfInputChannels, size_t numberOfOutputChannels, ExceptionCode&);
- PassRefPtr<ChannelSplitterNode> createChannelSplitter(ExceptionCode&);
- PassRefPtr<ChannelSplitterNode> createChannelSplitter(size_t numberOfOutputs, ExceptionCode&);
- PassRefPtr<ChannelMergerNode> createChannelMerger(ExceptionCode&);
- PassRefPtr<ChannelMergerNode> createChannelMerger(size_t numberOfInputs, ExceptionCode&);
- PassRefPtr<OscillatorNode> createOscillator();
- PassRefPtr<PeriodicWave> createPeriodicWave(Float32Array* real, Float32Array* imag, ExceptionCode&);
</del><ins>+ Ref<GainNode> createGain();
+ Ref<BiquadFilterNode> createBiquadFilter();
+ Ref<WaveShaperNode> createWaveShaper();
+ RefPtr<DelayNode> createDelay(ExceptionCode&);
+ RefPtr<DelayNode> createDelay(double maxDelayTime, ExceptionCode&);
+ Ref<PannerNode> createPanner();
+ Ref<ConvolverNode> createConvolver();
+ Ref<DynamicsCompressorNode> createDynamicsCompressor();
+ Ref<AnalyserNode> createAnalyser();
+ RefPtr<ScriptProcessorNode> createScriptProcessor(size_t bufferSize, ExceptionCode&);
+ RefPtr<ScriptProcessorNode> createScriptProcessor(size_t bufferSize, size_t numberOfInputChannels, ExceptionCode&);
+ RefPtr<ScriptProcessorNode> createScriptProcessor(size_t bufferSize, size_t numberOfInputChannels, size_t numberOfOutputChannels, ExceptionCode&);
+ RefPtr<ChannelSplitterNode> createChannelSplitter(ExceptionCode&);
+ RefPtr<ChannelSplitterNode> createChannelSplitter(size_t numberOfOutputs, ExceptionCode&);
+ RefPtr<ChannelMergerNode> createChannelMerger(ExceptionCode&);
+ RefPtr<ChannelMergerNode> createChannelMerger(size_t numberOfInputs, ExceptionCode&);
+ Ref<OscillatorNode> createOscillator();
+ RefPtr<PeriodicWave> createPeriodicWave(Float32Array* real, Float32Array* imag, ExceptionCode&);
</ins><span class="cx">
</span><span class="cx"> // When a source node has no more processing to do (has finished playing), then it tells the context to dereference it.
</span><span class="cx"> void notifyNodeFinishedProcessing(AudioNode*);
</span><span class="lines">@@ -303,8 +303,8 @@
</span><span class="cx"> // In turn, these nodes reference all nodes they're connected to. All nodes are ultimately connected to the AudioDestinationNode.
</span><span class="cx"> // When the context dereferences a source node, it will be deactivated from the rendering graph along with all other nodes it is
</span><span class="cx"> // uniquely connected to. See the AudioNode::ref() and AudioNode::deref() methods for more details.
</span><del>- void refNode(AudioNode*);
- void derefNode(AudioNode*);
</del><ins>+ void refNode(AudioNode&);
+ void derefNode(AudioNode&);
</ins><span class="cx">
</span><span class="cx"> // ActiveDOMObject API.
</span><span class="cx"> void stop() override;
</span></span></pre></div>
<a id="trunkSourceWebCoreModuleswebaudioAudioContextidl"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/webaudio/AudioContext.idl (199774 => 199775)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/webaudio/AudioContext.idl        2016-04-20 16:14:14 UTC (rev 199774)
+++ trunk/Source/WebCore/Modules/webaudio/AudioContext.idl        2016-04-20 17:27:37 UTC (rev 199775)
</span><span class="lines">@@ -31,13 +31,12 @@
</span><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> [
</span><del>- EnabledBySetting=WebAudio,
- Conditional=WEB_AUDIO,
</del><span class="cx"> ActiveDOMObject,
</span><ins>+ Conditional=WEB_AUDIO,
</ins><span class="cx"> CustomConstructor,
</span><del>- UsePointersEvenForNonNullableObjectArguments,
- InterfaceName=webkitAudioContext,
</del><ins>+ EnabledBySetting=WebAudio,
</ins><span class="cx"> ExportMacro=WEBCORE_EXPORT,
</span><ins>+ InterfaceName=webkitAudioContext,
</ins><span class="cx"> ] interface AudioContext : EventTarget {
</span><span class="cx"> // All rendered audio ultimately connects to destination, which represents the audio hardware.
</span><span class="cx"> readonly attribute AudioDestinationNode destination;
</span><span class="lines">@@ -62,22 +61,19 @@
</span><span class="cx"> readonly attribute unsigned long activeSourceCount;
</span><span class="cx">
</span><span class="cx"> [RaisesException] AudioBuffer createBuffer(unsigned long numberOfChannels, unsigned long numberOfFrames, unrestricted float sampleRate);
</span><del>- [RaisesException] AudioBuffer createBuffer(ArrayBuffer? buffer, boolean mixToMono);
</del><ins>+ [RaisesException] AudioBuffer createBuffer(ArrayBuffer buffer, boolean mixToMono);
</ins><span class="cx">
</span><span class="cx"> // Asynchronous audio file data decoding.
</span><del>- [RaisesException] void decodeAudioData(ArrayBuffer audioData, AudioBufferCallback successCallback, optional AudioBufferCallback errorCallback);
</del><ins>+ // FIXME: successCallback should be optional and the callbacks should not be nullable. This should also return a Promise.
+ void decodeAudioData(ArrayBuffer audioData, AudioBufferCallback? successCallback, optional AudioBufferCallback? errorCallback);
</ins><span class="cx">
</span><span class="cx"> // Sources
</span><span class="cx"> AudioBufferSourceNode createBufferSource();
</span><span class="cx">
</span><del>-#if defined(ENABLE_VIDEO) && ENABLE_VIDEO
- [RaisesException] MediaElementAudioSourceNode createMediaElementSource(HTMLMediaElement mediaElement);
-#endif
</del><ins>+ [Conditional=VIDEO, RaisesException] MediaElementAudioSourceNode createMediaElementSource(HTMLMediaElement mediaElement);
</ins><span class="cx">
</span><del>-#if defined(ENABLE_MEDIA_STREAM) && ENABLE_MEDIA_STREAM
- [RaisesException] MediaStreamAudioSourceNode createMediaStreamSource(MediaStream mediaStream);
- MediaStreamAudioDestinationNode createMediaStreamDestination();
-#endif
</del><ins>+ [Conditional=MEDIA_STREAM, RaisesException] MediaStreamAudioSourceNode createMediaStreamSource(MediaStream mediaStream);
+ [Conditional=MEDIA_STREAM] MediaStreamAudioDestinationNode createMediaStreamDestination();
</ins><span class="cx">
</span><span class="cx"> // Processing nodes
</span><span class="cx"> GainNode createGain();
</span></span></pre></div>
<a id="trunkSourceWebCoreModuleswebaudioMediaElementAudioSourceNodecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/webaudio/MediaElementAudioSourceNode.cpp (199774 => 199775)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/webaudio/MediaElementAudioSourceNode.cpp        2016-04-20 16:14:14 UTC (rev 199774)
+++ trunk/Source/WebCore/Modules/webaudio/MediaElementAudioSourceNode.cpp        2016-04-20 17:27:37 UTC (rev 199775)
</span><span class="lines">@@ -40,12 +40,12 @@
</span><span class="cx">
</span><span class="cx"> namespace WebCore {
</span><span class="cx">
</span><del>-Ref<MediaElementAudioSourceNode> MediaElementAudioSourceNode::create(AudioContext& context, HTMLMediaElement* mediaElement)
</del><ins>+Ref<MediaElementAudioSourceNode> MediaElementAudioSourceNode::create(AudioContext& context, HTMLMediaElement& mediaElement)
</ins><span class="cx"> {
</span><span class="cx"> return adoptRef(*new MediaElementAudioSourceNode(context, mediaElement));
</span><span class="cx"> }
</span><span class="cx">
</span><del>-MediaElementAudioSourceNode::MediaElementAudioSourceNode(AudioContext& context, HTMLMediaElement* mediaElement)
</del><ins>+MediaElementAudioSourceNode::MediaElementAudioSourceNode(AudioContext& context, HTMLMediaElement& mediaElement)
</ins><span class="cx"> : AudioNode(context, context.sampleRate())
</span><span class="cx"> , m_mediaElement(mediaElement)
</span><span class="cx"> , m_sourceNumberOfChannels(0)
</span><span class="lines">@@ -104,7 +104,7 @@
</span><span class="cx"> {
</span><span class="cx"> AudioBus* outputBus = output(0)->bus();
</span><span class="cx">
</span><del>- if (!mediaElement() || !m_sourceNumberOfChannels || !m_sourceSampleRate) {
</del><ins>+ if (!m_sourceNumberOfChannels || !m_sourceSampleRate) {
</ins><span class="cx"> outputBus->zero();
</span><span class="cx"> return;
</span><span class="cx"> }
</span><span class="lines">@@ -119,7 +119,7 @@
</span><span class="cx"> return;
</span><span class="cx"> }
</span><span class="cx">
</span><del>- if (AudioSourceProvider* provider = mediaElement()->audioSourceProvider()) {
</del><ins>+ if (AudioSourceProvider* provider = mediaElement().audioSourceProvider()) {
</ins><span class="cx"> if (m_multiChannelResampler.get()) {
</span><span class="cx"> ASSERT(m_sourceSampleRate != sampleRate());
</span><span class="cx"> m_multiChannelResampler->process(provider, outputBus, numberOfFrames);
</span></span></pre></div>
<a id="trunkSourceWebCoreModuleswebaudioMediaElementAudioSourceNodeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/webaudio/MediaElementAudioSourceNode.h (199774 => 199775)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/webaudio/MediaElementAudioSourceNode.h        2016-04-20 16:14:14 UTC (rev 199774)
+++ trunk/Source/WebCore/Modules/webaudio/MediaElementAudioSourceNode.h        2016-04-20 17:27:37 UTC (rev 199775)
</span><span class="lines">@@ -41,11 +41,11 @@
</span><span class="cx">
</span><span class="cx"> class MediaElementAudioSourceNode : public AudioNode, public AudioSourceProviderClient {
</span><span class="cx"> public:
</span><del>- static Ref<MediaElementAudioSourceNode> create(AudioContext&, HTMLMediaElement*);
</del><ins>+ static Ref<MediaElementAudioSourceNode> create(AudioContext&, HTMLMediaElement&);
</ins><span class="cx">
</span><span class="cx"> virtual ~MediaElementAudioSourceNode();
</span><span class="cx">
</span><del>- HTMLMediaElement* mediaElement() { return m_mediaElement.get(); }
</del><ins>+ HTMLMediaElement& mediaElement() { return m_mediaElement; }
</ins><span class="cx">
</span><span class="cx"> // AudioNode
</span><span class="cx"> void process(size_t framesToProcess) override;
</span><span class="lines">@@ -58,7 +58,7 @@
</span><span class="cx"> void unlock();
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- MediaElementAudioSourceNode(AudioContext&, HTMLMediaElement*);
</del><ins>+ MediaElementAudioSourceNode(AudioContext&, HTMLMediaElement&);
</ins><span class="cx">
</span><span class="cx"> double tailTime() const override { return 0; }
</span><span class="cx"> double latencyTime() const override { return 0; }
</span><span class="lines">@@ -66,7 +66,7 @@
</span><span class="cx"> // As an audio source, we will never propagate silence.
</span><span class="cx"> bool propagatesSilence() const override { return false; }
</span><span class="cx">
</span><del>- RefPtr<HTMLMediaElement> m_mediaElement;
</del><ins>+ Ref<HTMLMediaElement> m_mediaElement;
</ins><span class="cx"> Lock m_processMutex;
</span><span class="cx">
</span><span class="cx"> unsigned m_sourceNumberOfChannels;
</span></span></pre></div>
<a id="trunkSourceWebCoreModuleswebaudioOscillatorNodeidl"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/webaudio/OscillatorNode.idl (199774 => 199775)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/webaudio/OscillatorNode.idl        2016-04-20 16:14:14 UTC (rev 199774)
+++ trunk/Source/WebCore/Modules/webaudio/OscillatorNode.idl        2016-04-20 17:27:37 UTC (rev 199775)
</span><span class="lines">@@ -25,7 +25,6 @@
</span><span class="cx"> // OscillatorNode is an audio generator of periodic waveforms.
</span><span class="cx"> [
</span><span class="cx"> Conditional=WEB_AUDIO,
</span><del>- UsePointersEvenForNonNullableObjectArguments,
</del><span class="cx"> JSGenerateToJSObject,
</span><span class="cx"> ] interface OscillatorNode : AudioNode {
</span><span class="cx">
</span><span class="lines">@@ -55,7 +54,7 @@
</span><span class="cx"> [Conditional=LEGACY_WEB_AUDIO, RaisesException] void noteOn(unrestricted double when);
</span><span class="cx"> [Conditional=LEGACY_WEB_AUDIO, RaisesException] void noteOff(unrestricted double when);
</span><span class="cx">
</span><del>- void setPeriodicWave(PeriodicWave wave);
</del><ins>+ void setPeriodicWave(PeriodicWave? wave); // FIXME: The parameter should not be nullable.
</ins><span class="cx">
</span><span class="cx"> attribute EventHandler onended;
</span><span class="cx"> };
</span></span></pre>
</div>
</div>
</body>
</html>