/*
 * Copyright (C) 2009 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. AND ITS CONTRIBUTORS ``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 ITS 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 "bindings/v8/V8PerIsolateData.h"

#include "bindings/v8/DOMDataStore.h"
#include "bindings/v8/ScriptGCEvent.h"
#include "bindings/v8/ScriptProfiler.h"
#include "bindings/v8/V8Binding.h"
#include "bindings/v8/V8HiddenPropertyName.h"
#include "bindings/v8/V8ObjectConstructor.h"
#include "bindings/v8/V8ScriptRunner.h"

namespace WebCore {

V8PerIsolateData::V8PerIsolateData(v8::Isolate* isolate)
    : m_isolate(isolate)
    , m_stringCache(adoptPtr(new StringCache()))
    , m_workerDomDataStore(0)
    , m_hiddenPropertyName(adoptPtr(new V8HiddenPropertyName()))
    , m_constructorMode(ConstructorMode::CreateNewObject)
    , m_recursionLevel(0)
#ifndef NDEBUG
    , m_internalScriptRecursionLevel(0)
#endif
    , m_gcEventData(adoptPtr(new GCEventData()))
    , m_shouldCollectGarbageSoon(false)
{
}

V8PerIsolateData::~V8PerIsolateData()
{
}

V8PerIsolateData* V8PerIsolateData::create(v8::Isolate* isolate)
{
    ASSERT(isolate);
    ASSERT(!isolate->GetData(gin::kEmbedderBlink));
    V8PerIsolateData* data = new V8PerIsolateData(isolate);
    isolate->SetData(gin::kEmbedderBlink, data);
    return data;
}

void V8PerIsolateData::ensureInitialized(v8::Isolate* isolate)
{
    ASSERT(isolate);
    if (!isolate->GetData(gin::kEmbedderBlink))
        create(isolate);
}

v8::Persistent<v8::Value>& V8PerIsolateData::ensureLiveRoot()
{
    if (m_liveRoot.isEmpty())
        m_liveRoot.set(m_isolate, v8::Null(m_isolate));
    return m_liveRoot.getUnsafe();
}

void V8PerIsolateData::dispose(v8::Isolate* isolate)
{
    void* data = isolate->GetData(gin::kEmbedderBlink);
    delete static_cast<V8PerIsolateData*>(data);
    isolate->SetData(gin::kEmbedderBlink, 0);
}

v8::Handle<v8::FunctionTemplate> V8PerIsolateData::toStringTemplate()
{
    if (m_toStringTemplate.isEmpty())
        m_toStringTemplate.set(m_isolate, v8::FunctionTemplate::New(m_isolate, constructorOfToString));
    return m_toStringTemplate.newLocal(m_isolate);
}

v8::Handle<v8::FunctionTemplate> V8PerIsolateData::privateTemplate(WrapperWorldType currentWorldType, void* privatePointer, v8::FunctionCallback callback, v8::Handle<v8::Value> data, v8::Handle<v8::Signature> signature, int length)
{
    TemplateMap& templates = templateMap(currentWorldType);
    TemplateMap::iterator result = templates.find(privatePointer);
    if (result != templates.end())
        return result->value.newLocal(m_isolate);
    v8::Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(m_isolate, callback, data, signature, length);
    templates.add(privatePointer, UnsafePersistent<v8::FunctionTemplate>(m_isolate, templ));
    return templ;
}

v8::Handle<v8::FunctionTemplate> V8PerIsolateData::privateTemplateIfExists(WrapperWorldType currentWorldType, void* privatePointer)
{
    TemplateMap& templates = templateMap(currentWorldType);
    TemplateMap::iterator result = templates.find(privatePointer);
    if (result != templates.end())
        return result->value.newLocal(m_isolate);
    return v8::Local<v8::FunctionTemplate>();
}

void V8PerIsolateData::setPrivateTemplate(WrapperWorldType currentWorldType, void* privatePointer, v8::Handle<v8::FunctionTemplate> templ)
{
    templateMap(currentWorldType).add(privatePointer, UnsafePersistent<v8::FunctionTemplate>(m_isolate, templ));
}

v8::Handle<v8::FunctionTemplate> V8PerIsolateData::rawDOMTemplate(const WrapperTypeInfo* info, WrapperWorldType currentWorldType)
{
    TemplateMap& templates = rawDOMTemplateMap(currentWorldType);
    TemplateMap::iterator result = templates.find(info);
    if (result != templates.end())
        return result->value.newLocal(m_isolate);

    v8::EscapableHandleScope handleScope(m_isolate);
    v8::Local<v8::FunctionTemplate> templ = createRawTemplate(m_isolate);
    templates.add(info, UnsafePersistent<v8::FunctionTemplate>(m_isolate, templ));
    return handleScope.Escape(templ);
}

v8::Local<v8::Context> V8PerIsolateData::ensureRegexContext()
{
    if (m_regexContext.isEmpty()) {
        v8::HandleScope handleScope(m_isolate);
        m_regexContext.set(m_isolate, v8::Context::New(m_isolate));
    }
    return m_regexContext.newLocal(m_isolate);
}

bool V8PerIsolateData::hasInstance(const WrapperTypeInfo* info, v8::Handle<v8::Value> value, WrapperWorldType currentWorldType)
{
    TemplateMap& templates = rawDOMTemplateMap(currentWorldType);
    TemplateMap::iterator result = templates.find(info);
    if (result == templates.end())
        return false;
    v8::HandleScope handleScope(m_isolate);
    return result->value.newLocal(m_isolate)->HasInstance(value);
}

void V8PerIsolateData::constructorOfToString(const v8::FunctionCallbackInfo<v8::Value>& info)
{
    // The DOM constructors' toString functions grab the current toString
    // for Functions by taking the toString function of itself and then
    // calling it with the constructor as its receiver. This means that
    // changes to the Function prototype chain or toString function are
    // reflected when printing DOM constructors. The only wart is that
    // changes to a DOM constructor's toString's toString will cause the
    // toString of the DOM constructor itself to change. This is extremely
    // obscure and unlikely to be a problem.
    v8::Handle<v8::Value> value = info.Callee()->Get(v8AtomicString(info.GetIsolate(), "toString"));
    if (!value->IsFunction()) {
        v8SetReturnValue(info, v8::String::Empty(info.GetIsolate()));
        return;
    }
    v8SetReturnValue(info, V8ScriptRunner::callInternalFunction(v8::Handle<v8::Function>::Cast(value), info.This(), 0, 0, v8::Isolate::GetCurrent()));
}

} // namespace WebCore
