OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. |
| 4 |
| 5 #include "include/dart_mirrors_api.h" |
| 6 |
| 7 #include "platform/assert.h" |
| 8 #include "vm/class_finalizer.h" |
| 9 #include "vm/dart.h" |
| 10 #include "vm/dart_api_impl.h" |
| 11 #include "vm/dart_api_state.h" |
| 12 #include "vm/dart_entry.h" |
| 13 #include "vm/exceptions.h" |
| 14 #include "vm/growable_array.h" |
| 15 #include "vm/object.h" |
| 16 #include "vm/resolver.h" |
| 17 #include "vm/stack_frame.h" |
| 18 #include "vm/symbols.h" |
| 19 |
| 20 namespace dart { |
| 21 |
| 22 // When we want to return a handle to a type to the user, we handle |
| 23 // class-types differently than some other types. |
| 24 static Dart_Handle TypeToHandle(Isolate* isolate, |
| 25 const char* function_name, |
| 26 const AbstractType& type) { |
| 27 if (type.IsMalformed()) { |
| 28 const Error& error = Error::Handle(type.malformed_error()); |
| 29 return Api::NewError("%s: malformed type encountered: %s.", |
| 30 function_name, error.ToErrorCString()); |
| 31 } else if (type.HasResolvedTypeClass()) { |
| 32 const Class& cls = Class::Handle(isolate, type.type_class()); |
| 33 #if defined(DEBUG) |
| 34 const Library& lib = Library::Handle(cls.library()); |
| 35 if (lib.IsNull()) { |
| 36 ASSERT(cls.IsDynamicClass() || cls.IsVoidClass()); |
| 37 } |
| 38 #endif |
| 39 return Api::NewHandle(isolate, cls.raw()); |
| 40 } else if (type.IsTypeParameter()) { |
| 41 return Api::NewHandle(isolate, type.raw()); |
| 42 } else { |
| 43 return Api::NewError("%s: unexpected type '%s' encountered.", |
| 44 function_name, type.ToCString()); |
| 45 } |
| 46 } |
| 47 |
| 48 |
| 49 // --- Classes and Interfaces Reflection --- |
| 50 |
| 51 DART_EXPORT Dart_Handle Dart_ClassName(Dart_Handle clazz) { |
| 52 Isolate* isolate = Isolate::Current(); |
| 53 DARTSCOPE(isolate); |
| 54 const Class& cls = Api::UnwrapClassHandle(isolate, clazz); |
| 55 if (cls.IsNull()) { |
| 56 RETURN_TYPE_ERROR(isolate, clazz, Class); |
| 57 } |
| 58 return Api::NewHandle(isolate, cls.UserVisibleName()); |
| 59 } |
| 60 |
| 61 |
| 62 DART_EXPORT Dart_Handle Dart_ClassGetLibrary(Dart_Handle clazz) { |
| 63 Isolate* isolate = Isolate::Current(); |
| 64 DARTSCOPE(isolate); |
| 65 const Class& cls = Api::UnwrapClassHandle(isolate, clazz); |
| 66 if (cls.IsNull()) { |
| 67 RETURN_TYPE_ERROR(isolate, clazz, Class); |
| 68 } |
| 69 |
| 70 #if defined(DEBUG) |
| 71 const Library& lib = Library::Handle(cls.library()); |
| 72 if (lib.IsNull()) { |
| 73 // ASSERT(cls.IsDynamicClass() || cls.IsVoidClass()); |
| 74 if (!cls.IsDynamicClass() && !cls.IsVoidClass()) { |
| 75 fprintf(stderr, "NO LIBRARY: %s\n", cls.ToCString()); |
| 76 } |
| 77 } |
| 78 #endif |
| 79 |
| 80 return Api::NewHandle(isolate, cls.library()); |
| 81 } |
| 82 |
| 83 |
| 84 DART_EXPORT Dart_Handle Dart_ClassGetInterfaceCount(Dart_Handle clazz, |
| 85 intptr_t* count) { |
| 86 Isolate* isolate = Isolate::Current(); |
| 87 DARTSCOPE(isolate); |
| 88 const Class& cls = Api::UnwrapClassHandle(isolate, clazz); |
| 89 if (cls.IsNull()) { |
| 90 RETURN_TYPE_ERROR(isolate, clazz, Class); |
| 91 } |
| 92 |
| 93 const Array& interface_types = Array::Handle(isolate, cls.interfaces()); |
| 94 if (interface_types.IsNull()) { |
| 95 *count = 0; |
| 96 } else { |
| 97 *count = interface_types.Length(); |
| 98 } |
| 99 return Api::Success(); |
| 100 } |
| 101 |
| 102 |
| 103 DART_EXPORT Dart_Handle Dart_ClassGetInterfaceAt(Dart_Handle clazz, |
| 104 intptr_t index) { |
| 105 Isolate* isolate = Isolate::Current(); |
| 106 DARTSCOPE(isolate); |
| 107 const Class& cls = Api::UnwrapClassHandle(isolate, clazz); |
| 108 if (cls.IsNull()) { |
| 109 RETURN_TYPE_ERROR(isolate, clazz, Class); |
| 110 } |
| 111 |
| 112 // Finalize all classes. |
| 113 Dart_Handle state = Api::CheckIsolateState(isolate); |
| 114 if (::Dart_IsError(state)) { |
| 115 return state; |
| 116 } |
| 117 |
| 118 const Array& interface_types = Array::Handle(isolate, cls.interfaces()); |
| 119 if (index < 0 || index >= interface_types.Length()) { |
| 120 return Api::NewError("%s: argument 'index' out of bounds.", CURRENT_FUNC); |
| 121 } |
| 122 Type& interface_type = Type::Handle(isolate); |
| 123 interface_type ^= interface_types.At(index); |
| 124 if (interface_type.HasResolvedTypeClass()) { |
| 125 return Api::NewHandle(isolate, interface_type.type_class()); |
| 126 } |
| 127 const String& type_name = |
| 128 String::Handle(isolate, interface_type.TypeClassName()); |
| 129 return Api::NewError("%s: internal error: found unresolved type class '%s'.", |
| 130 CURRENT_FUNC, type_name.ToCString()); |
| 131 } |
| 132 |
| 133 |
| 134 DART_EXPORT bool Dart_ClassIsTypedef(Dart_Handle clazz) { |
| 135 Isolate* isolate = Isolate::Current(); |
| 136 DARTSCOPE(isolate); |
| 137 const Class& cls = Api::UnwrapClassHandle(isolate, clazz); |
| 138 if (cls.IsNull()) { |
| 139 RETURN_TYPE_ERROR(isolate, clazz, Class); |
| 140 } |
| 141 // For now we represent typedefs as non-canonical signature classes. |
| 142 // I anticipate this may change if we make typedefs more general. |
| 143 return cls.IsSignatureClass() && !cls.IsCanonicalSignatureClass(); |
| 144 } |
| 145 |
| 146 |
| 147 DART_EXPORT Dart_Handle Dart_ClassGetTypedefReferent(Dart_Handle clazz) { |
| 148 Isolate* isolate = Isolate::Current(); |
| 149 DARTSCOPE(isolate); |
| 150 const Class& cls = Api::UnwrapClassHandle(isolate, clazz); |
| 151 if (cls.IsNull()) { |
| 152 RETURN_TYPE_ERROR(isolate, clazz, Class); |
| 153 } |
| 154 |
| 155 if (!cls.IsSignatureClass() && !cls.IsCanonicalSignatureClass()) { |
| 156 const String& cls_name = String::Handle(cls.UserVisibleName()); |
| 157 return Api::NewError("%s: class '%s' is not a typedef class. " |
| 158 "See Dart_ClassIsTypedef.", |
| 159 CURRENT_FUNC, cls_name.ToCString()); |
| 160 } |
| 161 |
| 162 const Function& func = Function::Handle(isolate, cls.signature_function()); |
| 163 return Api::NewHandle(isolate, func.signature_class()); |
| 164 } |
| 165 |
| 166 |
| 167 DART_EXPORT bool Dart_ClassIsFunctionType(Dart_Handle clazz) { |
| 168 Isolate* isolate = Isolate::Current(); |
| 169 DARTSCOPE(isolate); |
| 170 const Class& cls = Api::UnwrapClassHandle(isolate, clazz); |
| 171 if (cls.IsNull()) { |
| 172 RETURN_TYPE_ERROR(isolate, clazz, Class); |
| 173 } |
| 174 // A class represents a function type when it is a canonical |
| 175 // signature class. |
| 176 return cls.IsCanonicalSignatureClass(); |
| 177 } |
| 178 |
| 179 |
| 180 DART_EXPORT Dart_Handle Dart_ClassGetFunctionTypeSignature(Dart_Handle clazz) { |
| 181 Isolate* isolate = Isolate::Current(); |
| 182 DARTSCOPE(isolate); |
| 183 const Class& cls = Api::UnwrapClassHandle(isolate, clazz); |
| 184 if (cls.IsNull()) { |
| 185 RETURN_TYPE_ERROR(isolate, clazz, Class); |
| 186 } |
| 187 if (!cls.IsCanonicalSignatureClass()) { |
| 188 const String& cls_name = String::Handle(cls.UserVisibleName()); |
| 189 return Api::NewError("%s: class '%s' is not a function-type class. " |
| 190 "See Dart_ClassIsFunctionType.", |
| 191 CURRENT_FUNC, cls_name.ToCString()); |
| 192 } |
| 193 return Api::NewHandle(isolate, cls.signature_function()); |
| 194 } |
| 195 |
| 196 |
| 197 // --- Function and Variable Reflection --- |
| 198 |
| 199 // Outside of the vm, we expose setter names with a trailing '='. |
| 200 static bool HasExternalSetterSuffix(const String& name) { |
| 201 return name.CharAt(name.Length() - 1) == '='; |
| 202 } |
| 203 |
| 204 |
| 205 static RawString* RemoveExternalSetterSuffix(const String& name) { |
| 206 ASSERT(HasExternalSetterSuffix(name)); |
| 207 return String::SubString(name, 0, name.Length() - 1); |
| 208 } |
| 209 |
| 210 |
| 211 DART_EXPORT Dart_Handle Dart_GetFunctionNames(Dart_Handle target) { |
| 212 Isolate* isolate = Isolate::Current(); |
| 213 DARTSCOPE(isolate); |
| 214 const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(target)); |
| 215 if (obj.IsError()) { |
| 216 return target; |
| 217 } |
| 218 |
| 219 const GrowableObjectArray& names = |
| 220 GrowableObjectArray::Handle(isolate, GrowableObjectArray::New()); |
| 221 Function& func = Function::Handle(); |
| 222 String& name = String::Handle(); |
| 223 |
| 224 if (obj.IsClass()) { |
| 225 const Class& cls = Class::Cast(obj); |
| 226 const Error& error = Error::Handle(isolate, cls.EnsureIsFinalized(isolate)); |
| 227 if (!error.IsNull()) { |
| 228 return Api::NewHandle(isolate, error.raw()); |
| 229 } |
| 230 const Array& func_array = Array::Handle(cls.functions()); |
| 231 |
| 232 // Some special types like 'dynamic' have a null functions list. |
| 233 if (!func_array.IsNull()) { |
| 234 for (intptr_t i = 0; i < func_array.Length(); ++i) { |
| 235 func ^= func_array.At(i); |
| 236 |
| 237 // Skip implicit getters and setters. |
| 238 if (func.kind() == RawFunction::kImplicitGetter || |
| 239 func.kind() == RawFunction::kImplicitSetter || |
| 240 func.kind() == RawFunction::kConstImplicitGetter || |
| 241 func.kind() == RawFunction::kMethodExtractor) { |
| 242 continue; |
| 243 } |
| 244 |
| 245 name = func.UserVisibleName(); |
| 246 names.Add(name); |
| 247 } |
| 248 } |
| 249 } else if (obj.IsLibrary()) { |
| 250 const Library& lib = Library::Cast(obj); |
| 251 DictionaryIterator it(lib); |
| 252 Object& obj = Object::Handle(); |
| 253 while (it.HasNext()) { |
| 254 obj = it.GetNext(); |
| 255 if (obj.IsFunction()) { |
| 256 func ^= obj.raw(); |
| 257 name = func.UserVisibleName(); |
| 258 names.Add(name); |
| 259 } |
| 260 } |
| 261 } else { |
| 262 return Api::NewError( |
| 263 "%s expects argument 'target' to be a class or library.", |
| 264 CURRENT_FUNC); |
| 265 } |
| 266 return Api::NewHandle(isolate, Array::MakeArray(names)); |
| 267 } |
| 268 |
| 269 |
| 270 DART_EXPORT Dart_Handle Dart_LookupFunction(Dart_Handle target, |
| 271 Dart_Handle function_name) { |
| 272 Isolate* isolate = Isolate::Current(); |
| 273 DARTSCOPE(isolate); |
| 274 const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(target)); |
| 275 if (obj.IsError()) { |
| 276 return target; |
| 277 } |
| 278 const String& func_name = Api::UnwrapStringHandle(isolate, function_name); |
| 279 if (func_name.IsNull()) { |
| 280 RETURN_TYPE_ERROR(isolate, function_name, String); |
| 281 } |
| 282 |
| 283 Function& func = Function::Handle(isolate); |
| 284 String& tmp_name = String::Handle(isolate); |
| 285 if (obj.IsClass()) { |
| 286 const Class& cls = Class::Cast(obj); |
| 287 |
| 288 // Case 1. Lookup the unmodified function name. |
| 289 func = cls.LookupFunctionAllowPrivate(func_name); |
| 290 |
| 291 // Case 2. Lookup the function without the external setter suffix |
| 292 // '='. Make sure to do this check after the regular lookup, so |
| 293 // that we don't interfere with operator lookups (like ==). |
| 294 if (func.IsNull() && HasExternalSetterSuffix(func_name)) { |
| 295 tmp_name = RemoveExternalSetterSuffix(func_name); |
| 296 tmp_name = Field::SetterName(tmp_name); |
| 297 func = cls.LookupFunctionAllowPrivate(tmp_name); |
| 298 } |
| 299 |
| 300 // Case 3. Lookup the funciton with the getter prefix prepended. |
| 301 if (func.IsNull()) { |
| 302 tmp_name = Field::GetterName(func_name); |
| 303 func = cls.LookupFunctionAllowPrivate(tmp_name); |
| 304 } |
| 305 |
| 306 // Case 4. Lookup the function with a . appended to find the |
| 307 // unnamed constructor. |
| 308 if (func.IsNull()) { |
| 309 tmp_name = String::Concat(func_name, Symbols::Dot()); |
| 310 func = cls.LookupFunctionAllowPrivate(tmp_name); |
| 311 } |
| 312 } else if (obj.IsLibrary()) { |
| 313 const Library& lib = Library::Cast(obj); |
| 314 |
| 315 // Case 1. Lookup the unmodified function name. |
| 316 func = lib.LookupFunctionAllowPrivate(func_name); |
| 317 |
| 318 // Case 2. Lookup the function without the external setter suffix |
| 319 // '='. Make sure to do this check after the regular lookup, so |
| 320 // that we don't interfere with operator lookups (like ==). |
| 321 if (func.IsNull() && HasExternalSetterSuffix(func_name)) { |
| 322 tmp_name = RemoveExternalSetterSuffix(func_name); |
| 323 tmp_name = Field::SetterName(tmp_name); |
| 324 func = lib.LookupFunctionAllowPrivate(tmp_name); |
| 325 } |
| 326 |
| 327 // Case 3. Lookup the function with the getter prefix prepended. |
| 328 if (func.IsNull()) { |
| 329 tmp_name = Field::GetterName(func_name); |
| 330 func = lib.LookupFunctionAllowPrivate(tmp_name); |
| 331 } |
| 332 } else { |
| 333 return Api::NewError( |
| 334 "%s expects argument 'target' to be a class or library.", |
| 335 CURRENT_FUNC); |
| 336 } |
| 337 |
| 338 #if defined(DEBUG) |
| 339 if (!func.IsNull()) { |
| 340 // We only provide access to a subset of function kinds. |
| 341 RawFunction::Kind func_kind = func.kind(); |
| 342 ASSERT(func_kind == RawFunction::kRegularFunction || |
| 343 func_kind == RawFunction::kGetterFunction || |
| 344 func_kind == RawFunction::kSetterFunction || |
| 345 func_kind == RawFunction::kConstructor); |
| 346 } |
| 347 #endif |
| 348 return Api::NewHandle(isolate, func.raw()); |
| 349 } |
| 350 |
| 351 |
| 352 DART_EXPORT Dart_Handle Dart_FunctionName(Dart_Handle function) { |
| 353 Isolate* isolate = Isolate::Current(); |
| 354 DARTSCOPE(isolate); |
| 355 const Function& func = Api::UnwrapFunctionHandle(isolate, function); |
| 356 if (func.IsNull()) { |
| 357 RETURN_TYPE_ERROR(isolate, function, Function); |
| 358 } |
| 359 return Api::NewHandle(isolate, func.UserVisibleName()); |
| 360 } |
| 361 |
| 362 |
| 363 DART_EXPORT Dart_Handle Dart_FunctionOwner(Dart_Handle function) { |
| 364 Isolate* isolate = Isolate::Current(); |
| 365 DARTSCOPE(isolate); |
| 366 const Function& func = Api::UnwrapFunctionHandle(isolate, function); |
| 367 if (func.IsNull()) { |
| 368 RETURN_TYPE_ERROR(isolate, function, Function); |
| 369 } |
| 370 if (func.IsNonImplicitClosureFunction()) { |
| 371 RawFunction* parent_function = func.parent_function(); |
| 372 return Api::NewHandle(isolate, parent_function); |
| 373 } |
| 374 const Class& owner = Class::Handle(func.Owner()); |
| 375 ASSERT(!owner.IsNull()); |
| 376 if (owner.IsTopLevel()) { |
| 377 // Top-level functions are implemented as members of a hidden class. We hide |
| 378 // that class here and instead answer the library. |
| 379 #if defined(DEBUG) |
| 380 const Library& lib = Library::Handle(owner.library()); |
| 381 if (lib.IsNull()) { |
| 382 ASSERT(owner.IsDynamicClass() || owner.IsVoidClass()); |
| 383 } |
| 384 #endif |
| 385 return Api::NewHandle(isolate, owner.library()); |
| 386 } else { |
| 387 return Api::NewHandle(isolate, owner.raw()); |
| 388 } |
| 389 } |
| 390 |
| 391 |
| 392 DART_EXPORT Dart_Handle Dart_FunctionIsAbstract(Dart_Handle function, |
| 393 bool* is_abstract) { |
| 394 Isolate* isolate = Isolate::Current(); |
| 395 DARTSCOPE(isolate); |
| 396 if (is_abstract == NULL) { |
| 397 RETURN_NULL_ERROR(is_abstract); |
| 398 } |
| 399 const Function& func = Api::UnwrapFunctionHandle(isolate, function); |
| 400 if (func.IsNull()) { |
| 401 RETURN_TYPE_ERROR(isolate, function, Function); |
| 402 } |
| 403 *is_abstract = func.is_abstract(); |
| 404 return Api::Success(); |
| 405 } |
| 406 |
| 407 |
| 408 DART_EXPORT Dart_Handle Dart_FunctionIsStatic(Dart_Handle function, |
| 409 bool* is_static) { |
| 410 Isolate* isolate = Isolate::Current(); |
| 411 DARTSCOPE(isolate); |
| 412 if (is_static == NULL) { |
| 413 RETURN_NULL_ERROR(is_static); |
| 414 } |
| 415 const Function& func = Api::UnwrapFunctionHandle(isolate, function); |
| 416 if (func.IsNull()) { |
| 417 RETURN_TYPE_ERROR(isolate, function, Function); |
| 418 } |
| 419 *is_static = func.is_static(); |
| 420 return Api::Success(); |
| 421 } |
| 422 |
| 423 |
| 424 DART_EXPORT Dart_Handle Dart_FunctionIsConstructor(Dart_Handle function, |
| 425 bool* is_constructor) { |
| 426 Isolate* isolate = Isolate::Current(); |
| 427 DARTSCOPE(isolate); |
| 428 if (is_constructor == NULL) { |
| 429 RETURN_NULL_ERROR(is_constructor); |
| 430 } |
| 431 const Function& func = Api::UnwrapFunctionHandle(isolate, function); |
| 432 if (func.IsNull()) { |
| 433 RETURN_TYPE_ERROR(isolate, function, Function); |
| 434 } |
| 435 *is_constructor = func.kind() == RawFunction::kConstructor; |
| 436 return Api::Success(); |
| 437 } |
| 438 |
| 439 |
| 440 DART_EXPORT Dart_Handle Dart_FunctionIsGetter(Dart_Handle function, |
| 441 bool* is_getter) { |
| 442 Isolate* isolate = Isolate::Current(); |
| 443 DARTSCOPE(isolate); |
| 444 if (is_getter == NULL) { |
| 445 RETURN_NULL_ERROR(is_getter); |
| 446 } |
| 447 const Function& func = Api::UnwrapFunctionHandle(isolate, function); |
| 448 if (func.IsNull()) { |
| 449 RETURN_TYPE_ERROR(isolate, function, Function); |
| 450 } |
| 451 *is_getter = func.IsGetterFunction(); |
| 452 return Api::Success(); |
| 453 } |
| 454 |
| 455 |
| 456 DART_EXPORT Dart_Handle Dart_FunctionIsSetter(Dart_Handle function, |
| 457 bool* is_setter) { |
| 458 Isolate* isolate = Isolate::Current(); |
| 459 DARTSCOPE(isolate); |
| 460 if (is_setter == NULL) { |
| 461 RETURN_NULL_ERROR(is_setter); |
| 462 } |
| 463 const Function& func = Api::UnwrapFunctionHandle(isolate, function); |
| 464 if (func.IsNull()) { |
| 465 RETURN_TYPE_ERROR(isolate, function, Function); |
| 466 } |
| 467 *is_setter = (func.kind() == RawFunction::kSetterFunction); |
| 468 return Api::Success(); |
| 469 } |
| 470 |
| 471 |
| 472 DART_EXPORT Dart_Handle Dart_FunctionReturnType(Dart_Handle function) { |
| 473 Isolate* isolate = Isolate::Current(); |
| 474 DARTSCOPE(isolate); |
| 475 const Function& func = Api::UnwrapFunctionHandle(isolate, function); |
| 476 if (func.IsNull()) { |
| 477 RETURN_TYPE_ERROR(isolate, function, Function); |
| 478 } |
| 479 |
| 480 if (func.kind() == RawFunction::kConstructor) { |
| 481 // Special case the return type for constructors. Inside the vm |
| 482 // we mark them as returning dynamic, but for the purposes of |
| 483 // reflection, they return the type of the class being |
| 484 // constructed. |
| 485 return Api::NewHandle(isolate, func.Owner()); |
| 486 } else { |
| 487 const AbstractType& return_type = |
| 488 AbstractType::Handle(isolate, func.result_type()); |
| 489 return TypeToHandle(isolate, "Dart_FunctionReturnType", return_type); |
| 490 } |
| 491 } |
| 492 |
| 493 |
| 494 DART_EXPORT Dart_Handle Dart_FunctionParameterCounts( |
| 495 Dart_Handle function, |
| 496 int64_t* fixed_param_count, |
| 497 int64_t* opt_param_count) { |
| 498 Isolate* isolate = Isolate::Current(); |
| 499 DARTSCOPE(isolate); |
| 500 if (fixed_param_count == NULL) { |
| 501 RETURN_NULL_ERROR(fixed_param_count); |
| 502 } |
| 503 if (opt_param_count == NULL) { |
| 504 RETURN_NULL_ERROR(opt_param_count); |
| 505 } |
| 506 const Function& func = Api::UnwrapFunctionHandle(isolate, function); |
| 507 if (func.IsNull()) { |
| 508 RETURN_TYPE_ERROR(isolate, function, Function); |
| 509 } |
| 510 |
| 511 // We hide implicit parameters, such as a method's receiver. This is |
| 512 // consistent with Invoke or New, which don't expect their callers to |
| 513 // provide them in the argument lists they are handed. |
| 514 *fixed_param_count = func.num_fixed_parameters() - |
| 515 func.NumImplicitParameters(); |
| 516 // TODO(regis): Separately report named and positional optional param counts. |
| 517 *opt_param_count = func.NumOptionalParameters(); |
| 518 |
| 519 ASSERT(*fixed_param_count >= 0); |
| 520 ASSERT(*opt_param_count >= 0); |
| 521 |
| 522 return Api::Success(); |
| 523 } |
| 524 |
| 525 |
| 526 DART_EXPORT Dart_Handle Dart_FunctionParameterType(Dart_Handle function, |
| 527 int parameter_index) { |
| 528 Isolate* isolate = Isolate::Current(); |
| 529 DARTSCOPE(isolate); |
| 530 const Function& func = Api::UnwrapFunctionHandle(isolate, function); |
| 531 if (func.IsNull()) { |
| 532 RETURN_TYPE_ERROR(isolate, function, Function); |
| 533 } |
| 534 |
| 535 const intptr_t num_implicit_params = func.NumImplicitParameters(); |
| 536 const intptr_t num_params = func.NumParameters() - num_implicit_params; |
| 537 if (parameter_index < 0 || parameter_index >= num_params) { |
| 538 return Api::NewError( |
| 539 "%s: argument 'parameter_index' out of range. " |
| 540 "Expected 0..%"Pd" but saw %d.", |
| 541 CURRENT_FUNC, num_params, parameter_index); |
| 542 } |
| 543 const AbstractType& param_type = |
| 544 AbstractType::Handle(isolate, func.ParameterTypeAt( |
| 545 num_implicit_params + parameter_index)); |
| 546 return TypeToHandle(isolate, "Dart_FunctionParameterType", param_type); |
| 547 } |
| 548 |
| 549 |
| 550 DART_EXPORT Dart_Handle Dart_GetVariableNames(Dart_Handle target) { |
| 551 Isolate* isolate = Isolate::Current(); |
| 552 DARTSCOPE(isolate); |
| 553 const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(target)); |
| 554 if (obj.IsError()) { |
| 555 return target; |
| 556 } |
| 557 |
| 558 const GrowableObjectArray& names = |
| 559 GrowableObjectArray::Handle(isolate, GrowableObjectArray::New()); |
| 560 Field& field = Field::Handle(isolate); |
| 561 String& name = String::Handle(isolate); |
| 562 |
| 563 if (obj.IsClass()) { |
| 564 const Class& cls = Class::Cast(obj); |
| 565 const Error& error = Error::Handle(isolate, cls.EnsureIsFinalized(isolate)); |
| 566 if (!error.IsNull()) { |
| 567 return Api::NewHandle(isolate, error.raw()); |
| 568 } |
| 569 const Array& field_array = Array::Handle(cls.fields()); |
| 570 |
| 571 // Some special types like 'dynamic' have a null fields list. |
| 572 // |
| 573 // TODO(turnidge): Fix 'dynamic' so that it does not have a null |
| 574 // fields list. This will have to wait until the empty array is |
| 575 // allocated in the vm isolate. |
| 576 if (!field_array.IsNull()) { |
| 577 for (intptr_t i = 0; i < field_array.Length(); ++i) { |
| 578 field ^= field_array.At(i); |
| 579 name = field.UserVisibleName(); |
| 580 names.Add(name); |
| 581 } |
| 582 } |
| 583 } else if (obj.IsLibrary()) { |
| 584 const Library& lib = Library::Cast(obj); |
| 585 DictionaryIterator it(lib); |
| 586 Object& obj = Object::Handle(isolate); |
| 587 while (it.HasNext()) { |
| 588 obj = it.GetNext(); |
| 589 if (obj.IsField()) { |
| 590 field ^= obj.raw(); |
| 591 name = field.UserVisibleName(); |
| 592 names.Add(name); |
| 593 } |
| 594 } |
| 595 } else { |
| 596 return Api::NewError( |
| 597 "%s expects argument 'target' to be a class or library.", |
| 598 CURRENT_FUNC); |
| 599 } |
| 600 return Api::NewHandle(isolate, Array::MakeArray(names)); |
| 601 } |
| 602 |
| 603 |
| 604 DART_EXPORT Dart_Handle Dart_LookupVariable(Dart_Handle target, |
| 605 Dart_Handle variable_name) { |
| 606 Isolate* isolate = Isolate::Current(); |
| 607 DARTSCOPE(isolate); |
| 608 const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(target)); |
| 609 if (obj.IsError()) { |
| 610 return target; |
| 611 } |
| 612 const String& var_name = Api::UnwrapStringHandle(isolate, variable_name); |
| 613 if (var_name.IsNull()) { |
| 614 RETURN_TYPE_ERROR(isolate, variable_name, String); |
| 615 } |
| 616 if (obj.IsClass()) { |
| 617 const Class& cls = Class::Cast(obj); |
| 618 return Api::NewHandle(isolate, cls.LookupField(var_name)); |
| 619 } |
| 620 if (obj.IsLibrary()) { |
| 621 const Library& lib = Library::Cast(obj); |
| 622 return Api::NewHandle(isolate, lib.LookupFieldAllowPrivate(var_name)); |
| 623 } |
| 624 return Api::NewError( |
| 625 "%s expects argument 'target' to be a class or library.", |
| 626 CURRENT_FUNC); |
| 627 } |
| 628 |
| 629 |
| 630 DART_EXPORT Dart_Handle Dart_VariableName(Dart_Handle variable) { |
| 631 Isolate* isolate = Isolate::Current(); |
| 632 DARTSCOPE(isolate); |
| 633 const Field& var = Api::UnwrapFieldHandle(isolate, variable); |
| 634 if (var.IsNull()) { |
| 635 RETURN_TYPE_ERROR(isolate, variable, Field); |
| 636 } |
| 637 return Api::NewHandle(isolate, var.UserVisibleName()); |
| 638 } |
| 639 |
| 640 |
| 641 DART_EXPORT Dart_Handle Dart_VariableIsStatic(Dart_Handle variable, |
| 642 bool* is_static) { |
| 643 Isolate* isolate = Isolate::Current(); |
| 644 DARTSCOPE(isolate); |
| 645 if (is_static == NULL) { |
| 646 RETURN_NULL_ERROR(is_static); |
| 647 } |
| 648 const Field& var = Api::UnwrapFieldHandle(isolate, variable); |
| 649 if (var.IsNull()) { |
| 650 RETURN_TYPE_ERROR(isolate, variable, Field); |
| 651 } |
| 652 *is_static = var.is_static(); |
| 653 return Api::Success(); |
| 654 } |
| 655 |
| 656 |
| 657 DART_EXPORT Dart_Handle Dart_VariableIsFinal(Dart_Handle variable, |
| 658 bool* is_final) { |
| 659 Isolate* isolate = Isolate::Current(); |
| 660 DARTSCOPE(isolate); |
| 661 if (is_final == NULL) { |
| 662 RETURN_NULL_ERROR(is_final); |
| 663 } |
| 664 const Field& var = Api::UnwrapFieldHandle(isolate, variable); |
| 665 if (var.IsNull()) { |
| 666 RETURN_TYPE_ERROR(isolate, variable, Field); |
| 667 } |
| 668 *is_final = var.is_final(); |
| 669 return Api::Success(); |
| 670 } |
| 671 |
| 672 |
| 673 DART_EXPORT Dart_Handle Dart_VariableType(Dart_Handle variable) { |
| 674 Isolate* isolate = Isolate::Current(); |
| 675 DARTSCOPE(isolate); |
| 676 const Field& var = Api::UnwrapFieldHandle(isolate, variable); |
| 677 if (var.IsNull()) { |
| 678 RETURN_TYPE_ERROR(isolate, variable, Field); |
| 679 } |
| 680 |
| 681 const AbstractType& type = AbstractType::Handle(isolate, var.type()); |
| 682 return TypeToHandle(isolate, "Dart_VariableType", type); |
| 683 } |
| 684 |
| 685 |
| 686 DART_EXPORT Dart_Handle Dart_GetTypeVariableNames(Dart_Handle clazz) { |
| 687 Isolate* isolate = Isolate::Current(); |
| 688 DARTSCOPE(isolate); |
| 689 const Class& cls = Api::UnwrapClassHandle(isolate, clazz); |
| 690 if (cls.IsNull()) { |
| 691 RETURN_TYPE_ERROR(isolate, clazz, Class); |
| 692 } |
| 693 |
| 694 const intptr_t num_type_params = cls.NumTypeParameters(); |
| 695 const TypeArguments& type_params = |
| 696 TypeArguments::Handle(cls.type_parameters()); |
| 697 |
| 698 const GrowableObjectArray& names = |
| 699 GrowableObjectArray::Handle(isolate, GrowableObjectArray::New()); |
| 700 TypeParameter& type_param = TypeParameter::Handle(isolate); |
| 701 String& name = String::Handle(isolate); |
| 702 for (intptr_t i = 0; i < num_type_params; i++) { |
| 703 type_param ^= type_params.TypeAt(i); |
| 704 name = type_param.name(); |
| 705 names.Add(name); |
| 706 } |
| 707 return Api::NewHandle(isolate, Array::MakeArray(names)); |
| 708 } |
| 709 |
| 710 |
| 711 DART_EXPORT Dart_Handle Dart_LookupTypeVariable( |
| 712 Dart_Handle clazz, |
| 713 Dart_Handle type_variable_name) { |
| 714 Isolate* isolate = Isolate::Current(); |
| 715 DARTSCOPE(isolate); |
| 716 const Class& cls = Api::UnwrapClassHandle(isolate, clazz); |
| 717 if (cls.IsNull()) { |
| 718 RETURN_TYPE_ERROR(isolate, clazz, Class); |
| 719 } |
| 720 const String& var_name = Api::UnwrapStringHandle(isolate, type_variable_name); |
| 721 if (var_name.IsNull()) { |
| 722 RETURN_TYPE_ERROR(isolate, type_variable_name, String); |
| 723 } |
| 724 |
| 725 const intptr_t num_type_params = cls.NumTypeParameters(); |
| 726 const TypeArguments& type_params = |
| 727 TypeArguments::Handle(cls.type_parameters()); |
| 728 |
| 729 TypeParameter& type_param = TypeParameter::Handle(isolate); |
| 730 String& name = String::Handle(isolate); |
| 731 for (intptr_t i = 0; i < num_type_params; i++) { |
| 732 type_param ^= type_params.TypeAt(i); |
| 733 name = type_param.name(); |
| 734 if (name.Equals(var_name)) { |
| 735 return Api::NewHandle(isolate, type_param.raw()); |
| 736 } |
| 737 } |
| 738 const String& cls_name = String::Handle(cls.UserVisibleName()); |
| 739 return Api::NewError( |
| 740 "%s: Could not find type variable named '%s' for class %s.\n", |
| 741 CURRENT_FUNC, var_name.ToCString(), cls_name.ToCString()); |
| 742 } |
| 743 |
| 744 |
| 745 DART_EXPORT Dart_Handle Dart_TypeVariableName(Dart_Handle type_variable) { |
| 746 Isolate* isolate = Isolate::Current(); |
| 747 DARTSCOPE(isolate); |
| 748 const TypeParameter& type_var = |
| 749 Api::UnwrapTypeParameterHandle(isolate, type_variable); |
| 750 if (type_var.IsNull()) { |
| 751 RETURN_TYPE_ERROR(isolate, type_variable, TypeParameter); |
| 752 } |
| 753 return Api::NewHandle(isolate, type_var.name()); |
| 754 } |
| 755 |
| 756 |
| 757 DART_EXPORT Dart_Handle Dart_TypeVariableOwner(Dart_Handle type_variable) { |
| 758 Isolate* isolate = Isolate::Current(); |
| 759 DARTSCOPE(isolate); |
| 760 const TypeParameter& type_var = |
| 761 Api::UnwrapTypeParameterHandle(isolate, type_variable); |
| 762 if (type_var.IsNull()) { |
| 763 RETURN_TYPE_ERROR(isolate, type_variable, TypeParameter); |
| 764 } |
| 765 const Class& owner = Class::Handle(type_var.parameterized_class()); |
| 766 ASSERT(!owner.IsNull() && owner.IsClass()); |
| 767 return Api::NewHandle(isolate, owner.raw()); |
| 768 } |
| 769 |
| 770 |
| 771 DART_EXPORT Dart_Handle Dart_TypeVariableUpperBound(Dart_Handle type_variable) { |
| 772 Isolate* isolate = Isolate::Current(); |
| 773 DARTSCOPE(isolate); |
| 774 const TypeParameter& type_var = |
| 775 Api::UnwrapTypeParameterHandle(isolate, type_variable); |
| 776 if (type_var.IsNull()) { |
| 777 RETURN_TYPE_ERROR(isolate, type_variable, TypeParameter); |
| 778 } |
| 779 const AbstractType& bound = AbstractType::Handle(type_var.bound()); |
| 780 return TypeToHandle(isolate, "Dart_TypeVariableUpperBound", bound); |
| 781 } |
| 782 |
| 783 |
| 784 // --- Libraries Reflection --- |
| 785 |
| 786 DART_EXPORT Dart_Handle Dart_LibraryName(Dart_Handle library) { |
| 787 Isolate* isolate = Isolate::Current(); |
| 788 DARTSCOPE(isolate); |
| 789 const Library& lib = Api::UnwrapLibraryHandle(isolate, library); |
| 790 if (lib.IsNull()) { |
| 791 RETURN_TYPE_ERROR(isolate, library, Library); |
| 792 } |
| 793 const String& name = String::Handle(isolate, lib.name()); |
| 794 ASSERT(!name.IsNull()); |
| 795 return Api::NewHandle(isolate, name.raw()); |
| 796 } |
| 797 |
| 798 |
| 799 DART_EXPORT Dart_Handle Dart_LibraryGetClassNames(Dart_Handle library) { |
| 800 Isolate* isolate = Isolate::Current(); |
| 801 DARTSCOPE(isolate); |
| 802 const Library& lib = Api::UnwrapLibraryHandle(isolate, library); |
| 803 if (lib.IsNull()) { |
| 804 RETURN_TYPE_ERROR(isolate, library, Library); |
| 805 } |
| 806 |
| 807 const GrowableObjectArray& names = |
| 808 GrowableObjectArray::Handle(isolate, GrowableObjectArray::New()); |
| 809 ClassDictionaryIterator it(lib); |
| 810 Class& cls = Class::Handle(); |
| 811 String& name = String::Handle(); |
| 812 while (it.HasNext()) { |
| 813 cls = it.GetNextClass(); |
| 814 if (cls.IsSignatureClass()) { |
| 815 if (!cls.IsCanonicalSignatureClass()) { |
| 816 // This is a typedef. Add it to the list of class names. |
| 817 name = cls.UserVisibleName(); |
| 818 names.Add(name); |
| 819 } else { |
| 820 // Skip canonical signature classes. These are not named. |
| 821 } |
| 822 } else { |
| 823 name = cls.UserVisibleName(); |
| 824 names.Add(name); |
| 825 } |
| 826 } |
| 827 return Api::NewHandle(isolate, Array::MakeArray(names)); |
| 828 } |
| 829 |
| 830 |
| 831 // --- Closures Reflection --- |
| 832 |
| 833 DART_EXPORT Dart_Handle Dart_ClosureFunction(Dart_Handle closure) { |
| 834 Isolate* isolate = Isolate::Current(); |
| 835 DARTSCOPE(isolate); |
| 836 const Instance& closure_obj = Api::UnwrapInstanceHandle(isolate, closure); |
| 837 if (closure_obj.IsNull() || !closure_obj.IsClosure()) { |
| 838 RETURN_TYPE_ERROR(isolate, closure, Instance); |
| 839 } |
| 840 |
| 841 ASSERT(ClassFinalizer::AllClassesFinalized()); |
| 842 |
| 843 RawFunction* rf = Closure::function(closure_obj); |
| 844 return Api::NewHandle(isolate, rf); |
| 845 } |
| 846 |
| 847 |
| 848 // --- Metadata Reflection ---- |
| 849 |
| 850 DART_EXPORT Dart_Handle Dart_GetMetadata(Dart_Handle object) { |
| 851 Isolate* isolate = Isolate::Current(); |
| 852 CHECK_ISOLATE(isolate); |
| 853 DARTSCOPE(isolate); |
| 854 const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(object)); |
| 855 Class& cls = Class::Handle(isolate); |
| 856 if (obj.IsClass()) { |
| 857 cls ^= obj.raw(); |
| 858 } else if (obj.IsFunction()) { |
| 859 cls = Function::Cast(obj).origin(); |
| 860 } else if (obj.IsField()) { |
| 861 cls = Field::Cast(obj).origin(); |
| 862 } else { |
| 863 return Api::NewHandle(isolate, Object::empty_array().raw()); |
| 864 } |
| 865 const Library& lib = Library::Handle(cls.library()); |
| 866 return Api::NewHandle(isolate, lib.GetMetadata(obj)); |
| 867 } |
| 868 |
| 869 } // namespace dart |
OLD | NEW |