| Index: Source/bindings/core/dart/DartHandleProxy.cpp
 | 
| diff --git a/Source/bindings/core/dart/DartHandleProxy.cpp b/Source/bindings/core/dart/DartHandleProxy.cpp
 | 
| new file mode 100644
 | 
| index 0000000000000000000000000000000000000000..6fad89a0f4f125fe4b1cef6681ad9d9bda7ca182
 | 
| --- /dev/null
 | 
| +++ b/Source/bindings/core/dart/DartHandleProxy.cpp
 | 
| @@ -0,0 +1,1249 @@
 | 
| +/*
 | 
| + * Copyright (C) 2012 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/DartHandleProxy.h"
 | 
| +
 | 
| +#include "bindings/core/dart/DartJsInterop.h"
 | 
| +#include "bindings/core/dart/DartPersistentValue.h"
 | 
| +#include "bindings/core/dart/V8Converter.h"
 | 
| +#include "bindings/core/v8/PageScriptDebugServer.h"
 | 
| +#include "bindings/core/v8/ScriptController.h"
 | 
| +#include "bindings/core/v8/V8Binding.h"
 | 
| +#include "bindings/core/v8/V8ScriptRunner.h"
 | 
| +#include "bindings/core/v8/V8ThrowException.h"
 | 
| +
 | 
| +#include "wtf/StdLibExtras.h"
 | 
| +
 | 
| +namespace blink {
 | 
| +
 | 
| +struct DartHandleProxy::CallbackData {
 | 
| +    ScopedPersistent<v8::Object> handle;
 | 
| +    DartPersistentValue* value;
 | 
| +};
 | 
| +
 | 
| +typedef HashMap<String, v8::Persistent<v8::FunctionTemplate>* > FunctionTemplateMap;
 | 
| +
 | 
| +static v8::Local<v8::FunctionTemplate> objectProxyTemplate(Dart_Handle instance);
 | 
| +static v8::Local<v8::FunctionTemplate> functionProxyTemplate();
 | 
| +static v8::Local<v8::FunctionTemplate> libraryProxyTemplate(v8::Handle<v8::String> libraryNameV8);
 | 
| +static v8::Local<v8::FunctionTemplate> typeProxyTemplate(Dart_Handle type);
 | 
| +static v8::Local<v8::FunctionTemplate> frameProxyTemplate();
 | 
| +
 | 
| +DartPersistentValue* DartHandleProxy::readPointerFromProxy(v8::Handle<v8::Value> proxy)
 | 
| +{
 | 
| +    void* pointer = proxy.As<v8::Object>()->GetAlignedPointerFromInternalField(0);
 | 
| +    return static_cast<DartPersistentValue*>(pointer);
 | 
| +}
 | 
| +
 | 
| +bool DartHandleProxy::isDartProxy(v8::Handle<v8::Value> value)
 | 
| +{
 | 
| +    if (!value.IsEmpty() && value->IsObject()) {
 | 
| +        v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
 | 
| +        v8::Local<v8::Value> hiddenValue = value.As<v8::Object>()->GetHiddenValue(v8::String::NewFromUtf8(v8Isolate, "dartProxy"));
 | 
| +        return *hiddenValue && hiddenValue->IsBoolean();
 | 
| +    }
 | 
| +    return false;
 | 
| +}
 | 
| +
 | 
| +bool isGlobalObjectProxy(v8::Handle<v8::Object> value)
 | 
| +{
 | 
| +    v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
 | 
| +    v8::Local<v8::Value> hiddenValue = value.As<v8::Object>()->GetHiddenValue(v8::String::NewFromUtf8(v8Isolate, "asGlobal"));
 | 
| +    return *hiddenValue && hiddenValue->IsBoolean();
 | 
| +}
 | 
| +
 | 
| +DartScopes::DartScopes(v8::Local<v8::Object> v8Handle, bool disableBreak) :
 | 
| +    scriptValue(DartHandleProxy::readPointerFromProxy(v8Handle)),
 | 
| +    scope(scriptValue->isolate()),
 | 
| +    disableBreak(disableBreak)
 | 
| +{
 | 
| +    ASSERT(scriptValue->isIsolateAlive());
 | 
| +    handle = scriptValue->value();
 | 
| +    if (disableBreak) {
 | 
| +        previousPauseInfo = Dart_GetExceptionPauseInfo();
 | 
| +        Dart_SetExceptionPauseInfo(kNoPauseOnExceptions);
 | 
| +    }
 | 
| +}
 | 
| +
 | 
| +DartScopes::~DartScopes()
 | 
| +{
 | 
| +    if (disableBreak) {
 | 
| +        Dart_SetExceptionPauseInfo(previousPauseInfo);
 | 
| +    }
 | 
| +}
 | 
| +
 | 
| +static void weakCallback(const v8::WeakCallbackData<v8::Object, DartHandleProxy::CallbackData >& data)
 | 
| +{
 | 
| +    DartHandleProxy::CallbackData* callbackData = data.GetParameter();
 | 
| +    callbackData->handle.clear();
 | 
| +    delete callbackData->value;
 | 
| +    delete callbackData;
 | 
| +}
 | 
| +
 | 
| +Dart_Handle DartHandleProxy::unwrapValue(v8::Handle<v8::Value> value)
 | 
| +{
 | 
| +    if (DartHandleProxy::isDartProxy(value))
 | 
| +        return readPointerFromProxy(value)->value();
 | 
| +
 | 
| +    Dart_Handle exception = 0;
 | 
| +    Dart_Handle handle = V8Converter::toDart(value, exception);
 | 
| +    ASSERT(!exception);
 | 
| +    return handle;
 | 
| +}
 | 
| +
 | 
| +bool libraryHasMember(Dart_Handle library, Dart_Handle name)
 | 
| +{
 | 
| +    return !Dart_IsError(Dart_GetField(library, name))
 | 
| +        || !Dart_IsError(Dart_GetType(library, name, 0, 0))
 | 
| +        || Dart_IsFunction(Dart_LookupFunction(library, name));
 | 
| +}
 | 
| +
 | 
| +bool typeHasMember(Dart_Handle type, Dart_Handle name)
 | 
| +{
 | 
| +    return !Dart_IsError(Dart_GetField(type, name)) || Dart_IsFunction(Dart_LookupFunction(type, name));
 | 
| +}
 | 
| +
 | 
| +Dart_Handle getEncodedMapKeyList(Dart_Handle object)
 | 
| +{
 | 
| +    return DartUtilities::invokeUtilsMethod("getEncodedMapKeyList", 1, &object);
 | 
| +}
 | 
| +
 | 
| +Dart_Handle stripTrailingDot(Dart_Handle str)
 | 
| +{
 | 
| +    return DartUtilities::invokeUtilsMethod("stripTrailingDot", 1, &str);
 | 
| +}
 | 
| +
 | 
| +Dart_Handle addTrailingDot(Dart_Handle str)
 | 
| +{
 | 
| +    return DartUtilities::invokeUtilsMethod("addTrailingDot", 1, &str);
 | 
| +}
 | 
| +
 | 
| +Dart_Handle demangle(Dart_Handle str)
 | 
| +{
 | 
| +    return DartUtilities::invokeUtilsMethod("demangle", 1, &str);
 | 
| +}
 | 
| +
 | 
| +Dart_Handle lookupValueForEncodedMapKey(Dart_Handle object, Dart_Handle key)
 | 
| +{
 | 
| +    Dart_Handle args[] = {object, key};
 | 
| +    return DartUtilities::invokeUtilsMethod("lookupValueForEncodedMapKey", 2, args);
 | 
| +}
 | 
| +
 | 
| +Dart_Handle buildConstructorName(Dart_Handle typeName, Dart_Handle constructorName)
 | 
| +{
 | 
| +    Dart_Handle args[] = {typeName, constructorName};
 | 
| +    return DartUtilities::invokeUtilsMethod("buildConstructorName", 2, args);
 | 
| +}
 | 
| +
 | 
| +Dart_Handle stripClassName(Dart_Handle str, Dart_Handle typeName)
 | 
| +{
 | 
| +    Dart_Handle args[] = {str, typeName};
 | 
| +    return DartUtilities::invokeUtilsMethod("stripClassName", 2, args);
 | 
| +}
 | 
| +
 | 
| +bool isNoSuchMethodError(Dart_Handle type)
 | 
| +{
 | 
| +    Dart_Handle exception = 0;
 | 
| +    bool ret = DartUtilities::dartToBool(DartUtilities::invokeUtilsMethod("isNoSuchMethodError", 1, &type), exception);
 | 
| +    ASSERT(!exception);
 | 
| +    return ret;
 | 
| +}
 | 
| +
 | 
| +Dart_Handle createLocalVariablesMap(Dart_Handle localVariablesList)
 | 
| +{
 | 
| +    return DartUtilities::invokeUtilsMethod("createLocalVariablesMap", 1, &localVariablesList);
 | 
| +}
 | 
| +
 | 
| +Dart_Handle getMapKeyList(Dart_Handle localVariablesMap)
 | 
| +{
 | 
| +    return DartUtilities::invokeUtilsMethod("getMapKeyList", 1, &localVariablesMap);
 | 
| +}
 | 
| +
 | 
| +bool mapContainsKey(Dart_Handle map, Dart_Handle key)
 | 
| +{
 | 
| +    Dart_Handle exception = 0;
 | 
| +    return DartUtilities::dartToBool(Dart_Invoke(map, Dart_NewStringFromCString("containsKey"), 1, &key), exception);
 | 
| +}
 | 
| +
 | 
| +void addFunctionNames(Dart_Handle handle, v8::Local<v8::Array>& properties, intptr_t* count, bool isInstance, bool noMethods)
 | 
| +{
 | 
| +    intptr_t length = 0;
 | 
| +    Dart_Handle functionNames = Dart_GetFunctionNames(handle);
 | 
| +    ASSERT(!Dart_IsError(functionNames));
 | 
| +    bool isLibrary = Dart_IsLibrary(handle);
 | 
| +    Dart_ListLength(functionNames, &length);
 | 
| +    for (intptr_t i = 0; i < length; i++) {
 | 
| +        Dart_Handle functionName = Dart_ListGetAt(functionNames, i);
 | 
| +        Dart_Handle function = Dart_LookupFunction(handle, functionName);
 | 
| +
 | 
| +        // FIXME: the DartVM doesn't correctly handle invoking properties with
 | 
| +        // private names. For now, skip private function names.
 | 
| +        intptr_t functionNameLength = 0;
 | 
| +        uint8_t* functionNameData;
 | 
| +        Dart_StringToUTF8(functionName, &functionNameData, &functionNameLength);
 | 
| +        if (functionNameLength > 0 && functionNameData[0] == '_')
 | 
| +            continue;
 | 
| +
 | 
| +        bool isStatic = false;
 | 
| +        Dart_FunctionIsStatic(function, &isStatic);
 | 
| +
 | 
| +        bool isConstructor = false;
 | 
| +        Dart_FunctionIsConstructor(function, &isConstructor);
 | 
| +
 | 
| +        if (!isLibrary) {
 | 
| +            if (isInstance == (isStatic || isConstructor))
 | 
| +                continue;
 | 
| +
 | 
| +            bool isSetter = false;
 | 
| +            Dart_FunctionIsSetter(function, &isSetter);
 | 
| +            bool isGetter = false;
 | 
| +            Dart_FunctionIsGetter(function, &isGetter);
 | 
| +
 | 
| +            if (noMethods && !isSetter && !isGetter)
 | 
| +                continue;
 | 
| +
 | 
| +            // Skip setters as any setter we care to enumerate should have a matching getter.
 | 
| +            // Setters without matching getters will still be callable but won't be enumerated.
 | 
| +            if (isSetter)
 | 
| +                continue;
 | 
| +        }
 | 
| +
 | 
| +        // Strip off the leading typename from constructor name.
 | 
| +        if (isConstructor)
 | 
| +            functionName = stripClassName(functionName, Dart_TypeName(handle));
 | 
| +
 | 
| +        functionName = demangle(functionName);
 | 
| +        properties->Set(*count, V8Converter::stringToV8(functionName));
 | 
| +        *count = *count + 1;
 | 
| +    }
 | 
| +}
 | 
| +
 | 
| +void addClassNames(Dart_Handle library, v8::Local<v8::Array>& properties, intptr_t* count)
 | 
| +{
 | 
| +    intptr_t length = 0;
 | 
| +    Dart_Handle typeNames = Dart_LibraryGetClassNames(library);
 | 
| +    ASSERT(!Dart_IsNull(typeNames));
 | 
| +    ASSERT(Dart_IsList(typeNames));
 | 
| +    Dart_ListLength(typeNames, &length);
 | 
| +    for (intptr_t i = 0; i < length; i++) {
 | 
| +        Dart_Handle typeName = Dart_ListGetAt(typeNames, i);
 | 
| +        properties->Set(*count, V8Converter::stringToV8(typeName));
 | 
| +        *count = *count + 1;
 | 
| +    }
 | 
| +}
 | 
| +
 | 
| +void addFieldNames(Dart_Handle fieldNames, v8::Local<v8::Array>& properties, intptr_t* count)
 | 
| +{
 | 
| +    ASSERT(!Dart_IsApiError(fieldNames));
 | 
| +    ASSERT(Dart_IsList(fieldNames));
 | 
| +    intptr_t length = 0;
 | 
| +    Dart_ListLength(fieldNames, &length);
 | 
| +    for (intptr_t i = 0; i < length; i += 2) {
 | 
| +        Dart_Handle fieldName = Dart_ListGetAt(fieldNames, i);
 | 
| +        properties->Set(*count, V8Converter::stringToV8(demangle(fieldName)));
 | 
| +        *count = *count + 1;
 | 
| +    }
 | 
| +}
 | 
| +
 | 
| +template<typename CallbackInfo>
 | 
| +void setReturnValue(CallbackInfo info, Dart_Handle result)
 | 
| +{
 | 
| +    if (Dart_IsError(result)) {
 | 
| +        // FIXME: we would really prefer to call the following however it has
 | 
| +        // bad unintended consequences as then JS cannot catch the thrown exception.
 | 
| +        // DartUtilities::reportProblem(DartUtilities::scriptExecutionContext(), result);
 | 
| +        v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
 | 
| +        V8ThrowException::throwException(v8::String::NewFromUtf8(v8Isolate, Dart_GetError(result)), v8::Isolate::GetCurrent());
 | 
| +    } else {
 | 
| +        v8SetReturnValue(info, DartHandleProxy::create(result));
 | 
| +    }
 | 
| +}
 | 
| +
 | 
| +void DartHandleProxy::writePointerToProxy(v8::Local<v8::Object> proxy, Dart_Handle value)
 | 
| +{
 | 
| +    ASSERT(!proxy.IsEmpty());
 | 
| +    DartPersistentValue* dartScriptValue = new DartPersistentValue(value);
 | 
| +    proxy->SetAlignedPointerInInternalField(0, dartScriptValue);
 | 
| +    v8::Isolate* isolate = v8::Isolate::GetCurrent();
 | 
| +    v8::Persistent<v8::Object> persistentHandle;
 | 
| +    DartHandleProxy::CallbackData* callbackData = new DartHandleProxy::CallbackData();
 | 
| +    callbackData->value = dartScriptValue;
 | 
| +    callbackData->handle.set(isolate, proxy);
 | 
| +    callbackData->handle.setWeak(callbackData, &weakCallback);
 | 
| +}
 | 
| +
 | 
| +intptr_t getLibraryId(v8::Local<v8::Object> proxy)
 | 
| +{
 | 
| +    v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
 | 
| +    return (intptr_t)proxy.As<v8::Object>()->GetHiddenValue(v8::String::NewFromUtf8(v8Isolate, "libraryId"))->Int32Value();
 | 
| +}
 | 
| +
 | 
| +// Returns a String of the library prefix or Dart_Null if no prefix is found.
 | 
| +Dart_Handle getLibraryPrefix(v8::Local<v8::Object> proxy)
 | 
| +{
 | 
| +    v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
 | 
| +    v8::Local<v8::Value> prefix = proxy.As<v8::Object>()->GetHiddenValue(v8::String::NewFromUtf8(v8Isolate, "prefix"));
 | 
| +    if (*prefix && prefix->IsString())
 | 
| +        return V8Converter::stringToDart(prefix);
 | 
| +    return Dart_Null();
 | 
| +}
 | 
| +
 | 
| +static void functionNamedPropertyGetter(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Value>& info)
 | 
| +{
 | 
| +    DartScopes scopes(info.Holder());
 | 
| +    Dart_Handle handle = scopes.handle;
 | 
| +
 | 
| +    ASSERT(DartUtilities::isFunction(DartDOMData::current(), handle) || Dart_IsFunction(handle));
 | 
| +    v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
 | 
| +    Dart_Handle ret = Dart_Invoke(handle, V8Converter::stringToDart(v8::String::Concat(v8::String::NewFromUtf8(v8Isolate, "get:"), name)), 0, 0);
 | 
| +    if (Dart_IsError(ret) && name->Equals(v8::String::NewFromUtf8(v8Isolate, "__proto__")))
 | 
| +        return;
 | 
| +
 | 
| +    setReturnValue(info, ret);
 | 
| +}
 | 
| +
 | 
| +static void functionNamedPropertySetter(v8::Local<v8::String> property, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info)
 | 
| +{
 | 
| +    v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
 | 
| +    V8ThrowException::throwException(v8::String::NewFromUtf8(v8Isolate, "Dart functions do not have writeable properties"), v8::Isolate::GetCurrent());
 | 
| +}
 | 
| +
 | 
| +static void functionInvocationCallback(const v8::FunctionCallbackInfo<v8::Value>& args)
 | 
| +{
 | 
| +    DartScopes scopes(args.Holder());
 | 
| +    Dart_Handle handle = scopes.handle;
 | 
| +
 | 
| +    DartDOMData* domData = DartDOMData::current();
 | 
| +    ASSERT(DartUtilities::isFunction(domData, handle) || Dart_IsFunction(handle));
 | 
| +    bool isConstructor = false;
 | 
| +    Dart_FunctionIsConstructor(handle, &isConstructor);
 | 
| +    if (args.IsConstructCall() != isConstructor) {
 | 
| +        v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
 | 
| +        V8ThrowException::throwException(v8::String::NewFromUtf8(v8Isolate, isConstructor ? "Constructor called without new" : "Regular function called as constructor"), v8Isolate);
 | 
| +        return;
 | 
| +    }
 | 
| +
 | 
| +    Vector<Dart_Handle> dartFunctionArgs;
 | 
| +    for (intptr_t i = 0; i < args.Length(); ++i)
 | 
| +        dartFunctionArgs.append(DartHandleProxy::unwrapValue(args[i]));
 | 
| +
 | 
| +    if (DartUtilities::isFunction(domData, handle)) {
 | 
| +        setReturnValue(args, Dart_InvokeClosure(handle, dartFunctionArgs.size(), dartFunctionArgs.data()));
 | 
| +        return;
 | 
| +    }
 | 
| +    Dart_Handle type = Dart_FunctionOwner(handle);
 | 
| +    if (isConstructor) {
 | 
| +        // FIXME: this seems like an overly complex way to have to invoke a constructor.
 | 
| +        setReturnValue(args,
 | 
| +            Dart_New(type, stripClassName(Dart_FunctionName(handle), Dart_TypeName(type)),
 | 
| +                dartFunctionArgs.size(), dartFunctionArgs.data()));
 | 
| +    } else {
 | 
| +        // Workaround so that invoking toString on a Class object returns
 | 
| +        // something meaningful instead of throwing an exception.
 | 
| +        if (Dart_IsType(type)) {
 | 
| +            bool isStatic = true;
 | 
| +            Dart_FunctionIsStatic(handle, &isStatic);
 | 
| +            // Attempting to invoke a static method on a Class object will fail
 | 
| +            // so there is not much harm in returning a more user friendly
 | 
| +            // result for toString().
 | 
| +            v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
 | 
| +            if (!isStatic && V8Converter::stringToV8(Dart_FunctionName(handle))->Equals(v8::String::NewFromUtf8(v8Isolate, "toString"))) {
 | 
| +                setReturnValue(args, Dart_QualifiedTypeName(type));
 | 
| +                return;
 | 
| +            }
 | 
| +        }
 | 
| +        setReturnValue(args,
 | 
| +            Dart_Invoke(type, Dart_FunctionName(handle), dartFunctionArgs.size(), dartFunctionArgs.data()));
 | 
| +    }
 | 
| +}
 | 
| +
 | 
| +static void typeProxyConstructorInvocationCallback(const v8::FunctionCallbackInfo<v8::Value>& args)
 | 
| +{
 | 
| +    DartScopes scopes(args.Holder());
 | 
| +    Dart_Handle handle = scopes.handle;
 | 
| +
 | 
| +    ASSERT(Dart_IsType(handle));
 | 
| +
 | 
| +    if (!args.IsConstructCall()) {
 | 
| +        v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
 | 
| +        V8ThrowException::throwException(v8::String::NewFromUtf8(v8Isolate, "Constructors can only be invoked with 'new'"), v8Isolate);
 | 
| +        return;
 | 
| +    }
 | 
| +
 | 
| +    Vector<Dart_Handle> dartFunctionArgs;
 | 
| +    for (intptr_t i = 0; i < args.Length(); ++i)
 | 
| +        dartFunctionArgs.append(DartHandleProxy::unwrapValue(args[i]));
 | 
| +
 | 
| +    setReturnValue(args, Dart_New(handle, Dart_Null(), dartFunctionArgs.size(), dartFunctionArgs.data()));
 | 
| +}
 | 
| +
 | 
| +void getImportedLibrariesMatchingPrefix(intptr_t libraryId, Dart_Handle prefix, Vector<std::pair<Dart_Handle, intptr_t> >* libraries)
 | 
| +{
 | 
| +    Dart_Handle imports = Dart_GetLibraryImports(libraryId);
 | 
| +    ASSERT(!Dart_IsError(imports));
 | 
| +    // Unfortunately dart_tools_api.h adds a trailing dot to import prefixes.
 | 
| +    if (!Dart_IsNull(prefix))
 | 
| +        prefix = addTrailingDot(prefix);
 | 
| +    intptr_t length = 0;
 | 
| +    Dart_ListLength(imports, &length);
 | 
| +    for (intptr_t i = 0; i < length; i += 2) {
 | 
| +        Dart_Handle importPrefix = Dart_ListGetAt(imports, i);
 | 
| +        ASSERT(Dart_IsNull(importPrefix) || Dart_IsString(importPrefix));
 | 
| +        bool equals = false;
 | 
| +        Dart_Handle ALLOW_UNUSED result = Dart_ObjectEquals(prefix, importPrefix, &equals);
 | 
| +        ASSERT(!Dart_IsError(result));
 | 
| +        if (equals) {
 | 
| +            Dart_Handle importedLibraryIdHandle = Dart_ListGetAt(imports, i + 1);
 | 
| +            ASSERT(Dart_IsInteger(importedLibraryIdHandle));
 | 
| +            int64_t importedLibraryId;
 | 
| +            Dart_IntegerToInt64(importedLibraryIdHandle, &importedLibraryId);
 | 
| +            Dart_Handle libraryURL = Dart_GetLibraryURL(importedLibraryId);
 | 
| +            ASSERT(!Dart_IsError(libraryURL));
 | 
| +            Dart_Handle library = Dart_LookupLibrary(libraryURL);
 | 
| +            ASSERT(Dart_IsLibrary(library));
 | 
| +            libraries->append(std::pair<Dart_Handle, intptr_t>(library, importedLibraryId));
 | 
| +        }
 | 
| +    }
 | 
| +}
 | 
| +
 | 
| +static bool libraryNamedPropertyGetterHelper(Dart_Handle library, Dart_Handle dartName,
 | 
| +    const v8::PropertyCallbackInfo<v8::Value>* info)
 | 
| +{
 | 
| +    Dart_Handle ret;
 | 
| +    ret  = Dart_GetField(library, dartName);
 | 
| +    if (!Dart_IsApiError(ret)) {
 | 
| +        if (info)
 | 
| +            setReturnValue(*info, ret);
 | 
| +        return true;
 | 
| +    }
 | 
| +
 | 
| +    ret = Dart_GetType(library, dartName, 0, 0);
 | 
| +    if (!Dart_IsError(ret)) {
 | 
| +        if (info)
 | 
| +            v8SetReturnValue(*info, DartHandleProxy::createTypeProxy(ret, true));
 | 
| +        return true;
 | 
| +    }
 | 
| +
 | 
| +    ret = Dart_LookupFunction(library, dartName);
 | 
| +    if (!Dart_IsNull(ret) && !Dart_IsError(ret)) {
 | 
| +        if (info)
 | 
| +            setReturnValue(*info, ret);
 | 
| +        return true;
 | 
| +    }
 | 
| +    return false;
 | 
| +}
 | 
| +
 | 
| +/**
 | 
| + * Helper for getting library property values.
 | 
| + * Info may be 0 in which case no V8 If info is 0, no return value is set.
 | 
| + */
 | 
