<!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>[278307] trunk/Source/WebCore</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/278307">278307</a></dd>
<dt>Author</dt> <dd>cdumez@apple.com</dd>
<dt>Date</dt> <dd>2021-06-01 08:09:47 -0700 (Tue, 01 Jun 2021)</dd>
</dl>

<h3>Log Message</h3>
<pre>Fix thread safety issues in WaveShaperProcessor
https://bugs.webkit.org/show_bug.cgi?id=226478

Reviewed by Youenn Fablet.

Adopt thread safety analysis annotations in WaveShaperProcessor and fix bugs
found by clang. In particular, the following issues were fixed:
- WaveShaperDSPKernel::latencyTime() was failing to grab the lock before accessing
  the WaveShaperProcessor's oversample on the rendering thread, even though
  oversample gets modified on the main thread.
- WaveShaperNode::propagatesSilence() was failing to grab the lock before accessing
  the WaveShaperProcessor's curve on the rendering thread, even though the curve
  gets modified on the main thread.

* Modules/webaudio/AudioBasicProcessorNode.h:
(WebCore::AudioBasicProcessorNode::processor const):
* Modules/webaudio/WaveShaperDSPKernel.cpp:
(WebCore::WaveShaperDSPKernel::process):
(WebCore::WaveShaperDSPKernel::processCurve):
(WebCore::WaveShaperDSPKernel::latencyTime const):
* Modules/webaudio/WaveShaperDSPKernel.h:
* Modules/webaudio/WaveShaperNode.cpp:
(WebCore::WaveShaperNode::create):
(WebCore::WaveShaperNode::setCurveForBindings):
(WebCore::WaveShaperNode::curveForBindings):
(WebCore::WaveShaperNode::setOversampleForBindings):
(WebCore::WaveShaperNode::oversampleForBindings const):
(WebCore::WaveShaperNode::propagatesSilence const):
* Modules/webaudio/WaveShaperNode.h:
* Modules/webaudio/WaveShaperNode.idl:
* Modules/webaudio/WaveShaperProcessor.cpp:
(WebCore::WaveShaperProcessor::setCurveForBindings):
(WebCore::WaveShaperProcessor::setOversampleForBindings):
(WebCore::WaveShaperProcessor::process):
* Modules/webaudio/WaveShaperProcessor.h:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreModuleswebaudioAudioBasicProcessorNodeh">trunk/Source/WebCore/Modules/webaudio/AudioBasicProcessorNode.h</a></li>
<li><a href="#trunkSourceWebCoreModuleswebaudioWaveShaperDSPKernelcpp">trunk/Source/WebCore/Modules/webaudio/WaveShaperDSPKernel.cpp</a></li>
<li><a href="#trunkSourceWebCoreModuleswebaudioWaveShaperDSPKernelh">trunk/Source/WebCore/Modules/webaudio/WaveShaperDSPKernel.h</a></li>
<li><a href="#trunkSourceWebCoreModuleswebaudioWaveShaperNodecpp">trunk/Source/WebCore/Modules/webaudio/WaveShaperNode.cpp</a></li>
<li><a href="#trunkSourceWebCoreModuleswebaudioWaveShaperNodeh">trunk/Source/WebCore/Modules/webaudio/WaveShaperNode.h</a></li>
<li><a href="#trunkSourceWebCoreModuleswebaudioWaveShaperNodeidl">trunk/Source/WebCore/Modules/webaudio/WaveShaperNode.idl</a></li>
<li><a href="#trunkSourceWebCoreModuleswebaudioWaveShaperProcessorcpp">trunk/Source/WebCore/Modules/webaudio/WaveShaperProcessor.cpp</a></li>
<li><a href="#trunkSourceWebCoreModuleswebaudioWaveShaperProcessorh">trunk/Source/WebCore/Modules/webaudio/WaveShaperProcessor.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (278306 => 278307)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog   2021-06-01 14:56:04 UTC (rev 278306)
+++ trunk/Source/WebCore/ChangeLog      2021-06-01 15:09:47 UTC (rev 278307)
</span><span class="lines">@@ -1,5 +1,43 @@
</span><span class="cx"> 2021-06-01  Chris Dumez  <cdumez@apple.com>
</span><span class="cx"> 
</span><ins>+        Fix thread safety issues in WaveShaperProcessor
+        https://bugs.webkit.org/show_bug.cgi?id=226478
+
+        Reviewed by Youenn Fablet.
+
+        Adopt thread safety analysis annotations in WaveShaperProcessor and fix bugs
+        found by clang. In particular, the following issues were fixed:
+        - WaveShaperDSPKernel::latencyTime() was failing to grab the lock before accessing
+          the WaveShaperProcessor's oversample on the rendering thread, even though
+          oversample gets modified on the main thread.
+        - WaveShaperNode::propagatesSilence() was failing to grab the lock before accessing
+          the WaveShaperProcessor's curve on the rendering thread, even though the curve
+          gets modified on the main thread.
+
+        * Modules/webaudio/AudioBasicProcessorNode.h:
+        (WebCore::AudioBasicProcessorNode::processor const):
+        * Modules/webaudio/WaveShaperDSPKernel.cpp:
+        (WebCore::WaveShaperDSPKernel::process):
+        (WebCore::WaveShaperDSPKernel::processCurve):
+        (WebCore::WaveShaperDSPKernel::latencyTime const):
+        * Modules/webaudio/WaveShaperDSPKernel.h:
+        * Modules/webaudio/WaveShaperNode.cpp:
+        (WebCore::WaveShaperNode::create):
+        (WebCore::WaveShaperNode::setCurveForBindings):
+        (WebCore::WaveShaperNode::curveForBindings):
+        (WebCore::WaveShaperNode::setOversampleForBindings):
+        (WebCore::WaveShaperNode::oversampleForBindings const):
+        (WebCore::WaveShaperNode::propagatesSilence const):
+        * Modules/webaudio/WaveShaperNode.h:
+        * Modules/webaudio/WaveShaperNode.idl:
+        * Modules/webaudio/WaveShaperProcessor.cpp:
+        (WebCore::WaveShaperProcessor::setCurveForBindings):
+        (WebCore::WaveShaperProcessor::setOversampleForBindings):
+        (WebCore::WaveShaperProcessor::process):
+        * Modules/webaudio/WaveShaperProcessor.h:
+
+2021-06-01  Chris Dumez  <cdumez@apple.com>
+
</ins><span class="cx">         Fix thread safety issues in MediaElementAudioSourceNode
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=226475
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreModuleswebaudioAudioBasicProcessorNodeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/webaudio/AudioBasicProcessorNode.h (278306 => 278307)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/webaudio/AudioBasicProcessorNode.h  2021-06-01 14:56:04 UTC (rev 278306)
+++ trunk/Source/WebCore/Modules/webaudio/AudioBasicProcessorNode.h     2021-06-01 15:09:47 UTC (rev 278307)
</span><span class="lines">@@ -58,6 +58,8 @@
</span><span class="cx">     bool requiresTailProcessing() const override;
</span><span class="cx"> 
</span><span class="cx">     AudioProcessor* processor() { return m_processor.get(); }
</span><ins>+    const AudioProcessor* processor() const { return m_processor.get(); }
+
</ins><span class="cx">     std::unique_ptr<AudioProcessor> m_processor;
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreModuleswebaudioWaveShaperDSPKernelcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/webaudio/WaveShaperDSPKernel.cpp (278306 => 278307)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/webaudio/WaveShaperDSPKernel.cpp    2021-06-01 14:56:04 UTC (rev 278306)
+++ trunk/Source/WebCore/Modules/webaudio/WaveShaperDSPKernel.cpp       2021-06-01 15:09:47 UTC (rev 278307)
</span><span class="lines">@@ -59,6 +59,7 @@
</span><span class="cx"> 
</span><span class="cx"> void WaveShaperDSPKernel::process(const float* source, float* destination, size_t framesToProcess)
</span><span class="cx"> {
</span><ins>+    assertIsHeld(waveShaperProcessor()->processLock());
</ins><span class="cx">     switch (waveShaperProcessor()->oversample()) {
</span><span class="cx">     case WaveShaperProcessor::OverSampleNone:
</span><span class="cx">         processCurve(source, destination, framesToProcess);
</span><span class="lines">@@ -79,6 +80,7 @@
</span><span class="cx"> {
</span><span class="cx">     ASSERT(source && destination && waveShaperProcessor());
</span><span class="cx"> 
</span><ins>+    assertIsHeld(waveShaperProcessor()->processLock());
</ins><span class="cx">     Float32Array* curve = waveShaperProcessor()->curve();
</span><span class="cx">     if (!curve) {
</span><span class="cx">         // Act as "straight wire" pass-through if no curve is set.
</span><span class="lines">@@ -163,10 +165,13 @@
</span><span class="cx"> 
</span><span class="cx"> double WaveShaperDSPKernel::latencyTime() const
</span><span class="cx"> {
</span><ins>+    if (!waveShaperProcessor()->processLock().tryLock())
+        return std::numeric_limits<double>::infinity();
+
+    Locker locker { AdoptLock, waveShaperProcessor()->processLock() };
+
</ins><span class="cx">     size_t latencyFrames = 0;
</span><del>-    WaveShaperDSPKernel* kernel = const_cast<WaveShaperDSPKernel*>(this);
-
-    switch (kernel->waveShaperProcessor()->oversample()) {
</del><ins>+    switch (waveShaperProcessor()->oversample()) {
</ins><span class="cx">     case WaveShaperProcessor::OverSampleNone:
</span><span class="cx">         break;
</span><span class="cx">     case WaveShaperProcessor::OverSample2x:
</span></span></pre></div>
<a id="trunkSourceWebCoreModuleswebaudioWaveShaperDSPKernelh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/webaudio/WaveShaperDSPKernel.h (278306 => 278307)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/webaudio/WaveShaperDSPKernel.h      2021-06-01 14:56:04 UTC (rev 278306)
+++ trunk/Source/WebCore/Modules/webaudio/WaveShaperDSPKernel.h 2021-06-01 15:09:47 UTC (rev 278307)
</span><span class="lines">@@ -40,10 +40,10 @@
</span><span class="cx">     explicit WaveShaperDSPKernel(WaveShaperProcessor*);
</span><span class="cx"> 
</span><span class="cx">     // AudioDSPKernel
</span><del>-    void process(const float* source, float* dest, size_t framesToProcess) override;
-    void reset() override;
-    double tailTime() const override { return 0; }
-    double latencyTime() const override;
</del><ins>+    void process(const float* source, float* dest, size_t framesToProcess) final;
+    void reset() final;
+    double tailTime() const final { return 0; }
+    double latencyTime() const final;
</ins><span class="cx"> 
</span><span class="cx">     // Oversampling requires more resources, so let's only allocate them if needed.
</span><span class="cx">     void lazyInitializeOversampling();
</span><span class="lines">@@ -59,6 +59,7 @@
</span><span class="cx">     bool requiresTailProcessing() const final;
</span><span class="cx"> 
</span><span class="cx">     WaveShaperProcessor* waveShaperProcessor() { return static_cast<WaveShaperProcessor*>(processor()); }
</span><ins>+    const WaveShaperProcessor* waveShaperProcessor() const { return static_cast<const WaveShaperProcessor*>(processor()); }
</ins><span class="cx"> 
</span><span class="cx">     // Oversampling.
</span><span class="cx">     std::unique_ptr<AudioFloatArray> m_tempBuffer;
</span></span></pre></div>
<a id="trunkSourceWebCoreModuleswebaudioWaveShaperNodecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/webaudio/WaveShaperNode.cpp (278306 => 278307)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/webaudio/WaveShaperNode.cpp 2021-06-01 14:56:04 UTC (rev 278306)
+++ trunk/Source/WebCore/Modules/webaudio/WaveShaperNode.cpp    2021-06-01 15:09:47 UTC (rev 278307)
</span><span class="lines">@@ -53,12 +53,12 @@
</span><span class="cx">         return result.releaseException();
</span><span class="cx"> 
</span><span class="cx">     if (curve) {
</span><del>-        result = node->setCurve(WTFMove(curve));
</del><ins>+        result = node->setCurveForBindings(WTFMove(curve));
</ins><span class="cx">         if (result.hasException())
</span><span class="cx">             return result.releaseException();
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    node->setOversample(options.oversample);
</del><ins>+    node->setOversampleForBindings(options.oversample);
</ins><span class="cx"> 
</span><span class="cx">     return node;
</span><span class="cx"> }
</span><span class="lines">@@ -71,7 +71,7 @@
</span><span class="cx">     initialize();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-ExceptionOr<void> WaveShaperNode::setCurve(RefPtr<Float32Array>&& curve)
</del><ins>+ExceptionOr<void> WaveShaperNode::setCurveForBindings(RefPtr<Float32Array>&& curve)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(isMainThread()); 
</span><span class="cx">     DEBUG_LOG(LOGIDENTIFIER);
</span><span class="lines">@@ -85,13 +85,14 @@
</span><span class="cx">         curve = WTFMove(clonedCurve);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    waveShaperProcessor()->setCurve(curve.get());
</del><ins>+    waveShaperProcessor()->setCurveForBindings(curve.get());
</ins><span class="cx">     return { };
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-Float32Array* WaveShaperNode::curve()
</del><ins>+Float32Array* WaveShaperNode::curveForBindings()
</ins><span class="cx"> {
</span><del>-    return waveShaperProcessor()->curve();
</del><ins>+    ASSERT(isMainThread());
+    return waveShaperProcessor()->curveForBindings();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static inline WaveShaperProcessor::OverSampleType processorType(OverSampleType type)
</span><span class="lines">@@ -108,7 +109,7 @@
</span><span class="cx">     return WaveShaperProcessor::OverSampleNone;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void WaveShaperNode::setOversample(OverSampleType type)
</del><ins>+void WaveShaperNode::setOversampleForBindings(OverSampleType type)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(isMainThread());
</span><span class="cx">     INFO_LOG(LOGIDENTIFIER, type);
</span><span class="lines">@@ -115,12 +116,13 @@
</span><span class="cx"> 
</span><span class="cx">     // Synchronize with any graph changes or changes to channel configuration.
</span><span class="cx">     Locker contextLocker { context().graphLock() };
</span><del>-    waveShaperProcessor()->setOversample(processorType(type));
</del><ins>+    waveShaperProcessor()->setOversampleForBindings(processorType(type));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-auto WaveShaperNode::oversample() const -> OverSampleType
</del><ins>+auto WaveShaperNode::oversampleForBindings() const -> OverSampleType
</ins><span class="cx"> {
</span><del>-    switch (const_cast<WaveShaperNode*>(this)->waveShaperProcessor()->oversample()) {
</del><ins>+    ASSERT(isMainThread());
+    switch (waveShaperProcessor()->oversampleForBindings()) {
</ins><span class="cx">     case WaveShaperProcessor::OverSampleNone:
</span><span class="cx">         return OverSampleType::None;
</span><span class="cx">     case WaveShaperProcessor::OverSample2x:
</span><span class="lines">@@ -134,7 +136,11 @@
</span><span class="cx"> 
</span><span class="cx"> bool WaveShaperNode::propagatesSilence() const
</span><span class="cx"> {
</span><del>-    auto curve = const_cast<WaveShaperNode*>(this)->curve();
</del><ins>+    if (!waveShaperProcessor()->processLock().tryLock())
+        return false;
+
+    Locker locker { AdoptLock, waveShaperProcessor()->processLock() };
+    auto curve = waveShaperProcessor()->curve();
</ins><span class="cx">     return !curve || !curve->length();
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreModuleswebaudioWaveShaperNodeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/webaudio/WaveShaperNode.h (278306 => 278307)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/webaudio/WaveShaperNode.h   2021-06-01 14:56:04 UTC (rev 278306)
+++ trunk/Source/WebCore/Modules/webaudio/WaveShaperNode.h      2021-06-01 15:09:47 UTC (rev 278307)
</span><span class="lines">@@ -40,11 +40,11 @@
</span><span class="cx">     static ExceptionOr<Ref<WaveShaperNode>> create(BaseAudioContext&, const WaveShaperOptions& = { });
</span><span class="cx"> 
</span><span class="cx">     // setCurve() is called on the main thread.
</span><del>-    ExceptionOr<void> setCurve(RefPtr<Float32Array>&&);
-    Float32Array* curve();
</del><ins>+    ExceptionOr<void> setCurveForBindings(RefPtr<Float32Array>&&);
+    Float32Array* curveForBindings();
</ins><span class="cx"> 
</span><del>-    void setOversample(OverSampleType);
-    OverSampleType oversample() const;
</del><ins>+    void setOversampleForBindings(OverSampleType);
+    OverSampleType oversampleForBindings() const;
</ins><span class="cx"> 
</span><span class="cx">     double latency() const { return latencyTime(); }
</span><span class="cx"> 
</span><span class="lines">@@ -54,6 +54,7 @@
</span><span class="cx">     bool propagatesSilence() const final;
</span><span class="cx"> 
</span><span class="cx">     WaveShaperProcessor* waveShaperProcessor() { return static_cast<WaveShaperProcessor*>(processor()); }
</span><ins>+    const WaveShaperProcessor* waveShaperProcessor() const { return static_cast<const WaveShaperProcessor*>(processor()); }
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> String convertEnumerationToString(WebCore::OverSampleType); // in JSOverSampleType.cpp
</span></span></pre></div>
<a id="trunkSourceWebCoreModuleswebaudioWaveShaperNodeidl"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/webaudio/WaveShaperNode.idl (278306 => 278307)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/webaudio/WaveShaperNode.idl 2021-06-01 14:56:04 UTC (rev 278306)
+++ trunk/Source/WebCore/Modules/webaudio/WaveShaperNode.idl    2021-06-01 15:09:47 UTC (rev 278307)
</span><span class="lines">@@ -29,6 +29,6 @@
</span><span class="cx"> ] interface WaveShaperNode : AudioNode {
</span><span class="cx">     [EnabledBySetting=WebAudio] constructor(BaseAudioContext context, optional WaveShaperOptions options);
</span><span class="cx"> 
</span><del>-    attribute Float32Array? curve;
-    attribute OverSampleType oversample;
</del><ins>+    [ImplementedAs=curveForBindings] attribute Float32Array? curve;
+    [ImplementedAs=oversampleForBindings] attribute OverSampleType oversample;
</ins><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceWebCoreModuleswebaudioWaveShaperProcessorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/webaudio/WaveShaperProcessor.cpp (278306 => 278307)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/webaudio/WaveShaperProcessor.cpp    2021-06-01 14:56:04 UTC (rev 278306)
+++ trunk/Source/WebCore/Modules/webaudio/WaveShaperProcessor.cpp       2021-06-01 15:09:47 UTC (rev 278307)
</span><span class="lines">@@ -48,8 +48,9 @@
</span><span class="cx">     return makeUnique<WaveShaperDSPKernel>(this);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void WaveShaperProcessor::setCurve(Float32Array* curve)
</del><ins>+void WaveShaperProcessor::setCurveForBindings(Float32Array* curve)
</ins><span class="cx"> {
</span><ins>+    ASSERT(isMainThread());
</ins><span class="cx">     // This synchronizes with process().
</span><span class="cx">     Locker locker { m_processLock };
</span><span class="cx"> 
</span><span class="lines">@@ -56,19 +57,19 @@
</span><span class="cx">     m_curve = curve;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void WaveShaperProcessor::setOversample(OverSampleType oversample)
</del><ins>+void WaveShaperProcessor::setOversampleForBindings(OverSampleType oversample)
</ins><span class="cx"> {
</span><ins>+    ASSERT(isMainThread());
</ins><span class="cx">     // This synchronizes with process().
</span><span class="cx">     Locker locker { m_processLock };
</span><span class="cx"> 
</span><span class="cx">     m_oversample = oversample;
</span><span class="cx"> 
</span><del>-    if (oversample != OverSampleNone) {
-        for (auto& audioDSPKernel : m_kernels) {
-            WaveShaperDSPKernel& kernel = static_cast<WaveShaperDSPKernel&>(*audioDSPKernel);
-            kernel.lazyInitializeOversampling();
-        }
-    }
</del><ins>+    if (oversample == OverSampleNone)
+        return;
+
+    for (auto& audioDSPKernel : m_kernels)
+        static_cast<WaveShaperDSPKernel&>(*audioDSPKernel).lazyInitializeOversampling();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void WaveShaperProcessor::process(const AudioBus* source, AudioBus* destination, size_t framesToProcess)
</span><span class="lines">@@ -92,8 +93,8 @@
</span><span class="cx">     Locker locker { AdoptLock, m_processLock };
</span><span class="cx"> 
</span><span class="cx">     // For each channel of our input, process using the corresponding WaveShaperDSPKernel into the output channel.
</span><del>-    for (unsigned i = 0; i < m_kernels.size(); ++i)
-        m_kernels[i]->process(source->channel(i)->data(), destination->channel(i)->mutableData(), framesToProcess);
</del><ins>+    for (size_t i = 0; i < m_kernels.size(); ++i)
+        static_cast<WaveShaperDSPKernel&>(*m_kernels[i]).process(source->channel(i)->data(), destination->channel(i)->mutableData(), framesToProcess);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCoreModuleswebaudioWaveShaperProcessorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/webaudio/WaveShaperProcessor.h (278306 => 278307)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/webaudio/WaveShaperProcessor.h      2021-06-01 14:56:04 UTC (rev 278306)
+++ trunk/Source/WebCore/Modules/webaudio/WaveShaperProcessor.h 2021-06-01 15:09:47 UTC (rev 278307)
</span><span class="lines">@@ -48,21 +48,25 @@
</span><span class="cx"> 
</span><span class="cx">     virtual ~WaveShaperProcessor();
</span><span class="cx"> 
</span><del>-    std::unique_ptr<AudioDSPKernel> createKernel() override;
</del><ins>+    std::unique_ptr<AudioDSPKernel> createKernel() final;
</ins><span class="cx"> 
</span><del>-    void process(const AudioBus* source, AudioBus* destination, size_t framesToProcess) override;
</del><ins>+    void process(const AudioBus* source, AudioBus* destination, size_t framesToProcess) final;
</ins><span class="cx"> 
</span><del>-    void setCurve(Float32Array*);
-    Float32Array* curve() { return m_curve.get(); }
</del><ins>+    void setCurveForBindings(Float32Array*);
+    Float32Array* curveForBindings() WTF_IGNORES_THREAD_SAFETY_ANALYSIS { ASSERT(isMainThread()); return m_curve.get(); } // Doesn't grab the lock, only safe to call on the main thread.
+    Float32Array* curve() const WTF_REQUIRES_LOCK(m_processLock) { return m_curve.get(); }
</ins><span class="cx"> 
</span><del>-    void setOversample(OverSampleType);
-    OverSampleType oversample() const { return m_oversample; }
</del><ins>+    void setOversampleForBindings(OverSampleType);
+    OverSampleType oversampleForBindings() const WTF_IGNORES_THREAD_SAFETY_ANALYSIS { ASSERT(isMainThread()); return m_oversample; } // Doesn't grab the lock, only safe to call on the main thread.
+    OverSampleType oversample() const WTF_REQUIRES_LOCK(m_processLock) { return m_oversample; }
</ins><span class="cx"> 
</span><ins>+    Lock& processLock() const WTF_RETURNS_LOCK(m_processLock) { return m_processLock; }
+
</ins><span class="cx"> private:
</span><span class="cx">     // m_curve represents the non-linear shaping curve.
</span><del>-    RefPtr<Float32Array> m_curve;
</del><ins>+    RefPtr<Float32Array> m_curve WTF_GUARDED_BY_LOCK(m_processLock);
</ins><span class="cx"> 
</span><del>-    OverSampleType m_oversample { OverSampleNone };
</del><ins>+    OverSampleType m_oversample WTF_GUARDED_BY_LOCK(m_processLock) { OverSampleNone };
</ins><span class="cx"> 
</span><span class="cx">     // This synchronizes process() with setCurve().
</span><span class="cx">     mutable Lock m_processLock;
</span></span></pre>
</div>
</div>

</body>
</html>