2012-03-12 23:51:03 +00:00
|
|
|
// 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.
|
|
|
|
|
2012-05-30 17:07:19 +00:00
|
|
|
#include "include/dart_api.h"
|
|
|
|
#include "include/dart_debugger_api.h"
|
2013-06-14 23:47:40 +00:00
|
|
|
#include "include/dart_mirrors_api.h"
|
2013-04-17 10:11:21 +00:00
|
|
|
#include "vm/dart_api_impl.h"
|
2013-07-08 22:05:15 +00:00
|
|
|
#include "vm/dart_api_state.h" // TODO(11742): Remove with CreateMirrorRef.
|
2012-08-30 17:41:19 +00:00
|
|
|
#include "vm/bootstrap_natives.h"
|
2012-03-12 23:51:03 +00:00
|
|
|
#include "vm/dart_entry.h"
|
|
|
|
#include "vm/exceptions.h"
|
|
|
|
#include "vm/message.h"
|
2013-07-30 01:09:05 +00:00
|
|
|
#include "vm/object_store.h"
|
2012-03-12 23:51:03 +00:00
|
|
|
#include "vm/port.h"
|
2013-07-15 21:14:43 +00:00
|
|
|
#include "vm/symbols.h"
|
2013-07-24 00:29:17 +00:00
|
|
|
#include "lib/invocation_mirror.h"
|
2012-03-12 23:51:03 +00:00
|
|
|
|
|
|
|
namespace dart {
|
|
|
|
|
2013-07-19 23:17:47 +00:00
|
|
|
static RawInstance* CreateMirror(const String& mirror_class_name,
|
|
|
|
const Array& constructor_arguments) {
|
|
|
|
const Library& mirrors_lib = Library::Handle(Library::MirrorsLibrary());
|
|
|
|
const String& constructor_name = Symbols::Dot();
|
|
|
|
|
|
|
|
const Object& result = Object::Handle(
|
|
|
|
DartLibraryCalls::InstanceCreate(mirrors_lib,
|
|
|
|
mirror_class_name,
|
|
|
|
constructor_name,
|
|
|
|
constructor_arguments));
|
2013-07-30 22:57:59 +00:00
|
|
|
ASSERT(!result.IsError());
|
2013-07-19 23:17:47 +00:00
|
|
|
return Instance::Cast(result).raw();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-10-31 17:56:46 +00:00
|
|
|
inline Dart_Handle NewString(const char* str) {
|
|
|
|
return Dart_NewStringFromCString(str);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-05-30 17:07:19 +00:00
|
|
|
DEFINE_NATIVE_ENTRY(Mirrors_isLocalPort, 1) {
|
2012-12-10 17:59:40 +00:00
|
|
|
GET_NON_NULL_NATIVE_ARGUMENT(Instance, port, arguments->NativeArgAt(0));
|
2012-05-30 17:07:19 +00:00
|
|
|
|
|
|
|
// Get the port id from the SendPort instance.
|
|
|
|
const Object& id_obj = Object::Handle(DartLibraryCalls::PortGetId(port));
|
|
|
|
if (id_obj.IsError()) {
|
2012-07-02 21:42:53 +00:00
|
|
|
Exceptions::PropagateError(Error::Cast(id_obj));
|
2012-05-30 17:07:19 +00:00
|
|
|
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());
|
2012-08-30 17:41:19 +00:00
|
|
|
return Bool::Get(PortMap::IsLocalPort(port_id));
|
2012-03-12 23:51:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-05-30 17:07:19 +00:00
|
|
|
static Dart_Handle MirrorLib() {
|
2012-10-31 17:56:46 +00:00
|
|
|
Dart_Handle mirror_lib_name = NewString("dart:mirrors");
|
2012-05-30 17:07:19 +00:00
|
|
|
return Dart_LookupLibrary(mirror_lib_name);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-07-08 22:05:15 +00:00
|
|
|
// 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 =
|
2013-07-24 23:35:15 +00:00
|
|
|
MirrorReference::Handle(MirrorReference::New(referent));
|
2013-07-08 22:05:15 +00:00
|
|
|
return Api::NewHandle(isolate, reference.raw());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-07-24 23:35:15 +00:00
|
|
|
static RawInstance* CreateParameterMirrorList(const Function& func) {
|
|
|
|
HANDLESCOPE(Isolate::Current());
|
|
|
|
const intptr_t param_cnt = func.num_fixed_parameters() -
|
|
|
|
func.NumImplicitParameters() +
|
|
|
|
func.NumOptionalParameters();
|
|
|
|
const Array& results = Array::Handle(Array::New(param_cnt));
|
|
|
|
const Array& args = Array::Handle(Array::New(3));
|
|
|
|
args.SetAt(0, MirrorReference::Handle(MirrorReference::New(func)));
|
|
|
|
Smi& pos = Smi::Handle();
|
|
|
|
Instance& param = Instance::Handle();
|
|
|
|
for (intptr_t i = 0; i < param_cnt; i++) {
|
|
|
|
pos ^= Smi::New(i);
|
|
|
|
args.SetAt(1, pos);
|
|
|
|
args.SetAt(2, (i >= func.num_fixed_parameters()) ?
|
|
|
|
Bool::True() : Bool::False());
|
|
|
|
param ^= CreateMirror(Symbols::_LocalParameterMirrorImpl(), args);
|
|
|
|
results.SetAt(i, param);
|
|
|
|
}
|
|
|
|
results.MakeImmutable();
|
|
|
|
return results.raw();
|
|
|
|
}
|
2012-09-13 17:47:25 +00:00
|
|
|
|
|
|
|
|
2013-07-19 23:17:47 +00:00
|
|
|
static RawInstance* CreateTypeVariableMirror(const TypeParameter& param,
|
|
|
|
const Instance& owner_mirror) {
|
2013-07-30 22:57:59 +00:00
|
|
|
const Array& args = Array::Handle(Array::New(3));
|
|
|
|
args.SetAt(0, param);
|
|
|
|
args.SetAt(1, String::Handle(param.name()));
|
|
|
|
args.SetAt(2, owner_mirror);
|
|
|
|
return CreateMirror(Symbols::_LocalTypeVariableMirrorImpl(), args);
|
2013-07-19 23:17:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-07-30 22:57:59 +00:00
|
|
|
// We create a list in native code and let Dart code create the type mirror
|
|
|
|
// object and the ordered map.
|
|
|
|
static RawInstance* CreateTypeVariableList(const Class& cls) {
|
|
|
|
const TypeArguments& args = TypeArguments::Handle(cls.type_parameters());
|
|
|
|
if (args.IsNull()) {
|
|
|
|
return Object::empty_array().raw();
|
2012-09-13 17:47:25 +00:00
|
|
|
}
|
2013-07-30 22:57:59 +00:00
|
|
|
const Array& result = Array::Handle(Array::New(args.Length() * 2));
|
|
|
|
TypeParameter& type = TypeParameter::Handle();
|
|
|
|
String& name = String::Handle();
|
|
|
|
for (intptr_t i = 0; i < args.Length(); i++) {
|
|
|
|
type ^= args.TypeAt(i);
|
|
|
|
ASSERT(type.IsTypeParameter());
|
|
|
|
name ^= type.name();
|
|
|
|
result.SetAt(2 * i, name);
|
|
|
|
result.SetAt(2 * i + 1, type);
|
2012-09-13 17:47:25 +00:00
|
|
|
}
|
2013-07-30 22:57:59 +00:00
|
|
|
return result.raw();
|
2012-09-13 17:47:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-07-31 23:31:14 +00:00
|
|
|
static RawInstance* CreateTypedefMirror(const Class& cls,
|
|
|
|
const Instance& owner_mirror) {
|
|
|
|
const Array& args = Array::Handle(Array::New(3));
|
|
|
|
args.SetAt(0, MirrorReference::Handle(MirrorReference::New(cls)));
|
|
|
|
args.SetAt(1, String::Handle(cls.UserVisibleName()));
|
|
|
|
args.SetAt(2, owner_mirror);
|
|
|
|
return CreateMirror(Symbols::_LocalTypedefMirrorImpl(), args);
|
|
|
|
}
|
2012-09-13 17:47:25 +00:00
|
|
|
|
|
|
|
|
2013-07-31 23:31:14 +00:00
|
|
|
static Dart_Handle CreateTypedefMirrorUsingApi(Dart_Handle cls,
|
|
|
|
Dart_Handle cls_name,
|
|
|
|
Dart_Handle owner_mirror) {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
return Api::NewHandle(
|
|
|
|
isolate, CreateTypedefMirror(
|
|
|
|
Api::UnwrapClassHandle(isolate, cls),
|
|
|
|
Api::UnwrapInstanceHandle(isolate, owner_mirror)));
|
2012-09-13 17:47:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-07-18 22:04:57 +00:00
|
|
|
static Dart_Handle CreateClassMirrorUsingApi(Dart_Handle intf,
|
|
|
|
Dart_Handle intf_name,
|
|
|
|
Dart_Handle lib_mirror) {
|
2012-11-30 01:26:31 +00:00
|
|
|
ASSERT(Dart_IsClass(intf));
|
2012-09-13 17:47:25 +00:00
|
|
|
if (Dart_ClassIsTypedef(intf)) {
|
|
|
|
// This class is actually a typedef. Represent it specially in
|
|
|
|
// reflection.
|
2013-07-31 23:31:14 +00:00
|
|
|
return CreateTypedefMirrorUsingApi(intf, intf_name, lib_mirror);
|
2012-09-13 17:47:25 +00:00
|
|
|
}
|
|
|
|
|
2012-10-31 17:56:46 +00:00
|
|
|
Dart_Handle cls_name = NewString("_LocalClassMirrorImpl");
|
2013-06-26 21:30:18 +00:00
|
|
|
Dart_Handle type = Dart_GetType(MirrorLib(), cls_name, 0, NULL);
|
|
|
|
if (Dart_IsError(type)) {
|
|
|
|
return type;
|
2012-06-12 21:07:49 +00:00
|
|
|
}
|
|
|
|
|
2012-07-09 23:57:08 +00:00
|
|
|
Dart_Handle args[] = {
|
2013-07-08 22:05:15 +00:00
|
|
|
CreateMirrorReference(intf),
|
|
|
|
Dart_Null(), // "name"
|
2012-07-09 23:57:08 +00:00
|
|
|
};
|
2013-06-26 21:30:18 +00:00
|
|
|
Dart_Handle mirror = Dart_New(type, Dart_Null(), ARRAY_SIZE(args), args);
|
2012-06-12 21:07:49 +00:00
|
|
|
return mirror;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-07-25 21:10:09 +00:00
|
|
|
static RawInstance* CreateMethodMirror(const Function& func,
|
|
|
|
const Instance& owner_mirror) {
|
2013-07-30 22:22:17 +00:00
|
|
|
const Array& args = Array::Handle(Array::New(12));
|
2013-07-25 21:10:09 +00:00
|
|
|
args.SetAt(0, MirrorReference::Handle(MirrorReference::New(func)));
|
2013-07-30 22:22:17 +00:00
|
|
|
args.SetAt(1, String::Handle(func.UserVisibleName()));
|
|
|
|
args.SetAt(2, owner_mirror);
|
|
|
|
args.SetAt(3, func.is_static() ? Bool::True() : Bool::False());
|
|
|
|
args.SetAt(4, func.is_abstract() ? Bool::True() : Bool::False());
|
|
|
|
args.SetAt(5, func.IsGetterFunction() ? Bool::True() : Bool::False());
|
|
|
|
args.SetAt(6, func.IsSetterFunction() ? Bool::True() : Bool::False());
|
|
|
|
args.SetAt(7, func.IsConstructor() ? Bool::True() : Bool::False());
|
2013-07-25 21:10:09 +00:00
|
|
|
// TODO(mlippautz): Implement different constructor kinds.
|
|
|
|
args.SetAt(8, Bool::False());
|
|
|
|
args.SetAt(9, Bool::False());
|
|
|
|
args.SetAt(10, Bool::False());
|
2013-07-30 22:22:17 +00:00
|
|
|
args.SetAt(11, Bool::False());
|
2013-07-25 21:10:09 +00:00
|
|
|
return CreateMirror(Symbols::_LocalMethodMirrorImpl(), args);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-07-22 23:05:54 +00:00
|
|
|
static RawInstance* CreateVariableMirror(const Field& field,
|
|
|
|
const Instance& owner_mirror) {
|
|
|
|
const MirrorReference& field_ref =
|
2013-07-24 23:35:15 +00:00
|
|
|
MirrorReference::Handle(MirrorReference::New(field));
|
2012-07-09 23:57:08 +00:00
|
|
|
|
2013-07-22 23:05:54 +00:00
|
|
|
const String& name = String::Handle(field.UserVisibleName());
|
2012-07-09 23:57:08 +00:00
|
|
|
|
2013-07-22 23:05:54 +00:00
|
|
|
const Array& args = Array::Handle(Array::New(6));
|
|
|
|
args.SetAt(0, field_ref);
|
|
|
|
args.SetAt(1, name);
|
|
|
|
args.SetAt(2, owner_mirror);
|
|
|
|
args.SetAt(3, Instance::Handle()); // Null for type.
|
|
|
|
args.SetAt(4, field.is_static() ? Bool::True() : Bool::False());
|
|
|
|
args.SetAt(5, field.is_final() ? Bool::True() : Bool::False());
|
2012-09-13 17:47:25 +00:00
|
|
|
|
2013-07-22 23:05:54 +00:00
|
|
|
return CreateMirror(Symbols::_LocalVariableMirrorImpl(), args);
|
2012-07-09 23:57:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-07-18 22:04:57 +00:00
|
|
|
static RawInstance* CreateClassMirror(const Class& cls,
|
|
|
|
const Instance& owner_mirror) {
|
2013-07-19 00:44:36 +00:00
|
|
|
Instance& retvalue = Instance::Handle();
|
2013-07-18 22:04:57 +00:00
|
|
|
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);
|
|
|
|
}
|
2013-07-19 00:44:36 +00:00
|
|
|
Dart_Handle lib_mirror = Api::NewHandle(isolate, owner_mirror.raw());
|
2013-07-18 22:04:57 +00:00
|
|
|
// 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);
|
|
|
|
}
|
2013-07-19 00:44:36 +00:00
|
|
|
retvalue ^= Api::UnwrapHandle(result);
|
2013-07-18 22:04:57 +00:00
|
|
|
Dart_ExitScope();
|
|
|
|
return retvalue.raw();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static RawInstance* CreateLibraryMirror(const Library& lib) {
|
2013-07-30 20:52:44 +00:00
|
|
|
const Array& args = Array::Handle(Array::New(3));
|
|
|
|
args.SetAt(0, MirrorReference::Handle(MirrorReference::New(lib)));
|
|
|
|
String& str = String::Handle();
|
|
|
|
str = lib.name();
|
|
|
|
args.SetAt(1, str);
|
|
|
|
str = lib.url();
|
|
|
|
args.SetAt(2, str);
|
|
|
|
return CreateMirror(Symbols::_LocalLibraryMirrorImpl(), args);
|
2013-07-18 22:04:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-07-19 23:17:47 +00:00
|
|
|
static RawInstance* CreateTypeMirror(const AbstractType& type) {
|
|
|
|
ASSERT(!type.IsMalformed());
|
|
|
|
if (type.HasResolvedTypeClass()) {
|
|
|
|
const Class& cls = Class::Handle(type.type_class());
|
|
|
|
// Handle void and dynamic types.
|
|
|
|
if (cls.IsVoidClass()) {
|
|
|
|
Array& args = Array::Handle(Array::New(1));
|
|
|
|
args.SetAt(0, Symbols::Void());
|
|
|
|
// TODO(mlippautz): Create once in the VM isolate and retrieve from there.
|
|
|
|
return CreateMirror(Symbols::_SpecialTypeMirrorImpl(), args);
|
|
|
|
} else if (cls.IsDynamicClass()) {
|
|
|
|
Array& args = Array::Handle(Array::New(1));
|
|
|
|
args.SetAt(0, Symbols::Dynamic());
|
|
|
|
// TODO(mlippautz): Create once in the VM isolate and retrieve from there.
|
|
|
|
return CreateMirror(Symbols::_SpecialTypeMirrorImpl(), args);
|
|
|
|
}
|
|
|
|
return CreateClassMirror(cls, Object::null_instance());
|
|
|
|
} else if (type.IsTypeParameter()) {
|
|
|
|
return CreateTypeVariableMirror(TypeParameter::Cast(type),
|
|
|
|
Object::null_instance());
|
|
|
|
}
|
|
|
|
UNREACHABLE();
|
|
|
|
return Instance::null();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-07-30 01:09:05 +00:00
|
|
|
static RawInstance* CreateIsolateMirror() {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
const String& debug_name = String::Handle(String::New(isolate->name()));
|
|
|
|
const Library& root_library =
|
|
|
|
Library::Handle(isolate, isolate->object_store()->root_library());
|
|
|
|
const Instance& root_library_mirror =
|
|
|
|
Instance::Handle(CreateLibraryMirror(root_library));
|
|
|
|
|
|
|
|
const Array& args = Array::Handle(Array::New(2));
|
|
|
|
args.SetAt(0, debug_name);
|
|
|
|
args.SetAt(1, root_library_mirror);
|
|
|
|
return CreateMirror(Symbols::_LocalIsolateMirrorImpl(), args);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static RawInstance* CreateMirrorSystem() {
|
|
|
|
Isolate* isolate = Isolate::Current();
|
|
|
|
const GrowableObjectArray& libraries =
|
|
|
|
GrowableObjectArray::Handle(isolate->object_store()->libraries());
|
|
|
|
|
|
|
|
const int num_libraries = libraries.Length();
|
|
|
|
const Array& library_mirrors = Array::Handle(Array::New(num_libraries));
|
|
|
|
Library& library = Library::Handle();
|
|
|
|
Instance& library_mirror = Instance::Handle();
|
|
|
|
|
|
|
|
for (int i = 0; i < num_libraries; i++) {
|
|
|
|
library ^= libraries.At(i);
|
|
|
|
library_mirror = CreateLibraryMirror(library);
|
|
|
|
library_mirrors.SetAt(i, library_mirror);
|
2012-06-12 21:07:49 +00:00
|
|
|
}
|
2013-07-30 01:09:05 +00:00
|
|
|
|
|
|
|
const Instance& isolate_mirror = Instance::Handle(CreateIsolateMirror());
|
|
|
|
|
|
|
|
const Array& args = Array::Handle(Array::New(2));
|
|
|
|
args.SetAt(0, library_mirrors);
|
|
|
|
args.SetAt(1, isolate_mirror);
|
|
|
|
return CreateMirror(Symbols::_LocalMirrorSystemImpl(), args);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DEFINE_NATIVE_ENTRY(Mirrors_makeLocalMirrorSystem, 0) {
|
|
|
|
return CreateMirrorSystem();
|
2012-06-12 21:07:49 +00:00
|
|
|
}
|
|
|
|
|
2012-07-23 22:53:52 +00:00
|
|
|
|
2013-04-17 10:11:21 +00:00
|
|
|
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);
|
|
|
|
}
|
2013-07-19 00:44:36 +00:00
|
|
|
Dart_Handle lib_mirror = Dart_Null();
|
2013-07-18 22:04:57 +00:00
|
|
|
Dart_Handle result = CreateClassMirrorUsingApi(cls_handle,
|
|
|
|
name_handle,
|
|
|
|
lib_mirror);
|
2013-04-17 10:11:21 +00:00
|
|
|
if (Dart_IsError(result)) {
|
|
|
|
Dart_PropagateError(result);
|
|
|
|
}
|
|
|
|
Dart_SetReturnValue(args, result);
|
|
|
|
Dart_ExitScope();
|
|
|
|
}
|
|
|
|
|
2013-06-14 21:12:58 +00:00
|
|
|
|
2013-07-25 20:49:59 +00:00
|
|
|
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.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();
|
|
|
|
}
|
|
|
|
Exceptions::PropagateError(error);
|
|
|
|
UNREACHABLE();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-07-17 21:50:54 +00:00
|
|
|
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();
|
2013-06-14 21:12:58 +00:00
|
|
|
}
|
2013-07-17 21:50:54 +00:00
|
|
|
|
|
|
|
const Library& library = Library::Handle(klass.library());
|
2013-07-25 20:49:59 +00:00
|
|
|
const Object& metadata = Object::Handle(library.GetMetadata(decl));
|
|
|
|
if (metadata.IsError()) {
|
|
|
|
ThrowInvokeError(Error::Cast(metadata));
|
|
|
|
}
|
|
|
|
return metadata.raw();
|
2013-06-14 21:12:58 +00:00
|
|
|
}
|
|
|
|
|
2012-05-30 17:07:19 +00:00
|
|
|
|
2013-07-31 23:31:14 +00:00
|
|
|
DEFINE_NATIVE_ENTRY(FunctionTypeMirror_parameters, 1) {
|
|
|
|
GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(0));
|
|
|
|
const Class& cls = Class::Handle(ref.GetClassReferent());
|
|
|
|
const Function& func = Function::Handle(cls.signature_function());
|
|
|
|
return CreateParameterMirrorList(func);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DEFINE_NATIVE_ENTRY(FunctionTypeMirror_return_type, 1) {
|
|
|
|
GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(0));
|
|
|
|
const Class& cls = Class::Handle(ref.GetClassReferent());
|
|
|
|
const Function& func = Function::Handle(cls.signature_function());
|
|
|
|
const AbstractType& return_type = AbstractType::Handle(func.result_type());
|
|
|
|
return CreateTypeMirror(return_type);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-07-15 21:14:43 +00:00
|
|
|
void HandleMirrorsMessage(Isolate* isolate,
|
|
|
|
Dart_Port reply_port,
|
|
|
|
const Instance& message) {
|
|
|
|
UNIMPLEMENTED();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static bool FieldIsUninitialized(const Field& field) {
|
|
|
|
ASSERT(!field.IsNull());
|
2012-07-23 22:53:52 +00:00
|
|
|
|
2013-07-15 21:14:43 +00:00
|
|
|
// 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) {
|
2013-07-22 22:49:08 +00:00
|
|
|
GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(0));
|
|
|
|
const Class& klass = Class::Handle(ref.GetClassReferent());
|
2013-07-24 23:51:15 +00:00
|
|
|
return klass.UserVisibleName();
|
2013-07-15 21:14:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-07-19 00:44:36 +00:00
|
|
|
DEFINE_NATIVE_ENTRY(ClassMirror_library, 1) {
|
2013-07-22 22:49:08 +00:00
|
|
|
GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(0));
|
|
|
|
const Class& klass = Class::Handle(ref.GetClassReferent());
|
2013-07-19 00:44:36 +00:00
|
|
|
return CreateLibraryMirror(Library::Handle(klass.library()));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-07-25 22:45:07 +00:00
|
|
|
DEFINE_NATIVE_ENTRY(ClassMirror_supertype, 1) {
|
|
|
|
GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(0));
|
|
|
|
const Class& klass = Class::Handle(ref.GetClassReferent());
|
|
|
|
return klass.super_type();
|
|
|
|
}
|
|
|
|
|
2013-07-30 00:29:52 +00:00
|
|
|
|
|
|
|
DEFINE_NATIVE_ENTRY(ClassMirror_interfaces, 1) {
|
|
|
|
GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(0));
|
|
|
|
const Class& klass = Class::Handle(ref.GetClassReferent());
|
|
|
|
|
|
|
|
const Error& error = Error::Handle(klass.EnsureIsFinalized(isolate));
|
|
|
|
if (!error.IsNull()) {
|
|
|
|
ThrowInvokeError(error);
|
|
|
|
}
|
|
|
|
|
|
|
|
return klass.interfaces();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-07-23 23:54:16 +00:00
|
|
|
DEFINE_NATIVE_ENTRY(ClassMirror_members, 2) {
|
|
|
|
GET_NON_NULL_NATIVE_ARGUMENT(Instance,
|
|
|
|
owner_mirror,
|
|
|
|
arguments->NativeArgAt(0));
|
|
|
|
GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(1));
|
|
|
|
const Class& klass = Class::Handle(ref.GetClassReferent());
|
|
|
|
|
2013-07-26 18:29:38 +00:00
|
|
|
const Error& error = Error::Handle(klass.EnsureIsFinalized(isolate));
|
|
|
|
if (!error.IsNull()) {
|
|
|
|
ThrowInvokeError(error);
|
|
|
|
}
|
|
|
|
|
2013-07-23 23:54:16 +00:00
|
|
|
const Array& fields = Array::Handle(klass.fields());
|
|
|
|
// Some special types like 'dynamic' have a null fields list, but they should
|
|
|
|
// not wind up as the reflectees of ClassMirrors.
|
|
|
|
ASSERT(!fields.IsNull());
|
|
|
|
const intptr_t num_fields = fields.Length();
|
|
|
|
|
|
|
|
const Array& functions = Array::Handle(klass.functions());
|
|
|
|
// Some special types like 'dynamic' have a null functions list, but they
|
|
|
|
// should not wind up as the reflectees of ClassMirrors.
|
|
|
|
ASSERT(!functions.IsNull());
|
|
|
|
const intptr_t num_functions = functions.Length();
|
|
|
|
|
|
|
|
Instance& member_mirror = Instance::Handle();
|
|
|
|
const GrowableObjectArray& member_mirrors = GrowableObjectArray::Handle(
|
|
|
|
GrowableObjectArray::New(num_fields + num_functions));
|
|
|
|
|
|
|
|
Field& field = Field::Handle();
|
|
|
|
for (intptr_t i = 0; i < num_fields; i++) {
|
|
|
|
field ^= fields.At(i);
|
|
|
|
member_mirror = CreateVariableMirror(field, owner_mirror);
|
|
|
|
member_mirrors.Add(member_mirror);
|
|
|
|
}
|
|
|
|
|
|
|
|
Function& func = Function::Handle();
|
|
|
|
for (intptr_t i = 0; i < num_functions; i++) {
|
|
|
|
func ^= functions.At(i);
|
|
|
|
if (func.kind() == RawFunction::kRegularFunction ||
|
|
|
|
func.kind() == RawFunction::kGetterFunction ||
|
|
|
|
func.kind() == RawFunction::kSetterFunction) {
|
|
|
|
member_mirror = CreateMethodMirror(func, owner_mirror);
|
|
|
|
member_mirrors.Add(member_mirror);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return member_mirrors.raw();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-07-26 18:29:38 +00:00
|
|
|
DEFINE_NATIVE_ENTRY(ClassMirror_constructors, 2) {
|
|
|
|
GET_NON_NULL_NATIVE_ARGUMENT(Instance,
|
|
|
|
owner_mirror,
|
|
|
|
arguments->NativeArgAt(0));
|
|
|
|
GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(1));
|
|
|
|
const Class& klass = Class::Handle(ref.GetClassReferent());
|
|
|
|
|
|
|
|
const Error& error = Error::Handle(klass.EnsureIsFinalized(isolate));
|
|
|
|
if (!error.IsNull()) {
|
|
|
|
ThrowInvokeError(error);
|
|
|
|
}
|
|
|
|
|
|
|
|
const Array& functions = Array::Handle(klass.functions());
|
|
|
|
// Some special types like 'dynamic' have a null functions list, but they
|
|
|
|
// should not wind up as the reflectees of ClassMirrors.
|
|
|
|
ASSERT(!functions.IsNull());
|
|
|
|
const intptr_t num_functions = functions.Length();
|
|
|
|
|
|
|
|
Instance& constructor_mirror = Instance::Handle();
|
|
|
|
const GrowableObjectArray& constructor_mirrors = GrowableObjectArray::Handle(
|
|
|
|
GrowableObjectArray::New(num_functions));
|
|
|
|
|
|
|
|
Function& func = Function::Handle();
|
|
|
|
for (intptr_t i = 0; i < num_functions; i++) {
|
|
|
|
func ^= functions.At(i);
|
|
|
|
if (func.kind() == RawFunction::kConstructor) {
|
|
|
|
constructor_mirror = CreateMethodMirror(func, owner_mirror);
|
|
|
|
constructor_mirrors.Add(constructor_mirror);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return constructor_mirrors.raw();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-07-24 23:51:15 +00:00
|
|
|
DEFINE_NATIVE_ENTRY(LibraryMirror_members, 2) {
|
|
|
|
GET_NON_NULL_NATIVE_ARGUMENT(Instance,
|
|
|
|
owner_mirror,
|
|
|
|
arguments->NativeArgAt(0));
|
|
|
|
GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(1));
|
|
|
|
const Library& library = Library::Handle(ref.GetLibraryReferent());
|
|
|
|
|
|
|
|
Instance& member_mirror = Instance::Handle();
|
|
|
|
const GrowableObjectArray& member_mirrors =
|
|
|
|
GrowableObjectArray::Handle(GrowableObjectArray::New());
|
|
|
|
|
|
|
|
Object& entry = Object::Handle();
|
|
|
|
DictionaryIterator entries(library);
|
|
|
|
|
|
|
|
while (entries.HasNext()) {
|
|
|
|
entry = entries.GetNext();
|
|
|
|
if (entry.IsClass()) {
|
|
|
|
const Class& klass = Class::Cast(entry);
|
|
|
|
if (!klass.IsCanonicalSignatureClass()) {
|
|
|
|
// The various implementations of public classes don't always have the
|
|
|
|
// expected superinterfaces or other properties, so we filter them out.
|
|
|
|
if (!RawObject::IsImplementationClassId(klass.id())) {
|
|
|
|
member_mirror = CreateClassMirror(klass, owner_mirror);
|
|
|
|
member_mirrors.Add(member_mirror);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (entry.IsField()) {
|
|
|
|
const Field& field = Field::Cast(entry);
|
|
|
|
member_mirror = CreateVariableMirror(field, owner_mirror);
|
|
|
|
member_mirrors.Add(member_mirror);
|
|
|
|
} else if (entry.IsFunction()) {
|
|
|
|
const Function& func = Function::Cast(entry);
|
|
|
|
if (func.kind() == RawFunction::kRegularFunction ||
|
|
|
|
func.kind() == RawFunction::kGetterFunction ||
|
|
|
|
func.kind() == RawFunction::kSetterFunction) {
|
|
|
|
member_mirror = CreateMethodMirror(func, owner_mirror);
|
|
|
|
member_mirrors.Add(member_mirror);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return member_mirrors.raw();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-07-30 22:57:59 +00:00
|
|
|
DEFINE_NATIVE_ENTRY(ClassMirror_type_variables, 1) {
|
|
|
|
GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(0));
|
|
|
|
const Class& klass = Class::Handle(ref.GetClassReferent());
|
|
|
|
return CreateTypeVariableList(klass);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DEFINE_NATIVE_ENTRY(LocalTypeVariableMirror_owner, 1) {
|
|
|
|
GET_NON_NULL_NATIVE_ARGUMENT(TypeParameter, param, arguments->NativeArgAt(0));
|
|
|
|
return CreateClassMirror(Class::Handle(param.parameterized_class()),
|
|
|
|
Instance::null_instance());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DEFINE_NATIVE_ENTRY(LocalTypeVariableMirror_upper_bound, 1) {
|
|
|
|
GET_NON_NULL_NATIVE_ARGUMENT(TypeParameter, param, arguments->NativeArgAt(0));
|
|
|
|
return CreateTypeMirror(AbstractType::Handle(param.bound()));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-07-15 21:14:43 +00:00
|
|
|
// 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);
|
2013-04-16 23:19:30 +00:00
|
|
|
} else {
|
2013-07-15 21:14:43 +00:00
|
|
|
result = DartEntry::InvokeFunction(function, arguments);
|
2013-04-16 23:19:30 +00:00
|
|
|
}
|
2013-07-15 21:14:43 +00:00
|
|
|
|
|
|
|
if (result.IsError()) {
|
|
|
|
ThrowInvokeError(Error::Cast(result));
|
|
|
|
UNREACHABLE();
|
2012-07-23 22:53:52 +00:00
|
|
|
}
|
2013-07-15 21:14:43 +00:00
|
|
|
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.
|
2013-07-22 22:49:08 +00:00
|
|
|
GET_NATIVE_ARGUMENT(Instance, reflectee, arguments->NativeArgAt(1));
|
|
|
|
GET_NON_NULL_NATIVE_ARGUMENT(
|
|
|
|
String, function_name, arguments->NativeArgAt(2));
|
|
|
|
GET_NON_NULL_NATIVE_ARGUMENT(
|
|
|
|
Array, positional_args, arguments->NativeArgAt(3));
|
2013-07-15 21:14:43 +00:00
|
|
|
|
|
|
|
intptr_t number_of_arguments = positional_args.Length();
|
|
|
|
|
|
|
|
const Array& args =
|
2013-07-16 09:38:13 +00:00
|
|
|
Array::Handle(Array::New(number_of_arguments + 1)); // Plus receiver.
|
2013-07-15 21:14:43 +00:00
|
|
|
Object& arg = Object::Handle();
|
|
|
|
args.SetAt(0, reflectee);
|
|
|
|
for (int i = 0; i < number_of_arguments; i++) {
|
|
|
|
arg = positional_args.At(i);
|
2013-07-16 09:38:13 +00:00
|
|
|
args.SetAt(i + 1, arg); // Plus receiver.
|
2012-07-23 22:53:52 +00:00
|
|
|
}
|
|
|
|
|
2013-07-16 09:38:13 +00:00
|
|
|
ArgumentsDescriptor args_desc(
|
|
|
|
Array::Handle(ArgumentsDescriptor::New(args.Length())));
|
2013-07-31 23:45:12 +00:00
|
|
|
|
|
|
|
Class& klass = Class::Handle(reflectee.clazz());
|
|
|
|
Function& function = Function::Handle();
|
|
|
|
while (!klass.IsNull()) {
|
|
|
|
function = klass.LookupDynamicFunctionAllowPrivate(function_name);
|
|
|
|
if (!function.IsNull()) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
klass = klass.SuperClass();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!function.IsNull() &&
|
|
|
|
!function.AreValidArguments(args_desc, NULL)) {
|
|
|
|
function = Function::null();
|
|
|
|
}
|
2013-07-15 21:14:43 +00:00
|
|
|
|
|
|
|
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.
|
2013-07-22 22:49:08 +00:00
|
|
|
GET_NATIVE_ARGUMENT(Instance, reflectee, arguments->NativeArgAt(1));
|
|
|
|
GET_NON_NULL_NATIVE_ARGUMENT(String, getter_name, arguments->NativeArgAt(2));
|
2013-07-15 21:14:43 +00:00
|
|
|
|
|
|
|
// 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();
|
2012-07-23 22:53:52 +00:00
|
|
|
}
|
2013-07-15 21:14:43 +00:00
|
|
|
|
|
|
|
const int kNumArgs = 1;
|
|
|
|
const Array& args = Array::Handle(Array::New(kNumArgs));
|
|
|
|
args.SetAt(0, reflectee);
|
|
|
|
|
|
|
|
return ReflectivelyInvokeDynamicFunction(reflectee,
|
|
|
|
getter,
|
|
|
|
internal_getter_name,
|
|
|
|
args);
|
2012-07-23 22:53:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-07-15 21:14:43 +00:00
|
|
|
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.
|
2013-07-22 22:49:08 +00:00
|
|
|
GET_NATIVE_ARGUMENT(Instance, reflectee, arguments->NativeArgAt(1));
|
|
|
|
GET_NON_NULL_NATIVE_ARGUMENT(String, setter_name, arguments->NativeArgAt(2));
|
|
|
|
GET_NATIVE_ARGUMENT(Instance, value, arguments->NativeArgAt(3));
|
2013-07-15 21:14:43 +00:00
|
|
|
|
|
|
|
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();
|
2012-07-24 17:59:12 +00:00
|
|
|
}
|
2013-07-15 21:14:43 +00:00
|
|
|
|
|
|
|
// 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) {
|
2013-07-22 22:49:08 +00:00
|
|
|
GET_NON_NULL_NATIVE_ARGUMENT(Instance, closure, arguments->NativeArgAt(0));
|
2013-07-15 21:14:43 +00:00
|
|
|
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);
|
2012-07-24 17:59:12 +00:00
|
|
|
}
|
|
|
|
|
2013-07-15 21:14:43 +00:00
|
|
|
obj = DartEntry::InvokeClosure(args);
|
|
|
|
if (obj.IsError()) {
|
|
|
|
ThrowInvokeError(Error::Cast(obj));
|
|
|
|
UNREACHABLE();
|
2012-07-24 17:59:12 +00:00
|
|
|
}
|
2013-07-15 21:14:43 +00:00
|
|
|
return obj.raw();
|
2012-07-24 17:59:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-07-29 23:57:31 +00:00
|
|
|
DEFINE_NATIVE_ENTRY(ClosureMirror_function, 1) {
|
|
|
|
GET_NON_NULL_NATIVE_ARGUMENT(Instance, closure, arguments->NativeArgAt(0));
|
|
|
|
ASSERT(closure.IsClosure());
|
|
|
|
|
|
|
|
const Function& func = Function::Handle(Closure::function(closure));
|
|
|
|
return CreateMethodMirror(func, Instance::null_instance());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-07-24 00:29:17 +00:00
|
|
|
static void ThrowNoSuchMethod(const Instance& receiver,
|
|
|
|
const String& function_name,
|
|
|
|
const Function& function,
|
|
|
|
const InvocationMirror::Call call,
|
|
|
|
const InvocationMirror::Type type) {
|
|
|
|
const Smi& invocation_type = Smi::Handle(Smi::New(
|
|
|
|
InvocationMirror::EncodeType(call, type)));
|
|
|
|
|
|
|
|
const Array& args = Array::Handle(Array::New(6));
|
|
|
|
args.SetAt(0, receiver);
|
|
|
|
args.SetAt(1, function_name);
|
|
|
|
args.SetAt(2, invocation_type);
|
|
|
|
if (!function.IsNull()) {
|
|
|
|
const int total_num_parameters = function.NumParameters();
|
|
|
|
const Array& array = Array::Handle(Array::New(total_num_parameters));
|
|
|
|
String& param_name = String::Handle();
|
|
|
|
for (int i = 0; i < total_num_parameters; i++) {
|
|
|
|
param_name = function.ParameterNameAt(i);
|
|
|
|
array.SetAt(i, param_name);
|
|
|
|
}
|
|
|
|
args.SetAt(5, array);
|
|
|
|
}
|
|
|
|
|
|
|
|
Exceptions::ThrowByType(Exceptions::kNoSuchMethod, args);
|
|
|
|
UNREACHABLE();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void ThrowNoSuchMethod(const Class& klass,
|
|
|
|
const String& function_name,
|
|
|
|
const Function& function,
|
|
|
|
const InvocationMirror::Call call,
|
|
|
|
const InvocationMirror::Type type) {
|
|
|
|
AbstractTypeArguments& type_arguments = AbstractTypeArguments::Handle();
|
|
|
|
Type& pre_type = Type::Handle(
|
|
|
|
Type::New(klass, type_arguments, Scanner::kDummyTokenIndex));
|
|
|
|
pre_type.SetIsFinalized();
|
|
|
|
AbstractType& runtime_type = AbstractType::Handle(pre_type.Canonicalize());
|
|
|
|
|
|
|
|
ThrowNoSuchMethod(runtime_type,
|
|
|
|
function_name,
|
|
|
|
function,
|
|
|
|
call,
|
|
|
|
type);
|
|
|
|
UNREACHABLE();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void ThrowNoSuchMethod(const Library& library,
|
|
|
|
const String& function_name,
|
|
|
|
const Function& function,
|
|
|
|
const InvocationMirror::Call call,
|
|
|
|
const InvocationMirror::Type type) {
|
|
|
|
ThrowNoSuchMethod(Instance::null_instance(),
|
|
|
|
function_name,
|
|
|
|
function,
|
|
|
|
call,
|
|
|
|
type);
|
|
|
|
UNREACHABLE();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-07-15 21:14:43 +00:00
|
|
|
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.
|
2013-07-22 22:49:08 +00:00
|
|
|
GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(1));
|
|
|
|
const Class& klass = Class::Handle(ref.GetClassReferent());
|
|
|
|
GET_NON_NULL_NATIVE_ARGUMENT(
|
|
|
|
String, function_name, arguments->NativeArgAt(2));
|
|
|
|
GET_NON_NULL_NATIVE_ARGUMENT(
|
|
|
|
Array, positional_args, arguments->NativeArgAt(3));
|
2013-07-15 21:14:43 +00:00
|
|
|
|
|
|
|
intptr_t number_of_arguments = positional_args.Length();
|
|
|
|
|
|
|
|
const Function& function = Function::Handle(
|
2013-07-24 00:29:17 +00:00
|
|
|
klass.LookupStaticFunctionAllowPrivate(function_name));
|
|
|
|
|
|
|
|
if (function.IsNull() ||
|
|
|
|
!function.AreValidArgumentCounts(number_of_arguments,
|
|
|
|
/* named_args */ 0,
|
|
|
|
NULL)) {
|
|
|
|
ThrowNoSuchMethod(klass,
|
|
|
|
function_name,
|
|
|
|
function,
|
|
|
|
InvocationMirror::kStatic,
|
|
|
|
InvocationMirror::kMethod);
|
2013-07-15 21:14:43 +00:00
|
|
|
UNREACHABLE();
|
2012-07-30 17:48:47 +00:00
|
|
|
}
|
2013-07-24 00:29:17 +00:00
|
|
|
|
2013-07-15 21:14:43 +00:00
|
|
|
Object& result = Object::Handle(DartEntry::InvokeFunction(function,
|
|
|
|
positional_args));
|
|
|
|
if (result.IsError()) {
|
|
|
|
ThrowInvokeError(Error::Cast(result));
|
|
|
|
UNREACHABLE();
|
2012-07-30 17:48:47 +00:00
|
|
|
}
|
2013-07-15 21:14:43 +00:00
|
|
|
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.
|
2013-07-22 22:49:08 +00:00
|
|
|
GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(1));
|
|
|
|
const Class& klass = Class::Handle(ref.GetClassReferent());
|
|
|
|
GET_NON_NULL_NATIVE_ARGUMENT(String, getter_name, arguments->NativeArgAt(2));
|
2013-07-15 21:14:43 +00:00
|
|
|
|
|
|
|
// 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()) {
|
2013-07-24 00:29:17 +00:00
|
|
|
ThrowNoSuchMethod(klass,
|
|
|
|
getter_name,
|
|
|
|
getter,
|
|
|
|
InvocationMirror::kStatic,
|
|
|
|
InvocationMirror::kGetter);
|
2013-07-15 21:14:43 +00:00
|
|
|
UNREACHABLE();
|
|
|
|
}
|
2012-07-30 17:48:47 +00:00
|
|
|
|
2013-07-15 21:14:43 +00:00
|
|
|
// 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();
|
2012-07-30 17:48:47 +00:00
|
|
|
}
|
2013-07-15 21:14:43 +00:00
|
|
|
return field.value();
|
2012-07-30 17:48:47 +00:00
|
|
|
}
|
|
|
|
|
2013-07-08 22:05:15 +00:00
|
|
|
|
2013-07-15 21:14:43 +00:00
|
|
|
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.
|
2013-07-22 22:49:08 +00:00
|
|
|
GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(1));
|
|
|
|
const Class& klass = Class::Handle(ref.GetClassReferent());
|
|
|
|
GET_NON_NULL_NATIVE_ARGUMENT(String, setter_name, arguments->NativeArgAt(2));
|
|
|
|
GET_NATIVE_ARGUMENT(Instance, value, arguments->NativeArgAt(3));
|
2013-07-15 21:14:43 +00:00
|
|
|
|
|
|
|
// 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()) {
|
2013-07-24 00:29:17 +00:00
|
|
|
ThrowNoSuchMethod(klass,
|
|
|
|
setter_name,
|
|
|
|
setter,
|
|
|
|
InvocationMirror::kStatic,
|
|
|
|
InvocationMirror::kSetter);
|
2013-07-15 21:14:43 +00:00
|
|
|
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();
|
2012-03-12 23:51:03 +00:00
|
|
|
}
|
|
|
|
|
2013-07-08 22:05:15 +00:00
|
|
|
|
2013-07-15 21:14:43 +00:00
|
|
|
DEFINE_NATIVE_ENTRY(ClassMirror_invokeConstructor, 3) {
|
2013-07-22 22:49:08 +00:00
|
|
|
GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(0));
|
|
|
|
const Class& klass = Class::Handle(ref.GetClassReferent());
|
|
|
|
GET_NON_NULL_NATIVE_ARGUMENT(
|
|
|
|
String, constructor_name, arguments->NativeArgAt(1));
|
|
|
|
GET_NON_NULL_NATIVE_ARGUMENT(
|
|
|
|
Array, positional_args, arguments->NativeArgAt(2));
|
2013-07-15 21:14:43 +00:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2013-07-24 00:29:17 +00:00
|
|
|
Function& constructor = Function::Handle(
|
|
|
|
klass.LookupFunctionAllowPrivate(internal_constructor_name));
|
|
|
|
|
|
|
|
if (constructor.IsNull() ||
|
|
|
|
(!constructor.IsConstructor() && !constructor.IsFactory()) ||
|
|
|
|
!constructor.AreValidArgumentCounts(number_of_arguments +
|
|
|
|
constructor.NumImplicitParameters(),
|
|
|
|
/* named args */ 0,
|
|
|
|
NULL)) {
|
|
|
|
// Pretend we didn't find the constructor at all when the arity is wrong
|
|
|
|
// so as to produce the same NoSuchMethodError as the non-reflective case.
|
|
|
|
constructor = Function::null();
|
|
|
|
ThrowNoSuchMethod(klass,
|
|
|
|
internal_constructor_name,
|
|
|
|
constructor,
|
|
|
|
InvocationMirror::kConstructor,
|
|
|
|
InvocationMirror::kMethod);
|
|
|
|
UNREACHABLE();
|
|
|
|
}
|
2013-07-15 21:14:43 +00:00
|
|
|
|
|
|
|
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.
|
2013-07-22 22:49:08 +00:00
|
|
|
GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(1));
|
|
|
|
const Library& library = Library::Handle(ref.GetLibraryReferent());
|
|
|
|
GET_NON_NULL_NATIVE_ARGUMENT(
|
|
|
|
String, function_name, arguments->NativeArgAt(2));
|
|
|
|
GET_NON_NULL_NATIVE_ARGUMENT(
|
|
|
|
Array, positional_args, arguments->NativeArgAt(3));
|
2013-07-15 21:14:43 +00:00
|
|
|
|
|
|
|
intptr_t number_of_arguments = positional_args.Length();
|
|
|
|
|
2013-07-23 00:19:39 +00:00
|
|
|
String& ambiguity_error_msg = String::Handle(isolate);
|
2013-07-15 21:14:43 +00:00
|
|
|
const Function& function = Function::Handle(
|
2013-07-23 00:19:39 +00:00
|
|
|
library.LookupFunctionAllowPrivate(function_name, &ambiguity_error_msg));
|
2013-07-15 21:14:43 +00:00
|
|
|
|
2013-07-24 00:29:17 +00:00
|
|
|
if (function.IsNull() && !ambiguity_error_msg.IsNull()) {
|
|
|
|
ThrowMirroredCompilationError(ambiguity_error_msg);
|
2013-07-15 21:14:43 +00:00
|
|
|
UNREACHABLE();
|
|
|
|
}
|
|
|
|
|
2013-07-24 00:29:17 +00:00
|
|
|
if (function.IsNull() ||
|
|
|
|
!function.AreValidArgumentCounts(number_of_arguments,
|
|
|
|
0,
|
|
|
|
NULL) ) {
|
|
|
|
ThrowNoSuchMethod(library,
|
|
|
|
function_name,
|
|
|
|
function,
|
|
|
|
InvocationMirror::kTopLevel,
|
|
|
|
InvocationMirror::kMethod);
|
2013-07-15 21:14:43 +00:00
|
|
|
UNREACHABLE();
|
|
|
|
}
|
|
|
|
|
|
|
|
const Object& result = Object::Handle(
|
|
|
|
DartEntry::InvokeFunction(function, positional_args));
|
|
|
|
if (result.IsError()) {
|
|
|
|
ThrowInvokeError(Error::Cast(result));
|
|
|
|
UNREACHABLE();
|
|
|
|
}
|
|
|
|
return result.raw();
|
2013-07-08 22:05:15 +00:00
|
|
|
}
|
|
|
|
|
2013-07-15 21:14:43 +00:00
|
|
|
|
|
|
|
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.
|
2013-07-22 22:49:08 +00:00
|
|
|
GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(1));
|
|
|
|
const Library& library = Library::Handle(ref.GetLibraryReferent());
|
|
|
|
GET_NON_NULL_NATIVE_ARGUMENT(String, getter_name, arguments->NativeArgAt(2));
|
2013-07-15 21:14:43 +00:00
|
|
|
|
|
|
|
// 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.
|
2013-07-23 00:19:39 +00:00
|
|
|
String& ambiguity_error_msg = String::Handle(isolate);
|
|
|
|
const Field& field = Field::Handle(
|
|
|
|
library.LookupFieldAllowPrivate(getter_name, &ambiguity_error_msg));
|
2013-07-15 21:14:43 +00:00
|
|
|
Function& getter = Function::Handle();
|
2013-07-23 00:19:39 +00:00
|
|
|
if (field.IsNull() && ambiguity_error_msg.IsNull()) {
|
|
|
|
// No field found and no ambiguity error. Check for a getter in the lib.
|
2013-07-15 21:14:43 +00:00
|
|
|
const String& internal_getter_name =
|
|
|
|
String::Handle(Field::GetterName(getter_name));
|
2013-07-23 00:19:39 +00:00
|
|
|
getter = library.LookupFunctionAllowPrivate(internal_getter_name,
|
|
|
|
&ambiguity_error_msg);
|
|
|
|
} else if (!field.IsNull() && FieldIsUninitialized(field)) {
|
2013-07-15 21:14:43 +00:00
|
|
|
// 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();
|
2013-07-23 00:19:39 +00:00
|
|
|
}
|
|
|
|
if (!field.IsNull()) {
|
2013-07-15 21:14:43 +00:00
|
|
|
return field.value();
|
2013-07-23 00:19:39 +00:00
|
|
|
}
|
|
|
|
if (ambiguity_error_msg.IsNull()) {
|
2013-07-24 00:29:17 +00:00
|
|
|
ThrowNoSuchMethod(library,
|
|
|
|
getter_name,
|
|
|
|
getter,
|
|
|
|
InvocationMirror::kTopLevel,
|
|
|
|
InvocationMirror::kGetter);
|
2013-07-23 00:19:39 +00:00
|
|
|
} else {
|
|
|
|
ThrowMirroredCompilationError(ambiguity_error_msg);
|
2013-07-15 21:14:43 +00:00
|
|
|
}
|
2013-07-23 00:19:39 +00:00
|
|
|
UNREACHABLE();
|
|
|
|
return Instance::null();
|
2013-07-15 21:14:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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.
|
2013-07-22 22:49:08 +00:00
|
|
|
GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(1));
|
|
|
|
const Library& library = Library::Handle(ref.GetLibraryReferent());
|
|
|
|
GET_NON_NULL_NATIVE_ARGUMENT(String, setter_name, arguments->NativeArgAt(2));
|
|
|
|
GET_NATIVE_ARGUMENT(Instance, value, arguments->NativeArgAt(3));
|
2013-07-15 21:14:43 +00:00
|
|
|
|
|
|
|
// 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.
|
2013-07-23 00:19:39 +00:00
|
|
|
String& ambiguity_error_msg = String::Handle(isolate);
|
|
|
|
const Field& field = Field::Handle(
|
|
|
|
library.LookupFieldAllowPrivate(setter_name, &ambiguity_error_msg));
|
2013-07-15 21:14:43 +00:00
|
|
|
|
2013-07-23 00:19:39 +00:00
|
|
|
if (field.IsNull() && ambiguity_error_msg.IsNull()) {
|
2013-07-15 21:14:43 +00:00
|
|
|
const String& internal_setter_name =
|
|
|
|
String::Handle(Field::SetterName(setter_name));
|
|
|
|
const Function& setter = Function::Handle(
|
2013-07-23 00:19:39 +00:00
|
|
|
library.LookupFunctionAllowPrivate(internal_setter_name,
|
|
|
|
&ambiguity_error_msg));
|
2013-07-15 21:14:43 +00:00
|
|
|
if (setter.IsNull()) {
|
2013-07-23 00:19:39 +00:00
|
|
|
if (ambiguity_error_msg.IsNull()) {
|
2013-07-24 00:29:17 +00:00
|
|
|
ThrowNoSuchMethod(library,
|
|
|
|
setter_name,
|
|
|
|
setter,
|
|
|
|
InvocationMirror::kTopLevel,
|
|
|
|
InvocationMirror::kSetter);
|
2013-07-23 00:19:39 +00:00
|
|
|
} else {
|
|
|
|
ThrowMirroredCompilationError(ambiguity_error_msg);
|
|
|
|
}
|
2013-07-15 21:14:43 +00:00
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-07-18 22:04:57 +00:00
|
|
|
DEFINE_NATIVE_ENTRY(MethodMirror_owner, 1) {
|
2013-07-22 22:49:08 +00:00
|
|
|
GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(0));
|
|
|
|
const Function& func = Function::Handle(ref.GetFunctionReferent());
|
2013-07-18 22:04:57 +00:00
|
|
|
if (func.IsNonImplicitClosureFunction()) {
|
|
|
|
return CreateMethodMirror(Function::Handle(
|
2013-07-22 22:49:08 +00:00
|
|
|
func.parent_function()), Object::null_instance());
|
2013-07-18 22:04:57 +00:00
|
|
|
}
|
|
|
|
const Class& owner = Class::Handle(func.Owner());
|
|
|
|
if (owner.IsTopLevel()) {
|
|
|
|
return CreateLibraryMirror(Library::Handle(owner.library()));
|
|
|
|
}
|
2013-07-22 22:49:08 +00:00
|
|
|
return CreateClassMirror(owner, Object::null_instance());
|
2013-07-18 22:04:57 +00:00
|
|
|
}
|
|
|
|
|
2013-07-19 23:17:47 +00:00
|
|
|
|
2013-07-25 21:10:09 +00:00
|
|
|
DEFINE_NATIVE_ENTRY(MethodMirror_parameters, 1) {
|
|
|
|
GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(0));
|
|
|
|
const Function& func = Function::Handle(ref.GetFunctionReferent());
|
|
|
|
return CreateParameterMirrorList(func);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-07-19 23:17:47 +00:00
|
|
|
DEFINE_NATIVE_ENTRY(MethodMirror_return_type, 1) {
|
|
|
|
GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(0));
|
|
|
|
const Function& func = Function::Handle(ref.GetFunctionReferent());
|
|
|
|
// We handle constructors in Dart code.
|
|
|
|
ASSERT(!func.IsConstructor());
|
|
|
|
const AbstractType& return_type = AbstractType::Handle(func.result_type());
|
|
|
|
return CreateTypeMirror(return_type);
|
|
|
|
}
|
|
|
|
|
2013-07-22 23:05:54 +00:00
|
|
|
|
2013-07-31 23:31:14 +00:00
|
|
|
DEFINE_NATIVE_ENTRY(TypedefMirror_referent, 1) {
|
|
|
|
GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(0));
|
|
|
|
const Class& cls = Class::Handle(ref.GetClassReferent());
|
|
|
|
const Function& sig_func = Function::Handle(cls.signature_function());
|
|
|
|
const Class& sig_cls = Class::Handle(sig_func.signature_class());
|
|
|
|
return MirrorReference::New(sig_cls);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-07-23 00:39:28 +00:00
|
|
|
DEFINE_NATIVE_ENTRY(ParameterMirror_type, 2) {
|
|
|
|
GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(0));
|
|
|
|
GET_NON_NULL_NATIVE_ARGUMENT(Smi, pos, arguments->NativeArgAt(1));
|
|
|
|
const Function& func = Function::Handle(ref.GetFunctionReferent());
|
|
|
|
const AbstractType& param_type = AbstractType::Handle(func.ParameterTypeAt(
|
|
|
|
func.NumImplicitParameters() + pos.Value()));
|
|
|
|
return CreateTypeMirror(param_type);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-07-22 23:05:54 +00:00
|
|
|
DEFINE_NATIVE_ENTRY(VariableMirror_type, 1) {
|
|
|
|
GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(0));
|
|
|
|
const Field& field = Field::Handle(ref.GetFieldReferent());
|
|
|
|
|
|
|
|
const AbstractType& type = AbstractType::Handle(field.type());
|
|
|
|
return CreateTypeMirror(type);
|
|
|
|
}
|
|
|
|
|
2012-03-12 23:51:03 +00:00
|
|
|
} // namespace dart
|