[fuchsia] Fuchsia support to Node
diff --git a/src/api/environment.cc b/src/api/environment.cc
index a99201e..8d04d99 100644
--- a/src/api/environment.cc
+++ b/src/api/environment.cc
@@ -201,6 +201,7 @@
 }
 
 void SetIsolateCreateParamsForNode(Isolate::CreateParams* params) {
+#ifndef __Fuchsia__
   const uint64_t constrained_memory = uv_get_constrained_memory();
   const uint64_t total_memory = constrained_memory > 0 ?
       std::min(uv_get_total_memory(), constrained_memory) :
@@ -213,6 +214,7 @@
   }
   params->embedder_wrapper_object_index = BaseObject::InternalFields::kSlot;
   params->embedder_wrapper_type_index = std::numeric_limits<int>::max();
+#endif
 }
 
 void SetIsolateErrorHandlers(v8::Isolate* isolate, const IsolateSettings& s) {
diff --git a/src/debug_utils.cc b/src/debug_utils.cc
index a601c5e..45269b6 100644
--- a/src/debug_utils.cc
+++ b/src/debug_utils.cc
@@ -13,7 +13,8 @@
 
 #if defined(__linux__) && !defined(__GLIBC__) || \
     defined(__UCLIBC__) || \
-    defined(_AIX)
+    defined(_AIX) || \
+    defined(__Fuchsia__)
 #define HAVE_EXECINFO_H 0
 #else
 #define HAVE_EXECINFO_H 1
diff --git a/src/inspector_agent.cc b/src/inspector_agent.cc
index 4b7997a..62ef8f5 100644
--- a/src/inspector_agent.cc
+++ b/src/inspector_agent.cc
@@ -131,11 +131,13 @@
     // receiving the signal would terminate the process.
     return -err;
   }
+#ifndef __Fuchsia__
   RegisterSignalHandler(SIGUSR1, StartIoThreadWakeup);
   // Unblock SIGUSR1.  A pending SIGUSR1 signal will now be delivered.
   sigemptyset(&sigmask);
   sigaddset(&sigmask, SIGUSR1);
   CHECK_EQ(0, pthread_sigmask(SIG_UNBLOCK, &sigmask, nullptr));
+#endif
   return 0;
 }
 #endif  // __POSIX__
diff --git a/src/node.cc b/src/node.cc
index d68c6d8..737bb73 100644
--- a/src/node.cc
+++ b/src/node.cc
@@ -101,7 +101,9 @@
 #define STDIN_FILENO 0
 #else
 #include <pthread.h>
+#ifndef __Fuchsia__
 #include <sys/resource.h>  // getrlimit, setrlimit
+#endif
 #include <termios.h>       // tcgetattr, tcsetattr
 #include <unistd.h>        // STDIN_FILENO, STDERR_FILENO
 #endif
@@ -527,7 +529,7 @@
 }
 #endif  // NODE_USE_V8_WASM_TRAP_HANDLER
 
-#ifdef __POSIX__
+#if defined(POSIX) && !defined(__Fuchsia__)
 void RegisterSignalHandler(int signal,
                            sigaction_cb handler,
                            bool reset_handler) {
@@ -572,6 +574,10 @@
   // Make sure file descriptors 0-2 are valid before we start logging anything.
   for (auto& s : stdio) {
     const int fd = &s - stdio;
+#ifdef __Fuchsia__
+    // In fuchsia stdin is not readily available.
+    if (fd == 0) continue;
+#endif
     if (fstat(fd, &s.stat) == 0)
       continue;
     // Anything but EBADF means something is seriously wrong.  We don't
@@ -589,7 +595,7 @@
 #endif  // HAVE_INSPECTOR
 
   // TODO(addaleax): NODE_SHARED_MODE does not really make sense here.
-#ifndef NODE_SHARED_MODE
+#if !defined(NODE_SHARED_MODE) && !defined(__Fuchsia__)
   // Restore signal dispositions, the parent process may have changed them.
   struct sigaction act;
   memset(&act, 0, sizeof(act));
@@ -611,6 +617,10 @@
   for (auto& s : stdio) {
     const int fd = &s - stdio;
     int err;
+#ifdef __Fuchsia__
+    // In fuchsia stdin is not readily available.
+    if (fd == 0) continue;
+#endif
 
     do
       s.flags = fcntl(fd, F_GETFL);
@@ -626,6 +636,7 @@
     CHECK_EQ(err, 0);
   }
 
+#ifndef __Fuchsia__
   RegisterSignalHandler(SIGINT, SignalExit, true);
   RegisterSignalHandler(SIGTERM, SignalExit, true);
 
@@ -663,6 +674,7 @@
       }
     } while (min + 1 < max);
   }