| +static bool libraryNamedPropertyGetterHelper(v8::Local<v8::String> name, v8::Local<v8::Object> holder,
 | 
| +    const v8::PropertyCallbackInfo<v8::Value>* info)
 | 
| +{
 | 
| +    DartScopes scopes(holder);
 | 
| +    Dart_Handle handle = scopes.handle;
 | 
| +
 | 
| +    ASSERT(Dart_IsLibrary(handle));
 | 
| +    intptr_t libraryId = getLibraryId(holder);
 | 
| +    Dart_Handle dartName = V8Converter::stringToDart(name);
 | 
| +    Dart_Handle prefix = getLibraryPrefix(holder);
 | 
| +    bool hasLibraryPrefix = !Dart_IsNull(prefix) && Dart_IsString(prefix);
 | 
| +
 | 
| +    if (hasLibraryPrefix) {
 | 
| +        Vector<std::pair<Dart_Handle, intptr_t> > libraries;
 | 
| +        getImportedLibrariesMatchingPrefix(libraryId, prefix, &libraries);
 | 
| +        for (size_t i = 0; i < libraries.size(); i++) {
 | 
| +            if (libraryNamedPropertyGetterHelper(libraries[i].first, dartName, info))
 | 
| +                return true;
 | 
| +        }
 | 
| +    } else {
 | 
| +        if (libraryNamedPropertyGetterHelper(handle, dartName, info))
 | 
| +            return true;
 | 
| +
 | 
| +        // Check whether there is at least one library imported with the specified prefix.
 | 
| +        Vector<std::pair<Dart_Handle, intptr_t> > libraries;
 | 
| +        getImportedLibrariesMatchingPrefix(libraryId, dartName, &libraries);
 | 
| +        if (libraries.size() > 0) {
 | 
| +            if (info)
 | 
| +                v8SetReturnValue(*info, DartHandleProxy::createLibraryProxy(handle, libraryId, dartName, false));
 | 
| +            return true;
 | 
| +        }
 | 
| +    }
 | 
| +
 | 
| +    v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
 | 
| +    if (name->Equals(v8::String::NewFromUtf8(v8Isolate, "__proto__"))) {
 | 
| +        if (info)
 | 
| +            v8SetReturnValue(*info, v8::Null(v8Isolate));
 | 
| +        return true;
 | 
| +    }
 | 
| +    return false;
 | 
| +}
 | 
