/*
 * Copyright (C) 2008-2019 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 "DebuggerScope.h"

#include "JSLexicalEnvironment.h"
#include "JSCInlines.h"

namespace JSC {

STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(DebuggerScope);

const ClassInfo DebuggerScope::s_info = { "DebuggerScope", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(DebuggerScope) };

DebuggerScope* DebuggerScope::create(VM& vm, JSScope* scope)
{
    Structure* structure = scope->globalObject(vm)->debuggerScopeStructure();
    DebuggerScope* debuggerScope = new (NotNull, allocateCell<DebuggerScope>(vm.heap)) DebuggerScope(vm, structure, scope);
    debuggerScope->finishCreation(vm);
    return debuggerScope;
}

DebuggerScope::DebuggerScope(VM& vm, Structure* structure, JSScope* scope)
    : JSNonFinalObject(vm, structure)
{
    ASSERT(scope);
    m_scope.set(vm, this, scope);
}

void DebuggerScope::finishCreation(VM& vm)
{
    Base::finishCreation(vm);
}

void DebuggerScope::visitChildren(JSCell* cell, SlotVisitor& visitor)
{
    DebuggerScope* thisObject = jsCast<DebuggerScope*>(cell);
    ASSERT_GC_OBJECT_INHERITS(thisObject, info());
    Base::visitChildren(cell, visitor);

    visitor.append(thisObject->m_scope);
    visitor.append(thisObject->m_next);
}

String DebuggerScope::className(const JSObject* object, VM& vm)
{
    const DebuggerScope* scope = jsCast<const DebuggerScope*>(object);
    // We cannot assert that scope->isValid() because the TypeProfiler may encounter an invalidated
    // DebuggerScope in its log entries. We just need to handle it appropriately as below.
    if (!scope->isValid())
        return String();
    JSObject* thisObject = JSScope::objectAtScope(scope->jsScope());
    return thisObject->methodTable(vm)->className(thisObject, vm);
}

String DebuggerScope::toStringName(const JSObject* object, JSGlobalObject* globalObject)
{
    const DebuggerScope* scope = jsCast<const DebuggerScope*>(object);
    // We cannot assert that scope->isValid() because the TypeProfiler may encounter an invalidated
    // DebuggerScope in its log entries. We just need to handle it appropriately as below.
    if (!scope->isValid())
        return String();
    JSObject* thisObject = JSScope::objectAtScope(scope->jsScope());
    return thisObject->methodTable(globalObject->vm())->toStringName(thisObject, globalObject);
}

bool DebuggerScope::getOwnPropertySlot(JSObject* object, JSGlobalObject* globalObject, PropertyName propertyName, PropertySlot& slot)
{
    DebuggerScope* scope = jsCast<DebuggerScope*>(object);
    if (!scope->isValid())
        return false;
    JSObject* thisObject = JSScope::objectAtScope(scope->jsScope());
    slot.setThisValue(JSValue(thisObject));

    // By default, JSObject::getPropertySlot() will look in the DebuggerScope's prototype
    // chain and not the wrapped scope, and JSObject::getPropertySlot() cannot be overridden
    // to behave differently for the DebuggerScope.
    //
    // Instead, we'll treat all properties in the wrapped scope and its prototype chain as
    // the own properties of the DebuggerScope. This is fine because the WebInspector
    // does not presently need to distinguish between what's owned at each level in the
    // prototype chain. Hence, we'll invoke getPropertySlot() on the wrapped scope here
    // instead of getOwnPropertySlot().
    bool result = thisObject->getPropertySlot(globalObject, propertyName, slot);
    if (result && slot.isValue() && slot.getValue(globalObject, propertyName) == jsTDZValue()) {
        // FIXME:
        // We hit a scope property that has the TDZ empty value.
        // Currently, we just lie to the inspector and claim that this property is undefined.
        // This is not ideal and we should fix it.
        // https://bugs.webkit.org/show_bug.cgi?id=144977
        slot.setValue(slot.slotBase(), static_cast<unsigned>(PropertyAttribute::DontEnum), jsUndefined());
        return true;
    }
    return result;
}

bool DebuggerScope::put(JSCell* cell, JSGlobalObject* globalObject, PropertyName propertyName, JSValue value, PutPropertySlot& slot)
{
    DebuggerScope* scope = jsCast<DebuggerScope*>(cell);
    ASSERT(scope->isValid());
    if (!scope->isValid())
        return false;
    JSObject* thisObject = JSScope::objectAtScope(scope->jsScope());
    slot.setThisValue(JSValue(thisObject));
    return thisObject->methodTable(globalObject->vm())->put(thisObject, globalObject, propertyName, value, slot);
}

bool DebuggerScope::deleteProperty(JSCell* cell, JSGlobalObject* globalObject, PropertyName propertyName, DeletePropertySlot& slot)
{
    DebuggerScope* scope = jsCast<DebuggerScope*>(cell);
    ASSERT(scope->isValid());
    if (!scope->isValid())
        return false;
    JSObject* thisObject = JSScope::objectAtScope(scope->jsScope());
    return thisObject->methodTable(globalObject->vm())->deleteProperty(thisObject, globalObject, propertyName, slot);
}

void DebuggerScope::getOwnPropertyNames(JSObject* object, JSGlobalObject* globalObject, PropertyNameArray& propertyNames, EnumerationMode mode)
{
    DebuggerScope* scope = jsCast<DebuggerScope*>(object);
    ASSERT(scope->isValid());
    if (!scope->isValid())
        return;
    JSObject* thisObject = JSScope::objectAtScope(scope->jsScope());
    thisObject->methodTable(globalObject->vm())->getPropertyNames(thisObject, globalObject, propertyNames, mode);
}

bool DebuggerScope::defineOwnProperty(JSObject* object, JSGlobalObject* globalObject, PropertyName propertyName, const PropertyDescriptor& descriptor, bool shouldThrow)
{
    DebuggerScope* scope = jsCast<DebuggerScope*>(object);
    ASSERT(scope->isValid());
    if (!scope->isValid())
        return false;
    JSObject* thisObject = JSScope::objectAtScope(scope->jsScope());
    return thisObject->methodTable(globalObject->vm())->defineOwnProperty(thisObject, globalObject, propertyName, descriptor, shouldThrow);
}

DebuggerScope* DebuggerScope::next()
{
    ASSERT(isValid());
    if (!m_next && m_scope->next()) {
        VM& vm = m_scope->vm();
        DebuggerScope* nextScope = create(vm, m_scope->next());
        m_next.set(vm, this, nextScope);
    }
    return m_next.get();
}

void DebuggerScope::invalidateChain()
{
    if (!isValid())
        return;

    DebuggerScope* scope = this;
    while (scope) {
        DebuggerScope* nextScope = scope->m_next.get();
        scope->m_next.clear();
        scope->m_scope.clear(); // This also marks this scope as invalid.
        scope = nextScope;
    }
}

bool DebuggerScope::isCatchScope() const
{
    return m_scope->isCatchScope();
}

bool DebuggerScope::isFunctionNameScope() const
{
    return m_scope->isFunctionNameScopeObject();
}

bool DebuggerScope::isWithScope() const
{
    return m_scope->isWithScope();
}

bool DebuggerScope::isGlobalScope() const
{
    return m_scope->isGlobalObject();
}

bool DebuggerScope::isGlobalLexicalEnvironment() const
{
    return m_scope->isGlobalLexicalEnvironment();
}

bool DebuggerScope::isClosureScope() const
{
    // In the current debugger implementation, every function or eval will create an
    // lexical environment object. Hence, a lexical environment object implies a
    // function or eval scope.
    return m_scope->isVarScope() || m_scope->isLexicalScope();
}

bool DebuggerScope::isNestedLexicalScope() const
{
    return m_scope->isNestedLexicalScope();
}

String DebuggerScope::name() const
{
    SymbolTable* symbolTable = m_scope->symbolTable(vm());
    if (!symbolTable)
        return String();

    CodeBlock* codeBlock = symbolTable->rareDataCodeBlock();
    if (!codeBlock)
        return String();

    return String::fromUTF8(codeBlock->inferredName());
}

DebuggerLocation DebuggerScope::location() const
{
    SymbolTable* symbolTable = m_scope->symbolTable(vm());
    if (!symbolTable)
        return DebuggerLocation();

    CodeBlock* codeBlock = symbolTable->rareDataCodeBlock();
    if (!codeBlock)
        return DebuggerLocation();

    ScriptExecutable* executable = codeBlock->ownerExecutable();
    return DebuggerLocation(executable);
}

JSValue DebuggerScope::caughtValue(JSGlobalObject* globalObject) const
{
    ASSERT(isCatchScope());
    JSLexicalEnvironment* catchEnvironment = jsCast<JSLexicalEnvironment*>(m_scope.get());
    SymbolTable* catchSymbolTable = catchEnvironment->symbolTable();
    RELEASE_ASSERT(catchSymbolTable->size() == 1);
    PropertyName errorName(catchSymbolTable->begin(catchSymbolTable->m_lock)->key.get());
    PropertySlot slot(m_scope.get(), PropertySlot::InternalMethodType::Get);
    bool success = catchEnvironment->getOwnPropertySlot(catchEnvironment, globalObject, errorName, slot);
    RELEASE_ASSERT(success && slot.isValue());
    return slot.getValue(globalObject, errorName);
}

} // namespace JSC
