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

Unified Diff: runtime/lib/mirrors.cc

Issue 18463003: Implement the invoke methods (invoke, getField, setField, newInstance, apply) as internal natives. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | runtime/lib/mirrors_impl.dart » ('j') | tests/lib/mirrors/mirrors_test.dart » ('J')
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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));
« no previous file with comments | « no previous file | runtime/lib/mirrors_impl.dart » ('j') | tests/lib/mirrors/mirrors_test.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698