| +
 | 
| +static void libraryNamedPropertyGetter(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Value>& info)
 | 
| +{
 | 
| +    libraryNamedPropertyGetterHelper(name, info.Holder(), &info);
 | 
| +}
 | 
| +
 | 
| +// FIXME: we need to handle prefixes when setting library properties as well
 | 
| +// for completness. Postponing implementing this for now as we hope Dart_Invoke
 | 
| +// can just be fixed to handle libraries correctly.
 | 
| +static void libraryNamedPropertySetter(v8::Local<v8::String> property, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info)
 | 
| +{
 | 
| +    DartScopes scopes(info.Holder());
 | 
| +    Dart_Handle handle = scopes.handle;
 | 
| +
 | 
| +    ASSERT(Dart_IsLibrary(handle));
 | 
| +    Dart_Handle dartValue = DartHandleProxy::unwrapValue(value);
 | 
| +    setReturnValue(info, Dart_SetField(handle, V8Converter::stringToDart(property), dartValue));
 | 
| +}
 | 
| +
 | 
| +static void libraryQueryProperty(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Integer>& info)
 | 
| +{
 | 
| +    if (libraryNamedPropertyGetterHelper(name, info.Holder(), 0))
 | 
| +        v8SetReturnValueInt(info, 0);
 | 
| +}
 | 
