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