#include "async_context_frame.h"
#include "async_wrap-inl.h"
#include "env-inl.h"
#define NAPI_EXPERIMENTAL
#include "js_native_api_v8.h"
#include "memory_tracker-inl.h"
#include "node_api.h"
#include "node_api_internals.h"
#include "node_binding.h"
#include "node_buffer.h"
#include "node_errors.h"
#include "node_internals.h"
#include "node_process.h"
#include "node_url.h"
#include "threadpoolwork-inl.h"
#include "tracing/traced_value.h"
#include "util-inl.h"

#include <atomic>
#include <cstring>
#include <memory>

namespace v8impl {
static void ThrowNodeApiVersionError(node::Environment* node_env,
                                     const char* module_name,
                                     int32_t module_api_version) {
  std::string error_message;
  error_message += module_name;
  error_message += " requires Node-API version ";
  error_message += std::to_string(module_api_version);
  error_message += ", but this version of Node.js only supports version ";
  error_message += NODE_STRINGIFY(NODE_API_SUPPORTED_VERSION_MAX) " add-ons.";
  node_env->ThrowError(error_message.c_str());
}
}  // namespace v8impl

/*static*/ napi_env node_napi_env__::New(v8::Local<v8::Context> context,
                                         const std::string& module_filename,
                                         int32_t module_api_version) {
  node_napi_env result;

  // Validate module_api_version.
  if (module_api_version < NODE_API_DEFAULT_MODULE_API_VERSION) {
    module_api_version = NODE_API_DEFAULT_MODULE_API_VERSION;
  } else if (module_api_version > NODE_API_SUPPORTED_VERSION_MAX &&
             module_api_version != NAPI_VERSION_EXPERIMENTAL) {
    node::Environment* node_env = node::Environment::GetCurrent(context);
    CHECK_NOT_NULL(node_env);
    v8impl::ThrowNodeApiVersionError(
        node_env, module_filename.c_str(), module_api_version);
    return nullptr;
  }

  result = new node_napi_env__(context, module_filename, module_api_version);
  // TODO(addaleax): There was previously code that tried to delete the
  // napi_env when its v8::Context was garbage collected;
  // However, as long as N-API addons using this napi_env are in place,
  // the Context needs to be accessible and alive.
  // Ideally, we'd want an on-addon-unload hook that takes care of this
  // once all N-API addons using this napi_env are unloaded.
  // For now, a per-Environment cleanup hook is the best we can do.
  result->node_env()->AddCleanupHook(
      [](void* arg) { static_cast<napi_env>(arg)->Unref(); },
      static_cast<void*>(result));

  return result;
}

node_napi_env__::node_napi_env__(v8::Local<v8::Context> context,
                                 const std::string& module_filename,
                                 int32_t module_api_version)
    : napi_env__(context, module_api_version), filename(module_filename) {
  CHECK_NOT_NULL(node_env());
}

void node_napi_env__::DeleteMe() {
  destructing = true;
  DrainFinalizerQueue();
  napi_env__::DeleteMe();
}

bool node_napi_env__::can_call_into_js() const {
  return node_env()->can_call_into_js();
}

void node_napi_env__::CallFinalizer(napi_finalize cb, void* data, void* hint) {
  CallFinalizer<true>(cb, data, hint);
}

template <bool enforceUncaughtExceptionPolicy>
void node_napi_env__::CallFinalizer(napi_finalize cb, void* data, void* hint) {
  v8::HandleScope handle_scope(isolate);
  v8::Context::Scope context_scope(context());
  CallbackIntoModule<enforceUncaughtExceptionPolicy>(
      [&](napi_env env) { cb(env, data, hint); });
}

void node_napi_env__::EnqueueFinalizer(v8impl::RefTracker* finalizer) {
  napi_env__::EnqueueFinalizer(finalizer);
  // Schedule a second pass only when it has not been scheduled, and not
  // destructing the env.
  // When the env is being destructed, queued finalizers are drained in the
  // loop of `node_napi_env__::DrainFinalizerQueue`.
  if (!finalization_scheduled && !destructing) {
    finalization_scheduled = true;
    Ref();
    node_env()->SetImmediate([this](node::Environment* node_env) {
      finalization_scheduled = false;
      Unref();
      DrainFinalizerQueue();
    });
  }
}

void node_napi_env__::DrainFinalizerQueue() {
  // As userland code can delete additional references in one finalizer,
  // the list of pending finalizers may be mutated as we execute them, so
  // we keep iterating it until it is empty.
  while (!pending_finalizers.empty()) {
    v8impl::RefTracker* ref_tracker = *pending_finalizers.begin();
    pending_finalizers.erase(ref_tracker);
    ref_tracker->Finalize();
  }
}

void node_napi_env__::trigger_fatal_exception(v8::Local<v8::Value> local_err) {
  v8::Local<v8::Message> local_msg =
      v8::Exception::CreateMessage(isolate, local_err);
  node::errors::TriggerUncaughtException(isolate, local_err, local_msg);
}

// The option enforceUncaughtExceptionPolicy is added for not breaking existing
// running Node-API add-ons.
template <bool enforceUncaughtExceptionPolicy, typename T>
void node_napi_env__::CallbackIntoModule(T&& call) {
  CallIntoModule(call, [](napi_env env_, v8::Local<v8::Value> local_err) {
    node_napi_env__* env = static_cast<node_napi_env__*>(env_);
    if (env->terminatedOrTerminating()) {
      return;
    }
    node::Environment* node_env = env->node_env();
    // If the module api version is less than 10, and the option
    // --force-node-api-uncaught-exceptions-policy is not specified, emit a
    // warning about the uncaught exception instead of triggering the uncaught
    // exception event.
    if (env->module_api_version < 10 &&
        !node_env->options()->force_node_api_uncaught_exceptions_policy &&
        !enforceUncaughtExceptionPolicy) {
      ProcessEmitDeprecationWarning(
          node_env,
          "Uncaught N-API callback exception detected, please run node "
          "with option --force-node-api-uncaught-exceptions-policy=true "
          "to handle those exceptions properly.",
          "DEP0168");
      return;
    }
    // If there was an unhandled exception in the complete callback,
    // report it as a fatal exception. (There is no JavaScript on the
    // call stack that can possibly handle it.)
    env->trigger_fatal_exception(local_err);
  });
}