| +
 | 
| +void libraryEnumerateHelper(Dart_Handle library, intptr_t libraryId, v8::Local<v8::Array> properties, intptr_t* count)
 | 
| +{
 | 
| +    addFunctionNames(library, properties, count, false, false);
 | 
| +    addClassNames(library, properties, count);
 | 
| +    addFieldNames(Dart_GetLibraryFields(libraryId), properties, count);
 | 
| +}
 | 
| +
 | 
| +static void libraryPropertyEnumerator(const v8::PropertyCallbackInfo<v8::Array>& info)
 | 
| +{
 | 
| +    DartScopes scopes(info.Holder());
 | 
| +    Dart_Handle handle = scopes.handle;
 | 
| +
 | 
| +    intptr_t libraryId = getLibraryId(info.Holder());
 | 
| +    ASSERT(Dart_IsLibrary(handle));
 | 
| +    v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
 | 
| +    v8::Local<v8::Array> cachedProperties = info.Holder().As<v8::Object>()->GetHiddenValue(v8::String::NewFromUtf8(v8Isolate, "cache")).As<v8::Array>();
 | 
| +    if (*cachedProperties) {
 | 
| +        v8SetReturnValue(info, cachedProperties);
 | 
| +        return;
 | 
| +    }
 | 
| +
 | 
| +    Dart_Handle prefix = getLibraryPrefix(info.Holder());
 | 
| +    bool hasLibraryPrefix = Dart_IsString(prefix);
 | 
| +
 | 
| +    v8::Local<v8::Array> properties = v8::Array::New(v8Isolate);
 | 
| +    intptr_t count = 0;
 | 
| +
 | 
| +    if (hasLibraryPrefix) {
 | 
| +        Vector<std::pair<Dart_Handle, intptr_t> > libraries;
 | 
| +        getImportedLibrariesMatchingPrefix(libraryId, prefix, &libraries);
 | 
| +        for (size_t i = 0; i < libraries.size(); i++)
 | 
| +            libraryEnumerateHelper(libraries[i].first, libraries[i].second, properties, &count);
 | 
| +    } else {
 | 
| +        libraryEnumerateHelper(handle, libraryId, properties, &count);
 | 
| +        // Add all library prefixes of imports to the library.
 | 
| +        Dart_Handle imports = Dart_GetLibraryImports(libraryId);
 | 
| +        ASSERT(!Dart_IsError(imports));
 | 
| +        intptr_t length = 0;
 | 
| +        Dart_ListLength(imports, &length);
 | 
| +        for (intptr_t i = 0; i < length; i += 2) {
 | 
| +            Dart_Handle importPrefix = Dart_ListGetAt(imports, i);
 | 
| +            if (!Dart_IsNull(importPrefix)) {
 | 
| +                ASSERT(Dart_IsString(importPrefix));
 | 
| +                properties->Set(count, V8Converter::stringToV8(
 | 
| +                    demangle(stripTrailingDot(importPrefix))));
 | 
| +                count++;
 | 
| +            }
 | 
| +        }
 | 
| +    }
 | 
| +
 | 
| +    info.Holder()->SetHiddenValue(v8::String::NewFromUtf8(v8Isolate, "cache"), properties);
 | 
| +    v8SetReturnValue(info, properties);
 | 
| +}
 | 
| +
 | 
| +bool isShowStatics(v8::Handle<v8::Value> value)
 | 
| +{
 | 
| +    v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
 | 
| +    v8::Local<v8::Value> showStatics = value.As<v8::Object>()->GetHiddenValue(v8::String::NewFromUtf8(v8Isolate, "showStatics"));
 | 
| +    ASSERT(*showStatics && showStatics->IsBoolean());
 | 
| +    return showStatics->BooleanValue();
 | 
| +}
 | 
| +
 | 
| +static void typeNamedPropertyGetter(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Value>& info)
 | 
| +{
 | 
| +    DartScopes scopes(info.Holder());
 | 
| +    Dart_Handle handle = scopes.handle;
 | 
| +
 | 
| +    Dart_Handle ret;
 | 
| +    ASSERT(Dart_IsType(handle));
 | 
| +    v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
 | 
| +    if (name->Equals(v8::String::NewFromUtf8(v8Isolate, "__proto__"))) {
 | 
| +        // Due to Dart semantics, if we are showing statics, we need to
 | 
| +        // not link types up to their superclasses as statics in superclasses
 | 
| +        // are not visible in subclasses.
 | 
| +        if (isShowStatics(info.Holder())) {
 | 
| +            v8SetReturnValue(info, v8::Null(v8Isolate));
 | 
| +            return;
 | 
| +        }
 | 
| +
 | 
| +        Dart_Handle supertype = Dart_GetSupertype(handle);
 | 
| +        if (!Dart_IsNull(supertype))
 | 
| +            v8SetReturnValue(info, DartHandleProxy::createTypeProxy(supertype, false));
 | 
| +        else
 | 
| +            v8SetReturnValue(info, v8::Null(v8Isolate));
 | 
| +        return;
 | 
| +    }
 | 
| +
 | 
| +    Dart_Handle dartName = V8Converter::stringToDart(name);
 | 
| +    ret = Dart_GetField(handle, dartName);
 | 
| +    if (!Dart_IsError(ret)) {
 | 
| +        setReturnValue(info, ret);
 | 
| +        return;
 | 
| +    }
 | 
| +    ret = Dart_LookupFunction(handle, dartName);
 | 
| +    if (!Dart_IsNull(ret) && !Dart_IsError(ret)) {
 | 
| +        setReturnValue(info, ret);
 | 
| +        return;
 | 
| +    }
 | 
| +
 | 
| +    Dart_Handle typeName = Dart_TypeName(handle);
 | 
| +    ASSERT(Dart_IsString(typeName));
 | 
| +    Dart_Handle constructorName = buildConstructorName(typeName, V8Converter::stringToDart(name));
 | 
| +    ret = Dart_LookupFunction(handle, constructorName);
 | 
| +    if (!Dart_IsNull(ret) && !Dart_IsError(ret))
 | 
| +        setReturnValue(info, ret);
 | 
| +}
 | 
| +
 | 
| +static void typeNamedPropertySetter(v8::Local<v8::String> property, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info)
 | 
| +{
 | 
| +    DartScopes scopes(info.Holder());
 | 
| +    Dart_Handle handle = scopes.handle;
 | 
| +
 | 
| +    ASSERT(Dart_IsType(handle));
 | 
| +    Dart_Handle dartValue = DartHandleProxy::unwrapValue(value);
 | 
| +    v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
 | 
| +    setReturnValue(info, Dart_Invoke(handle, V8Converter::stringToDart(v8::String::Concat(v8::String::NewFromUtf8(v8Isolate, "set:"), property)), 1, &dartValue));
 | 
| +}
 | 
| +
 | 
| +static void typeQueryProperty(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Integer>& info)
 | 
| +{
 | 
| +    DartScopes scopes(info.Holder());
 | 
| +    Dart_Handle handle = scopes.handle;
 | 
| +
 | 
| +    ASSERT(Dart_IsType(handle));
 | 
| +    v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
 | 
| +    if (name->Equals(v8::String::NewFromUtf8(v8Isolate, "__proto__"))
 | 
| +        || typeHasMember(handle, V8Converter::stringToDart(name)))
 | 
| +        return v8SetReturnValueInt(info, 0);
 | 
| +}
 | 
| +
 | 
| +static void typePropertyEnumerator(const v8::PropertyCallbackInfo<v8::Array>& info)
 | 
| +{
 | 
| +    DartScopes scopes(info.Holder());
 | 
| +    Dart_Handle handle = scopes.handle;
 | 
| +    bool showStatics = isShowStatics(info.Holder());
 | 
| +
 | 
| +    ASSERT(Dart_IsType(handle));
 | 
| +
 | 
| +    v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
 | 
| +    v8::Local<v8::Array> properties = v8::Array::New(v8Isolate);
 | 
| +    intptr_t count = 0;
 | 
| +    addFunctionNames(handle, properties, &count, !showStatics, false);
 | 
| +    if (showStatics)
 | 
| +        addFieldNames(Dart_GetStaticFields(handle), properties, &count);
 | 
| +
 | 
| +    properties->Set(count, v8::String::NewFromUtf8(v8Isolate, "__proto__"));
 | 
| +    count++;
 | 
| +    v8SetReturnValue(info, properties);
 | 
| +}
 | 
