void JSQuarantinedObjectWrapper::transferExceptionToExecState(ExecState* exec) const
{
    ASSERT(exec != unwrappedExecState());

    if (!unwrappedExecState()->hadException())
        return;

    exec->setException(wrapOutgoingValue(unwrappedExecState(), unwrappedExecState()->exception()));
    unwrappedExecState()->clearException();
}
JSValue* JSInspectedObjectWrapper::prepareIncomingValue(ExecState*, JSValue* value) const
{
    // The Inspector is only allowed to pass primitive values and wrapped objects to objects from the inspected page.

    if (!value->isObject())
        return value;

    JSQuarantinedObjectWrapper* wrapper = asWrapper(value);
    ASSERT_WITH_MESSAGE(wrapper, "Objects passed to JSInspectedObjectWrapper must be wrapped");
    if (!wrapper)
        return jsUndefined();

    if (wrapper->allowsUnwrappedAccessFrom(unwrappedExecState())) {
        ASSERT_WITH_MESSAGE(wrapper->inherits(&s_info), "A wrapper contains an object from the inspected page but is not a JSInspectedObjectWrapper");
        if (!wrapper->inherits(&s_info))
            return jsUndefined();

        // Return the unwrapped object so the inspected page never sees one of its own objects in wrapped form.
        return wrapper->unwrappedObject();
    }

    ASSERT_WITH_MESSAGE(wrapper->inherits(&JSInspectorCallbackWrapper::s_info), "A wrapper that was not from the inspected page and is not an Inspector callback was passed to a JSInspectedObjectWrapper");
    if (!wrapper->inherits(&JSInspectorCallbackWrapper::s_info))
        return jsUndefined();

    return wrapper;
}
void JSQuarantinedObjectWrapper::getPropertyNames(ExecState* exec, PropertyNameArray& array)
{
    if (!allowsGetPropertyNames())
        return;

    m_unwrappedObject->getPropertyNames(unwrappedExecState(), array);
}
void JSQuarantinedObjectWrapper::put(ExecState* exec, unsigned identifier, JSValue* value)
{
    if (!allowsSetProperty())
        return;

    m_unwrappedObject->put(unwrappedExecState(), identifier, prepareIncomingValue(exec, value));

    transferExceptionToExecState(exec);
}
bool JSQuarantinedObjectWrapper::getOwnPropertySlot(ExecState* exec, unsigned identifier, PropertySlot& slot)
{
    if (!allowsGetProperty()) {
        slot.setUndefined();
        return true;
    }

    PropertySlot unwrappedSlot(m_unwrappedObject);
    bool result = m_unwrappedObject->getOwnPropertySlot(unwrappedExecState(), identifier, unwrappedSlot);
    if (result) {
        JSValue* unwrappedValue = unwrappedSlot.getValue(unwrappedExecState(), identifier);
        slot.setCustom(static_cast<JSObject*>(wrapOutgoingValue(unwrappedExecState(), unwrappedValue)), cachedValueGetter);
    }

    transferExceptionToExecState(exec);

    return result;
}
bool JSQuarantinedObjectWrapper::hasInstance(ExecState* exec, JSValue* value)
{
    if (!allowsHasInstance())
        return false;

    bool result = m_unwrappedObject->hasInstance(unwrappedExecState(), prepareIncomingValue(exec, value));

    transferExceptionToExecState(exec);

    return result;
}
bool JSQuarantinedObjectWrapper::deleteProperty(ExecState* exec, unsigned identifier)
{
    if (!allowsDeleteProperty())
        return false;

    bool result = m_unwrappedObject->deleteProperty(unwrappedExecState(), identifier);

    transferExceptionToExecState(exec);

    return result;
}