namespace v8impl {

namespace {

class BufferFinalizer : private Finalizer {
 public:
  static BufferFinalizer* New(napi_env env,
                              napi_finalize finalize_callback,
                              void* finalize_data,
                              void* finalize_hint) {
    return new BufferFinalizer(
        env, finalize_callback, finalize_data, finalize_hint);
  }
  // node::Buffer::FreeCallback
  static void FinalizeBufferCallback(char* data, void* hint) {
    std::unique_ptr<BufferFinalizer, Deleter> finalizer{
        static_cast<BufferFinalizer*>(hint)};
    // It is safe to call into JavaScript at this point.
    finalizer->CallFinalizer();
  }

  struct Deleter {
    void operator()(BufferFinalizer* finalizer) { delete finalizer; }
  };

 private:
  BufferFinalizer(napi_env env,
                  napi_finalize finalize_callback,
                  void* finalize_data,
                  void* finalize_hint)
      : Finalizer(env, finalize_callback, finalize_data, finalize_hint) {
    env->Ref();
  }

  ~BufferFinalizer() { env()->Unref(); }
};

class ThreadSafeFunction : public node::AsyncResource {
 public:
  ThreadSafeFunction(v8::Local<v8::Function> func,
                     v8::Local<v8::Object> resource,
                     v8::Local<v8::String> name,
                     size_t thread_count_,
                     void* context_,
                     size_t max_queue_size_,
                     node_napi_env env_,
                     void* finalize_data_,
                     napi_finalize finalize_cb_,
                     napi_threadsafe_function_call_js call_js_cb_)
      : AsyncResource(env_->isolate,
                      resource,
                      *v8::String::Utf8Value(env_->isolate, name)),
        thread_count(thread_count_),
        is_closing(false),
        dispatch_state(kDispatchIdle),
        context(context_),
        max_queue_size(max_queue_size_),
        env(env_),
        finalize_data(finalize_data_),
        finalize_cb(finalize_cb_),
        call_js_cb(call_js_cb_ == nullptr ? CallJs : call_js_cb_),
        handles_closing(false) {
    ref.Reset(env->isolate, func);
    node::AddEnvironmentCleanupHook(env->isolate, Cleanup, this);
    env->Ref();
  }

  ~ThreadSafeFunction() override {
    node::RemoveEnvironmentCleanupHook(env->isolate, Cleanup, this);
    env->Unref();
  }

  // These methods can be called from any thread.

  napi_status Push(void* data, napi_threadsafe_function_call_mode mode) {
    node::Mutex::ScopedLock lock(this->mutex);

    while (queue.size() >= max_queue_size && max_queue_size > 0 &&
           !is_closing) {
      if (mode == napi_tsfn_nonblocking) {
        return napi_queue_full;
      }
      cond->Wait(lock);
    }

    if (is_closing) {
      if (thread_count == 0) {
        return napi_invalid_arg;
      } else {
        thread_count--;
        return napi_closing;
      }
    } else {
      queue.push(data);
      Send();
      return napi_ok;
    }
  }

  napi_status Acquire() {
    node::Mutex::ScopedLock lock(this->mutex);

    if (is_closing) {
      return napi_closing;
    }

    thread_count++;

    return napi_ok;
  }

  napi_status Release(napi_threadsafe_function_release_mode mode) {
    node::Mutex::ScopedLock lock(this->mutex);

    if (thread_count == 0) {
      return napi_invalid_arg;
    }

    thread_count--;

    if (thread_count == 0 || mode == napi_tsfn_abort) {
      if (!is_closing) {
        is_closing = (mode == napi_tsfn_abort);
        if (is_closing && max_queue_size > 0) {
          cond->Signal(lock);
        }
        Send();
      }
    }

    return napi_ok;
  }

  void EmptyQueueAndDelete() {
    for (; !queue.empty(); queue.pop()) {
      call_js_cb(nullptr, nullptr, context, queue.front());
    }
    delete this;
  }

  // These methods must only be called from the loop thread.

  napi_status Init() {
    ThreadSafeFunction* ts_fn = this;
    uv_loop_t* loop = env->node_env()->event_loop();

    if (uv_async_init(loop, &async, AsyncCb) == 0) {
      if (max_queue_size > 0) {
        cond = std::make_unique<node::ConditionVariable>();
      }
      if (max_queue_size == 0 || cond) {
        return napi_ok;
      }

      env->node_env()->CloseHandle(
          reinterpret_cast<uv_handle_t*>(&async),
          [](uv_handle_t* handle) -> void {
            ThreadSafeFunction* ts_fn =
                node::ContainerOf(&ThreadSafeFunction::async,
                                  reinterpret_cast<uv_async_t*>(handle));
            delete ts_fn;
          });

      // Prevent the thread-safe function from being deleted here, because
      // the callback above will delete it.
      ts_fn = nullptr;
    }

    delete ts_fn;

    return napi_generic_failure;
  }

  napi_status Unref() {
    uv_unref(reinterpret_cast<uv_handle_t*>(&async));

    return napi_ok;
  }

  napi_status Ref() {
    uv_ref(reinterpret_cast<uv_handle_t*>(&async));

    return napi_ok;
  }

  inline void* Context() { return context; }

 protected:
  void Dispatch() {
    bool has_more = true;

    // Limit maximum synchronous iteration count to prevent event loop
    // starvation. See `src/node_messaging.cc` for an inspiration.
    unsigned int iterations_left = kMaxIterationCount;
    while (has_more && --iterations_left != 0) {
      dispatch_state = kDispatchRunning;
      has_more = DispatchOne();

      // Send() was called while we were executing the JS function
      if (dispatch_state.exchange(kDispatchIdle) != kDispatchRunning) {
        has_more = true;
      }
    }

    if (has_more) {
      Send();
    }
  }