| +
 | 
| +static void frameNamedPropertyGetter(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Value>& info)
 | 
| +{
 | 
| +    DartScopes scopes(info.Holder());
 | 
| +    Dart_Handle handle = scopes.handle;
 | 
| +
 | 
| +    if (mapContainsKey(handle, V8Converter::stringToDart(name))) {
 | 
| +        Dart_Handle indexedGetterOperator = Dart_NewStringFromCString("[]");
 | 
| +        Dart_Handle dartName = V8Converter::stringToDart(name);
 | 
| +        setReturnValue(info, Dart_Invoke(handle, indexedGetterOperator, 1, &dartName));
 | 
| +    }
 | 
| +    v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
 | 
| +    if (name->Equals(v8::String::NewFromUtf8(v8Isolate, "__proto__"))) {
 | 
| +        v8SetReturnValue(info, v8::Null(v8Isolate));
 | 
| +    }
 | 
| +}
 | 
| +
 | 
| +static void frameNamedPropertySetter(v8::Local<v8::String> property, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info)
 | 
| +{
 | 
| +    v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
 | 
| +    V8ThrowException::throwException(v8::String::NewFromUtf8(v8Isolate, "Dart does not yet provide a debugger api for setting local fields"), v8Isolate);
 | 
| +}
 | 
| +
 | 
| +static void frameQueryProperty(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Integer>& info)
 | 
| +{
 | 
| +    DartScopes scopes(info.Holder());
 | 
| +
 | 
| +    if (mapContainsKey(scopes.handle, V8Converter::stringToDart(name)))
 | 
| +        v8SetReturnValueInt(info, 0);
 | 
| +}
 | 
| +
 | 
| +static void framePropertyEnumerator(const v8::PropertyCallbackInfo<v8::Array>& info)
 | 
| +{
 | 
| +    DartScopes scopes(info.Holder());
 | 
| +    Dart_Handle keyList = getMapKeyList(scopes.handle);
 | 
| +    ASSERT(!Dart_IsError(keyList));
 | 
| +    ASSERT(Dart_IsList(keyList));
 | 
| +
 | 
| +    intptr_t length = 0;
 | 
| +    Dart_ListLength(keyList, &length);
 | 
| +    v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
 | 
| +    v8::Local<v8::Array> properties = v8::Array::New(v8Isolate, length);
 | 
| +    for (intptr_t i = 0; i < length; i ++)
 | 
| +        properties->Set(i, V8Converter::stringToV8(Dart_ListGetAt(keyList, i)));
 | 
| +    v8SetReturnValue(info, properties);
 | 
| +}
 | 
| +
 | 
| +static void namedPropertyGetter(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Value>& info)
 | 
| +{
 | 
| +    DartScopes scopes(info.Holder());
 | 
| +    Dart_Handle handle = scopes.handle;
 | 
| +
 | 
| +    ASSERT(Dart_IsInstance(handle));
 | 
| +    v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
 | 
| +    if (name->Equals(v8::String::NewFromUtf8(v8Isolate, "__proto__"))) {
 | 
| +        v8SetReturnValue(info, DartHandleProxy::createTypeProxy(Dart_InstanceGetType(handle), false));
 | 
| +        return;
 | 
| +    }
 | 
| +
 | 
| +    v8::String::Utf8Value stringName(name);
 | 
| +    const char* data = *stringName;
 | 
| +    if (data[0] == ':' || data[0] == '#') {
 | 
| +        // Look up a map key instead of a regular property as regular dart property names
 | 
| +        // cannot start with these symbols.
 | 
| +        setReturnValue(info,
 | 
| +            lookupValueForEncodedMapKey(handle, V8Converter::stringToDart(name)));
 | 
| +        return;
 | 
| +    }
 | 
| +    // Prefix for metadata used only by the Dart Editor debugger.
 | 
| +    if (data[0] == '@') {
 | 
| +        if (name->Equals(v8::String::NewFromUtf8(v8Isolate, "@staticFields"))) {
 | 
| +            v8SetReturnValue(info, DartHandleProxy::createTypeProxy(Dart_InstanceGetType(handle), true));
 | 
| +            return;
 | 
| +        }
 | 
| +        if (name->Equals(v8::String::NewFromUtf8(v8Isolate, "@library"))) {
 | 
| +            intptr_t libraryId = 0;
 | 
| +            intptr_t classId = 0;
 | 
| +            Dart_Handle ALLOW_UNUSED result = Dart_GetObjClassId(handle, &classId);
 | 
| +            ASSERT(!Dart_IsError(result));
 | 
| +            result = Dart_GetClassInfo(classId, 0, &libraryId, 0, 0);
 | 
| +            ASSERT(!Dart_IsError(result));
 | 
| +            v8SetReturnValue(info, DartHandleProxy::createLibraryProxy(Dart_GetLibraryFromId(libraryId), libraryId, Dart_Null(), false));
 | 
| +            return;
 | 
| +        }
 | 
| +    }
 | 
| +
 | 
| +    Dart_Handle result = Dart_Invoke(handle, V8Converter::stringToDart(v8::String::Concat(v8::String::NewFromUtf8(v8Isolate, "get:"), name)), 0, 0);
 | 
| +    if (Dart_IsError(result)) {
 | 
| +        // To match JS conventions, we should just return undefined if a
 | 
| +        // property does not exist rather than throwing.
 | 
| +        if (Dart_ErrorHasException(result) && isNoSuchMethodError(Dart_ErrorGetException(result)))
 | 
| +            return;
 | 
| +        v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
 | 
| +        v8Isolate->ThrowException(v8::String::NewFromUtf8(v8Isolate, Dart_GetError(result)));
 | 
| +        return;
 | 
| +    }
 | 
| +    v8SetReturnValue(info, DartHandleProxy::create(result));
 | 
| +}
 | 
| +
 | 
| +static void namedPropertySetter(v8::Local<v8::String> property, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info)
 | 
| +{
 | 
| +    DartScopes scopes(info.Holder());
 | 
| +    Dart_Handle handle = scopes.handle;
 | 
| +
 | 
| +    Dart_Handle dartValue = DartHandleProxy::unwrapValue(value);
 | 
| +    v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
 | 
| +    setReturnValue(info, Dart_Invoke(handle, V8Converter::stringToDart(v8::String::Concat(v8::String::NewFromUtf8(v8Isolate, "set:"), property)), 1, &dartValue));
 | 
| +}
 | 
| +
 | 
| +static void objectQueryProperty(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Integer>& info)
 | 
| +{
 | 
| +    DartScopes scopes(info.Holder());
 | 
| +    Dart_Handle handle = scopes.handle;
 | 
| +
 | 
| +    Dart_Handle ret;
 | 
| +    ASSERT(Dart_IsInstance(handle));
 | 
| +    v8::String::Utf8Value stringName(name);
 | 
| +    const char* data = *stringName;
 | 
| +
 | 
| +    // Looking up a map key instead of a regular property... as regular dart property names
 | 
| +    // cannot start with these symbols.
 | 
| +    if (data[0] == ':' || data[0] == '#') {
 | 
| +        v8SetReturnValueInt(info, v8::ReadOnly);
 | 
| +        return;
 | 
| +    }
 | 
| +    if (data[0] == '@') {
 | 
| +        v8SetReturnValueInt(info, v8::DontEnum);
 | 
| +        return;
 | 
| +    }
 | 
| +
 | 
| +    v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
 | 
| +    ret = Dart_Invoke(handle, V8Converter::stringToDart(v8::String::Concat(v8::String::NewFromUtf8(v8Isolate, "get:"), name)), 0, 0);
 | 
| +    if (Dart_IsError(ret) && !name->Equals(v8::String::NewFromUtf8(v8Isolate, "__proto__"))) {
 | 
| +        return;
 | 
| +    }
 | 
| +    v8SetReturnValueInt(info, 0);
 | 
| +}
 | 
| +
 | 
| +static void objectPropertyEnumerator(const v8::PropertyCallbackInfo<v8::Array>& info)
 | 
