Chromium Code Reviews| Index: Source/bindings/dart/DartHandleProxy.cpp |
| diff --git a/Source/bindings/dart/DartHandleProxy.cpp b/Source/bindings/dart/DartHandleProxy.cpp |
| index 7a4c587878a9e4880eb367d83cb749500b104225..74626268ed963cb908b227991a851fc643127d3a 100644 |
| --- a/Source/bindings/dart/DartHandleProxy.cpp |
| +++ b/Source/bindings/dart/DartHandleProxy.cpp |
| @@ -28,19 +28,33 @@ |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| #include "config.h" |
| +#include "DartNode.h" |
| #include "bindings/dart/DartHandleProxy.h" |
| - |
| #include "bindings/dart/DartScriptValue.h" |
| #include "bindings/dart/DartUtilities.h" |
| #include "bindings/dart/V8Converter.h" |
| +#include "bindings/v8/PageScriptDebugServer.h" |
| +#include "bindings/v8/ScriptController.h" |
| +#include "bindings/v8/ScriptState.h" |
| +#include "bindings/v8/V8Binding.h" |
| + |
| +#include "core/platform/Logging.h" |
| + |
| +#include "wtf/StdLibExtras.h" |
| #include <dart_debugger_api.h> |
| namespace WebCore { |
| -static v8::Persistent<v8::FunctionTemplate> proxyTemplate(); |
| +typedef HashMap<String, v8::Persistent<v8::FunctionTemplate> > FunctionTemplateMap; |
| -static DartScriptValue* readPointerFromProxy(v8::Handle<v8::Value> proxy) |
| +static v8::Persistent<v8::FunctionTemplate> objectProxyTemplate(Dart_Handle instance); |
| +static v8::Persistent<v8::FunctionTemplate> functionProxyTemplate(); |
| +static v8::Persistent<v8::FunctionTemplate> libraryProxyTemplate(); |
| +static v8::Persistent<v8::FunctionTemplate> classProxyTemplate(Dart_Handle clazz); |
| +static v8::Persistent<v8::FunctionTemplate> frameProxyTemplate(); |
| + |
| +DartScriptValue* readPointerFromProxy(v8::Handle<v8::Value> proxy) |
| { |
| void* pointer = proxy.As<v8::Object>()->GetAlignedPointerFromInternalField(0); |
| return static_cast<DartScriptValue*>(pointer); |
| @@ -52,320 +66,979 @@ static void weakCallback(v8::Isolate* isolate, v8::Persistent<v8::Object>* proxy |
| proxy->Dispose(isolate); |
| } |
| -v8::Handle<v8::Value> DartHandleProxy::create(Dart_Handle value) |
| +static Dart_Handle unwrapValue(v8::Handle<v8::Value> value) |
| { |
| - v8::Context::Scope scope(DartUtilities::currentV8Context()); |
| + if (DartHandleProxy::isDartProxy(value)) { |
| + return Dart_HandleFromPersistent(readPointerFromProxy(value)->value()); |
| + } |
| + Dart_Handle exception = 0; |
| + Dart_Handle handle = V8Converter::toDart(value, exception); |
| + ASSERT(!exception); |
| + return handle; |
| +} |
| - if (Dart_IsNull(value)) |
| - return v8::Null(); |
| - if (Dart_IsString(value)) |
| - return V8Converter::stringToV8(value); |
| - if (Dart_IsBoolean(value)) |
| - return V8Converter::booleanToV8(value); |
| - if (Dart_IsNumber(value)) |
| - return V8Converter::numberToV8(value); |
| +bool libraryHasMember(Dart_Handle library, Dart_Handle name) |
|
Jacob
2013/07/11 18:52:27
Requested Dart API:
"LibraryHasMember" or somethin
|
| +{ |
| + return !Dart_IsError(Dart_GetField(library, name)) |
| + || !Dart_IsError(Dart_GetClass(library, name)) |
| + || Dart_IsFunction(Dart_LookupFunction(library, name)); |
| +} |
| - v8::Local<v8::Object> proxy = proxyTemplate()->InstanceTemplate()->NewInstance(); |
| - proxy->SetAlignedPointerInInternalField(0, new DartScriptValue(value)); |
| - v8::Isolate* isolate = v8::Isolate::GetCurrent(); |
| - v8::Persistent<v8::Object> persistentHandle = v8::Persistent<v8::Object>::New(isolate, proxy); |
| - persistentHandle.MakeWeak<v8::Object, void>(0, &weakCallback); |
| - proxy->Set(v8::String::New("isProxy"), v8::Boolean::New(true)); |
| - return proxy; |
| +bool classHasMember(Dart_Handle clazz, Dart_Handle name) |
| +{ |
|
Jacob
2013/07/11 18:52:27
Requested Dart Api:
"ClassHasMember"
would be nice
|
| + return !Dart_IsError(Dart_GetField(clazz, name)) || Dart_IsFunction(Dart_LookupFunction(clazz, name)); |
| } |
| -v8::Handle<v8::Value> DartHandleProxy::createForLibrary(intptr_t libraryId) |
| +Dart_Handle getEncodedMapKeyList(Dart_Handle object) |
| { |
| - Dart_Handle libraryURL = Dart_GetLibraryURL(libraryId); |
| - ASSERT(!Dart_IsError(libraryURL)); |
| - Dart_Handle library = Dart_LookupLibrary(libraryURL); |
| - v8::Handle<v8::Object> libraryProxy = create(library)->ToObject(); |
| - libraryProxy->SetHiddenValue(v8::String::New("libraryId"), v8::Number::New(libraryId)); |
| - return libraryProxy; |
| + return DartUtilities::invokeUtilsMethod("getEncodedMapKeyList", 1, &object); |
| } |
| -class DartReceiverScope { |
| -public: |
| - DartReceiverScope(const v8::Arguments& args) |
| - : m_receiver(readPointerFromProxy(args[0])) |
| - , m_isolateScope(m_receiver->isolate()) |
| - , m_apiScope() |
| - { |
| - } |
| +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 receiver() { return Dart_HandleFromPersistent(m_receiver->value()); } |
| +Dart_Handle lookupValueForEncodedMapKey(Dart_Handle object, Dart_Handle key) |
| +{ |
| + Dart_Handle args[] = {object, key}; |
| + return DartUtilities::invokeUtilsMethod("lookupValueForEncodedMapKey", 2, args); |
| +} |
| -private: |
| - DartScriptValue* m_receiver; |
| - DartIsolateScope m_isolateScope; |
| - DartApiScope m_apiScope; |
| -}; |
| +Dart_Handle buildConstructorName(Dart_Handle className, Dart_Handle constructorName) |
| +{ |
| + Dart_Handle args[] = {className, constructorName}; |
| + return DartUtilities::invokeUtilsMethod("buildConstructorName", 2, args); |
| +} |
| -static v8::Persistent<v8::FunctionTemplate> proxyTemplate() |
| +Dart_Handle stripClassName(Dart_Handle str, Dart_Handle className) |
| { |
| - static v8::Persistent<v8::FunctionTemplate> proxyTemplate; |
| - if (proxyTemplate.IsEmpty()) { |
| - proxyTemplate = v8::Persistent<v8::FunctionTemplate>::New(v8::Isolate::GetCurrent(), v8::FunctionTemplate::New()); |
| - v8::Local<v8::ObjectTemplate> instanceTemplate = proxyTemplate->InstanceTemplate(); |
| - instanceTemplate->SetInternalFieldCount(1); |
| + Dart_Handle args[] = {str, className}; |
| + return DartUtilities::invokeUtilsMethod("stripClassName", 2, args); |
| +} |
| + |
| +Dart_Handle isNode(Dart_Handle clazz) |
| +{ |
| + return DartUtilities::invokeUtilsMethod("isNode", 1, &clazz); |
| +} |
| + |
| +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); |
| + 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; |
| + |
| + if (isInstance && (isSetter || isStatic || isConstructor)) |
| + continue; |
| + } |
| + |
| + // Strip off the leading classname from constructor name. |
| + if (isConstructor) |
|
Jacob
2013/07/11 18:52:27
Nit: why are constructor names prefixed with the c
|
| + functionName = stripClassName(functionName, Dart_ClassName(handle)); |
| + |
| + properties->Set(*count, V8Converter::stringToV8(functionName)); |
| + *count = *count + 1; |
| } |
| - return proxyTemplate; |
| } |
| -static Dart_Handle unwrapValue(v8::Handle<v8::Value> value) |
| +void addClassNames(Dart_Handle library, v8::Local<v8::Array>& properties, intptr_t* count) |
| { |
| - if (proxyTemplate()->HasInstance(value)) |
| - return Dart_HandleFromPersistent(readPointerFromProxy(value)->value()); |
| - Dart_Handle exception = 0; |
| - Dart_Handle handle = V8Converter::toDart(value, exception); |
| - ASSERT(!exception); |
| - return handle; |
| + intptr_t length = 0; |
| + Dart_Handle classNames = Dart_LibraryGetClassNames(library); |
| + ASSERT(!Dart_IsNull(classNames)); |
| + ASSERT(Dart_IsList(classNames)); |
| + Dart_ListLength(classNames, &length); |
| + for (intptr_t i = 0; i < length; i++) { |
| + Dart_Handle className = Dart_ListGetAt(classNames, i); |
| + properties->Set(*count, V8Converter::stringToV8(className)); |
| + *count = *count + 1; |
| + } |
| +} |
| + |
| +void addFieldNames(intptr_t libraryId, v8::Local<v8::Array>& properties, intptr_t* count) |
| +{ |
| + intptr_t length = 0; |
| + Dart_Handle fieldNames = Dart_GetLibraryFields(libraryId); |
| + ASSERT(!Dart_IsNull(fieldNames)); |
| + ASSERT(Dart_IsList(fieldNames)); |
| + 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(fieldName)); |
| + *count = *count + 1; |
| + } |
| } |
| static v8::Handle<v8::Value> convertResult(Dart_Handle result) |
| { |
| if (Dart_IsError(result)) { |
| - // Consider wrapping not as a string, but as dedicated |
| - // exception wrapper. |
| - return v8::String::New("<Exception thrown>"); |
| + // 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); |
| + // return v8::Undefined(); |
| + |
| + return v8::ThrowException(v8::String::New(Dart_GetError(result))); |
| } |
| return DartHandleProxy::create(result); |
| } |
| -// --- Objects ---- |
| +void setDartHandleInternalField(v8::Local<v8::Object> proxy, Dart_Handle value) |
| +{ |
| + proxy->SetAlignedPointerInInternalField(0, new DartScriptValue(value)); |
| + v8::Isolate* isolate = v8::Isolate::GetCurrent(); |
| + v8::Persistent<v8::Object> persistentHandle = v8::Persistent<v8::Object>::New(isolate, proxy); |
| + persistentHandle.MakeWeak<v8::Object, void>(0, &weakCallback); |
| +} |
| -static v8::Handle<v8::Value> instanceGetClass(const v8::Arguments& args) |
| +intptr_t getLibraryId(v8::Local<v8::Object> proxy) |
| { |
| - DartReceiverScope scope(args); |
| - return convertResult(Dart_InstanceGetClass(scope.receiver())); |
| + return (intptr_t)proxy.As<v8::Object>()->GetHiddenValue(v8::String::NewSymbol("libraryId"))->Int32Value(); |
| } |
| -// --- Lists --- |
| +// Returns a String of the library prefix or Dart_Null if no prefix is found. |
| +Dart_Handle getLibraryPrefix(v8::Local<v8::Object> proxy) |
| +{ |
| + v8::Local<v8::Value> prefix = proxy.As<v8::Object>()->GetHiddenValue(v8::String::NewSymbol("prefix")); |
| + if (*prefix && prefix->IsString()) |
| + return V8Converter::stringToDart(prefix); |
| + return Dart_Null(); |
| +} |
| -static v8::Handle<v8::Value> isList(const v8::Arguments& args) |
| +static v8::Handle<v8::Value> functionNamedPropertyGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) |
| { |
| - DartReceiverScope scope(args); |
| - return v8::Boolean::New(Dart_IsList(scope.receiver())); |
| + DartScriptValue* scriptValue = readPointerFromProxy(info.This()); |
| + ASSERT(scriptValue->isIsolateAlive()); |
| + DartIsolateScope scope(scriptValue->isolate()); |
| + DartApiScope apiScope; |
| + Dart_Handle handle = Dart_HandleFromPersistent(scriptValue->value()); |
| + |
| + Dart_Handle ret; |
| + ASSERT(Dart_IsFunction(handle) || Dart_IsClosure(handle)); |
| + |
| + ret = Dart_Invoke(handle, V8Converter::stringToDart(v8::String::Concat(v8::String::New("get:"), name)), 0, 0); |
|
Jacob
2013/07/11 18:52:27
For classes, I can just call
Dart_Invoke with the
|
| + if (Dart_IsError(ret) && name->Equals(v8::String::NewSymbol("__proto__"))) |
| + return v8::Undefined(); |
| + |
| + return convertResult(ret); |
| } |
| -static v8::Handle<v8::Value> listGetAt(const v8::Arguments& args) |
| +static v8::Handle<v8::Value> functionNamedPropertySetter(v8::Local<v8::String> property, v8::Local<v8::Value> value, const v8::AccessorInfo& info) |
| { |
| - DartReceiverScope scope(args); |
| - return convertResult(Dart_ListGetAt(scope.receiver(), args[1]->Int32Value())); |
| + return throwError(v8ReferenceError, "Dart functions do not have writeable properties", v8::Isolate::GetCurrent()); |
| } |
| -static v8::Handle<v8::Value> listSetAt(const v8::Arguments& args) |
| +static v8::Handle<v8::Value> functionInvocationCallback(v8::Arguments const& args) |
| { |
| - DartReceiverScope scope(args); |
| - return convertResult(Dart_ListSetAt(scope.receiver(), args[1]->Int32Value(), unwrapValue(args[2]))); |
| + DartScriptValue* scriptValue = readPointerFromProxy(args.Holder()); |
| + ASSERT(scriptValue->isIsolateAlive()); |
| + DartIsolateScope scope(scriptValue->isolate()); |
| + DartApiScope apiScope; |
| + Dart_Handle handle = Dart_HandleFromPersistent(scriptValue->value()); |
| + |
| + ASSERT(Dart_IsFunction(handle) || Dart_IsClosure(handle)); |
| + bool isConstructor = false; |
| + Dart_FunctionIsConstructor(handle, &isConstructor); |
| + if (args.IsConstructCall() != isConstructor) { |
| + return throwError(v8ReferenceError, |
| + isConstructor ? "Constructor called without new" : "Regular function called as constructor", |
| + v8::Isolate::GetCurrent()); |
| + } |
| + |
| + Vector<Dart_Handle> dartFunctionArgs; |
| + for (uint32_t i = 0; i < args.Length(); ++i) |
| + dartFunctionArgs.append(unwrapValue(args[i])); |
| + |
| + if (Dart_IsClosure(handle)) |
| + return convertResult(Dart_InvokeClosure(handle, dartFunctionArgs.size(), dartFunctionArgs.data())); |
| + Dart_Handle clazz = Dart_FunctionOwner(handle); |
| + if (isConstructor) |
| + // FIXME: this seems like an overly complex way to have to invoke a constructor. |
|
Jacob
2013/07/11 18:52:27
nit: this seems more complex than needed.
|
| + return convertResult( |
| + Dart_New(clazz, stripClassName(Dart_FunctionName(handle), Dart_ClassName(clazz)), |
| + dartFunctionArgs.size(), dartFunctionArgs.data())); |
| + else |
| + return convertResult( |
| + Dart_Invoke(clazz, Dart_FunctionName(handle), dartFunctionArgs.size(), dartFunctionArgs.data())); |
| } |
| -// --- Classes and Interfaces --- |
| +static v8::Handle<v8::Value> classProxyConstructorInvocationCallback(v8::Arguments const& args) |
| +{ |
| + DartScriptValue* scriptValue = readPointerFromProxy(args.Holder()); |
| + ASSERT(scriptValue->isIsolateAlive()); |
| + DartIsolateScope scope(scriptValue->isolate()); |
| + DartApiScope apiScope; |
| + Dart_Handle handle = Dart_HandleFromPersistent(scriptValue->value()); |
| + |
| + ASSERT(Dart_IsClass(handle)); |
| -static v8::Handle<v8::Value> className(const v8::Arguments& args) |
| + if (!args.IsConstructCall()) |
| + return throwError(v8SyntaxError, "Constructors can only be invoked with 'new'", v8::Isolate::GetCurrent()); |
| + |
| + Vector<Dart_Handle> dartFunctionArgs; |
| + for (uint32_t i = 0; i < args.Length(); ++i) |
| + dartFunctionArgs.append(unwrapValue(args[i])); |
| + |
| + return convertResult(Dart_New(handle, Dart_Null(), dartFunctionArgs.size(), dartFunctionArgs.data())); |
| +} |
| + |
| +void getImportedLibrariesMatchingPrefix(int32_t libraryId, Dart_Handle prefix, Vector<std::pair<Dart_Handle, intptr_t> >* libraries) |
|
Jacob
2013/07/11 18:52:27
It would be nice if I didn't have to do all this w
|
| { |
| - DartReceiverScope scope(args); |
| - return convertResult(Dart_ClassName(scope.receiver())); |
| + Dart_Handle imports = Dart_GetLibraryImports(libraryId); |
| + ASSERT(!Dart_IsError(imports)); |
| + // Unfortunately dart_debugger_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 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 v8::Handle<v8::Value> classGetLibrary(const v8::Arguments& args) |
| +static v8::Handle<v8::Value> libraryNamedPropertyGetterHelper(Dart_Handle library, Dart_Handle dartName, bool* handled) |
| { |
|
Jacob
2013/07/11 18:52:27
would be nice if I could just call Dart_Invoke ins
|
| - DartReceiverScope scope(args); |
| - return convertResult(Dart_ClassGetLibrary(scope.receiver())); |
| + Dart_Handle ret; |
| + ret = Dart_GetField(library, dartName); |
| + if (!Dart_IsApiError(ret)) { |
| + *handled = true; |
| + return convertResult(ret); |
| + } |
| + |
| + ret = Dart_GetClass(library, dartName); |
| + if (!Dart_IsError(ret)) { |
| + *handled = true; |
| + return convertResult(ret); |
| + } |
| + |
| + ret = Dart_LookupFunction(library, dartName); |
| + if (!Dart_IsNull(ret) && !Dart_IsError(ret)) { |
|
Jacob
2013/07/15 18:03:26
why do i have a null check here?
|
| + *handled = true; |
| + return convertResult(ret); |
| + } |
| + return v8::Undefined(); |
| } |
| -static v8::Handle<v8::Value> getSuperclass(const v8::Arguments& args) |
| +static v8::Handle<v8::Value> libraryNamedPropertyGetterHelper(v8::Local<v8::String> name, |
| + const v8::AccessorInfo& info, bool* handled) |
| { |
|
Jacob
2013/07/11 18:52:27
This is a mess due to handling prefixes.
It would
|
| - DartReceiverScope scope(args); |
| - return convertResult(Dart_GetSuperclass(scope.receiver())); |
| + DartScriptValue* scriptValue = readPointerFromProxy(info.This()); |
| + ASSERT(scriptValue->isIsolateAlive()); |
| + DartIsolateScope scope(scriptValue->isolate()); |
| + DartApiScope apiScope; |
| + Dart_Handle handle = Dart_HandleFromPersistent(scriptValue->value()); |
| + |
| + Dart_Handle ret; |
| + ASSERT(Dart_IsLibrary(handle)); |
| + intptr_t libraryId = getLibraryId(info.This()); |
| + Dart_Handle dartName = V8Converter::stringToDart(name); |
| + Dart_Handle prefix = getLibraryPrefix(info.This()); |
| + 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++) { |
| + v8::Handle<v8::Value> returnValue = libraryNamedPropertyGetterHelper(libraries[i].first, dartName, handled); |
| + if (*handled) |
| + return returnValue; |
| + } |
| + } else { |
| + v8::Handle<v8::Value> returnValue = libraryNamedPropertyGetterHelper(handle, dartName, handled); |
| + if (*handled) |
| + return returnValue; |
| + |
| + // 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) { |
| + *handled = true; |
| + return DartHandleProxy::createLibraryProxy(handle, libraryId, dartName); |
| + } |
| + } |
| + |
| + if (name->Equals(v8::String::NewSymbol("__proto__"))) { |
| + *handled = true; |
| + return v8::Null(); |
| + } |
| + return v8::Undefined(); |
| } |
| -// --- Function and Variable Declarations --- |
| +static v8::Handle<v8::Value> libraryNamedPropertyGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) |
| +{ |
| + bool handled = false; |
| + v8::Handle<v8::Value> ret = libraryNamedPropertyGetterHelper(name, info, &handled); |
| + if (handled) |
| + return ret; |
| + return v8::ThrowException(v8::Exception::ReferenceError(v8::String::Concat(name, v8::String::New(" is not defined")))); |
| +} |
| -static v8::Handle<v8::Value> getFunctionNames(const v8::Arguments& args) |
| +// TODO(jacobr): need to handle prefixes in this case as well. |
| +// Before checkin, handle prefixes correctly. |
| +static v8::Handle<v8::Value> libraryNamedPropertySetter(v8::Local<v8::String> property, v8::Local<v8::Value> value, const v8::AccessorInfo& info) |
| { |
| - DartReceiverScope scope(args); |
| - return V8Converter::listToV8(Dart_GetFunctionNames(scope.receiver())); |
| + DartScriptValue* scriptValue = readPointerFromProxy(info.This()); |
| + ASSERT(scriptValue->isIsolateAlive()); |
| + DartIsolateScope scope(scriptValue->isolate()); |
| + DartApiScope apiScope; |
| + Dart_Handle handle = Dart_HandleFromPersistent(scriptValue->value()); |
| + |
| + Dart_Handle ret; |
| + ASSERT(Dart_IsLibrary(handle)); |
| + Dart_Handle dartValue = unwrapValue(value); |
| + ret = Dart_SetField(handle, V8Converter::stringToDart(property), dartValue); |
| + return convertResult(ret); |
| } |
| -static v8::Handle<v8::Value> getClassNames(const v8::Arguments& args) |
| +static v8::Handle<v8::Integer> libraryQueryProperty(v8::Local<v8::String> name, const v8::AccessorInfo& info) |
| { |
| - DartReceiverScope scope(args); |
| - Dart_Handle classNames = Dart_LibraryGetClassNames(scope.receiver()); |
| - ASSERT(!Dart_IsError(classNames) && !Dart_IsNull(classNames)); |
| - return V8Converter::listToV8(classNames); |
| + bool handled = false; |
| + libraryNamedPropertyGetterHelper(name, info, &handled); |
| + return handled ? v8Integer(0, info.GetIsolate()) : v8::Handle<v8::Integer>(); |
| } |
| -static v8::Handle<v8::Value> lookupClass(const v8::Arguments& args) |
| +void libraryEnumerateHelper(Dart_Handle library, intptr_t libraryId, v8::Local<v8::Array> properties, intptr_t* count) |
| { |
| - DartReceiverScope scope(args); |
| - return convertResult(Dart_GetClass(scope.receiver(), V8Converter::stringToDart(args[1]))); |
| + addFunctionNames(library, properties, count, false, false); |
| + addClassNames(library, properties, count); |
| + addFieldNames(libraryId, properties, count); |
| } |
| -static v8::Handle<v8::Value> lookupFunction(const v8::Arguments& args) |
| +static v8::Handle<v8::Array> libraryPropertyEnumerator(const v8::AccessorInfo& info) |
| { |
|
Jacob
2013/07/11 18:52:27
It would be nice if Dart libraries provided a meth
|
| - DartReceiverScope scope(args); |
| + DartScriptValue* scriptValue = readPointerFromProxy(info.This()); |
| + ASSERT(scriptValue->isIsolateAlive()); |
| + DartIsolateScope scope(scriptValue->isolate()); |
| + DartApiScope apiScope; |
| + Dart_Handle handle = Dart_HandleFromPersistent(scriptValue->value()); |
| - Dart_Handle function = Dart_LookupFunction(scope.receiver(), V8Converter::stringToDart(args[1])); |
| - ASSERT(!Dart_IsError(function) && !Dart_IsNull(function)); |
| + intptr_t libraryId = getLibraryId(info.This()); |
| + ASSERT(Dart_IsLibrary(handle)); |
| + v8::Local<v8::Array> cachedProperties = info.This().As<v8::Object>()->GetHiddenValue(v8::String::NewSymbol("cache")).As<v8::Array>(); |
| + if (*cachedProperties) |
| + return cachedProperties; |
| - Dart_Handle result; |
| - UNUSED_PARAM(result); |
| + Dart_Handle prefix = getLibraryPrefix(info.This()); |
| + bool hasLibraryPrefix = Dart_IsString(prefix); |
| - bool isAbstract; |
| - result = Dart_FunctionIsAbstract(function, &isAbstract); |
| - ASSERT(!Dart_IsError(result)); |
| - bool isStatic; |
| - result = Dart_FunctionIsStatic(function, &isStatic); |
| - ASSERT(!Dart_IsError(result)); |
| - bool isConstructor; |
| - result = Dart_FunctionIsConstructor(function, &isConstructor); |
| - ASSERT(!Dart_IsError(result)); |
| - bool isGetter; |
| - result = Dart_FunctionIsGetter(function, &isGetter); |
| - ASSERT(!Dart_IsError(result)); |
| - bool isSetter; |
| - result = Dart_FunctionIsSetter(function, &isSetter); |
| - ASSERT(!Dart_IsError(result)); |
| - int64_t fixedParameterCount; |
| - int64_t optionalParamerterCount; |
| - result = Dart_FunctionParameterCounts(function, &fixedParameterCount, &optionalParamerterCount); |
| - ASSERT(!Dart_IsError(result)); |
| + v8::Local<v8::Array> properties = v8::Array::New(); |
| + intptr_t count = 0; |
| - v8::Handle<v8::Object> description = v8::Object::New(); |
| - description->Set(v8::String::New("isAbstract"), v8::Boolean::New(isAbstract)); |
| - description->Set(v8::String::New("isStatic"), v8::Boolean::New(isStatic)); |
| - description->Set(v8::String::New("isConstructor"), v8::Boolean::New(isConstructor)); |
| - description->Set(v8::String::New("isGetter"), v8::Boolean::New(isGetter)); |
| - description->Set(v8::String::New("isSetter"), v8::Boolean::New(isSetter)); |
| - description->Set(v8::String::New("fixedParameterCount"), v8::Integer::New(fixedParameterCount)); |
| - description->Set(v8::String::New("optionalParamerterCount"), v8::Integer::New(optionalParamerterCount)); |
| - return description; |
| + if (hasLibraryPrefix) { |
| + Vector<std::pair<Dart_Handle, intptr_t> > libraries; |
| + getImportedLibrariesMatchingPrefix(libraryId, prefix, &libraries); |
| + for (intptr_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( |
| + stripTrailingDot(importPrefix))); |
| + count++; |
| + } |
| + bool equals = false; |
| + } |
| + } |
| + info.This()->SetHiddenValue(v8::String::NewSymbol("cache"), properties); |
| + return properties; |
| } |
| -static v8::Handle<v8::Value> getVariableNames(const v8::Arguments& args) |
| +static v8::Handle<v8::Value> classNamedPropertyGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) |
| { |
| - DartReceiverScope scope(args); |
| - return V8Converter::listToV8(Dart_GetVariableNames(scope.receiver())); |
| + DartScriptValue* scriptValue = readPointerFromProxy(info.This()); |
| + ASSERT(scriptValue->isIsolateAlive()); |
| + DartIsolateScope scope(scriptValue->isolate()); |
| + DartApiScope apiScope; |
| + Dart_Handle handle = Dart_HandleFromPersistent(scriptValue->value()); |
| + |
| + Dart_Handle ret; |
| + ASSERT(Dart_IsClass(handle)); |
| + // XXX hack... remove... FILE A BUG! |
| + bool isDynamic = false; |
|
Jacob
2013/07/11 18:52:27
What should we do about the class "dynamic".
It ex
|
| + Dart_ObjectEquals(Dart_ClassName(handle), Dart_NewStringFromCString("dynamic"), &isDynamic); |
| + |
| + if (!Dart_ClassIsTypedef(handle) && !Dart_ClassIsFunctionType(handle) && !isDynamic) { |
|
Jacob
2013/07/11 18:52:27
Similarly to the case of Library, it would be nice
|
| + |
| + Dart_Handle dartName = V8Converter::stringToDart(name); |
| + ret = Dart_GetField(handle, dartName); |
| + if (!Dart_IsError(ret)) |
| + return convertResult(ret); |
| + ret = Dart_LookupFunction(handle, dartName); |
| + if (!Dart_IsNull(ret) && !Dart_IsError(ret)) |
| + return convertResult(ret); |
| + |
| + Dart_Handle className = Dart_ClassName(handle); |
| + ASSERT(Dart_IsString(className)); |
| + Dart_Handle constructorName = buildConstructorName(className, V8Converter::stringToDart(name)); |
| + ret = Dart_LookupFunction(handle, constructorName); |
| + if (!Dart_IsNull(ret) && !Dart_IsError(ret)) |
| + return convertResult(ret); |
| + } |
| + |
| + if (name->Equals(v8::String::NewSymbol("__proto__"))) { |
| + Dart_Handle superclass = Dart_GetSuperclass(handle); |
| + if (!Dart_IsError(superclass)) |
| + return DartHandleProxy::create(superclass); |
| + return v8::Undefined(); |
| + } |
| + return v8::ThrowException(v8::Exception::ReferenceError(v8::String::Concat(name, v8::String::New(" is not defined")))); |
| } |
| -static v8::Handle<v8::Value> lookupVariable(const v8::Arguments& args) |
| +static v8::Handle<v8::Value> classNamedPropertySetter(v8::Local<v8::String> property, v8::Local<v8::Value> value, const v8::AccessorInfo& info) |
| { |
| - DartReceiverScope scope(args); |
| - Dart_Handle variable = Dart_LookupVariable(scope.receiver(), V8Converter::stringToDart(args[1])); |
| - ASSERT(!Dart_IsError(variable) && !Dart_IsNull(variable)); |
| + DartScriptValue* scriptValue = readPointerFromProxy(info.This()); |
| + ASSERT(scriptValue->isIsolateAlive()); |
| + DartIsolateScope scope(scriptValue->isolate()); |
| + DartApiScope apiScope; |
| + Dart_Handle handle = Dart_HandleFromPersistent(scriptValue->value()); |
| - Dart_Handle result; |
| - UNUSED_PARAM(result); |
| + Dart_Handle ret; |
| + ASSERT(Dart_IsClass(handle)); |
| + Dart_Handle dartValue = unwrapValue(value); |
| + ret = Dart_Invoke(handle, V8Converter::stringToDart(v8::String::Concat(v8::String::New("set:"), property)), 1, &dartValue); |
|
Jacob
2013/07/11 18:52:27
TODO(jacobr): similar to the case of Libraries, th
|
| + return convertResult(ret); |
| +} |
| - bool isStatic; |
| - result = Dart_VariableIsStatic(variable, &isStatic); |
| - ASSERT(!Dart_IsError(result)); |
| - bool isFinal; |
| - result = Dart_VariableIsFinal(variable, &isFinal); |
| - ASSERT(!Dart_IsError(result)); |
| +static v8::Handle<v8::Integer> classQueryProperty(v8::Local<v8::String> name, const v8::AccessorInfo& info) |
| +{ |
| + DartScriptValue* scriptValue = readPointerFromProxy(info.This()); |
| + ASSERT(scriptValue->isIsolateAlive()); |
| + DartIsolateScope scope(scriptValue->isolate()); |
| + DartApiScope apiScope; |
| + Dart_Handle handle = Dart_HandleFromPersistent(scriptValue->value()); |
| - v8::Local<v8::Object> description = v8::Object::New(); |
| - description->Set(v8::String::New("isStatic"), v8::Boolean::New(isStatic)); |
| - description->Set(v8::String::New("isFinal"), v8::Boolean::New(isFinal)); |
| - return description; |
| + Dart_Handle ret; |
| + ASSERT(Dart_IsClass(handle)); |
| + if (classHasMember(handle, V8Converter::stringToDart(name))) |
| + return v8Integer(0, info.GetIsolate()); |
| + return v8::Handle<v8::Integer>(); |
| } |
| -// --- Constructors, Methods, and Fields --- |
| +static v8::Handle<v8::Array> classPropertyEnumerator(const v8::AccessorInfo& info) |
| +{ |
| + DartScriptValue* scriptValue = readPointerFromProxy(info.This()); |
| + ASSERT(scriptValue->isIsolateAlive()); |
| + DartIsolateScope scope(scriptValue->isolate()); |
| + DartApiScope apiScope; |
| + Dart_Handle handle = Dart_HandleFromPersistent(scriptValue->value()); |
| + |
| + ASSERT(Dart_IsClass(handle)); |
| -static v8::Handle<v8::Value> invoke(const v8::Arguments& args) |
| + v8::Local<v8::Array> properties = v8::Array::New(); |
| + intptr_t count = 0; |
| + addFunctionNames(handle, properties, &count, false, false); |
|
Jacob
2013/07/11 18:52:27
it would be nice if there was just an Dart API met
|
| + return properties; |
| +} |
| + |
| +// Returns the index in the list of the property if it is found, -1 otherwise. |
| +static int findMatchingNamedProperty(Dart_Handle list, v8::Local<v8::String> name) |
| { |
| - DartReceiverScope scope(args); |
| - Vector<Dart_Handle> dartFunctionArgs; |
| - v8::Handle<v8::Array> v8FunctionArgs = args[2].As<v8::Array>(); |
| - for (uint32_t i = 0; i < v8FunctionArgs->Length(); ++i) |
| - dartFunctionArgs.append(unwrapValue(v8FunctionArgs->Get(i))); |
| - return convertResult(Dart_Invoke(scope.receiver(), V8Converter::stringToDart(args[1]), dartFunctionArgs.size(), dartFunctionArgs.data())); |
| + // FIXME: perhaps push this logic into Dart code instead. |
| + v8::String::Utf8Value stringValue(name); |
| + const char* nameData = *stringValue; |
| + intptr_t nameLength = stringValue.length(); |
| + |
| + intptr_t length = 0; |
| + Dart_ListLength(list, &length); |
| + for (intptr_t i = 0; i < length; i += 2) { |
| + intptr_t candidateNameLength = 0; |
| + uint8_t* candidateData = 0; |
| + intptr_t candidateLength = 0; |
| + Dart_StringToUTF8(Dart_ListGetAt(list, i), &candidateData, &candidateLength); |
| + if ((candidateLength >= nameLength |
| + && (candidateLength == nameLength || candidateData[nameLength] == '@')) |
| + && !memcmp(candidateData, nameData, nameLength)) |
| + return i / 2; |
| + } |
| + return -1; |
| } |
| -static v8::Handle<v8::Value> dartNew(const v8::Arguments& args) |
| +static v8::Handle<v8::Value> frameNamedPropertyGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) |
| { |
|
Jacob
2013/07/11 18:52:27
It would be nice if the local frame was just expos
|
| - DartReceiverScope scope(args); |
| - Vector<Dart_Handle> dartConstructorArgs; |
| - v8::Handle<v8::Array> v8ConstructorArgs = args[2].As<v8::Array>(); |
| - for (uint32_t i = 0; i < v8ConstructorArgs->Length(); ++i) |
| - dartConstructorArgs.append(unwrapValue(v8ConstructorArgs->Get(i))); |
| - return convertResult(Dart_New(scope.receiver(), V8Converter::stringToDart(args[1]), dartConstructorArgs.size(), dartConstructorArgs.data())); |
| + DartScriptValue* scriptValue = readPointerFromProxy(info.This()); |
| + ASSERT(scriptValue->isIsolateAlive()); |
| + DartIsolateScope scope(scriptValue->isolate()); |
| + DartApiScope apiScope; |
| + Dart_Handle handle = Dart_HandleFromPersistent(scriptValue->value()); |
| + |
| + ASSERT(Dart_IsList(handle)); |
| + int index = findMatchingNamedProperty(handle, name); |
| + if (index != -1) |
| + return convertResult(Dart_ListGetAt(handle, index * 2 + 1)); |
| + if (name->Equals(v8::String::NewSymbol("this"))) |
| + return v8::Undefined(); |
| + return v8::ThrowException(v8::Exception::ReferenceError(v8::String::Concat(name, v8::String::New(" is not defined")))); |
| } |
| -static v8::Handle<v8::Value> getField(const v8::Arguments& args) |
| +static v8::Handle<v8::Value> frameNamedPropertySetter(v8::Local<v8::String> property, v8::Local<v8::Value> value, const v8::AccessorInfo& info) |
| { |
|
Jacob
2013/07/11 18:52:27
This is the one case where we can't manipulate Dat
|
| - DartReceiverScope scope(args); |
| + return throwError(v8ReferenceError, "Dart does not yet provide a debugger api for setting local fields", v8::Isolate::GetCurrent()); |
| +} |
| + |
| +static v8::Handle<v8::Integer> frameQueryProperty(v8::Local<v8::String> name, const v8::AccessorInfo& info) |
| +{ |
| + DartScriptValue* scriptValue = readPointerFromProxy(info.This()); |
| + ASSERT(scriptValue->isIsolateAlive()); |
| + DartIsolateScope scope(scriptValue->isolate()); |
| + DartApiScope apiScope; |
| + Dart_Handle handle = Dart_HandleFromPersistent(scriptValue->value()); |
| - return convertResult(Dart_GetField(scope.receiver(), V8Converter::stringToDart(args[1]))); |
| + ASSERT(Dart_IsList(handle)); |
| + int index = findMatchingNamedProperty(handle, name); |
| + return index == -1 ? v8::Handle<v8::Integer>() : v8Integer(0, info.GetIsolate()); |
| } |
| -static v8::Handle<v8::Value> setField(const v8::Arguments& args) |
| +static v8::Handle<v8::Array> framePropertyEnumerator(const v8::AccessorInfo& info) |
| { |
| - DartReceiverScope scope(args); |
| - v8::Handle<v8::Array> v8FunctionArgs = args[2].As<v8::Array>(); |
| - ASSERT(v8FunctionArgs->Length() == 1); |
| - return convertResult(Dart_SetField(scope.receiver(), V8Converter::stringToDart(args[1]), unwrapValue(v8FunctionArgs->Get(0)))); |
| + DartScriptValue* scriptValue = readPointerFromProxy(info.This()); |
| + ASSERT(scriptValue->isIsolateAlive()); |
| + DartIsolateScope scope(scriptValue->isolate()); |
| + DartApiScope apiScope; |
| + Dart_Handle handle = Dart_HandleFromPersistent(scriptValue->value()); |
| + |
| + ASSERT(Dart_IsList(handle)); |
| + |
| + intptr_t length = 0; |
| + Dart_ListLength(handle, &length); |
| + v8::Local<v8::Array> properties = v8::Array::New(length / 2); |
| + for (intptr_t i = 0; i < length; i += 2) { |
| + // Truncate everything after the '@'. |
|
Jacob
2013/07/11 18:52:27
it would be nice if there was an option to get nam
|
| + // TODO(jacobr): we shouldn't have to do this, there should be an API that provides |
| + // Mirror APIs on frames directly. |
| + const char* nameData = 0; |
| + Dart_StringToCString(Dart_ListGetAt(handle, i), &nameData); |
| + ASSERT(nameData); |
| + if (!nameData) |
| + continue; |
| + |
| + intptr_t nameLength = strlen(nameData); |
| + |
| + for (intptr_t j = 0; j < nameLength; j++) { |
| + if (nameData[j] == '@') { |
| + nameLength = j; |
| + break; |
| + } |
| + } |
| + properties->Set(i / 2, v8::String::New(nameData, nameLength)); |
| + } |
| + return properties; |
| } |
| -// --- Scripts and Libraries --- |
| +static v8::Handle<v8::Value> namedPropertyGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) |
| +{ |
| + DartScriptValue* scriptValue = readPointerFromProxy(info.This()); |
| + ASSERT(scriptValue->isIsolateAlive()); |
| + DartIsolateScope scope(scriptValue->isolate()); |
| + DartApiScope apiScope; |
| + Dart_Handle handle = Dart_HandleFromPersistent(scriptValue->value()); |
| + |
| + Dart_Handle ret; |
| + ASSERT(Dart_IsInstance(handle)); |
| + 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. |
| + return convertResult( |
| + lookupValueForEncodedMapKey(handle, V8Converter::stringToDart(name))); |
| + } |
| + |
| + ret = Dart_Invoke(handle, V8Converter::stringToDart(v8::String::Concat(v8::String::New("get:"), name)), 0, 0); |
| + if (Dart_IsError(ret) && name->Equals(v8::String::NewSymbol("__proto__"))) |
| + return DartHandleProxy::create(Dart_GetObjClass(handle)); |
| + |
| + return convertResult(ret); |
| +} |
| -static v8::Handle<v8::Value> libraryName(const v8::Arguments& args) |
| +static v8::Handle<v8::Value> namedPropertySetter(v8::Local<v8::String> property, v8::Local<v8::Value> value, const v8::AccessorInfo& info) |
| { |
| - DartReceiverScope scope(args); |
| - return convertResult(Dart_LibraryName(scope.receiver())); |
| + DartScriptValue* scriptValue = readPointerFromProxy(info.This()); |
| + ASSERT(scriptValue->isIsolateAlive()); |
| + DartIsolateScope scope(scriptValue->isolate()); |
| + DartApiScope apiScope; |
| + Dart_Handle handle = Dart_HandleFromPersistent(scriptValue->value()); |
| + |
| + Dart_Handle ret; |
| + Dart_Handle dartValue = unwrapValue(value); |
| + ret = Dart_Invoke(handle, V8Converter::stringToDart(v8::String::Concat(v8::String::New("set:"), property)), 1, &dartValue); |
| + if (Dart_IsError(ret)) { |
| + Dart_Handle dartPropertyName = V8Converter::stringToDart(property); |
| + Dart_Handle indexedGetterOperator = Dart_NewStringFromCString("[]="); |
| + Dart_Handle args[] = {dartPropertyName, dartValue}; |
| + ret = Dart_Invoke(handle, indexedGetterOperator, 2, args); |
| + } |
| + return convertResult(ret); |
| } |
| -static v8::Handle<v8::Value> libraryUrl(const v8::Arguments& args) |
| +// FIXME: duplicated code with getter. XXX |
| +static v8::Handle<v8::Integer> objectQueryProperty(v8::Local<v8::String> name, const v8::AccessorInfo& info) |
| { |
| - DartReceiverScope scope(args); |
| - return convertResult(Dart_LibraryUrl(scope.receiver())); |
| + DartScriptValue* scriptValue = readPointerFromProxy(info.This()); |
| + ASSERT(scriptValue->isIsolateAlive()); |
| + DartIsolateScope scope(scriptValue->isolate()); |
| + DartApiScope apiScope; |
| + Dart_Handle handle = Dart_HandleFromPersistent(scriptValue->value()); |
| + |
| + 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] == '#') |
| + return v8Integer(0, info.GetIsolate()); |
| + |
| + ret = Dart_Invoke(handle, V8Converter::stringToDart(v8::String::Concat(v8::String::New("get:"), name)), 0, 0); |
| + if (Dart_IsError(ret)) { |
| + if (name->Equals(v8::String::NewSymbol("__proto__"))) |
| + return v8Integer(0, info.GetIsolate()); |
| + return v8::Handle<v8::Integer>(); |
| + } |
| + return v8Integer(0, info.GetIsolate()); |
| } |
| -static v8::Handle<v8::Value> libraryImports(const v8::Arguments& args) |
| +static v8::Handle<v8::Array> objectPropertyEnumerator(const v8::AccessorInfo& info) |
| { |
| - DartReceiverScope scope(args); |
| - int32_t libraryId = args[0].As<v8::Object>()->GetHiddenValue(v8::String::New("libraryId"))->Int32Value(); |
| - Dart_Handle imports = Dart_GetLibraryImports(libraryId); |
| - ASSERT(!Dart_IsError(imports)); |
| + DartScriptValue* scriptValue = readPointerFromProxy(info.This()); |
| + ASSERT(scriptValue->isIsolateAlive()); |
| + DartIsolateScope scope(scriptValue->isolate()); |
| + DartApiScope apiScope; |
| + Dart_Handle handle = Dart_HandleFromPersistent(scriptValue->value()); |
| + |
| + ASSERT(Dart_IsInstance(handle)); |
| + |
| + Dart_Handle typeHandle; |
| + if (Dart_IsInstance(handle)) |
| + typeHandle = Dart_InstanceGetClass(handle); |
| + else |
| + typeHandle = handle; |
| + |
| + v8::Local<v8::Array> properties = v8::Array::New(); |
| + 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(imports, &length); |
| - v8::Handle<v8::Array> result = v8::Array::New(); |
| + Dart_ListLength(instanceFields, &length); |
| for (intptr_t i = 0; i < length; i += 2) { |
| - Dart_Handle prefix = Dart_ListGetAt(imports, i); |
| - result->Set(i, DartHandleProxy::create(prefix)); |
| - Dart_Handle importedLibraryIdHandle = Dart_ListGetAt(imports, i + 1); |
| - ASSERT(Dart_IsInteger(importedLibraryIdHandle)); |
| - int64_t importedLibraryId; |
| - Dart_IntegerToInt64(importedLibraryIdHandle, &importedLibraryId); |
| - result->Set(i + 1, DartHandleProxy::createForLibrary(importedLibraryId)); |
| + properties->Set(count, DartHandleProxy::create( |
| + Dart_ListGetAt(instanceFields, i))); |
| + count++; |
| + } |
| + |
| + while (!Dart_IsError(typeHandle) && !Dart_IsNull(typeHandle)) { |
| + intptr_t interfaceCount = 0; |
| + Dart_ClassGetInterfaceCount(typeHandle, &interfaceCount); |
| + for (intptr_t i = 0; i < interfaceCount; i++) { |
| + addFunctionNames(Dart_ClassGetInterfaceAt(typeHandle, i), |
| + properties, &count, true, true); |
| + } |
| + // TODO(jacobr): is this duplicated work? |
| + addFunctionNames(typeHandle, properties, &count, true, true); |
| + typeHandle = Dart_GetSuperclass(typeHandle); |
| + } |
| + return properties; |
| +} |
| + |
| +static v8::Handle<v8::Value> indexedGetter(uint32_t index, const v8::AccessorInfo& info) |
| +{ |
| + DartScriptValue* scriptValue = readPointerFromProxy(info.This()); |
| + ASSERT(scriptValue->isIsolateAlive()); |
| + DartIsolateScope scope(scriptValue->isolate()); |
| + DartApiScope apiScope; |
| + Dart_Handle handle = Dart_HandleFromPersistent(scriptValue->value()); |
| + |
| + Dart_Handle ret = 0; |
| + if (Dart_IsList(handle)) |
| + ret = Dart_ListGetAt(handle, index); |
| + else |
| + ret = Dart_Null(); |
| + |
| + return convertResult(ret); |
| +} |
| + |
| +static v8::Handle<v8::Value> indexedSetter(uint32_t index, v8::Local<v8::Value> value, const v8::AccessorInfo& info) |
| +{ |
| + DartScriptValue* scriptValue = readPointerFromProxy(info.This()); |
| + ASSERT(scriptValue->isIsolateAlive()); |
| + DartIsolateScope scope(scriptValue->isolate()); |
| + DartApiScope apiScope; |
| + Dart_Handle handle = Dart_HandleFromPersistent(scriptValue->value()); |
| + |
| + Dart_Handle ret = 0; |
| + if (Dart_IsList(handle)) |
| + ret = Dart_ListSetAt(handle, index, unwrapValue(value)); |
| + else |
| + ret = Dart_Null(); |
| + |
| + return convertResult(ret); |
| +} |
| + |
| +static v8::Handle<v8::Array> indexedEnumerator(const v8::AccessorInfo& info) |
| +{ |
| + DartScriptValue* scriptValue = readPointerFromProxy(info.This()); |
| + ASSERT(scriptValue->isIsolateAlive()); |
| + DartIsolateScope scope(scriptValue->isolate()); |
| + DartApiScope apiScope; |
| + Dart_Handle handle = Dart_HandleFromPersistent(scriptValue->value()); |
| + |
| + intptr_t length = 0; |
| + if (Dart_IsList(handle)) |
| + Dart_ListLength(handle, &length); |
| + |
| + v8::Local<v8::Array> indexes = v8::Array::New(length); |
| + for (int i = 0; i < length; i++) |
| + indexes->Set(i, v8::Integer::New(i)); |
| + |
| + return indexes; |
| +} |
| + |
| +static v8::Local<v8::ObjectTemplate> setupInstanceTemplate(v8::Persistent<v8::FunctionTemplate> proxyTemplate) |
| +{ |
| + v8::Local<v8::ObjectTemplate> instanceTemplate = proxyTemplate->InstanceTemplate(); |
| + instanceTemplate->SetInternalFieldCount(1); |
| + return instanceTemplate; |
| +} |
| + |
| +static v8::Persistent<v8::FunctionTemplate> objectProxyTemplate(Dart_Handle instance) |
| +{ |
| + DEFINE_STATIC_LOCAL(FunctionTemplateMap, map, ()); |
| + // FIXME: we should switch to Dart_InstanceGetType when possible. |
| + Dart_Handle dartType = Dart_InstanceGetClass(instance); |
| + ASSERT(!Dart_IsError(dartType)); |
| + Dart_Handle classNameHandle = Dart_ClassName(dartType); |
| + ASSERT(!Dart_IsError(classNameHandle)); |
| + if (Dart_IsError(classNameHandle)) |
| + classNameHandle = Dart_NewStringFromCString("MYSTERY DART CLAZZ XXX"); |
| + ASSERT(!Dart_IsError(classNameHandle)); |
| + v8::Handle<v8::String> classNameV8 = V8Converter::stringToV8(classNameHandle); |
| + String className = toWebCoreString(classNameV8); |
| + v8::Persistent<v8::FunctionTemplate> proxyTemplate = map.get(className); |
| + |
| + if (proxyTemplate.IsEmpty()) { |
| + proxyTemplate = v8::Persistent<v8::FunctionTemplate>::New(v8::Isolate::GetCurrent(), v8::FunctionTemplate::New()); |
| + proxyTemplate->SetClassName(classNameV8); |
| + map.set(className, proxyTemplate); |
| + v8::Local<v8::ObjectTemplate> instanceTemplate = setupInstanceTemplate(proxyTemplate); |
| + instanceTemplate->SetIndexedPropertyHandler(&indexedGetter, &indexedSetter, 0, 0, &indexedEnumerator); |
| + instanceTemplate->SetNamedPropertyHandler(&namedPropertyGetter, &namedPropertySetter, &objectQueryProperty, 0, &objectPropertyEnumerator); |
| + } |
| + return proxyTemplate; |
| +} |
| + |
| +static v8::Persistent<v8::FunctionTemplate> functionProxyTemplate() |
| +{ |
| + static v8::Persistent<v8::FunctionTemplate> proxyTemplate; |
| + if (proxyTemplate.IsEmpty()) { |
| + proxyTemplate = v8::Persistent<v8::FunctionTemplate>::New(v8::Isolate::GetCurrent(), v8::FunctionTemplate::New()); |
| + proxyTemplate->SetClassName(v8::String::New("[Dart Function]")); |
| + v8::Local<v8::ObjectTemplate> instanceTemplate = setupInstanceTemplate(proxyTemplate); |
| + instanceTemplate->SetNamedPropertyHandler(&functionNamedPropertyGetter, &functionNamedPropertySetter); |
| + instanceTemplate->SetCallAsFunctionHandler(&functionInvocationCallback); |
| } |
| - return result; |
| -} |
| - |
| -void DartHandleProxy::getMirrorAPI(v8::Handle<v8::Object> container) |
| -{ |
| - V8Scope v8scope; |
| - container->Set(v8::String::New("instanceGetClass"), v8::FunctionTemplate::New(&instanceGetClass)->GetFunction()); |
| - container->Set(v8::String::New("isList"), v8::FunctionTemplate::New(&isList)->GetFunction()); |
| - container->Set(v8::String::New("listGetAt"), v8::FunctionTemplate::New(&listGetAt)->GetFunction()); |
| - container->Set(v8::String::New("listSetAt"), v8::FunctionTemplate::New(&listSetAt)->GetFunction()); |
| - container->Set(v8::String::New("className"), v8::FunctionTemplate::New(&className)->GetFunction()); |
| - container->Set(v8::String::New("classGetLibrary"), v8::FunctionTemplate::New(&classGetLibrary)->GetFunction()); |
| - container->Set(v8::String::New("getSuperclass"), v8::FunctionTemplate::New(&getSuperclass)->GetFunction()); |
| - container->Set(v8::String::New("getFunctionNames"), v8::FunctionTemplate::New(&getFunctionNames)->GetFunction()); |
| - container->Set(v8::String::New("getClassNames"), v8::FunctionTemplate::New(&getClassNames)->GetFunction()); |
| - container->Set(v8::String::New("lookupFunction"), v8::FunctionTemplate::New(&lookupFunction)->GetFunction()); |
| - container->Set(v8::String::New("lookupClass"), v8::FunctionTemplate::New(&lookupClass)->GetFunction()); |
| - container->Set(v8::String::New("getVariableNames"), v8::FunctionTemplate::New(&getVariableNames)->GetFunction()); |
| - container->Set(v8::String::New("lookupVariable"), v8::FunctionTemplate::New(&lookupVariable)->GetFunction()); |
| - container->Set(v8::String::New("invoke"), v8::FunctionTemplate::New(&invoke)->GetFunction()); |
| - container->Set(v8::String::New("dartNew"), v8::FunctionTemplate::New(&dartNew)->GetFunction()); |
| - container->Set(v8::String::New("getField"), v8::FunctionTemplate::New(&getField)->GetFunction()); |
| - container->Set(v8::String::New("setField"), v8::FunctionTemplate::New(&setField)->GetFunction()); |
| - container->Set(v8::String::New("libraryName"), v8::FunctionTemplate::New(&libraryName)->GetFunction()); |
| - container->Set(v8::String::New("libraryUrl"), v8::FunctionTemplate::New(&libraryUrl)->GetFunction()); |
| - container->Set(v8::String::New("libraryImports"), v8::FunctionTemplate::New(&libraryImports)->GetFunction()); |
| + return proxyTemplate; |
| +} |
| + |
| +static v8::Persistent<v8::FunctionTemplate> libraryProxyTemplate() |
| +{ |
| + static v8::Persistent<v8::FunctionTemplate> proxyTemplate; |
| + if (proxyTemplate.IsEmpty()) { |
| + proxyTemplate = v8::Persistent<v8::FunctionTemplate>::New(v8::Isolate::GetCurrent(), v8::FunctionTemplate::New()); |
| + proxyTemplate->SetClassName(v8::String::New("[Dart Library]")); |
| + v8::Local<v8::ObjectTemplate> instanceTemplate = setupInstanceTemplate(proxyTemplate); |
| + instanceTemplate->SetNamedPropertyHandler(&libraryNamedPropertyGetter, &libraryNamedPropertySetter, &libraryQueryProperty, 0, &libraryPropertyEnumerator); |
| + } |
| + return proxyTemplate; |
| +} |
| + |
| +static v8::Persistent<v8::FunctionTemplate> classProxyTemplate(Dart_Handle clazz) |
| +{ |
| + DEFINE_STATIC_LOCAL(FunctionTemplateMap, map, ()); |
| + Dart_Handle classNameHandle = Dart_ClassName(clazz); |
| + ASSERT(!Dart_IsError(classNameHandle)); |
| + v8::Handle<v8::String> classNameV8 = V8Converter::stringToV8(classNameHandle); |
| + String className = toWebCoreString(classNameV8); |
| + |
| + v8::Persistent<v8::FunctionTemplate> proxyTemplate = map.get(className); |
| + if (proxyTemplate.IsEmpty()) { |
| + proxyTemplate = v8::Persistent<v8::FunctionTemplate>::New(v8::Isolate::GetCurrent(), v8::FunctionTemplate::New()); |
| + proxyTemplate->SetClassName(classNameV8); |
| + v8::Local<v8::ObjectTemplate> instanceTemplate = setupInstanceTemplate(proxyTemplate); |
| + instanceTemplate->SetNamedPropertyHandler(&classNamedPropertyGetter, &classNamedPropertySetter, &classQueryProperty, 0, &classPropertyEnumerator); |
| + instanceTemplate->SetCallAsFunctionHandler(&classProxyConstructorInvocationCallback); |
| + map.set(className, proxyTemplate); |
| + } |
| + return proxyTemplate; |
| +} |
| + |
| +static v8::Persistent<v8::FunctionTemplate> frameProxyTemplate() |
| +{ |
| + static v8::Persistent<v8::FunctionTemplate> proxyTemplate; |
| + if (proxyTemplate.IsEmpty()) { |
| + proxyTemplate = v8::Persistent<v8::FunctionTemplate>::New(v8::Isolate::GetCurrent(), v8::FunctionTemplate::New()); |
| + proxyTemplate->SetClassName(v8::String::New("[Dart Frame]")); |
| + v8::Local<v8::ObjectTemplate> instanceTemplate = setupInstanceTemplate(proxyTemplate); |
| + instanceTemplate->SetNamedPropertyHandler(&frameNamedPropertyGetter, &frameNamedPropertySetter, &frameQueryProperty, 0, &framePropertyEnumerator); |
| + } |
| + return proxyTemplate; |
| +} |
| + |
| +v8::Handle<v8::Value> DartHandleProxy::create(Dart_Handle value) |
| +{ |
| + v8::Context::Scope scope(DartUtilities::currentV8Context()); |
| + |
| + if (Dart_IsNull(value)) |
| + return v8::Null(); |
| + 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; |
| + // TODO(jacobr): could optimize the order of these checks. |
| + if (Dart_IsFunction(value) || Dart_IsClosure(value)) |
| + proxy = functionProxyTemplate()->InstanceTemplate()->NewInstance(); |
| + else if (Dart_IsInstance(value)) |
| + proxy = objectProxyTemplate(value)->InstanceTemplate()->NewInstance(); |
| + else { |
| + ASSERT(Dart_IsClass(value)); |
| + proxy = classProxyTemplate(value)->InstanceTemplate()->NewInstance(); |
| + } |
| + setDartHandleInternalField(proxy, value); |
| + proxy->SetHiddenValue(v8::String::NewSymbol("dartProxy"), v8::Boolean::New(true)); |
| + |
| + return proxy; |
| +} |
| + |
| +bool DartHandleProxy::isDartProxy(v8::Handle<v8::Value> value) |
| +{ |
| + if (value->IsObject()) { |
| + v8::Local<v8::Value> hiddenValue = value.As<v8::Object>()->GetHiddenValue(v8::String::NewSymbol("dartProxy")); |
| + return *hiddenValue && hiddenValue->IsBoolean(); |
| + } |
| + return false; |
| +} |
| + |
| +const char* DartHandleProxy::getType(v8::Handle<v8::Value> value) { |
| + DartScriptValue* scriptValue = readPointerFromProxy(value); |
| + ASSERT(scriptValue->isIsolateAlive()); |
| + DartIsolateScope scope(scriptValue->isolate()); |
| + DartApiScope apiScope; |
| + Dart_Handle handle = Dart_HandleFromPersistent(scriptValue->value()); |
| + |
| + if (Dart_IsInstance(handle)) { |
| + if (Dart_IsList(handle)) |
| + return "array"; |
| + |
| + Dart_Handle exception = 0; |
| + if (DartUtilities::dartToBool(isNode(handle), exception)) |
| + return "node"; |
| + ASSERT(!exception); |
| + } |
| + |
| + return 0; |
| +} |
| + |
| +Node* DartHandleProxy::toNativeNode(v8::Handle<v8::Value> value) { |
| + DartScriptValue* scriptValue = readPointerFromProxy(value); |
| + ASSERT(scriptValue->isIsolateAlive()); |
| + DartIsolateScope scope(scriptValue->isolate()); |
| + DartApiScope apiScope; |
| + Dart_Handle handle = Dart_HandleFromPersistent(scriptValue->value()); |
| + Dart_Handle exception = 0; |
| + Node* node = DartNode::toNative(handle, exception); |
| + ASSERT(!exception); |
| + return node; |
| +} |
| + |
| +/** |
| + * 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, int32_t libraryId, Dart_Handle prefix) |
| +{ |
|
Jacob
2013/07/11 18:52:27
why do I have to keep around both a handle to a li
|
| + v8::Context::Scope scope(DartUtilities::currentV8Context()); |
| + ASSERT(Dart_IsLibrary(value)); |
| + v8::Local<v8::Object> proxy = libraryProxyTemplate()->InstanceTemplate()->NewInstance(); |
| + setDartHandleInternalField(proxy, value); |
| + proxy->SetHiddenValue(v8::String::NewSymbol("libraryId"), v8::Number::New(libraryId)); |
| + if (Dart_IsString(prefix)) |
| + proxy->SetHiddenValue(v8::String::NewSymbol("prefix"), V8Converter::stringToV8(prefix)); |
| + |
| + proxy->SetHiddenValue(v8::String::NewSymbol("dartProxy"), v8::Boolean::New(true)); |
| + return proxy; |
| +} |
| + |
| +v8::Handle<v8::Value> DartHandleProxy::createLocalScopeProxy(Dart_Handle localVariables) |
| +{ |
| + v8::Local<v8::Object> proxy = frameProxyTemplate()->InstanceTemplate()->NewInstance(); |
| + setDartHandleInternalField(proxy, localVariables); |
| + proxy->SetHiddenValue(v8::String::NewSymbol("dartProxy"), v8::Boolean::New(true)); |
| + return proxy; |
| } |
| } |