  bool DispatchOne() {
    void* data = nullptr;
    bool popped_value = false;
    bool has_more = false;

    {
      node::Mutex::ScopedLock lock(this->mutex);
      if (is_closing) {
        CloseHandlesAndMaybeDelete();
      } else {
        size_t size = queue.size();
        if (size > 0) {
          data = queue.front();
          queue.pop();
          popped_value = true;
          if (size == max_queue_size && max_queue_size > 0) {
            cond->Signal(lock);
          }
          size--;
        }

        if (size == 0) {
          if (thread_count == 0) {
            is_closing = true;
            if (max_queue_size > 0) {
              cond->Signal(lock);
            }
            CloseHandlesAndMaybeDelete();
          }
        } else {
          has_more = true;
        }
      }
    }

    if (popped_value) {
      v8::HandleScope scope(env->isolate);
      CallbackScope cb_scope(this);
      napi_value js_callback = nullptr;
      if (!ref.IsEmpty()) {
        v8::Local<v8::Function> js_cb =
            v8::Local<v8::Function>::New(env->isolate, ref);
        js_callback = v8impl::JsValueFromV8LocalValue(js_cb);
      }
      env->CallbackIntoModule<false>(
          [&](napi_env env) { call_js_cb(env, js_callback, context, data); });
    }

    return has_more;
  }

  void Finalize() {
    v8::HandleScope scope(env->isolate);
    if (finalize_cb) {
      CallbackScope cb_scope(this);
      env->CallFinalizer<false>(finalize_cb, finalize_data, context);
    }
    EmptyQueueAndDelete();
  }

  void CloseHandlesAndMaybeDelete(bool set_closing = false) {
    v8::HandleScope scope(env->isolate);
    if (set_closing) {
      node::Mutex::ScopedLock lock(this->mutex);
      is_closing = true;
      if (max_queue_size > 0) {
        cond->Signal(lock);
      }
    }
    if (handles_closing) {
      return;
    }
    handles_closing = true;
    env->node_env()->CloseHandle(
        reinterpret_cast<uv_handle_t*>(&async),
        [](uv_handle_t* handle) -> void {
          ThreadSafeFunction* ts_fn =
              node::ContainerOf(&ThreadSafeFunction::async,
                                reinterpret_cast<uv_async_t*>(handle));
          ts_fn->Finalize();
        });
  }

  void Send() {
    // Ask currently running Dispatch() to make one more iteration
    unsigned char current_state = dispatch_state.fetch_or(kDispatchPending);
    if ((current_state & kDispatchRunning) == kDispatchRunning) {
      return;
    }

    CHECK_EQ(0, uv_async_send(&async));
  }

  // Default way of calling into JavaScript. Used when ThreadSafeFunction is
  //  without a call_js_cb_.
  static void CallJs(napi_env env, napi_value cb, void* context, void* data) {
    if (!(env == nullptr || cb == nullptr)) {
      napi_value recv;
      napi_status status;

      status = napi_get_undefined(env, &recv);
      if (status != napi_ok) {
        napi_throw_error(env,
                         "ERR_NAPI_TSFN_GET_UNDEFINED",
                         "Failed to retrieve undefined value");
        return;
      }

      status = napi_call_function(env, recv, cb, 0, nullptr, nullptr);
      if (status != napi_ok && status != napi_pending_exception) {
        napi_throw_error(
            env, "ERR_NAPI_TSFN_CALL_JS", "Failed to call JS callback");
        return;
      }
    }
  }

  static void AsyncCb(uv_async_t* async) {
    ThreadSafeFunction* ts_fn =
        node::ContainerOf(&ThreadSafeFunction::async, async);
    ts_fn->Dispatch();
  }

  static void Cleanup(void* data) {
    reinterpret_cast<ThreadSafeFunction*>(data)->CloseHandlesAndMaybeDelete(
        true);
  }

 private:
  static const unsigned char kDispatchIdle = 0;
  static const unsigned char kDispatchRunning = 1 << 0;
  static const unsigned char kDispatchPending = 1 << 1;

  static const unsigned int kMaxIterationCount = 1000;

  // These are variables protected by the mutex.
  node::Mutex mutex;
  std::unique_ptr<node::ConditionVariable> cond;
  std::queue<void*> queue;
  uv_async_t async;
  size_t thread_count;
  bool is_closing;
  std::atomic_uchar dispatch_state;

  // These are variables set once, upon creation, and then never again, which
  // means we don't need the mutex to read them.
  void* context;
  size_t max_queue_size;

  // These are variables accessed only from the loop thread.
  v8impl::Persistent<v8::Function> ref;
  node_napi_env env;
  void* finalize_data;
  napi_finalize finalize_cb;
  napi_threadsafe_function_call_js call_js_cb;
  bool handles_closing;
};

/**
 * Compared to node::AsyncResource, the resource object in AsyncContext is
 * gc-able. AsyncContext holds a weak reference to the resource object.
 * AsyncContext::MakeCallback doesn't implicitly set the receiver of the
 * callback to the resource object.
 */
class AsyncContext {
 public:
  AsyncContext(node_napi_env env,
               v8::Local<v8::Object> resource_object,
               const v8::Local<v8::String> resource_name,
               bool externally_managed_resource)
      : env_(env) {
    async_id_ = node_env()->new_async_id();
    trigger_async_id_ = node_env()->get_default_trigger_async_id();
    v8::Isolate* isolate = node_env()->isolate();
    resource_.Reset(isolate, resource_object);
    context_frame_.Reset(isolate, node::async_context_frame::current(isolate));
    lost_reference_ = false;
    if (externally_managed_resource) {
      resource_.SetWeak(
          this, AsyncContext::WeakCallback, v8::WeakCallbackType::kParameter);
    }

    node::AsyncWrap::EmitAsyncInit(node_env(),
                                   resource_object,
                                   resource_name,
                                   async_id_,
                                   trigger_async_id_);
  }

  ~AsyncContext() {
    resource_.Reset();
    lost_reference_ = true;
    node::AsyncWrap::EmitDestroy(node_env(), async_id_);
  }

