Index: runtime/lib/mirrors.cc |
=================================================================== |
--- runtime/lib/mirrors.cc (revision 25019) |
+++ runtime/lib/mirrors.cc (working copy) |
@@ -13,6 +13,7 @@ |
#include "vm/message.h" |
#include "vm/port.h" |
#include "vm/resolver.h" |
+#include "vm/symbols.h" |
namespace dart { |
@@ -68,19 +69,6 @@ |
} |
-static Dart_Handle IsMirror(Dart_Handle object, bool* is_mirror) { |
- Dart_Handle cls_name = NewString("Mirror"); |
- 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 IsMethodMirror(Dart_Handle object, bool* is_mirror) { |
Dart_Handle cls_name = NewString("MethodMirror"); |
Dart_Handle type = Dart_GetType(MirrorLib(), cls_name, 0, NULL); |
@@ -108,14 +96,6 @@ |
} |
-static bool IsSimpleValue(Dart_Handle object) { |
- return (Dart_IsNull(object) || |
- Dart_IsNumber(object) || |
- Dart_IsString(object) || |
- Dart_IsBoolean(object)); |
-} |
- |
- |
static void FreeVMReference(Dart_WeakPersistentHandle weak_ref, void* data) { |
Dart_PersistentHandle perm_handle = |
reinterpret_cast<Dart_PersistentHandle>(data); |
@@ -282,59 +262,7 @@ |
// will return nonsense if mirror is not an ObjectMirror |
} |
-static Dart_Handle UnwrapArg(Dart_Handle arg) { |
- if (Dart_IsError(arg)) { |
- return arg; |
- } |
- bool is_mirror = false; |
- Dart_Handle result = IsMirror(arg, &is_mirror); |
- if (Dart_IsError(result)) { |
- return result; |
- } |
- if (is_mirror) { |
- return UnwrapMirror(arg); |
- } else { |
- // Simple value. |
- ASSERT(IsSimpleValue(arg)); |
- return arg; |
- } |
-} |
-static Dart_Handle UnwrapArgList(Dart_Handle arg_list, |
- GrowableArray<Dart_Handle>* arg_array) { |
- intptr_t len = 0; |
- Dart_Handle result = Dart_ListLength(arg_list, &len); |
- if (Dart_IsError(result)) { |
- return result; |
- } |
- for (intptr_t i = 0; i < len; i++) { |
- Dart_Handle arg = Dart_ListGetAt(arg_list, i); |
- Dart_Handle unwrapped_arg = UnwrapArg(arg); |
- if (Dart_IsError(unwrapped_arg)) { |
- return unwrapped_arg; |
- } |
- arg_array->Add(unwrapped_arg); |
- } |
- return Dart_True(); |
-} |
- |
-static Dart_Handle UnpackLocalArgList(Dart_Handle arg_list, |
- GrowableArray<Dart_Handle>* arg_array) { |
- intptr_t len = 0; |
- Dart_Handle result = Dart_ListLength(arg_list, &len); |
- if (Dart_IsError(result)) { |
- return result; |
- } |
- for (intptr_t i = 0; i < len; i++) { |
- Dart_Handle arg = Dart_ListGetAt(arg_list, i); |
- if (Dart_IsError(arg)) { |
- return arg; |
- } |
- arg_array->Add(arg); |
- } |
- return Dart_True(); |
-} |
- |
static Dart_Handle CreateLazyMirror(Dart_Handle target); |
@@ -952,6 +880,7 @@ |
return member_map; |
} |
Dart_Handle args[] = { |
+ CreateMirrorReference(lib), |
CreateVMReference(lib), |
Dart_LibraryName(lib), |
Dart_LibraryUrl(lib), |
@@ -1121,51 +1050,6 @@ |
} |
-static Dart_Handle CreateMirroredError(Dart_Handle error) { |
- ASSERT(Dart_IsError(error)); |
- if (Dart_IsUnhandledExceptionError(error)) { |
- Dart_Handle exc = Dart_ErrorGetException(error); |
- if (Dart_IsError(exc)) { |
- return exc; |
- } |
- Dart_Handle exc_string = Dart_ToString(exc); |
- if (Dart_IsError(exc_string)) { |
- // Only propagate fatal errors from exc.toString(). Ignore the rest. |
- if (Dart_IsFatalError(exc_string)) { |
- return exc_string; |
- } |
- exc_string = Dart_Null(); |
- } |
- |
- Dart_Handle stack = Dart_ErrorGetStacktrace(error); |
- if (Dart_IsError(stack)) { |
- return stack; |
- } |
- Dart_Handle cls_name = NewString("MirroredUncaughtExceptionError"); |
- Dart_Handle type = Dart_GetType(MirrorLib(), cls_name, 0, NULL); |
- Dart_Handle args[] = { |
- CreateInstanceMirror(exc), |
- exc_string, |
- stack, |
- }; |
- Dart_Handle mirrored_exc = |
- Dart_New(type, Dart_Null(), ARRAY_SIZE(args), args); |
- return Dart_NewUnhandledExceptionError(mirrored_exc); |
- } else if (Dart_IsApiError(error) || |
- Dart_IsCompilationError(error)) { |
- Dart_Handle cls_name = NewString("MirroredCompilationError"); |
- Dart_Handle type = Dart_GetType(MirrorLib(), cls_name, 0, NULL); |
- Dart_Handle args[] = { NewString(Dart_GetError(error)) }; |
- Dart_Handle mirrored_exc = |
- Dart_New(type, Dart_Null(), ARRAY_SIZE(args), args); |
- return Dart_NewUnhandledExceptionError(mirrored_exc); |
- } else { |
- ASSERT(Dart_IsFatalError(error)); |
- return error; |
- } |
-} |
- |
- |
void NATIVE_ENTRY_FUNCTION(Mirrors_makeLocalMirrorSystem)( |
Dart_NativeArguments args) { |
Dart_EnterScope(); |
@@ -1242,192 +1126,697 @@ |
Dart_ExitScope(); |
} |
-void NATIVE_ENTRY_FUNCTION(LocalObjectMirrorImpl_invoke)( |
- Dart_NativeArguments args) { |
- Dart_EnterScope(); |
- Dart_Handle mirror = Dart_GetNativeArgument(args, 0); |
- Dart_Handle member_name = Dart_GetNativeArgument(args, 1); |
- // The arguments are either simple values or instance mirrors. |
- Dart_Handle positional_arguments = Dart_GetNativeArgument(args, 2); |
- Dart_Handle async = Dart_GetNativeArgument(args, 3); |
- Dart_Handle reflectee = UnwrapMirror(mirror); |
- Dart_Handle result; |
- GrowableArray<Dart_Handle> invoke_args; |
- if (Dart_IdentityEquals(async, Dart_True())) { |
- result = UnwrapArgList(positional_arguments, &invoke_args); |
- } else { |
- result = UnpackLocalArgList(positional_arguments, &invoke_args); |
+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(); |
} |
- if (Dart_IsError(result)) { |
- Dart_PropagateError(result); |
+ |
+ 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); |
} |
- result = Dart_Invoke(reflectee, |
- member_name, |
- invoke_args.length(), |
- invoke_args.data()); |
- if (Dart_IsError(result)) { |
- // Instead of propagating the error from an invoke directly, we |
- // provide reflective access to the error. |
- Dart_PropagateError(CreateMirroredError(result)); |
+ 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(); |
+} |
- Dart_Handle wrapped_result = CreateInstanceMirror(result); |
- if (Dart_IsError(wrapped_result)) { |
- Dart_PropagateError(wrapped_result); |
+ |
+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(); |
+ } |
} |
- Dart_SetReturnValue(args, wrapped_result); |
- Dart_ExitScope(); |
+ 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(); |
} |
-void NATIVE_ENTRY_FUNCTION(LocalObjectMirrorImpl_getField)( |
- Dart_NativeArguments args) { |
- Dart_EnterScope(); |
- Dart_Handle mirror = Dart_GetNativeArgument(args, 0); |
- Dart_Handle fieldName = Dart_GetNativeArgument(args, 1); |
+static bool FieldIsUninitialized(const Field& field) { |
+ ASSERT(!field.IsNull()); |
- Dart_Handle reflectee = UnwrapMirror(mirror); |
- Dart_Handle result = Dart_GetField(reflectee, fieldName); |
- if (Dart_IsError(result)) { |
- // Instead of propagating the error from a GetField directly, we |
- // provide reflective access to the error. |
- Dart_PropagateError(CreateMirroredError(result)); |
+ // 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(); |
+} |
+ |
+ |
+// 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); |
} |
- Dart_Handle wrapped_result = CreateInstanceMirror(result); |
- if (Dart_IsError(wrapped_result)) { |
- Dart_PropagateError(wrapped_result); |
+ if (result.IsError()) { |
+ ThrowInvokeError(Error::Cast(result)); |
+ UNREACHABLE(); |
} |
- Dart_SetReturnValue(args, wrapped_result); |
- Dart_ExitScope(); |
+ return result.raw(); |
} |
-void NATIVE_ENTRY_FUNCTION(LocalObjectMirrorImpl_setField)( |
- Dart_NativeArguments args) { |
- Dart_EnterScope(); |
- Dart_Handle mirror = Dart_GetNativeArgument(args, 0); |
- Dart_Handle fieldName = Dart_GetNativeArgument(args, 1); |
- Dart_Handle value = Dart_GetNativeArgument(args, 2); |
- Dart_Handle async = Dart_GetNativeArgument(args, 3); |
+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. |
- Dart_Handle reflectee = UnwrapMirror(mirror); |
- Dart_Handle set_arg; |
- if (Dart_IdentityEquals(async, Dart_True())) { |
- set_arg = UnwrapArg(value); |
- } else { |
- set_arg = value; |
+ 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 intptr_t num_receiver = 1; // 1 for instance methods |
+ const Array& args = |
+ Array::Handle(Array::New(number_of_arguments + num_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 + num_receiver), arg); |
Florian Schneider
2013/07/16 09:39:56
Please don't over-parenthesize. I don't think ther
|
} |
- if (Dart_IsError(set_arg)) { |
- Dart_PropagateError(set_arg); |
+ |
+ // TODO(11771): This won't find private members. |
+ const Function& function = Function::Handle( |
+ Resolver::ResolveDynamic(reflectee, |
+ function_name, |
+ (number_of_arguments + 1), |
Florian Schneider
2013/07/16 09:39:56
Please don't over-parenthesize. I don't think ther
|
+ Resolver::kIsQualified)); |
Florian Schneider
2013/07/16 09:39:56
This is an enum where the function expects an int.
|
+ |
+ 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(); |
} |
- Dart_Handle result = Dart_SetField(reflectee, fieldName, set_arg); |
- if (Dart_IsError(result)) { |
- // Instead of propagating the error from a SetField directly, we |
- // provide reflective access to the error. |
- Dart_PropagateError(CreateMirroredError(result)); |
+ |
+ 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(); |
} |
- Dart_Handle wrapped_result = CreateInstanceMirror(result); |
- if (Dart_IsError(wrapped_result)) { |
- Dart_PropagateError(wrapped_result); |
- } |
- Dart_SetReturnValue(args, wrapped_result); |
- Dart_ExitScope(); |
+ // 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); |
} |
-void NATIVE_ENTRY_FUNCTION(LocalClosureMirrorImpl_apply)( |
- Dart_NativeArguments args) { |
- Dart_EnterScope(); |
- Dart_Handle mirror = Dart_GetNativeArgument(args, 0); |
- // The arguments are either simple values or instance mirrors. |
- Dart_Handle positional_arguments = Dart_GetNativeArgument(args, 1); |
- Dart_Handle async = Dart_GetNativeArgument(args, 2); |
+DEFINE_NATIVE_ENTRY(ClosureMirror_apply, 2) { |
+ const Instance& closure = Instance::CheckedHandle(arguments->NativeArgAt(0)); |
+ ASSERT(!closure.IsNull() && closure.IsCallable(NULL, NULL)); |
- Dart_Handle reflectee = UnwrapMirror(mirror); |
- GrowableArray<Dart_Handle> invoke_args; |
- Dart_Handle result; |
- if (Dart_IdentityEquals(async, Dart_True())) { |
- result = UnwrapArgList(positional_arguments, &invoke_args); |
- } else { |
- result = UnpackLocalArgList(positional_arguments, &invoke_args); |
+ 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); |
} |
- if (Dart_IsError(result)) { |
- Dart_PropagateError(result); |
- } |
- result = |
- Dart_InvokeClosure(reflectee, invoke_args.length(), invoke_args.data()); |
- if (Dart_IsError(result)) { |
- // Instead of propagating the error from an apply directly, we |
- // provide reflective access to the error. |
- Dart_PropagateError(CreateMirroredError(result)); |
- } |
- Dart_Handle wrapped_result = CreateInstanceMirror(result); |
- if (Dart_IsError(wrapped_result)) { |
- Dart_PropagateError(wrapped_result); |
+ obj = DartEntry::InvokeClosure(args); |
+ if (obj.IsError()) { |
+ ThrowInvokeError(Error::Cast(obj)); |
+ UNREACHABLE(); |
} |
- Dart_SetReturnValue(args, wrapped_result); |
- Dart_ExitScope(); |
+ return obj.raw(); |
} |
-void NATIVE_ENTRY_FUNCTION(LocalClassMirrorImpl_invokeConstructor)( |
- Dart_NativeArguments args) { |
- Dart_EnterScope(); |
- Dart_Handle klass_mirror = Dart_GetNativeArgument(args, 0); |
- Dart_Handle constructor_name = Dart_GetNativeArgument(args, 1); |
- // The arguments are either simple values or instance mirrors. |
- Dart_Handle positional_arguments = Dart_GetNativeArgument(args, 2); |
- Dart_Handle async = Dart_GetNativeArgument(args, 3); |
+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. |
- Dart_Handle klass = UnwrapMirror(klass_mirror); |
- GrowableArray<Dart_Handle> invoke_args; |
- Dart_Handle result; |
- if (Dart_IdentityEquals(async, Dart_True())) { |
- result = UnwrapArgList(positional_arguments, &invoke_args); |
- } else { |
- result = UnpackLocalArgList(positional_arguments, &invoke_args); |
+ 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 %d-arg static method '%s.%s'.", |
+ "ClassMirror_invoke", |
+ number_of_arguments, |
+ klass_name.ToCString(), |
+ function_name.ToCString())); |
+ ThrowMirroredCompilationError(message); |
+ UNREACHABLE(); |
} |
- if (Dart_IsError(result)) { |
- Dart_PropagateError(result); |
+ Object& result = Object::Handle(DartEntry::InvokeFunction(function, |
+ positional_args)); |
+ if (result.IsError()) { |
+ ThrowInvokeError(Error::Cast(result)); |
+ UNREACHABLE(); |
} |
- result = Dart_New(klass, |
- constructor_name, |
- invoke_args.length(), |
- invoke_args.data()); |
- if (Dart_IsError(result)) { |
- // Instead of propagating the error from an invoke directly, we |
- // provide reflective access to the error. |
- Dart_PropagateError(CreateMirroredError(result)); |
- } |
+ return result.raw(); |
+} |
- Dart_Handle wrapped_result = CreateInstanceMirror(result); |
- if (Dart_IsError(wrapped_result)) { |
- Dart_PropagateError(wrapped_result); |
+ |
+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(); |
} |
- Dart_SetReturnValue(args, wrapped_result); |
- Dart_ExitScope(); |
+ return field.value(); |
} |
-void HandleMirrorsMessage(Isolate* isolate, |
- Dart_Port reply_port, |
- const Instance& message) { |
- UNIMPLEMENTED(); |
+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_name, 1) { |
+DEFINE_NATIVE_ENTRY(ClassMirror_invokeConstructor, 3) { |
const MirrorReference& klass_ref = |
MirrorReference::CheckedHandle(arguments->NativeArgAt(0)); |
Class& klass = Class::Handle(); |
klass ^= klass_ref.referent(); |
- return klass.Name(); |
+ |
+ 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)); |