wasmer-napi 0.702.0-alpha.3

NAPI library for Wasmer WebAssembly runtime
#include "internal/napi_scope.h"

#include "internal/napi_env.h"
#include "internal/napi_lifetime_tracker.h"

napi_scope__::napi_scope__(napi_env env, napi_handle_scope parent)
    : values_{this}, env_{env}, parent_{parent}
{
  napi_scope__ *parent_scope = this->parent();
  level_ = parent_scope == nullptr ? 0 : parent_scope->level() + 1;
}

napi_scope__::~napi_scope__()
{
  close();
}

bool napi_scope__::is_active() const
{
  return env_ != nullptr;
}

size_t napi_scope__::level() const
{
  return level_;
}

napi_value napi_scope__::wrap_value(JSValue value, bool owned)
{
  return wrap_value(env_ == nullptr ? nullptr : env_->context(), value, owned);
}

napi_value napi_scope__::wrap_value(JSContext *context, JSValue value, bool owned)
{
  if (closed_)
  {
    if (owned && env_ != nullptr && context != nullptr)
      JS_FreeValue(context, value);
    return nullptr;
  }

  napi_value wrapped = values_.allocate(env_, context, value, owned);
  if (wrapped == nullptr)
  {
    if (owned && env_ != nullptr && context != nullptr)
      JS_FreeValue(context, value);
    return nullptr;
  }

  return wrapped;
}

napi_value napi_scope__::escape_value(napi_value value)
{
  auto record_escape = [this](napi_value escaped)
  {
    quickjs::detail::napi_lifetime_tracker__::record_scope_escape(env_, escaped != nullptr);
    return escaped;
  };

  if (parent_ == nullptr || value == nullptr)
    return record_escape(nullptr);

  napi_scope__ *owner = ValuesAllocator::unsafe_owner(value);
  assert(owner == this);

  if (owner != this)
    return record_escape(nullptr);

  napi_scope__ *parent_scope = parent();
  return record_escape(parent_scope == nullptr ? nullptr : parent_scope->wrap_value(value->context(), value->get_inner(), false));
}

void napi_scope__::delete_value(napi_value value)
{
  if (value == nullptr)
    return;

  napi_scope__ *owner = ValuesAllocator::unsafe_owner(value);

  if (owner == this)
  {
    values_.destroy(value);
  }
}

void napi_scope__::close()
{
  if (closed_)
    return;

  values_.close();
  closed_ = true;
}

size_t napi_scope__::value_slot_count() const
{
  return values_.slot_count();
}

size_t napi_scope__::value_storage_slot_count() const
{
  return values_.storage_slot_count();
}

size_t napi_scope__::active_value_count() const
{
  return values_.count_active();
}

napi_handle_scope napi_scope__::parent_handle() const
{
  return parent_;
}

napi_scope__ *napi_scope__::parent() const
{
  return env_ == nullptr || parent_ == nullptr ? nullptr : env_->scope_from_handle(parent_);
}

napi_env napi_scope__::env() const
{
  return env_;
}

bool napi_scope__::has_escaped() const
{
  return escaped_;
}

void napi_scope__::mark_escaped()
{
  escaped_ = true;
}