Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(805)

Unified Diff: runtime/vm/mirrors_api_impl.cc

Issue 16973003: Split dart_api.h into multiple parts: (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/dart_api_message.h ('k') | runtime/vm/native_api_impl.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/mirrors_api_impl.cc
===================================================================
--- runtime/vm/mirrors_api_impl.cc (revision 0)
+++ runtime/vm/mirrors_api_impl.cc (revision 0)
@@ -0,0 +1,869 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "include/dart_mirrors_api.h"
+
+#include "platform/assert.h"
+#include "vm/class_finalizer.h"
+#include "vm/dart.h"
+#include "vm/dart_api_impl.h"
+#include "vm/dart_api_state.h"
+#include "vm/dart_entry.h"
+#include "vm/exceptions.h"
+#include "vm/growable_array.h"
+#include "vm/object.h"
+#include "vm/resolver.h"
+#include "vm/stack_frame.h"
+#include "vm/symbols.h"
+
+namespace dart {
+
+// When we want to return a handle to a type to the user, we handle
+// class-types differently than some other types.
+static Dart_Handle TypeToHandle(Isolate* isolate,
+ const char* function_name,
+ const AbstractType& type) {
+ if (type.IsMalformed()) {
+ const Error& error = Error::Handle(type.malformed_error());
+ return Api::NewError("%s: malformed type encountered: %s.",
+ function_name, error.ToErrorCString());
+ } else if (type.HasResolvedTypeClass()) {
+ const Class& cls = Class::Handle(isolate, type.type_class());
+#if defined(DEBUG)
+ const Library& lib = Library::Handle(cls.library());
+ if (lib.IsNull()) {
+ ASSERT(cls.IsDynamicClass() || cls.IsVoidClass());
+ }
+#endif
+ return Api::NewHandle(isolate, cls.raw());
+ } else if (type.IsTypeParameter()) {
+ return Api::NewHandle(isolate, type.raw());
+ } else {
+ return Api::NewError("%s: unexpected type '%s' encountered.",
+ function_name, type.ToCString());
+ }
+}
+
+
+// --- Classes and Interfaces Reflection ---
+
+DART_EXPORT Dart_Handle Dart_ClassName(Dart_Handle clazz) {
+ Isolate* isolate = Isolate::Current();
+ DARTSCOPE(isolate);
+ const Class& cls = Api::UnwrapClassHandle(isolate, clazz);
+ if (cls.IsNull()) {
+ RETURN_TYPE_ERROR(isolate, clazz, Class);
+ }
+ return Api::NewHandle(isolate, cls.UserVisibleName());
+}
+
+
+DART_EXPORT Dart_Handle Dart_ClassGetLibrary(Dart_Handle clazz) {
+ Isolate* isolate = Isolate::Current();
+ DARTSCOPE(isolate);
+ const Class& cls = Api::UnwrapClassHandle(isolate, clazz);
+ if (cls.IsNull()) {
+ RETURN_TYPE_ERROR(isolate, clazz, Class);
+ }
+
+#if defined(DEBUG)
+ const Library& lib = Library::Handle(cls.library());
+ if (lib.IsNull()) {
+ // ASSERT(cls.IsDynamicClass() || cls.IsVoidClass());
+ if (!cls.IsDynamicClass() && !cls.IsVoidClass()) {
+ fprintf(stderr, "NO LIBRARY: %s\n", cls.ToCString());
+ }
+ }
+#endif
+
+ return Api::NewHandle(isolate, cls.library());
+}
+
+
+DART_EXPORT Dart_Handle Dart_ClassGetInterfaceCount(Dart_Handle clazz,
+ intptr_t* count) {
+ Isolate* isolate = Isolate::Current();
+ DARTSCOPE(isolate);
+ const Class& cls = Api::UnwrapClassHandle(isolate, clazz);
+ if (cls.IsNull()) {
+ RETURN_TYPE_ERROR(isolate, clazz, Class);
+ }
+
+ const Array& interface_types = Array::Handle(isolate, cls.interfaces());
+ if (interface_types.IsNull()) {
+ *count = 0;
+ } else {
+ *count = interface_types.Length();
+ }
+ return Api::Success();
+}
+
+
+DART_EXPORT Dart_Handle Dart_ClassGetInterfaceAt(Dart_Handle clazz,
+ intptr_t index) {
+ Isolate* isolate = Isolate::Current();
+ DARTSCOPE(isolate);
+ const Class& cls = Api::UnwrapClassHandle(isolate, clazz);
+ if (cls.IsNull()) {
+ RETURN_TYPE_ERROR(isolate, clazz, Class);
+ }
+
+ // Finalize all classes.
+ Dart_Handle state = Api::CheckIsolateState(isolate);
+ if (::Dart_IsError(state)) {
+ return state;
+ }
+
+ const Array& interface_types = Array::Handle(isolate, cls.interfaces());
+ if (index < 0 || index >= interface_types.Length()) {
+ return Api::NewError("%s: argument 'index' out of bounds.", CURRENT_FUNC);
+ }
+ Type& interface_type = Type::Handle(isolate);
+ interface_type ^= interface_types.At(index);
+ if (interface_type.HasResolvedTypeClass()) {
+ return Api::NewHandle(isolate, interface_type.type_class());
+ }
+ const String& type_name =
+ String::Handle(isolate, interface_type.TypeClassName());
+ return Api::NewError("%s: internal error: found unresolved type class '%s'.",
+ CURRENT_FUNC, type_name.ToCString());
+}
+
+
+DART_EXPORT bool Dart_ClassIsTypedef(Dart_Handle clazz) {
+ Isolate* isolate = Isolate::Current();
+ DARTSCOPE(isolate);
+ const Class& cls = Api::UnwrapClassHandle(isolate, clazz);
+ if (cls.IsNull()) {
+ RETURN_TYPE_ERROR(isolate, clazz, Class);
+ }
+ // For now we represent typedefs as non-canonical signature classes.
+ // I anticipate this may change if we make typedefs more general.
+ return cls.IsSignatureClass() && !cls.IsCanonicalSignatureClass();
+}
+
+
+DART_EXPORT Dart_Handle Dart_ClassGetTypedefReferent(Dart_Handle clazz) {
+ Isolate* isolate = Isolate::Current();
+ DARTSCOPE(isolate);
+ const Class& cls = Api::UnwrapClassHandle(isolate, clazz);
+ if (cls.IsNull()) {
+ RETURN_TYPE_ERROR(isolate, clazz, Class);
+ }
+
+ if (!cls.IsSignatureClass() && !cls.IsCanonicalSignatureClass()) {
+ const String& cls_name = String::Handle(cls.UserVisibleName());
+ return Api::NewError("%s: class '%s' is not a typedef class. "
+ "See Dart_ClassIsTypedef.",
+ CURRENT_FUNC, cls_name.ToCString());
+ }
+
+ const Function& func = Function::Handle(isolate, cls.signature_function());
+ return Api::NewHandle(isolate, func.signature_class());
+}
+
+
+DART_EXPORT bool Dart_ClassIsFunctionType(Dart_Handle clazz) {
+ Isolate* isolate = Isolate::Current();
+ DARTSCOPE(isolate);
+ const Class& cls = Api::UnwrapClassHandle(isolate, clazz);
+ if (cls.IsNull()) {
+ RETURN_TYPE_ERROR(isolate, clazz, Class);
+ }
+ // A class represents a function type when it is a canonical
+ // signature class.
+ return cls.IsCanonicalSignatureClass();
+}
+
+
+DART_EXPORT Dart_Handle Dart_ClassGetFunctionTypeSignature(Dart_Handle clazz) {
+ Isolate* isolate = Isolate::Current();
+ DARTSCOPE(isolate);
+ const Class& cls = Api::UnwrapClassHandle(isolate, clazz);
+ if (cls.IsNull()) {
+ RETURN_TYPE_ERROR(isolate, clazz, Class);
+ }
+ if (!cls.IsCanonicalSignatureClass()) {
+ const String& cls_name = String::Handle(cls.UserVisibleName());
+ return Api::NewError("%s: class '%s' is not a function-type class. "
+ "See Dart_ClassIsFunctionType.",
+ CURRENT_FUNC, cls_name.ToCString());
+ }
+ return Api::NewHandle(isolate, cls.signature_function());
+}
+
+
+// --- Function and Variable Reflection ---
+
+// Outside of the vm, we expose setter names with a trailing '='.
+static bool HasExternalSetterSuffix(const String& name) {
+ return name.CharAt(name.Length() - 1) == '=';
+}
+
+
+static RawString* RemoveExternalSetterSuffix(const String& name) {
+ ASSERT(HasExternalSetterSuffix(name));
+ return String::SubString(name, 0, name.Length() - 1);
+}
+
+
+DART_EXPORT Dart_Handle Dart_GetFunctionNames(Dart_Handle target) {
+ Isolate* isolate = Isolate::Current();
+ DARTSCOPE(isolate);
+ const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(target));
+ if (obj.IsError()) {
+ return target;
+ }
+
+ const GrowableObjectArray& names =
+ GrowableObjectArray::Handle(isolate, GrowableObjectArray::New());
+ Function& func = Function::Handle();
+ String& name = String::Handle();
+
+ if (obj.IsClass()) {
+ const Class& cls = Class::Cast(obj);
+ const Error& error = Error::Handle(isolate, cls.EnsureIsFinalized(isolate));
+ if (!error.IsNull()) {
+ return Api::NewHandle(isolate, error.raw());
+ }
+ const Array& func_array = Array::Handle(cls.functions());
+
+ // Some special types like 'dynamic' have a null functions list.
+ if (!func_array.IsNull()) {
+ for (intptr_t i = 0; i < func_array.Length(); ++i) {
+ func ^= func_array.At(i);
+
+ // Skip implicit getters and setters.
+ if (func.kind() == RawFunction::kImplicitGetter ||
+ func.kind() == RawFunction::kImplicitSetter ||
+ func.kind() == RawFunction::kConstImplicitGetter ||
+ func.kind() == RawFunction::kMethodExtractor) {
+ continue;
+ }
+
+ name = func.UserVisibleName();
+ names.Add(name);
+ }
+ }
+ } else if (obj.IsLibrary()) {
+ const Library& lib = Library::Cast(obj);
+ DictionaryIterator it(lib);
+ Object& obj = Object::Handle();
+ while (it.HasNext()) {
+ obj = it.GetNext();
+ if (obj.IsFunction()) {
+ func ^= obj.raw();
+ name = func.UserVisibleName();
+ names.Add(name);
+ }
+ }
+ } else {
+ return Api::NewError(
+ "%s expects argument 'target' to be a class or library.",
+ CURRENT_FUNC);
+ }
+ return Api::NewHandle(isolate, Array::MakeArray(names));
+}
+
+
+DART_EXPORT Dart_Handle Dart_LookupFunction(Dart_Handle target,
+ Dart_Handle function_name) {
+ Isolate* isolate = Isolate::Current();
+ DARTSCOPE(isolate);
+ const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(target));
+ if (obj.IsError()) {
+ return target;
+ }
+ const String& func_name = Api::UnwrapStringHandle(isolate, function_name);
+ if (func_name.IsNull()) {
+ RETURN_TYPE_ERROR(isolate, function_name, String);
+ }
+
+ Function& func = Function::Handle(isolate);
+ String& tmp_name = String::Handle(isolate);
+ if (obj.IsClass()) {
+ const Class& cls = Class::Cast(obj);
+
+ // Case 1. Lookup the unmodified function name.
+ func = cls.LookupFunctionAllowPrivate(func_name);
+
+ // Case 2. Lookup the function without the external setter suffix
+ // '='. Make sure to do this check after the regular lookup, so
+ // that we don't interfere with operator lookups (like ==).
+ if (func.IsNull() && HasExternalSetterSuffix(func_name)) {
+ tmp_name = RemoveExternalSetterSuffix(func_name);
+ tmp_name = Field::SetterName(tmp_name);
+ func = cls.LookupFunctionAllowPrivate(tmp_name);
+ }
+
+ // Case 3. Lookup the funciton with the getter prefix prepended.
+ if (func.IsNull()) {
+ tmp_name = Field::GetterName(func_name);
+ func = cls.LookupFunctionAllowPrivate(tmp_name);
+ }
+
+ // Case 4. Lookup the function with a . appended to find the
+ // unnamed constructor.
+ if (func.IsNull()) {
+ tmp_name = String::Concat(func_name, Symbols::Dot());
+ func = cls.LookupFunctionAllowPrivate(tmp_name);
+ }
+ } else if (obj.IsLibrary()) {
+ const Library& lib = Library::Cast(obj);
+
+ // Case 1. Lookup the unmodified function name.
+ func = lib.LookupFunctionAllowPrivate(func_name);
+
+ // Case 2. Lookup the function without the external setter suffix
+ // '='. Make sure to do this check after the regular lookup, so
+ // that we don't interfere with operator lookups (like ==).
+ if (func.IsNull() && HasExternalSetterSuffix(func_name)) {
+ tmp_name = RemoveExternalSetterSuffix(func_name);
+ tmp_name = Field::SetterName(tmp_name);
+ func = lib.LookupFunctionAllowPrivate(tmp_name);
+ }
+
+ // Case 3. Lookup the function with the getter prefix prepended.
+ if (func.IsNull()) {
+ tmp_name = Field::GetterName(func_name);
+ func = lib.LookupFunctionAllowPrivate(tmp_name);
+ }
+ } else {
+ return Api::NewError(
+ "%s expects argument 'target' to be a class or library.",
+ CURRENT_FUNC);
+ }
+
+#if defined(DEBUG)
+ if (!func.IsNull()) {
+ // We only provide access to a subset of function kinds.
+ RawFunction::Kind func_kind = func.kind();
+ ASSERT(func_kind == RawFunction::kRegularFunction ||
+ func_kind == RawFunction::kGetterFunction ||
+ func_kind == RawFunction::kSetterFunction ||
+ func_kind == RawFunction::kConstructor);
+ }
+#endif
+ return Api::NewHandle(isolate, func.raw());
+}
+
+
+DART_EXPORT Dart_Handle Dart_FunctionName(Dart_Handle function) {
+ Isolate* isolate = Isolate::Current();
+ DARTSCOPE(isolate);
+ const Function& func = Api::UnwrapFunctionHandle(isolate, function);
+ if (func.IsNull()) {
+ RETURN_TYPE_ERROR(isolate, function, Function);
+ }
+ return Api::NewHandle(isolate, func.UserVisibleName());
+}
+
+
+DART_EXPORT Dart_Handle Dart_FunctionOwner(Dart_Handle function) {
+ Isolate* isolate = Isolate::Current();
+ DARTSCOPE(isolate);
+ const Function& func = Api::UnwrapFunctionHandle(isolate, function);
+ if (func.IsNull()) {
+ RETURN_TYPE_ERROR(isolate, function, Function);
+ }
+ if (func.IsNonImplicitClosureFunction()) {
+ RawFunction* parent_function = func.parent_function();
+ return Api::NewHandle(isolate, parent_function);
+ }
+ const Class& owner = Class::Handle(func.Owner());
+ ASSERT(!owner.IsNull());
+ if (owner.IsTopLevel()) {
+ // Top-level functions are implemented as members of a hidden class. We hide
+ // that class here and instead answer the library.
+#if defined(DEBUG)
+ const Library& lib = Library::Handle(owner.library());
+ if (lib.IsNull()) {
+ ASSERT(owner.IsDynamicClass() || owner.IsVoidClass());
+ }
+#endif
+ return Api::NewHandle(isolate, owner.library());
+ } else {
+ return Api::NewHandle(isolate, owner.raw());
+ }
+}
+
+
+DART_EXPORT Dart_Handle Dart_FunctionIsAbstract(Dart_Handle function,
+ bool* is_abstract) {
+ Isolate* isolate = Isolate::Current();
+ DARTSCOPE(isolate);
+ if (is_abstract == NULL) {
+ RETURN_NULL_ERROR(is_abstract);
+ }
+ const Function& func = Api::UnwrapFunctionHandle(isolate, function);
+ if (func.IsNull()) {
+ RETURN_TYPE_ERROR(isolate, function, Function);
+ }
+ *is_abstract = func.is_abstract();
+ return Api::Success();
+}
+
+
+DART_EXPORT Dart_Handle Dart_FunctionIsStatic(Dart_Handle function,
+ bool* is_static) {
+ Isolate* isolate = Isolate::Current();
+ DARTSCOPE(isolate);
+ if (is_static == NULL) {
+ RETURN_NULL_ERROR(is_static);
+ }
+ const Function& func = Api::UnwrapFunctionHandle(isolate, function);
+ if (func.IsNull()) {
+ RETURN_TYPE_ERROR(isolate, function, Function);
+ }
+ *is_static = func.is_static();
+ return Api::Success();
+}
+
+
+DART_EXPORT Dart_Handle Dart_FunctionIsConstructor(Dart_Handle function,
+ bool* is_constructor) {
+ Isolate* isolate = Isolate::Current();
+ DARTSCOPE(isolate);
+ if (is_constructor == NULL) {
+ RETURN_NULL_ERROR(is_constructor);
+ }
+ const Function& func = Api::UnwrapFunctionHandle(isolate, function);
+ if (func.IsNull()) {
+ RETURN_TYPE_ERROR(isolate, function, Function);
+ }
+ *is_constructor = func.kind() == RawFunction::kConstructor;
+ return Api::Success();
+}
+
+
+DART_EXPORT Dart_Handle Dart_FunctionIsGetter(Dart_Handle function,
+ bool* is_getter) {
+ Isolate* isolate = Isolate::Current();
+ DARTSCOPE(isolate);
+ if (is_getter == NULL) {
+ RETURN_NULL_ERROR(is_getter);
+ }
+ const Function& func = Api::UnwrapFunctionHandle(isolate, function);
+ if (func.IsNull()) {
+ RETURN_TYPE_ERROR(isolate, function, Function);
+ }
+ *is_getter = func.IsGetterFunction();
+ return Api::Success();
+}
+
+
+DART_EXPORT Dart_Handle Dart_FunctionIsSetter(Dart_Handle function,
+ bool* is_setter) {
+ Isolate* isolate = Isolate::Current();
+ DARTSCOPE(isolate);
+ if (is_setter == NULL) {
+ RETURN_NULL_ERROR(is_setter);
+ }
+ const Function& func = Api::UnwrapFunctionHandle(isolate, function);
+ if (func.IsNull()) {
+ RETURN_TYPE_ERROR(isolate, function, Function);
+ }
+ *is_setter = (func.kind() == RawFunction::kSetterFunction);
+ return Api::Success();
+}
+
+
+DART_EXPORT Dart_Handle Dart_FunctionReturnType(Dart_Handle function) {
+ Isolate* isolate = Isolate::Current();
+ DARTSCOPE(isolate);
+ const Function& func = Api::UnwrapFunctionHandle(isolate, function);
+ if (func.IsNull()) {
+ RETURN_TYPE_ERROR(isolate, function, Function);
+ }
+
+ if (func.kind() == RawFunction::kConstructor) {
+ // Special case the return type for constructors. Inside the vm
+ // we mark them as returning dynamic, but for the purposes of
+ // reflection, they return the type of the class being
+ // constructed.
+ return Api::NewHandle(isolate, func.Owner());
+ } else {
+ const AbstractType& return_type =
+ AbstractType::Handle(isolate, func.result_type());
+ return TypeToHandle(isolate, "Dart_FunctionReturnType", return_type);
+ }
+}
+
+
+DART_EXPORT Dart_Handle Dart_FunctionParameterCounts(
+ Dart_Handle function,
+ int64_t* fixed_param_count,
+ int64_t* opt_param_count) {
+ Isolate* isolate = Isolate::Current();
+ DARTSCOPE(isolate);
+ if (fixed_param_count == NULL) {
+ RETURN_NULL_ERROR(fixed_param_count);
+ }
+ if (opt_param_count == NULL) {
+ RETURN_NULL_ERROR(opt_param_count);
+ }
+ const Function& func = Api::UnwrapFunctionHandle(isolate, function);
+ if (func.IsNull()) {
+ RETURN_TYPE_ERROR(isolate, function, Function);
+ }
+
+ // We hide implicit parameters, such as a method's receiver. This is
+ // consistent with Invoke or New, which don't expect their callers to
+ // provide them in the argument lists they are handed.
+ *fixed_param_count = func.num_fixed_parameters() -
+ func.NumImplicitParameters();
+ // TODO(regis): Separately report named and positional optional param counts.
+ *opt_param_count = func.NumOptionalParameters();
+
+ ASSERT(*fixed_param_count >= 0);
+ ASSERT(*opt_param_count >= 0);
+
+ return Api::Success();
+}
+
+
+DART_EXPORT Dart_Handle Dart_FunctionParameterType(Dart_Handle function,
+ int parameter_index) {
+ Isolate* isolate = Isolate::Current();
+ DARTSCOPE(isolate);
+ const Function& func = Api::UnwrapFunctionHandle(isolate, function);
+ if (func.IsNull()) {
+ RETURN_TYPE_ERROR(isolate, function, Function);
+ }
+
+ const intptr_t num_implicit_params = func.NumImplicitParameters();
+ const intptr_t num_params = func.NumParameters() - num_implicit_params;
+ if (parameter_index < 0 || parameter_index >= num_params) {
+ return Api::NewError(
+ "%s: argument 'parameter_index' out of range. "
+ "Expected 0..%"Pd" but saw %d.",
+ CURRENT_FUNC, num_params, parameter_index);
+ }
+ const AbstractType& param_type =
+ AbstractType::Handle(isolate, func.ParameterTypeAt(
+ num_implicit_params + parameter_index));
+ return TypeToHandle(isolate, "Dart_FunctionParameterType", param_type);
+}
+
+
+DART_EXPORT Dart_Handle Dart_GetVariableNames(Dart_Handle target) {
+ Isolate* isolate = Isolate::Current();
+ DARTSCOPE(isolate);
+ const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(target));
+ if (obj.IsError()) {
+ return target;
+ }
+
+ const GrowableObjectArray& names =
+ GrowableObjectArray::Handle(isolate, GrowableObjectArray::New());
+ Field& field = Field::Handle(isolate);
+ String& name = String::Handle(isolate);
+
+ if (obj.IsClass()) {
+ const Class& cls = Class::Cast(obj);
+ const Error& error = Error::Handle(isolate, cls.EnsureIsFinalized(isolate));
+ if (!error.IsNull()) {
+ return Api::NewHandle(isolate, error.raw());
+ }
+ const Array& field_array = Array::Handle(cls.fields());
+
+ // Some special types like 'dynamic' have a null fields list.
+ //
+ // TODO(turnidge): Fix 'dynamic' so that it does not have a null
+ // fields list. This will have to wait until the empty array is
+ // allocated in the vm isolate.
+ if (!field_array.IsNull()) {
+ for (intptr_t i = 0; i < field_array.Length(); ++i) {
+ field ^= field_array.At(i);
+ name = field.UserVisibleName();
+ names.Add(name);
+ }
+ }
+ } else if (obj.IsLibrary()) {
+ const Library& lib = Library::Cast(obj);
+ DictionaryIterator it(lib);
+ Object& obj = Object::Handle(isolate);
+ while (it.HasNext()) {
+ obj = it.GetNext();
+ if (obj.IsField()) {
+ field ^= obj.raw();
+ name = field.UserVisibleName();
+ names.Add(name);
+ }
+ }
+ } else {
+ return Api::NewError(
+ "%s expects argument 'target' to be a class or library.",
+ CURRENT_FUNC);
+ }
+ return Api::NewHandle(isolate, Array::MakeArray(names));
+}
+
+
+DART_EXPORT Dart_Handle Dart_LookupVariable(Dart_Handle target,
+ Dart_Handle variable_name) {
+ Isolate* isolate = Isolate::Current();
+ DARTSCOPE(isolate);
+ const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(target));
+ if (obj.IsError()) {
+ return target;
+ }
+ const String& var_name = Api::UnwrapStringHandle(isolate, variable_name);
+ if (var_name.IsNull()) {
+ RETURN_TYPE_ERROR(isolate, variable_name, String);
+ }
+ if (obj.IsClass()) {
+ const Class& cls = Class::Cast(obj);
+ return Api::NewHandle(isolate, cls.LookupField(var_name));
+ }
+ if (obj.IsLibrary()) {
+ const Library& lib = Library::Cast(obj);
+ return Api::NewHandle(isolate, lib.LookupFieldAllowPrivate(var_name));
+ }
+ return Api::NewError(
+ "%s expects argument 'target' to be a class or library.",
+ CURRENT_FUNC);
+}
+
+
+DART_EXPORT Dart_Handle Dart_VariableName(Dart_Handle variable) {
+ Isolate* isolate = Isolate::Current();
+ DARTSCOPE(isolate);
+ const Field& var = Api::UnwrapFieldHandle(isolate, variable);
+ if (var.IsNull()) {
+ RETURN_TYPE_ERROR(isolate, variable, Field);
+ }
+ return Api::NewHandle(isolate, var.UserVisibleName());
+}
+
+
+DART_EXPORT Dart_Handle Dart_VariableIsStatic(Dart_Handle variable,
+ bool* is_static) {
+ Isolate* isolate = Isolate::Current();
+ DARTSCOPE(isolate);
+ if (is_static == NULL) {
+ RETURN_NULL_ERROR(is_static);
+ }
+ const Field& var = Api::UnwrapFieldHandle(isolate, variable);
+ if (var.IsNull()) {
+ RETURN_TYPE_ERROR(isolate, variable, Field);
+ }
+ *is_static = var.is_static();
+ return Api::Success();
+}
+
+
+DART_EXPORT Dart_Handle Dart_VariableIsFinal(Dart_Handle variable,
+ bool* is_final) {
+ Isolate* isolate = Isolate::Current();
+ DARTSCOPE(isolate);
+ if (is_final == NULL) {
+ RETURN_NULL_ERROR(is_final);
+ }
+ const Field& var = Api::UnwrapFieldHandle(isolate, variable);
+ if (var.IsNull()) {
+ RETURN_TYPE_ERROR(isolate, variable, Field);
+ }
+ *is_final = var.is_final();
+ return Api::Success();
+}
+
+
+DART_EXPORT Dart_Handle Dart_VariableType(Dart_Handle variable) {
+ Isolate* isolate = Isolate::Current();
+ DARTSCOPE(isolate);
+ const Field& var = Api::UnwrapFieldHandle(isolate, variable);
+ if (var.IsNull()) {
+ RETURN_TYPE_ERROR(isolate, variable, Field);
+ }
+
+ const AbstractType& type = AbstractType::Handle(isolate, var.type());
+ return TypeToHandle(isolate, "Dart_VariableType", type);
+}
+
+
+DART_EXPORT Dart_Handle Dart_GetTypeVariableNames(Dart_Handle clazz) {
+ Isolate* isolate = Isolate::Current();
+ DARTSCOPE(isolate);
+ const Class& cls = Api::UnwrapClassHandle(isolate, clazz);
+ if (cls.IsNull()) {
+ RETURN_TYPE_ERROR(isolate, clazz, Class);
+ }
+
+ const intptr_t num_type_params = cls.NumTypeParameters();
+ const TypeArguments& type_params =
+ TypeArguments::Handle(cls.type_parameters());
+
+ const GrowableObjectArray& names =
+ GrowableObjectArray::Handle(isolate, GrowableObjectArray::New());
+ TypeParameter& type_param = TypeParameter::Handle(isolate);
+ String& name = String::Handle(isolate);
+ for (intptr_t i = 0; i < num_type_params; i++) {
+ type_param ^= type_params.TypeAt(i);
+ name = type_param.name();
+ names.Add(name);
+ }
+ return Api::NewHandle(isolate, Array::MakeArray(names));
+}
+
+
+DART_EXPORT Dart_Handle Dart_LookupTypeVariable(
+ Dart_Handle clazz,
+ Dart_Handle type_variable_name) {
+ Isolate* isolate = Isolate::Current();
+ DARTSCOPE(isolate);
+ const Class& cls = Api::UnwrapClassHandle(isolate, clazz);
+ if (cls.IsNull()) {
+ RETURN_TYPE_ERROR(isolate, clazz, Class);
+ }
+ const String& var_name = Api::UnwrapStringHandle(isolate, type_variable_name);
+ if (var_name.IsNull()) {
+ RETURN_TYPE_ERROR(isolate, type_variable_name, String);
+ }
+
+ const intptr_t num_type_params = cls.NumTypeParameters();
+ const TypeArguments& type_params =
+ TypeArguments::Handle(cls.type_parameters());
+
+ TypeParameter& type_param = TypeParameter::Handle(isolate);
+ String& name = String::Handle(isolate);
+ for (intptr_t i = 0; i < num_type_params; i++) {
+ type_param ^= type_params.TypeAt(i);
+ name = type_param.name();
+ if (name.Equals(var_name)) {
+ return Api::NewHandle(isolate, type_param.raw());
+ }
+ }
+ const String& cls_name = String::Handle(cls.UserVisibleName());
+ return Api::NewError(
+ "%s: Could not find type variable named '%s' for class %s.\n",
+ CURRENT_FUNC, var_name.ToCString(), cls_name.ToCString());
+}
+
+
+DART_EXPORT Dart_Handle Dart_TypeVariableName(Dart_Handle type_variable) {
+ Isolate* isolate = Isolate::Current();
+ DARTSCOPE(isolate);
+ const TypeParameter& type_var =
+ Api::UnwrapTypeParameterHandle(isolate, type_variable);
+ if (type_var.IsNull()) {
+ RETURN_TYPE_ERROR(isolate, type_variable, TypeParameter);
+ }
+ return Api::NewHandle(isolate, type_var.name());
+}
+
+
+DART_EXPORT Dart_Handle Dart_TypeVariableOwner(Dart_Handle type_variable) {
+ Isolate* isolate = Isolate::Current();
+ DARTSCOPE(isolate);
+ const TypeParameter& type_var =
+ Api::UnwrapTypeParameterHandle(isolate, type_variable);
+ if (type_var.IsNull()) {
+ RETURN_TYPE_ERROR(isolate, type_variable, TypeParameter);
+ }
+ const Class& owner = Class::Handle(type_var.parameterized_class());
+ ASSERT(!owner.IsNull() && owner.IsClass());
+ return Api::NewHandle(isolate, owner.raw());
+}
+
+
+DART_EXPORT Dart_Handle Dart_TypeVariableUpperBound(Dart_Handle type_variable) {
+ Isolate* isolate = Isolate::Current();
+ DARTSCOPE(isolate);
+ const TypeParameter& type_var =
+ Api::UnwrapTypeParameterHandle(isolate, type_variable);
+ if (type_var.IsNull()) {
+ RETURN_TYPE_ERROR(isolate, type_variable, TypeParameter);
+ }
+ const AbstractType& bound = AbstractType::Handle(type_var.bound());
+ return TypeToHandle(isolate, "Dart_TypeVariableUpperBound", bound);
+}
+
+
+// --- Libraries Reflection ---
+
+DART_EXPORT Dart_Handle Dart_LibraryName(Dart_Handle library) {
+ Isolate* isolate = Isolate::Current();
+ DARTSCOPE(isolate);
+ const Library& lib = Api::UnwrapLibraryHandle(isolate, library);
+ if (lib.IsNull()) {
+ RETURN_TYPE_ERROR(isolate, library, Library);
+ }
+ const String& name = String::Handle(isolate, lib.name());
+ ASSERT(!name.IsNull());
+ return Api::NewHandle(isolate, name.raw());
+}
+
+
+DART_EXPORT Dart_Handle Dart_LibraryGetClassNames(Dart_Handle library) {
+ Isolate* isolate = Isolate::Current();
+ DARTSCOPE(isolate);
+ const Library& lib = Api::UnwrapLibraryHandle(isolate, library);
+ if (lib.IsNull()) {
+ RETURN_TYPE_ERROR(isolate, library, Library);
+ }
+
+ const GrowableObjectArray& names =
+ GrowableObjectArray::Handle(isolate, GrowableObjectArray::New());
+ ClassDictionaryIterator it(lib);
+ Class& cls = Class::Handle();
+ String& name = String::Handle();
+ while (it.HasNext()) {
+ cls = it.GetNextClass();
+ if (cls.IsSignatureClass()) {
+ if (!cls.IsCanonicalSignatureClass()) {
+ // This is a typedef. Add it to the list of class names.
+ name = cls.UserVisibleName();
+ names.Add(name);
+ } else {
+ // Skip canonical signature classes. These are not named.
+ }
+ } else {
+ name = cls.UserVisibleName();
+ names.Add(name);
+ }
+ }
+ return Api::NewHandle(isolate, Array::MakeArray(names));
+}
+
+
+// --- Closures Reflection ---
+
+DART_EXPORT Dart_Handle Dart_ClosureFunction(Dart_Handle closure) {
+ Isolate* isolate = Isolate::Current();
+ DARTSCOPE(isolate);
+ const Instance& closure_obj = Api::UnwrapInstanceHandle(isolate, closure);
+ if (closure_obj.IsNull() || !closure_obj.IsClosure()) {
+ RETURN_TYPE_ERROR(isolate, closure, Instance);
+ }
+
+ ASSERT(ClassFinalizer::AllClassesFinalized());
+
+ RawFunction* rf = Closure::function(closure_obj);
+ return Api::NewHandle(isolate, rf);
+}
+
+
+// --- Metadata Reflection ----
+
+DART_EXPORT Dart_Handle Dart_GetMetadata(Dart_Handle object) {
+ Isolate* isolate = Isolate::Current();
+ CHECK_ISOLATE(isolate);
+ DARTSCOPE(isolate);
+ const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(object));
+ Class& cls = Class::Handle(isolate);
+ if (obj.IsClass()) {
+ cls ^= obj.raw();
+ } else if (obj.IsFunction()) {
+ cls = Function::Cast(obj).origin();
+ } else if (obj.IsField()) {
+ cls = Field::Cast(obj).origin();
+ } else {
+ return Api::NewHandle(isolate, Object::empty_array().raw());
+ }
+ const Library& lib = Library::Handle(cls.library());
+ return Api::NewHandle(isolate, lib.GetMetadata(obj));
+}
+
+} // namespace dart
« no previous file with comments | « runtime/vm/dart_api_message.h ('k') | runtime/vm/native_api_impl.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698