  inline v8::MaybeLocal<v8::Value> MakeCallback(
      v8::Local<v8::Object> recv,
      const v8::Local<v8::Function> callback,
      int argc,
      v8::Local<v8::Value> argv[]) {
    EnsureReference();
    return node::InternalMakeCallback(
        node_env(),
        resource(),
        recv,
        callback,
        argc,
        argv,
        {async_id_, trigger_async_id_},
        context_frame_.Get(node_env()->isolate()));
  }

  inline napi_callback_scope OpenCallbackScope() {
    EnsureReference();
    napi_callback_scope it =
        reinterpret_cast<napi_callback_scope>(new CallbackScope(this));
    env_->open_callback_scopes++;
    return it;
  }

  inline void EnsureReference() {
    if (lost_reference_) {
      const v8::HandleScope handle_scope(node_env()->isolate());
      resource_.Reset(node_env()->isolate(),
                      v8::Object::New(node_env()->isolate()));
      lost_reference_ = false;
    }
  }

  inline node::Environment* node_env() { return env_->node_env(); }
  inline v8::Local<v8::Object> resource() {
    return resource_.Get(node_env()->isolate());
  }
  inline node::async_context async_context() {
    return {async_id_, trigger_async_id_};
  }

  static inline void CloseCallbackScope(node_napi_env env,
                                        napi_callback_scope s) {
    CallbackScope* callback_scope = reinterpret_cast<CallbackScope*>(s);
    delete callback_scope;
    env->open_callback_scopes--;
  }

  static void WeakCallback(const v8::WeakCallbackInfo<AsyncContext>& data) {
    AsyncContext* async_context = data.GetParameter();
    async_context->resource_.Reset();
    async_context->lost_reference_ = true;
  }

 private:
  class CallbackScope : public node::CallbackScope {
   public:
    explicit CallbackScope(AsyncContext* async_context)
        : node::CallbackScope(async_context->node_env(),
                              async_context->resource_.Get(
                                  async_context->node_env()->isolate()),
                              async_context->async_context()) {}
  };

  node_napi_env env_;
  double async_id_;
  double trigger_async_id_;
  v8::Global<v8::Object> resource_;
  bool lost_reference_;
  v8::Global<v8::Value> context_frame_;
};

}  // end of anonymous namespace

}  // end of namespace v8impl

// Intercepts the Node-V8 module registration callback. Converts parameters
// to NAPI equivalents and then calls the registration callback specified
// by the NAPI module.
static void napi_module_register_cb(v8::Local<v8::Object> exports,
                                    v8::Local<v8::Value> module,
                                    v8::Local<v8::Context> context,
                                    void* priv) {
  napi_module_register_by_symbol(
      exports,
      module,
      context,
      static_cast<const napi_module*>(priv)->nm_register_func);
}

template <int32_t module_api_version>
static void node_api_context_register_func(v8::Local<v8::Object> exports,
                                           v8::Local<v8::Value> module,
                                           v8::Local<v8::Context> context,
                                           void* priv) {
  napi_module_register_by_symbol(
      exports,
      module,
      context,
      reinterpret_cast<napi_addon_register_func>(priv),
      module_api_version);
}

// This function must be augmented for each new Node API version.
// The key role of this function is to encode module_api_version in the function
// pointer. We are not going to have many Node API versions and having one
// function per version is relatively cheap. It avoids dynamic memory
// allocations or implementing more expensive changes to module registration.
// Currently AddLinkedBinding is the only user of this function.
node::addon_context_register_func get_node_api_context_register_func(
    node::Environment* node_env,
    const char* module_name,
    int32_t module_api_version) {
  static_assert(
      NODE_API_SUPPORTED_VERSION_MAX == 10,
      "New version of Node-API requires adding another else-if statement below "
      "for the new version and updating this assert condition.");
  if (module_api_version == 9) {
    return node_api_context_register_func<9>;
  } else if (module_api_version == 10) {
    return node_api_context_register_func<10>;
  } else if (module_api_version == NAPI_VERSION_EXPERIMENTAL) {
    return node_api_context_register_func<NAPI_VERSION_EXPERIMENTAL>;
  } else if (module_api_version >= NODE_API_SUPPORTED_VERSION_MIN &&
             module_api_version <= NODE_API_DEFAULT_MODULE_API_VERSION) {
    return node_api_context_register_func<NODE_API_DEFAULT_MODULE_API_VERSION>;
  } else {
    v8impl::ThrowNodeApiVersionError(node_env, module_name, module_api_version);
    return nullptr;
  }
}

void napi_module_register_by_symbol(v8::Local<v8::Object> exports,
                                    v8::Local<v8::Value> module,
                                    v8::Local<v8::Context> context,
                                    napi_addon_register_func init,
                                    int32_t module_api_version) {
  node::Environment* node_env = node::Environment::GetCurrent(context);
  CHECK_NOT_NULL(node_env);
  std::string module_filename = "";
  if (init == nullptr) {
    node_env->ThrowError("Module has no declared entry point.");
    return;
  }

  // We set `env->filename` from `module.filename` here, but we could just as
  // easily add a private property to `exports` in `process.dlopen`, which
  // receives the file name from JS, and retrieve *that* here. Thus, we are not
  // endorsing commonjs here by making use of `module.filename`.
  v8::Local<v8::Value> filename_js;
  v8::Local<v8::Object> modobj;
  if (module->ToObject(context).ToLocal(&modobj) &&
      modobj->Get(context, node_env->filename_string()).ToLocal(&filename_js) &&
      filename_js->IsString()) {
    node::Utf8Value filename(node_env->isolate(), filename_js);

    // Turn the absolute path into a URL. Currently the absolute path is always
    // a file system path.
    // TODO(gabrielschulhof): Pass the `filename` through unchanged if/when we
    // receive it as a URL already.
    module_filename = node::url::FromFilePath(filename.ToStringView());
  }

  // Create a new napi_env for this specific module.
  napi_env env =
      node_napi_env__::New(context, module_filename, module_api_version);

  napi_value _exports = nullptr;
  env->CallIntoModule([&](napi_env env) {
    _exports = init(env, v8impl::JsValueFromV8LocalValue(exports));
  });

  // If register function returned a non-null exports object different from
  // the exports object we passed it, set that as the "exports" property of
  // the module.
  if (_exports != nullptr &&
      _exports != v8impl::JsValueFromV8LocalValue(exports)) {
    napi_value _module = v8impl::JsValueFromV8LocalValue(module);
    napi_set_named_property(env, _module, "exports", _exports);
  }
}

