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

Unified Diff: runtime/vm/dart_api_impl.cc

Issue 10687004: Implement method and variable reflection in dart:mirrors. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/tests/vm/dart/isolate_mirror_local_test.dart ('k') | runtime/vm/dart_api_impl_test.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/dart_api_impl.cc
===================================================================
--- runtime/vm/dart_api_impl.cc (revision 9490)
+++ runtime/vm/dart_api_impl.cc (working copy)
@@ -34,6 +34,7 @@
ThreadLocalKey Api::api_native_key_ = Thread::kUnsetThreadLocalKey;
+
const char* CanonicalFunction(const char* func) {
if (strncmp(func, "dart::", 6) == 0) {
return func + 6;
@@ -42,6 +43,7 @@
}
}
+
#define RETURN_TYPE_ERROR(isolate, dart_handle, type) \
do { \
const Object& tmp = \
@@ -58,6 +60,86 @@
} while (0)
+#define RETURN_NULL_ERROR(parameter) \
+ return Api::NewError("%s expects argument '%s' to be non-null.", \
+ CURRENT_FUNC, #parameter);
+
+
+// Takes a vm internal name and makes it suitable for external user.
+//
+// Examples:
+//
+// Internal getter and setter prefices are removed:
+//
+// get:foo -> foo
+// set:foo -> foo
+//
+// Private name mangling is removed, possibly twice:
+//
+// _ReceivePortImpl@6be832b -> _ReceivePortImpl
+// _ReceivePortImpl@6be832b._internal@6be832b -> +ReceivePortImpl._internal
+//
+// The trailing . on the default constructor name is dropped:
+//
+// List. -> List
+//
+// And so forth:
+//
+// get:foo@6be832b -> foo
+// _MyClass@6b3832b. -> _MyClass
+// _MyClass@6b3832b.named -> _MyClass.named
+//
+static RawString* IdentifierPrettyName(Isolate* isolate, const String& name) {
+ intptr_t len = name.Length();
+ intptr_t start = 0;
+ intptr_t at_pos = len; // Position of '@' in the name.
+ intptr_t dot_pos = len; // Position of '.' in the name.
+
+ for (int i = 0; i < name.Length(); i++) {
+ if (name.CharAt(i) == ':') {
+ ASSERT(start == 0);
+ start = i + 1;
+ } else if (name.CharAt(i) == '@') {
+ ASSERT(at_pos == len);
+ at_pos = i;
+ } else if (name.CharAt(i) == '.') {
+ dot_pos = i;
+ break;
+ }
+ }
+ intptr_t limit = (at_pos < dot_pos ? at_pos : dot_pos);
+ if (start == 0 && limit == len) {
+ // This name is fine as it is.
+ return name.raw();
+ }
+
+ String& result = String::Handle(isolate);
+ result = String::SubString(name, start, (limit - start));
+
+ // Look for a second '@' now to correctly handle names like
+ // "_ReceivePortImpl@6be832b._internal@6be832b".
+ at_pos = len;
+ for (int i = dot_pos; i < name.Length(); i++) {
+ if (name.CharAt(i) == '@') {
+ ASSERT(at_pos == len);
+ at_pos = i;
+ }
+ }
+
+ intptr_t suffix_len = at_pos - dot_pos;
+ if (suffix_len <= 1) {
+ // The constructor name is of length 0 or 1. That means that
+ // either this isn't a constructor or that this is an unnamed
+ // constructor. In either case, we're done.
+ return result.raw();
+ }
+
+ const String& suffix =
+ String::Handle(isolate, String::SubString(name, dot_pos, suffix_len));
+ return String::Concat(result, suffix);
+}
+
+
// Return error if isolate is in an inconsistent state.
// Return NULL when no error condition exists.
//
@@ -108,7 +190,7 @@
}
RawObject* Api::UnwrapHandle(Dart_Handle object) {
-#ifdef DEBUG
+#if defined(DEBUG)
Isolate* isolate = Isolate::Current();
ASSERT(isolate != NULL);
ApiState* state = isolate->api_state();
@@ -575,8 +657,7 @@
ApiState* state = isolate->api_state();
ASSERT(state != NULL);
if (keys == NULL) {
- return Api::NewError("%s expects argument 'keys' to be non-null.",
- CURRENT_FUNC);
+ RETURN_NULL_ERROR(keys);
}
if (num_keys <= 0) {
return Api::NewError(
@@ -584,8 +665,7 @@
CURRENT_FUNC);
}
if (values == NULL) {
- return Api::NewError("%s expects argument 'values' to be non-null.",
- CURRENT_FUNC);
+ RETURN_NULL_ERROR(values);
}
if (num_values <= 0) {
return Api::NewError(
@@ -670,8 +750,7 @@
Isolate* isolate = Isolate::Current();
CHECK_ISOLATE(isolate);
if (callback == NULL) {
- return Api::NewError("%s expects argument 'callback' to be non-null.",
- CURRENT_FUNC);
+ RETURN_NULL_ERROR(callback);
}
isolate->heap()->Profile(callback, stream);
return Api::Success(isolate);
@@ -814,12 +893,10 @@
DARTSCOPE(isolate);
TIMERSCOPE(time_creating_snapshot);
if (buffer == NULL) {
- return Api::NewError("%s expects argument 'buffer' to be non-null.",
- CURRENT_FUNC);
+ RETURN_NULL_ERROR(buffer);
}
if (size == NULL) {
- return Api::NewError("%s expects argument 'size' to be non-null.",
- CURRENT_FUNC);
+ RETURN_NULL_ERROR(size);
}
const char* msg = CheckIsolateState(isolate,
ClassFinalizer::kGeneratingSnapshot);
@@ -841,12 +918,10 @@
DARTSCOPE(isolate);
TIMERSCOPE(time_creating_snapshot);
if (buffer == NULL) {
- return Api::NewError("%s expects argument 'buffer' to be non-null.",
- CURRENT_FUNC);
+ RETURN_NULL_ERROR(buffer);
}
if (size == NULL) {
- return Api::NewError("%s expects argument 'size' to be non-null.",
- CURRENT_FUNC);
+ RETURN_NULL_ERROR(size);
}
const char* msg = CheckIsolateState(isolate);
if (msg != NULL) {
@@ -1490,8 +1565,7 @@
Isolate* isolate = Isolate::Current();
DARTSCOPE(isolate);
if (str == NULL) {
- return Api::NewError("%s expects argument 'str' to be non-null.",
- CURRENT_FUNC);
+ RETURN_NULL_ERROR(str);
}
if (!Utf8::IsValid(str)) {
return Api::NewError("%s expects argument 'str' to be valid UTF-8.",
@@ -1544,8 +1618,7 @@
CURRENT_FUNC);
}
if (peer == NULL) {
- return Api::NewError("%s expects argument 'peer' to be non-null.",
- CURRENT_FUNC);
+ RETURN_NULL_ERROR(peer);
}
*peer = str.GetPeer();
return Api::Success(isolate);
@@ -1559,8 +1632,7 @@
Isolate* isolate = Isolate::Current();
DARTSCOPE(isolate);
if (codepoints == NULL && length != 0) {
- return Api::NewError("%s expects argument 'codepoints' to be non-null.",
- CURRENT_FUNC);
+ RETURN_NULL_ERROR(codepoints);
}
if (length < 0) {
return Api::NewError("%s expects argument 'length' to be greater than 0.",
@@ -1578,8 +1650,7 @@
Isolate* isolate = Isolate::Current();
DARTSCOPE(isolate);
if (codepoints == NULL && length != 0) {
- return Api::NewError("%s expects argument 'codepoints' to be non-null.",
- CURRENT_FUNC);
+ RETURN_NULL_ERROR(codepoints);
}
if (length < 0) {
return Api::NewError("%s expects argument 'length' to be greater than 0.",
@@ -1597,8 +1668,7 @@
Isolate* isolate = Isolate::Current();
DARTSCOPE(isolate);
if (codepoints == NULL && length != 0) {
- return Api::NewError("%s expects argument 'codepoints' to be non-null.",
- CURRENT_FUNC);
+ RETURN_NULL_ERROR(codepoints);
}
if (length < 0) {
return Api::NewError("%s expects argument 'length' to be greater than 0.",
@@ -1701,12 +1771,10 @@
RETURN_TYPE_ERROR(isolate, object, String);
}
if (bytes == NULL) {
- return Api::NewError("%s expects argument 'bytes' to be non-null.",
- CURRENT_FUNC);
+ RETURN_NULL_ERROR(bytes);
}
if (length == NULL) {
- return Api::NewError("%s expects argument 'length' to be non-null.",
- CURRENT_FUNC);
+ RETURN_NULL_ERROR(length);
}
const char* cstring = str.ToCString();
*length = Utf8::Length(str);
@@ -2106,8 +2174,7 @@
Isolate* isolate = Isolate::Current();
DARTSCOPE(isolate);
if (data == NULL && length != 0) {
- return Api::NewError("%s expects argument 'data' to be non-null.",
- CURRENT_FUNC);
+ RETURN_NULL_ERROR(data);
}
if (length < 0) {
return Api::NewError("%s expects argument 'length' to be greater than 0.",
@@ -2128,8 +2195,7 @@
RETURN_TYPE_ERROR(isolate, object, ExternalUint8Array);
}
if (peer == NULL) {
- return Api::NewError("%s expects argument 'peer' to be non-null.",
- CURRENT_FUNC);
+ RETURN_NULL_ERROR(peer);
}
*peer = array.GetPeer();
return Api::Success(isolate);
@@ -2407,7 +2473,8 @@
if (cls.IsNull()) {
RETURN_TYPE_ERROR(isolate, clazz, Class);
}
- return Api::NewHandle(isolate, cls.Name());
+ const String& cls_name = String::Handle(isolate, cls.Name());
+ return Api::NewHandle(isolate, IdentifierPrettyName(isolate, cls_name));
}
@@ -2419,6 +2486,14 @@
if (cls.IsNull()) {
RETURN_TYPE_ERROR(isolate, clazz, Class);
}
+
+#if defined(DEBUG)
+ const Library& lib = Library::Handle(cls.library());
+ if (lib.IsNull()) {
+ ASSERT(cls.IsDynamicClass() || cls.IsVoidClass());
+ }
+#endif
+
return Api::NewHandle(isolate, cls.library());
}
@@ -2497,6 +2572,417 @@
}
+// --- Function and Variable Reflection ---
+
+
+// Outside of the vm, we expose setter names with a trailing '='.
+static bool HasExternalSetterSuffix(const String& name) {
+ return name.CharAt(name.Length() - 1) == '=';
+}
+
+
+static RawString* AddExternalSetterSuffix(const String& name) {
+ const String& equals = String::Handle(String::NewSymbol("="));
+ return String::Concat(name, equals);
+}
+
+
+static RawString* RemoveExternalSetterSuffix(const String& name) {
+ ASSERT(HasExternalSetterSuffix(name));
+ return String::SubString(name, 0, name.Length() - 1);
+}
+
+
+DART_EXPORT Dart_Handle Dart_GetFunctionNames(Dart_Handle target) {
+ Isolate* isolate = Isolate::Current();
+ DARTSCOPE(isolate);
+ const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(target));
+ if (obj.IsError()) {
+ return target;
+ }
+
+ const GrowableObjectArray& names =
+ GrowableObjectArray::Handle(isolate, GrowableObjectArray::New());
+ Function& func = Function::Handle();
+ String& name = String::Handle();
+
+ if (obj.IsClass()) {
+ const Class& cls = Class::Cast(obj);
+ const Array& func_array = Array::Handle(cls.functions());
+
+ // Some special types like 'Dynamic' have a null functions list.
+ if (!func_array.IsNull()) {
+ for (intptr_t i = 0; i < func_array.Length(); ++i) {
+ func ^= func_array.At(i);
+
+ // Skip implicit getters and setters.
+ if (func.kind() == RawFunction::kImplicitGetter ||
+ func.kind() == RawFunction::kImplicitSetter ||
+ func.kind() == RawFunction::kConstImplicitGetter) {
+ continue;
+ }
+
+ name = func.name();
+ bool is_setter = Field::IsSetterName(name);
+ name = IdentifierPrettyName(isolate, name);
+
+ if (is_setter) {
+ name = AddExternalSetterSuffix(name);
+ }
+ names.Add(name);
+ }
+ }
+ } else if (obj.IsLibrary()) {
+ const Library& lib = Library::Cast(obj);
+ DictionaryIterator it(lib);
+ Object& obj = Object::Handle();
+ while (it.HasNext()) {
+ obj = it.GetNext();
+ if (obj.IsFunction()) {
+ func ^= obj.raw();
+ name = func.name();
+ bool is_setter = Field::IsSetterName(name);
+ name = IdentifierPrettyName(isolate, name);
+ if (is_setter) {
+ name = AddExternalSetterSuffix(name);
+ }
+ names.Add(name);
+ }
+ }
+ } else {
+ return Api::NewError(
+ "%s expects argument 'target' to be a class or library.",
+ CURRENT_FUNC);
+ }
+ return Api::NewHandle(isolate, Array::MakeArray(names));
+}
+
+
+DART_EXPORT Dart_Handle Dart_LookupFunction(Dart_Handle target,
+ Dart_Handle function_name) {
+ Isolate* isolate = Isolate::Current();
+ DARTSCOPE(isolate);
+ const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(target));
+ if (obj.IsError()) {
+ return target;
+ }
+ const String& func_name = Api::UnwrapStringHandle(isolate, function_name);
+ if (func_name.IsNull()) {
+ RETURN_TYPE_ERROR(isolate, function_name, String);
+ }
+
+ Function& func = Function::Handle(isolate);
+ String& tmp_name = String::Handle(isolate);
+ if (obj.IsClass()) {
+ const Class& cls = Class::Cast(obj);
+
+ // Case 1. Lookup the unmodified function name.
+ func = cls.LookupFunction(func_name);
+
+ // Case 2. Lookup the function without the external setter suffix
+ // '='. Make sure to do this check after the regular lookup, so
+ // that we don't interfere with operator lookups (like ==).
+ if (func.IsNull() && HasExternalSetterSuffix(func_name)) {
+ tmp_name = RemoveExternalSetterSuffix(func_name);
+ tmp_name = Field::SetterName(tmp_name);
+ func = cls.LookupFunction(tmp_name);
+ }
+
+ // Case 3. Lookup the funciton with the getter prefix prepended.
+ if (func.IsNull()) {
+ tmp_name = Field::GetterName(func_name);
+ func = cls.LookupFunction(tmp_name);
+ }
+
+ // Case 4. Lookup the function with a . appended to find the
+ // unnamed constructor.
+ if (func.IsNull()) {
+ const String& dot = String::Handle(String::NewSymbol("."));
+ tmp_name = String::Concat(func_name, dot);
+ func = cls.LookupFunction(tmp_name);
+ }
+ } else if (obj.IsLibrary()) {
+ const Library& lib = Library::Cast(obj);
+
+ // Case 1. Lookup the unmodified function name.
+ func = lib.LookupFunctionAllowPrivate(func_name);
+
+ // Case 2. Lookup the function without the external setter suffix
+ // '='. Make sure to do this check after the regular lookup, so
+ // that we don't interfere with operator lookups (like ==).
+ if (func.IsNull() && HasExternalSetterSuffix(func_name)) {
+ tmp_name = RemoveExternalSetterSuffix(func_name);
+ tmp_name = Field::SetterName(tmp_name);
+ func = lib.LookupFunctionAllowPrivate(tmp_name);
+ }
+
+ // Case 3. Lookup the funciton with the getter prefix prepended.
+ if (func.IsNull()) {
+ tmp_name = Field::GetterName(func_name);
+ func = lib.LookupFunctionAllowPrivate(tmp_name);
+ }
+ } else {
+ return Api::NewError(
+ "%s expects argument 'target' to be a class or library.",
+ CURRENT_FUNC);
+ }
+
+#if defined(DEBUG)
+ if (!func.IsNull()) {
+ // We only provide access to a subset of function kinds.
+ RawFunction::Kind func_kind = func.kind();
+ ASSERT(func_kind == RawFunction::kFunction ||
+ func_kind == RawFunction::kGetterFunction ||
+ func_kind == RawFunction::kSetterFunction ||
+ func_kind == RawFunction::kConstructor ||
+ func_kind == RawFunction::kAbstract);
+ }
+#endif
+ return Api::NewHandle(isolate, func.raw());
+}
+
+
+DART_EXPORT bool Dart_IsFunction(Dart_Handle handle) {
+ return Api::ClassId(handle) == kFunction;
+}
+
+
+DART_EXPORT Dart_Handle Dart_FunctionName(Dart_Handle function) {
+ Isolate* isolate = Isolate::Current();
+ DARTSCOPE(isolate);
+ const Function& func = Api::UnwrapFunctionHandle(isolate, function);
+ if (func.IsNull()) {
+ RETURN_TYPE_ERROR(isolate, function, Function);
+ }
+ String& func_name = String::Handle(isolate);
+ func_name = func.name();
+ bool is_setter = Field::IsSetterName(func_name);
+ func_name = IdentifierPrettyName(isolate, func_name);
+ if (is_setter) {
+ func_name = AddExternalSetterSuffix(func_name);
+ }
+ return Api::NewHandle(isolate, func_name.raw());
+}
+
+
+DART_EXPORT Dart_Handle Dart_FunctionIsAbstract(Dart_Handle function,
+ bool* is_abstract) {
+ Isolate* isolate = Isolate::Current();
+ DARTSCOPE(isolate);
+ if (is_abstract == NULL) {
+ RETURN_NULL_ERROR(is_abstract);
+ }
+ const Function& func = Api::UnwrapFunctionHandle(isolate, function);
+ if (func.IsNull()) {
+ RETURN_TYPE_ERROR(isolate, function, Function);
+ }
+ *is_abstract = (func.kind() == RawFunction::kAbstract);
+ return Api::Success(isolate);
+}
+
+
+DART_EXPORT Dart_Handle Dart_FunctionIsStatic(Dart_Handle function,
+ bool* is_static) {
+ Isolate* isolate = Isolate::Current();
+ DARTSCOPE(isolate);
+ if (is_static == NULL) {
+ RETURN_NULL_ERROR(is_static);
+ }
+ const Function& func = Api::UnwrapFunctionHandle(isolate, function);
+ if (func.IsNull()) {
+ RETURN_TYPE_ERROR(isolate, function, Function);
+ }
+ *is_static = func.is_static();
+ return Api::Success(isolate);
+}
+
+
+DART_EXPORT Dart_Handle Dart_FunctionIsConstructor(Dart_Handle function,
+ bool* is_constructor) {
+ Isolate* isolate = Isolate::Current();
+ DARTSCOPE(isolate);
+ if (is_constructor == NULL) {
+ RETURN_NULL_ERROR(is_constructor);
+ }
+ const Function& func = Api::UnwrapFunctionHandle(isolate, function);
+ if (func.IsNull()) {
+ RETURN_TYPE_ERROR(isolate, function, Function);
+ }
+ *is_constructor = func.kind() == RawFunction::kConstructor;
+ return Api::Success(isolate);
+}
+
+
+DART_EXPORT Dart_Handle Dart_FunctionIsGetter(Dart_Handle function,
+ bool* is_getter) {
+ Isolate* isolate = Isolate::Current();
+ DARTSCOPE(isolate);
+ if (is_getter == NULL) {
+ RETURN_NULL_ERROR(is_getter);
+ }
+ const Function& func = Api::UnwrapFunctionHandle(isolate, function);
+ if (func.IsNull()) {
+ RETURN_TYPE_ERROR(isolate, function, Function);
+ }
+ // TODO(turnidge): It would be nice if I could just use func.kind()
+ // to check for a getter function here, but unfortunately the only
+ // way to distinguish abstract getter functions is to use the name
+ // itself. Consider adding a RawFunction::kAbstractGetter type.
+ const String& func_name = String::Handle(isolate, func.name());
+ *is_getter = Field::IsGetterName(func_name);
+
+ return Api::Success(isolate);
+}
+
+
+DART_EXPORT Dart_Handle Dart_FunctionIsSetter(Dart_Handle function,
+ bool* is_setter) {
+ Isolate* isolate = Isolate::Current();
+ DARTSCOPE(isolate);
+ if (is_setter == NULL) {
+ RETURN_NULL_ERROR(is_setter);
+ }
+ const Function& func = Api::UnwrapFunctionHandle(isolate, function);
+ if (func.IsNull()) {
+ RETURN_TYPE_ERROR(isolate, function, Function);
+ }
+ // TODO(turnidge): It would be nice if I could just use func.kind()
+ // to check for a setter function here, but unfortunately the only
+ // way to distinguish abstract setter functions is to use the name
+ // itself. Consider adding a RawFunction::kAbstractSetter type.
+ const String& func_name = String::Handle(isolate, func.name());
+ *is_setter = Field::IsSetterName(func_name);
+
+ return Api::Success(isolate);
+}
+
+
+DART_EXPORT Dart_Handle Dart_GetVariableNames(Dart_Handle target) {
+ Isolate* isolate = Isolate::Current();
+ DARTSCOPE(isolate);
+ const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(target));
+ if (obj.IsError()) {
+ return target;
+ }
+
+ const GrowableObjectArray& names =
+ GrowableObjectArray::Handle(isolate, GrowableObjectArray::New());
+ Field& field = Field::Handle(isolate);
+ String& name = String::Handle(isolate);
+
+ if (obj.IsClass()) {
+ const Class& cls = Class::Cast(obj);
+ const Array& field_array = Array::Handle(cls.fields());
+
+ // Some special types like 'Dynamic' have a null fields list.
+ //
+ // TODO(turnidge): Fix 'Dynamic' so that it does not have a null
+ // fields list. This will have to wait until the empty array is
+ // allocated in the vm isolate.
+ if (!field_array.IsNull()) {
+ for (intptr_t i = 0; i < field_array.Length(); ++i) {
+ field ^= field_array.At(i);
+ name = field.name();
+ name = IdentifierPrettyName(isolate, name);
+ names.Add(name);
+ }
+ }
+ } else if (obj.IsLibrary()) {
+ const Library& lib = Library::Cast(obj);
+ DictionaryIterator it(lib);
+ Object& obj = Object::Handle(isolate);
+ while (it.HasNext()) {
+ obj = it.GetNext();
+ if (obj.IsField()) {
+ field ^= obj.raw();
+ name = field.name();
+ name = IdentifierPrettyName(isolate, name);
+ names.Add(name);
+ }
+ }
+ } else {
+ return Api::NewError(
+ "%s expects argument 'target' to be a class or library.",
+ CURRENT_FUNC);
+ }
+ return Api::NewHandle(isolate, Array::MakeArray(names));
+}
+
+
+DART_EXPORT Dart_Handle Dart_LookupVariable(Dart_Handle target,
+ Dart_Handle variable_name) {
+ Isolate* isolate = Isolate::Current();
+ DARTSCOPE(isolate);
+ const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(target));
+ if (obj.IsError()) {
+ return target;
+ }
+ const String& var_name = Api::UnwrapStringHandle(isolate, variable_name);
+ if (var_name.IsNull()) {
+ RETURN_TYPE_ERROR(isolate, variable_name, String);
+ }
+ if (obj.IsClass()) {
+ const Class& cls = Class::Cast(obj);
+ return Api::NewHandle(isolate, cls.LookupField(var_name));
+ }
+ if (obj.IsLibrary()) {
+ const Library& lib = Library::Cast(obj);
+ return Api::NewHandle(isolate, lib.LookupFieldAllowPrivate(var_name));
+ }
+ return Api::NewError(
+ "%s expects argument 'target' to be a class or library.",
+ CURRENT_FUNC);
+}
+
+
+DART_EXPORT bool Dart_IsVariable(Dart_Handle handle) {
+ return Api::ClassId(handle) == kField;
+}
+
+
+DART_EXPORT Dart_Handle Dart_VariableName(Dart_Handle variable) {
+ Isolate* isolate = Isolate::Current();
+ DARTSCOPE(isolate);
+ const Field& var = Api::UnwrapFieldHandle(isolate, variable);
+ if (var.IsNull()) {
+ RETURN_TYPE_ERROR(isolate, variable, Field);
+ }
+ const String& var_name = String::Handle(var.name());
+ return Api::NewHandle(isolate, IdentifierPrettyName(isolate, var_name));
+}
+
+
+DART_EXPORT Dart_Handle Dart_VariableIsStatic(Dart_Handle variable,
+ bool* is_static) {
+ Isolate* isolate = Isolate::Current();
+ DARTSCOPE(isolate);
+ if (is_static == NULL) {
+ RETURN_NULL_ERROR(is_static);
+ }
+ const Field& var = Api::UnwrapFieldHandle(isolate, variable);
+ if (var.IsNull()) {
+ RETURN_TYPE_ERROR(isolate, variable, Field);
+ }
+ *is_static = var.is_static();
+ return Api::Success(isolate);
+}
+
+
+DART_EXPORT Dart_Handle Dart_VariableIsFinal(Dart_Handle variable,
+ bool* is_final) {
+ Isolate* isolate = Isolate::Current();
+ DARTSCOPE(isolate);
+ if (is_final == NULL) {
+ RETURN_NULL_ERROR(is_final);
+ }
+ const Field& var = Api::UnwrapFieldHandle(isolate, variable);
+ if (var.IsNull()) {
+ RETURN_TYPE_ERROR(isolate, variable, Field);
+ }
+ *is_final = var.is_final();
+ return Api::Success(isolate);
+}
+
// --- Constructors, Methods, and Fields ---
@@ -3333,8 +3819,7 @@
DARTSCOPE(isolate);
TIMERSCOPE(time_script_loading);
if (buffer == NULL) {
- return Api::NewError("%s expects argument 'buffer' to be non-null.",
- CURRENT_FUNC);
+ RETURN_NULL_ERROR(buffer);
}
const Snapshot* snapshot = Snapshot::SetupFromBuffer(buffer);
if (!snapshot->IsScriptSnapshot()) {
@@ -3464,8 +3949,15 @@
String& name = String::Handle();
while (it.HasNext()) {
cls = it.GetNextClass();
- name = cls.Name();
- names.Add(name);
+ // For now we suppress the signature classes of closures.
+ //
+ // TODO(turnidge): Add this to the unit test.
+ const Function& signature_func = Function::Handle(cls.signature_function());
+ if (signature_func.IsNull()) {
+ name = cls.Name();
+ name = IdentifierPrettyName(isolate, name);
+ names.Add(name);
+ }
}
return Api::NewHandle(isolate, Array::MakeArray(names));
}
« no previous file with comments | « runtime/tests/vm/dart/isolate_mirror_local_test.dart ('k') | runtime/vm/dart_api_impl_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698