+#endif  // __Fuchsia__
 #endif  // __POSIX__
 #ifdef _WIN32
   for (int fd = 0; fd <= 2; ++fd) {
@@ -687,6 +699,11 @@
   for (auto& s : stdio) {
     const int fd = &s - stdio;
 
+#ifdef __Fuchsia__
+    // In fuchsia stdin is not readily available.
+    if (fd == 0) continue;
+#endif
+
     struct stat tmp;
     if (-1 == fstat(fd, &tmp)) {
       CHECK_EQ(errno, EBADF);  // Program closed file descriptor.
diff --git a/src/node_os.cc b/src/node_os.cc
index 2e151ac..8cd38ab 100644
--- a/src/node_os.cc
+++ b/src/node_os.cc
@@ -77,7 +77,15 @@
 static void GetOSInformation(const FunctionCallbackInfo<Value>& args) {
   Environment* env = Environment::GetCurrent(args);
   uv_utsname_t info;
-  int err = uv_os_uname(&info);
+  int err = 0;
+#ifdef __Fuchsia__
+  // TODO(victor): Update uv_os_uname to get these informations for Fuchsia
+  info.sysname[0] = 0;
+  info.version[0] = 0;
+  info.release[0] = 0;
+#else
+  err = uv_os_uname(&info);
+#endif
 
   if (err != 0) {
     CHECK_GE(args.Length(), 1);
@@ -328,6 +336,7 @@
   args.GetReturnValue().Set(entry);
 }
 
+#ifndef __Fuchsia__
 
 static void SetPriority(const FunctionCallbackInfo<Value>& args) {
   Environment* env = Environment::GetCurrent(args);
@@ -367,7 +376,7 @@
 
   args.GetReturnValue().Set(priority);
 }
-
+#endif // !__Fuchsia__
 
 void Initialize(Local<Object> target,
                 Local<Value> unused,
@@ -383,9 +392,12 @@
   env->SetMethod(target, "getInterfaceAddresses", GetInterfaceAddresses);
   env->SetMethod(target, "getHomeDirectory", GetHomeDirectory);
   env->SetMethod(target, "getUserInfo", GetUserInfo);
+#ifndef __Fuchsia__
   env->SetMethod(target, "setPriority", SetPriority);
   env->SetMethod(target, "getPriority", GetPriority);
+#endif
   env->SetMethod(target, "getOSInformation", GetOSInformation);
+
   target->Set(env->context(),
               FIXED_ONE_BYTE_STRING(env->isolate(), "isBigEndian"),
               Boolean::New(env->isolate(), IsBigEndian())).Check();
diff --git a/src/node_process_methods.cc b/src/node_process_methods.cc
index 826dad1..be9d75a 100644
--- a/src/node_process_methods.cc
+++ b/src/node_process_methods.cc
@@ -28,7 +28,9 @@
 typedef int mode_t;
 #else
 #include <pthread.h>
+#if !defined(__Fuchsia__)
 #include <sys/resource.h>  // getrlimit, setrlimit
+#endif
 #include <termios.h>  // tcgetattr, tcsetattr
 #endif
 
@@ -89,6 +91,7 @@
   }
 }
 
+#ifndef __Fuchsia__
 // CPUUsage use libuv's uv_getrusage() this-process resource usage accessor,
 // to access ru_utime (user CPU time used) and ru_stime (system CPU time used),
 // which are uv_timeval_t structs (long tv_sec, long tv_usec).
@@ -116,6 +119,7 @@
   fields[0] = MICROS_PER_SEC * rusage.ru_utime.tv_sec + rusage.ru_utime.tv_usec;
   fields[1] = MICROS_PER_SEC * rusage.ru_stime.tv_sec + rusage.ru_stime.tv_usec;
 }
+#endif
 
 static void Cwd(const FunctionCallbackInfo<Value>& args) {
   Environment* env = Environment::GetCurrent(args);
@@ -145,7 +149,7 @@
   int sig;
   if (!args[1]->Int32Value(context).To(&sig)) return;
 
-  uv_pid_t own_pid = uv_os_getpid();
+  int own_pid = uv_os_getpid();
   if (sig > 0 &&
       (pid == 0 || pid == -1 || pid == own_pid || pid == -own_pid) &&
       !HasSignalJSHandler(sig)) {
@@ -267,6 +271,7 @@
       Array::New(env->isolate(), handle_v.data(), handle_v.size()));
 }
 
+#ifndef __Fuchsia__
 static void ResourceUsage(const FunctionCallbackInfo<Value>& args) {
   Environment* env = Environment::GetCurrent(args);
 
@@ -298,6 +303,7 @@
   fields[14] = rusage.ru_nvcsw;
   fields[15] = rusage.ru_nivcsw;
 }
+#endif
 
 #ifdef __POSIX__
 static void DebugProcess(const FunctionCallbackInfo<Value>& args) {
@@ -547,8 +553,11 @@
   env->SetMethod(target, "umask", Umask);
   env->SetMethod(target, "_rawDebug", RawDebug);
   env->SetMethod(target, "memoryUsage", MemoryUsage);
+  
+  #ifndef __Fuchsia__
   env->SetMethod(target, "cpuUsage", CPUUsage);
   env->SetMethod(target, "resourceUsage", ResourceUsage);
+  #endif
 
   env->SetMethod(target, "_getActiveRequests", GetActiveRequests);
   env->SetMethod(target, "_getActiveHandles", GetActiveHandles);
@@ -573,8 +582,10 @@
   registry->Register(Umask);
   registry->Register(RawDebug);
   registry->Register(MemoryUsage);
+#ifndef __Fuchsia__
   registry->Register(CPUUsage);
   registry->Register(ResourceUsage);
+#endif
 
   registry->Register(GetActiveRequests);
   registry->Register(GetActiveHandles);
diff --git a/src/node_report.cc b/src/node_report.cc
index e7bfe7f..dc3ea42 100644
--- a/src/node_report.cc
+++ b/src/node_report.cc
@@ -12,7 +12,9 @@
 #ifdef _WIN32
 #include <Windows.h>
 #else  // !_WIN32
+#ifndef __Fuchsia__
 #include <sys/resource.h>
+#endif
 #include <cxxabi.h>
 #include <dlfcn.h>
 #endif
@@ -608,6 +610,7 @@
       (uv_hrtime() - node::per_process::node_start_time) / (NANOS_PER_SEC);
   if (uptime == 0) uptime = 1;  // avoid division by zero.
 
+#ifndef __Fuchsia__
   // Process and current thread usage statistics
   uv_rusage_t rusage;
   writer->json_objectstart("resourceUsage");
@@ -632,6 +635,7 @@
     writer->json_objectend();
   }
   writer->json_objectend();
+#endif
 #ifdef RUSAGE_THREAD
   struct rusage stats;
   if (getrusage(RUSAGE_THREAD, &stats) == 0) {
@@ -676,7 +680,7 @@
 
   writer->json_objectend();
 
-#ifndef _WIN32
+#if !defined(_WIN32) && !defined(__Fuchsia__)
   static struct {
     const char* description;
     int id;
@@ -723,7 +727,7 @@
     }
   }
   writer->json_objectend();
-#endif  // _WIN32
+#endif  // _WIN32 && __Fuchsia__
 
   PrintLoadedLibraries(writer);
 }
diff --git a/src/node_watchdog.cc b/src/node_watchdog.cc
index 8bd3b28..d10abf4 100644
--- a/src/node_watchdog.cc
+++ b/src/node_watchdog.cc
@@ -297,6 +297,7 @@
     return 0;
   }
 
