Add DartStickyError utility class
Change-Id: I079c58cc3341abb04de4eaf08a4f99bc59ef692d
diff --git a/BUILD.gn b/BUILD.gn
index 67cf7ef..b51765c 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -20,6 +20,8 @@
"dart_persistent_value.h",
"dart_state.cc",
"dart_state.h",
+ "dart_sticky_error.cc",
+ "dart_sticky_error.h",
"dart_wrappable.cc",
"dart_wrappable.h",
"dart_wrapper_info.h",
diff --git a/dart_message_handler.cc b/dart_message_handler.cc
index 6528fd3..53fbdf4 100644
--- a/dart_message_handler.cc
+++ b/dart_message_handler.cc
@@ -10,6 +10,7 @@
#include "lib/ftl/logging.h"
#include "lib/tonic/logging/dart_error.h"
#include "lib/tonic/dart_state.h"
+#include "lib/tonic/dart_sticky_error.h"
namespace tonic {
@@ -82,6 +83,11 @@
}
Dart_SetPausedOnExit(false);
}
+ } else if (DartStickyError::IsSet()) {
+ // Only process service messages if we have a sticky error set.
+ if (Dart_HasServiceMessages()) {
+ Dart_HandleServiceMessages();
+ }
} else {
// We are processing messages normally.
result = Dart_HandleMessages();
@@ -89,10 +95,9 @@
}
if (error) {
- if (!Dart_HasStickyError() && Dart_IsUnhandledExceptionError(result)) {
+ if (DartStickyError::MaybeSet(result)) {
// Remember that we had an uncaught exception error.
isolate_had_uncaught_exception_error_ = true;
- Dart_SetStickyError(result);
}
} else if (!Dart_HasLivePorts()) {
// The isolate has no live ports and would like to exit.
diff --git a/dart_microtask_queue.cc b/dart_microtask_queue.cc
index 8caaf9a..182a94a 100644
--- a/dart_microtask_queue.cc
+++ b/dart_microtask_queue.cc
@@ -9,6 +9,7 @@
#include "lib/tonic/logging/dart_invoke.h"
#include "lib/tonic/dart_persistent_value.h"
#include "lib/tonic/dart_state.h"
+#include "lib/tonic/dart_sticky_error.h"
namespace tonic {
namespace {
@@ -36,7 +37,14 @@
if (!dart_state.get())
continue;
DartState::Scope dart_scope(dart_state.get());
- DartInvokeVoid(callback.value());
+ if (DartStickyError::IsSet()) {
+ break;
+ }
+ Dart_Handle result = DartInvokeVoid(callback.value());
+ // Let the isolate remember any uncaught exceptions.
+ if (DartStickyError::MaybeSet(result)) {
+ break;
+ }
}
}
}
diff --git a/dart_sticky_error.cc b/dart_sticky_error.cc
new file mode 100644
index 0000000..c232948
--- /dev/null
+++ b/dart_sticky_error.cc
@@ -0,0 +1,29 @@
+// Copyright 2016 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "lib/tonic/dart_sticky_error.h"
+
+namespace tonic {
+
+bool DartStickyError::MaybeSet(Dart_Handle result) {
+ if (!Dart_IsError(result)) {
+ // Not an error.
+ return false;
+ }
+ if (Dart_HasStickyError()) {
+ // We only remember the first error.
+ return false;
+ }
+ if (!Dart_IsUnhandledExceptionError(result)) {
+ result = Dart_NewUnhandledExceptionError(result);
+ }
+ Dart_SetStickyError(result);
+ return true;
+}
+
+bool DartStickyError::IsSet() {
+ return Dart_HasStickyError();
+}
+
+} // namespace tonic
diff --git a/dart_sticky_error.h b/dart_sticky_error.h
new file mode 100644
index 0000000..3064849
--- /dev/null
+++ b/dart_sticky_error.h
@@ -0,0 +1,23 @@
+// Copyright 2016 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef LIB_TONIC_DART_STICKY_ERROR_H_
+#define LIB_TONIC_DART_STICKY_ERROR_H_
+
+#include "dart/runtime/include/dart_api.h"
+
+namespace tonic {
+
+class DartStickyError {
+ public:
+ // Returns true if the sticky error was set.
+ static bool MaybeSet(Dart_Handle result);
+
+ // Returns true if the isolate has a sticky error set.
+ static bool IsSet();
+};
+
+} // namespace tonic
+
+#endif // LIB_TONIC_DART_MICROTASK_QUEUE_H_
diff --git a/logging/dart_invoke.cc b/logging/dart_invoke.cc
index 8f86e88..87406f3 100644
--- a/logging/dart_invoke.cc
+++ b/logging/dart_invoke.cc
@@ -24,9 +24,10 @@
LogIfError(handle);
}
-void DartInvokeVoid(Dart_Handle closure) {
+Dart_Handle DartInvokeVoid(Dart_Handle closure) {
Dart_Handle handle = Dart_InvokeClosure(closure, 0, nullptr);
LogIfError(handle);
+ return handle;
}
} // namespace tonic
diff --git a/logging/dart_invoke.h b/logging/dart_invoke.h
index 0d84746..28c001c 100644
--- a/logging/dart_invoke.h
+++ b/logging/dart_invoke.h
@@ -16,7 +16,7 @@
std::initializer_list<Dart_Handle> args);
void DartInvoke(Dart_Handle closure, std::initializer_list<Dart_Handle> args);
-void DartInvokeVoid(Dart_Handle closure);
+Dart_Handle DartInvokeVoid(Dart_Handle closure);
} // namespace tonic