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

#include "config.h"
#include "WorkletScriptController.h"

#if ENABLE(CSS_PAINTING_API)

#include "JSDOMBinding.h"
#include "JSEventTarget.h"
#include "JSExecState.h"
#include "JSPaintWorkletGlobalScope.h"
#include "ScriptSourceCode.h"
#include "WebCoreJSClientData.h"
#include "WorkletConsoleClient.h"

#include <JavaScriptCore/Completion.h>
#include <JavaScriptCore/Exception.h>
#include <JavaScriptCore/ExceptionHelpers.h>
#include <JavaScriptCore/GCActivityCallback.h>
#include <JavaScriptCore/JSLock.h>
#include <JavaScriptCore/PromiseTimer.h>
#include <JavaScriptCore/StrongInlines.h>

namespace WebCore {
using namespace JSC;

WorkletScriptController::WorkletScriptController(WorkletGlobalScope* workletGlobalScope)
    : m_vm(VM::create())
    , m_workletGlobalScope(workletGlobalScope)
    , m_workletGlobalScopeWrapper(*m_vm)
{
    m_vm->heap.acquireAccess(); // It's not clear that we have good discipline for heap access, so turn it on permanently.
    JSVMClientData::initNormalWorld(m_vm.get());
}

WorkletScriptController::~WorkletScriptController()
{
    JSLockHolder lock(vm());
    forbidExecution();

    if (m_workletGlobalScopeWrapper) {
        m_workletGlobalScopeWrapper->clearDOMGuardedObjects();
        m_workletGlobalScopeWrapper->setConsoleClient(nullptr);
        m_consoleClient = nullptr;
    }
    m_workletGlobalScopeWrapper.clear();
    m_vm = nullptr;
}

void WorkletScriptController::forbidExecution()
{
    ASSERT(m_workletGlobalScope->isContextThread());
    m_executionForbidden = true;
}

bool WorkletScriptController::isExecutionForbidden() const
{
    ASSERT(m_workletGlobalScope->isContextThread());
    return m_executionForbidden;
}

void WorkletScriptController::disableEval(const String& errorMessage)
{
    if (isExecutionForbidden())
        return;

    initScriptIfNeeded();
    JSLockHolder lock { vm() };

    m_workletGlobalScopeWrapper->setEvalEnabled(false, errorMessage);
}

void WorkletScriptController::disableWebAssembly(const String& errorMessage)
{
    if (isExecutionForbidden())
        return;

    initScriptIfNeeded();
    JSLockHolder lock { vm() };

    m_workletGlobalScopeWrapper->setWebAssemblyEnabled(false, errorMessage);
}


template<typename JSGlobalScopePrototype, typename JSGlobalScope, typename GlobalScope>
void WorkletScriptController::initScriptWithSubclass()
{
    ASSERT(!m_workletGlobalScopeWrapper);

    JSLockHolder lock { vm() };

    // Explicitly protect the global object's prototype so it isn't collected
    // when we allocate the global object. (Once the global object is fully
    // constructed, it can mark its own prototype.)
    Structure* contextPrototypeStructure = JSGlobalScopePrototype::createStructure(*m_vm, nullptr, jsNull());
    auto* contextPrototype = JSGlobalScopePrototype::create(*m_vm, nullptr, contextPrototypeStructure);
    Structure* structure = JSGlobalScope::createStructure(*m_vm, nullptr, contextPrototype);
    auto* proxyStructure = JSProxy::createStructure(*m_vm, nullptr, jsNull(), PureForwardingProxyType);
    auto* proxy = JSProxy::create(*m_vm, proxyStructure);

    m_workletGlobalScopeWrapper.set(*m_vm, JSGlobalScope::create(*m_vm, structure, static_cast<GlobalScope&>(*m_workletGlobalScope), proxy));
    contextPrototypeStructure->setGlobalObject(*m_vm, m_workletGlobalScopeWrapper.get());
    ASSERT(structure->globalObject() == m_workletGlobalScopeWrapper);
    ASSERT(m_workletGlobalScopeWrapper->structure(*m_vm)->globalObject() == m_workletGlobalScopeWrapper);
    contextPrototype->structure(*m_vm)->setGlobalObject(*m_vm, m_workletGlobalScopeWrapper.get());
    auto* globalScopePrototype = JSGlobalScope::prototype(*m_vm, *m_workletGlobalScopeWrapper.get());
    globalScopePrototype->didBecomePrototype();
    contextPrototype->structure(*m_vm)->setPrototypeWithoutTransition(*m_vm, globalScopePrototype);

    proxy->setTarget(*m_vm, m_workletGlobalScopeWrapper.get());
    proxy->structure(*m_vm)->setGlobalObject(*m_vm, m_workletGlobalScopeWrapper.get());

    ASSERT(m_workletGlobalScopeWrapper->globalObject() == m_workletGlobalScopeWrapper);
    ASSERT(asObject(m_workletGlobalScopeWrapper->getPrototypeDirect(*m_vm))->globalObject() == m_workletGlobalScopeWrapper);

    m_consoleClient = makeUnique<WorkletConsoleClient>(*m_workletGlobalScope);
    m_workletGlobalScopeWrapper->setConsoleClient(m_consoleClient.get());
}

void WorkletScriptController::initScript()
{
    if (isExecutionForbidden())
        return;

    if (is<PaintWorkletGlobalScope>(m_workletGlobalScope)) {
        initScriptWithSubclass<JSPaintWorkletGlobalScopePrototype, JSPaintWorkletGlobalScope, PaintWorkletGlobalScope>();
        return;
    }

    ASSERT_NOT_REACHED();
}

void WorkletScriptController::evaluate(const ScriptSourceCode& sourceCode, String* returnedExceptionMessage)
{
    if (isExecutionForbidden())
        return;

    NakedPtr<JSC::Exception> exception;
    evaluate(sourceCode, exception, returnedExceptionMessage);
    if (exception) {
        JSLockHolder lock(vm());
        reportException(m_workletGlobalScopeWrapper->globalObject(), exception);
    }
}

// Important: The caller of this function must verify that the returned exception message does not violate CORS if it is going to be passed back to JS.
void WorkletScriptController::evaluate(const ScriptSourceCode& sourceCode, NakedPtr<JSC::Exception>& returnedException, String* returnedExceptionMessage)
{
    if (isExecutionForbidden())
        return;

    initScriptIfNeeded();

    auto& globalObject = *m_workletGlobalScopeWrapper->globalObject();
    VM& vm = globalObject.vm();
    JSLockHolder lock { vm };

    JSExecState::profiledEvaluate(&globalObject, JSC::ProfilingReason::Other, sourceCode.jsSourceCode(), m_workletGlobalScopeWrapper->globalThis(), returnedException);

    if (returnedException && returnedExceptionMessage) {
        // This FIXME is from WorkerScriptController.
        // FIXME: It's not great that this can run arbitrary code to string-ify the value of the exception.
        // Do we need to do anything to handle that properly, if it, say, raises another exception?
        *returnedExceptionMessage = returnedException->value().toWTFString(&globalObject);
    }
}

void WorkletScriptController::setException(JSC::Exception* exception)
{
    auto* lexicalGlobalObject = m_workletGlobalScopeWrapper->globalObject();
    VM& vm = lexicalGlobalObject->vm();
    auto scope = DECLARE_THROW_SCOPE(vm);
    throwException(lexicalGlobalObject, scope, exception);
}

} // namespace WebCore
#endif
