/*
 * Copyright (C) 2008-2021 Apple Inc. All Rights Reserved.
 * Copyright (C) 2012 Google 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 "FetchOptions.h"
#include "WorkerThreadType.h"
#include <JavaScriptCore/Debugger.h>
#include <JavaScriptCore/JSRunLoopTimer.h>
#include <wtf/Forward.h>
#include <wtf/Lock.h>
#include <wtf/MessageQueue.h>
#include <wtf/NakedPtr.h>

namespace JSC {
class Exception;
class JSGlobalObject;
class VM;
}

namespace WebCore {

class Exception;
class JSDOMGlobalObject;
class ScriptSourceCode;
class WorkerConsoleClient;
class WorkerOrWorkletGlobalScope;
class WorkerScriptFetcher;

class WorkerOrWorkletScriptController {
    WTF_MAKE_NONCOPYABLE(WorkerOrWorkletScriptController);
    WTF_MAKE_FAST_ALLOCATED;
public:
    WorkerOrWorkletScriptController(WorkerThreadType, Ref<JSC::VM>&&, WorkerOrWorkletGlobalScope*);
    explicit WorkerOrWorkletScriptController(WorkerThreadType, WorkerOrWorkletGlobalScope*);
    ~WorkerOrWorkletScriptController();

    void releaseHeapAccess();
    void acquireHeapAccess();

    void addTimerSetNotification(JSC::JSRunLoopTimer::TimerNotificationCallback);
    void removeTimerSetNotification(JSC::JSRunLoopTimer::TimerNotificationCallback);

    JSDOMGlobalObject* globalScopeWrapper()
    {
        initScriptIfNeeded();
        return m_globalScopeWrapper.get();
    }

    void attachDebugger(JSC::Debugger*);
    void detachDebugger(JSC::Debugger*);

    // Async request to terminate a JS run execution. Eventually causes termination
    // exception raised during JS execution, if the worker thread happens to run JS.
    // After JS execution was terminated in this way, the Worker thread has to use
    // forbidExecution()/isExecutionForbidden() to guard against reentry into JS.
    // Can be called from any thread.
    void scheduleExecutionTermination();
    bool isTerminatingExecution() const;

    // Called on Worker thread when JS exits with termination exception caused by forbidExecution() request,
    // or by Worker thread termination code to prevent future entry into JS.
    void forbidExecution();
    bool isExecutionForbidden() const;

    JSC::VM& vm() { return *m_vm; }

    void setException(JSC::Exception*);

    void disableEval(const String& errorMessage);
    void disableWebAssembly(const String& errorMessage);

    void evaluate(const ScriptSourceCode&, String* returnedExceptionMessage = nullptr);
    void evaluate(const ScriptSourceCode&, NakedPtr<JSC::Exception>& returnedException, String* returnedExceptionMessage = nullptr);

    JSC::JSValue evaluateModule(JSC::JSModuleRecord&, JSC::JSValue awaitedValue, JSC::JSValue resumeMode);

    void linkAndEvaluateModule(WorkerScriptFetcher&, const ScriptSourceCode&, String* returnedExceptionMessage = nullptr);
    bool loadModuleSynchronously(WorkerScriptFetcher&, const ScriptSourceCode&);

    void loadAndEvaluateModule(const URL& moduleURL, FetchOptions::Credentials, CompletionHandler<void(std::optional<Exception>&&)>&&);

protected:
    WorkerOrWorkletGlobalScope* globalScope() const { return m_globalScope; }

    void initScriptIfNeeded()
    {
        if (!m_globalScopeWrapper)
            initScript();
    }
    WEBCORE_EXPORT void initScript();

private:
    template<typename JSGlobalScopePrototype, typename JSGlobalScope, typename GlobalScope>
    void initScriptWithSubclass();

    RefPtr<JSC::VM> m_vm;
    WorkerOrWorkletGlobalScope* m_globalScope;
    JSC::Strong<JSDOMGlobalObject> m_globalScopeWrapper;
    std::unique_ptr<WorkerConsoleClient> m_consoleClient;
    mutable Lock m_scheduledTerminationLock;
    bool m_isTerminatingExecution WTF_GUARDED_BY_LOCK(m_scheduledTerminationLock) { false };
};

} // namespace WebCore
