Chromium Code Reviews| Index: runtime/vm/dart_api_impl.cc |
| =================================================================== |
| --- runtime/vm/dart_api_impl.cc (revision 1328) |
| +++ runtime/vm/dart_api_impl.cc (working copy) |
| @@ -27,43 +27,138 @@ |
| namespace dart { |
| -DART_EXPORT bool Dart_IsValid(const Dart_Handle& handle) { |
| +DART_EXPORT bool Dart_IsError(const Dart_Handle& handle) { |
| ASSERT(Isolate::Current() != NULL); |
| Zone zone; // Setup a VM zone as we are creating some handles. |
| HandleScope scope; // Setup a VM handle scope. |
| + const Object& obj = Object::Handle(Api::UnwrapHandle(handle)); |
| + return obj.IsApiError(); |
| +} |
| - // Make sure that the object isn't an ApiFailure. |
| + |
| +DART_EXPORT bool Dart_IsUnhandledException(Dart_Handle handle) { |
| + Zone zone; // Setup a VM zone as we are creating some handles. |
| + HandleScope scope; // Setup a VM handle scope. |
| const Object& obj = Object::Handle(Api::UnwrapHandle(handle)); |
| - return !obj.IsApiFailure(); |
| + if (obj.IsApiError()) { |
| + ApiError& failure = ApiError::Handle(); |
| + failure ^= obj.raw(); |
|
Anton Muhin
2011/11/09 12:34:03
may you used const ApiError& = ApiError::Handle(ob
turnidge
2011/11/09 19:53:41
Done.
Anton Muhin
2011/11/10 08:28:39
Thanks. There are ways more instance of the same
turnidge
2011/11/10 20:59:13
To get this to work I need to use CheckedHandle.
|
| + const Object& data = Object::Handle(failure.data()); |
| + return data.IsUnhandledException(); |
| + } |
| + return false; |
| } |
| -DART_EXPORT void _Dart_ReportInvalidHandle(const char* file, |
| +DART_EXPORT Dart_Handle Dart_GetException(Dart_Handle handle) { |
| + Zone zone; // Setup a VM zone as we are creating some handles. |
| + HandleScope scope; // Setup a VM handle scope. |
| + const Object& obj = Object::Handle(Api::UnwrapHandle(handle)); |
| + if (obj.IsApiError()) { |
| + ApiError& failure = ApiError::Handle(); |
| + failure ^= obj.raw(); |
| + const Object& data = Object::Handle(failure.data()); |
| + if (data.IsUnhandledException()) { |
| + const UnhandledException& unhandled = UnhandledException::Handle( |
| + reinterpret_cast<RawUnhandledException*>(data.raw())); |
| + const Object& exception = Object::Handle(unhandled.exception()); |
| + return Api::NewLocalHandle(exception); |
| + } else { |
| + return Api::Error("This error is not an unhandled exception error."); |
| + } |
| + } else { |
| + return Api::Error("Can only get exceptions from error handles."); |
| + } |
| +} |
| + |
| + |
| +DART_EXPORT Dart_Handle Dart_GetStacktrace(Dart_Handle handle) { |
| + Zone zone; // Setup a VM zone as we are creating some handles. |
| + HandleScope scope; // Setup a VM handle scope. |
| + const Object& obj = Object::Handle(Api::UnwrapHandle(handle)); |
| + if (obj.IsApiError()) { |
| + ApiError& failure = ApiError::Handle(); |
| + failure ^= obj.raw(); |
| + const Object& data = Object::Handle(failure.data()); |
| + if (data.IsUnhandledException()) { |
| + const UnhandledException& unhandled = UnhandledException::Handle( |
| + reinterpret_cast<RawUnhandledException*>(data.raw())); |
| + const Object& stacktrace = Object::Handle(unhandled.stacktrace()); |
| + return Api::NewLocalHandle(stacktrace); |
| + } else { |
| + return Api::Error("This error is not an unhandled exception error."); |
| + } |
| + } else { |
| + return Api::Error("Can only get stacktraces from error handles."); |
| + } |
| +} |
| + |
| + |
| +DART_EXPORT void _Dart_ReportErrorHandle(const char* file, |
| int line, |
| const char* handle, |
| const char* message) { |
| - fprintf(stderr, "%s:%d: invalid handle: '%s':\n '%s'\n", |
| + fprintf(stderr, "%s:%d: error handle: '%s':\n '%s'\n", |
| file, line, handle, message); |
| OS::Abort(); |
| } |
| +static const char* MakeUnhandledExceptionCString( |
| + const UnhandledException& uhe) { |
| + const Instance& exception = Instance::Handle(uhe.exception()); |
| + Object& strtmp = Object::Handle(DartLibraryCalls::ToString(exception)); |
|
Anton Muhin
2011/11/09 12:34:03
this is a typical paranoia and DartLibraryCalls::T
turnidge
2011/11/09 19:53:41
Done.
|
| + const char* exc_str = |
| + "<Received exception while converting exception to string>"; |
| + if (strtmp.IsString()) { |
| + exc_str = strtmp.ToCString(); |
| + } |
| + |
| + const Instance& stack = Instance::Handle(uhe.stacktrace()); |
| + strtmp = DartLibraryCalls::ToString(stack); |
| + const char* stack_str = |
| + "<Received exception while converting stacktrace to string>"; |
| + if (strtmp.IsString()) { |
| + stack_str = strtmp.ToCString(); |
| + } |
| + |
| + const char* format = "Unhandled exception:\n%s\n%s"; |
| + int len = strlen(exc_str) + strlen(stack_str) + strlen(format) - 2; |
|
Anton Muhin
2011/11/09 12:34:03
why - 2, to account for %s? if yes, shouldn't it
Anton Muhin
2011/11/09 12:34:03
maybe add + 1 into len as well not to duplicate it
turnidge
2011/11/09 19:53:41
Sorry, brain spasm there. Reworked this to be mor
|
| + char* buffer = reinterpret_cast<char*>(Api::Allocate(len + 1)); |
| + OS::SNPrint(buffer, (len + 1), format, exc_str, stack_str); |
| + return buffer; |
| +} |
| + |
| + |
| DART_EXPORT const char* Dart_GetError(const Dart_Handle& handle) { |
| ASSERT(Isolate::Current() != NULL); |
| Zone zone; // Setup a VM zone as we are creating some handles. |
| HandleScope scope; // Setup a VM handle scope. |
| const Object& obj = Object::Handle(Api::UnwrapHandle(handle)); |
| - if (!obj.IsApiFailure()) { |
| + if (!obj.IsApiError()) { |
| return ""; |
| } |
| - ApiFailure& failure = ApiFailure::Handle(); |
| + ApiError& failure = ApiError::Handle(); |
| failure ^= obj.raw(); |
| - const String& message = String::Handle(failure.message()); |
| - const char* msg = message.ToCString(); |
| - intptr_t len = strlen(msg) + 1; |
| - char* msg_copy = reinterpret_cast<char*>(Api::Allocate(len)); |
| - OS::SNPrint(msg_copy, len, "%s", msg); |
| - return msg_copy; |
| + const Object& data = Object::Handle(failure.data()); |
| + if (data.IsString()) { |
| + // Simple error message. |
| + String& message = String::Handle(); |
| + message ^= failure.data(); |
| + const char* msg = message.ToCString(); |
| + intptr_t len = strlen(msg) + 1; |
| + char* msg_copy = reinterpret_cast<char*>(Api::Allocate(len)); |
| + OS::SNPrint(msg_copy, len, "%s", msg); |
|
Anton Muhin
2011/11/09 12:34:03
I see you're keeping old code, but strncpy (unless
turnidge
2011/11/09 19:53:41
Um, fixed.
|
| + return msg_copy; |
| + |
| + } else if (data.IsUnhandledException()) { |
| + UnhandledException& uhe = UnhandledException::Handle(); |
| + uhe ^= data.raw(); |
| + return MakeUnhandledExceptionCString(uhe); |
| + |
| + } else { |
| + return "<Internal error in Dart_GetError: malformed error handle>"; |
| + } |
| } |
| @@ -141,7 +236,7 @@ |
| // may get deallocated when we return back from the Dart API call. |
| const String& error = String::Handle( |
| Isolate::Current()->object_store()->sticky_error()); |
| - const Object& obj = Object::Handle(ApiFailure::New(error)); |
| + const Object& obj = Object::Handle(ApiError::New(error)); |
| *handle = Api::NewLocalHandle(obj); |
| } |
| @@ -172,22 +267,9 @@ |
| } |
| -static void ProcessUnhandledException(const UnhandledException& uhe) { |
| - const Instance& exception = Instance::Handle(uhe.exception()); |
| - Instance& strtmp = Instance::Handle(DartLibraryCalls::ToString(exception)); |
| - const char* str = strtmp.ToCString(); |
| - fprintf(stderr, "%s\n", str); |
| - const Instance& stack = Instance::Handle(uhe.stacktrace()); |
| - strtmp = DartLibraryCalls::ToString(stack); |
| - str = strtmp.ToCString(); |
| - fprintf(stderr, "%s\n", str); |
| - exit(255); |
| -} |
| - |
| - |
| -DART_EXPORT void Dart_HandleMessage(Dart_Port dest_port, |
| - Dart_Port reply_port, |
| - Dart_Message dart_message) { |
| +DART_EXPORT Dart_Handle Dart_HandleMessage(Dart_Port dest_port, |
| + Dart_Port reply_port, |
| + Dart_Message dart_message) { |
| Zone zone; // Setup a VM zone as we are creating some handles. |
| HandleScope scope; // Setup a VM handle scope. |
| const Instance& msg = Instance::Handle(DeserializeMessage(dart_message)); |
| @@ -211,14 +293,10 @@ |
| const Object& result = Object::Handle( |
| DartEntry::InvokeStatic(function, arguments, kNoArgumentNames)); |
| if (result.IsUnhandledException()) { |
| - UnhandledException& uhe = UnhandledException::Handle(); |
| - uhe ^= result.raw(); |
| - // TODO(turnidge): Instead of exiting here, just return the |
| - // exception so that the embedder can choose how to handle this |
| - // case. |
| - ProcessUnhandledException(uhe); |
| + return Api::ErrorFromException(result); |
| } |
| ASSERT(result.IsNull()); |
| + return Api::Success(); |
| } |
| @@ -448,7 +526,7 @@ |
| receiver ^= obj.raw(); |
| result = DartLibraryCalls::ToString(receiver); |
| if (result.IsUnhandledException()) { |
| - return Api::Error("An exception occurred when converting to string"); |
| + return Api::ErrorFromException(result); |
| } |
| } else { |
| // This is a VM internal object. Call the C++ method of printing. |
| @@ -510,8 +588,10 @@ |
| b ^= result.raw(); |
| *value = b.value(); |
| return Api::Success(); |
| + } else if (result.IsUnhandledException()) { |
| + return Api::ErrorFromException(result); |
| } else { |
| - return Api::Error("An exception occured when calling '=='"); |
| + return Api::Error("Expected boolean result from =="); |
| } |
| } |
| @@ -981,6 +1061,8 @@ |
| result = Api::Error("Length of List object is greater than the " |
| "maximum value that 'len' parameter can hold"); |
| } |
| + } else if (retval.IsUnhandledException()) { |
| + result = Api::ErrorFromException(retval); |
| } else { |
| result = Api::Error("Length of List object is not an integer"); |
| } |
| @@ -1015,7 +1097,7 @@ |
| args, |
| kNoArgumentNames); |
| if (retval.IsUnhandledException()) { |
| - *result = Api::Error("Unexpected exception in '[]'"); |
| + *result = Api::ErrorFromException(retval); |
| } else { |
| *result = Api::Success(); |
| } |
| @@ -1068,7 +1150,7 @@ |
| for (int i = 0; i < length; i++) { |
| intobj = Integer::New(offset + i); |
| element = GetListAt(isolate, instance, intobj, function, &result); |
| - if (!Dart_IsValid(result)) { |
| + if (Dart_IsError(result)) { |
| return result; // Error condition. |
| } |
| intobj ^= element.raw(); |
| @@ -1111,7 +1193,7 @@ |
| Dart_Handle result; |
| indexobj = Integer::New(index); |
| element = GetListAt(isolate, instance, indexobj, function, &result); |
| - if (!Dart_IsValid(result)) { |
| + if (Dart_IsError(result)) { |
| return result; // Error condition. |
| } |
| return Api::NewLocalHandle(element); |
| @@ -1143,7 +1225,7 @@ |
| args, |
| kNoArgumentNames); |
| if (retval.IsUnhandledException()) { |
| - *result = Api::Error("Unexpected exception in '[]='"); |
| + *result = Api::ErrorFromException(retval); |
| } else { |
| *result = Api::Success(); |
| } |
| @@ -1190,7 +1272,7 @@ |
| indexobj = Integer::New(offset + i); |
| valueobj ^= Integer::New(native_array[i]); |
| SetListAt(isolate, instance, indexobj, valueobj, function, &result); |
| - if (!Dart_IsValid(result)) { |
| + if (Dart_IsError(result)) { |
| return result; // Error condition. |
| } |
| } |
| @@ -1252,7 +1334,11 @@ |
| const Array& kNoArgumentNames = Array::Handle(); |
| const Instance& retval = Instance::Handle( |
| DartEntry::InvokeStatic(function, args, kNoArgumentNames)); |
| - *result = Api::NewLocalHandle(retval); |
| + if (retval.IsUnhandledException()) { |
| + *result = Api::ErrorFromException(retval); |
| + } else { |
| + *result = Api::NewLocalHandle(retval); |
| + } |
| } else { |
| SetupErrorResult(result); |
| } |
| @@ -1276,7 +1362,11 @@ |
| const Array& kNoArgumentNames = Array::Handle(); |
| const Instance& retval = Instance::Handle( |
| DartEntry::InvokeDynamic(receiver, function, args, kNoArgumentNames)); |
| - *result = Api::NewLocalHandle(retval); |
| + if (retval.IsUnhandledException()) { |
| + *result = Api::ErrorFromException(retval); |
| + } else { |
| + *result = Api::NewLocalHandle(retval); |
| + } |
| } else { |
| SetupErrorResult(result); |
| } |
| @@ -1299,7 +1389,11 @@ |
| const Array& kNoArgumentNames = Array::Handle(); |
| const Instance& retval = Instance::Handle( |
| DartEntry::InvokeClosure(closure, args, kNoArgumentNames)); |
| - *result = Api::NewLocalHandle(retval); |
| + if (retval.IsUnhandledException()) { |
| + *result = Api::ErrorFromException(retval); |
| + } else { |
| + *result = Api::NewLocalHandle(retval); |
| + } |
| } else { |
| SetupErrorResult(result); |
| } |
| @@ -1463,42 +1557,6 @@ |
| } |
| -DART_EXPORT bool Dart_ExceptionOccurred(Dart_Handle result) { |
| - Zone zone; // Setup a VM zone as we are creating some handles. |
| - HandleScope scope; // Setup a VM handle scope. |
| - const Object& retval = Object::Handle(Api::UnwrapHandle(result)); |
| - return retval.IsUnhandledException(); |
| -} |
| - |
| - |
| -DART_EXPORT Dart_Handle Dart_GetException(Dart_Handle result) { |
| - Zone zone; // Setup a VM zone as we are creating some handles. |
| - HandleScope scope; // Setup a VM handle scope. |
| - const Object& retval = Object::Handle(Api::UnwrapHandle(result)); |
| - if (retval.IsUnhandledException()) { |
| - const UnhandledException& unhandled = UnhandledException::Handle( |
| - reinterpret_cast<RawUnhandledException*>(retval.raw())); |
| - const Object& exception = Object::Handle(unhandled.exception()); |
| - return Api::NewLocalHandle(exception); |
| - } |
| - return Api::Error("Object is not an unhandled exception object"); |
| -} |
| - |
| - |
| -DART_EXPORT Dart_Handle Dart_GetStacktrace(Dart_Handle unhandled_excp) { |
| - Zone zone; // Setup a VM zone as we are creating some handles. |
| - HandleScope scope; // Setup a VM handle scope. |
| - const Object& retval = Object::Handle(Api::UnwrapHandle(unhandled_excp)); |
| - if (retval.IsUnhandledException()) { |
| - const UnhandledException& unhandled = UnhandledException::Handle( |
| - reinterpret_cast<RawUnhandledException*>(retval.raw())); |
| - const Object& stacktrace = Object::Handle(unhandled.stacktrace()); |
| - return Api::NewLocalHandle(stacktrace); |
| - } |
| - return Api::Error("Object is not an unhandled exception object"); |
| -} |
| - |
| - |
| DART_EXPORT Dart_Handle Dart_ThrowException(Dart_Handle exception) { |
| Isolate* isolate = Isolate::Current(); |
| ASSERT(isolate != NULL); |
| @@ -1695,7 +1753,7 @@ |
| Zone zone; // Setup a VM zone as we are creating some handles. |
| HandleScope scope; // Setup a VM handle scope. |
| Dart_Handle result = LookupStaticField(cls, name, kGetter); |
| - if (!::Dart_IsValid(result)) { |
| + if (::Dart_IsError(result)) { |
| return result; |
| } |
| Object& retval = Object::Handle(); |
| @@ -1710,25 +1768,20 @@ |
| func ^= obj.raw(); |
| GrowableArray<const Object*> args; |
| InvokeStatic(func, args, &result); |
| - if (::Dart_IsValid(result)) { |
| - if (Dart_ExceptionOccurred(result)) { |
| - return Api::Error( |
| - "An exception occurred when getting the static field"); |
| - } |
| - } |
| return result; |
| } |
| } |
| // TODO(iposva): The value parameter should be documented as being an instance. |
| +// TODO(turnidge): Is this skipping the setter? |
| DART_EXPORT Dart_Handle Dart_SetStaticField(Dart_Handle cls, |
| Dart_Handle name, |
| Dart_Handle value) { |
| Zone zone; // Setup a VM zone as we are creating some handles. |
| HandleScope scope; // Setup a VM handle scope. |
| Dart_Handle result = LookupStaticField(cls, name, kSetter); |
| - if (!::Dart_IsValid(result)) { |
| + if (::Dart_IsError(result)) { |
| return result; |
| } |
| Field& fld = Field::Handle(); |
| @@ -1755,19 +1808,13 @@ |
| Instance& object = Instance::Handle(); |
| object ^= param.raw(); |
| Dart_Handle result = LookupInstanceField(object, name, kGetter); |
| - if (!::Dart_IsValid(result)) { |
| + if (::Dart_IsError(result)) { |
| return result; |
| } |
| Function& func = Function::Handle(); |
| func ^= Api::UnwrapHandle(result); |
| GrowableArray<const Object*> arguments; |
| InvokeDynamic(object, func, arguments, &result); |
| - if (::Dart_IsValid(result)) { |
| - if (Dart_ExceptionOccurred(result)) { |
| - return Api::Error( |
| - "An exception occurred when accessing the instance field"); |
| - } |
| - } |
| return result; |
| } |
| @@ -1784,7 +1831,7 @@ |
| Instance& object = Instance::Handle(); |
| object ^= param.raw(); |
| Dart_Handle result = LookupInstanceField(object, name, kSetter); |
| - if (!::Dart_IsValid(result)) { |
| + if (::Dart_IsError(result)) { |
| return result; |
| } |
| Function& func = Function::Handle(); |
| @@ -1793,12 +1840,6 @@ |
| const Object& arg = Object::Handle(Api::UnwrapHandle(value)); |
| arguments.Add(&arg); |
| InvokeDynamic(object, func, arguments, &result); |
| - if (::Dart_IsValid(result)) { |
| - if (Dart_ExceptionOccurred(result)) { |
| - return Api::Error( |
| - "An exception occurred when setting the instance field"); |
| - } |
| - } |
| return result; |
| } |
| @@ -2034,7 +2075,7 @@ |
| OS::VSNPrint(buffer, (len + 1), format, args); |
| const String& message = String::Handle(String::New(buffer)); |
| - const Object& obj = Object::Handle(ApiFailure::New(message)); |
| + const Object& obj = Object::Handle(ApiError::New(message)); |
| return Api::NewLocalHandle(obj); |
| } |
| @@ -2048,6 +2089,22 @@ |
| } |
| +Dart_Handle Api::ErrorFromException(const Object& obj) { |
| + Zone zone; // Setup a VM zone as we are creating some handles. |
| + HandleScope scope; // Setup a VM handle scope. |
| + |
| + ASSERT(obj.IsUnhandledException()); |
| + if (obj.IsUnhandledException()) { |
| + UnhandledException& uhe = UnhandledException::Handle(); |
| + uhe ^= obj.raw(); |
| + const Object& error = Object::Handle(ApiError::New(uhe)); |
| + return Api::NewLocalHandle(error); |
| + } else { |
| + return Api::Error("Internal error: expected obj.IsUnhandledException()."); |
| + } |
| +} |
| + |
| + |
| Dart_Handle Api::Null() { |
| Isolate* isolate = Isolate::Current(); |
| ASSERT(isolate != NULL); |