// Copyright 2011, 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:
//
//    * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//    * 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.
//    * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
// OWNER 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 "bindings/core/dart/DartUtilities.h"

#if OS(ANDROID)
#include <sys/system_properties.h>
#endif

#include "bindings/core/dart/DartController.h"
#include "bindings/core/dart/DartDOMData.h"
#include "bindings/core/dart/DartJsInterop.h"
#include "bindings/core/dart/DartScriptDebugServer.h"
#include "bindings/core/dart/DartScriptState.h"
#include "bindings/core/dart/V8Converter.h"
#include "bindings/core/v8/ExceptionState.h"
#include "bindings/core/v8/ScriptController.h"
#include "bindings/core/v8/SerializedScriptValueFactory.h"
#include "bindings/core/v8/V8Binding.h"
#include "bindings/core/v8/V8Node.h"
#include "bindings/core/v8/V8PerIsolateData.h"
#include "core/dom/DOMArrayBuffer.h"
#include "core/dom/DOMDataView.h"
#include "core/dom/Document.h"
#include "core/events/ErrorEvent.h"
#include "core/fetch/FetchInitiatorTypeNames.h"
#include "core/fetch/ResourceFetcher.h"
#include "core/frame/LocalDOMWindow.h"
#include "core/frame/LocalFrame.h"
#include "core/inspector/ScriptArguments.h"
#include "core/inspector/ScriptCallStack.h"
#include "core/loader/FrameLoader.h"
#include "modules/webdatabase/sqlite/SQLValue.h"
#include "platform/SharedBuffer.h"
#include "platform/network/ResourceRequest.h"

#include "wtf/ArrayBufferView.h"
#include "wtf/Float32Array.h"
#include "wtf/Float64Array.h"
#include "wtf/Int16Array.h"
#include "wtf/Int32Array.h"
#include "wtf/Int8Array.h"
#include "wtf/RefCounted.h"
#include "wtf/Uint16Array.h"
#include "wtf/Uint32Array.h"
#include "wtf/Uint8Array.h"
#include "wtf/Uint8ClampedArray.h"
#include "wtf/text/AtomicString.h"
#include "wtf/text/CString.h"
#include "wtf/text/WTFString.h"