+#ifndef __Fuchsia__
 #ifdef __POSIX__
   CHECK_EQ(has_running_thread_, false);
   has_pending_signal_ = false;
@@ -322,6 +323,7 @@
     SetConsoleCtrlHandler(WinCtrlCHandlerRoutine, TRUE);
   }
 #endif
+#endif
 
   return 0;
 }
@@ -349,6 +351,7 @@
     watchdogs_.clear();
   }
 
+#ifndef __Fuchsia__
 #ifdef __POSIX__
   if (!has_running_thread_) {
     has_pending_signal_ = false;
@@ -369,7 +372,7 @@
 
   had_pending_signal = has_pending_signal_;
   has_pending_signal_ = false;
-
+#endif
   return had_pending_signal;
 }
 
diff --git a/test/cctest/gtest/gtest-all.cc b/test/cctest/gtest/gtest-all.cc
index ffa5f77..eca8143 100644
--- a/test/cctest/gtest/gtest-all.cc
+++ b/test/cctest/gtest/gtest-all.cc
@@ -8401,12 +8401,10 @@
       : DeathTestImpl(a_statement, std::move(matcher)),
         file_(file),
         line_(line) {}
-
   // All of these virtual functions are inherited from DeathTest.
   int Wait() override;
   TestRole AssumeRole() override;
   std::string GetErrorLogs() override;