namespace node {
node_module napi_module_to_node_module(const napi_module* mod) {
  return {
      -1,
      mod->nm_flags | NM_F_DELETEME,
      nullptr,
      mod->nm_filename,
      nullptr,
      napi_module_register_cb,
      mod->nm_modname,
      const_cast<napi_module*>(mod),  // priv
      nullptr,
  };
}
}  // namespace node

// Registers a NAPI module.
void NAPI_CDECL napi_module_register(napi_module* mod) {
  node::node_module* nm =
      new node::node_module(node::napi_module_to_node_module(mod));
  node::node_module_register(nm);
}

napi_status NAPI_CDECL napi_add_env_cleanup_hook(node_api_basic_env env,
                                                 napi_cleanup_hook fun,
                                                 void* arg) {
  CHECK_ENV(env);
  CHECK_ARG(env, fun);

  node::AddEnvironmentCleanupHook(env->isolate, fun, arg);

  return napi_ok;
}

napi_status NAPI_CDECL napi_remove_env_cleanup_hook(node_api_basic_env env,
                                                    napi_cleanup_hook fun,
                                                    void* arg) {
  CHECK_ENV(env);
  CHECK_ARG(env, fun);

  node::RemoveEnvironmentCleanupHook(env->isolate, fun, arg);

  return napi_ok;
}

struct napi_async_cleanup_hook_handle__ {
  napi_async_cleanup_hook_handle__(napi_env env,
                                   napi_async_cleanup_hook user_hook,
                                   void* user_data)
      : env_(env), user_hook_(user_hook), user_data_(user_data) {
    handle_ = node::AddEnvironmentCleanupHook(env->isolate, Hook, this);
    env->Ref();
  }

  ~napi_async_cleanup_hook_handle__() {
    node::RemoveEnvironmentCleanupHook(std::move(handle_));
    if (done_cb_ != nullptr) done_cb_(done_data_);

    // Release the `env` handle asynchronously since it would be surprising if
    // a call to a N-API function would destroy `env` synchronously.
    static_cast<node_napi_env>(env_)->node_env()->SetImmediate(
        [env = env_](node::Environment*) { env->Unref(); });
  }

  static void Hook(void* data, void (*done_cb)(void*), void* done_data) {
    napi_async_cleanup_hook_handle__* handle =
        static_cast<napi_async_cleanup_hook_handle__*>(data);
    handle->done_cb_ = done_cb;
    handle->done_data_ = done_data;
    handle->user_hook_(handle, handle->user_data_);
  }

  node::AsyncCleanupHookHandle handle_;
  napi_env env_ = nullptr;
  napi_async_cleanup_hook user_hook_ = nullptr;
  void* user_data_ = nullptr;
  void (*done_cb_)(void*) = nullptr;
  void* done_data_ = nullptr;
};

napi_status NAPI_CDECL
napi_add_async_cleanup_hook(node_api_basic_env basic_env,
                            napi_async_cleanup_hook hook,
                            void* arg,
                            napi_async_cleanup_hook_handle* remove_handle) {
  napi_env env = const_cast<napi_env>(basic_env);
  CHECK_ENV(env);
  CHECK_ARG(env, hook);

  napi_async_cleanup_hook_handle__* handle =
      new napi_async_cleanup_hook_handle__(env, hook, arg);

  if (remove_handle != nullptr) *remove_handle = handle;

  return napi_clear_last_error(env);
}

napi_status NAPI_CDECL
napi_remove_async_cleanup_hook(napi_async_cleanup_hook_handle remove_handle) {
  if (remove_handle == nullptr) return napi_invalid_arg;

  delete remove_handle;

  return napi_ok;
}

napi_status NAPI_CDECL napi_fatal_exception(napi_env env, napi_value err) {
  NAPI_PREAMBLE(env);
  CHECK_ARG(env, err);

  v8::Local<v8::Value> local_err = v8impl::V8LocalValueFromJsValue(err);
  static_cast<node_napi_env>(env)->trigger_fatal_exception(local_err);

  return napi_clear_last_error(env);
}

NAPI_NO_RETURN void NAPI_CDECL napi_fatal_error(const char* location,
                                                size_t location_len,
                                                const char* message,
                                                size_t message_len) {
  std::string location_string;
  std::string message_string;

  if (location_len != NAPI_AUTO_LENGTH) {
    location_string.assign(const_cast<char*>(location), location_len);
  } else {
    location_string.assign(const_cast<char*>(location), strlen(location));
  }

  if (message_len != NAPI_AUTO_LENGTH) {
    message_string.assign(const_cast<char*>(message), message_len);
  } else {
    message_string.assign(const_cast<char*>(message), strlen(message));
  }

  node::OnFatalError(location_string.c_str(), message_string.c_str());
}

napi_status NAPI_CDECL
napi_open_callback_scope(napi_env env,
                         napi_value /** ignored */,
                         napi_async_context async_context_handle,
                         napi_callback_scope* result) {
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
  // JS exceptions.
  CHECK_ENV(env);
  CHECK_ARG(env, result);

  v8impl::AsyncContext* node_async_context =
      reinterpret_cast<v8impl::AsyncContext*>(async_context_handle);

  *result = node_async_context->OpenCallbackScope();

  return napi_clear_last_error(env);
}

napi_status NAPI_CDECL napi_close_callback_scope(napi_env env,
                                                 napi_callback_scope scope) {
  // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
  // JS exceptions.
  CHECK_ENV(env);
  CHECK_ARG(env, scope);
  if (env->open_callback_scopes == 0) {
    return napi_callback_scope_mismatch;
  }

  v8impl::AsyncContext::CloseCallbackScope(reinterpret_cast<node_napi_env>(env),
                                           scope);

  return napi_clear_last_error(env);
}