namespace blink {

V8Scope::V8Scope(DartDOMData* dartDOMData, v8::Handle<v8::Context> context)
    : m_v8Isolate(v8::Isolate::GetCurrent())
    , m_dartDOMData(dartDOMData)
    , m_handleScope(m_v8Isolate)
    , m_contextScope(context)
    , m_recursionScope(m_v8Isolate)
{
    if (m_dartDOMData)
        (*m_dartDOMData->recursion())++;
}

V8Scope::V8Scope(DartDOMData* dartDOMData)
    : m_v8Isolate(v8::Isolate::GetCurrent())
    , m_dartDOMData(dartDOMData)
    , m_handleScope(m_v8Isolate)
    , m_contextScope(DartUtilities::currentV8Context())
    , m_recursionScope(m_v8Isolate)
{
    if (m_dartDOMData)
        (*m_dartDOMData->recursion())++;
}

V8Scope::~V8Scope()
{
    if (m_dartDOMData)
        (*m_dartDOMData->recursion())--;
}

DartStringPeer* DartStringPeer::nullString()
{
    DEFINE_STATIC_LOCAL(DartStringPeer, empty, ());
    return &empty;
}

DartStringPeer* DartStringPeer::emptyString()
{
    DEFINE_STATIC_LOCAL(DartStringPeer, empty, (StringImpl::empty()));
    return &empty;
}


static void stringFinalizer(void* peer)
{
    ASSERT(reinterpret_cast<DartStringPeer*>(peer) != DartStringPeer::nullString());
    delete reinterpret_cast<DartStringPeer*>(peer);
}

template <typename T> DartStringPeer* convertAndExternalize(Dart_Handle string, intptr_t length)
{
    if (!length)
        return new DartStringPeer(StringImpl::empty());
#ifndef NDEBUG
    {
        intptr_t storageSize = 0;
        Dart_StringStorageSize(string, &storageSize);
        ASSERT(length * intptr_t(sizeof(T)) == storageSize);
    }
#endif
    T* buffer = 0;
    DartStringPeer* peer = new DartStringPeer(StringImpl::createUninitialized(length, buffer));
    Dart_Handle r = Dart_MakeExternalString(string, buffer, length * sizeof(T), peer, stringFinalizer);
    ALLOW_UNUSED_LOCAL(r);
    ASSERT(!Dart_IsError(r));
    return peer;
}

DartStringPeer* DartUtilities::toStringImpl(Dart_Handle object, intptr_t charsize, intptr_t strlength)
{
    ASSERT(Dart_IsString(object) && !Dart_IsExternalString(object));
    return (charsize == 1) ? convertAndExternalize<LChar>(object, strlength) : convertAndExternalize<UChar>(object, strlength);
}


Dart_Handle DartUtilities::stringImplToDartString(StringImpl* stringImpl)
{
    if (!stringImpl) {
        DartDOMData* domData = DartDOMData::current();
        return domData->emptyString();
    }

    DartStringPeer* peer = new DartStringPeer(stringImpl);
    if (stringImpl->is8Bit()) {
        // FIXME: maybe it makes sense only externalize strings longer than certain threshold, such as 5 symbols.
        return Dart_NewExternalLatin1String(reinterpret_cast<const uint8_t*>(stringImpl->characters8()),
            stringImpl->length(), peer, stringFinalizer);
    } else {
        // FIXME: maybe it makes sense only externalize strings longer than certain threshold, such as 5 symbols.
        return Dart_NewExternalUTF16String(reinterpret_cast<const uint16_t*>(stringImpl->characters16()),
            stringImpl->length(), peer, stringFinalizer);
    }
}

Dart_Handle DartUtilities::stringToDartString(const String& str)
{
    return stringImplToDartString(str.impl());
}

Dart_Handle DartUtilities::stringToDartString(const AtomicString& str)
{
    return stringImplToDartString(str.impl());
}


Dart_Handle DartUtilities::safeStringImplToDartString(StringImpl* stringImpl)
{
    if (!stringImpl) {
        DartDOMData* domData = DartDOMData::current();
        return domData->emptyString();
    }

    if (stringImpl->is8Bit()) {
        return Dart_NewStringFromUTF8(
            reinterpret_cast<const uint8_t*>(stringImpl->characters8()),
            stringImpl->length());
    } else {
        return Dart_NewStringFromUTF16(
            reinterpret_cast<const uint16_t*>(stringImpl->characters16()),
            stringImpl->length());
    }
}

Dart_Handle DartUtilities::safeStringToDartString(const String& str)
{
    return safeStringImplToDartString(str.impl());
}

Dart_Handle DartUtilities::safeStringToDartString(const AtomicString& str)
{
    return safeStringImplToDartString(str.impl());
}

template <typename Trait>
typename Trait::nativeType convert(Dart_Handle object, Dart_Handle& exception)
{
    typename Trait::nativeType value;
    Dart_Handle result = Trait::convert(object, &value);
    if (Dart_IsError(result)) {
        exception = Dart_NewStringFromCString(Dart_GetError(result));
        return typename Trait::nativeType();
    }
    return value;
}

struct IntegerTrait {
    typedef int64_t nativeType;
    static Dart_Handle convert(Dart_Handle object, int64_t* value)
    {
        return Dart_IntegerToInt64(object, value);
        // FIXME: support bigints.
    }
};

int64_t DartUtilities::toInteger(Dart_Handle object, Dart_Handle& exception)
{
    return convert<IntegerTrait>(object, exception);
}

String DartUtilities::toString(Dart_Handle object)
{
    Dart_Handle exception = 0;
    String string = dartToString(object, exception);
    ASSERT(!exception);
    return string;
}

struct DoubleTrait {
    typedef double nativeType;
    static Dart_Handle convert(Dart_Handle object, double* value)
    {
        if (Dart_IsDouble(object))
            return Dart_DoubleValue(object, value);

        if (Dart_IsInteger(object)) {
            int64_t v = 0;
            Dart_Handle result = Dart_IntegerToInt64(object, &v);
            if (!Dart_IsError(result)) {
                *value = static_cast<double>(v);
                return result;
            }
        }

        if (Dart_IsNumber(object)) {
            object = Dart_Invoke(object, Dart_NewStringFromCString("toDouble"), 0, 0);
            if (Dart_IsError(object))
                return object;
        }

        // For non-Number objects, use the error message returned by Dart_DoubleValue.
        return Dart_DoubleValue(object, value);
    }
};

double DartUtilities::dartToDouble(Dart_Handle object, Dart_Handle& exception)
{
    return convert<DoubleTrait>(object, exception);
}

struct BoolTrait {
    typedef bool nativeType;
    static Dart_Handle convert(Dart_Handle object, bool* value)
    {
        if (Dart_IsNull(object)) {
            *value = false;
            return Dart_Null();
        }
        return Dart_BooleanValue(object, value);
    }
};

bool DartUtilities::dartToBool(Dart_Handle object, Dart_Handle& exception)
{
    return convert<BoolTrait>(object, exception);
}

DartStringAdapter DartUtilities::dartToStringImpl(Dart_Handle object, Dart_Handle& exception, bool autoDartScope)
{
    if (!Dart_IsError(object) && !Dart_IsNull(object)) {
        ASSERT(Dart_IsString(object) && !Dart_IsExternalString(object));
        intptr_t charsize = Dart_IsStringLatin1(object) ? 1 : 2;
        intptr_t strlength;
        Dart_StringLength(object, &strlength);
        if (autoDartScope)
            return DartStringAdapter(toStringImpl(object, charsize, strlength));
        DartApiScope apiScope;
        return DartStringAdapter(toStringImpl(object, charsize, strlength));
    }
    if (!autoDartScope) {
        DartApiScope apiScope;
        DartDOMData* domData = DartDOMData::current();
        Dart_Handle excp = Dart_NewStringFromCString("String expected");
        Dart_SetPersistentHandle(domData->currentException(), excp);
        exception = domData->currentException();
    } else {
        exception = Dart_NewStringFromCString("String expected");
    }
    return DartStringAdapter(DartStringPeer::nullString());
}

void DartUtilities::extractMapElements(Dart_Handle map, Dart_Handle& exception, HashMap<String, Dart_Handle>& elements)
{
    ASSERT(elements.isEmpty());
    Dart_Handle list = DartUtilities::invokeUtilsMethod("convertMapToList", 1, &map);
    if (!DartUtilities::checkResult(list, exception))
        return;
    ASSERT(Dart_IsList(list));

    intptr_t length = 0;
    Dart_ListLength(list, &length);
    ASSERT(length % 2 == 0);

    for (intptr_t i = 0; i < length; i += 2) {
        Dart_Handle key = Dart_ListGetAt(list, i);
        ASSERT(!Dart_IsError(key) && Dart_IsString(key));
        Dart_Handle value = Dart_ListGetAt(list, i+1);
        ASSERT(!Dart_IsError(value));
        String keyString = DartUtilities::dartToString(key, exception);
        if (exception)
            return;
        elements.add(keyString, value);
    }
}

Dart_Handle DartUtilities::toList(const Vector<Dart_Handle>& elements, Dart_Handle& exception)
{
    Dart_Handle ret = Dart_NewList(elements.size());
    if (Dart_IsError(ret)) {
        exception = ret;
        return Dart_Null();
    }
    for (size_t i = 0; i < elements.size(); i++) {
        Dart_ListSetAt(ret, i, elements[i]);
    }
    return ret;
}

void DartUtilities::extractListElements(Dart_Handle list, Dart_Handle& exception, Vector<Dart_Handle>& elements)
{
    ASSERT(elements.isEmpty());
    list = DartUtilities::invokeUtilsMethod("convertToList", 1, &list);
    if (!DartUtilities::checkResult(list, exception))
        return;
    ASSERT(Dart_IsList(list));

    intptr_t length = 0;
    Dart_ListLength(list, &length);
    elements.reserveCapacity(length);
    for (intptr_t i = 0; i < length; i++) {
        Dart_Handle element = Dart_ListGetAt(list, i);
        ASSERT(!Dart_IsError(element));
        elements.append(element);
    }
}

v8::Local<v8::Context> DartUtilities::currentV8Context()
{
    LocalFrame* frame = DartUtilities::domWindowForCurrentIsolate()->frame();
    v8::Local<v8::Context> context = toV8Context(frame, DOMWrapperWorld::mainWorld());
    ASSERT(!context.IsEmpty());
    return context;
}

int DartUtilities::dartToInt(Dart_Handle object, Dart_Handle& exception)
{
    int64_t value = toInteger(object, exception);
    if (exception)
        return 0;
    if (value < INT_MIN || value > INT_MAX) {
        exception = Dart_NewStringFromCString("value out of range");
        return 0;
    }
    return value;
}

unsigned DartUtilities::dartToUnsigned(Dart_Handle object, Dart_Handle& exception)
{
    int64_t value = toInteger(object, exception);
    if (exception)
        return 0;
    if (value < 0 || value > UINT_MAX) {
        exception = Dart_NewStringFromCString("value out of range");
        return 0;
    }
    return value;
}

long long DartUtilities::dartToLongLong(Dart_Handle object, Dart_Handle& exception)
{
    // FIXME: proper processing of longer integer values.
    return toInteger(object, exception);
}

unsigned long long DartUtilities::dartToUnsignedLongLong(Dart_Handle object, Dart_Handle& exception)
{
    // FIXME: proper processing of longer integer values.
    int64_t value = toInteger(object, exception);
    if (exception)
        return 0;
    if (value < 0) {
        exception = Dart_NewStringFromCString("value out of range");
        return 0;
    }
    return value;
}

// TODO(terry): Copied from V8Binding.cpp (private member in V8).
const int64_t kJSMaxInteger = 0x20000000000000LL - 1; // 2^53 - 1, maximum uniquely representable integer in ECMAScript.
const int64_t maxJSInteger = kJSMaxInteger;
const int64_t minJSInteger = -kJSMaxInteger;

Dart_Handle DartUtilities::numberToDart(double value)
{
    // JS can store integer values that are no greater than 2^53 - 1.
    // TODO(terry): Need to call V8Binding's toInt64 however, we need an isolate
    if (minJSInteger <= value && value <= maxJSInteger) {
        int64_t intValue = static_cast<int64_t>(value);
        if (value == intValue)
            return intToDart(intValue);
    }
    return doubleToDart(value);
}

ScriptValue DartUtilities::dartToScriptValue(Dart_Handle object)
{
    // TODO(terry): Added bug per JacobR - he thinks it would be better to use
    //              DartHandleProxy probably pressing pause crashes Dartium 45.
    //              See issue: https://github.com/dart-lang/sdk/issues/25589
    Dart_Handle exception = 0;
    ScriptState* v8ScriptState = currentDartScriptState()->v8ScriptState();
    v8::Handle<v8::Value> value = V8Converter::toV8(object, exception);
    if (exception)
        return ScriptValue(v8ScriptState, v8::Undefined(v8ScriptState->isolate()));
    ASSERT(!value.IsEmpty());

    return ScriptValue(v8ScriptState, value);
}

PassRefPtr<SerializedScriptValue> DartUtilities::toSerializedScriptValue(Dart_Handle value, MessagePortArray* ports, ArrayBufferArray* arrayBuffers, Dart_Handle& exception)
{
    v8::Handle<v8::Value> v8Value = V8Converter::toV8(value, exception);
    if (exception)
        return nullptr;

    TrackExceptionState exceptionState;
    RefPtr<SerializedScriptValue> message = SerializedScriptValueFactory::instance().create(v8::Isolate::GetCurrent(), v8Value, ports, arrayBuffers, exceptionState);
    if (exceptionState.hadException()) {
        // FIXME: better exception here. We should match the exception v8 would throw.
        exception = Dart_NewStringFromCString("Failed to create SerializedScriptValue");
        return nullptr;
    }

    return message.release();
}

Dart_Handle DartUtilities::dateToDart(double date)
{
    Dart_Handle asDouble = DartUtilities::doubleToDart(date);
    ASSERT(!Dart_IsError(asDouble));
    return DartUtilities::invokeUtilsMethod("doubleToDateTime", 1, &asDouble);
}

double DartUtilities::dartToDate(Dart_Handle date, Dart_Handle& exception)
{
    Dart_Handle asDouble = DartUtilities::invokeUtilsMethod("dateTimeToDouble", 1, &date);
    if (!DartUtilities::checkResult(asDouble, exception))
        return 0.0;

    return DartUtilities::dartToDouble(asDouble, exception);
}

double DartUtilities::dartToDate(Dart_NativeArguments args, int idx, Dart_Handle& exception)
{
    Dart_Handle object = Dart_GetNativeArgument(args, idx);
    return dartToDate(object, exception);
}

bool DartUtilities::isDateTime(DartDOMData* domData, Dart_Handle handle)
{
    Dart_Handle dartType = DartUtilities::getDartType("dart:core", "DateTime");
    return objectIsType(handle, dartType);
}

bool DartUtilities::objectIsType(Dart_Handle handle, Dart_Handle type)
{
    bool isType = false;
    Dart_Handle result = Dart_ObjectIsType(handle, type, &isType);
    if (Dart_IsError(result))
        return false;
    return isType;
}

bool DartUtilities::isTypeSubclassOf(Dart_Handle type, Dart_Handle library, const char* typeName)
{
    Dart_Handle other = Dart_GetType(library, Dart_NewStringFromCString(typeName), 0, 0);
    ASSERT(!Dart_IsError(other));

    Dart_Handle args[2] = { type, other };
    Dart_Handle result = DartUtilities::invokeUtilsMethod("isTypeSubclassOf", 2, args);
    if (Dart_IsError(result)) {
        ASSERT_NOT_REACHED();
        return false;
    }

    Dart_Handle exception = 0;
    bool boolResult = dartToBool(result, exception);
    if (exception)
        return false;
    return boolResult;
}

Dart_Handle DartUtilities::getAndValidateNativeType(Dart_Handle type, const String& tagName)
{
    Dart_Handle args[2] = { type, stringToDartString(tagName) };
    Dart_Handle result = DartUtilities::invokeUtilsMethod("getAndValidateNativeType", 2, args);
    ASSERT(!Dart_IsError(result));
    if (Dart_IsError(result)) {
        ASSERT_NOT_REACHED();
        return Dart_Null();
    }
    return result;
}

bool DartUtilities::isFunction(DartDOMData* domData, Dart_Handle handle)
{
    return DartUtilities::objectIsType(handle, domData->functionType());
}

Dart_Handle DartUtilities::getDartType(const char* libraryName, const char* typeName)
{
    Dart_Handle library = Dart_LookupLibrary(Dart_NewStringFromCString(libraryName));
    ASSERT(!Dart_IsError(library));

    Dart_Handle dartType = Dart_GetType(library, Dart_NewStringFromCString(typeName), 0, 0);
    ASSERT(!Dart_IsError(dartType));

    return dartType;
}

Dart_Handle DartUtilities::getDartHtmlType(const char* typeName)
{
    Dart_Handle dartType = Dart_GetType(DartDOMData::current()->htmlLibrary(),
        Dart_NewStringFromCString(typeName), 0, 0);
    ASSERT(!Dart_IsError(dartType));

    return dartType;
}

bool DartUtilities::isNode(Dart_Handle handle)
{
    Dart_Handle dartType = DartUtilities::getDartHtmlType("Node");
    if (!objectIsType(handle, dartType)) {
        return false;
    }
    // Some dart:html Node instances may not really be Node objects.
    Dart_Handle exception = 0;
    v8::Handle<v8::Value> v8Node = JsInterop::fromDart(DartDOMData::current(), handle, exception);
    if (exception) {
        return false;
    }
    return V8Node::hasInstance(v8Node, v8::Isolate::GetCurrent());
}

Node* DartUtilities::dartNodeToNativeNode(Dart_Handle handle)
{
    Dart_Handle exception = 0;
    v8::Handle<v8::Value> v8Node = JsInterop::fromDart(DartDOMData::current(), handle, exception);
    ASSERT(!exception);
    ASSERT(V8Node::hasInstance(v8Node, v8::Isolate::GetCurrent()));
    Node* node = V8Node::toImpl(v8Node.As<v8::Object>());
    return node;
}

bool DartUtilities::isMessagePort(Dart_Handle handle)
{
    Dart_Handle dartType = DartUtilities::getDartHtmlType("MessagePort");
    return objectIsType(handle, dartType);
}

MessagePort* DartUtilities::dartMessagePortToNativeMessagePort(void* value)
{
    return static_cast<MessagePort*>(value);
}

static Dart_TypedData_Type typedDataTypeFromViewType(ArrayBufferView::ViewType type)
{
    switch (type) {
    case ArrayBufferView::TypeInt8:
        return Dart_TypedData_kInt8;
    case ArrayBufferView::TypeUint8:
        return Dart_TypedData_kUint8;
    case ArrayBufferView::TypeUint8Clamped:
        return Dart_TypedData_kUint8Clamped;
    case ArrayBufferView::TypeInt16:
        return Dart_TypedData_kInt16;
    case ArrayBufferView::TypeUint16:
        return Dart_TypedData_kUint16;
    case ArrayBufferView::TypeInt32:
        return Dart_TypedData_kInt32;
    case ArrayBufferView::TypeUint32:
        return Dart_TypedData_kUint32;
    case ArrayBufferView::TypeFloat32:
        return Dart_TypedData_kFloat32;
    case ArrayBufferView::TypeFloat64:
        return Dart_TypedData_kFloat64;
    case ArrayBufferView::TypeDataView:
        return Dart_TypedData_kByteData;
    }
    ASSERT_NOT_REACHED();
    return Dart_TypedData_kInvalid;
}

static unsigned elementSizeFromViewType(Dart_TypedData_Type type)
{
    switch (type) {
    case Dart_TypedData_kByteData:
        return sizeof(uint8_t);
    case Dart_TypedData_kInt8:
        return sizeof(int8_t);
    case Dart_TypedData_kUint8:
        return sizeof(uint8_t);
    case Dart_TypedData_kUint8Clamped:
        return sizeof(uint8_t);
    case Dart_TypedData_kInt16:
        return sizeof(int16_t);
    case Dart_TypedData_kUint16:
        return sizeof(uint16_t);
    case Dart_TypedData_kInt32:
        return sizeof(int32_t);
    case Dart_TypedData_kUint32:
        return sizeof(uint32_t);
    case Dart_TypedData_kFloat32:
        return sizeof(float);
    case Dart_TypedData_kFloat64:
        return sizeof(double);
    case Dart_TypedData_kFloat32x4:
        return 4 * sizeof(float);
    default:
        break;
    }
    ASSERT_NOT_REACHED();
    return 0;
}

static unsigned elementSizeFromViewType(ArrayBufferView::ViewType type)
{
    return elementSizeFromViewType(typedDataTypeFromViewType(type));
}

class TypedDataPeer {
public:
    virtual ~TypedDataPeer() { };
    virtual bool isViewPeer() = 0;
};

class TypedBufferPeer : public TypedDataPeer {
public:
    TypedBufferPeer(PassRefPtr<ArrayBuffer> buffer) : m_buffer(buffer) { }
    virtual ~TypedBufferPeer() { }