-
  private:
   // The name of the file in which the death test is located.
   const char* const file_;
@@ -8414,17 +8412,14 @@
   const int line_;
   // The stderr data captured by the child process.
   std::string captured_stderr_;
-
   zx::process child_process_;
-  zx::port port_;
+  zx::channel exception_channel_;
   zx::socket stderr_socket_;
 };
-
 // Utility class for accumulating command-line arguments.
 class Arguments {
  public:
   Arguments() { args_.push_back(nullptr); }
-
   ~Arguments() {
     for (std::vector<char*>::iterator i = args_.begin(); i != args_.end();
          ++i) {
@@ -8434,7 +8429,6 @@
   void AddArgument(const char* argument) {
     args_.insert(args_.end() - 1, posix::StrDup(argument));
   }
-
   template <typename Str>
   void AddArguments(const ::std::vector<Str>& arguments) {
     for (typename ::std::vector<Str>::const_iterator i = arguments.begin();
@@ -8446,58 +8440,58 @@
   char* const* Argv() {
     return &args_[0];
   }
-
   int size() {
     return args_.size() - 1;
   }
-
  private:
   std::vector<char*> args_;
 };
-
 // Waits for the child in a death test to exit, returning its exit
 // status, or 0 if no child process exists.  As a side effect, sets the
 // outcome data member.
 int FuchsiaDeathTest::Wait() {
   const int kProcessKey = 0;
   const int kSocketKey = 1;
-
+  const int kExceptionKey = 2;
   if (!spawned())
     return 0;
-
-  // Register to wait for the child process to terminate.
+  // Create a port to wait for socket/task/exception events.
   zx_status_t status_zx;
+  zx::port port;
+  status_zx = zx::port::create(0, &port);
+  GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
+  // Register to wait for the child process to terminate.
   status_zx = child_process_.wait_async(
-      port_, kProcessKey, ZX_PROCESS_TERMINATED, ZX_WAIT_ASYNC_ONCE);
+      port, kProcessKey, ZX_PROCESS_TERMINATED, ZX_WAIT_ASYNC_ONCE);
   GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
   // Register to wait for the socket to be readable or closed.
   status_zx = stderr_socket_.wait_async(
-      port_, kSocketKey, ZX_SOCKET_READABLE | ZX_SOCKET_PEER_CLOSED,
-      ZX_WAIT_ASYNC_REPEATING);
+      port, kSocketKey, ZX_SOCKET_READABLE | ZX_SOCKET_PEER_CLOSED,
+      ZX_WAIT_ASYNC_ONCE);
   GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
-
+  // Register to wait for an exception.
+  status_zx = exception_channel_.wait_async(
+      port, kExceptionKey, ZX_CHANNEL_READABLE, ZX_WAIT_ASYNC_ONCE);
+  GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
   bool process_terminated = false;
   bool socket_closed = false;
   do {
     zx_port_packet_t packet = {};
-    status_zx = port_.wait(zx::time::infinite(), &packet);
+    status_zx = port.wait(zx::time::infinite(), &packet);
     GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
-
-    if (packet.key == kProcessKey) {
-      if (ZX_PKT_IS_EXCEPTION(packet.type)) {
-        // Process encountered an exception. Kill it directly rather than
-        // letting other handlers process the event. We will get a second
-        // kProcessKey event when the process actually terminates.
-        status_zx = child_process_.kill();
-        GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
-      } else {
-        // Process terminated.
-        GTEST_DEATH_TEST_CHECK_(ZX_PKT_IS_SIGNAL_ONE(packet.type));
-        GTEST_DEATH_TEST_CHECK_(packet.signal.observed & ZX_PROCESS_TERMINATED);
-        process_terminated = true;
-      }
+    if (packet.key == kExceptionKey) {
+      // Process encountered an exception. Kill it directly rather than
+      // letting other handlers process the event. We will get a kProcessKey
+      // event when the process actually terminates.
+      status_zx = child_process_.kill();
+      GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
+    } else if (packet.key == kProcessKey) {
+      // Process terminated.
+      GTEST_DEATH_TEST_CHECK_(ZX_PKT_IS_SIGNAL_ONE(packet.type));
+      GTEST_DEATH_TEST_CHECK_(packet.signal.observed & ZX_PROCESS_TERMINATED);
+      process_terminated = true;
     } else if (packet.key == kSocketKey) {
-      GTEST_DEATH_TEST_CHECK_(ZX_PKT_IS_SIGNAL_REP(packet.type));
+      GTEST_DEATH_TEST_CHECK_(ZX_PKT_IS_SIGNAL_ONE(packet.type));
       if (packet.signal.observed & ZX_SOCKET_READABLE) {
         // Read data from the socket.
         constexpr size_t kBufferSize = 1024;
@@ -8514,6 +8508,10 @@
           socket_closed = true;
         } else {
           GTEST_DEATH_TEST_CHECK_(status_zx == ZX_ERR_SHOULD_WAIT);
+          status_zx = stderr_socket_.wait_async(
+              port, kSocketKey, ZX_SOCKET_READABLE | ZX_SOCKET_PEER_CLOSED,
+              ZX_WAIT_ASYNC_ONCE);
+          GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
         }
       } else {
         GTEST_DEATH_TEST_CHECK_(packet.signal.observed & ZX_SOCKET_PEER_CLOSED);
@@ -8521,19 +8519,15 @@
       }
     }
   } while (!process_terminated && !socket_closed);
-
   ReadAndInterpretStatusByte();
-
   zx_info_process_t buffer;
   status_zx = child_process_.get_info(
       ZX_INFO_PROCESS, &buffer, sizeof(buffer), nullptr, nullptr);
   GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
-
   GTEST_DEATH_TEST_CHECK_(buffer.exited);
   set_status(buffer.return_code);
   return status();
 }
-
 // The AssumeRole process for a Fuchsia death test.  It creates a child
 // process with the same executable as the current process to run the
 // death test.  The child process is given the --gtest_filter and
@@ -8545,17 +8539,14 @@
       impl->internal_run_death_test_flag();
   const TestInfo* const info = impl->current_test_info();
   const int death_test_index = info->result()->death_test_count();
-
   if (flag != nullptr) {
     // ParseInternalRunDeathTestFlag() has performed all the necessary
     // processing.
     set_write_fd(kFuchsiaReadPipeFd);
     return EXECUTE_TEST;
   }
-
   // Flush the log buffers since the log streams are shared with the child.
   FlushInfoLog();
-
   // Build the child process command line.
   const std::string filter_flag = std::string("--") + GTEST_FLAG_PREFIX_ +
                                   kFilterFlag + "=" + info->test_suite_name() +
@@ -8569,22 +8560,19 @@
   args.AddArguments(GetInjectableArgvs());
   args.AddArgument(filter_flag.c_str());
   args.AddArgument(internal_flag.c_str());
-
   // Build the pipe for communication with the child.
   zx_status_t status;
   zx_handle_t child_pipe_handle;
   int child_pipe_fd;
-  status = fdio_pipe_half2(&child_pipe_fd, &child_pipe_handle);
-  GTEST_DEATH_TEST_CHECK_(status != ZX_OK);
+  status = fdio_pipe_half(&child_pipe_fd, &child_pipe_handle);
+  GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
   set_read_fd(child_pipe_fd);
-
   // Set the pipe handle for the child.
   fdio_spawn_action_t spawn_actions[2] = {};
   fdio_spawn_action_t* add_handle_action = &spawn_actions[0];
   add_handle_action->action = FDIO_SPAWN_ACTION_ADD_HANDLE;
   add_handle_action->h.id = PA_HND(PA_FD, kFuchsiaReadPipeFd);
   add_handle_action->h.handle = child_pipe_handle;
-
   // Create a socket pair will be used to receive the child process' stderr.
   zx::socket stderr_producer_socket;
   status =
@@ -8594,15 +8582,12 @@
   status =
       fdio_fd_create(stderr_producer_socket.release(), &stderr_producer_fd);
   GTEST_DEATH_TEST_CHECK_(status >= 0);
-
   // Make the stderr socket nonblocking.
   GTEST_DEATH_TEST_CHECK_(fcntl(stderr_producer_fd, F_SETFL, 0) == 0);
-
   fdio_spawn_action_t* add_stderr_action = &spawn_actions[1];
   add_stderr_action->action = FDIO_SPAWN_ACTION_CLONE_FD;
   add_stderr_action->fd.local_fd = stderr_producer_fd;
   add_stderr_action->fd.target_fd = STDERR_FILENO;
-
   // Create a child job.
   zx_handle_t child_job = ZX_HANDLE_INVALID;
   status = zx_job_create(zx_job_default(), 0, & child_job);
@@ -8613,25 +8598,20 @@
   status = zx_job_set_policy(
       child_job, ZX_JOB_POL_RELATIVE, ZX_JOB_POL_BASIC, &policy, 1);
   GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
-
-  // Create an exception port and attach it to the |child_job|, to allow
+  // Create an exception channel attached to the |child_job|, to allow
   // us to suppress the system default exception handler from firing.
-  status = zx::port::create(0, &port_);
+  status =
+      zx_task_create_exception_channel(
+          child_job, 0, exception_channel_.reset_and_get_address());
   GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
-  status = zx_task_bind_exception_port(
-      child_job, port_.get(), 0 /* key */, 0 /*options */);
-  GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
-
   // Spawn the child process.
   status = fdio_spawn_etc(
       child_job, FDIO_SPAWN_CLONE_ALL, args.Argv()[0], args.Argv(), nullptr,
       2, spawn_actions, child_process_.reset_and_get_address(), nullptr);
   GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
-
   set_spawned(true);
   return OVERSEE_TEST;
 }
-
 std::string FuchsiaDeathTest::GetErrorLogs() {
   return captured_stderr_;
 }