/*
 * Copyright (C) 2006-2020 Apple Inc. All rights reserved.
 * Copyright (C) 2008 Kelvin W Sherlock (ksherlock@gmail.com)
 *
 * 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 "JSObjectRef.h"
#include "JSObjectRefPrivate.h"

#include "APICast.h"
#include "APIUtils.h"
#include "DateConstructor.h"
#include "FunctionConstructor.h"
#include "Identifier.h"
#include "InitializeThreading.h"
#include "JSArray.h"
#include "JSCInlines.h"
#include "JSCallbackConstructor.h"
#include "JSCallbackFunction.h"
#include "JSCallbackObject.h"
#include "JSClassRef.h"
#include "JSPromise.h"
#include "JSString.h"
#include "ObjectConstructor.h"
#include "ObjectPrototype.h"
#include "PropertyNameArray.h"
#include "ProxyObject.h"
#include "RegExpConstructor.h"

#if ENABLE(REMOTE_INSPECTOR)
#include "JSGlobalObjectInspectorController.h"
#endif

using namespace JSC;

JSClassRef JSClassCreate(const JSClassDefinition* definition)
{
    JSC::initialize();
    auto jsClass = (definition->attributes & kJSClassAttributeNoAutomaticPrototype)
        ? OpaqueJSClass::createNoAutomaticPrototype(definition)
        : OpaqueJSClass::create(definition);
    
    return &jsClass.leakRef();
}

JSClassRef JSClassRetain(JSClassRef jsClass)
{
    jsClass->ref();
    return jsClass;
}

void JSClassRelease(JSClassRef jsClass)
{
    jsClass->deref();
}

JSObjectRef JSObjectMake(JSContextRef ctx, JSClassRef jsClass, void* data)
{
    if (!ctx) {
        ASSERT_NOT_REACHED();
        return nullptr;
    }
    JSGlobalObject* globalObject = toJS(ctx);
    VM& vm = globalObject->vm();
    JSLockHolder locker(vm);

    if (!jsClass)
        return toRef(constructEmptyObject(globalObject));

    JSCallbackObject<JSNonFinalObject>* object = JSCallbackObject<JSNonFinalObject>::create(globalObject, globalObject->callbackObjectStructure(), jsClass, data);
    if (JSObject* prototype = jsClass->prototype(globalObject))
        object->setPrototypeDirect(vm, prototype);

    return toRef(object);
}

JSObjectRef JSObjectMakeFunctionWithCallback(JSContextRef ctx, JSStringRef name, JSObjectCallAsFunctionCallback callAsFunction)
{
    if (!ctx) {
        ASSERT_NOT_REACHED();
        return nullptr;
    }
    JSGlobalObject* globalObject = toJS(ctx);
    VM& vm = globalObject->vm();
    JSLockHolder locker(vm);
    return toRef(JSCallbackFunction::create(vm, globalObject, callAsFunction, name ? name->string() : "anonymous"_s));
}

JSObjectRef JSObjectMakeConstructor(JSContextRef ctx, JSClassRef jsClass, JSObjectCallAsConstructorCallback callAsConstructor)
{
    if (!ctx) {
        ASSERT_NOT_REACHED();
        return nullptr;
    }
    JSGlobalObject* globalObject = toJS(ctx);
    VM& vm = globalObject->vm();
    JSLockHolder locker(vm);

    JSValue jsPrototype = jsClass ? jsClass->prototype(globalObject) : nullptr;
    if (!jsPrototype)
        jsPrototype = globalObject->objectPrototype();

    JSCallbackConstructor* constructor = JSCallbackConstructor::create(globalObject, globalObject->callbackConstructorStructure(), jsClass, callAsConstructor);
    constructor->putDirect(vm, vm.propertyNames->prototype, jsPrototype, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly);
    return toRef(constructor);
}

JSObjectRef JSObjectMakeFunction(JSContextRef ctx, JSStringRef name, unsigned parameterCount, const JSStringRef parameterNames[], JSStringRef body, JSStringRef sourceURLString, int startingLineNumber, JSValueRef* exception)
{
    if (!ctx) {
        ASSERT_NOT_REACHED();
        return nullptr;
    }
    JSGlobalObject* globalObject = toJS(ctx);
    VM& vm = globalObject->vm();
    JSLockHolder locker(vm);
    auto scope = DECLARE_CATCH_SCOPE(vm);

    startingLineNumber = std::max(1, startingLineNumber);
    Identifier nameID = name ? name->identifier(&vm) : Identifier::fromString(vm, "anonymous");
    
    MarkedArgumentBuffer args;
    for (unsigned i = 0; i < parameterCount; i++)
        args.append(jsString(vm, parameterNames[i]->string()));
    args.append(jsString(vm, body->string()));
    if (UNLIKELY(args.hasOverflowed())) {
        auto throwScope = DECLARE_THROW_SCOPE(vm);
        throwOutOfMemoryError(globalObject, throwScope);
        handleExceptionIfNeeded(scope, ctx, exception);
        return nullptr;
    }

    auto sourceURL = sourceURLString ? URL({ }, sourceURLString->string()) : URL();
    JSObject* result = constructFunction(globalObject, args, nameID, SourceOrigin { sourceURL }, sourceURL.string(), TextPosition(OrdinalNumber::fromOneBasedInt(startingLineNumber), OrdinalNumber()));
    if (handleExceptionIfNeeded(scope, ctx, exception) == ExceptionStatus::DidThrow)
        result = nullptr;
    return toRef(result);
}

JSObjectRef JSObjectMakeArray(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[],  JSValueRef* exception)
{
    if (!ctx) {
        ASSERT_NOT_REACHED();
        return nullptr;
    }
    JSGlobalObject* globalObject = toJS(ctx);
    VM& vm = globalObject->vm();
    JSLockHolder locker(vm);
    auto scope = DECLARE_CATCH_SCOPE(vm);

    JSObject* result;
    if (argumentCount) {
        MarkedArgumentBuffer argList;
        for (size_t i = 0; i < argumentCount; ++i)
            argList.append(toJS(globalObject, arguments[i]));
        if (UNLIKELY(argList.hasOverflowed())) {
            auto throwScope = DECLARE_THROW_SCOPE(vm);
            throwOutOfMemoryError(globalObject, throwScope);
            handleExceptionIfNeeded(scope, ctx, exception);
            return nullptr;
        }

        result = constructArray(globalObject, static_cast<ArrayAllocationProfile*>(nullptr), argList);
    } else
        result = constructEmptyArray(globalObject, nullptr);

    if (handleExceptionIfNeeded(scope, ctx, exception) == ExceptionStatus::DidThrow)
        result = nullptr;

    return toRef(result);
}

JSObjectRef JSObjectMakeDate(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[],  JSValueRef* exception)
{
    if (!ctx) {
        ASSERT_NOT_REACHED();
        return nullptr;
    }
    JSGlobalObject* globalObject = toJS(ctx);
    VM& vm = globalObject->vm();
    JSLockHolder locker(vm);
    auto scope = DECLARE_CATCH_SCOPE(vm);

    MarkedArgumentBuffer argList;
    for (size_t i = 0; i < argumentCount; ++i)
        argList.append(toJS(globalObject, arguments[i]));
    if (UNLIKELY(argList.hasOverflowed())) {
        auto throwScope = DECLARE_THROW_SCOPE(vm);
        throwOutOfMemoryError(globalObject, throwScope);
        handleExceptionIfNeeded(scope, ctx, exception);
        return nullptr;
    }

    JSObject* result = constructDate(globalObject, JSValue(), argList);
    if (handleExceptionIfNeeded(scope, ctx, exception) == ExceptionStatus::DidThrow)
        result = nullptr;

    return toRef(result);
}

JSObjectRef JSObjectMakeError(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[],  JSValueRef* exception)
{
    if (!ctx) {
        ASSERT_NOT_REACHED();
        return nullptr;
    }
    JSGlobalObject* globalObject = toJS(ctx);
    VM& vm = globalObject->vm();
    JSLockHolder locker(vm);
    auto scope = DECLARE_CATCH_SCOPE(vm);

    JSValue message = argumentCount ? toJS(globalObject, arguments[0]) : jsUndefined();
    JSValue options = argumentCount > 1 ? toJS(globalObject, arguments[1]) : jsUndefined();
    Structure* errorStructure = globalObject->errorStructure();
    JSObject* result = ErrorInstance::create(globalObject, errorStructure, message, options);

    if (handleExceptionIfNeeded(scope, ctx, exception) == ExceptionStatus::DidThrow)
        result = nullptr;

    return toRef(result);
}

JSObjectRef JSObjectMakeRegExp(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[],  JSValueRef* exception)
{
    if (!ctx) {
        ASSERT_NOT_REACHED();
        return nullptr;
    }
    JSGlobalObject* globalObject = toJS(ctx);
    VM& vm = globalObject->vm();
    JSLockHolder locker(vm);
    auto scope = DECLARE_CATCH_SCOPE(vm);

    MarkedArgumentBuffer argList;
    for (size_t i = 0; i < argumentCount; ++i)
        argList.append(toJS(globalObject, arguments[i]));
    if (UNLIKELY(argList.hasOverflowed())) {
        auto throwScope = DECLARE_THROW_SCOPE(vm);
        throwOutOfMemoryError(globalObject, throwScope);
        handleExceptionIfNeeded(scope, ctx, exception);
        return nullptr;
    }

    JSObject* result = constructRegExp(globalObject, argList);
    if (handleExceptionIfNeeded(scope, ctx, exception) == ExceptionStatus::DidThrow)
        result = nullptr;
    
    return toRef(result);
}

JSObjectRef JSObjectMakeDeferredPromise(JSContextRef ctx, JSObjectRef* resolve, JSObjectRef* reject, JSValueRef* exception)
{
    if (!ctx) {
        ASSERT_NOT_REACHED();
        return nullptr;
    }

    JSGlobalObject* globalObject = toJS(ctx);
    VM& vm = globalObject->vm();
    JSLockHolder locker(globalObject);
    auto scope = DECLARE_CATCH_SCOPE(vm);

    JSPromise::DeferredData data = JSPromise::createDeferredData(globalObject, globalObject->promiseConstructor());
    if (handleExceptionIfNeeded(scope, ctx, exception) == ExceptionStatus::DidThrow)
        return nullptr;

    if (resolve)
        *resolve = toRef(data.resolve);
    if (reject)
        *reject = toRef(data.reject);
    return toRef(data.promise);
}

JSValueRef JSObjectGetPrototype(JSContextRef ctx, JSObjectRef object)
{
    if (!ctx) {
        ASSERT_NOT_REACHED();
        return nullptr;
    }
    JSGlobalObject* globalObject = toJS(ctx);
    JSLockHolder locker(globalObject);

    JSObject* jsObject = toJS(object); 
    return toRef(globalObject, jsObject->getPrototypeDirect(globalObject->vm()));
}

void JSObjectSetPrototype(JSContextRef ctx, JSObjectRef object, JSValueRef value)
{
    if (!ctx) {
        ASSERT_NOT_REACHED();
        return;
    }
    JSGlobalObject* globalObject = toJS(ctx);
    VM& vm = globalObject->vm();
    JSLockHolder locker(vm);
    auto scope = DECLARE_CATCH_SCOPE(vm);

    JSObject* jsObject = toJS(object);
    JSValue jsValue = toJS(globalObject, value);
    jsObject->setPrototype(vm, globalObject, jsValue.isObject() ? jsValue : jsNull());
    handleExceptionIfNeeded(scope, ctx, nullptr);
}

bool JSObjectHasProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName)
{
    if (!ctx) {
        ASSERT_NOT_REACHED();
        return false;
    }
    JSGlobalObject* globalObject = toJS(ctx);
    VM& vm = globalObject->vm();
    JSLockHolder locker(vm);

    JSObject* jsObject = toJS(object);
    
    return jsObject->hasProperty(globalObject, propertyName->identifier(&vm));
}

JSValueRef JSObjectGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
{
    if (!ctx || !object) {
        ASSERT_NOT_REACHED();
        return nullptr;
    }
    JSGlobalObject* globalObject = toJS(ctx);
    VM& vm = globalObject->vm();
    JSLockHolder locker(vm);
    auto scope = DECLARE_CATCH_SCOPE(vm);

    JSObject* jsObject = toJS(object);

    JSValue jsValue = jsObject->get(globalObject, propertyName->identifier(&vm));
    if (handleExceptionIfNeeded(scope, ctx, exception) == ExceptionStatus::DidThrow)
        return nullptr;
    return toRef(globalObject, jsValue);
}

void JSObjectSetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSPropertyAttributes attributes, JSValueRef* exception)
{
    if (!ctx) {
        ASSERT_NOT_REACHED();
        return;
    }
    JSGlobalObject* globalObject = toJS(ctx);
    VM& vm = globalObject->vm();
    JSLockHolder locker(vm);
    auto scope = DECLARE_CATCH_SCOPE(vm);

    JSObject* jsObject = toJS(object);
    Identifier name(propertyName->identifier(&vm));
    JSValue jsValue = toJS(globalObject, value);

    bool doesNotHaveProperty = attributes && !jsObject->hasProperty(globalObject, name);
    if (LIKELY(!scope.exception())) {
        if (doesNotHaveProperty) {
            PropertyDescriptor desc(jsValue, attributes);
            jsObject->methodTable(vm)->defineOwnProperty(jsObject, globalObject, name, desc, false);
        } else {
            PutPropertySlot slot(jsObject);
            jsObject->methodTable(vm)->put(jsObject, globalObject, name, jsValue, slot);
        }
    }
    handleExceptionIfNeeded(scope, ctx, exception);
}

bool JSObjectHasPropertyForKey(JSContextRef ctx, JSObjectRef object, JSValueRef key, JSValueRef* exception)
{
    if (!ctx) {
        ASSERT_NOT_REACHED();
        return false;
    }
    JSGlobalObject* globalObject = toJS(ctx);
    VM& vm = globalObject->vm();
    JSLockHolder locker(vm);
    auto scope = DECLARE_CATCH_SCOPE(vm);

    JSObject* jsObject = toJS(object);
    Identifier ident = toJS(globalObject, key).toPropertyKey(globalObject);
    if (handleExceptionIfNeeded(scope, ctx, exception) == ExceptionStatus::DidThrow)
        return false;

    bool result = jsObject->hasProperty(globalObject, ident);
    if (handleExceptionIfNeeded(scope, ctx, exception) == ExceptionStatus::DidThrow)
        return false;
    return result;
}

JSValueRef JSObjectGetPropertyForKey(JSContextRef ctx, JSObjectRef object, JSValueRef key, JSValueRef* exception)
{
    if (!ctx) {
        ASSERT_NOT_REACHED();
        return nullptr;
    }
    JSGlobalObject* globalObject = toJS(ctx);
    VM& vm = globalObject->vm();
    JSLockHolder locker(vm);
    auto scope = DECLARE_CATCH_SCOPE(vm);

    JSObject* jsObject = toJS(object);
    Identifier ident = toJS(globalObject, key).toPropertyKey(globalObject);
    if (handleExceptionIfNeeded(scope, ctx, exception) == ExceptionStatus::DidThrow)
        return nullptr;

    JSValue jsValue = jsObject->get(globalObject, ident);
    if (handleExceptionIfNeeded(scope, ctx, exception) == ExceptionStatus::DidThrow)
        return nullptr;
    return toRef(globalObject, jsValue);
}

void JSObjectSetPropertyForKey(JSContextRef ctx, JSObjectRef object, JSValueRef key, JSValueRef value, JSPropertyAttributes attributes, JSValueRef* exception)
{
    if (!ctx) {
        ASSERT_NOT_REACHED();
        return;
    }
    JSGlobalObject* globalObject = toJS(ctx);
    VM& vm = globalObject->vm();
    JSLockHolder locker(vm);
    auto scope = DECLARE_CATCH_SCOPE(vm);

    JSObject* jsObject = toJS(object);
    JSValue jsValue = toJS(globalObject, value);

    Identifier ident = toJS(globalObject, key).toPropertyKey(globalObject);
    if (handleExceptionIfNeeded(scope, ctx, exception) == ExceptionStatus::DidThrow)
        return;

    bool doesNotHaveProperty = attributes && !jsObject->hasProperty(globalObject, ident);
    if (LIKELY(!scope.exception())) {
        if (doesNotHaveProperty) {
            PropertyDescriptor desc(jsValue, attributes);
            jsObject->methodTable(vm)->defineOwnProperty(jsObject, globalObject, ident, desc, false);
        } else {
            PutPropertySlot slot(jsObject);
            jsObject->methodTable(vm)->put(jsObject, globalObject, ident, jsValue, slot);
        }
    }
    handleExceptionIfNeeded(scope, ctx, exception);
}

bool JSObjectDeletePropertyForKey(JSContextRef ctx, JSObjectRef object, JSValueRef key, JSValueRef* exception)
{
    if (!ctx) {
        ASSERT_NOT_REACHED();
        return false;
    }
    JSGlobalObject* globalObject = toJS(ctx);
    VM& vm = globalObject->vm();
    JSLockHolder locker(vm);
    auto scope = DECLARE_CATCH_SCOPE(vm);

    JSObject* jsObject = toJS(object);
    Identifier ident = toJS(globalObject, key).toPropertyKey(globalObject);
    if (handleExceptionIfNeeded(scope, ctx, exception) == ExceptionStatus::DidThrow)
        return false;

    bool result = JSCell::deleteProperty(jsObject, globalObject, ident);
    if (handleExceptionIfNeeded(scope, ctx, exception) == ExceptionStatus::DidThrow)
        return false;
    return result;
}

JSValueRef JSObjectGetPropertyAtIndex(JSContextRef ctx, JSObjectRef object, unsigned propertyIndex, JSValueRef* exception)
{
    if (!ctx) {
        ASSERT_NOT_REACHED();
        return nullptr;
    }
    JSGlobalObject* globalObject = toJS(ctx);
    VM& vm = globalObject->vm();
    JSLockHolder locker(vm);
    auto scope = DECLARE_CATCH_SCOPE(vm);

    JSObject* jsObject = toJS(object);

    JSValue jsValue = jsObject->get(globalObject, propertyIndex);
    if (handleExceptionIfNeeded(scope, ctx, exception) == ExceptionStatus::DidThrow)
        return nullptr;
    return toRef(globalObject, jsValue);
}


void JSObjectSetPropertyAtIndex(JSContextRef ctx, JSObjectRef object, unsigned propertyIndex, JSValueRef value, JSValueRef* exception)
{
    if (!ctx) {
        ASSERT_NOT_REACHED();
        return;
    }
    JSGlobalObject* globalObject = toJS(ctx);
    VM& vm = globalObject->vm();
    JSLockHolder locker(vm);
    auto scope = DECLARE_CATCH_SCOPE(vm);

    JSObject* jsObject = toJS(object);
    JSValue jsValue = toJS(globalObject, value);
    
    jsObject->methodTable(vm)->putByIndex(jsObject, globalObject, propertyIndex, jsValue, false);
    handleExceptionIfNeeded(scope, ctx, exception);
}

bool JSObjectDeleteProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
{
    if (!ctx) {
        ASSERT_NOT_REACHED();
        return false;
    }
    JSGlobalObject* globalObject = toJS(ctx);
    VM& vm = globalObject->vm();
    JSLockHolder locker(vm);
    auto scope = DECLARE_CATCH_SCOPE(vm);

    JSObject* jsObject = toJS(object);

    bool result = JSCell::deleteProperty(jsObject, globalObject, propertyName->identifier(&vm));
    if (handleExceptionIfNeeded(scope, ctx, exception) == ExceptionStatus::DidThrow)
        return false;
    return result;
}

// API objects have private properties, which may get accessed during destruction. This
// helper lets us get the ClassInfo of an API object from a function that may get called
// during destruction.
static const ClassInfo* classInfoPrivate(JSObject* jsObject)
{
    VM& vm = jsObject->vm();
    
    if (vm.currentlyDestructingCallbackObject != jsObject)
        return jsObject->classInfo(vm);

    return vm.currentlyDestructingCallbackObjectClassInfo;
}

void* JSObjectGetPrivate(JSObjectRef object)
{
    JSObject* jsObject = uncheckedToJS(object);
    VM& vm = jsObject->vm();

    const ClassInfo* classInfo = classInfoPrivate(jsObject);
    
    // Get wrapped object if proxied
    if (classInfo->isSubClassOf(JSProxy::info())) {
        jsObject = static_cast<JSProxy*>(jsObject)->target();
        classInfo = jsObject->classInfo(vm);
    }

    if (classInfo->isSubClassOf(JSCallbackObject<JSGlobalObject>::info()))
        return static_cast<JSCallbackObject<JSGlobalObject>*>(jsObject)->getPrivate();
    if (classInfo->isSubClassOf(JSCallbackObject<JSNonFinalObject>::info()))
        return static_cast<JSCallbackObject<JSNonFinalObject>*>(jsObject)->getPrivate();
#if JSC_OBJC_API_ENABLED
    if (classInfo->isSubClassOf(JSCallbackObject<JSAPIWrapperObject>::info()))
        return static_cast<JSCallbackObject<JSAPIWrapperObject>*>(jsObject)->getPrivate();
#endif
    
    return nullptr;
}

bool JSObjectSetPrivate(JSObjectRef object, void* data)
{
    JSObject* jsObject = uncheckedToJS(object);
    VM& vm = jsObject->vm();

    const ClassInfo* classInfo = classInfoPrivate(jsObject);
    
    // Get wrapped object if proxied
    if (classInfo->isSubClassOf(JSProxy::info())) {
        jsObject = static_cast<JSProxy*>(jsObject)->target();
        classInfo = jsObject->classInfo(vm);
    }

    if (classInfo->isSubClassOf(JSCallbackObject<JSGlobalObject>::info())) {
        static_cast<JSCallbackObject<JSGlobalObject>*>(jsObject)->setPrivate(data);
        return true;
    }
    if (classInfo->isSubClassOf(JSCallbackObject<JSNonFinalObject>::info())) {
        static_cast<JSCallbackObject<JSNonFinalObject>*>(jsObject)->setPrivate(data);
        return true;
    }
#if JSC_OBJC_API_ENABLED
    if (classInfo->isSubClassOf(JSCallbackObject<JSAPIWrapperObject>::info())) {
        static_cast<JSCallbackObject<JSAPIWrapperObject>*>(jsObject)->setPrivate(data);
        return true;
    }
#endif
        
    return false;
}

JSValueRef JSObjectGetPrivateProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName)
{
    JSGlobalObject* globalObject = toJS(ctx);
    VM& vm = globalObject->vm();
    JSLockHolder locker(vm);
    JSObject* jsObject = toJS(object);
    JSValue result;
    Identifier name(propertyName->identifier(&vm));


    // Get wrapped object if proxied
    if (jsObject->inherits<JSProxy>(vm))
        jsObject = jsCast<JSProxy*>(jsObject)->target();

    if (jsObject->inherits<JSCallbackObject<JSGlobalObject>>(vm))
        result = jsCast<JSCallbackObject<JSGlobalObject>*>(jsObject)->getPrivateProperty(name);
    else if (jsObject->inherits<JSCallbackObject<JSNonFinalObject>>(vm))
        result = jsCast<JSCallbackObject<JSNonFinalObject>*>(jsObject)->getPrivateProperty(name);
#if JSC_OBJC_API_ENABLED
    else if (jsObject->inherits<JSCallbackObject<JSAPIWrapperObject>>(vm))
        result = jsCast<JSCallbackObject<JSAPIWrapperObject>*>(jsObject)->getPrivateProperty(name);
#endif
    return toRef(globalObject, result);
}

bool JSObjectSetPrivateProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value)
{
    JSGlobalObject* globalObject = toJS(ctx);
    VM& vm = globalObject->vm();
    JSLockHolder locker(vm);
    JSObject* jsObject = toJS(object);
    JSValue jsValue = value ? toJS(globalObject, value) : JSValue();
    Identifier name(propertyName->identifier(&vm));

    // Get wrapped object if proxied
    if (jsObject->inherits<JSProxy>(vm))
        jsObject = jsCast<JSProxy*>(jsObject)->target();

    if (jsObject->inherits<JSCallbackObject<JSGlobalObject>>(vm)) {
        jsCast<JSCallbackObject<JSGlobalObject>*>(jsObject)->setPrivateProperty(vm, name, jsValue);
        return true;
    }
    if (jsObject->inherits<JSCallbackObject<JSNonFinalObject>>(vm)) {
        jsCast<JSCallbackObject<JSNonFinalObject>*>(jsObject)->setPrivateProperty(vm, name, jsValue);
        return true;
    }
#if JSC_OBJC_API_ENABLED
    if (jsObject->inherits<JSCallbackObject<JSAPIWrapperObject>>(vm)) {
        jsCast<JSCallbackObject<JSAPIWrapperObject>*>(jsObject)->setPrivateProperty(vm, name, jsValue);
        return true;
    }
#endif
    return false;
}

bool JSObjectDeletePrivateProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName)
{
    JSGlobalObject* globalObject = toJS(ctx);
    VM& vm = globalObject->vm();
    JSLockHolder locker(vm);
    JSObject* jsObject = toJS(object);
    Identifier name(propertyName->identifier(&vm));

    // Get wrapped object if proxied
    if (jsObject->inherits<JSProxy>(vm))
        jsObject = jsCast<JSProxy*>(jsObject)->target();

    if (jsObject->inherits<JSCallbackObject<JSGlobalObject>>(vm)) {
        jsCast<JSCallbackObject<JSGlobalObject>*>(jsObject)->deletePrivateProperty(name);
        return true;
    }
    if (jsObject->inherits<JSCallbackObject<JSNonFinalObject>>(vm)) {
        jsCast<JSCallbackObject<JSNonFinalObject>*>(jsObject)->deletePrivateProperty(name);
        return true;
    }
#if JSC_OBJC_API_ENABLED
    if (jsObject->inherits<JSCallbackObject<JSAPIWrapperObject>>(vm)) {
        jsCast<JSCallbackObject<JSAPIWrapperObject>*>(jsObject)->deletePrivateProperty(name);
        return true;
    }
#endif
    return false;
}

bool JSObjectIsFunction(JSContextRef ctx, JSObjectRef object)
{
    if (!object)
        return false;
    JSGlobalObject* globalObject = toJS(ctx);
    VM& vm = globalObject->vm();
    JSLockHolder locker(vm);
    JSCell* cell = toJS(object);
    return cell->isCallable(vm);
}

JSValueRef JSObjectCallAsFunction(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
{
    JSGlobalObject* globalObject = toJS(ctx);
    VM& vm = globalObject->vm();
    JSLockHolder locker(vm);
    auto scope = DECLARE_CATCH_SCOPE(vm);

    if (!object)
        return nullptr;

    JSObject* jsObject = toJS(object);
    JSObject* jsThisObject = toJS(thisObject);

    if (!jsThisObject)
        jsThisObject = globalObject->globalThis();

    MarkedArgumentBuffer argList;
    for (size_t i = 0; i < argumentCount; i++)
        argList.append(toJS(globalObject, arguments[i]));
    if (UNLIKELY(argList.hasOverflowed())) {
        auto throwScope = DECLARE_THROW_SCOPE(vm);
        throwOutOfMemoryError(globalObject, throwScope);
        handleExceptionIfNeeded(scope, ctx, exception);
        return nullptr;
    }

    auto callData = getCallData(vm, jsObject);
    if (callData.type == CallData::Type::None)
        return nullptr;

    JSValueRef result = toRef(globalObject, profiledCall(globalObject, ProfilingReason::API, jsObject, callData, jsThisObject, argList));
    if (handleExceptionIfNeeded(scope, ctx, exception) == ExceptionStatus::DidThrow)
        result = nullptr;
    return result;
}

bool JSObjectIsConstructor(JSContextRef ctx, JSObjectRef object)
{
    JSGlobalObject* globalObject = toJS(ctx);
    VM& vm = globalObject->vm();
    JSLockHolder locker(vm);
    if (!object)
        return false;
    return toJS(object)->isConstructor(vm);
}

JSObjectRef JSObjectCallAsConstructor(JSContextRef ctx, JSObjectRef object, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
{
    JSGlobalObject* globalObject = toJS(ctx);
    VM& vm = globalObject->vm();
    JSLockHolder locker(vm);
    auto scope = DECLARE_CATCH_SCOPE(vm);

    if (!object)
        return nullptr;

    JSObject* jsObject = toJS(object);

    auto constructData = getConstructData(vm, jsObject);
    if (constructData.type == CallData::Type::None)
        return nullptr;

    MarkedArgumentBuffer argList;
    for (size_t i = 0; i < argumentCount; i++)
        argList.append(toJS(globalObject, arguments[i]));
    if (UNLIKELY(argList.hasOverflowed())) {
        auto throwScope = DECLARE_THROW_SCOPE(vm);
        throwOutOfMemoryError(globalObject, throwScope);
        handleExceptionIfNeeded(scope, ctx, exception);
        return nullptr;
    }

    JSObjectRef result = toRef(profiledConstruct(globalObject, ProfilingReason::API, jsObject, constructData, argList));
    if (handleExceptionIfNeeded(scope, ctx, exception) == ExceptionStatus::DidThrow)
        result = nullptr;
    return result;
}

struct OpaqueJSPropertyNameArray {
    WTF_MAKE_FAST_ALLOCATED;
public:
    // FIXME: Why not inherit from RefCounted?
    OpaqueJSPropertyNameArray(VM* vm)
        : refCount(0)
        , vm(vm)
    {
    }
    
    unsigned refCount;
    VM* vm;
    Vector<Ref<OpaqueJSString>> array;
};

JSPropertyNameArrayRef JSObjectCopyPropertyNames(JSContextRef ctx, JSObjectRef object)
{
    if (!ctx) {
        ASSERT_NOT_REACHED();
        return nullptr;
    }
    JSGlobalObject* globalObject = toJS(ctx);
    JSLockHolder locker(globalObject);

    VM& vm = globalObject->vm();

    JSObject* jsObject = toJS(object);
    JSPropertyNameArrayRef propertyNames = new OpaqueJSPropertyNameArray(&vm);
    PropertyNameArray array(vm, PropertyNameMode::Strings, PrivateSymbolMode::Exclude);
    jsObject->getPropertyNames(globalObject, array, DontEnumPropertiesMode::Exclude);

    size_t size = array.size();
    propertyNames->array.reserveInitialCapacity(size);
    for (size_t i = 0; i < size; ++i)
        propertyNames->array.uncheckedAppend(OpaqueJSString::tryCreate(array[i].string()).releaseNonNull());

    return JSPropertyNameArrayRetain(propertyNames);
}

JSPropertyNameArrayRef JSPropertyNameArrayRetain(JSPropertyNameArrayRef array)
{
    ++array->refCount;
    return array;
}

void JSPropertyNameArrayRelease(JSPropertyNameArrayRef array)
{
    if (--array->refCount == 0) {
        JSLockHolder locker(array->vm);
        delete array;
    }
}

size_t JSPropertyNameArrayGetCount(JSPropertyNameArrayRef array)
{
    return array->array.size();
}

JSStringRef JSPropertyNameArrayGetNameAtIndex(JSPropertyNameArrayRef array, size_t index)
{
    return array->array[static_cast<unsigned>(index)].ptr();
}

void JSPropertyNameAccumulatorAddName(JSPropertyNameAccumulatorRef array, JSStringRef propertyName)
{
    PropertyNameArray* propertyNames = toJS(array);
    VM& vm = propertyNames->vm();
    JSLockHolder locker(vm);
    propertyNames->add(propertyName->identifier(&vm));
}

JSObjectRef JSObjectGetProxyTarget(JSObjectRef objectRef)
{
    JSObject* object = toJS(objectRef);
    if (!object)
        return nullptr;
    VM& vm = object->vm();
    JSLockHolder locker(vm);
    JSObject* result = nullptr;
    if (JSProxy* proxy = jsDynamicCast<JSProxy*>(vm, object))
        result = proxy->target();
    else if (ProxyObject* proxy = jsDynamicCast<ProxyObject*>(vm, object))
        result = proxy->target();
    return toRef(result);
}

JSGlobalContextRef JSObjectGetGlobalContext(JSObjectRef objectRef)
{
    JSObject* object = toJS(objectRef);
    if (!object)
        return nullptr;
    return reinterpret_cast<JSGlobalContextRef>(object->globalObject());
}

