env: introduce `KickNextTick`
authorFedor Indutny <fedor@indutny.com>
Wed, 26 Aug 2015 11:37:50 +0000 (04:37 -0700)
committerFedor Indutny <fedor@indutny.com>
Wed, 26 Aug 2015 19:45:16 +0000 (12:45 -0700)
There might be a need to "kick off" the next tick queue and execute
events on it. Normally it is done through the `MakeCallback` interface,
but in case when it is not - we need a way to "kick them off" manually.

PR-URL: https://github.com/nodejs/node/pull/2355
Reviewed-By: Trevor Norris <trev.norris@gmail.com>
src/env.cc
src/env.h
src/node.cc
src/node_internals.h

index 3deb4db..e28866e 100644 (file)
@@ -10,6 +10,7 @@ using v8::Local;
 using v8::Message;
 using v8::StackFrame;
 using v8::StackTrace;
+using v8::TryCatch;
 
 void Environment::PrintSyncTrace() const {
   if (!trace_sync_io_)
@@ -55,4 +56,38 @@ void Environment::PrintSyncTrace() const {
   fflush(stderr);
 }
 
+
+bool Environment::KickNextTick() {
+  TickInfo* info = tick_info();
+
+  if (info->in_tick()) {
+    return true;
+  }
+
+  if (info->length() == 0) {
+    isolate()->RunMicrotasks();
+  }
+
+  if (info->length() == 0) {
+    info->set_index(0);
+    return true;
+  }
+
+  info->set_in_tick(true);
+
+  // process nextTicks after call
+  TryCatch try_catch;
+  try_catch.SetVerbose(true);
+  tick_callback_function()->Call(process_object(), 0, nullptr);
+
+  info->set_in_tick(false);
+
+  if (try_catch.HasCaught()) {
+    info->set_last_threw(true);
+    return false;
+  }
+
+  return true;
+}
+
 }  // namespace node
index 1801ffe..5830b02 100644 (file)
--- a/src/env.h
+++ b/src/env.h
@@ -424,6 +424,8 @@ class Environment {
   void PrintSyncTrace() const;
   inline void set_trace_sync_io(bool value);
 
+  bool KickNextTick();
+
   inline uint32_t* heap_statistics_buffer() const;
   inline void set_heap_statistics_buffer(uint32_t* pointer);
 
index 3c6441a..084fe90 100644 (file)
@@ -1026,7 +1026,6 @@ Handle<Value> MakeCallback(Environment* env,
   // If you hit this assertion, you forgot to enter the v8::Context first.
   CHECK_EQ(env->context(), env->isolate()->GetCurrentContext());
 
-  Local<Object> process = env->process_object();
   Local<Object> object, domain;
   bool has_async_queue = false;
   bool has_domain = false;
@@ -1092,32 +1091,8 @@ Handle<Value> MakeCallback(Environment* env,
     return Undefined(env->isolate());
   }
 
-  Environment::TickInfo* tick_info = env->tick_info();
-
-  if (tick_info->in_tick()) {
-    return ret;
-  }
-
-  if (tick_info->length() == 0) {
-    env->isolate()->RunMicrotasks();
-  }
-
-  if (tick_info->length() == 0) {
-    tick_info->set_index(0);
-    return ret;
-  }
-
-  tick_info->set_in_tick(true);
-
-  // process nextTicks after call
-  env->tick_callback_function()->Call(process, 0, nullptr);
-
-  tick_info->set_in_tick(false);
-
-  if (try_catch.HasCaught()) {
-    tick_info->set_last_threw(true);
+  if (!env->KickNextTick())
     return Undefined(env->isolate());
-  }
 
   return ret;
 }
index 8f35433..ffb5ec7 100644 (file)
@@ -69,6 +69,8 @@ v8::Handle<v8::Value> MakeCallback(Environment* env,
                                    int argc = 0,
                                    v8::Handle<v8::Value>* argv = nullptr);
 
+bool KickNextTick();
+
 // Convert a struct sockaddr to a { address: '1.2.3.4', port: 1234 } JS object.
 // Sets address and port properties on the info object and returns it.
 // If |info| is omitted, a new object is returned.