| +{
 | 
| +    DartScopes scopes(info.Holder());
 | 
| +    Dart_Handle handle = scopes.handle;
 | 
| +
 | 
| +    ASSERT(Dart_IsInstance(handle));
 | 
| +
 | 
| +    Dart_Handle typeHandle = Dart_InstanceGetType(handle);
 | 
| +
 | 
| +    v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
 | 
| +    v8::Local<v8::Array> properties = v8::Array::New(v8Isolate);
 | 
| +    intptr_t count = 0;
 | 
| +    Dart_Handle mapKeys = getEncodedMapKeyList(handle);
 | 
| +    if (Dart_IsList(mapKeys)) {
 | 
| +        // If the object has map keys, add them all as properties at the start
 | 
| +        // of the list. This aids for debugging although it risks confusing
 | 
| +        // users.
 | 
| +        intptr_t length = 0;
 | 
| +        Dart_ListLength(mapKeys, &length);
 | 
| +        for (intptr_t i = 0; i < length; i++) {
 | 
| +            properties->Set(count, V8Converter::stringToV8(Dart_ListGetAt(mapKeys, i)));
 | 
| +            count++;
 | 
| +        }
 | 
| +    }
 | 
| +
 | 
| +    Dart_Handle instanceFields = Dart_GetInstanceFields(handle);
 | 
| +    intptr_t length = 0;
 | 
| +    Dart_ListLength(instanceFields, &length);
 | 
| +    for (intptr_t i = 0; i < length; i += 2) {
 | 
| +        properties->Set(count, DartHandleProxy::create(
 | 
| +            Dart_ListGetAt(instanceFields, i)));
 | 
| +        count++;
 | 
| +    }
 | 
| +
 | 
| +    while (!Dart_IsError(typeHandle) && !Dart_IsNull(typeHandle)) {
 | 
| +        addFunctionNames(typeHandle, properties, &count, true, true);
 | 
| +        typeHandle = Dart_GetSupertype(typeHandle);
 | 
| +    }
 | 
| +
 | 
| +    properties->Set(count, v8::String::NewFromUtf8(v8Isolate, "@staticFields"));
 | 
| +    count++;
 | 
| +    properties->Set(count, v8::String::NewFromUtf8(v8Isolate, "@library"));
 | 
| +    count++;
 | 
| +    v8SetReturnValue(info, properties);
 | 
| +}
 | 
| +
 | 
| +static void indexedGetter(uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& info)
 | 
| +{
 | 
| +    DartScopes scopes(info.Holder());
 | 
| +    Dart_Handle handle = scopes.handle;
 | 
| +
 | 
| +    Dart_Handle ret = 0;
 | 
| +    if (Dart_IsList(handle))
 | 
| +        ret = Dart_ListGetAt(handle, index);
 | 
| +    else
 | 
| +        ret = Dart_Null();
 | 
| +
 | 
| +    setReturnValue(info, ret);
 | 
| +}
 | 
| +
 | 
| +static void indexedSetter(uint32_t index, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info)
 | 
| +{
 | 
| +    DartScopes scopes(info.Holder());
 | 
| +    Dart_Handle handle = scopes.handle;
 | 
| +
 | 
| +    Dart_Handle ret = 0;
 | 
| +    if (Dart_IsList(handle))
 | 
| +        ret = Dart_ListSetAt(handle, index, DartHandleProxy::unwrapValue(value));
 | 
| +    else
 | 
| +        ret = Dart_Null();
 | 
| +
 | 
| +    setReturnValue(info, ret);
 | 
| +}
 | 
| +
 | 
| +static void indexedEnumerator(const v8::PropertyCallbackInfo<v8::Array>& info)
 | 
| +{
 | 
| +    DartScopes scopes(info.Holder());
 | 
| +    Dart_Handle handle = scopes.handle;
 | 
| +
 | 
| +    intptr_t length = 0;
 | 
| +    if (Dart_IsList(handle))
 | 
| +        Dart_ListLength(handle, &length);
 | 
| +
 | 
| +    v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
 | 
| +    v8::Local<v8::Array> indexes = v8::Array::New(v8Isolate, length);
 | 
| +    for (int i = 0; i < length; i++)
 | 
| +        indexes->Set(i, v8::Integer::New(v8Isolate, i));
 | 
| +
 | 
| +    v8SetReturnValue(info, indexes);
 | 
| +}
 | 
| +
 | 
| +static v8::Local<v8::ObjectTemplate> setupInstanceTemplate(v8::Local<v8::FunctionTemplate> proxyTemplate)
 | 
| +{
 | 
| +    v8::Local<v8::ObjectTemplate> instanceTemplate = proxyTemplate->InstanceTemplate();
 | 
| +    instanceTemplate->SetInternalFieldCount(1);
 | 
| +    return instanceTemplate;
 | 
| +}
 | 
| +
 | 
| +static v8::Local<v8::FunctionTemplate> objectProxyTemplate(Dart_Handle instance)
 | 
| +{
 | 
| +    DEFINE_STATIC_LOCAL(FunctionTemplateMap, map, ());
 | 
| +    Dart_Handle dartType = Dart_InstanceGetType(instance);
 | 
| +    ASSERT(!Dart_IsError(dartType));
 | 
| +    Dart_Handle typeNameHandle = Dart_TypeName(dartType);
 | 
| +    ASSERT(!Dart_IsError(typeNameHandle));
 | 
| +    v8::Handle<v8::String> typeNameV8 = V8Converter::stringToV8(typeNameHandle);
 | 
| +    String typeName = toCoreString(typeNameV8);
 | 
| +    v8::Persistent<v8::FunctionTemplate>* proxyTemplate = map.get(typeName);
 | 
| +    v8::Local<v8::FunctionTemplate> proxyTemplateLocal;
 | 
| +    v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
 | 
| +    if (!proxyTemplate) {
 | 
| +        proxyTemplate = new v8::Persistent<v8::FunctionTemplate>(v8Isolate, v8::FunctionTemplate::New(v8Isolate));
 | 
| +        proxyTemplateLocal = v8::Local<v8::FunctionTemplate>::New(v8Isolate, *proxyTemplate);
 | 
| +        proxyTemplateLocal->SetClassName(typeNameV8);
 | 
| +        map.set(typeName, proxyTemplate);
 | 
| +        v8::Local<v8::ObjectTemplate> instanceTemplate = setupInstanceTemplate(proxyTemplateLocal);
 | 
| +        instanceTemplate->SetIndexedPropertyHandler(&indexedGetter, &indexedSetter, 0, 0, &indexedEnumerator);
 | 
| +        instanceTemplate->SetNamedPropertyHandler(&namedPropertyGetter, &namedPropertySetter, &objectQueryProperty, 0, &objectPropertyEnumerator);
 | 
| +    } else {
 | 
| +        proxyTemplateLocal = v8::Local<v8::FunctionTemplate>::New(v8Isolate, *proxyTemplate);
 | 
| +    }
 | 
| +    return proxyTemplateLocal;
 | 
| +}
 | 
| +
 | 
| +static v8::Local<v8::FunctionTemplate> functionProxyTemplate()
 | 
| +{
 | 
| +    DEFINE_STATIC_LOCAL(v8::Persistent<v8::FunctionTemplate>, proxyTemplate, ());
 | 
| +    v8::Local<v8::FunctionTemplate> proxyTemplateLocal;
 | 
| +    v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
 | 
| +    if (proxyTemplate.IsEmpty()) {
 | 
| +        proxyTemplate.Reset(v8::Isolate::GetCurrent(), v8::FunctionTemplate::New(v8Isolate));
 | 
| +        proxyTemplateLocal = v8::Local<v8::FunctionTemplate>::New(v8Isolate, proxyTemplate);
 | 
| +        proxyTemplateLocal->SetClassName(v8::String::NewFromUtf8(v8Isolate, "[Dart Function]"));
 | 
| +        v8::Local<v8::ObjectTemplate> instanceTemplate = setupInstanceTemplate(proxyTemplateLocal);
 | 
| +        instanceTemplate->SetNamedPropertyHandler(&functionNamedPropertyGetter, &functionNamedPropertySetter);
 | 
| +        instanceTemplate->SetCallAsFunctionHandler(&functionInvocationCallback);
 | 
| +    } else {
 | 
| +        proxyTemplateLocal = v8::Local<v8::FunctionTemplate>::New(v8Isolate, proxyTemplate);
 | 
| +    }
 | 
| +    return proxyTemplateLocal;
 | 
| +}
 | 
| +
 | 
| +static v8::Local<v8::FunctionTemplate> libraryProxyTemplate(v8::Handle<v8::String> libraryNameV8)
 | 
| +{
 | 
| +    DEFINE_STATIC_LOCAL(FunctionTemplateMap, map, ());
 | 
| +    String typeName = toCoreString(libraryNameV8);
 | 
| +    v8::Persistent<v8::FunctionTemplate>* proxyTemplate = map.get(typeName);
 | 
| +    v8::Local<v8::FunctionTemplate> proxyTemplateLocal;
 | 
| +    v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
 | 
| +    if (!proxyTemplate) {
 | 
| +        proxyTemplate = new v8::Persistent<v8::FunctionTemplate>(v8Isolate, v8::FunctionTemplate::New(v8Isolate));
 | 
| +        proxyTemplateLocal = v8::Local<v8::FunctionTemplate>::New(v8Isolate, *proxyTemplate);
 | 
| +        proxyTemplateLocal->SetClassName(libraryNameV8);
 | 
| +        map.set(typeName, proxyTemplate);
 | 
| +        v8::Local<v8::ObjectTemplate> instanceTemplate = setupInstanceTemplate(proxyTemplateLocal);
 | 
| +        instanceTemplate->SetNamedPropertyHandler(&libraryNamedPropertyGetter, &libraryNamedPropertySetter, &libraryQueryProperty, 0, &libraryPropertyEnumerator);
 | 
| +    } else {
 | 
| +        proxyTemplateLocal = v8::Local<v8::FunctionTemplate>::New(v8Isolate, *proxyTemplate);
 | 
| +    }
 | 
| +    return proxyTemplateLocal;
 | 
| +}
 | 
