blob: a6ea151b8d943a6ad15a5a7d950c57b53f1eb951 [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 "vm/dart_api_impl.h"
#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"
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 cls = Dart_GetClass(CoreLib(), NewString("Map"));
if (Dart_IsError(cls)) {
return cls;
}
return Dart_New(cls, 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 IsMirror(Dart_Handle object, bool* is_mirror) {
Dart_Handle cls_name = NewString("Mirror");
Dart_Handle cls = Dart_GetClass(MirrorLib(), cls_name);
if (Dart_IsError(cls)) {
return cls;
}
Dart_Handle result = Dart_ObjectIsType(object, cls, is_mirror);
if (Dart_IsError(result)) {
return result;
}
return Dart_True(); // Indicates success. Result is in is_mirror.
}
static Dart_Handle IsMethodMirror(Dart_Handle object, bool* is_mirror) {
Dart_Handle cls_name = NewString("MethodMirror");
Dart_Handle cls = Dart_GetClass(MirrorLib(), cls_name);
if (Dart_IsError(cls)) {
return cls;
}
Dart_Handle result = Dart_ObjectIsType(object, cls, 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 cls = Dart_GetClass(MirrorLib(), cls_name);
if (Dart_IsError(cls)) {
return cls;
}
Dart_Handle result = Dart_ObjectIsType(object, cls, is_mirror);
if (Dart_IsError(result)) {
return result;
}
return Dart_True(); // Indicates success. Result is in is_mirror.
}
static bool IsSimpleValue(Dart_Handle object) {
return (Dart_IsNull(object) ||
Dart_IsNumber(object) ||
Dart_IsString(object) ||
Dart_IsBoolean(object));
}
static void FreeVMReference(Dart_WeakPersistentHandle weak_ref, void* data) {
Dart_PersistentHandle perm_handle =
reinterpret_cast<Dart_PersistentHandle>(data);
Dart_DeletePersistentHandle(perm_handle);
Dart_DeleteWeakPersistentHandle(weak_ref);
}
static Dart_Handle CreateVMReference(Dart_Handle handle) {
// Create the VMReference object.
Dart_Handle cls_name = NewString("VMReference");
Dart_Handle cls = Dart_GetClass(MirrorLib(), cls_name);
if (Dart_IsError(cls)) {
return cls;
}
Dart_Handle vm_ref = Dart_New(cls, Dart_Null(), 0, NULL);
if (Dart_IsError(vm_ref)) {
return vm_ref;
}
// Allocate a persistent handle.
Dart_PersistentHandle perm_handle = Dart_NewPersistentHandle(handle);
ASSERT(perm_handle != NULL);
// Store the persistent handle in the VMReference.
intptr_t perm_handle_value = reinterpret_cast<intptr_t>(perm_handle);
Dart_Handle result =
Dart_SetNativeInstanceField(vm_ref, 0, perm_handle_value);
if (Dart_IsError(result)) {
Dart_DeletePersistentHandle(perm_handle);
return result;
}
// Create a weak reference. We use the callback to be informed when
// the VMReference is collected, so we can release the persistent
// handle.
void* perm_handle_data = reinterpret_cast<void*>(perm_handle);
Dart_WeakPersistentHandle weak_ref =
Dart_NewWeakPersistentHandle(vm_ref, perm_handle_data, FreeVMReference);
ASSERT(weak_ref != NULL);
// Success.
return vm_ref;
}
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 UnwrapArg(Dart_Handle arg) {
if (Dart_IsError(arg)) {
return arg;
}
bool is_mirror = false;
Dart_Handle result = IsMirror(arg, &is_mirror);
if (Dart_IsError(result)) {
return result;
}
if (is_mirror) {
return UnwrapMirror(arg);
} else {
// Simple value.
ASSERT(IsSimpleValue(arg));
return arg;
}
}
static Dart_Handle UnwrapArgList(Dart_Handle arg_list,
GrowableArray<Dart_Handle>* arg_array) {
intptr_t len = 0;
Dart_Handle result = Dart_ListLength(arg_list, &len);
if (Dart_IsError(result)) {
return result;
}
for (intptr_t i = 0; i < len; i++) {
Dart_Handle arg = Dart_ListGetAt(arg_list, i);
Dart_Handle unwrapped_arg = UnwrapArg(arg);
if (Dart_IsError(unwrapped_arg)) {
return unwrapped_arg;
}
arg_array->Add(unwrapped_arg);
}
return Dart_True();
}
static Dart_Handle UnpackLocalArgList(Dart_Handle arg_list,
GrowableArray<Dart_Handle>* arg_array) {
intptr_t len = 0;
Dart_Handle result = Dart_ListLength(arg_list, &len);
if (Dart_IsError(result)) {
return result;
}
for (intptr_t i = 0; i < len; i++) {
Dart_Handle arg = Dart_ListGetAt(arg_list, i);
if (Dart_IsError(arg)) {
return arg;
}
arg_array->Add(arg);
}
return Dart_True();
}
static Dart_Handle CreateLazyMirror(Dart_Handle target);
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_cls = Dart_GetClass(MirrorLib(), param_cls_name);
if (Dart_IsError(param_cls)) {
return param_cls;
}
for (int64_t i = 0; i < param_count; i++) {
Dart_Handle param_type = Dart_FunctionParameterType(func, i);
if (Dart_IsError(param_type)) {
return param_type;
}
Dart_Handle args[] = {
CreateLazyMirror(param_type),
Dart_NewBoolean(i >= fixed_param_count), // optional param?
};
Dart_Handle param =
Dart_New(param_cls, 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 cls = Dart_GetClass(MirrorLib(), cls_name);
Dart_Handle args[] = { Dart_LibraryUrl(target) };
return Dart_New(cls, Dart_Null(), ARRAY_SIZE(args), args);
}
if (Dart_IsClass(target)) {
if (Dart_ClassIsFunctionType(target)) {
Dart_Handle cls_name = NewString("_LazyFunctionTypeMirror");
Dart_Handle cls = Dart_GetClass(MirrorLib(), cls_name);
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(cls, Dart_Null(), ARRAY_SIZE(args), args);
} else {
Dart_Handle cls_name = NewString("_LazyTypeMirror");
Dart_Handle cls = Dart_GetClass(MirrorLib(), cls_name);
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(cls, 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 cls = Dart_GetClass(MirrorLib(), cls_name);
Dart_Handle args[] = { var_name, owner_mirror };
return Dart_New(cls, 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 cls = Dart_GetClass(MirrorLib(), cls_name);
if (Dart_IsError(cls)) {
return cls;
}
Dart_Handle upper_bound = Dart_TypeVariableUpperBound(type_var);
if (Dart_IsError(upper_bound)) {
return upper_bound;
}
Dart_Handle args[] = {
type_var_name,
owner_mirror,
CreateLazyMirror(upper_bound),
};
Dart_Handle mirror = Dart_New(cls, 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_cls = Dart_GetClass(MirrorLib(), mirror_cls_name);
if (Dart_IsError(mirror_cls)) {
return mirror_cls;
}
Dart_Handle referent = Dart_ClassGetTypedefReferent(cls);
if (Dart_IsError(referent)) {
return referent;
}
Dart_Handle args[] = {
cls_name,
owner_mirror,
CreateLazyMirror(referent),
};
Dart_Handle mirror =
Dart_New(mirror_cls, 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 CreateClassMirror(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 cls = Dart_GetClass(MirrorLib(), cls_name);
if (Dart_IsError(cls)) {
return cls;
}
// 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[] = {
CreateVMReference(intf),
intf_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(cls, Dart_Null(), ARRAY_SIZE(args), args);
return mirror;
}
static Dart_Handle CreateMethodMirror(Dart_Handle func,
Dart_Handle func_name,
Dart_Handle owner_mirror) {
ASSERT(Dart_IsFunction(func));
Dart_Handle mirror_cls_name = NewString("_LocalMethodMirrorImpl");
Dart_Handle mirror_cls = Dart_GetClass(MirrorLib(), mirror_cls_name);
if (Dart_IsError(mirror_cls)) {
return mirror_cls;
}
bool is_static = false;
bool is_abstract = false;
bool is_getter = false;
bool is_setter = false;
bool is_constructor = false;
Dart_Handle result = Dart_FunctionIsStatic(func, &is_static);
if (Dart_IsError(result)) {
return result;
}
result = Dart_FunctionIsAbstract(func, &is_abstract);
if (Dart_IsError(result)) {
return result;
}
result = Dart_FunctionIsGetter(func, &is_getter);
if (Dart_IsError(result)) {
return result;
}
result = Dart_FunctionIsSetter(func, &is_setter);
if (Dart_IsError(result)) {
return result;
}
result = Dart_FunctionIsConstructor(func, &is_constructor);
if (Dart_IsError(result)) {
return result;
}
Dart_Handle return_type = Dart_FunctionReturnType(func);
if (Dart_IsError(return_type)) {
return return_type;
}
int64_t fixed_param_count;
int64_t opt_param_count;
result = Dart_FunctionParameterCounts(func,
&fixed_param_count,
&opt_param_count);
if (Dart_IsError(result)) {
return result;
}
// TODO(turnidge): Implement constructor kinds (arguments 7 - 10).
Dart_Handle args[] = {
func_name,
owner_mirror,
CreateParameterMirrorList(func),
CreateLazyMirror(return_type),
Dart_NewBoolean(is_static),
Dart_NewBoolean(is_abstract),
Dart_NewBoolean(is_getter),
Dart_NewBoolean(is_setter),
Dart_NewBoolean(is_constructor),
Dart_False(),
Dart_False(),
Dart_False(),
Dart_False(),
};
Dart_Handle mirror =
Dart_New(mirror_cls, Dart_Null(), ARRAY_SIZE(args), args);
return mirror;
}
static Dart_Handle CreateVariableMirror(Dart_Handle var,
Dart_Handle var_name,
Dart_Handle lib_mirror) {
ASSERT(Dart_IsVariable(var));
Dart_Handle cls_name = NewString("_LocalVariableMirrorImpl");
Dart_Handle cls = Dart_GetClass(MirrorLib(), cls_name);
if (Dart_IsError(cls)) {
return cls;
}
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 type = Dart_VariableType(var);
if (Dart_IsError(type)) {
return type;
}
Dart_Handle args[] = {
var_name,
lib_mirror,
CreateLazyMirror(type),
Dart_NewBoolean(is_static),
Dart_NewBoolean(is_final),
};
Dart_Handle mirror = Dart_New(cls, 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 =
CreateClassMirror(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 = CreateMethodMirror(func, func_name, 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 = CreateMethodMirror(func, func_name, 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 CreateLibraryMirror(Dart_Handle lib) {
Dart_Handle cls_name = NewString("_LocalLibraryMirrorImpl");
Dart_Handle cls = Dart_GetClass(MirrorLib(), cls_name);
if (Dart_IsError(cls)) {
return cls;
}
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[] = {
CreateVMReference(lib),
Dart_LibraryName(lib),
Dart_LibraryUrl(lib),
member_map,
};
Dart_Handle lib_mirror = Dart_New(cls, 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 = CreateLibraryMirror(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 cls = Dart_GetClass(MirrorLib(), cls_name);
if (Dart_IsError(cls)) {
return cls;
}
Dart_Handle args[] = {
Dart_DebugName(),
CreateLazyMirror(Dart_RootLibrary()),
};
return Dart_New(cls, Dart_Null(), ARRAY_SIZE(args), args);
}
static Dart_Handle CreateMirrorSystem() {
Dart_Handle cls_name = NewString("_LocalMirrorSystemImpl");
Dart_Handle cls = Dart_GetClass(MirrorLib(), cls_name);
if (Dart_IsError(cls)) {
return cls;
}
Dart_Handle libraries = CreateLibrariesMap();
if (Dart_IsError(libraries)) {
return libraries;
}
Dart_Handle args[] = {
libraries,
CreateIsolateMirror(),
};
Dart_Handle mirror = Dart_New(cls, 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 cls = Dart_GetClass(MirrorLib(), cls_name);
if (Dart_IsError(cls)) {
return cls;
}
// TODO(turnidge): This is wrong. The Null class is distinct from object.
Dart_Handle object_class = Dart_GetClass(CoreLib(), NewString("Object"));
Dart_Handle args[] = {
CreateVMReference(Dart_Null()),
CreateLazyMirror(object_class),
Dart_Null(),
};
Dart_Handle mirror = Dart_New(cls, 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 cls = Dart_GetClass(MirrorLib(), cls_name);
if (Dart_IsError(cls)) {
return cls;
}
// 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_name = NewString("call");
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 =
CreateMethodMirror(func, func_name, Dart_Null());
if (Dart_IsError(func_mirror)) {
return func_mirror;
}
Dart_Handle args[] = {
CreateVMReference(instance),
CreateLazyMirror(instance_cls),
instance,
func_mirror,
};
return Dart_New(cls, Dart_Null(), ARRAY_SIZE(args), args);
} else {
Dart_Handle cls_name = NewString("_LocalInstanceMirrorImpl");
Dart_Handle cls = Dart_GetClass(MirrorLib(), cls_name);
if (Dart_IsError(cls)) {
return cls;
}
Dart_Handle args[] = {
CreateVMReference(instance),
CreateLazyMirror(instance_cls),
instance,
};
return Dart_New(cls, Dart_Null(), ARRAY_SIZE(args), args);
}
}
static Dart_Handle CreateMirroredError(Dart_Handle error) {
ASSERT(Dart_IsError(error));
if (Dart_IsUnhandledExceptionError(error)) {
Dart_Handle exc = Dart_ErrorGetException(error);
if (Dart_IsError(exc)) {
return exc;
}
Dart_Handle exc_string = Dart_ToString(exc);
if (Dart_IsError(exc_string)) {
// Only propagate fatal errors from exc.toString(). Ignore the rest.
if (Dart_IsFatalError(exc_string)) {
return exc_string;
}
exc_string = Dart_Null();
}
Dart_Handle stack = Dart_ErrorGetStacktrace(error);
if (Dart_IsError(stack)) {
return stack;
}
Dart_Handle cls_name = NewString("MirroredUncaughtExceptionError");
Dart_Handle cls = Dart_GetClass(MirrorLib(), cls_name);
Dart_Handle args[] = {
CreateInstanceMirror(exc),
exc_string,
stack,
};
Dart_Handle mirrored_exc =
Dart_New(cls, Dart_Null(), ARRAY_SIZE(args), args);
return Dart_NewUnhandledExceptionError(mirrored_exc);
} else if (Dart_IsApiError(error) ||
Dart_IsCompilationError(error)) {
Dart_Handle cls_name = NewString("MirroredCompilationError");
Dart_Handle cls = Dart_GetClass(MirrorLib(), cls_name);
Dart_Handle args[] = { NewString(Dart_GetError(error)) };
Dart_Handle mirrored_exc =
Dart_New(cls, Dart_Null(), ARRAY_SIZE(args), args);
return Dart_NewUnhandledExceptionError(mirrored_exc);
} else {
ASSERT(Dart_IsFatalError(error));
return error;
}
}
void NATIVE_ENTRY_FUNCTION(Mirrors_makeLocalMirrorSystem)(
Dart_NativeArguments args) {
Dart_EnterScope();
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 = CreateLibraryMirror(lib_handle);
if (Dart_IsError(lib_mirror)) {
Dart_PropagateError(lib_mirror);
}
Dart_Handle result = CreateClassMirror(cls_handle,
name_handle,
lib_handle,
lib_mirror);
if (Dart_IsError(result)) {
Dart_PropagateError(result);
}
Dart_SetReturnValue(args, result);
Dart_ExitScope();
}
void NATIVE_ENTRY_FUNCTION(Mirrors_metadata)(Dart_NativeArguments args) {
Dart_EnterScope();
Dart_Handle mirror = Dart_GetNativeArgument(args, 0);
Dart_Handle reflectee = UnwrapMirror(mirror);
Dart_Handle result = Dart_GetMetadata(reflectee);
if (Dart_IsError(result)) {
Dart_PropagateError(result);
}
ASSERT(Dart_IsList(result));
Dart_SetReturnValue(args, result);
Dart_ExitScope();
}
void NATIVE_ENTRY_FUNCTION(LocalObjectMirrorImpl_invoke)(
Dart_NativeArguments args) {
Dart_EnterScope();
Dart_Handle mirror = Dart_GetNativeArgument(args, 0);
Dart_Handle member_name = Dart_GetNativeArgument(args, 1);
// The arguments are either simple values or instance mirrors.
Dart_Handle positional_arguments = Dart_GetNativeArgument(args, 2);
Dart_Handle async = Dart_GetNativeArgument(args, 3);
Dart_Handle reflectee = UnwrapMirror(mirror);
Dart_Handle result;
GrowableArray<Dart_Handle> invoke_args;
if (Dart_IdentityEquals(async, Dart_True())) {
result = UnwrapArgList(positional_arguments, &invoke_args);
} else {
result = UnpackLocalArgList(positional_arguments, &invoke_args);
}
if (Dart_IsError(result)) {
Dart_PropagateError(result);
}
result = Dart_Invoke(reflectee,
member_name,
invoke_args.length(),
invoke_args.data());
if (Dart_IsError(result)) {
// Instead of propagating the error from an invoke directly, we
// provide reflective access to the error.
Dart_PropagateError(CreateMirroredError(result));
}
Dart_Handle wrapped_result = CreateInstanceMirror(result);
if (Dart_IsError(wrapped_result)) {
Dart_PropagateError(wrapped_result);
}
Dart_SetReturnValue(args, wrapped_result);
Dart_ExitScope();
}
void NATIVE_ENTRY_FUNCTION(LocalObjectMirrorImpl_getField)(
Dart_NativeArguments args) {
Dart_EnterScope();
Dart_Handle mirror = Dart_GetNativeArgument(args, 0);
Dart_Handle fieldName = Dart_GetNativeArgument(args, 1);
Dart_Handle reflectee = UnwrapMirror(mirror);
Dart_Handle result = Dart_GetField(reflectee, fieldName);
if (Dart_IsError(result)) {
// Instead of propagating the error from a GetField directly, we
// provide reflective access to the error.
Dart_PropagateError(CreateMirroredError(result));
}
Dart_Handle wrapped_result = CreateInstanceMirror(result);
if (Dart_IsError(wrapped_result)) {
Dart_PropagateError(wrapped_result);
}
Dart_SetReturnValue(args, wrapped_result);
Dart_ExitScope();
}
void NATIVE_ENTRY_FUNCTION(LocalObjectMirrorImpl_setField)(
Dart_NativeArguments args) {
Dart_EnterScope();
Dart_Handle mirror = Dart_GetNativeArgument(args, 0);
Dart_Handle fieldName = Dart_GetNativeArgument(args, 1);
Dart_Handle value = Dart_GetNativeArgument(args, 2);
Dart_Handle async = Dart_GetNativeArgument(args, 3);
Dart_Handle reflectee = UnwrapMirror(mirror);
Dart_Handle set_arg;
if (Dart_IdentityEquals(async, Dart_True())) {
set_arg = UnwrapArg(value);
} else {
set_arg = value;
}
if (Dart_IsError(set_arg)) {
Dart_PropagateError(set_arg);
}
Dart_Handle result = Dart_SetField(reflectee, fieldName, set_arg);
if (Dart_IsError(result)) {
// Instead of propagating the error from a SetField directly, we
// provide reflective access to the error.
Dart_PropagateError(CreateMirroredError(result));
}
Dart_Handle wrapped_result = CreateInstanceMirror(result);
if (Dart_IsError(wrapped_result)) {
Dart_PropagateError(wrapped_result);
}
Dart_SetReturnValue(args, wrapped_result);
Dart_ExitScope();
}
void NATIVE_ENTRY_FUNCTION(LocalClosureMirrorImpl_apply)(
Dart_NativeArguments args) {
Dart_EnterScope();
Dart_Handle mirror = Dart_GetNativeArgument(args, 0);
// The arguments are either simple values or instance mirrors.
Dart_Handle positional_arguments = Dart_GetNativeArgument(args, 1);
Dart_Handle async = Dart_GetNativeArgument(args, 2);
Dart_Handle reflectee = UnwrapMirror(mirror);
GrowableArray<Dart_Handle> invoke_args;
Dart_Handle result;
if (Dart_IdentityEquals(async, Dart_True())) {
result = UnwrapArgList(positional_arguments, &invoke_args);
} else {
result = UnpackLocalArgList(positional_arguments, &invoke_args);
}
if (Dart_IsError(result)) {
Dart_PropagateError(result);
}
result =
Dart_InvokeClosure(reflectee, invoke_args.length(), invoke_args.data());
if (Dart_IsError(result)) {
// Instead of propagating the error from an apply directly, we
// provide reflective access to the error.
Dart_PropagateError(CreateMirroredError(result));
}
Dart_Handle wrapped_result = CreateInstanceMirror(result);
if (Dart_IsError(wrapped_result)) {
Dart_PropagateError(wrapped_result);
}
Dart_SetReturnValue(args, wrapped_result);
Dart_ExitScope();
}
void NATIVE_ENTRY_FUNCTION(LocalClassMirrorImpl_invokeConstructor)(
Dart_NativeArguments args) {
Dart_EnterScope();
Dart_Handle klass_mirror = Dart_GetNativeArgument(args, 0);
Dart_Handle constructor_name = Dart_GetNativeArgument(args, 1);
// The arguments are either simple values or instance mirrors.
Dart_Handle positional_arguments = Dart_GetNativeArgument(args, 2);
Dart_Handle async = Dart_GetNativeArgument(args, 3);
Dart_Handle klass = UnwrapMirror(klass_mirror);
GrowableArray<Dart_Handle> invoke_args;
Dart_Handle result;
if (Dart_IdentityEquals(async, Dart_True())) {
result = UnwrapArgList(positional_arguments, &invoke_args);
} else {
result = UnpackLocalArgList(positional_arguments, &invoke_args);
}
if (Dart_IsError(result)) {
Dart_PropagateError(result);
}
result = Dart_New(klass,
constructor_name,
invoke_args.length(),
invoke_args.data());
if (Dart_IsError(result)) {
// Instead of propagating the error from an invoke directly, we
// provide reflective access to the error.
Dart_PropagateError(CreateMirroredError(result));
}
Dart_Handle wrapped_result = CreateInstanceMirror(result);
if (Dart_IsError(wrapped_result)) {
Dart_PropagateError(wrapped_result);
}
Dart_SetReturnValue(args, wrapped_result);
Dart_ExitScope();
}
void HandleMirrorsMessage(Isolate* isolate,
Dart_Port reply_port,
const Instance& message) {
UNIMPLEMENTED();
}
} // namespace dart