napi_status NAPI_CDECL napi_async_init(napi_env env,
                                       napi_value async_resource,
                                       napi_value async_resource_name,
                                       napi_async_context* result) {
  CHECK_ENV_NOT_IN_GC(env);
  CHECK_ARG(env, async_resource_name);
  CHECK_ARG(env, result);

  v8::Isolate* isolate = env->isolate;
  v8::Local<v8::Context> context = env->context();

  v8::Local<v8::Object> v8_resource;
  bool externally_managed_resource;
  if (async_resource != nullptr) {
    CHECK_TO_OBJECT(env, context, v8_resource, async_resource);
    externally_managed_resource = true;
  } else {
    v8_resource = v8::Object::New(isolate);
    externally_managed_resource = false;
  }

  v8::Local<v8::String> v8_resource_name;
  CHECK_TO_STRING(env, context, v8_resource_name, async_resource_name);

  v8impl::AsyncContext* async_context =
      new v8impl::AsyncContext(reinterpret_cast<node_napi_env>(env),
                               v8_resource,
                               v8_resource_name,
                               externally_managed_resource);

  *result = reinterpret_cast<napi_async_context>(async_context);

  return napi_clear_last_error(env);
}

napi_status NAPI_CDECL napi_async_destroy(napi_env env,
                                          napi_async_context async_context) {
  CHECK_ENV_NOT_IN_GC(env);
  CHECK_ARG(env, async_context);

  v8impl::AsyncContext* node_async_context =
      reinterpret_cast<v8impl::AsyncContext*>(async_context);

  delete node_async_context;

  return napi_clear_last_error(env);
}

napi_status NAPI_CDECL napi_make_callback(napi_env env,
                                          napi_async_context async_context,
                                          napi_value recv,
                                          napi_value func,
                                          size_t argc,
                                          const napi_value* argv,
                                          napi_value* result) {
  NAPI_PREAMBLE(env);
  CHECK_ARG(env, recv);
  if (argc > 0) {
    CHECK_ARG(env, argv);
  }

  v8::Local<v8::Context> context = env->context();

  v8::Local<v8::Object> v8recv;
  CHECK_TO_OBJECT(env, context, v8recv, recv);

  v8::Local<v8::Function> v8func;
  CHECK_TO_FUNCTION(env, v8func, func);

  v8::MaybeLocal<v8::Value> callback_result;

  if (async_context == nullptr) {
    callback_result = node::MakeCallback(
        env->isolate,
        v8recv,
        v8func,
        argc,
        reinterpret_cast<v8::Local<v8::Value>*>(const_cast<napi_value*>(argv)),
        {0, 0});
  } else {
    v8impl::AsyncContext* node_async_context =
        reinterpret_cast<v8impl::AsyncContext*>(async_context);
    callback_result = node_async_context->MakeCallback(
        v8recv,
        v8func,
        argc,
        reinterpret_cast<v8::Local<v8::Value>*>(const_cast<napi_value*>(argv)));
  }

  if (try_catch.HasCaught()) {
    return napi_set_last_error(env, napi_pending_exception);
  } else {
    CHECK_MAYBE_EMPTY(env, callback_result, napi_generic_failure);
    if (result != nullptr) {
      *result =
          v8impl::JsValueFromV8LocalValue(callback_result.ToLocalChecked());
    }
  }

  return GET_RETURN_STATUS(env);
}

napi_status NAPI_CDECL napi_create_buffer(napi_env env,
                                          size_t length,
                                          void** data,
                                          napi_value* result) {
  NAPI_PREAMBLE(env);
  CHECK_ARG(env, result);

  v8::MaybeLocal<v8::Object> maybe = node::Buffer::New(env->isolate, length);

  CHECK_MAYBE_EMPTY(env, maybe, napi_generic_failure);

  v8::Local<v8::Object> buffer = maybe.ToLocalChecked();

  *result = v8impl::JsValueFromV8LocalValue(buffer);

  if (data != nullptr) {
    *data = node::Buffer::Data(buffer);
  }

  return GET_RETURN_STATUS(env);
}

napi_status NAPI_CDECL
napi_create_external_buffer(napi_env env,
                            size_t length,
                            void* data,
                            node_api_basic_finalize basic_finalize_cb,
                            void* finalize_hint,
                            napi_value* result) {
  napi_finalize finalize_cb =
      reinterpret_cast<napi_finalize>(basic_finalize_cb);
  NAPI_PREAMBLE(env);
  CHECK_ARG(env, result);

#ifdef V8_ENABLE_SANDBOX
  return napi_set_last_error(env, napi_no_external_buffers_allowed);
#endif  // V8_ENABLE_SANDBOX

  v8::Isolate* isolate = env->isolate;

  // The finalizer object will delete itself after invoking the callback.
  v8impl::BufferFinalizer* finalizer =
      v8impl::BufferFinalizer::New(env, finalize_cb, data, finalize_hint);

  v8::MaybeLocal<v8::Object> maybe =
      node::Buffer::New(isolate,
                        static_cast<char*>(data),
                        length,
                        v8impl::BufferFinalizer::FinalizeBufferCallback,
                        finalizer);

  CHECK_MAYBE_EMPTY(env, maybe, napi_generic_failure);

  *result = v8impl::JsValueFromV8LocalValue(maybe.ToLocalChecked());
  return GET_RETURN_STATUS(env);
  // Tell coverity that 'finalizer' should not be freed when we return
  // as it will be deleted when the buffer to which it is associated
  // is finalized.
  // coverity[leaked_storage]
}

napi_status NAPI_CDECL napi_create_buffer_copy(napi_env env,
                                               size_t length,
                                               const void* data,
                                               void** result_data,
                                               napi_value* result) {
  NAPI_PREAMBLE(env);
  CHECK_ARG(env, result);

  v8::MaybeLocal<v8::Object> maybe =
      node::Buffer::Copy(env->isolate, static_cast<const char*>(data), length);

  CHECK_MAYBE_EMPTY(env, maybe, napi_generic_failure);

  v8::Local<v8::Object> buffer = maybe.ToLocalChecked();
  *result = v8impl::JsValueFromV8LocalValue(buffer);

  if (result_data != nullptr) {
    *result_data = node::Buffer::Data(buffer);
  }

  return GET_RETURN_STATUS(env);
}