| +
 | 
| +static v8::Local<v8::FunctionTemplate> typeProxyTemplate(Dart_Handle type)
 | 
| +{
 | 
| +    DEFINE_STATIC_LOCAL(FunctionTemplateMap, map, ());
 | 
| +    Dart_Handle typeNameHandle = Dart_TypeName(type);
 | 
| +    ASSERT(!Dart_IsError(typeNameHandle));
 | 
| +    v8::Handle<v8::String> typeNameV8 = V8Converter::stringToV8(typeNameHandle);
 | 
| +    String typeName = toCoreString(typeNameV8);
 | 
| +
 | 
| +    v8::Persistent<v8::FunctionTemplate>* proxyTemplate = map.get(typeName);
 | 
| +    v8::Local<v8::FunctionTemplate> proxyTemplateLocal;
 | 
| +    v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
 | 
| +    if (!proxyTemplate) {
 | 
| +        proxyTemplate = new v8::Persistent<v8::FunctionTemplate>(v8Isolate, v8::FunctionTemplate::New(v8Isolate));
 | 
| +        proxyTemplateLocal = v8::Local<v8::FunctionTemplate>::New(v8Isolate, *proxyTemplate);
 | 
| +        proxyTemplateLocal->SetClassName(typeNameV8);
 | 
| +        v8::Local<v8::ObjectTemplate> instanceTemplate = setupInstanceTemplate(proxyTemplateLocal);
 | 
| +        instanceTemplate->SetNamedPropertyHandler(&typeNamedPropertyGetter, &typeNamedPropertySetter, &typeQueryProperty, 0, &typePropertyEnumerator);
 | 
| +        instanceTemplate->SetCallAsFunctionHandler(&typeProxyConstructorInvocationCallback);
 | 
| +        map.set(typeName, proxyTemplate);
 | 
| +    } else {
 | 
| +        proxyTemplateLocal = v8::Local<v8::FunctionTemplate>::New(v8Isolate, *proxyTemplate);
 | 
| +    }
 | 
| +    return proxyTemplateLocal;
 | 
| +}
 | 
| +
 | 
| +static v8::Local<v8::FunctionTemplate> frameProxyTemplate()
 | 
| +{
 | 
| +    DEFINE_STATIC_LOCAL(v8::Persistent<v8::FunctionTemplate>, proxyTemplate, ());
 | 
| +    v8::Local<v8::FunctionTemplate> proxyTemplateLocal;
 | 
| +    v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
 | 
| +    if (proxyTemplate.IsEmpty()) {
 | 
| +        proxyTemplate.Reset(v8::Isolate::GetCurrent(), v8::FunctionTemplate::New(v8Isolate));
 | 
| +        proxyTemplateLocal = v8::Local<v8::FunctionTemplate>::New(v8Isolate, proxyTemplate);
 | 
| +        proxyTemplateLocal->SetClassName(v8::String::NewFromUtf8(v8Isolate, "[Dart Frame]"));
 | 
| +        v8::Local<v8::ObjectTemplate> instanceTemplate = setupInstanceTemplate(proxyTemplateLocal);
 | 
| +        instanceTemplate->SetNamedPropertyHandler(&frameNamedPropertyGetter, &frameNamedPropertySetter, &frameQueryProperty, 0, &framePropertyEnumerator);
 | 
| +    } else {
 | 
| +        proxyTemplateLocal = v8::Local<v8::FunctionTemplate>::New(v8Isolate, proxyTemplate);
 | 
| +    }
 | 
| +    return proxyTemplateLocal;
 | 
| +}
 | 
| +
 | 
| +v8::Handle<v8::Value> DartHandleProxy::create(Dart_Handle value)
 | 
| +{
 | 
| +    v8::Context::Scope scope(DartUtilities::currentV8Context());
 | 
| +    v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
 | 
| +
 | 
| +    if (Dart_IsNull(value))
 | 
| +        return v8::Null(v8Isolate);
 | 
| +    if (Dart_IsString(value))
 | 
| +        return V8Converter::stringToV8(value);
 | 
| +    if (Dart_IsBoolean(value))
 | 
| +        return V8Converter::booleanToV8(value);
 | 
| +    if (Dart_IsNumber(value))
 | 
| +        return V8Converter::numberToV8(value);
 | 
| +    v8::Local<v8::Object> proxy;
 | 
| +    // We could unwrap Dart DOM types to native types and then rewrap them as
 | 
| +    // JS DOM types but currently we choose not to instead returning JS
 | 
| +    // proxies for the Dart DOM types so that the Dart DOM APIs for DOM types
 | 
| +    // are exposed in the debugger instead of the JS APIs.
 | 
| +    // We attempt to get the best of both worlds by providing the method
 | 
| +    // getJavaScriptType to let debugger APIs treat these Dart proxies for
 | 
| +    // DOM types like native DOM types for cases such as visual Node
 | 
| +    // highlighting.
 | 
| +
 | 
| +    DartDOMData* domData = DartDOMData::current();
 | 
| +    // FIXME: refactor code so we do not have to check for Dart_IsFunction.
 | 
| +    if (DartUtilities::isFunction(domData, value) || Dart_IsFunction(value)) {
 | 
| +        proxy = functionProxyTemplate()->InstanceTemplate()->NewInstance();
 | 
| +    } else {
 | 
| +        ASSERT(Dart_IsInstance(value));
 | 
| +        proxy = objectProxyTemplate(value)->InstanceTemplate()->NewInstance();
 | 
| +    }
 | 
| +    writePointerToProxy(proxy, value);
 | 
| +    proxy->SetHiddenValue(v8::String::NewFromUtf8(v8Isolate, "dartProxy"), v8::Boolean::New(v8Isolate, true));
 | 
| +
 | 
| +    return proxy;
 | 
| +}
 | 
| +
 | 
| +v8::Handle<v8::Value> DartHandleProxy::createTypeProxy(Dart_Handle value, bool showStatics)
 | 
| +{
 | 
| +    ASSERT(Dart_IsType(value));
 | 
| +    v8::Local<v8::Object> proxy = typeProxyTemplate(value)->InstanceTemplate()->NewInstance();
 | 
| +    writePointerToProxy(proxy, value);
 | 
| +    v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
 | 
| +    proxy->SetHiddenValue(v8::String::NewFromUtf8(v8Isolate, "dartProxy"), v8::Boolean::New(v8Isolate, true));
 | 
| +    proxy->SetHiddenValue(v8::String::NewFromUtf8(v8Isolate, "showStatics"), v8::Boolean::New(v8Isolate, showStatics));
 | 
| +    return proxy;
 | 
| +}
 | 
| +
 | 
| +/**
 | 
| + * Returns the JavaScript type name following the Chrome debugger conventions
 | 
| + * for Dart objects that have natural JavaScript analogs.
 | 
| + * This enables visually consistent display of Dart Lists and JavaScript arrays,
 | 
| + * functions, and DOM nodes.
 | 
| + */
 | 
| +const char* DartHandleProxy::getJavaScriptType(v8::Handle<v8::Value> value)
 | 
| +{
 | 
| +    DartPersistentValue* scriptValue = readPointerFromProxy(value);
 | 
| +    ASSERT(scriptValue->isIsolateAlive());
 | 
| +    DartIsolateScope scope(scriptValue->isolate());
 | 
| +    DartApiScope apiScope;
 | 
| +    Dart_PersistentHandle handle = scriptValue->value();
 | 
| +
 | 
| +    if (Dart_IsInstance(handle)) {
 | 
| +        if (Dart_IsList(handle))
 | 
| +            return "array";
 | 
| +
 | 
| +        if (DartUtilities::isNode(handle))
 | 
| +            return "node";
 | 
| +    }
 | 
| +
 | 
| +    return 0;
 | 
| +}
 | 
| +
 | 
| +Node* DartHandleProxy::toNativeNode(v8::Handle<v8::Value> value)
 | 
| +{
 | 
| +    DartPersistentValue* scriptValue = readPointerFromProxy(value);
 | 
| +    ASSERT(scriptValue->isIsolateAlive());
 | 
| +    DartIsolateScope scope(scriptValue->isolate());
 | 
| +    DartApiScope apiScope;
 | 
| +
 | 
| +    Dart_PersistentHandle handle = scriptValue->value();
 | 
| +    if (!DartUtilities::isNode(handle)) {
 | 
| +        // Not a DOM node.
 | 
| +        ASSERT_NOT_REACHED();
 | 
| +        return 0;
 | 
| +    }
 | 
| +    return DartUtilities::dartNodeToNativeNode(handle);
 | 
| +}
 | 
| +
 | 
| +/**
 | 
| + * Creates a proxy for a Dart library.
 | 
| + * If a string prefix is specified, we similuate that all requests to the library start with
 | 
| + * the specified prefix.
 | 
| + */
 | 
| +v8::Handle<v8::Value> DartHandleProxy::createLibraryProxy(Dart_Handle value, intptr_t libraryId, Dart_Handle prefix, bool asGlobal)
 | 
