// /*
//  * Copyright (C) 2008 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. ``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
//  * 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.
//  *
//  */

// #pragma once

// #include "ContextDestructionObserver.h"
// #include "TaskSource.h"
// #include <wtf/Assertions.h>
// #include <wtf/CancellableTask.h>
// #include <wtf/Forward.h>
// #include <wtf/Function.h>
// #include <wtf/RefCounted.h>
// #include <wtf/Threading.h>

// namespace WebCore {

// class Document;
// class Event;
// class EventLoopTaskGroup;
// class EventTarget;

// enum class ReasonForSuspension {
//     JavaScriptDebuggerPaused,
//     WillDeferLoading,
//     BackForwardCache,
//     PageWillBeSuspended,
// };

// class WEBCORE_EXPORT ActiveDOMObject : public ContextDestructionObserver {
// public:
//     // The suspendIfNeeded must be called exactly once after object construction to update
//     // the suspended state to match that of the ScriptExecutionContext.
//     void suspendIfNeeded();
//     void assertSuspendIfNeededWasCalled() const;

//     // This function is used by JS bindings to determine if the JS wrapper should be kept alive or not.
//     bool hasPendingActivity() const { return m_pendingActivityInstanceCount || virtualHasPendingActivity(); }

//     // However, the suspend function will sometimes be called even if canSuspendForDocumentSuspension() returns false.
//     // That happens in step-by-step JS debugging for example - in this case it would be incorrect
//     // to stop the object. Exact semantics of suspend is up to the object in cases like that.

//     virtual const char* activeDOMObjectName() const = 0;

//     // These functions must not have a side effect of creating or destroying
//     // any ActiveDOMObject. That means they must not result in calls to arbitrary JavaScript.
//     virtual void suspend(ReasonForSuspension);
//     virtual void resume();

//     // This function must not have a side effect of creating an ActiveDOMObject.
//     // That means it must not result in calls to arbitrary JavaScript.
//     // It can, however, have a side effect of deleting an ActiveDOMObject.
//     virtual void stop();

//     template<class T>
//     class PendingActivity : public RefCounted<PendingActivity<T>> {
//     public:
//         explicit PendingActivity(T& thisObject)
//             : m_thisObject(thisObject)
//         {
//             ++(m_thisObject->m_pendingActivityInstanceCount);
//         }

//         ~PendingActivity()
//         {
//             ASSERT(m_thisObject->m_pendingActivityInstanceCount > 0);
//             --(m_thisObject->m_pendingActivityInstanceCount);
//         }

//     private:
//         Ref<T> m_thisObject;
//     };

//     template<class T> Ref<PendingActivity<T>> makePendingActivity(T& thisObject)
//     {
//         ASSERT(&thisObject == this);
//         return adoptRef(*new PendingActivity<T>(thisObject));
//     }

// bool isContextStopped() const;
//     bool isAllowedToRunScript() const;

//     template<typename T>
//     static void queueTaskKeepingObjectAlive(T& object, TaskSource source, Function<void ()>&& task)
//     {
//         object.queueTaskInEventLoop(source, [protectedObject = Ref { object }, activity = object.ActiveDOMObject::makePendingActivity(object), task = WTFMove(task)] () {
//             task();
//         });
//     }

//     template<typename T>
//     static void queueCancellableTaskKeepingObjectAlive(T& object, TaskSource source, TaskCancellationGroup& cancellationGroup, Function<void()>&& task)
//     {
//         CancellableTask cancellableTask(cancellationGroup, WTFMove(task));
//         object.queueTaskInEventLoop(source, [protectedObject = Ref { object }, activity = object.ActiveDOMObject::makePendingActivity(object), cancellableTask = WTFMove(cancellableTask)]() mutable {
//             cancellableTask();
//         });
//     }

//     template<typename EventTargetType>
//     static void queueTaskToDispatchEvent(EventTargetType& target, TaskSource source, Ref<Event>&& event)
//     {
//         target.queueTaskToDispatchEventInternal(target, source, WTFMove(event));
//     }

//     template<typename EventTargetType>
//     static void queueCancellableTaskToDispatchEvent(EventTargetType& target, TaskSource source, TaskCancellationGroup& cancellationGroup, Ref<Event>&& event)
//     {
//         target.queueCancellableTaskToDispatchEventInternal(target, source, cancellationGroup, WTFMove(event));
//     }

// protected:
//     explicit ActiveDOMObject(ScriptExecutionContext*);
//     explicit ActiveDOMObject(Document*);
//     explicit ActiveDOMObject(Document&);
//     virtual ~ActiveDOMObject();

// private:
//     enum CheckedScriptExecutionContextType { CheckedScriptExecutionContext };
//     ActiveDOMObject(ScriptExecutionContext*, CheckedScriptExecutionContextType);

//     // This is used by subclasses to indicate that they have pending activity, meaning that they would
//     // like the JS wrapper to stay alive (because they may still fire JS events).
//     virtual bool virtualHasPendingActivity() const { return false; }

//     void queueTaskInEventLoop(TaskSource, Function<void ()>&&);
//     void queueTaskToDispatchEventInternal(EventTarget&, TaskSource, Ref<Event>&&);
//     void queueCancellableTaskToDispatchEventInternal(EventTarget&, TaskSource, TaskCancellationGroup&, Ref<Event>&&);

//     uint64_t m_pendingActivityInstanceCount { 0 };
// #if ASSERT_ENABLED
//     bool m_suspendIfNeededWasCalled { false };
//     Ref<Thread> m_creationThread { Thread::current() };
// #endif

//     friend class ActiveDOMObjectEventDispatchTask;
// };

// #if !ASSERT_ENABLED

// inline void ActiveDOMObject::assertSuspendIfNeededWasCalled() const
// {
// }

// #endif

// } // namespace WebCore