napi_status NAPI_CDECL napi_is_buffer(napi_env env,
                                      napi_value value,
                                      bool* result) {
  CHECK_ENV_NOT_IN_GC(env);
  CHECK_ARG(env, value);
  CHECK_ARG(env, result);

  *result = node::Buffer::HasInstance(v8impl::V8LocalValueFromJsValue(value));
  return napi_clear_last_error(env);
}

napi_status NAPI_CDECL napi_get_buffer_info(napi_env env,
                                            napi_value value,
                                            void** data,
                                            size_t* length) {
  CHECK_ENV_NOT_IN_GC(env);
  CHECK_ARG(env, value);

  v8::Local<v8::Value> buffer = v8impl::V8LocalValueFromJsValue(value);
  RETURN_STATUS_IF_FALSE(
      env, node::Buffer::HasInstance(buffer), napi_invalid_arg);

  if (data != nullptr) {
    *data = node::Buffer::Data(buffer);
  }
  if (length != nullptr) {
    *length = node::Buffer::Length(buffer);
  }

  return napi_clear_last_error(env);
}

napi_status NAPI_CDECL napi_get_node_version(node_api_basic_env env,
                                             const napi_node_version** result) {
  CHECK_ENV(env);
  CHECK_ARG(env, result);
  static const napi_node_version version = {
      NODE_MAJOR_VERSION, NODE_MINOR_VERSION, NODE_PATCH_VERSION, NODE_RELEASE};
  *result = &version;
  return napi_clear_last_error(env);
}

namespace {
namespace uvimpl {

static napi_status ConvertUVErrorCode(int code) {
  switch (code) {
    case 0:
      return napi_ok;
    case UV_EINVAL:
      return napi_invalid_arg;
    case UV_ECANCELED:
      return napi_cancelled;
    default:
      return napi_generic_failure;
  }
}

// Wrapper around uv_work_t which calls user-provided callbacks.
class Work : public node::AsyncResource, public node::ThreadPoolWork {
 private:
  explicit Work(node_napi_env env,
                v8::Local<v8::Object> async_resource,
                v8::Local<v8::String> async_resource_name,
                napi_async_execute_callback execute,
                napi_async_complete_callback complete = nullptr,
                void* data = nullptr)
      : AsyncResource(
            env->isolate,
            async_resource,
            *v8::String::Utf8Value(env->isolate, async_resource_name)),
        ThreadPoolWork(env->node_env(), "node_api"),
        _env(env),
        _data(data),
        _execute(execute),
        _complete(complete) {}

  ~Work() override = default;

 public:
  static Work* New(node_napi_env env,
                   v8::Local<v8::Object> async_resource,
                   v8::Local<v8::String> async_resource_name,
                   napi_async_execute_callback execute,
                   napi_async_complete_callback complete,
                   void* data) {
    return new Work(
        env, async_resource, async_resource_name, execute, complete, data);
  }

  static void Delete(Work* work) { delete work; }

  void DoThreadPoolWork() override { _execute(_env, _data); }

  void AfterThreadPoolWork(int status) override {
    if (_complete == nullptr) return;

    // Establish a handle scope here so that every callback doesn't have to.
    // Also it is needed for the exception-handling below.
    v8::HandleScope scope(_env->isolate);

    CallbackScope callback_scope(this);

    _env->CallbackIntoModule<true>([&](napi_env env) {
      _complete(env, ConvertUVErrorCode(status), _data);
    });

    // Note: Don't access `work` after this point because it was
    // likely deleted by the complete callback.
  }

 private:
  node_napi_env _env;
  void* _data;
  napi_async_execute_callback _execute;
  napi_async_complete_callback _complete;
};

}  // end of namespace uvimpl
}  // end of anonymous namespace

#define CALL_UV(env, condition)                                                \
  do {                                                                         \
    int result = (condition);                                                  \
    napi_status status = uvimpl::ConvertUVErrorCode(result);                   \
    if (status != napi_ok) {                                                   \
      return napi_set_last_error(env, status, result);                         \
    }                                                                          \
  } while (0)

napi_status NAPI_CDECL
napi_create_async_work(napi_env env,
                       napi_value async_resource,
                       napi_value async_resource_name,
                       napi_async_execute_callback execute,
                       napi_async_complete_callback complete,
                       void* data,
                       napi_async_work* result) {
  CHECK_ENV_NOT_IN_GC(env);
  CHECK_ARG(env, execute);
  CHECK_ARG(env, result);

  v8::Local<v8::Context> context = env->context();

  v8::Local<v8::Object> resource;
  if (async_resource != nullptr) {
    CHECK_TO_OBJECT(env, context, resource, async_resource);
  } else {
    resource = v8::Object::New(env->isolate);
  }

  v8::Local<v8::String> resource_name;
  CHECK_TO_STRING(env, context, resource_name, async_resource_name);

  uvimpl::Work* work = uvimpl::Work::New(reinterpret_cast<node_napi_env>(env),
                                         resource,
                                         resource_name,
                                         execute,
                                         complete,
                                         data);

  *result = reinterpret_cast<napi_async_work>(work);

  return napi_clear_last_error(env);
}

napi_status NAPI_CDECL napi_delete_async_work(napi_env env,
                                              napi_async_work work) {
  CHECK_ENV_NOT_IN_GC(env);
  CHECK_ARG(env, work);

  uvimpl::Work::Delete(reinterpret_cast<uvimpl::Work*>(work));

  return napi_clear_last_error(env);
}

napi_status NAPI_CDECL napi_get_uv_event_loop(node_api_basic_env basic_env,
                                              uv_loop_t** loop) {
  napi_env env = const_cast<napi_env>(basic_env);
  CHECK_ENV(env);
  CHECK_ARG(env, loop);
  *loop = reinterpret_cast<node_napi_env>(env)->node_env()->event_loop();
  return napi_clear_last_error(env);
}