| +{
 | 
| +    v8::Context::Scope scope(DartUtilities::currentV8Context());
 | 
| +    ASSERT(Dart_IsLibrary(value));
 | 
| +    v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
 | 
| +    v8::Handle<v8::String> libraryNameV8 = Dart_IsNull(prefix) ? V8Converter::stringToV8(Dart_GetLibraryURL(libraryId)) : v8::String::NewFromUtf8(v8Isolate, "[Library Prefix]");
 | 
| +    v8::Local<v8::Object> proxy = libraryProxyTemplate(libraryNameV8)->InstanceTemplate()->NewInstance();
 | 
| +    writePointerToProxy(proxy, value);
 | 
| +    proxy->SetHiddenValue(v8::String::NewFromUtf8(v8Isolate, "libraryId"), v8::Number::New(v8Isolate, libraryId));
 | 
| +    if (Dart_IsString(prefix))
 | 
| +        proxy->SetHiddenValue(v8::String::NewFromUtf8(v8Isolate, "prefix"), V8Converter::stringToV8(prefix));
 | 
| +
 | 
| +    if (asGlobal)
 | 
| +        proxy->SetHiddenValue(v8::String::NewFromUtf8(v8Isolate, "asGlobal"), v8::Boolean::New(v8Isolate, true));
 | 
| +
 | 
| +    proxy->SetHiddenValue(v8::String::NewFromUtf8(v8Isolate, "dartProxy"), v8::Boolean::New(v8Isolate, true));
 | 
| +    return proxy;
 | 
| +}
 | 
| +
 | 
| +v8::Handle<v8::Value> DartHandleProxy::createLocalScopeProxy(Dart_Handle localVariables)
 | 
| +{
 | 
| +    v8::Local<v8::Object> proxy = frameProxyTemplate()->InstanceTemplate()->NewInstance();
 | 
| +    Dart_Handle localScopeVariableMap = createLocalVariablesMap(localVariables);
 | 
| +    ASSERT(!Dart_IsError(localScopeVariableMap));
 | 
| +    writePointerToProxy(proxy, localScopeVariableMap);
 | 
| +    v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
 | 
| +    proxy->SetHiddenValue(v8::String::NewFromUtf8(v8Isolate, "dartProxy"), v8::Boolean::New(v8Isolate, true));
 | 
| +    return proxy;
 | 
| +}
 | 
| +
 | 
| +v8::Handle<v8::Value> DartHandleProxy::evaluate(Dart_Handle target, Dart_Handle expression, Dart_Handle localVariables)
 | 
| +{
 | 
| +    DartDOMData* domData = DartDOMData::current();
 | 
| +    ASSERT(domData);
 | 
| +    ASSERT(Dart_IsList(localVariables) || Dart_IsNull(localVariables));
 | 
| +    v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
 | 
| +    if (V8Converter::stringToV8(expression)->Equals(v8::String::NewFromUtf8(v8Isolate, "@NamesInScope"))) {
 | 
| +        // Special case: return an object specifying all names that are in
 | 
| +        // scope for the current target. FIXME: we could handle this a lot more
 | 
| +        // efficiently given we don't really care what the values of the
 | 
| +        // variables are just that they are in scope.
 | 
| +        if (Dart_IsLibrary(target))
 | 
| +            return DartHandleProxy::createLibraryProxy(target, DartUtilities::libraryHandleToLibraryId(target), Dart_Null(), true);
 | 
| +        return DartHandleProxy::create(target);
 | 
| +    }
 | 
| +
 | 
| +    Dart_Handle exception = 0;
 | 
| +    bool ret = DartUtilities::dartToBool(DartUtilities::invokeUtilsMethod("isJsExpression", 1, &expression), exception);
 | 
| +    ASSERT(!exception);
 | 
| +    if (ret) {
 | 
| +        // FIXME(dartbug.com/13468): remove this hacky fallback of invoking JS
 | 
| +        // code when we believe a JS code fragment generated by the chrome
 | 
| +        // developer tools was passed to us rather than a fragment of true
 | 
| +        // Dart code.
 | 
| +        ASSERT(!v8Isolate->GetCurrentContext().IsEmpty());
 | 
| +        v8::Handle<v8::Value> result = V8ScriptRunner::compileAndRunInternalScript(V8Converter::stringToV8(expression), v8::Isolate::GetCurrent());
 | 
| +        return result;
 | 
| +    }
 | 
| +
 | 
| +    bool expectsConsoleApi = DartUtilities::dartToBool(DartUtilities::invokeUtilsMethod("expectsConsoleApi", 1, &expression), exception);
 | 
| +    ASSERT(!exception);
 | 
| +    if (expectsConsoleApi) {
 | 
| +        // Vector of local variables and injected console variables.
 | 
| +        Vector<Dart_Handle> locals;
 | 
| +        if (Dart_IsList(localVariables)) {
 | 
| +            DartUtilities::extractListElements(localVariables, exception, locals);
 | 
| +            ASSERT(!exception);
 | 
| +        }
 | 
| +        // Use JsInterop to proxy all properties and functions defined by
 | 
| +        // window.console._commandLineAPI
 | 
| +        v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
 | 
| +        v8::Handle<v8::Value> commandLineApiValue = v8Isolate->GetCurrentContext()->Global()->Get(v8::String::NewFromUtf8(v8Isolate, "__commandLineAPI"));
 | 
| +        ASSERT(commandLineApiValue->IsObject());
 | 
| +        if (commandLineApiValue->IsObject()) {
 | 
| +            v8::Handle<v8::Object> commandLineApi = commandLineApiValue.As<v8::Object>();
 | 
| +            v8::Local<v8::Array> propertyNames = commandLineApi->GetOwnPropertyNames();
 | 
| +            uint32_t length = propertyNames->Length();
 | 
| +            ASSERT(length > 0);
 | 
| +            for (uint32_t i = 0; i < length; i++) {
 | 
| +                v8::Handle<v8::String> propertyName = propertyNames->Get(i).As<v8::String>();
 | 
| +                ASSERT(!propertyNames.IsEmpty());
 | 
| +                v8::Handle<v8::Value> propertyValue = commandLineApi->Get(propertyName);
 | 
| +
 | 
| +                Dart_Handle dartValue;
 | 
| +                if (propertyValue->IsFunction()) {
 | 
| +                    dartValue = JsInterop::toDart(propertyValue);
 | 
| +                    // We need to wrap the JsFunction object we get back
 | 
| +                    // from the vanila JsInterop library so that users can
 | 
| +                    // call it like a normal Dart function instead of
 | 
| +                    // having to use the apply method.
 | 
| +                    dartValue = Dart_Invoke(domData->jsLibrary(), Dart_NewStringFromCString("_wrapAsDebuggerVarArgsFunction"), 1, &dartValue);
 | 
| +                } else {
 | 
| +                    dartValue = JsInterop::toDart(propertyValue);
 | 
| +                }
 | 
| +                locals.append(V8Converter::stringToDart(propertyName));
 | 
| +                locals.append(dartValue);
 | 
| +            }
 | 
| +        }
 | 
| +        localVariables = DartUtilities::toList(locals, exception);
 | 
| +        ASSERT(!exception);
 | 
| +    }
 | 
| +
 | 
| +    Dart_Handle wrapExpressionArgs[2] = { expression, localVariables };
 | 
| +    Dart_Handle wrappedExpressionTuple =
 | 
| +        DartUtilities::invokeUtilsMethod("wrapExpressionAsClosure", 2, wrapExpressionArgs);
 | 
| +    ASSERT(Dart_IsList(wrappedExpressionTuple));
 | 
| +    Dart_Handle wrappedExpression = Dart_ListGetAt(wrappedExpressionTuple, 0);
 | 
| +    Dart_Handle wrappedExpressionArgs = Dart_ListGetAt(wrappedExpressionTuple, 1);
 | 
| +
 | 
| +    ASSERT(Dart_IsString(wrappedExpression));
 | 
| +    Dart_Handle closure = Dart_EvaluateExpr(target, wrappedExpression);
 | 
| +    // There was a parse error. FIXME: consider cleaning up the line numbers in
 | 
| +    // the error message.
 | 
| +    if (Dart_IsError(closure))
 | 
| +        return V8ThrowException::throwException(v8::String::NewFromUtf8(v8Isolate, Dart_GetError(closure)), v8::Isolate::GetCurrent());
 | 
| +
 | 
| +    // Invoke the closure passing in the expression arguments specified by
 | 
| +    // wrappedExpressionTuple.
 | 
| +    ASSERT(DartUtilities::isFunction(domData, closure));
 | 
| +    intptr_t length = 0;
 | 
| +    Dart_ListLength(wrappedExpressionArgs, &length);
 | 
| +    Vector<Dart_Handle> dartFunctionArgs;
 | 
| +    for (intptr_t i = 0; i < length; i ++)
 | 
| +        dartFunctionArgs.append(Dart_ListGetAt(wrappedExpressionArgs, i));
 | 
| +
 | 
| +    Dart_Handle result = Dart_InvokeClosure(closure, dartFunctionArgs.size(), dartFunctionArgs.data());
 | 
| +    if (Dart_IsError(result))
 | 
| +        return V8ThrowException::throwException(v8::String::NewFromUtf8(v8Isolate, Dart_GetError(result)), v8::Isolate::GetCurrent());
 | 
| +    return DartHandleProxy::create(result);
 | 
| +}
 | 
| +
 | 
| +}
 | 
| 
 |