| // Copyright (c) 2012, 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_api.h" |
| #include "include/dart_debugger_api.h" |
| #include "include/dart_mirrors_api.h" |
| #include "vm/dart_api_impl.h" |
| #include "vm/dart_api_state.h" // TODO(11742): Remove with CreateMirrorRef. |
| #include "vm/bootstrap_natives.h" |
| #include "vm/dart_entry.h" |
| #include "vm/exceptions.h" |
| #include "vm/message.h" |
| #include "vm/port.h" |
| #include "vm/resolver.h" |
| #include "vm/symbols.h" |
| |
| namespace dart { |
| |
| inline Dart_Handle NewString(const char* str) { |
| return Dart_NewStringFromCString(str); |
| } |
| |
| |
| DEFINE_NATIVE_ENTRY(Mirrors_isLocalPort, 1) { |
| GET_NON_NULL_NATIVE_ARGUMENT(Instance, port, arguments->NativeArgAt(0)); |
| |
| // Get the port id from the SendPort instance. |
| const Object& id_obj = Object::Handle(DartLibraryCalls::PortGetId(port)); |
| if (id_obj.IsError()) { |
| Exceptions::PropagateError(Error::Cast(id_obj)); |
| UNREACHABLE(); |
| } |
| ASSERT(id_obj.IsSmi() || id_obj.IsMint()); |
| Integer& id = Integer::Handle(); |
| id ^= id_obj.raw(); |
| Dart_Port port_id = static_cast<Dart_Port>(id.AsInt64Value()); |
| return Bool::Get(PortMap::IsLocalPort(port_id)); |
| } |
| |
| |
| // TODO(turnidge): Add Map support to the dart embedding api instead |
| // of implementing it here. |
| static Dart_Handle CoreLib() { |
| Dart_Handle core_lib_name = NewString("dart:core"); |
| return Dart_LookupLibrary(core_lib_name); |
| } |
| |
| |
| static Dart_Handle MapNew() { |
| // TODO(turnidge): Switch to an order-preserving map type. |
| Dart_Handle type = Dart_GetType(CoreLib(), NewString("Map"), 0, NULL); |
| if (Dart_IsError(type)) { |
| return type; |
| } |
| return Dart_New(type, Dart_Null(), 0, NULL); |
| } |
| |
| |
| static Dart_Handle MapAdd(Dart_Handle map, Dart_Handle key, Dart_Handle value) { |
| Dart_Handle args[] = { key, value }; |
| return Dart_Invoke(map, NewString("[]="), ARRAY_SIZE(args), args); |
| } |
| |
| |
| static Dart_Handle MirrorLib() { |
| Dart_Handle mirror_lib_name = NewString("dart:mirrors"); |
| return Dart_LookupLibrary(mirror_lib_name); |
| } |
| |
| |
| static Dart_Handle IsMethodMirror(Dart_Handle object, bool* is_mirror) { |
| Dart_Handle cls_name = NewString("MethodMirror"); |
| Dart_Handle type = Dart_GetType(MirrorLib(), cls_name, 0, NULL); |
| if (Dart_IsError(type)) { |
| return type; |
| } |
| Dart_Handle result = Dart_ObjectIsType(object, type, is_mirror); |
| if (Dart_IsError(result)) { |
| return result; |
| } |
| return Dart_True(); // Indicates success. Result is in is_mirror. |
| } |
| |
| static Dart_Handle IsVariableMirror(Dart_Handle object, bool* is_mirror) { |
| Dart_Handle cls_name = NewString("VariableMirror"); |
| Dart_Handle type = Dart_GetType(MirrorLib(), cls_name, 0, NULL); |
| if (Dart_IsError(type)) { |
| return type; |
| } |
| Dart_Handle result = Dart_ObjectIsType(object, type, is_mirror); |
| if (Dart_IsError(result)) { |
| return result; |
| } |
| return Dart_True(); // Indicates success. Result is in is_mirror. |
| } |
| |
| |
| // TODO(11742): Remove once there are no more users of the Dart_Handle-based |
| // VMReferences. |
| static Dart_Handle CreateMirrorReference(Dart_Handle handle) { |
| Isolate* isolate = Isolate::Current(); |
| DARTSCOPE(isolate); |
| const Object& referent = Object::Handle(isolate, Api::UnwrapHandle(handle)); |
| const MirrorReference& reference = |
| MirrorReference::Handle(MirrorReference::New()); |
| reference.set_referent(referent); |
| return Api::NewHandle(isolate, reference.raw()); |
| } |
| |
| |
| static Dart_Handle StringFromSymbol(Dart_Handle symbol) { |
| Dart_Handle result = Dart_Invoke(MirrorLib(), NewString("_n"), 1, &symbol); |
| return result; |
| } |
| |
| |
| static Dart_Handle UnwrapVMReference(Dart_Handle vm_ref) { |
| // Retrieve the persistent handle from the VMReference |
| intptr_t perm_handle_value = 0; |
| Dart_Handle result = |
| Dart_GetNativeInstanceField(vm_ref, 0, &perm_handle_value); |
| if (Dart_IsError(result)) { |
| return result; |
| } |
| Dart_PersistentHandle perm_handle = |
| reinterpret_cast<Dart_PersistentHandle>(perm_handle_value); |
| ASSERT(perm_handle != NULL); |
| Dart_Handle handle = Dart_HandleFromPersistent(perm_handle); |
| ASSERT(handle != NULL); |
| ASSERT(!Dart_IsError(handle)); |
| return handle; |
| } |
| |
| static Dart_Handle UnwrapMirror(Dart_Handle mirror); |
| |
| static Dart_Handle UnwrapObjectMirror(Dart_Handle mirror) { |
| Dart_Handle field_name = NewString("_reference"); |
| Dart_Handle vm_ref = Dart_GetField(mirror, field_name); |
| if (Dart_IsError(vm_ref)) { |
| return vm_ref; |
| } |
| return UnwrapVMReference(vm_ref); |
| } |
| |
| |
| static Dart_Handle UnwrapMethodMirror(Dart_Handle methodMirror) { |
| Dart_Handle namefield_name = NewString("simpleName"); |
| Dart_Handle name_ref = Dart_GetField(methodMirror, namefield_name); |
| if (Dart_IsError(name_ref)) { |
| return name_ref; |
| } |
| Dart_Handle ownerfield_name = NewString("_owner"); |
| Dart_Handle owner_mirror = Dart_GetField(methodMirror, ownerfield_name); |
| if (Dart_IsError(owner_mirror)) { |
| return owner_mirror; |
| } |
| Dart_Handle owner = UnwrapMirror(owner_mirror); |
| if (Dart_IsError(owner)) { |
| return owner; |
| } |
| Dart_Handle func = Dart_LookupFunction(owner, StringFromSymbol(name_ref)); |
| if (Dart_IsError(func)) { |
| return func; |
| } |
| ASSERT(!Dart_IsNull(func)); |
| return func; |
| } |
| |
| static Dart_Handle UnwrapVariableMirror(Dart_Handle variableMirror) { |
| Dart_Handle namefield_name = NewString("simpleName"); |
| Dart_Handle name_ref = Dart_GetField(variableMirror, namefield_name); |
| if (Dart_IsError(name_ref)) { |
| return name_ref; |
| } |
| Dart_Handle ownerfield_name = NewString("_owner"); |
| Dart_Handle owner_mirror = Dart_GetField(variableMirror, ownerfield_name); |
| ASSERT(!Dart_IsNull(owner_mirror)); |
| if (Dart_IsError(owner_mirror)) { |
| return owner_mirror; |
| } |
| Dart_Handle owner = UnwrapMirror(owner_mirror); |
| if (Dart_IsError(owner)) { |
| return owner; |
| } |
| Dart_Handle variable = |
| Dart_LookupVariable(owner, StringFromSymbol(name_ref)); |
| if (Dart_IsError(variable)) { |
| return variable; |
| } |
| ASSERT(!Dart_IsNull(variable)); |
| return variable; |
| } |
| |
| static Dart_Handle UnwrapMirror(Dart_Handle mirror) { |
| // Caveat Emptor: |
| // only works for ObjectMirrors, VariableMirrors and MethodMirrors |
| // and their subtypes |
| bool is_method_mirror = false; |
| Dart_Handle result = IsMethodMirror(mirror, &is_method_mirror); |
| if (Dart_IsError(result)) { |
| return result; |
| } |
| if (is_method_mirror) { |
| return UnwrapMethodMirror(mirror); |
| } |
| bool is_variable_mirror = false; |
| result = IsVariableMirror(mirror, &is_variable_mirror); |
| if (Dart_IsError(result)) { |
| return result; |
| } |
| if (is_variable_mirror) { |
| return UnwrapVariableMirror(mirror); |
| } |
| return UnwrapObjectMirror(mirror); |
| // will return nonsense if mirror is not an ObjectMirror |
| } |
| |
| |
| static Dart_Handle CreateLazyMirror(Dart_Handle target); |
| |
| |
| static Dart_Handle CreateParameterMirrorList(Dart_Handle func) { |
| int64_t fixed_param_count; |
| int64_t opt_param_count; |
| Dart_Handle result = Dart_FunctionParameterCounts(func, |
| &fixed_param_count, |
| &opt_param_count); |
| if (Dart_IsError(result)) { |
| return result; |
| } |
| |
| int64_t param_count = fixed_param_count + opt_param_count; |
| Dart_Handle parameter_list = Dart_NewList(param_count); |
| if (Dart_IsError(parameter_list)) { |
| return result; |
| } |
| |
| Dart_Handle param_cls_name = NewString("_LocalParameterMirrorImpl"); |
| Dart_Handle param_type = Dart_GetType(MirrorLib(), param_cls_name, 0, NULL); |
| if (Dart_IsError(param_type)) { |
| return param_type; |
| } |
| |
| for (int64_t i = 0; i < param_count; i++) { |
| Dart_Handle arg_type = Dart_FunctionParameterType(func, i); |
| if (Dart_IsError(arg_type)) { |
| return arg_type; |
| } |
| Dart_Handle args[] = { |
| CreateLazyMirror(arg_type), |
| Dart_NewBoolean(i >= fixed_param_count), // optional param? |
| }; |
| Dart_Handle param = |
| Dart_New(param_type, Dart_Null(), ARRAY_SIZE(args), args); |
| if (Dart_IsError(param)) { |
| return param; |
| } |
| result = Dart_ListSetAt(parameter_list, i, param); |
| if (Dart_IsError(result)) { |
| return result; |
| } |
| } |
| return parameter_list; |
| } |
| |
| |
| static Dart_Handle CreateLazyMirror(Dart_Handle target) { |
| if (Dart_IsNull(target) || Dart_IsError(target)) { |
| return target; |
| } |
| |
| if (Dart_IsLibrary(target)) { |
| Dart_Handle cls_name = NewString("_LazyLibraryMirror"); |
| Dart_Handle type = Dart_GetType(MirrorLib(), cls_name, 0, NULL); |
| Dart_Handle args[] = { Dart_LibraryUrl(target) }; |
| return Dart_New(type, Dart_Null(), ARRAY_SIZE(args), args); |
| } |
| |
| if (Dart_IsClass(target)) { |
| if (Dart_ClassIsFunctionType(target)) { |
| Dart_Handle cls_name = NewString("_LazyFunctionTypeMirror"); |
| Dart_Handle type = Dart_GetType(MirrorLib(), cls_name, 0, NULL); |
| |
| Dart_Handle sig = Dart_ClassGetFunctionTypeSignature(target); |
| Dart_Handle return_type = Dart_FunctionReturnType(sig); |
| if (Dart_IsError(return_type)) { |
| return return_type; |
| } |
| |
| Dart_Handle args[] = { |
| CreateLazyMirror(return_type), |
| CreateParameterMirrorList(sig), |
| }; |
| return Dart_New(type, Dart_Null(), ARRAY_SIZE(args), args); |
| } else { |
| Dart_Handle cls_name = NewString("_LazyTypeMirror"); |
| Dart_Handle type = Dart_GetType(MirrorLib(), cls_name, 0, NULL); |
| Dart_Handle lib = Dart_ClassGetLibrary(target); |
| Dart_Handle lib_url; |
| if (Dart_IsNull(lib)) { |
| lib_url = Dart_Null(); |
| } else { |
| lib_url = Dart_LibraryUrl(lib); |
| } |
| Dart_Handle args[] = { lib_url, Dart_ClassName(target) }; |
| return Dart_New(type, Dart_Null(), ARRAY_SIZE(args), args); |
| } |
| } |
| |
| if (Dart_IsTypeVariable(target)) { |
| Dart_Handle var_name = Dart_TypeVariableName(target); |
| Dart_Handle owner = Dart_TypeVariableOwner(target); |
| Dart_Handle owner_mirror = CreateLazyMirror(owner); |
| |
| Dart_Handle cls_name = NewString("_LazyTypeVariableMirror"); |
| Dart_Handle type = Dart_GetType(MirrorLib(), cls_name, 0, NULL); |
| |
| Dart_Handle args[] = { var_name, owner_mirror }; |
| return Dart_New(type, Dart_Null(), ARRAY_SIZE(args), args); |
| } |
| |
| UNREACHABLE(); |
| return Dart_Null(); |
| } |
| |
| |
| static Dart_Handle CreateImplementsList(Dart_Handle intf) { |
| intptr_t len = 0; |
| Dart_Handle result = Dart_ClassGetInterfaceCount(intf, &len); |
| if (Dart_IsError(result)) { |
| return result; |
| } |
| |
| Dart_Handle mirror_list = Dart_NewList(len); |
| if (Dart_IsError(mirror_list)) { |
| return mirror_list; |
| } |
| |
| for (intptr_t i = 0; i < len; i++) { |
| Dart_Handle interface = Dart_ClassGetInterfaceAt(intf, i); |
| if (Dart_IsError(interface)) { |
| return interface; |
| } |
| Dart_Handle mirror = CreateLazyMirror(interface); |
| if (Dart_IsError(mirror)) { |
| return mirror; |
| } |
| Dart_Handle result = Dart_ListSetAt(mirror_list, i, mirror); |
| if (Dart_IsError(result)) { |
| return result; |
| } |
| } |
| return mirror_list; |
| } |
| |
| |
| static Dart_Handle CreateTypeVariableMirror(Dart_Handle type_var, |
| Dart_Handle type_var_name, |
| Dart_Handle owner_mirror) { |
| ASSERT(Dart_IsTypeVariable(type_var)); |
| Dart_Handle cls_name = NewString("_LocalTypeVariableMirrorImpl"); |
| Dart_Handle type = Dart_GetType(MirrorLib(), cls_name, 0, NULL); |
| if (Dart_IsError(type)) { |
| return type; |
| } |
| |
| Dart_Handle upper_bound = Dart_TypeVariableUpperBound(type_var); |
| if (Dart_IsError(upper_bound)) { |
| return upper_bound; |
| } |
| |
| Dart_Handle args[] = { |
| CreateMirrorReference(type_var), |
| type_var_name, |
| owner_mirror, |
| CreateLazyMirror(upper_bound), |
| }; |
| Dart_Handle mirror = Dart_New(type, Dart_Null(), ARRAY_SIZE(args), args); |
| return mirror; |
| } |
| |
| |
| static Dart_Handle CreateTypeVariableMap(Dart_Handle owner, |
| Dart_Handle owner_mirror) { |
| ASSERT(Dart_IsClass(owner)); |
| // TODO(turnidge): This should be an immutable map. |
| Dart_Handle map = MapNew(); |
| if (Dart_IsError(map)) { |
| return map; |
| } |
| |
| Dart_Handle names = Dart_GetTypeVariableNames(owner); |
| if (Dart_IsError(names)) { |
| return names; |
| } |
| intptr_t len; |
| Dart_Handle result = Dart_ListLength(names, &len); |
| if (Dart_IsError(result)) { |
| return result; |
| } |
| for (intptr_t i = 0; i < len; i++) { |
| Dart_Handle type_var_name = Dart_ListGetAt(names, i); |
| Dart_Handle type_var = Dart_LookupTypeVariable(owner, type_var_name); |
| if (Dart_IsError(type_var)) { |
| return type_var; |
| } |
| ASSERT(!Dart_IsNull(type_var)); |
| Dart_Handle type_var_mirror = |
| CreateTypeVariableMirror(type_var, type_var_name, owner_mirror); |
| if (Dart_IsError(type_var_mirror)) { |
| return type_var_mirror; |
| } |
| result = MapAdd(map, type_var_name, type_var_mirror); |
| if (Dart_IsError(result)) { |
| return result; |
| } |
| } |
| return map; |
| } |
| |
| |
| static Dart_Handle CreateTypedefMirror(Dart_Handle cls, |
| Dart_Handle cls_name, |
| Dart_Handle owner_mirror) { |
| Dart_Handle mirror_cls_name = NewString("_LocalTypedefMirrorImpl"); |
| Dart_Handle mirror_type = Dart_GetType(MirrorLib(), mirror_cls_name, 0, NULL); |
| if (Dart_IsError(mirror_type)) { |
| return mirror_type; |
| } |
| |
| Dart_Handle referent = Dart_ClassGetTypedefReferent(cls); |
| if (Dart_IsError(referent)) { |
| return referent; |
| } |
| |
| Dart_Handle args[] = { |
| CreateMirrorReference(cls), |
| cls_name, |
| owner_mirror, |
| CreateLazyMirror(referent), |
| }; |
| Dart_Handle mirror = |
| Dart_New(mirror_type, Dart_Null(), ARRAY_SIZE(args), args); |
| return mirror; |
| } |
| |
| |
| static Dart_Handle CreateMemberMap(Dart_Handle owner, Dart_Handle owner_mirror); |
| static Dart_Handle CreateConstructorMap(Dart_Handle owner, |
| Dart_Handle owner_mirror); |
| |
| static Dart_Handle CreateClassMirrorUsingApi(Dart_Handle intf, |
| Dart_Handle intf_name, |
| Dart_Handle lib_mirror) { |
| ASSERT(Dart_IsClass(intf)); |
| if (Dart_ClassIsTypedef(intf)) { |
| // This class is actually a typedef. Represent it specially in |
| // reflection. |
| return CreateTypedefMirror(intf, intf_name, lib_mirror); |
| } |
| |
| Dart_Handle cls_name = NewString("_LocalClassMirrorImpl"); |
| Dart_Handle type = Dart_GetType(MirrorLib(), cls_name, 0, NULL); |
| if (Dart_IsError(type)) { |
| return type; |
| } |
| |
| // TODO(turnidge): Why am I getting Null when I expect Object? |
| // TODO(gbracha): this is probably the root of bug 7868 |
| Dart_Handle super_class = Dart_GetSuperclass(intf); |
| if (Dart_IsNull(super_class)) { |
| super_class = Dart_GetClass(CoreLib(), NewString("Object")); |
| } |
| // TODO(turnidge): Simplify code, now that default classes have been removed. |
| Dart_Handle default_class = Dart_Null(); |
| |
| Dart_Handle intf_mirror = CreateLazyMirror(intf); |
| if (Dart_IsError(intf_mirror)) { |
| return intf_mirror; |
| } |
| Dart_Handle member_map = CreateMemberMap(intf, intf_mirror); |
| if (Dart_IsError(member_map)) { |
| return member_map; |
| } |
| Dart_Handle constructor_map = CreateConstructorMap(intf, intf_mirror); |
| if (Dart_IsError(constructor_map)) { |
| return constructor_map; |
| } |
| Dart_Handle type_var_map = CreateTypeVariableMap(intf, intf_mirror); |
| if (Dart_IsError(type_var_map)) { |
| return type_var_map; |
| } |
| |
| Dart_Handle args[] = { |
| CreateMirrorReference(intf), |
| Dart_Null(), // "name" |
| Dart_NewBoolean(Dart_IsClass(intf)), |
| lib_mirror, |
| CreateLazyMirror(super_class), |
| CreateImplementsList(intf), |
| CreateLazyMirror(default_class), |
| member_map, |
| constructor_map, |
| type_var_map, |
| }; |
| Dart_Handle mirror = Dart_New(type, Dart_Null(), ARRAY_SIZE(args), args); |
| return mirror; |
| } |
| |
| |
| static Dart_Handle CreateMethodMirrorUsingApi(Dart_Handle func, |
| Dart_Handle owner_mirror) { |
| // TODO(11742): Unwrapping is needed until the whole method is converted. |
| Isolate* isolate = Isolate::Current(); |
| DARTSCOPE(isolate); |
| const Function& func_obj = Api::UnwrapFunctionHandle(isolate, func); |
| |
| Dart_Handle mirror_cls_name = NewString("_LocalMethodMirrorImpl"); |
| Dart_Handle mirror_type = Dart_GetType(MirrorLib(), mirror_cls_name, 0, NULL); |
| if (Dart_IsError(mirror_type)) { |
| return mirror_type; |
| } |
| |
| Dart_Handle return_type = Dart_FunctionReturnType(func); |
| if (Dart_IsError(return_type)) { |
| return return_type; |
| } |
| |
| // TODO(turnidge): Implement constructor kinds (arguments 7 - 10). |
| Dart_Handle args[] = { |
| CreateMirrorReference(func), |
| owner_mirror, |
| CreateParameterMirrorList(func), |
| CreateLazyMirror(return_type), |
| func_obj.is_static() ? Api::True() : Api::False(), |
| func_obj.is_abstract() ? Api::True() : Api::False(), |
| func_obj.IsGetterFunction() ? Api::True() : Api::False(), |
| func_obj.IsSetterFunction() ? Api::True() : Api::False(), |
| func_obj.IsConstructor() ? Api::True() : Api::False(), |
| Api::False(), |
| Api::False(), |
| Api::False(), |
| Api::False() |
| }; |
| Dart_Handle mirror = |
| Dart_New(mirror_type, Dart_Null(), ARRAY_SIZE(args), args); |
| return mirror; |
| } |
| |
| |
| static Dart_Handle CreateVariableMirror(Dart_Handle var, |
| Dart_Handle var_name, |
| Dart_Handle owner_mirror) { |
| ASSERT(Dart_IsVariable(var)); |
| Dart_Handle cls_name = NewString("_LocalVariableMirrorImpl"); |
| Dart_Handle type = Dart_GetType(MirrorLib(), cls_name, 0, NULL); |
| if (Dart_IsError(type)) { |
| return type; |
| } |
| |
| bool is_static = false; |
| bool is_final = false; |
| |
| Dart_Handle result = Dart_VariableIsStatic(var, &is_static); |
| if (Dart_IsError(result)) { |
| return result; |
| } |
| result = Dart_VariableIsFinal(var, &is_final); |
| if (Dart_IsError(result)) { |
| return result; |
| } |
| |
| Dart_Handle var_type = Dart_VariableType(var); |
| if (Dart_IsError(var_type)) { |
| return var_type; |
| } |
| |
| Dart_Handle args[] = { |
| CreateMirrorReference(var), |
| var_name, |
| owner_mirror, |
| CreateLazyMirror(var_type), |
| Dart_NewBoolean(is_static), |
| Dart_NewBoolean(is_final), |
| }; |
| Dart_Handle mirror = Dart_New(type, Dart_Null(), ARRAY_SIZE(args), args); |
| return mirror; |
| } |
| |
| |
| static Dart_Handle AddMemberClasses(Dart_Handle map, |
| Dart_Handle owner, |
| Dart_Handle owner_mirror) { |
| ASSERT(Dart_IsLibrary(owner)); |
| Dart_Handle result; |
| Dart_Handle names = Dart_LibraryGetClassNames(owner); |
| if (Dart_IsError(names)) { |
| return names; |
| } |
| intptr_t len; |
| result = Dart_ListLength(names, &len); |
| if (Dart_IsError(result)) { |
| return result; |
| } |
| for (intptr_t i = 0; i < len; i++) { |
| Dart_Handle intf_name = Dart_ListGetAt(names, i); |
| Dart_Handle intf = Dart_GetClass(owner, intf_name); |
| if (Dart_IsError(intf)) { |
| return intf; |
| } |
| Dart_Handle intf_mirror = |
| CreateClassMirrorUsingApi(intf, intf_name, owner_mirror); |
| if (Dart_IsError(intf_mirror)) { |
| return intf_mirror; |
| } |
| result = MapAdd(map, intf_name, intf_mirror); |
| if (Dart_IsError(result)) { |
| return result; |
| } |
| } |
| return Dart_True(); |
| } |
| |
| |
| static Dart_Handle AddMemberFunctions(Dart_Handle map, |
| Dart_Handle owner, |
| Dart_Handle owner_mirror) { |
| Dart_Handle result; |
| Dart_Handle names = Dart_GetFunctionNames(owner); |
| if (Dart_IsError(names)) { |
| return names; |
| } |
| intptr_t len; |
| result = Dart_ListLength(names, &len); |
| if (Dart_IsError(result)) { |
| return result; |
| } |
| for (intptr_t i = 0; i < len; i++) { |
| Dart_Handle func_name = Dart_ListGetAt(names, i); |
| Dart_Handle func = Dart_LookupFunction(owner, func_name); |
| if (Dart_IsError(func)) { |
| return func; |
| } |
| ASSERT(!Dart_IsNull(func)); |
| |
| bool is_constructor = false; |
| result = Dart_FunctionIsConstructor(func, &is_constructor); |
| if (Dart_IsError(result)) { |
| return result; |
| } |
| if (is_constructor) { |
| // Skip constructors. |
| continue; |
| } |
| |
| Dart_Handle func_mirror = CreateMethodMirrorUsingApi(func, owner_mirror); |
| if (Dart_IsError(func_mirror)) { |
| return func_mirror; |
| } |
| result = MapAdd(map, func_name, func_mirror); |
| if (Dart_IsError(result)) { |
| return result; |
| } |
| } |
| return Dart_True(); |
| } |
| |
| |
| static Dart_Handle AddConstructors(Dart_Handle map, |
| Dart_Handle owner, |
| Dart_Handle owner_mirror) { |
| Dart_Handle result; |
| Dart_Handle names = Dart_GetFunctionNames(owner); |
| if (Dart_IsError(names)) { |
| return names; |
| } |
| intptr_t len; |
| result = Dart_ListLength(names, &len); |
| if (Dart_IsError(result)) { |
| return result; |
| } |
| for (intptr_t i = 0; i < len; i++) { |
| Dart_Handle func_name = Dart_ListGetAt(names, i); |
| Dart_Handle func = Dart_LookupFunction(owner, func_name); |
| if (Dart_IsError(func)) { |
| return func; |
| } |
| ASSERT(!Dart_IsNull(func)); |
| |
| bool is_constructor = false; |
| result = Dart_FunctionIsConstructor(func, &is_constructor); |
| if (Dart_IsError(result)) { |
| return result; |
| } |
| if (!is_constructor) { |
| // Skip non-constructors. |
| continue; |
| } |
| |
| Dart_Handle func_mirror = CreateMethodMirrorUsingApi(func, owner_mirror); |
| if (Dart_IsError(func_mirror)) { |
| return func_mirror; |
| } |
| result = MapAdd(map, func_name, func_mirror); |
| if (Dart_IsError(result)) { |
| return result; |
| } |
| } |
| return Dart_True(); |
| } |
| |
| |
| static Dart_Handle AddMemberVariables(Dart_Handle map, |
| Dart_Handle owner, |
| Dart_Handle owner_mirror) { |
| Dart_Handle result; |
| Dart_Handle names = Dart_GetVariableNames(owner); |
| if (Dart_IsError(names)) { |
| return names; |
| } |
| intptr_t len; |
| result = Dart_ListLength(names, &len); |
| if (Dart_IsError(result)) { |
| return result; |
| } |
| for (intptr_t i = 0; i < len; i++) { |
| Dart_Handle var_name = Dart_ListGetAt(names, i); |
| Dart_Handle var = Dart_LookupVariable(owner, var_name); |
| if (Dart_IsError(var)) { |
| return var; |
| } |
| ASSERT(!Dart_IsNull(var)); |
| Dart_Handle var_mirror = CreateVariableMirror(var, var_name, owner_mirror); |
| if (Dart_IsError(var_mirror)) { |
| return var_mirror; |
| } |
| result = MapAdd(map, var_name, var_mirror); |
| if (Dart_IsError(result)) { |
| return result; |
| } |
| } |
| return Dart_True(); |
| } |
| |
| |
| static Dart_Handle CreateMemberMap(Dart_Handle owner, |
| Dart_Handle owner_mirror) { |
| // TODO(turnidge): This should be an immutable map. |
| if (Dart_IsError(owner_mirror)) { |
| return owner_mirror; |
| } |
| Dart_Handle result; |
| Dart_Handle map = MapNew(); |
| if (Dart_IsLibrary(owner)) { |
| result = AddMemberClasses(map, owner, owner_mirror); |
| if (Dart_IsError(result)) { |
| return result; |
| } |
| } |
| result = AddMemberFunctions(map, owner, owner_mirror); |
| if (Dart_IsError(result)) { |
| return result; |
| } |
| result = AddMemberVariables(map, owner, owner_mirror); |
| if (Dart_IsError(result)) { |
| return result; |
| } |
| return map; |
| } |
| |
| |
| static Dart_Handle CreateConstructorMap(Dart_Handle owner, |
| Dart_Handle owner_mirror) { |
| // TODO(turnidge): This should be an immutable map. |
| if (Dart_IsError(owner_mirror)) { |
| return owner_mirror; |
| } |
| Dart_Handle result; |
| Dart_Handle map = MapNew(); |
| result = AddConstructors(map, owner, owner_mirror); |
| if (Dart_IsError(result)) { |
| return result; |
| } |
| return map; |
| } |
| |
| |
| static Dart_Handle CreateLibraryMirrorUsingApi(Dart_Handle lib) { |
| Dart_Handle cls_name = NewString("_LocalLibraryMirrorImpl"); |
| Dart_Handle type = Dart_GetType(MirrorLib(), cls_name, 0, NULL); |
| if (Dart_IsError(type)) { |
| return type; |
| } |
| Dart_Handle lazy_lib_mirror = CreateLazyMirror(lib); |
| if (Dart_IsError(lazy_lib_mirror)) { |
| return lazy_lib_mirror; |
| } |
| Dart_Handle member_map = CreateMemberMap(lib, lazy_lib_mirror); |
| if (Dart_IsError(member_map)) { |
| return member_map; |
| } |
| Dart_Handle args[] = { |
| CreateMirrorReference(lib), |
| Dart_LibraryName(lib), |
| Dart_LibraryUrl(lib), |
| member_map, |
| }; |
| Dart_Handle lib_mirror = Dart_New(type, Dart_Null(), ARRAY_SIZE(args), args); |
| if (Dart_IsError(lib_mirror)) { |
| return lib_mirror; |
| } |
| |
| return lib_mirror; |
| } |
| |
| |
| static Dart_Handle CreateLibrariesMap() { |
| // TODO(turnidge): This should be an immutable map. |
| Dart_Handle map = MapNew(); |
| |
| Dart_Handle lib_ids = Dart_GetLibraryIds(); |
| if (Dart_IsError(lib_ids)) { |
| return lib_ids; |
| } |
| intptr_t len; |
| Dart_Handle result = Dart_ListLength(lib_ids, &len); |
| if (Dart_IsError(result)) { |
| return result; |
| } |
| for (intptr_t i = 0; i < len; i++) { |
| Dart_Handle lib_id = Dart_ListGetAt(lib_ids, i); |
| int64_t id64; |
| Dart_IntegerToInt64(lib_id, &id64); |
| Dart_Handle lib_url = Dart_GetLibraryURL(id64); |
| if (Dart_IsError(lib_url)) { |
| return lib_url; |
| } |
| Dart_Handle lib = Dart_LookupLibrary(lib_url); |
| if (Dart_IsError(lib)) { |
| return lib; |
| } |
| Dart_Handle lib_mirror = CreateLibraryMirrorUsingApi(lib); |
| if (Dart_IsError(lib_mirror)) { |
| return lib_mirror; |
| } |
| result = MapAdd(map, lib_url, lib_mirror); |
| } |
| return map; |
| } |
| |
| |
| static Dart_Handle CreateIsolateMirror() { |
| Dart_Handle cls_name = NewString("_LocalIsolateMirrorImpl"); |
| Dart_Handle type = Dart_GetType(MirrorLib(), cls_name, 0, NULL); |
| if (Dart_IsError(type)) { |
| return type; |
| } |
| Dart_Handle args[] = { |
| Dart_DebugName(), |
| CreateLazyMirror(Dart_RootLibrary()), |
| }; |
| return Dart_New(type, Dart_Null(), ARRAY_SIZE(args), args); |
| } |
| |
| |
| static Dart_Handle CreateMirrorSystem() { |
| Dart_Handle cls_name = NewString("_LocalMirrorSystemImpl"); |
| Dart_Handle type = Dart_GetType(MirrorLib(), cls_name, 0, NULL); |
| if (Dart_IsError(type)) { |
| return type; |
| } |
| |
| Dart_Handle libraries = CreateLibrariesMap(); |
| if (Dart_IsError(libraries)) { |
| return libraries; |
| } |
| |
| Dart_Handle args[] = { |
| libraries, |
| CreateIsolateMirror(), |
| }; |
| Dart_Handle mirror = Dart_New(type, Dart_Null(), ARRAY_SIZE(args), args); |
| if (Dart_IsError(mirror)) { |
| return mirror; |
| } |
| |
| return mirror; |
| } |
| |
| |
| static Dart_Handle CreateNullMirror() { |
| Dart_Handle cls_name = NewString("_LocalInstanceMirrorImpl"); |
| Dart_Handle type = Dart_GetType(MirrorLib(), cls_name, 0, NULL); |
| if (Dart_IsError(type)) { |
| return type; |
| } |
| |
| // TODO(turnidge): This is wrong. The Null class is distinct from object. |
| Dart_Handle object_class = Dart_GetClass(CoreLib(), NewString("Object")); |
| |
| Dart_Handle args[] = { |
| CreateLazyMirror(object_class), |
| Dart_Null(), |
| }; |
| Dart_Handle mirror = Dart_New(type, Dart_Null(), ARRAY_SIZE(args), args); |
| return mirror; |
| } |
| |
| |
| static Dart_Handle CreateInstanceMirror(Dart_Handle instance) { |
| if (Dart_IsNull(instance)) { |
| return CreateNullMirror(); |
| } |
| ASSERT(Dart_IsInstance(instance)); |
| |
| Dart_Handle instance_cls = Dart_InstanceGetClass(instance); |
| if (Dart_IsError(instance_cls)) { |
| return instance_cls; |
| } |
| |
| if (Dart_IsClosure(instance)) { |
| Dart_Handle cls_name = NewString("_LocalClosureMirrorImpl"); |
| Dart_Handle type = Dart_GetType(MirrorLib(), cls_name, 0, NULL); |
| if (Dart_IsError(type)) { |
| return type; |
| } |
| // We set the function field of ClosureMirrors outside of the constructor |
| // to break the mutual recursion. |
| Dart_Handle func = Dart_ClosureFunction(instance); |
| if (Dart_IsError(func)) { |
| return func; |
| } |
| |
| // TODO(turnidge): Why not use the real function name here? |
| Dart_Handle func_owner = Dart_FunctionOwner(func); |
| if (Dart_IsError(func_owner)) { |
| return func_owner; |
| } |
| |
| // TODO(turnidge): Pass the function owner here. This will require |
| // us to support functions in CreateLazyMirror. |
| Dart_Handle func_mirror = |
| CreateMethodMirrorUsingApi(func, Dart_Null()); |
| if (Dart_IsError(func_mirror)) { |
| return func_mirror; |
| } |
| Dart_Handle args[] = { |
| CreateLazyMirror(instance_cls), |
| instance, |
| func_mirror, |
| }; |
| return Dart_New(type, Dart_Null(), ARRAY_SIZE(args), args); |
| |
| } else { |
| Dart_Handle cls_name = NewString("_LocalInstanceMirrorImpl"); |
| Dart_Handle type = Dart_GetType(MirrorLib(), cls_name, 0, NULL); |
| if (Dart_IsError(type)) { |
| return type; |
| } |
| Dart_Handle args[] = { |
| CreateLazyMirror(instance_cls), |
| instance, |
| }; |
| return Dart_New(type, Dart_Null(), ARRAY_SIZE(args), args); |
| } |
| } |
| |
| |
| static RawInstance* CreateClassMirror(const Class& cls, |
| const Instance& owner_mirror) { |
| Instance& retvalue = Instance::Handle(); |
| Dart_EnterScope(); |
| Isolate* isolate = Isolate::Current(); |
| Dart_Handle cls_handle = Api::NewHandle(isolate, cls.raw()); |
| if (Dart_IsError(cls_handle)) { |
| Dart_PropagateError(cls_handle); |
| } |
| Dart_Handle name_handle = Api::NewHandle(isolate, cls.Name()); |
| if (Dart_IsError(name_handle)) { |
| Dart_PropagateError(name_handle); |
| } |
| Dart_Handle lib_mirror = Api::NewHandle(isolate, owner_mirror.raw()); |
| // TODO(11742): At some point the handle calls will be replaced by inlined |
| // functionality. |
| Dart_Handle result = CreateClassMirrorUsingApi(cls_handle, |
| name_handle, |
| lib_mirror); |
| if (Dart_IsError(result)) { |
| Dart_PropagateError(result); |
| } |
| retvalue ^= Api::UnwrapHandle(result); |
| Dart_ExitScope(); |
| return retvalue.raw(); |
| } |
| |
| |
| static RawInstance* CreateLibraryMirror(const Library& lib) { |
| Instance& retvalue = Instance::Handle(); |
| Dart_EnterScope(); |
| Isolate* isolate = Isolate::Current(); |
| Dart_Handle lib_handle = Api::NewHandle(isolate, lib.raw()); |
| // TODO(11742): At some point the handle calls will be replaced by inlined |
| // functionality. |
| Dart_Handle result = CreateLibraryMirrorUsingApi(lib_handle); |
| if (Dart_IsError(result)) { |
| Dart_PropagateError(result); |
| } |
| retvalue ^= Api::UnwrapHandle(result); |
| Dart_ExitScope(); |
| return retvalue.raw(); |
| } |
| |
| |
| static RawInstance* CreateMethodMirror(const Function& func, |
| const Instance& owner_mirror) { |
| Instance& retvalue = Instance::Handle(); |
| Dart_EnterScope(); |
| Isolate* isolate = Isolate::Current(); |
| Dart_Handle func_handle = Api::NewHandle(isolate, func.raw()); |
| Dart_Handle owner_handle = Api::NewHandle(isolate, owner_mirror.raw()); |
| // TODO(11742): At some point the handle calls will be replaced by inlined |
| // functionality. |
| Dart_Handle result = CreateMethodMirrorUsingApi(func_handle, owner_handle); |
| if (Dart_IsError(result)) { |
| Dart_PropagateError(result); |
| } |
| retvalue ^= Api::UnwrapHandle(result); |
| Dart_ExitScope(); |
| return retvalue.raw(); |
| } |
| |
| |
| void NATIVE_ENTRY_FUNCTION(Mirrors_makeLocalMirrorSystem)( |
| Dart_NativeArguments args) { |
| Dart_EnterScope(); |
| Dart_Handle mirrors = CreateMirrorSystem(); |
| if (Dart_IsError(mirrors)) { |
| Dart_PropagateError(mirrors); |
| } |
| Dart_SetReturnValue(args, mirrors); |
| Dart_ExitScope(); |
| } |
| |
| |
| void NATIVE_ENTRY_FUNCTION(Mirrors_makeLocalInstanceMirror)( |
| Dart_NativeArguments args) { |
| Dart_EnterScope(); |
| Dart_Handle reflectee = Dart_GetNativeArgument(args, 0); |
| Dart_Handle mirror = CreateInstanceMirror(reflectee); |
| if (Dart_IsError(mirror)) { |
| Dart_PropagateError(mirror); |
| } |
| Dart_SetReturnValue(args, mirror); |
| Dart_ExitScope(); |
| } |
| |
| |
| void NATIVE_ENTRY_FUNCTION(Mirrors_makeLocalClassMirror)( |
| Dart_NativeArguments args) { |
| Dart_EnterScope(); |
| Isolate* isolate = Isolate::Current(); |
| Dart_Handle key = Dart_GetNativeArgument(args, 0); |
| if (Dart_IsError(key)) { |
| Dart_PropagateError(key); |
| } |
| const Type& type = Api::UnwrapTypeHandle(isolate, key); |
| const Class& cls = Class::Handle(type.type_class()); |
| Dart_Handle cls_handle = Api::NewHandle(isolate, cls.raw()); |
| if (Dart_IsError(cls_handle)) { |
| Dart_PropagateError(cls_handle); |
| } |
| Dart_Handle name_handle = Api::NewHandle(isolate, cls.Name()); |
| if (Dart_IsError(name_handle)) { |
| Dart_PropagateError(name_handle); |
| } |
| Dart_Handle lib_mirror = Dart_Null(); |
| Dart_Handle result = CreateClassMirrorUsingApi(cls_handle, |
| name_handle, |
| lib_mirror); |
| if (Dart_IsError(result)) { |
| Dart_PropagateError(result); |
| } |
| Dart_SetReturnValue(args, result); |
| Dart_ExitScope(); |
| } |
| |
| |
| DEFINE_NATIVE_ENTRY(DeclarationMirror_metadata, 1) { |
| const MirrorReference& decl_ref = |
| MirrorReference::CheckedHandle(arguments->NativeArgAt(0)); |
| const Object& decl = Object::Handle(decl_ref.referent()); |
| |
| Class& klass = Class::Handle(); |
| if (decl.IsClass()) { |
| klass ^= decl.raw(); |
| } else if (decl.IsFunction()) { |
| klass = Function::Cast(decl).origin(); |
| } else if (decl.IsField()) { |
| klass = Field::Cast(decl).origin(); |
| } else { |
| return Object::empty_array().raw(); |
| } |
| |
| const Library& library = Library::Handle(klass.library()); |
| return library.GetMetadata(decl); |
| } |
| |
| |
| void HandleMirrorsMessage(Isolate* isolate, |
| Dart_Port reply_port, |
| const Instance& message) { |
| UNIMPLEMENTED(); |
| } |
| |
| |
| // TODO(11742): This is transitional. |
| static RawInstance* Reflect(const Instance& reflectee) { |
| Isolate* isolate = Isolate::Current(); |
| DARTSCOPE(isolate); |
| return Instance::RawCast( |
| Api::UnwrapHandle( |
| CreateInstanceMirror( |
| Api::NewHandle(isolate, reflectee.raw())))); |
| } |
| |
| |
| static void ThrowMirroredUnhandledError(const Error& original_error) { |
| const UnhandledException& unhandled_ex = |
| UnhandledException::Cast(original_error); |
| Instance& exc = Instance::Handle(unhandled_ex.exception()); |
| Instance& stack = Instance::Handle(unhandled_ex.stacktrace()); |
| |
| Object& exc_string_or_error = |
| Object::Handle(DartLibraryCalls::ToString(exc)); |
| String& exc_string = String::Handle(); |
| // Ignore any errors that might occur in toString. |
| if (exc_string_or_error.IsString()) { |
| exc_string ^= exc_string_or_error.raw(); |
| } |
| |
| Instance& mirror_on_exc = Instance::Handle(Reflect(exc)); |
| |
| Array& args = Array::Handle(Array::New(3)); |
| args.SetAt(0, mirror_on_exc); |
| args.SetAt(1, exc_string); |
| args.SetAt(2, stack); |
| |
| Exceptions::ThrowByType(Exceptions::kMirroredUncaughtExceptionError, args); |
| UNREACHABLE(); |
| } |
| |
| |
| static void ThrowMirroredCompilationError(const String& message) { |
| Array& args = Array::Handle(Array::New(1)); |
| args.SetAt(0, message); |
| |
| Exceptions::ThrowByType(Exceptions::kMirroredCompilationError, args); |
| UNREACHABLE(); |
| } |
| |
| |
| static void ThrowInvokeError(const Error& error) { |
| if (error.IsUnhandledException()) { |
| // An ordinary runtime error. |
| ThrowMirroredUnhandledError(error); |
| } |
| if (error.IsLanguageError()) { |
| // A compilation error that was delayed by lazy compilation. |
| const LanguageError& compilation_error = LanguageError::Cast(error); |
| String& message = String::Handle(compilation_error.message()); |
| ThrowMirroredCompilationError(message); |
| } |
| UNREACHABLE(); |
| } |
| |
| |
| static RawFunction* ResolveConstructor(const char* current_func, |
| const Class& cls, |
| const String& class_name, |
| const String& constr_name, |
| int num_args) { |
| // The constructor must be present in the interface. |
| const Function& constructor = |
| Function::Handle(cls.LookupFunctionAllowPrivate(constr_name)); |
| if (constructor.IsNull() || |
| (!constructor.IsConstructor() && !constructor.IsFactory())) { |
| const String& lookup_class_name = String::Handle(cls.Name()); |
| if (!class_name.Equals(lookup_class_name)) { |
| // When the class name used to build the constructor name is |
| // different than the name of the class in which we are doing |
| // the lookup, it can be confusing to the user to figure out |
| // what's going on. Be a little more explicit for these error |
| // messages. |
| const String& message = String::Handle( |
| String::NewFormatted( |
| "%s: could not find factory '%s' in class '%s'.", |
| current_func, |
| constr_name.ToCString(), |
| lookup_class_name.ToCString())); |
| ThrowMirroredCompilationError(message); |
| UNREACHABLE(); |
| } else { |
| const String& message = String::Handle( |
| String::NewFormatted("%s: could not find constructor '%s'.", |
| current_func, constr_name.ToCString())); |
| ThrowMirroredCompilationError(message); |
| UNREACHABLE(); |
| } |
| } |
| int extra_args = (constructor.IsConstructor() ? 2 : 1); |
| String& error_message = String::Handle(); |
| if (!constructor.AreValidArgumentCounts(num_args + extra_args, |
| 0, |
| &error_message)) { |
| const String& message = String::Handle( |
| String::NewFormatted("%s: wrong argument count for " |
| "constructor '%s': %s.", |
| current_func, |
| constr_name.ToCString(), |
| error_message.ToCString())); |
| ThrowMirroredCompilationError(message); |
| UNREACHABLE(); |
| } |
| return constructor.raw(); |
| } |
| |
| |
| static bool FieldIsUninitialized(const Field& field) { |
| ASSERT(!field.IsNull()); |
| |
| // Return getter method for uninitialized fields, rather than the |
| // field object, since the value in the field object will not be |
| // initialized until the first time the getter is invoked. |
| const Instance& value = Instance::Handle(field.value()); |
| ASSERT(value.raw() != Object::transition_sentinel().raw()); |
| return value.raw() == Object::sentinel().raw(); |
| } |
| |
| |
| DEFINE_NATIVE_ENTRY(ClassMirror_name, 1) { |
| const MirrorReference& klass_ref = |
| MirrorReference::CheckedHandle(arguments->NativeArgAt(0)); |
| Class& klass = Class::Handle(); |
| klass ^= klass_ref.referent(); |
| return klass.Name(); |
| } |
| |
| |
| DEFINE_NATIVE_ENTRY(ClassMirror_library, 1) { |
| const MirrorReference& klass_ref = |
| MirrorReference::CheckedHandle(arguments->NativeArgAt(0)); |
| Class& klass = Class::Handle(); |
| klass ^= klass_ref.referent(); |
| |
| return CreateLibraryMirror(Library::Handle(klass.library())); |
| } |
| |
| |
| // Invoke the function, or noSuchMethod if it is null. Propagate any unhandled |
| // exceptions. Wrap and propagate any compilation errors. |
| static RawObject* ReflectivelyInvokeDynamicFunction(const Instance& receiver, |
| const Function& function, |
| const String& target_name, |
| const Array& arguments) { |
| // Note "arguments" is already the internal arguments with the receiver as |
| // the first element. |
| Object& result = Object::Handle(); |
| if (function.IsNull()) { |
| const Array& arguments_descriptor = |
| Array::Handle(ArgumentsDescriptor::New(arguments.Length())); |
| result = DartEntry::InvokeNoSuchMethod(receiver, |
| target_name, |
| arguments, |
| arguments_descriptor); |
| } else { |
| result = DartEntry::InvokeFunction(function, arguments); |
| } |
| |
| if (result.IsError()) { |
| ThrowInvokeError(Error::Cast(result)); |
| UNREACHABLE(); |
| } |
| return result.raw(); |
| } |
| |
| |
| DEFINE_NATIVE_ENTRY(InstanceMirror_invoke, 4) { |
| // Argument 0 is the mirror, which is unused by the native. It exists |
| // because this native is an instance method in order to be polymorphic |
| // with its cousins. |
| |
| const Instance& reflectee = |
| Instance::CheckedHandle(arguments->NativeArgAt(1)); |
| |
| const String& function_name = |
| String::CheckedHandle(arguments->NativeArgAt(2)); |
| |
| const Array& positional_args = |
| Array::CheckedHandle(arguments->NativeArgAt(3)); |
| intptr_t number_of_arguments = positional_args.Length(); |
| |
| const Array& args = |
| Array::Handle(Array::New(number_of_arguments + 1)); // Plus receiver. |
| Object& arg = Object::Handle(); |
| args.SetAt(0, reflectee); |
| for (int i = 0; i < number_of_arguments; i++) { |
| arg = positional_args.At(i); |
| args.SetAt(i + 1, arg); // Plus receiver. |
| } |
| |
| ArgumentsDescriptor args_desc( |
| Array::Handle(ArgumentsDescriptor::New(args.Length()))); |
| // TODO(11771): This won't find private members. |
| const Function& function = Function::Handle( |
| Resolver::ResolveDynamic(reflectee, |
| function_name, |
| args_desc)); |
| |
| return ReflectivelyInvokeDynamicFunction(reflectee, |
| function, |
| function_name, |
| args); |
| } |
| |
| |
| DEFINE_NATIVE_ENTRY(InstanceMirror_invokeGetter, 3) { |
| // Argument 0 is the mirror, which is unused by the native. It exists |
| // because this native is an instance method in order to be polymorphic |
| // with its cousins. |
| |
| const Instance& reflectee = |
| Instance::CheckedHandle(arguments->NativeArgAt(1)); |
| |
| const String& getter_name = |
| String::CheckedHandle(arguments->NativeArgAt(2)); |
| |
| // Every instance field has a getter Function. Try to find the |
| // getter in any superclass and use that function to access the |
| // field. |
| // NB: We do not use Resolver::ResolveDynamic because we want to find private |
| // members. |
| Class& klass = Class::Handle(reflectee.clazz()); |
| String& internal_getter_name = String::Handle(Field::GetterName(getter_name)); |
| Function& getter = Function::Handle(); |
| while (!klass.IsNull()) { |
| getter = klass.LookupDynamicFunctionAllowPrivate(internal_getter_name); |
| if (!getter.IsNull()) { |
| break; |
| } |
| klass = klass.SuperClass(); |
| } |
| |
| const int kNumArgs = 1; |
| const Array& args = Array::Handle(Array::New(kNumArgs)); |
| args.SetAt(0, reflectee); |
| |
| return ReflectivelyInvokeDynamicFunction(reflectee, |
| getter, |
| internal_getter_name, |
| args); |
| } |
| |
| |
| DEFINE_NATIVE_ENTRY(InstanceMirror_invokeSetter, 4) { |
| // Argument 0 is the mirror, which is unused by the native. It exists |
| // because this native is an instance method in order to be polymorphic |
| // with its cousins. |
| |
| const Instance& reflectee = |
| Instance::CheckedHandle(arguments->NativeArgAt(1)); |
| |
| const String& setter_name = |
| String::CheckedHandle(arguments->NativeArgAt(2)); |
| |
| const Instance& value = Instance::CheckedHandle(arguments->NativeArgAt(3)); |
| |
| String& internal_setter_name = |
| String::Handle(Field::SetterName(setter_name)); |
| Function& setter = Function::Handle(); |
| |
| Class& klass = Class::Handle(reflectee.clazz()); |
| Field& field = Field::Handle(); |
| |
| while (!klass.IsNull()) { |
| field = klass.LookupInstanceField(setter_name); |
| if (!field.IsNull() && field.is_final()) { |
| const String& message = String::Handle( |
| String::NewFormatted("%s: cannot set final field '%s'.", |
| "InstanceMirror_invokeSetter", |
| setter_name.ToCString())); |
| ThrowMirroredCompilationError(message); |
| UNREACHABLE(); |
| } |
| setter = klass.LookupDynamicFunctionAllowPrivate(internal_setter_name); |
| if (!setter.IsNull()) { |
| break; |
| } |
| klass = klass.SuperClass(); |
| } |
| |
| // Invoke the setter and return the result. |
| const int kNumArgs = 2; |
| const Array& args = Array::Handle(Array::New(kNumArgs)); |
| args.SetAt(0, reflectee); |
| args.SetAt(1, value); |
| |
| return ReflectivelyInvokeDynamicFunction(reflectee, |
| setter, |
| internal_setter_name, |
| args); |
| } |
| |
| |
| DEFINE_NATIVE_ENTRY(ClosureMirror_apply, 2) { |
| const Instance& closure = Instance::CheckedHandle(arguments->NativeArgAt(0)); |
| ASSERT(!closure.IsNull() && closure.IsCallable(NULL, NULL)); |
| |
| const Array& positional_args = |
| Array::CheckedHandle(arguments->NativeArgAt(1)); |
| intptr_t number_of_arguments = positional_args.Length(); |
| |
| // Set up arguments to include the closure as the first argument. |
| const Array& args = Array::Handle(Array::New(number_of_arguments + 1)); |
| Object& obj = Object::Handle(); |
| args.SetAt(0, closure); |
| for (int i = 0; i < number_of_arguments; i++) { |
| obj = positional_args.At(i); |
| args.SetAt(i + 1, obj); |
| } |
| |
| obj = DartEntry::InvokeClosure(args); |
| if (obj.IsError()) { |
| ThrowInvokeError(Error::Cast(obj)); |
| UNREACHABLE(); |
| } |
| return obj.raw(); |
| } |
| |
| |
| DEFINE_NATIVE_ENTRY(ClassMirror_invoke, 4) { |
| // Argument 0 is the mirror, which is unused by the native. It exists |
| // because this native is an instance method in order to be polymorphic |
| // with its cousins. |
| |
| const MirrorReference& klass_ref = |
| MirrorReference::CheckedHandle(arguments->NativeArgAt(1)); |
| Class& klass = Class::Handle(); |
| klass ^= klass_ref.referent(); |
| |
| const String& function_name = |
| String::CheckedHandle(arguments->NativeArgAt(2)); |
| |
| const Array& positional_args = |
| Array::CheckedHandle(arguments->NativeArgAt(3)); |
| intptr_t number_of_arguments = positional_args.Length(); |
| |
| // TODO(11771): This won't find private members. |
| const Function& function = Function::Handle( |
| Resolver::ResolveStatic(klass, |
| function_name, |
| number_of_arguments, |
| Object::empty_array(), |
| Resolver::kIsQualified)); |
| if (function.IsNull()) { |
| const String& klass_name = String::Handle(klass.Name()); |
| const String& message = String::Handle( |
| String::NewFormatted("%s: did not find static method '%s.%s'.", |
| "ClassMirror_invoke", |
| klass_name.ToCString(), |
| function_name.ToCString())); |
| ThrowMirroredCompilationError(message); |
| UNREACHABLE(); |
| } |
| Object& result = Object::Handle(DartEntry::InvokeFunction(function, |
| positional_args)); |
| if (result.IsError()) { |
| ThrowInvokeError(Error::Cast(result)); |
| UNREACHABLE(); |
| } |
| return result.raw(); |
| } |
| |
| |
| DEFINE_NATIVE_ENTRY(ClassMirror_invokeGetter, 3) { |
| // Argument 0 is the mirror, which is unused by the native. It exists |
| // because this native is an instance method in order to be polymorphic |
| // with its cousins. |
| |
| const MirrorReference& klass_ref = |
| MirrorReference::CheckedHandle(arguments->NativeArgAt(1)); |
| Class& klass = Class::Handle(); |
| klass ^= klass_ref.referent(); |
| |
| const String& getter_name = |
| String::CheckedHandle(arguments->NativeArgAt(2)); |
| |
| // Note static fields do not have implicit getters. |
| const Field& field = Field::Handle(klass.LookupStaticField(getter_name)); |
| if (field.IsNull() || FieldIsUninitialized(field)) { |
| const String& internal_getter_name = String::Handle( |
| Field::GetterName(getter_name)); |
| const Function& getter = Function::Handle( |
| klass.LookupStaticFunctionAllowPrivate(internal_getter_name)); |
| |
| if (getter.IsNull()) { |
| const String& message = String::Handle( |
| String::NewFormatted("%s: did not find static getter '%s'.", |
| "ClassMirror_invokeGetter", |
| getter_name.ToCString())); |
| ThrowMirroredCompilationError(message); |
| UNREACHABLE(); |
| } |
| |
| // Invoke the getter and return the result. |
| Object& result = Object::Handle( |
| DartEntry::InvokeFunction(getter, Object::empty_array())); |
| if (result.IsError()) { |
| ThrowInvokeError(Error::Cast(result)); |
| UNREACHABLE(); |
| } |
| return result.raw(); |
| } |
| return field.value(); |
| } |
| |
| |
| DEFINE_NATIVE_ENTRY(ClassMirror_invokeSetter, 4) { |
| // Argument 0 is the mirror, which is unused by the native. It exists |
| // because this native is an instance method in order to be polymorphic |
| // with its cousins. |
| |
| const MirrorReference& klass_ref = |
| MirrorReference::CheckedHandle(arguments->NativeArgAt(1)); |
| Class& klass = Class::Handle(); |
| klass ^= klass_ref.referent(); |
| |
| const String& setter_name = |
| String::CheckedHandle(arguments->NativeArgAt(2)); |
| |
| const Instance& value = Instance::CheckedHandle(arguments->NativeArgAt(3)); |
| |
| // Check for real fields and user-defined setters. |
| const Field& field = Field::Handle(klass.LookupStaticField(setter_name)); |
| if (field.IsNull()) { |
| const String& internal_setter_name = String::Handle( |
| Field::SetterName(setter_name)); |
| const Function& setter = Function::Handle( |
| klass.LookupStaticFunctionAllowPrivate(internal_setter_name)); |
| |
| if (setter.IsNull()) { |
| const String& message = String::Handle( |
| String::NewFormatted("%s: did not find static setter '%s'.", |
| "ClassMirror_invokeSetter", |
| setter_name.ToCString())); |
| ThrowMirroredCompilationError(message); |
| UNREACHABLE(); |
| } |
| |
| // Invoke the setter and return the result. |
| const int kNumArgs = 1; |
| const Array& args = Array::Handle(Array::New(kNumArgs)); |
| args.SetAt(0, value); |
| |
| Object& result = Object::Handle( |
| DartEntry::InvokeFunction(setter, args)); |
| if (result.IsError()) { |
| ThrowInvokeError(Error::Cast(result)); |
| UNREACHABLE(); |
| } |
| return result.raw(); |
| } |
| |
| if (field.is_final()) { |
| const String& message = String::Handle( |
| String::NewFormatted("%s: cannot set final field '%s'.", |
| "ClassMirror_invokeSetter", |
| setter_name.ToCString())); |
| ThrowMirroredCompilationError(message); |
| UNREACHABLE(); |
| } |
| |
| field.set_value(value); |
| return value.raw(); |
| } |
| |
| |
| DEFINE_NATIVE_ENTRY(ClassMirror_invokeConstructor, 3) { |
| const MirrorReference& klass_ref = |
| MirrorReference::CheckedHandle(arguments->NativeArgAt(0)); |
| Class& klass = Class::Handle(); |
| klass ^= klass_ref.referent(); |
| |
| const String& constructor_name = |
| String::CheckedHandle(arguments->NativeArgAt(1)); |
| |
| const Array& positional_args = |
| Array::CheckedHandle(arguments->NativeArgAt(2)); |
| |
| intptr_t number_of_arguments = positional_args.Length(); |
| |
| // By convention, the static function implementing a named constructor 'C' |
| // for class 'A' is labeled 'A.C', and the static function implementing the |
| // unnamed constructor for class 'A' is labeled 'A.'. |
| // This convention prevents users from explicitly calling constructors. |
| const String& klass_name = String::Handle(klass.Name()); |
| String& internal_constructor_name = |
| String::Handle(String::Concat(klass_name, Symbols::Dot())); |
| if (!constructor_name.IsNull()) { |
| internal_constructor_name = |
| String::Concat(internal_constructor_name, constructor_name); |
| } |
| |
| const Function& constructor = |
| Function::Handle(ResolveConstructor("ClassMirror_invokeConstructor", |
| klass, |
| klass_name, |
| internal_constructor_name, |
| number_of_arguments)); |
| |
| const Object& result = |
| Object::Handle(DartEntry::InvokeConstructor(klass, |
| constructor, |
| positional_args)); |
| if (result.IsError()) { |
| ThrowInvokeError(Error::Cast(result)); |
| UNREACHABLE(); |
| } |
| // Factories may return null. |
| ASSERT(result.IsInstance() || result.IsNull()); |
| return result.raw(); |
| } |
| |
| |
| DEFINE_NATIVE_ENTRY(LibraryMirror_invoke, 4) { |
| // Argument 0 is the mirror, which is unused by the native. It exists |
| // because this native is an instance method in order to be polymorphic |
| // with its cousins. |
| |
| const MirrorReference& library_ref = |
| MirrorReference::CheckedHandle(arguments->NativeArgAt(1)); |
| Library& library = Library::Handle(); |
| library ^= library_ref.referent(); |
| |
| const String& function_name = |
| String::CheckedHandle(arguments->NativeArgAt(2)); |
| |
| const Array& positional_args = |
| Array::CheckedHandle(arguments->NativeArgAt(3)); |
| intptr_t number_of_arguments = positional_args.Length(); |
| |
| |
| const Function& function = Function::Handle( |
| library.LookupFunctionAllowPrivate(function_name)); |
| |
| if (function.IsNull()) { |
| const String& message = String::Handle( |
| String::NewFormatted("%s: did not find top-level function '%s'.", |
| "LibraryMirror_invoke", |
| function_name.ToCString())); |
| ThrowMirroredCompilationError(message); |
| UNREACHABLE(); |
| } |
| |
| // LookupFunctionAllowPrivate does not check argument arity, so we |
| // do it here. |
| String& error_message = String::Handle(); |
| if (!function.AreValidArgumentCounts(number_of_arguments, |
| /* num_named_args */ 0, |
| &error_message)) { |
| const String& message = String::Handle( |
| String::NewFormatted("%s: wrong argument count for function '%s': %s.", |
| "LibraryMirror_invoke", |
| function_name.ToCString(), |
| error_message.ToCString())); |
| ThrowMirroredCompilationError(message); |
| UNREACHABLE(); |
| } |
| |
| const Object& result = Object::Handle( |
| DartEntry::InvokeFunction(function, positional_args)); |
| if (result.IsError()) { |
| ThrowInvokeError(Error::Cast(result)); |
| UNREACHABLE(); |
| } |
| return result.raw(); |
| } |
| |
| |
| DEFINE_NATIVE_ENTRY(LibraryMirror_invokeGetter, 3) { |
| // Argument 0 is the mirror, which is unused by the native. It exists |
| // because this native is an instance method in order to be polymorphic |
| // with its cousins. |
| |
| const MirrorReference& library_ref = |
| MirrorReference::CheckedHandle(arguments->NativeArgAt(1)); |
| Library& library = Library::Handle(); |
| library ^= library_ref.referent(); |
| |
| const String& getter_name = |
| String::CheckedHandle(arguments->NativeArgAt(2)); |
| |
| // To access a top-level we may need to use the Field or the |
| // getter Function. The getter function may either be in the |
| // library or in the field's owner class, depending. |
| const Field& field = |
| Field::Handle(library.LookupFieldAllowPrivate(getter_name)); |
| Function& getter = Function::Handle(); |
| if (field.IsNull()) { |
| // No field found. Check for a getter in the lib. |
| const String& internal_getter_name = |
| String::Handle(Field::GetterName(getter_name)); |
| getter = library.LookupFunctionAllowPrivate(internal_getter_name); |
| } else if (FieldIsUninitialized(field)) { |
| // A field was found. Check for a getter in the field's owner classs. |
| const Class& klass = Class::Handle(field.owner()); |
| const String& internal_getter_name = |
| String::Handle(Field::GetterName(getter_name)); |
| getter = klass.LookupStaticFunctionAllowPrivate(internal_getter_name); |
| } |
| |
| if (!getter.IsNull()) { |
| // Invoke the getter and return the result. |
| const Object& result = Object::Handle( |
| DartEntry::InvokeFunction(getter, Object::empty_array())); |
| if (result.IsError()) { |
| ThrowInvokeError(Error::Cast(result)); |
| UNREACHABLE(); |
| } |
| return result.raw(); |
| } else if (!field.IsNull()) { |
| return field.value(); |
| } else { |
| const String& message = String::Handle( |
| String::NewFormatted("%s: did not find top-level variable '%s'.", |
| "LibraryMirror_invokeGetter", |
| getter_name.ToCString())); |
| ThrowMirroredCompilationError(message); |
| UNREACHABLE(); |
| return Instance::null(); |
| } |
| } |
| |
| |
| DEFINE_NATIVE_ENTRY(LibraryMirror_invokeSetter, 4) { |
| // Argument 0 is the mirror, which is unused by the native. It exists |
| // because this native is an instance method in order to be polymorphic |
| // with its cousins. |
| |
| const MirrorReference& library_ref = |
| MirrorReference::CheckedHandle(arguments->NativeArgAt(1)); |
| Library& library = Library::Handle(); |
| library ^= library_ref.referent(); |
| |
| const String& setter_name = |
| String::CheckedHandle(arguments->NativeArgAt(2)); |
| |
| const Instance& value = Instance::CheckedHandle(arguments->NativeArgAt(3)); |
| |
| // To access a top-level we may need to use the Field or the |
| // setter Function. The setter function may either be in the |
| // library or in the field's owner class, depending. |
| const Field& field = |
| Field::Handle(library.LookupFieldAllowPrivate(setter_name)); |
| |
| if (field.IsNull()) { |
| const String& internal_setter_name = |
| String::Handle(Field::SetterName(setter_name)); |
| const Function& setter = Function::Handle( |
| library.LookupFunctionAllowPrivate(internal_setter_name)); |
| |
| if (setter.IsNull()) { |
| const String& message = String::Handle( |
| String::NewFormatted("%s: did not find top-level variable '%s'.", |
| "LibraryMirror_invokeSetter", |
| setter_name.ToCString())); |
| ThrowMirroredCompilationError(message); |
| UNREACHABLE(); |
| } |
| |
| // Invoke the setter and return the result. |
| const int kNumArgs = 1; |
| const Array& args = Array::Handle(Array::New(kNumArgs)); |
| args.SetAt(0, value); |
| const Object& result = Object::Handle( |
| DartEntry::InvokeFunction(setter, args)); |
| if (result.IsError()) { |
| ThrowInvokeError(Error::Cast(result)); |
| UNREACHABLE(); |
| } |
| return result.raw(); |
| } |
| |
| if (field.is_final()) { |
| const String& message = String::Handle( |
| String::NewFormatted("%s: cannot set final top-level variable '%s'.", |
| "LibraryMirror_invokeSetter", |
| setter_name.ToCString())); |
| ThrowMirroredCompilationError(message); |
| UNREACHABLE(); |
| } |
| |
| field.set_value(value); |
| return value.raw(); |
| } |
| |
| |
| DEFINE_NATIVE_ENTRY(MethodMirror_name, 1) { |
| const MirrorReference& func_ref = |
| MirrorReference::CheckedHandle(arguments->NativeArgAt(0)); |
| Function& func = Function::Handle(); |
| func ^= func_ref.referent(); |
| return func.UserVisibleName(); |
| } |
| |
| |
| DEFINE_NATIVE_ENTRY(MethodMirror_owner, 1) { |
| const MirrorReference& func_ref = |
| MirrorReference::CheckedHandle(arguments->NativeArgAt(0)); |
| Function& func = Function::Handle(); |
| func ^= func_ref.referent(); |
| if (func.IsNonImplicitClosureFunction()) { |
| return CreateMethodMirror(Function::Handle( |
| func.parent_function()), Instance::Handle()); |
| } |
| const Class& owner = Class::Handle(func.Owner()); |
| if (owner.IsTopLevel()) { |
| return CreateLibraryMirror(Library::Handle(owner.library())); |
| } |
| return CreateClassMirror(owner, Instance::Handle()); |
| } |
| |
| } // namespace dart |