/*
 * Copyright (C) 2010 Google Inc. All rights reserved.
 * Copyright (C) 2016-2021 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1.  Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2.  Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"

#if ENABLE(WEB_AUDIO)

#include "AudioContext.h"

#include "AnalyserNode.h"
#include "AsyncAudioDecoder.h"
#include "AudioBuffer.h"
#include "AudioBufferCallback.h"
#include "AudioBufferOptions.h"
#include "AudioBufferSourceNode.h"
#include "AudioDestination.h"
#include "AudioListener.h"
#include "AudioNodeInput.h"
#include "AudioNodeOutput.h"
#include "AudioParamDescriptor.h"
#include "AudioSession.h"
#include "AudioWorklet.h"
#include "BiquadFilterNode.h"
#include "ChannelMergerNode.h"
#include "ChannelMergerOptions.h"
#include "ChannelSplitterNode.h"
#include "ChannelSplitterOptions.h"
#include "ConstantSourceNode.h"
#include "ConstantSourceOptions.h"
#include "ConvolverNode.h"
#include "DelayNode.h"
#include "DelayOptions.h"
#include "Document.h"
#include "DynamicsCompressorNode.h"
#include "EventNames.h"
#include "FFTFrame.h"
#include "Frame.h"
#include "FrameLoader.h"
#include "GainNode.h"
#include "HRTFDatabaseLoader.h"
#include "HRTFPanner.h"
#include "IIRFilterNode.h"
#include "IIRFilterOptions.h"
#include "JSAudioBuffer.h"
#include "JSDOMPromiseDeferred.h"
#include "Logging.h"
#include "NetworkingContext.h"
#include "OscillatorNode.h"
#include "Page.h"
#include "PannerNode.h"
#include "PeriodicWave.h"
#include "PeriodicWaveOptions.h"
#include "ScriptController.h"
#include "ScriptProcessorNode.h"
#include "StereoPannerNode.h"
#include "StereoPannerOptions.h"
#include "WaveShaperNode.h"
#include <JavaScriptCore/ArrayBuffer.h>
#include <JavaScriptCore/ScriptCallStack.h>
#include <wtf/Atomics.h>
#include <wtf/IsoMallocInlines.h>
#include <wtf/MainThread.h>
#include <wtf/Ref.h>
#include <wtf/Scope.h>
#include <wtf/text/WTFString.h>

#if DEBUG_AUDIONODE_REFERENCES
#include <stdio.h>
#endif

#if USE(GSTREAMER)
#include "GStreamerCommon.h"
#endif

namespace WebCore {

WTF_MAKE_ISO_ALLOCATED_IMPL(BaseAudioContext);

bool BaseAudioContext::isSupportedSampleRate(float sampleRate)
{
    return sampleRate >= 3000 && sampleRate <= 384000;
}

static uint64_t generateContextID()
{
    ASSERT(isMainThread());
    static uint64_t contextIDSeed = 0;
    return ++contextIDSeed;
}

static HashSet<uint64_t>& liveAudioContexts()
{
    ASSERT(isMainThread());
    static NeverDestroyed<HashSet<uint64_t>> contexts;
    return contexts;
}

BaseAudioContext::BaseAudioContext(Document& document)
    : ActiveDOMObject(document)
#if !RELEASE_LOG_DISABLED
    , m_logger(document.logger())
    , m_logIdentifier(uniqueLogIdentifier())
#endif
    , m_contextID(generateContextID())
    , m_worklet(AudioWorklet::create(*this))
    , m_listener(AudioListener::create(*this))
{
    liveAudioContexts().add(m_contextID);

    FFTFrame::initialize();
}

BaseAudioContext::~BaseAudioContext()
{
    liveAudioContexts().remove(m_contextID);
#if DEBUG_AUDIONODE_REFERENCES
    fprintf(stderr, "%p: BaseAudioContext::~AudioContext()\n", this);
#endif
    ASSERT(m_nodesToDelete.isEmpty());
    ASSERT(m_referencedSourceNodes.isEmpty());
    ASSERT(m_automaticPullNodes.isEmpty());
    if (m_automaticPullNodesNeedUpdating)
        m_renderingAutomaticPullNodes.resize(m_automaticPullNodes.size());
    ASSERT(m_renderingAutomaticPullNodes.isEmpty());
    // FIXME: Can we assert that m_deferredBreakConnectionList is empty?
}

bool BaseAudioContext::isContextAlive(uint64_t contextID)
{
    return liveAudioContexts().contains(contextID);
}

void BaseAudioContext::lazyInitialize()
{
    if (isStopped() || isClosed())
        return;

    if (m_isInitialized)
        return;

    // Don't allow the context to initialize a second time after it's already been explicitly uninitialized.
    ASSERT(!m_isAudioThreadFinished);
    if (m_isAudioThreadFinished)
        return;

    destination().initialize();

    m_isInitialized = true;
}

void BaseAudioContext::clear()
{
    Ref protectedThis { *this };

    // Audio thread is dead. Nobody will schedule node deletion action. Let's do it ourselves.
    do {
        deleteMarkedNodes();
        m_nodesToDelete = std::exchange(m_nodesMarkedForDeletion, { });
    } while (!m_nodesToDelete.isEmpty());
}

void BaseAudioContext::uninitialize()
{
    ALWAYS_LOG(LOGIDENTIFIER);
    
    ASSERT(isMainThread());

    if (!m_isInitialized)
        return;

    // This stops the audio thread and all audio rendering.
    destination().uninitialize();

    // Don't allow the context to initialize a second time after it's already been explicitly uninitialized.
    m_isAudioThreadFinished = true;

    finishTailProcessing();

    {
        Locker locker { graphLock() };
        // This should have been called from handlePostRenderTasks() at the end of rendering.
        // However, in case of lock contention, the tryLock() call could have failed in handlePostRenderTasks(),
        // leaving nodes in m_referencedSourceNodes. Now that the audio thread is gone, make sure we deref those nodes
        // before the BaseAudioContext gets destroyed.
        derefFinishedSourceNodes();
    }

    // Get rid of the sources which may still be playing.
    derefUnfinishedSourceNodes();

    m_isInitialized = false;
}

void BaseAudioContext::addReaction(State state, DOMPromiseDeferred<void>&& promise)
{
    size_t stateIndex = static_cast<size_t>(state);
    if (stateIndex >= m_stateReactions.size())
        m_stateReactions.grow(stateIndex + 1);

    m_stateReactions[stateIndex].append(WTFMove(promise));
}

void BaseAudioContext::setState(State state)
{
    if (m_state != state) {
        m_state = state;
        queueTaskToDispatchEvent(*this, TaskSource::MediaElement, Event::create(eventNames().statechangeEvent, Event::CanBubble::Yes, Event::IsCancelable::No));
    }

    size_t stateIndex = static_cast<size_t>(state);
    if (stateIndex >= m_stateReactions.size())
        return;

    Vector<DOMPromiseDeferred<void>> reactions;
    m_stateReactions[stateIndex].swap(reactions);

    for (auto& promise : reactions)
        promise.resolve();
}

void BaseAudioContext::stop()
{
    ASSERT(isMainThread());
    ALWAYS_LOG(LOGIDENTIFIER);
    
    // Usually ScriptExecutionContext calls stop twice.
    if (m_isStopScheduled)
        return;

    Ref protectedThis { *this };

    m_isStopScheduled = true;

    ASSERT(document());
    document()->updateIsPlayingMedia();

    uninitialize();
    clear();
}

Document* BaseAudioContext::document() const
{
    return downcast<Document>(scriptExecutionContext());
}

bool BaseAudioContext::wouldTaintOrigin(const URL& url) const
{
    if (url.protocolIsData())
        return false;

    if (auto* document = this->document())
        return !document->securityOrigin().canRequest(url);

    return false;
}

ExceptionOr<Ref<AudioBuffer>> BaseAudioContext::createBuffer(unsigned numberOfChannels, unsigned length, float sampleRate)
{
    return AudioBuffer::create(AudioBufferOptions {numberOfChannels, length, sampleRate});
}

void BaseAudioContext::decodeAudioData(Ref<ArrayBuffer>&& audioData, RefPtr<AudioBufferCallback>&& successCallback, RefPtr<AudioBufferCallback>&& errorCallback, std::optional<Ref<DeferredPromise>>&& promise)
{
    if (promise && (!document() || !document()->isFullyActive())) {
        promise.value()->reject(Exception { InvalidStateError, "Document is not fully active"_s });
        return;
    }

    if (!m_audioDecoder)
        m_audioDecoder = makeUnique<AsyncAudioDecoder>();

    m_audioDecoder->decodeAsync(WTFMove(audioData), sampleRate(), [this, activity = makePendingActivity(*this), successCallback = WTFMove(successCallback), errorCallback = WTFMove(errorCallback), promise = WTFMove(promise)](ExceptionOr<Ref<AudioBuffer>>&& result) mutable {
        queueTaskKeepingObjectAlive(*this, TaskSource::InternalAsyncTask, [successCallback = WTFMove(successCallback), errorCallback = WTFMove(errorCallback), promise = WTFMove(promise), result = WTFMove(result)]() mutable {
            if (result.hasException()) {
                if (promise)
                    promise.value()->reject(result.releaseException());
                if (errorCallback)
                    errorCallback->handleEvent(nullptr);
                return;
            }
            auto audioBuffer = result.releaseReturnValue();
            if (promise)
                promise.value()->resolve<IDLInterface<AudioBuffer>>(audioBuffer.get());
            if (successCallback)
                successCallback->handleEvent(audioBuffer.ptr());
        });
    });
}

ExceptionOr<Ref<AudioBufferSourceNode>> BaseAudioContext::createBufferSource()
{
    ALWAYS_LOG(LOGIDENTIFIER);

    ASSERT(isMainThread());
    return AudioBufferSourceNode::create(*this);
}

ExceptionOr<Ref<ScriptProcessorNode>> BaseAudioContext::createScriptProcessor(size_t bufferSize, size_t numberOfInputChannels, size_t numberOfOutputChannels)
{
    ALWAYS_LOG(LOGIDENTIFIER);
    
    ASSERT(isMainThread());

    // W3C Editor's Draft 06 June 2017
    //  https://webaudio.github.io/web-audio-api/#widl-BaseAudioContext-createScriptProcessor-ScriptProcessorNode-unsigned-long-bufferSize-unsigned-long-numberOfInputChannels-unsigned-long-numberOfOutputChannels

    // The bufferSize parameter determines the buffer size in units of sample-frames. If it's not passed in,
    // or if the value is 0, then the implementation will choose the best buffer size for the given environment,
    // which will be constant power of 2 throughout the lifetime of the node. ... If the value of this parameter
    // is not one of the allowed power-of-2 values listed above, an IndexSizeError must be thrown.
    switch (bufferSize) {
    case 0:
#if USE(AUDIO_SESSION)
        // Pick a value between 256 (2^8) and 16384 (2^14), based on the buffer size of the current AudioSession:
        bufferSize = 1 << std::max<size_t>(8, std::min<size_t>(14, std::log2(AudioSession::sharedSession().bufferSize())));
#else
        bufferSize = 2048;
#endif
        break;
    case 256:
    case 512:
    case 1024:
    case 2048:
    case 4096:
    case 8192:
    case 16384:
        break;
    default:
        return Exception { IndexSizeError, "Unsupported buffer size for ScriptProcessorNode"_s };
    }

    // An IndexSizeError exception must be thrown if bufferSize or numberOfInputChannels or numberOfOutputChannels
    // are outside the valid range. It is invalid for both numberOfInputChannels and numberOfOutputChannels to be zero.
    // In this case an IndexSizeError must be thrown.

    if (!numberOfInputChannels && !numberOfOutputChannels)
        return Exception { IndexSizeError, "numberOfInputChannels and numberOfOutputChannels cannot both be 0"_s };

    // This parameter [numberOfInputChannels] determines the number of channels for this node's input. Values of
    // up to 32 must be supported. A NotSupportedError must be thrown if the number of channels is not supported.

    if (numberOfInputChannels > maxNumberOfChannels)
        return Exception { IndexSizeError, "numberOfInputChannels exceeds maximum number of channels"_s };

    // This parameter [numberOfOutputChannels] determines the number of channels for this node's output. Values of
    // up to 32 must be supported. A NotSupportedError must be thrown if the number of channels is not supported.

    if (numberOfOutputChannels > maxNumberOfChannels)
        return Exception { IndexSizeError, "numberOfOutputChannels exceeds maximum number of channels"_s };

    return ScriptProcessorNode::create(*this, bufferSize, numberOfInputChannels, numberOfOutputChannels);
}

ExceptionOr<Ref<BiquadFilterNode>> BaseAudioContext::createBiquadFilter()
{
    ALWAYS_LOG(LOGIDENTIFIER);
    
    ASSERT(isMainThread());
    return BiquadFilterNode::create(*this);
}

ExceptionOr<Ref<WaveShaperNode>> BaseAudioContext::createWaveShaper()
{
    ALWAYS_LOG(LOGIDENTIFIER);
    
    ASSERT(isMainThread());
    return WaveShaperNode::create(*this);
}

ExceptionOr<Ref<PannerNode>> BaseAudioContext::createPanner()
{
    ALWAYS_LOG(LOGIDENTIFIER);
    
    ASSERT(isMainThread());
    return PannerNode::create(*this);
}

ExceptionOr<Ref<ConvolverNode>> BaseAudioContext::createConvolver()
{
    ALWAYS_LOG(LOGIDENTIFIER);
    
    ASSERT(isMainThread());
    return ConvolverNode::create(*this);
}

ExceptionOr<Ref<DynamicsCompressorNode>> BaseAudioContext::createDynamicsCompressor()
{
    ALWAYS_LOG(LOGIDENTIFIER);
    
    ASSERT(isMainThread());
    return DynamicsCompressorNode::create(*this);
}

ExceptionOr<Ref<AnalyserNode>> BaseAudioContext::createAnalyser()
{
    ALWAYS_LOG(LOGIDENTIFIER);
    
    ASSERT(isMainThread());
    return AnalyserNode::create(*this);
}

ExceptionOr<Ref<GainNode>> BaseAudioContext::createGain()
{
    ALWAYS_LOG(LOGIDENTIFIER);
    
    ASSERT(isMainThread());
    return GainNode::create(*this);
}

ExceptionOr<Ref<DelayNode>> BaseAudioContext::createDelay(double maxDelayTime)
{
    ALWAYS_LOG(LOGIDENTIFIER);
    
    ASSERT(isMainThread());
    DelayOptions options;
    options.maxDelayTime = maxDelayTime;
    return DelayNode::create(*this, options);
}

ExceptionOr<Ref<ChannelSplitterNode>> BaseAudioContext::createChannelSplitter(size_t numberOfOutputs)
{
    ALWAYS_LOG(LOGIDENTIFIER);
    
    ASSERT(isMainThread());

    ChannelSplitterOptions options;
    options.numberOfOutputs = numberOfOutputs;
    return ChannelSplitterNode::create(*this, options);
}

ExceptionOr<Ref<ChannelMergerNode>> BaseAudioContext::createChannelMerger(size_t numberOfInputs)
{
    ALWAYS_LOG(LOGIDENTIFIER);
    
    ASSERT(isMainThread());

    ChannelMergerOptions options;
    options.numberOfInputs = numberOfInputs;
    return ChannelMergerNode::create(*this, options);
}

ExceptionOr<Ref<OscillatorNode>> BaseAudioContext::createOscillator()
{
    ALWAYS_LOG(LOGIDENTIFIER);
    
    ASSERT(isMainThread());
    return OscillatorNode::create(*this);
}

ExceptionOr<Ref<PeriodicWave>> BaseAudioContext::createPeriodicWave(Vector<float>&& real, Vector<float>&& imaginary, const PeriodicWaveConstraints& constraints)
{
    ALWAYS_LOG(LOGIDENTIFIER);
    
    ASSERT(isMainThread());
    
    PeriodicWaveOptions options;
    options.real = WTFMove(real);
    options.imag = WTFMove(imaginary);
    options.disableNormalization = constraints.disableNormalization;
    return PeriodicWave::create(*this, WTFMove(options));
}

ExceptionOr<Ref<ConstantSourceNode>> BaseAudioContext::createConstantSource()
{
    ALWAYS_LOG(LOGIDENTIFIER);
    
    ASSERT(isMainThread());
    return ConstantSourceNode::create(*this);
}

ExceptionOr<Ref<StereoPannerNode>> BaseAudioContext::createStereoPanner()
{
    ALWAYS_LOG(LOGIDENTIFIER);
    
    ASSERT(isMainThread());
    return StereoPannerNode::create(*this);
}

ExceptionOr<Ref<IIRFilterNode>> BaseAudioContext::createIIRFilter(ScriptExecutionContext& scriptExecutionContext, Vector<double>&& feedforward, Vector<double>&& feedback)
{
    ALWAYS_LOG(LOGIDENTIFIER);

    ASSERT(isMainThread());
    IIRFilterOptions options;
    options.feedforward = WTFMove(feedforward);
    options.feedback = WTFMove(feedback);
    return IIRFilterNode::create(scriptExecutionContext, *this, WTFMove(options));
}

void BaseAudioContext::derefFinishedSourceNodes()
{
    ASSERT(isGraphOwner());
    ASSERT(isAudioThread() || isAudioThreadFinished());

    if (!m_hasFinishedAudioSourceNodes)
        return;

    m_referencedSourceNodes.removeAllMatching([](auto& node) { return node->isFinishedSourceNode(); });
    m_hasFinishedAudioSourceNodes = false;
}

void BaseAudioContext::derefUnfinishedSourceNodes()
{
    ASSERT(isMainThread() && isAudioThreadFinished());
    m_referencedSourceNodes.clear();
}

void BaseAudioContext::addDeferredDecrementConnectionCount(AudioNode* node)
{
    ASSERT(isAudioThread());
    // Heap allocations are forbidden on the audio thread for performance reasons so we need to
    // explicitly allow the following allocation(s).
    DisableMallocRestrictionsForCurrentThreadScope disableMallocRestrictions;
    m_deferredBreakConnectionList.append(node);
}

void BaseAudioContext::handlePreRenderTasks(const AudioIOPosition& outputPosition)
{
    ASSERT(isAudioThread());

    // At the beginning of every render quantum, try to update the internal rendering graph state (from main thread changes).
    // It's OK if the tryLock() fails, we'll just take slightly longer to pick up the changes.
    if (auto locker = Locker<RecursiveLock>::tryLock(graphLock())) {
        // Fixup the state of any dirty AudioSummingJunctions and AudioNodeOutputs.
        handleDirtyAudioSummingJunctions();
        handleDirtyAudioNodeOutputs();

        updateAutomaticPullNodes();
        m_outputPosition = outputPosition;

        m_listener->updateDirtyState();
    }
}

AudioIOPosition BaseAudioContext::outputPosition()
{
    ASSERT(isMainThread());
    Locker locker { graphLock() };
    return m_outputPosition;
}

void BaseAudioContext::handlePostRenderTasks()
{
    ASSERT(isAudioThread());

    // Must use a tryLock() here too. Don't worry, the lock will very rarely be contended and this method is called frequently.
    // The worst that can happen is that there will be some nodes which will take slightly longer than usual to be deleted or removed
    // from the render graph (in which case they'll render silence).
    auto locker = Locker<RecursiveLock>::tryLock(graphLock());
    if (!locker)
        return;

    // Take care of finishing any derefs where the tryLock() failed previously.
    handleDeferredDecrementConnectionCounts();

    // Dynamically clean up nodes which are no longer needed.
    derefFinishedSourceNodes();

    // Don't delete in the real-time thread. Let the main thread do it.
    // Ref-counted objects held by certain AudioNodes may not be thread-safe.
    scheduleNodeDeletion();

    // Fixup the state of any dirty AudioSummingJunctions and AudioNodeOutputs.
    handleDirtyAudioSummingJunctions();
    handleDirtyAudioNodeOutputs();

    updateAutomaticPullNodes();
    updateTailProcessingNodes();
}

void BaseAudioContext::handleDeferredDecrementConnectionCounts()
{
    ASSERT(isAudioThread() && isGraphOwner());
    for (auto& node : m_deferredBreakConnectionList)
        node->decrementConnectionCountWithLock();
    
    m_deferredBreakConnectionList.clear();
}

void BaseAudioContext::addTailProcessingNode(AudioNode& node)
{
    ASSERT(isGraphOwner());
    if (node.isTailProcessing()) {
        ASSERT(m_tailProcessingNodes.contains(node) || m_finishedTailProcessingNodes.contains(node));
        return;
    }

    // Ideally we'd find a way to avoid this vector append since we try to avoid potential heap allocations
    // on the audio thread for performance reasons.
    DisableMallocRestrictionsForCurrentThreadScope disableMallocRestrictions;
    ASSERT(!m_tailProcessingNodes.contains(node));
    m_tailProcessingNodes.append(node);
}

void BaseAudioContext::removeTailProcessingNode(AudioNode& node)
{
    ASSERT(isGraphOwner());
    ASSERT(node.isTailProcessing());

    if (m_tailProcessingNodes.removeFirst(node))
        return;

    // Remove the node from finished tail processing nodes so we don't end up disabling its outputs later on the main thread.
    ASSERT(m_finishedTailProcessingNodes.contains(node));
    m_finishedTailProcessingNodes.removeFirst(node);
}

void BaseAudioContext::updateTailProcessingNodes()
{
    ASSERT(isAudioThread());
    ASSERT(isGraphOwner());
    // Go backwards as the current node may be removed from m_tailProcessingNodes as we iterate.
    // We are on the audio thread so we want to avoid allocations as much as possible.
    for (auto i = m_tailProcessingNodes.size(); i > 0; --i) {
        auto& node = m_tailProcessingNodes[i - 1];
        if (!node->propagatesSilence())
            continue; // Node is not done processing its tail.

        // Ideally we'd find a way to avoid this vector append since we try to avoid potential heap allocations
        // on the audio thread for performance reasons.
        DisableMallocRestrictionsForCurrentThreadScope disableMallocRestrictions;

        // Disabling of outputs should happen on the main thread we add the node to m_finishedTailProcessingNodes
        // for disableOutputsForFinishedTailProcessingNodes() to process later on the main thread.
        ASSERT(!m_finishedTailProcessingNodes.contains(node));
        m_finishedTailProcessingNodes.append(WTFMove(node));
        m_tailProcessingNodes.remove(i - 1);
    }

    if (m_finishedTailProcessingNodes.isEmpty() || m_disableOutputsForTailProcessingScheduled)
        return;

    m_disableOutputsForTailProcessingScheduled = true;

    // We try to avoid heap allocations on the audio thread but there is no way to do a main thread dispatch
    // without one.
    DisableMallocRestrictionsForCurrentThreadScope disableMallocRestrictions;
    callOnMainThread([this, protectedThis = Ref { *this }]() mutable {
        Locker locker { graphLock() };
        disableOutputsForFinishedTailProcessingNodes();
        m_disableOutputsForTailProcessingScheduled = false;
    });
}

void BaseAudioContext::disableOutputsForFinishedTailProcessingNodes()
{
    ASSERT(isMainThread());
    ASSERT(isGraphOwner());
    for (auto& finishedTailProcessingNode : std::exchange(m_finishedTailProcessingNodes, { }))
        finishedTailProcessingNode->disableOutputs();
}

void BaseAudioContext::finishTailProcessing()
{
    ASSERT(isMainThread());
    Locker locker { graphLock() };

    // disableOutputs() can cause new nodes to start tail processing so we need to loop until both vectors are empty.
    while (!m_tailProcessingNodes.isEmpty() || !m_finishedTailProcessingNodes.isEmpty()) {
        for (auto& tailProcessingNode : std::exchange(m_tailProcessingNodes, { }))
            tailProcessingNode->disableOutputs();
        disableOutputsForFinishedTailProcessingNodes();
    }
}

void BaseAudioContext::markForDeletion(AudioNode& node)
{
    ASSERT(isGraphOwner());
    ASSERT_WITH_MESSAGE(node.nodeType() != AudioNode::NodeTypeDestination, "Destination node is owned by the BaseAudioContext");

    if (isAudioThreadFinished())
        m_nodesToDelete.append(&node);
    else {
        // Heap allocations are forbidden on the audio thread for performance reasons so we need to
        // explicitly allow the following allocation(s).
        DisableMallocRestrictionsForCurrentThreadScope disableMallocRestrictions;
        m_nodesMarkedForDeletion.append(&node);
    }

    // This is probably the best time for us to remove the node from automatic pull list,
    // since all connections are gone and we hold the graph lock. Then when handlePostRenderTasks()
    // gets a chance to schedule the deletion work, updateAutomaticPullNodes() also gets a chance to
    // modify m_renderingAutomaticPullNodes.
    removeAutomaticPullNode(node);
}

void BaseAudioContext::scheduleNodeDeletion()
{
    bool isGood = m_isInitialized && isGraphOwner();
    ASSERT(isGood);
    if (!isGood)
        return;

    // Make sure to call deleteMarkedNodes() on main thread.    
    if (!m_nodesMarkedForDeletion.isEmpty() && !m_isDeletionScheduled) {
        ASSERT(m_nodesToDelete.isEmpty());
        m_nodesToDelete = std::exchange(m_nodesMarkedForDeletion, { });

        m_isDeletionScheduled = true;

        // Heap allocations are forbidden on the audio thread for performance reasons so we need to
        // explicitly allow the following allocation(s).
        DisableMallocRestrictionsForCurrentThreadScope disableMallocRestrictions;
        callOnMainThread([protectedThis = Ref { *this }]() mutable {
            protectedThis->deleteMarkedNodes();
        });
    }
}

void BaseAudioContext::deleteMarkedNodes()
{
    ASSERT(isMainThread());

    // Protect this object from being deleted before we release the lock.
    Ref protectedThis { *this };

    Locker locker { graphLock() };

    while (m_nodesToDelete.size()) {
        AudioNode* node = m_nodesToDelete.takeLast();

        // Before deleting the node, clear out any AudioNodeInputs from m_dirtySummingJunctions.
        unsigned numberOfInputs = node->numberOfInputs();
        for (unsigned i = 0; i < numberOfInputs; ++i)
            m_dirtySummingJunctions.remove(node->input(i));

        // Before deleting the node, clear out any AudioNodeOutputs from m_dirtyAudioNodeOutputs.
        unsigned numberOfOutputs = node->numberOfOutputs();
        for (unsigned i = 0; i < numberOfOutputs; ++i)
            m_dirtyAudioNodeOutputs.remove(node->output(i));

        ASSERT_WITH_MESSAGE(node->nodeType() != AudioNode::NodeTypeDestination, "Destination node is owned by the BaseAudioContext");

        // Finally, delete it.
        delete node;
    }
    m_isDeletionScheduled = false;
}

void BaseAudioContext::markSummingJunctionDirty(AudioSummingJunction* summingJunction)
{
    ASSERT(isGraphOwner());
    // Heap allocations are forbidden on the audio thread for performance reasons so we need to
    // explicitly allow the following allocation(s).
    DisableMallocRestrictionsForCurrentThreadScope disableMallocRestrictions;
    m_dirtySummingJunctions.add(summingJunction);
}

void BaseAudioContext::removeMarkedSummingJunction(AudioSummingJunction* summingJunction)
{
    ASSERT(isMainThread());
    Locker locker { graphLock() };
    m_dirtySummingJunctions.remove(summingJunction);
}

EventTargetInterface BaseAudioContext::eventTargetInterface() const
{
    return BaseAudioContextEventTargetInterfaceType;
}

void BaseAudioContext::markAudioNodeOutputDirty(AudioNodeOutput* output)
{
    ASSERT(isGraphOwner());
    m_dirtyAudioNodeOutputs.add(output);
}

void BaseAudioContext::handleDirtyAudioSummingJunctions()
{
    ASSERT(isGraphOwner());

    for (auto& junction : m_dirtySummingJunctions)
        junction->updateRenderingState();

    m_dirtySummingJunctions.clear();
}

void BaseAudioContext::handleDirtyAudioNodeOutputs()
{
    ASSERT(isGraphOwner());

    for (auto& output : m_dirtyAudioNodeOutputs)
        output->updateRenderingState();

    m_dirtyAudioNodeOutputs.clear();
}

void BaseAudioContext::addAutomaticPullNode(AudioNode& node)
{
    ASSERT(isGraphOwner());

    // Heap allocations are forbidden on the audio thread for performance reasons so we need to
    // explicitly allow the following allocation(s).
    DisableMallocRestrictionsForCurrentThreadScope disableMallocRestrictions;
    if (m_automaticPullNodes.add(&node).isNewEntry)
        m_automaticPullNodesNeedUpdating = true;
}

void BaseAudioContext::removeAutomaticPullNode(AudioNode& node)
{
    ASSERT(isGraphOwner());

    if (m_automaticPullNodes.remove(&node))
        m_automaticPullNodesNeedUpdating = true;
}

void BaseAudioContext::updateAutomaticPullNodes()
{
    ASSERT(isGraphOwner());

    if (!m_automaticPullNodesNeedUpdating)
        return;

    // Heap allocations are forbidden on the audio thread for performance reasons so we need to
    // explicitly allow the following allocation(s).
    DisableMallocRestrictionsForCurrentThreadScope disableMallocRestrictions;

    // Copy from m_automaticPullNodes to m_renderingAutomaticPullNodes.
    m_renderingAutomaticPullNodes.resize(m_automaticPullNodes.size());

    unsigned i = 0;
    for (auto& output : m_automaticPullNodes)
        m_renderingAutomaticPullNodes[i++] = output;

    m_automaticPullNodesNeedUpdating = false;
}

void BaseAudioContext::processAutomaticPullNodes(size_t framesToProcess)
{
    ASSERT(isAudioThread());

    for (auto& node : m_renderingAutomaticPullNodes)
        node->processIfNecessary(framesToProcess);
}

ScriptExecutionContext* BaseAudioContext::scriptExecutionContext() const
{
    return ActiveDOMObject::scriptExecutionContext();
}

void BaseAudioContext::postTask(Function<void()>&& task)
{
    ASSERT(isMainThread());
    if (!m_isStopScheduled)
        queueTaskKeepingObjectAlive(*this, TaskSource::MediaElement, WTFMove(task));
}

const SecurityOrigin* BaseAudioContext::origin() const
{
    auto* context = scriptExecutionContext();
    return context ? context->securityOrigin() : nullptr;
}

void BaseAudioContext::addConsoleMessage(MessageSource source, MessageLevel level, const String& message)
{
    if (auto* context = scriptExecutionContext())
        context->addConsoleMessage(source, level, message);
}

PeriodicWave& BaseAudioContext::periodicWave(OscillatorType type)
{
    switch (type) {
    case OscillatorType::Square:
        if (!m_cachedPeriodicWaveSquare)
            m_cachedPeriodicWaveSquare = PeriodicWave::createSquare(sampleRate());
        return *m_cachedPeriodicWaveSquare;
    case OscillatorType::Sawtooth:
        if (!m_cachedPeriodicWaveSawtooth)
            m_cachedPeriodicWaveSawtooth = PeriodicWave::createSawtooth(sampleRate());
        return *m_cachedPeriodicWaveSawtooth;
    case OscillatorType::Triangle:
        if (!m_cachedPeriodicWaveTriangle)
            m_cachedPeriodicWaveTriangle = PeriodicWave::createTriangle(sampleRate());
        return *m_cachedPeriodicWaveTriangle;
    case OscillatorType::Custom:
        RELEASE_ASSERT_NOT_REACHED();
    case OscillatorType::Sine:
        if (!m_cachedPeriodicWaveSine)
            m_cachedPeriodicWaveSine = PeriodicWave::createSine(sampleRate());
        return *m_cachedPeriodicWaveSine;
    }
    RELEASE_ASSERT_NOT_REACHED();
}

void BaseAudioContext::addAudioParamDescriptors(const String& processorName, Vector<AudioParamDescriptor>&& descriptors)
{
    ASSERT(!m_parameterDescriptorMap.contains(processorName));
    bool wasEmpty = m_parameterDescriptorMap.isEmpty();
    m_parameterDescriptorMap.add(processorName, WTFMove(descriptors));
    if (wasEmpty)
        workletIsReady();
}

void BaseAudioContext::sourceNodeWillBeginPlayback(AudioNode& node)
{
    ASSERT(isMainThread());
    Locker locker { graphLock() };

    ASSERT(!m_referencedSourceNodes.contains(&node));
    // Reference source node to keep it alive and playing even if its JS wrapper gets garbage collected.
    m_referencedSourceNodes.append(&node);
}

void BaseAudioContext::sourceNodeDidFinishPlayback(AudioNode& node)
{
    ASSERT(isAudioThread());

    node.setIsFinishedSourceNode();
    m_hasFinishedAudioSourceNodes = true;
}

void BaseAudioContext::workletIsReady()
{
    ASSERT(isMainThread());

    // If we're already rendering when the worklet becomes ready, we need to restart
    // rendering in order to switch to the audio worklet thread.
    destination().restartRendering();
}

#if !RELEASE_LOG_DISABLED
WTFLogChannel& BaseAudioContext::logChannel() const
{
    return LogMedia;
}
#endif

} // namespace WebCore

#endif // ENABLE(WEB_AUDIO)