    PassRefPtr<ArrayBuffer> buffer()
    {
        return m_buffer;
    }

    virtual bool isViewPeer()
    {
        return false;
    }

private:
    RefPtr<ArrayBuffer> m_buffer;
};

class TypedViewPeer : public TypedDataPeer {
public:
    TypedViewPeer(PassRefPtr<ArrayBufferView> view) : m_view(view) { }
    virtual ~TypedViewPeer() { }

    PassRefPtr<ArrayBufferView> view()
    {
        return m_view;
    }

    virtual bool isViewPeer()
    {
        return true;
    }

private:
    RefPtr<ArrayBufferView> m_view;
};

static void externalArrayBufferCallback(void* isolateCallbackData, Dart_WeakPersistentHandle handle, void* peer)
{
    delete reinterpret_cast<TypedDataPeer*>(peer);
}

static Dart_Handle createExternalTypedData(Dart_TypedData_Type type, void* data, intptr_t numberOfElements, TypedDataPeer* peer, intptr_t peerSize, Dart_WeakPersistentHandleFinalizer callback)
{
    Dart_Handle newInstance = Dart_NewExternalTypedData(type, data, numberOfElements);
    Dart_Handle result = Dart_SetPeer(newInstance, peer);
    if (Dart_IsError(result))
        return result;
    Dart_NewWeakPersistentHandle(newInstance, peer, peerSize, callback);
    return newInstance;
}

Dart_Handle DartUtilities::arrayBufferToDart(WTF::ArrayBuffer* buffer)
{
    void* data = buffer->data();
    unsigned byteLength = buffer->byteLength();
    TypedBufferPeer* peer = new TypedBufferPeer(buffer);
    Dart_Handle typedData =  createExternalTypedData(Dart_TypedData_kUint8, data, byteLength, peer, byteLength, externalArrayBufferCallback);
    ASSERT(!Dart_IsError(typedData));
    return Dart_NewByteBuffer(typedData);
}

static bool externalTypedDataGetPeer(Dart_Handle handle, void** peer)
{
    *peer = 0;
    Dart_Handle getPeerResult = Dart_GetPeer(handle, peer);
    if (!Dart_IsError(getPeerResult) && *peer) {
        return true;
    }
    return false;
}

static PassRefPtr<WTF::ArrayBuffer> dartToArrayBufferHelper(Dart_Handle array, Dart_Handle& exception, bool externalize)
{
    void* data = 0;

    // If a ByteBuffer is passed in extract the typed data first.
    if (Dart_IsByteBuffer(array)) {
        array = Dart_GetDataFromByteBuffer(array);
    }

    // Check if the Dart array buffer object is external and has an
    // ArrayBuffer peer.
    if (externalTypedDataGetPeer(array, &data) && !reinterpret_cast<TypedDataPeer*>(data)->isViewPeer()) {
        return reinterpret_cast<TypedBufferPeer*>(data)->buffer();
    }

    Dart_TypedData_Type type;
    intptr_t elementLength = 0;
    intptr_t byteLength = 0;

    // Check if the Dart object is a typed data object by acquiring its data.
    // If it is, create a thin ArrayBuffer wrapper around the data in the dart
    // heap.
    Dart_Handle result = Dart_TypedDataAcquireData(array, &type, &data, &elementLength);
    if (Dart_IsError(result)) {
        exception = Dart_NewStringFromCString("Typed data object expected");
        return nullptr;
    }
    // FIXME: we really shouldn't release the data until we are done with it.
    Dart_TypedDataReleaseData(array);
    byteLength = elementLength * elementSizeFromViewType(type);
    return externalize ? ArrayBuffer::create(data, byteLength) : ArrayBuffer::createNoCopy(data, byteLength);
}

PassRefPtr<WTF::ArrayBuffer> DartUtilities::dartToArrayBuffer(Dart_Handle array, Dart_Handle& exception)
{
    return dartToArrayBufferHelper(array, exception, false);
}

PassRefPtr<WTF::ArrayBuffer> DartUtilities::dartToExternalizedArrayBuffer(Dart_Handle array, Dart_Handle& exception)
{
    return dartToArrayBufferHelper(array, exception, true);
}

// FIXME: This mapping to dart objects loses object identity for
// the buffer part of views. If we have two views on the same buffer
// in C++ and we create dart wrappers we will get two different dart
// buffer objects. Additionally, this means that neutering will not work.
Dart_Handle DartUtilities::arrayBufferViewToDart(WTF::ArrayBufferView* view)
{
    ArrayBufferView::ViewType type = view->type();
    void* address = view->baseAddress();
    unsigned byteLength = view->byteLength();
    unsigned length = byteLength / elementSizeFromViewType(type);
    TypedViewPeer* peer = new TypedViewPeer(view);
    return createExternalTypedData(typedDataTypeFromViewType(type), address, length, peer, byteLength, externalArrayBufferCallback);
}


// FIXME: Again, this breaks the view-buffer relationship.
static PassRefPtr<WTF::ArrayBufferView> dartToArrayBufferViewHelper(Dart_Handle array, Dart_Handle& exception, bool externalize)
{
    void* data = 0;

    // Check if the array is external and has an ArrayBufferView peer.
    if (externalTypedDataGetPeer(array, &data)) {
        if (!reinterpret_cast<TypedDataPeer*>(data)->isViewPeer()) {
            exception = Dart_NewStringFromCString("Typed data view expected");
            return nullptr;
        }
        return reinterpret_cast<TypedViewPeer*>(data)->view();
    }

    // Check if the dart object is an internal typed data object and get
    // the data from it.
    Dart_TypedData_Type type;
    intptr_t elementLength = 0;
    Dart_Handle result = Dart_TypedDataAcquireData(array, &type, &data, &elementLength);
    if (Dart_IsError(result)) {
        exception = Dart_NewStringFromCString("Typed data object expected");
        return nullptr;
    }
    intptr_t byteLength = elementLength * elementSizeFromViewType(type);
    // FIXME: we really shouldn't release the data until we are done with it.
    Dart_TypedDataReleaseData(array);
    RefPtr<DOMArrayBuffer> buffer = externalize ? DOMArrayBuffer::create(data, byteLength) : DOMArrayBuffer::createNoCopy(data, byteLength);

    switch (type) {
    case Dart_TypedData_kByteData:
        return DOMDataView::create(buffer, 0, elementLength)->view();
    case Dart_TypedData_kInt8:
        return Int8Array::create(buffer->buffer(), 0, elementLength);
    case Dart_TypedData_kUint8:
        return Uint8Array::create(buffer->buffer(), 0, elementLength);
    case Dart_TypedData_kUint8Clamped:
        return Uint8ClampedArray::create(buffer->buffer(), 0, elementLength);
    case Dart_TypedData_kInt16:
        return Uint16Array::create(buffer->buffer(), 0, elementLength);
    case Dart_TypedData_kUint16:
        return Uint16Array::create(buffer->buffer(), 0, elementLength);
    case Dart_TypedData_kInt32:
        return Int32Array::create(buffer->buffer(), 0, elementLength);
    case Dart_TypedData_kUint32:
        return Uint32Array::create(buffer->buffer(), 0, elementLength);
    case Dart_TypedData_kFloat32:
        return Float32Array::create(buffer->buffer(), 0, elementLength);
    case Dart_TypedData_kFloat64:
        return Float64Array::create(buffer->buffer(), 0, elementLength);
    case Dart_TypedData_kFloat32x4:
        return Float32Array::create(buffer->buffer(), 0, elementLength * sizeof(float));
    default:
        break;
    }
    ASSERT_NOT_REACHED();
    return nullptr;
}

PassRefPtr<WTF::ArrayBufferView> DartUtilities::dartToArrayBufferView(Dart_Handle array, Dart_Handle& exception)
{
    return dartToArrayBufferViewHelper(array, exception, false);
}

PassRefPtr<WTF::ArrayBufferView> DartUtilities::dartToExternalizedArrayBufferView(Dart_Handle array, Dart_Handle& exception)
{
    return dartToArrayBufferViewHelper(array, exception, true);
}

PassRefPtr<WTF::Int8Array> DartUtilities::dartToInt8ArrayWithNullCheck(Dart_Handle handle, Dart_Handle& exception)
{
    return Dart_IsNull(handle) ? nullptr : dartToInt8Array(handle, exception);
}

PassRefPtr<WTF::Int8Array> DartUtilities::dartToInt8Array(Dart_Handle handle, Dart_Handle& exception)
{
    RefPtr<ArrayBufferView> view = DartUtilities::dartToArrayBufferView(handle, exception);
    if (exception)
        return nullptr;
    if (view->type() == ArrayBufferView::TypeInt8)
        return reinterpret_cast<Int8Array*>(view.get());
    exception = Dart_NewStringFromCString("Int8List expected");
    return nullptr;
}

PassRefPtr<WTF::Int8Array> DartUtilities::dartToInt8ArrayWithNullCheck(Dart_NativeArguments args, int idx, Dart_Handle& exception)
{
    Dart_Handle object = Dart_GetNativeArgument(args, idx);
    return dartToInt8ArrayWithNullCheck(object, exception);
}

PassRefPtr<WTF::Int8Array> DartUtilities::dartToInt8Array(Dart_NativeArguments args, int idx, Dart_Handle& exception)
{
    Dart_Handle object = Dart_GetNativeArgument(args, idx);
    return dartToInt8Array(object, exception);
}

PassRefPtr<WTF::Int32Array> DartUtilities::dartToInt32ArrayWithNullCheck(Dart_Handle handle, Dart_Handle& exception)
{
    return Dart_IsNull(handle) ? nullptr : dartToInt32Array(handle, exception);
}

PassRefPtr<WTF::Int32Array> DartUtilities::dartToInt32Array(Dart_Handle handle, Dart_Handle& exception)
{
    RefPtr<ArrayBufferView> view = DartUtilities::dartToArrayBufferView(handle, exception);
    if (exception)
        return nullptr;
    if (view->type() == ArrayBufferView::TypeInt32)
        return reinterpret_cast<Int32Array*>(view.get());
    exception = Dart_NewStringFromCString("Int32List expected");
    return nullptr;
}

PassRefPtr<WTF::Int32Array> DartUtilities::dartToInt32ArrayWithNullCheck(Dart_NativeArguments args, int idx, Dart_Handle& exception)
{
    Dart_Handle object = Dart_GetNativeArgument(args, idx);
    return dartToInt32ArrayWithNullCheck(object, exception);
}

PassRefPtr<WTF::Int32Array> DartUtilities::dartToInt32Array(Dart_NativeArguments args, int idx, Dart_Handle& exception)
{
    Dart_Handle object = Dart_GetNativeArgument(args, idx);
    return dartToInt32Array(object, exception);
}

PassRefPtr<WTF::Uint8ClampedArray> DartUtilities::dartToUint8ClampedArrayWithNullCheck(Dart_Handle handle, Dart_Handle& exception)
{
    return Dart_IsNull(handle) ? nullptr : dartToUint8ClampedArray(handle, exception);
}

PassRefPtr<WTF::Uint8ClampedArray> DartUtilities::dartToUint8ClampedArray(Dart_Handle handle, Dart_Handle& exception)
{
    RefPtr<ArrayBufferView> view = DartUtilities::dartToArrayBufferView(handle, exception);
    if (exception)
        return nullptr;
    if (view->type() == ArrayBufferView::TypeUint8Clamped)
        return reinterpret_cast<Uint8ClampedArray*>(view.get());
    exception = Dart_NewStringFromCString("Uint8ClampedList expected");
    return nullptr;
}

PassRefPtr<WTF::Uint8ClampedArray> DartUtilities::dartToUint8ClampedArrayWithNullCheck(Dart_NativeArguments args, int idx, Dart_Handle& exception)
{
    Dart_Handle object = Dart_GetNativeArgument(args, idx);
    return dartToUint8ClampedArrayWithNullCheck(object, exception);
}

PassRefPtr<WTF::Uint8ClampedArray> DartUtilities::dartToUint8ClampedArray(Dart_NativeArguments args, int idx, Dart_Handle& exception)
{
    Dart_Handle object = Dart_GetNativeArgument(args, idx);
    return dartToUint8ClampedArray(object, exception);
}

PassRefPtr<WTF::Uint8Array> DartUtilities::dartToUint8ArrayWithNullCheck(Dart_Handle handle, Dart_Handle& exception)
{
    return Dart_IsNull(handle) ? nullptr : dartToUint8Array(handle, exception);
}

PassRefPtr<WTF::Uint8Array> DartUtilities::dartToUint8Array(Dart_Handle handle, Dart_Handle& exception)
{
    RefPtr<ArrayBufferView> view = DartUtilities::dartToArrayBufferView(handle, exception);
    if (exception)
        return nullptr;
    if (view->type() == ArrayBufferView::TypeUint8)
        return reinterpret_cast<Uint8Array*>(view.get());
    exception = Dart_NewStringFromCString("Uint8List expected");
    return nullptr;
}

PassRefPtr<WTF::Uint8Array> DartUtilities::dartToUint8ArrayWithNullCheck(Dart_NativeArguments args, int idx, Dart_Handle& exception)
{
    Dart_Handle object = Dart_GetNativeArgument(args, idx);
    return dartToUint8ArrayWithNullCheck(object, exception);
}

PassRefPtr<WTF::Uint8Array> DartUtilities::dartToUint8Array(Dart_NativeArguments args, int idx, Dart_Handle& exception)
{
    Dart_Handle object = Dart_GetNativeArgument(args, idx);
    return dartToUint8Array(object, exception);
}

PassRefPtr<WTF::Float32Array> DartUtilities::dartToFloat32ArrayWithNullCheck(Dart_Handle handle, Dart_Handle& exception)
{
    return Dart_IsNull(handle) ? nullptr : dartToFloat32Array(handle, exception);
}

PassRefPtr<WTF::Float32Array> DartUtilities::dartToFloat32Array(Dart_Handle handle, Dart_Handle& exception)
{
    RefPtr<ArrayBufferView> view = DartUtilities::dartToArrayBufferView(handle, exception);
    if (exception)
        return nullptr;
    if (view->type() == ArrayBufferView::TypeFloat32)
        return reinterpret_cast<Float32Array*>(view.get());
    exception = Dart_NewStringFromCString("Float32List expected");
    return nullptr;
}

PassRefPtr<WTF::Float32Array> DartUtilities::dartToFloat32ArrayWithNullCheck(Dart_NativeArguments args, int idx, Dart_Handle& exception)
{
    Dart_Handle object = Dart_GetNativeArgument(args, idx);
    return dartToFloat32ArrayWithNullCheck(object, exception);
}

PassRefPtr<WTF::Float32Array> DartUtilities::dartToFloat32Array(Dart_NativeArguments args, int idx, Dart_Handle& exception)
{
    Dart_Handle object = Dart_GetNativeArgument(args, idx);
    return dartToFloat32Array(object, exception);
}

bool DartUtilities::isUint8Array(Dart_Handle object)
{
    return Dart_GetTypeOfTypedData(object) == Dart_TypedData_kUint8;
}

bool DartUtilities::isUint8ClampedArray(Dart_Handle object)
{
    return Dart_GetTypeOfTypedData(object) == Dart_TypedData_kUint8Clamped;
}

SQLValue DartUtilities::toSQLValue(Dart_Handle object, Dart_Handle& exception)
{
    if (Dart_IsNull(object))
        return SQLValue();

    if (Dart_IsNumber(object))
        return SQLValue(DartUtilities::dartToDouble(object, exception));

    return SQLValue(DartUtilities::dartToString(object, exception));
}

PassRefPtr<SerializedScriptValue> DartUtilities::dartToSerializedScriptValue(Dart_Handle object, Dart_Handle& exception)
{
    return toSerializedScriptValue(object, 0, 0, exception);
}

Dart_Handle DartUtilities::serializedScriptValueToDart(PassRefPtr<SerializedScriptValue> value)
{
    // FIXME: better error handling.
    Dart_Handle exception = 0;
    return V8Converter::toDart(value->deserialize(), exception);
}

// FIXME: this function requires better testing. Currently blocking as new MessageChannel hasn't been implemented yet.
void DartUtilities::toMessagePortArray(Dart_Handle value, MessagePortArray& ports, ArrayBufferArray& arrayBuffers, Dart_Handle& exception)
{
    Vector<Dart_Handle> elements;
    DartUtilities::extractListElements(value, exception, elements);
    if (exception)
        return;

    for (size_t i = 0; i < elements.size(); i++) {
        Dart_Handle element = elements[i];
        if (DartUtilities::isMessagePort(element)) {
            MessagePort* messagePort = DartUtilities::dartMessagePortToNativeMessagePort(element);
            ASSERT(messagePort);
            ports.append(messagePort);
            continue;
        }

        if (Dart_IsByteBuffer(element)) {
/* TODO(terry): Comment out to build 45 Roll - fix/review.
            element = Dart_GetDataFromByteBuffer(element);
            RefPtr<ArrayBuffer> arrayBuffer = DartUtilities::dartToExternalizedArrayBuffer(element, exception);
            ASSERT(!exception);
            ASSERT(arrayBuffer);
            arrayBuffers.append(arrayBuffer);
            continue;
*/
        }

        exception = Dart_NewStringFromCString("TransferArray argument must contain only Transferables");
        return;
    }
}

LocalDOMWindow* DartUtilities::domWindowForCurrentIsolate()
{
    DartDOMData* domData = DartDOMData::current();
    ASSERT(domData->scriptExecutionContext()->isDocument());
    Document* document = static_cast<Document*>(domData->scriptExecutionContext());
    return document->domWindow();
}

ScriptState* DartUtilities::v8ScriptStateForCurrentIsolate()
{
    return ScriptState::forMainWorld(domWindowForCurrentIsolate()->frame());
}

ExecutionContext* DartUtilities::scriptExecutionContext()
{
    if (Dart_CurrentIsolate())
        return DartDOMData::current()->scriptExecutionContext();
    return 0;
}

bool DartUtilities::processingUserGesture()
{
    // FIXME: implement this.
    return false;
}

intptr_t DartUtilities::libraryHandleToLibraryId(Dart_Handle library)
{
    intptr_t libraryId = -1;
    Dart_Handle result = Dart_LibraryId(library, &libraryId);
    ALLOW_UNUSED_LOCAL(result);
    ASSERT(!Dart_IsError(result));
    return libraryId;
}

DartScriptState* DartUtilities::currentDartScriptState()
{
    DartDOMData* dartDOMData = DartDOMData::current();
    if (!dartDOMData->rootScriptState()) {
        DartController* controller = DartController::retrieve(dartDOMData->scriptExecutionContext());
        intptr_t libraryId = DartUtilities::libraryHandleToLibraryId(Dart_RootLibrary());
        DartScriptState* scriptState = controller->lookupScriptState(Dart_CurrentIsolate(), currentV8Context(), libraryId);
        dartDOMData->setRootScriptState(scriptState);
        return scriptState;
    }
    return dartDOMData->rootScriptState();
}

static PassRefPtr<ScriptCallStack> createScriptCallStackFromStackTrace(Dart_StackTrace stackTrace)
{
    uintptr_t frameCount = 0;
    Dart_Handle result = Dart_StackTraceLength(stackTrace, reinterpret_cast<intptr_t*>(&frameCount));
    if (Dart_IsError(result))
        return nullptr;

    if (frameCount > ScriptCallStack::maxCallStackSizeToCapture)
        frameCount = ScriptCallStack::maxCallStackSizeToCapture;

    Dart_Isolate isolate = Dart_CurrentIsolate();
    Vector<ScriptCallFrame> scriptCallStackFrames;
    for (uintptr_t frameIndex = 0; frameIndex < frameCount; frameIndex++) {
        Dart_ActivationFrame frame = 0;
        result = Dart_GetActivationFrame(stackTrace, frameIndex, &frame);
        if (Dart_IsError(result)) {
            return nullptr;
        }
        ASSERT(frame);

        Dart_Handle dartFunctionName;
        Dart_Handle dartScriptUrl;
        intptr_t lineNumber = 0;
        intptr_t columnNumber = 0;
        result = Dart_ActivationFrameInfo(frame, &dartFunctionName, &dartScriptUrl, &lineNumber, &columnNumber);
        if (Dart_IsError(result)) {
            return nullptr;
        }

        // This skips frames where source is unavailable. WebKit code for the
        // console assumes that console.log et al. are implemented directly
        // as natives, i.e. that the top-of-stack will be the caller of
        // console.log. The Dart implementation involves intermediate Dart
        // calls, which are skipped by this clause.
        if (columnNumber == -1)
            continue;

        String functionName = DartUtilities::toString(dartFunctionName);
        String scriptUrl = DartUtilities::toString(dartScriptUrl);

        scriptCallStackFrames.append(ScriptCallFrame(functionName, DartScriptDebugServer::shared().getScriptId(scriptUrl, isolate), scriptUrl, lineNumber, columnNumber));
    }
    if (scriptCallStackFrames.isEmpty())
        scriptCallStackFrames.append(ScriptCallFrame("undefined", "undefined", "undefined", 0, 0));

    return ScriptCallStack::create(scriptCallStackFrames);
}

ScriptCallFrame DartUtilities::getTopFrame(Dart_StackTrace stackTrace, Dart_Handle& exception)
{
    {
        uintptr_t frameCount = 0;
        Dart_Handle result = Dart_StackTraceLength(stackTrace, reinterpret_cast<intptr_t*>(&frameCount));
        if (Dart_IsError(result)) {
            exception = result;
            goto fail;
        }
        if (!frameCount) {
            exception = Dart_NewStringFromCString("Empty stack trace");
            goto fail;
        }
        Dart_ActivationFrame frame = 0;
        result = Dart_GetActivationFrame(stackTrace, 0, &frame);
        if (Dart_IsError(result)) {
            exception = result;
            goto fail;
        }
        ASSERT(frame);
        return toScriptCallFrame(frame, exception);
    }
fail:
    return ScriptCallFrame("undefined", "undefined", "undefined", 0, 0);
}

ScriptCallFrame DartUtilities::toScriptCallFrame(Dart_ActivationFrame frame, Dart_Handle& exception)
{
    ASSERT(frame);
    Dart_Handle functionName;
    Dart_Handle scriptUrl;
    intptr_t lineNumber = 0;
    intptr_t columnNumber = 0;
    Dart_Handle result = Dart_ActivationFrameInfo(frame, &functionName, &scriptUrl, &lineNumber, &columnNumber);
    if (Dart_IsError(result)) {
        exception = result;
        return ScriptCallFrame("undefined", "undefined", "undefined", 0, 0);
    }
    return ScriptCallFrame(DartUtilities::toString(functionName), "undefined", DartUtilities::toString(scriptUrl), lineNumber, columnNumber);
}

PassRefPtr<ScriptCallStack> DartUtilities::createScriptCallStack()
{
    Dart_StackTrace trace = 0;
    Dart_Handle result = Dart_GetStackTrace(&trace);
    ALLOW_UNUSED_LOCAL(result);
    ASSERT(!Dart_IsError(result));
    ASSERT(!Dart_IsNull(result));
    ASSERT(trace);
    return createScriptCallStackFromStackTrace(trace);
}

static const uint8_t* snapshotBuffer(int index)
{
// DartSnapshot.bytes is generated by build system.
#include "bindings/dart/DartSnapshot.bytes"
    ASSERT(index == DartUtilities::VmIsolateSnapshotId || index == DartUtilities::IsolateSnapshotId);
    if (index == DartUtilities::VmIsolateSnapshotId) {
        return vmIsolateSnapshotBuffer;
    }
    return isolateSnapshotBuffer;
}

const uint8_t* DartUtilities::vmIsolateSnapshot()
{
    return snapshotBuffer(VmIsolateSnapshotId);
}

const uint8_t* DartUtilities::isolateSnapshot()
{
    return snapshotBuffer(IsolateSnapshotId);
}

Dart_Handle DartUtilities::canonicalizeUrl(Dart_Handle library, Dart_Handle urlHandle, String url)
{
    DEFINE_STATIC_LOCAL(String, dartPrefix, ("dart:"));
    DEFINE_STATIC_LOCAL(String, packagePrefix, ("package:"));

    if (url.startsWith(dartPrefix) || url.startsWith(packagePrefix))
        // Not a relative URL.
        return urlHandle;

    Dart_Handle libraryURLHandle = Dart_LibraryUrl(library);
    ASSERT(!Dart_IsError(libraryURLHandle));
    String libraryURL = DartUtilities::toString(libraryURLHandle);

    String result;
    if (libraryURL.startsWith(packagePrefix) && !libraryURL.startsWith("package://")) {
        // KURL expects a URL with an authority. If the library URL is
        // "package:<path>", we convert to "package://_/<path>" for resolution
        // and convert back.
        DEFINE_STATIC_LOCAL(String, resolvePrefix, ("package://_/"));

        libraryURL = resolvePrefix + libraryURL.substring(packagePrefix.length());
        result = KURL(KURL(KURL(), libraryURL), url).string();
        if (result.startsWith(resolvePrefix))
            result = packagePrefix + result.substring(resolvePrefix.length());
    } else {
        result = KURL(KURL(KURL(), libraryURL), url).string();
    }

    return DartUtilities::stringToDartString(result);
}

void DartUtilities::reportProblem(ExecutionContext* context, const String& error, int line, int col)
{
    String sourceURL = context->url().string();

    // FIXME: Pass in stack trace.
    if (context && context->isDocument()) {
        int scriptId = 0;
        static_cast<Document*>(context)->reportException(ErrorEvent::create(error, sourceURL, line, col, 0), scriptId, nullptr, NotSharableCrossOrigin);
    }
}

void DartUtilities::reportProblem(ExecutionContext* context, Dart_Handle result)
{
    // FIXME: provide sourceURL.
    String sourceURL = "FIXME";
    reportProblem(context, result, sourceURL);
}

void DartUtilities::reportProblem(ExecutionContext* context, Dart_Handle result, const String& sourceURL)
{
    ASSERT(Dart_IsError(result));
    ASSERT(!sourceURL.isEmpty());

    const String internalErrorPrefix("Internal error: ");

    String errorMessage;
    // FIXME: line number info.
    int lineNumber = 0;
    // FIXME: call stack info.
    RefPtr<ScriptCallStack> callStack;

    if (!Dart_ErrorHasException(result)) {
        errorMessage = internalErrorPrefix + Dart_GetError(result);
    } else {
        // Print the exception.
        Dart_Handle exception = Dart_ErrorGetException(result);
        ASSERT(!Dart_IsError(exception));

        exception = Dart_ToString(exception);
        if (Dart_IsError(exception))
            errorMessage = String("Error: ") + Dart_GetError(exception);
        else
            errorMessage = String("Exception: ") + DartUtilities::toString(exception);

        // Print the stack trace.
        Dart_StackTrace stacktrace;
        Dart_Handle traceResult = Dart_GetStackTraceFromError(result, &stacktrace);
        ALLOW_UNUSED_LOCAL(traceResult);
        ASSERT(!Dart_IsError(traceResult));
        callStack = createScriptCallStackFromStackTrace(stacktrace);
    }

    if (context && context->isDocument()) {
        int scriptId = 0;
        static_cast<Document*>(context)->reportException(ErrorEvent::create(errorMessage, sourceURL, lineNumber, 0, 0), scriptId, callStack, NotSharableCrossOrigin);
    }
}

Dart_Handle DartUtilities::toDartCoreException(const String& className, const String& message)
{
    DartApiScope apiScope;
    DartDOMData* domData = DartDOMData::current();
    Dart_Handle coreLib = Dart_LookupLibrary(Dart_NewStringFromCString("dart:core"));
    Dart_Handle errorClass = Dart_GetType(coreLib, stringToDart(className), 0, 0);
    Dart_Handle dartMessage = stringToDart(message);
    Dart_Handle error = Dart_New(errorClass, Dart_NewStringFromCString(""), 1, &dartMessage);
    Dart_SetPersistentHandle(domData->currentException(), error);
    return domData->currentException();
}

Dart_Handle DartUtilities::coreArgumentErrorException(const String& message)
{
    return DartUtilities::toDartCoreException("ArgumentError", message);
}

Dart_Handle DartUtilities::notImplementedException(const char* fileName, int lineNumber)
{
    Dart_Handle args[2] = { Dart_NewStringFromCString(fileName), Dart_NewInteger(lineNumber) };
    Dart_Handle result = DartUtilities::invokeUtilsMethod("makeUnimplementedError", 2, args);
    ASSERT(!Dart_IsError(result));
    return result;
}

Dart_Handle DartUtilities::newResolvedPromise(Dart_Handle value)
{
    Dart_Handle asyncLib = Dart_LookupLibrary(Dart_NewStringFromCString("dart:async"));
    Dart_Handle futureClass = Dart_GetType(asyncLib, Dart_NewStringFromCString("Future"), 0, 0);
    return Dart_New(futureClass, Dart_NewStringFromCString("value"), 1, &value);
}

Dart_Handle DartUtilities::newSmashedPromise(Dart_Handle error)
{
    Dart_Handle asyncLib = Dart_LookupLibrary(Dart_NewStringFromCString("dart:async"));
    Dart_Handle futureClass = Dart_GetType(asyncLib, Dart_NewStringFromCString("Future"), 0, 0);
    return Dart_New(futureClass, Dart_NewStringFromCString("error"), 1, &error);
}

Dart_Handle DartUtilities::newResolver()
{
    Dart_Handle asyncLib = Dart_LookupLibrary(Dart_NewStringFromCString("dart:async"));
    Dart_Handle futureClass = Dart_GetType(asyncLib, Dart_NewStringFromCString("Completer"), 0, 0);
    return Dart_New(futureClass, Dart_EmptyString(), 0, 0);
}

Dart_Handle DartUtilities::newArgumentError(const String& message)
{
    Dart_Handle asyncLib = Dart_LookupLibrary(Dart_NewStringFromCString("dart:core"));
    Dart_Handle futureClass = Dart_GetType(asyncLib, Dart_NewStringFromCString("ArgumentError"), 0, 0);
    Dart_Handle dartMessage = stringToDart(message);
    return Dart_New(futureClass, Dart_EmptyString(), 1, &dartMessage);
}

Dart_Handle DartUtilities::invokeUtilsMethod(const char* methodName, int argCount, Dart_Handle* args)
{
    DartDOMData* domData = DartDOMData::current();
    ASSERT(domData);
    Dart_PersistentHandle library = domData->htmlLibrary();
    ASSERT(!Dart_IsError(library));

    Dart_Handle utilsClass = Dart_GetType(library, Dart_NewStringFromCString("_Utils"), 0, 0);
    ASSERT(!Dart_IsError(utilsClass));

    return Dart_Invoke(utilsClass, Dart_NewStringFromCString(methodName), argCount, args);
}


int DartUtilities::getProp(const char* name, char* value, int valueLen)
{
#if OS(ANDROID)
    return __system_property_get(name, value);
#else
    char* v = getenv(name);
    if (!v) {
        return 0;
    }
    ASSERT(valueLen > 0 && static_cast<size_t>(valueLen) > strlen(v));
    strncpy(value, v, valueLen);
    value[valueLen - 1] = '\0';
    return strlen(value);
#endif
}
}
