Index: runtime/vm/native_entry.cc |
diff --git a/runtime/vm/native_entry.cc b/runtime/vm/native_entry.cc |
index 2277319bb4d0e994804e5ccc14bfa656340a35a6..34ea4bf64fb5c5998f56ec9eb4c502f24e2ea5b8 100644 |
--- a/runtime/vm/native_entry.cc |
+++ b/runtime/vm/native_entry.cc |
@@ -91,6 +91,25 @@ uword NativeEntry::NativeCallWrapperEntry() { |
} |
+bool NativeEntry::ReturnValueIsError(NativeArguments* arguments) { |
+ RawObject* retval = arguments->ReturnValue(); |
+ return (retval->IsHeapObject() && |
+ RawObject::IsErrorClassId(retval->GetClassId())); |
+} |
+ |
+ |
+void NativeEntry::PropagateErrors(NativeArguments* arguments) { |
+ Thread* thread = arguments->thread(); |
+ thread->UnwindScopes(thread->top_exit_frame_info()); |
+ |
+ // The thread->zone() is different here than before we unwound. |
+ const Object& error = |
+ Object::Handle(thread->zone(), arguments->ReturnValue()); |
+ Exceptions::PropagateError(Error::Cast(error)); |
+ UNREACHABLE(); |
+} |
+ |
+ |
void NativeEntry::NativeCallWrapper(Dart_NativeArguments args, |
Dart_NativeFunction func) { |
CHECK_STACK_ALIGNMENT; |
@@ -102,6 +121,9 @@ void NativeEntry::NativeCallWrapper(Dart_NativeArguments args, |
if (!arguments->IsNativeAutoSetupScope()) { |
TransitionGeneratedToNative transition(thread); |
func(args); |
+ if (ReturnValueIsError(arguments)) { |
+ PropagateErrors(arguments); |
+ } |
} else { |
Isolate* isolate = thread->isolate(); |
ApiState* state = isolate->api_state(); |
@@ -123,6 +145,9 @@ void NativeEntry::NativeCallWrapper(Dart_NativeArguments args, |
thread->set_api_top_scope(scope); // New scope is now the top scope. |
func(args); |
+ if (ReturnValueIsError(arguments)) { |
+ PropagateErrors(arguments); |
+ } |
ASSERT(current_top_scope == scope->previous()); |
thread->set_api_top_scope(current_top_scope); // Reset top scope to prev. |