napi_status NAPI_CDECL napi_queue_async_work(node_api_basic_env env,
                                             napi_async_work work) {
  CHECK_ENV(env);
  CHECK_ARG(env, work);

  uv_loop_t* event_loop = nullptr;
  STATUS_CALL(napi_get_uv_event_loop(env, &event_loop));

  uvimpl::Work* w = reinterpret_cast<uvimpl::Work*>(work);

  w->ScheduleWork();

  return napi_clear_last_error(env);
}

napi_status NAPI_CDECL napi_cancel_async_work(node_api_basic_env env,
                                              napi_async_work work) {
  CHECK_ENV(env);
  CHECK_ARG(env, work);

  uvimpl::Work* w = reinterpret_cast<uvimpl::Work*>(work);

  CALL_UV(env, w->CancelWork());

  return napi_clear_last_error(env);
}

napi_status NAPI_CDECL
napi_create_threadsafe_function(napi_env env,
                                napi_value func,
                                napi_value async_resource,
                                napi_value async_resource_name,
                                size_t max_queue_size,
                                size_t initial_thread_count,
                                void* thread_finalize_data,
                                napi_finalize thread_finalize_cb,
                                void* context,
                                napi_threadsafe_function_call_js call_js_cb,
                                napi_threadsafe_function* result) {
  CHECK_ENV_NOT_IN_GC(env);
  CHECK_ARG(env, async_resource_name);
  RETURN_STATUS_IF_FALSE(env, initial_thread_count > 0, napi_invalid_arg);
  CHECK_ARG(env, result);

  napi_status status = napi_ok;

  v8::Local<v8::Function> v8_func;
  if (func == nullptr) {
    CHECK_ARG(env, call_js_cb);
  } else {
    CHECK_TO_FUNCTION(env, v8_func, func);
  }

  v8::Local<v8::Context> v8_context = env->context();

  v8::Local<v8::Object> v8_resource;
  if (async_resource == nullptr) {
    v8_resource = v8::Object::New(env->isolate);
  } else {
    CHECK_TO_OBJECT(env, v8_context, v8_resource, async_resource);
  }

  v8::Local<v8::String> v8_name;
  CHECK_TO_STRING(env, v8_context, v8_name, async_resource_name);

  v8impl::ThreadSafeFunction* ts_fn =
      new v8impl::ThreadSafeFunction(v8_func,
                                     v8_resource,
                                     v8_name,
                                     initial_thread_count,
                                     context,
                                     max_queue_size,
                                     reinterpret_cast<node_napi_env>(env),
                                     thread_finalize_data,
                                     thread_finalize_cb,
                                     call_js_cb);

  if (ts_fn == nullptr) {
    status = napi_generic_failure;
  } else {
    // Init deletes ts_fn upon failure.
    status = ts_fn->Init();
    if (status == napi_ok) {
      *result = reinterpret_cast<napi_threadsafe_function>(ts_fn);
    }
  }

  return napi_set_last_error(env, status);
}

napi_status NAPI_CDECL napi_get_threadsafe_function_context(
    napi_threadsafe_function func, void** result) {
  CHECK_NOT_NULL(func);
  CHECK_NOT_NULL(result);

  *result = reinterpret_cast<v8impl::ThreadSafeFunction*>(func)->Context();
  return napi_ok;
}

napi_status NAPI_CDECL
napi_call_threadsafe_function(napi_threadsafe_function func,
                              void* data,
                              napi_threadsafe_function_call_mode is_blocking) {
  CHECK_NOT_NULL(func);
  return reinterpret_cast<v8impl::ThreadSafeFunction*>(func)->Push(data,
                                                                   is_blocking);
}

napi_status NAPI_CDECL
napi_acquire_threadsafe_function(napi_threadsafe_function func) {
  CHECK_NOT_NULL(func);
  return reinterpret_cast<v8impl::ThreadSafeFunction*>(func)->Acquire();
}

napi_status NAPI_CDECL napi_release_threadsafe_function(
    napi_threadsafe_function func, napi_threadsafe_function_release_mode mode) {
  CHECK_NOT_NULL(func);
  return reinterpret_cast<v8impl::ThreadSafeFunction*>(func)->Release(mode);
}

napi_status NAPI_CDECL napi_unref_threadsafe_function(
    node_api_basic_env env, napi_threadsafe_function func) {
  CHECK_NOT_NULL(func);
  return reinterpret_cast<v8impl::ThreadSafeFunction*>(func)->Unref();
}

napi_status NAPI_CDECL napi_ref_threadsafe_function(
    node_api_basic_env env, napi_threadsafe_function func) {
  CHECK_NOT_NULL(func);
  return reinterpret_cast<v8impl::ThreadSafeFunction*>(func)->Ref();
}

napi_status NAPI_CDECL node_api_get_module_file_name(
    node_api_basic_env basic_env, const char** result) {
  napi_env env = const_cast<napi_env>(basic_env);
  CHECK_ENV(env);
  CHECK_ARG(env, result);

  *result = static_cast<node_napi_env>(env)->GetFilename();
  return napi_clear_last_error(env);
}

#ifdef NAPI_EXPERIMENTAL

napi_status NAPI_CDECL
node_api_create_buffer_from_arraybuffer(napi_env env,
                                        napi_value arraybuffer,
                                        size_t byte_offset,
                                        size_t byte_length,
                                        napi_value* result) {
  NAPI_PREAMBLE(env);
  CHECK_ARG(env, arraybuffer);
  CHECK_ARG(env, result);

  v8::Local<v8::Value> arraybuffer_value =
      v8impl::V8LocalValueFromJsValue(arraybuffer);
  if (!arraybuffer_value->IsArrayBuffer()) {
    return napi_invalid_arg;
  }

  v8::Local<v8::ArrayBuffer> arraybuffer_obj =
      arraybuffer_value.As<v8::ArrayBuffer>();
  if (byte_offset + byte_length > arraybuffer_obj->ByteLength()) {
    return napi_throw_range_error(
        env, "ERR_OUT_OF_RANGE", "The byte offset + length is out of range");
  }

  v8::Local<v8::Object> buffer =
      node::Buffer::New(env->isolate, arraybuffer_obj, byte_offset, byte_length)
          .ToLocalChecked();

  *result = v8impl::JsValueFromV8LocalValue(buffer);
  return napi_ok;
}

#endif
