[flutter,dart] Run handle wait completers on the microtask queue

Change-Id: I66c39d9ef7d534094148212940eef45754559d04
diff --git a/public/dart-pkg/zircon/lib/src/handle.dart b/public/dart-pkg/zircon/lib/src/handle.dart
index ca7883c..47516de 100644
--- a/public/dart-pkg/zircon/lib/src/handle.dart
+++ b/public/dart-pkg/zircon/lib/src/handle.dart
@@ -39,3 +39,17 @@
 
   Handle duplicate(int rights) native 'Handle_Duplicate';
 }
+
+@pragma('vm:entry-point')
+class _OnWaitCompleteClosure {  // ignore: unused_element
+  // No public constructor - this can only be created from native code.
+  @pragma('vm:entry-point')
+  _OnWaitCompleteClosure(this._callback, this._arg1, this._arg2);
+
+  Function _callback;
+  Object _arg1;
+  Object _arg2;
+
+  @pragma('vm:entry-point')
+  Function get _closure => () => _callback(_arg1, _arg2); // ignore: unused_element
+}
diff --git a/public/dart-pkg/zircon/sdk_ext/handle_waiter.cc b/public/dart-pkg/zircon/sdk_ext/handle_waiter.cc
index 8ecfb87..0c86d7a 100644
--- a/public/dart-pkg/zircon/sdk_ext/handle_waiter.cc
+++ b/public/dart-pkg/zircon/sdk_ext/handle_waiter.cc
@@ -8,11 +8,13 @@
 
 #include "dart-pkg/zircon/sdk_ext/handle.h"
 #include "src/lib/fxl/logging.h"
+#include "third_party/dart/runtime/include/dart_api.h"
 #include "third_party/tonic/converter/dart_converter.h"
 #include "third_party/tonic/dart_args.h"
 #include "third_party/tonic/dart_binding_macros.h"
 #include "third_party/tonic/dart_library_natives.h"
 #include "third_party/tonic/dart_message_handler.h"
+#include "third_party/tonic/dart_microtask_queue.h"
 #include "third_party/tonic/logging/dart_invoke.h"
 
 using tonic::DartInvokeField;
@@ -85,14 +87,32 @@
   FXL_DCHECK(state);
   DartState::Scope scope(state);
 
-  std::vector<Dart_Handle> args{ToDart(status), ToDart(signal->observed)};
+  // Put the closure invocation on the microtask queue.
+  Dart_Handle zircon_lib = Dart_LookupLibrary(ToDart("dart:zircon"));
+  FXL_DCHECK(!tonic::LogIfError(zircon_lib));
+
+  Dart_Handle owc_type =
+      Dart_GetClass(zircon_lib, ToDart("_OnWaitCompleteClosure"));
+  FXL_DCHECK(!tonic::LogIfError(owc_type));
+
   FXL_DCHECK(!callback_.is_empty());
-  Dart_Handle result =
-      Dart_InvokeClosure(callback_.Release(), args.size(), args.data());
-  // If there was an uncaught error from the callback propagate it out.
-  if (tonic::LogIfError(result)) {
-    state->message_handler().UnhandledError(result);
-  }
+  std::vector<Dart_Handle> owc_args{
+      callback_.Release(), ToDart(status), ToDart(signal->observed)};
+  Dart_Handle owc = Dart_New(
+      owc_type, Dart_Null(), owc_args.size(), owc_args.data());
+  FXL_DCHECK(!tonic::LogIfError(owc));
+
+  Dart_Handle closure = Dart_GetField(owc, ToDart("_closure"));
+  FXL_DCHECK(!tonic::LogIfError(closure));
+
+  // TODO(issue#tbd): Use tonic::DartMicrotaskQueue::ScheduleMicrotask()
+  // instead when tonic::DartState gets a microtask queue field.
+  Dart_Handle async_lib = Dart_LookupLibrary(ToDart("dart:async"));
+  FXL_DCHECK(!tonic::LogIfError(async_lib));
+  std::vector<Dart_Handle> sm_args{closure};
+  Dart_Handle sm_result = Dart_Invoke(
+      async_lib, ToDart("scheduleMicrotask"), sm_args.size(), sm_args.data());
+  FXL_DCHECK(!tonic::LogIfError(sm_result));
 }
 
 }  // namespace dart
diff --git a/public/dart/sledge/lib/src/subscription/subscription.dart b/public/dart/sledge/lib/src/subscription/subscription.dart
index 66769cf..211c29c 100644
--- a/public/dart/sledge/lib/src/subscription/subscription.dart
+++ b/public/dart/sledge/lib/src/subscription/subscription.dart
@@ -42,7 +42,7 @@
       _applyChangeCallback(_currentChange);
       _currentChange.clear();
     }
-    return null;
+    return Future.value(null);
   }
 
   /// Ends subscription.