#include "node_messaging.h"

#include "async_wrap-inl.h"
#include "debug_utils-inl.h"
#include "memory_tracker-inl.h"
#include "node_buffer.h"
#include "node_contextify.h"
#include "node_errors.h"
#include "node_external_reference.h"
#include "node_process-inl.h"
#include "util-inl.h"

using node::contextify::ContextifyContext;
using node::errors::TryCatchScope;
using v8::Array;
using v8::ArrayBuffer;
using v8::BackingStore;
using v8::CompiledWasmModule;
using v8::Context;
using v8::EscapableHandleScope;
using v8::Function;
using v8::FunctionCallbackInfo;
using v8::FunctionTemplate;
using v8::Global;
using v8::HandleScope;
using v8::Isolate;
using v8::Just;
using v8::Local;
using v8::Maybe;
using v8::MaybeLocal;
using v8::Nothing;
using v8::Object;
using v8::ObjectTemplate;
using v8::SharedArrayBuffer;
using v8::SharedValueConveyor;
using v8::String;
using v8::Symbol;
using v8::Value;
using v8::ValueDeserializer;
using v8::ValueSerializer;
using v8::WasmModuleObject;

namespace node {

using BaseObjectList = std::vector<BaseObjectPtr<BaseObject>>;
using TransferMode = BaseObject::TransferMode;

// Hack to have WriteHostObject inform ReadHostObject that the value
// should be treated as a regular JS object. Used to transfer process.env.
static const uint32_t kNormalObject = static_cast<uint32_t>(-1);

namespace worker {

Maybe<bool> TransferData::FinalizeTransferWrite(
    Local<Context> context, ValueSerializer* serializer) {
  return Just(true);
}

Message::Message(MallocedBuffer<char>&& buffer)
    : main_message_buf_(std::move(buffer)) {}

bool Message::IsCloseMessage() const {
  return main_message_buf_.data == nullptr;
}

namespace {

// This is used to tell V8 how to read transferred host objects, like other
// `MessagePort`s and `SharedArrayBuffer`s, and make new JS objects out of them.
class DeserializerDelegate : public ValueDeserializer::Delegate {
 public:
  DeserializerDelegate(
      Message* m,
      Environment* env,
      const std::vector<BaseObjectPtr<BaseObject>>& host_objects,
      const std::vector<Local<SharedArrayBuffer>>& shared_array_buffers,
      const std::vector<CompiledWasmModule>& wasm_modules,
      const std::optional<SharedValueConveyor>& shared_value_conveyor)
      : env_(env),
        host_objects_(host_objects),
        shared_array_buffers_(shared_array_buffers),
        wasm_modules_(wasm_modules),
        shared_value_conveyor_(shared_value_conveyor) {}

  MaybeLocal<Object> ReadHostObject(Isolate* isolate) override {
    // Identifying the index in the message's BaseObject array is sufficient.
    uint32_t id;
    if (!deserializer->ReadUint32(&id))
      return MaybeLocal<Object>();
    if (id != kNormalObject) {
      CHECK_LT(id, host_objects_.size());
      Local<Object> object = host_objects_[id]->object(isolate);
      if (env_->js_transferable_constructor_template()->HasInstance(object)) {
        return Unwrap<JSTransferable>(object)->target();
      } else {
        return object;
      }
    }
    EscapableHandleScope scope(isolate);
    Local<Context> context = isolate->GetCurrentContext();
    Local<Value> object;
    if (!deserializer->ReadValue(context).ToLocal(&object))
      return MaybeLocal<Object>();
    CHECK(object->IsObject());
    return scope.Escape(object.As<Object>());
  }

  MaybeLocal<SharedArrayBuffer> GetSharedArrayBufferFromId(
      Isolate* isolate, uint32_t clone_id) override {
    CHECK_LT(clone_id, shared_array_buffers_.size());
    return shared_array_buffers_[clone_id];
  }

  MaybeLocal<WasmModuleObject> GetWasmModuleFromId(
      Isolate* isolate, uint32_t transfer_id) override {
    CHECK_LT(transfer_id, wasm_modules_.size());
    return WasmModuleObject::FromCompiledModule(
        isolate, wasm_modules_[transfer_id]);
  }

  const SharedValueConveyor* GetSharedValueConveyor(Isolate* isolate) override {
    CHECK(shared_value_conveyor_.has_value());
    return &shared_value_conveyor_.value();
  }

  ValueDeserializer* deserializer = nullptr;

 private:
  Environment* env_;
  const std::vector<BaseObjectPtr<BaseObject>>& host_objects_;
  const std::vector<Local<SharedArrayBuffer>>& shared_array_buffers_;
  const std::vector<CompiledWasmModule>& wasm_modules_;
  const std::optional<SharedValueConveyor>& shared_value_conveyor_;
};

}  // anonymous namespace

MaybeLocal<Value> Message::Deserialize(Environment* env,
                                       Local<Context> context,
                                       Local<Value>* port_list) {
  Context::Scope context_scope(context);

  CHECK(!IsCloseMessage());
  if (port_list != nullptr && !transferables_.empty()) {
    // Need to create this outside of the EscapableHandleScope, but inside
    // the Context::Scope.
    *port_list = Array::New(env->isolate());
  }

  EscapableHandleScope handle_scope(env->isolate());

  // Create all necessary objects for transferables, e.g. MessagePort handles.
  std::vector<BaseObjectPtr<BaseObject>> host_objects(transferables_.size());
  auto cleanup = OnScopeLeave([&]() {
    for (BaseObjectPtr<BaseObject> object : host_objects) {
      if (!object) continue;

      // If the function did not finish successfully, host_objects will contain
      // a list of objects that will never be passed to JS. Therefore, we
      // destroy them here.
      object->Detach();
    }
  });

  for (uint32_t i = 0; i < transferables_.size(); ++i) {
    HandleScope handle_scope(env->isolate());
    TransferData* data = transferables_[i].get();
    host_objects[i] = data->Deserialize(
        env, context, std::move(transferables_[i]));
    if (!host_objects[i]) return {};
    if (port_list != nullptr) {
      // If we gather a list of all message ports, and this transferred object
      // is a message port, add it to that list. This is a bit of an odd case
      // of special handling for MessagePorts (as opposed to applying to all
      // transferables), but it's required for spec compliance.
      DCHECK((*port_list)->IsArray());
      Local<Array> port_list_array = port_list->As<Array>();
      Local<Object> obj = host_objects[i]->object();
      if (env->message_port_constructor_template()->HasInstance(obj)) {
        if (port_list_array->Set(context,
                                 port_list_array->Length(),
                                 obj).IsNothing()) {
          return {};
        }
      }
    }
  }
  transferables_.clear();

  std::vector<Local<SharedArrayBuffer>> shared_array_buffers;
  // Attach all transferred SharedArrayBuffers to their new Isolate.
  for (uint32_t i = 0; i < shared_array_buffers_.size(); ++i) {
    Local<SharedArrayBuffer> sab =
        SharedArrayBuffer::New(env->isolate(), shared_array_buffers_[i]);
    shared_array_buffers.push_back(sab);
  }

  DeserializerDelegate delegate(this,
                                env,
                                host_objects,
                                shared_array_buffers,
                                wasm_modules_,
                                shared_value_conveyor_);
  ValueDeserializer deserializer(
      env->isolate(),
      reinterpret_cast<const uint8_t*>(main_message_buf_.data),
      main_message_buf_.size,
      &delegate);
  delegate.deserializer = &deserializer;

  // Attach all transferred ArrayBuffers to their new Isolate.
  for (uint32_t i = 0; i < array_buffers_.size(); ++i) {
    Local<ArrayBuffer> ab =
        ArrayBuffer::New(env->isolate(), std::move(array_buffers_[i]));
    deserializer.TransferArrayBuffer(i, ab);
  }

  if (deserializer.ReadHeader(context).IsNothing())
    return {};
  Local<Value> return_value;
  if (!deserializer.ReadValue(context).ToLocal(&return_value))
    return {};

  for (BaseObjectPtr<BaseObject> base_object : host_objects) {
    if (base_object->FinalizeTransferRead(context, &deserializer).IsNothing())
      return {};
  }

  host_objects.clear();
  return handle_scope.Escape(return_value);
}

void Message::AddSharedArrayBuffer(
    std::shared_ptr<BackingStore> backing_store) {
  shared_array_buffers_.emplace_back(std::move(backing_store));
}

void Message::AddTransferable(std::unique_ptr<TransferData>&& data) {
  transferables_.emplace_back(std::move(data));
}

uint32_t Message::AddWASMModule(CompiledWasmModule&& mod) {
  wasm_modules_.emplace_back(std::move(mod));
  return wasm_modules_.size() - 1;
}

void Message::AdoptSharedValueConveyor(SharedValueConveyor&& conveyor) {
  shared_value_conveyor_.emplace(std::move(conveyor));
}

namespace {

MaybeLocal<Function> GetEmitMessageFunction(Local<Context> context) {
  Isolate* isolate = context->GetIsolate();
  Local<Object> per_context_bindings;
  Local<Value> emit_message_val;
  if (!GetPerContextExports(context).ToLocal(&per_context_bindings) ||
      !per_context_bindings->Get(context,
                                FIXED_ONE_BYTE_STRING(isolate, "emitMessage"))
          .ToLocal(&emit_message_val)) {
    return MaybeLocal<Function>();
  }
  CHECK(emit_message_val->IsFunction());
  return emit_message_val.As<Function>();
}

MaybeLocal<Function> GetDOMException(Local<Context> context) {
  Isolate* isolate = context->GetIsolate();
  Local<Object> per_context_bindings;
  Local<Value> domexception_ctor_val;
  if (!GetPerContextExports(context).ToLocal(&per_context_bindings) ||
      !per_context_bindings->Get(context,
                                FIXED_ONE_BYTE_STRING(isolate, "DOMException"))
          .ToLocal(&domexception_ctor_val)) {
    return MaybeLocal<Function>();
  }
  CHECK(domexception_ctor_val->IsFunction());
  Local<Function> domexception_ctor = domexception_ctor_val.As<Function>();
  return domexception_ctor;
}

void ThrowDataCloneException(Local<Context> context, Local<String> message) {
  Isolate* isolate = context->GetIsolate();
  Local<Value> argv[] = {message,
                         FIXED_ONE_BYTE_STRING(isolate, "DataCloneError")};
  Local<Value> exception;
  Local<Function> domexception_ctor;
  if (!GetDOMException(context).ToLocal(&domexception_ctor) ||
      !domexception_ctor->NewInstance(context, arraysize(argv), argv)
           .ToLocal(&exception)) {
    return;
  }
  isolate->ThrowException(exception);
}

// This tells V8 how to serialize objects that it does not understand
// (e.g. C++ objects) into the output buffer, in a way that our own
// DeserializerDelegate understands how to unpack.
class SerializerDelegate : public ValueSerializer::Delegate {
 public:
  SerializerDelegate(Environment* env, Local<Context> context, Message* m)
      : env_(env), context_(context), msg_(m) {}

  void ThrowDataCloneError(Local<String> message) override {
    ThrowDataCloneException(context_, message);
  }

  bool HasCustomHostObject(Isolate* isolate) override { return true; }

  Maybe<bool> IsHostObject(Isolate* isolate, Local<Object> object) override {
    if (BaseObject::IsBaseObject(env_->isolate_data(), object)) {
      return Just(true);
    }

    return Just(JSTransferable::IsJSTransferable(env_, context_, object));
  }

  Maybe<bool> WriteHostObject(Isolate* isolate, Local<Object> object) override {
    if (BaseObject::IsBaseObject(env_->isolate_data(), object)) {
      return WriteHostObject(
          BaseObjectPtr<BaseObject> { Unwrap<BaseObject>(object) });
    }

    if (JSTransferable::IsJSTransferable(env_, context_, object)) {
      BaseObjectPtr<JSTransferable> js_transferable =
          JSTransferable::Wrap(env_, object);
      return WriteHostObject(js_transferable);
    }

    // Convert process.env to a regular object.
    auto env_proxy_ctor_template = env_->env_proxy_ctor_template();
    if (!env_proxy_ctor_template.IsEmpty() &&
        env_proxy_ctor_template->HasInstance(object)) {
      HandleScope scope(isolate);
      // TODO(bnoordhuis) Prototype-less object in case process.env contains
      // a "__proto__" key? process.env has a prototype with concomitant
      // methods like toString(). It's probably confusing if that gets lost
      // in transmission.
      Local<Object> normal_object = Object::New(isolate);
      env_->env_vars()->AssignToObject(isolate, env_->context(), normal_object);
      serializer->WriteUint32(kNormalObject);  // Instead of a BaseObject.
      return serializer->WriteValue(env_->context(), normal_object);
    }

    ThrowDataCloneError(env_->clone_unsupported_type_str());
    return Nothing<bool>();
  }

  Maybe<uint32_t> GetSharedArrayBufferId(
      Isolate* isolate,
      Local<SharedArrayBuffer> shared_array_buffer) override {
    uint32_t i;
    for (i = 0; i < seen_shared_array_buffers_.size(); ++i) {
      if (PersistentToLocal::Strong(seen_shared_array_buffers_[i]) ==
          shared_array_buffer) {
        return Just(i);
      }
    }

    seen_shared_array_buffers_.emplace_back(
      Global<SharedArrayBuffer> { isolate, shared_array_buffer });
    msg_->AddSharedArrayBuffer(shared_array_buffer->GetBackingStore());
    return Just(i);
  }

  Maybe<uint32_t> GetWasmModuleTransferId(
      Isolate* isolate, Local<WasmModuleObject> module) override {
    return Just(msg_->AddWASMModule(module->GetCompiledModule()));
  }

  bool AdoptSharedValueConveyor(Isolate* isolate,
                                SharedValueConveyor&& conveyor) override {
    msg_->AdoptSharedValueConveyor(std::move(conveyor));
    return true;
  }

  Maybe<bool> Finish(Local<Context> context) {
    for (uint32_t i = 0; i < host_objects_.size(); i++) {
      BaseObjectPtr<BaseObject> host_object = std::move(host_objects_[i]);
      std::unique_ptr<TransferData> data;
      if (i < first_cloned_object_index_) {
        data = host_object->TransferForMessaging();
      } else {
        data = host_object->CloneForMessaging();
      }
      if (!data) return Nothing<bool>();
      if (data->FinalizeTransferWrite(context, serializer).IsNothing())
        return Nothing<bool>();
      msg_->AddTransferable(std::move(data));
    }
    return Just(true);
  }

  inline void AddHostObject(BaseObjectPtr<BaseObject> host_object) {
    // Make sure we have not started serializing the value itself yet.
    CHECK_EQ(first_cloned_object_index_, SIZE_MAX);
    host_objects_.emplace_back(std::move(host_object));
  }

  // Some objects in the transfer list may register sub-objects that can be
  // transferred. This could e.g. be a public JS wrapper object, such as a
  // FileHandle, that is registering its C++ handle for transfer.
  inline Maybe<bool> AddNestedHostObjects() {
    for (size_t i = 0; i < host_objects_.size(); i++) {
      std::vector<BaseObjectPtr<BaseObject>> nested_transferables;
      if (!host_objects_[i]->NestedTransferables().To(&nested_transferables))
        return Nothing<bool>();
      for (auto& nested_transferable : nested_transferables) {
        if (std::find(host_objects_.begin(),
                      host_objects_.end(),
                      nested_transferable) == host_objects_.end()) {
          AddHostObject(nested_transferable);
        }
      }
    }
    return Just(true);
  }

  ValueSerializer* serializer = nullptr;

 private:
  Maybe<bool> WriteHostObject(BaseObjectPtr<BaseObject> host_object) {
    BaseObject::TransferMode mode = host_object->GetTransferMode();
    if (mode == TransferMode::kDisallowCloneAndTransfer) {
      ThrowDataCloneError(env_->clone_unsupported_type_str());
      return Nothing<bool>();
    }

    if (mode & TransferMode::kTransferable) {
      for (uint32_t i = 0; i < host_objects_.size(); i++) {
        if (host_objects_[i] == host_object) {
          serializer->WriteUint32(i);
          return Just(true);
        }
      }
      ThrowDataCloneError(env_->clone_transfer_needed_str());
      return Nothing<bool>();
    }

    uint32_t index = host_objects_.size();
    if (first_cloned_object_index_ == SIZE_MAX)
      first_cloned_object_index_ = index;
    serializer->WriteUint32(index);
    host_objects_.push_back(host_object);
    return Just(true);
  }

  Environment* env_;
  Local<Context> context_;
  Message* msg_;
  std::vector<Global<SharedArrayBuffer>> seen_shared_array_buffers_;
  std::vector<BaseObjectPtr<BaseObject>> host_objects_;
  size_t first_cloned_object_index_ = SIZE_MAX;

  friend class worker::Message;
};

}  // anonymous namespace

Maybe<bool> Message::Serialize(Environment* env,
                               Local<Context> context,
                               Local<Value> input,
                               const TransferList& transfer_list_v,
                               Local<Object> source_port) {
  HandleScope handle_scope(env->isolate());
  Context::Scope context_scope(context);

  // Verify that we're not silently overwriting an existing message.
  CHECK(main_message_buf_.is_empty());

  SerializerDelegate delegate(env, context, this);
  ValueSerializer serializer(env->isolate(), &delegate);
  delegate.serializer = &serializer;

  std::vector<Local<ArrayBuffer>> array_buffers;
  for (uint32_t i = 0; i < transfer_list_v.length(); ++i) {
    Local<Value> entry_val = transfer_list_v[i];
    if (!entry_val->IsObject()) {
      // Only object can be transferred.
      ThrowDataCloneException(context, env->clone_untransferable_str());
      return Nothing<bool>();
    }
    Local<Object> entry = entry_val.As<Object>();
    // See https://github.com/nodejs/node/pull/30339#issuecomment-552225353
    // for details.
    if (entry->HasPrivate(context, env->untransferable_object_private_symbol())
            .ToChecked()) {
      ThrowDataCloneException(context, env->transfer_unsupported_type_str());
      return Nothing<bool>();
    }

    // Currently, we support ArrayBuffers and BaseObjects for which
    // GetTransferMode() returns kTransferable.
    if (entry->IsArrayBuffer()) {
      Local<ArrayBuffer> ab = entry.As<ArrayBuffer>();
      // If we cannot render the ArrayBuffer unusable in this Isolate,
      // copying the buffer will have to do.
      // Note that we can currently transfer ArrayBuffers even if they were
      // not allocated by Node’s ArrayBufferAllocator in the first place,
      // because we pass the underlying v8::BackingStore around rather than
      // raw data *and* an Isolate with a non-default ArrayBuffer allocator
      // is always going to outlive any Workers it creates, and so will its
      // allocator along with it.
      if (!ab->IsDetachable() || ab->WasDetached()) {
        ThrowDataCloneException(context, env->transfer_unsupported_type_str());
        return Nothing<bool>();
      }
      if (std::find(array_buffers.begin(), array_buffers.end(), ab) !=
          array_buffers.end()) {
        ThrowDataCloneException(
            context,
            FIXED_ONE_BYTE_STRING(
                env->isolate(),
                "Transfer list contains duplicate ArrayBuffer"));
        return Nothing<bool>();
      }
      // We simply use the array index in the `array_buffers` list as the
      // ID that we write into the serialized buffer.
      uint32_t id = array_buffers.size();
      array_buffers.push_back(ab);
      serializer.TransferArrayBuffer(id, ab);
      continue;
    }

    // Check if the source MessagePort is being transferred.
    if (!source_port.IsEmpty() && entry == source_port) {
      ThrowDataCloneException(
          context,
          FIXED_ONE_BYTE_STRING(env->isolate(),
                                "Transfer list contains source port"));
      return Nothing<bool>();
    }
    BaseObjectPtr<BaseObject> host_object;
    if (BaseObject::IsBaseObject(env->isolate_data(), entry)) {
      host_object = BaseObjectPtr<BaseObject>{Unwrap<BaseObject>(entry)};
    } else {
      if (!JSTransferable::IsJSTransferable(env, context, entry)) {
        ThrowDataCloneException(context, env->clone_untransferable_str());
        return Nothing<bool>();
      }
      host_object = JSTransferable::Wrap(env, entry);
    }

    if (env->message_port_constructor_template()->HasInstance(entry) &&
        (!host_object ||
         static_cast<MessagePort*>(host_object.get())->IsDetached())) {
      ThrowDataCloneException(
          context,
          FIXED_ONE_BYTE_STRING(
              env->isolate(),
              "MessagePort in transfer list is already detached"));
      return Nothing<bool>();
    }
    if (std::find(delegate.host_objects_.begin(),
                  delegate.host_objects_.end(),
                  host_object) != delegate.host_objects_.end()) {
      ThrowDataCloneException(
          context,
          String::Concat(
              env->isolate(),
              FIXED_ONE_BYTE_STRING(env->isolate(),
                                    "Transfer list contains duplicate "),
              entry->GetConstructorName()));
      return Nothing<bool>();
    }
    if (host_object &&
        host_object->GetTransferMode() == TransferMode::kTransferable) {
      delegate.AddHostObject(host_object);
      continue;
    }
  }
  if (delegate.AddNestedHostObjects().IsNothing())
    return Nothing<bool>();

  serializer.WriteHeader();
  if (serializer.WriteValue(context, input).IsNothing()) {
    return Nothing<bool>();
  }

  for (Local<ArrayBuffer> ab : array_buffers) {
    // If serialization succeeded, we render it inaccessible in this Isolate.
    std::shared_ptr<BackingStore> backing_store = ab->GetBackingStore();
    ab->Detach(Local<Value>()).Check();

    array_buffers_.emplace_back(std::move(backing_store));
  }

  if (delegate.Finish(context).IsNothing())
    return Nothing<bool>();

  // The serializer gave us a buffer allocated using `malloc()`.
  std::pair<uint8_t*, size_t> data = serializer.Release();
  CHECK_NOT_NULL(data.first);
  main_message_buf_ =
      MallocedBuffer<char>(reinterpret_cast<char*>(data.first), data.second);
  return Just(true);
}

void Message::MemoryInfo(MemoryTracker* tracker) const {
  tracker->TrackField("array_buffers_", array_buffers_);
  tracker->TrackField("shared_array_buffers", shared_array_buffers_);
  tracker->TrackField("transferables", transferables_);
}

MessagePortData::MessagePortData(MessagePort* owner)
    : owner_(owner) {
}

MessagePortData::~MessagePortData() {
  CHECK_NULL(owner_);
  Disentangle();
}

void MessagePortData::MemoryInfo(MemoryTracker* tracker) const {
  Mutex::ScopedLock lock(mutex_);
  tracker->TrackField("incoming_messages", incoming_messages_);
}

void MessagePortData::AddToIncomingQueue(std::shared_ptr<Message> message) {
  // This function will be called by other threads.
  Mutex::ScopedLock lock(mutex_);
  incoming_messages_.emplace_back(std::move(message));

  if (owner_ != nullptr) {
    Debug(owner_, "Adding message to incoming queue");
    owner_->TriggerAsync();
  }
}

void MessagePortData::Entangle(MessagePortData* a, MessagePortData* b) {
  auto group = std::make_shared<SiblingGroup>();
  group->Entangle({a, b});
}

void MessagePortData::Disentangle() {
  if (group_) {
    group_->Disentangle(this);
  }
}

MessagePort::~MessagePort() {
  if (data_) Detach();
}

MessagePort::MessagePort(Environment* env,
                         Local<Context> context,
                         Local<Object> wrap)
  : HandleWrap(env,
               wrap,
               reinterpret_cast<uv_handle_t*>(&async_),
               AsyncWrap::PROVIDER_MESSAGEPORT),
    data_(new MessagePortData(this)) {
  auto onmessage = [](uv_async_t* handle) {
    // Called when data has been put into the queue.
    MessagePort* channel = ContainerOf(&MessagePort::async_, handle);
    channel->OnMessage(MessageProcessingMode::kNormalOperation);
  };

  CHECK_EQ(uv_async_init(env->event_loop(),
                         &async_,
                         onmessage), 0);
  // Reset later to indicate success of the constructor.
  bool succeeded = false;
  auto cleanup = OnScopeLeave([&]() { if (!succeeded) Close(); });

  Local<Value> fn;
  if (!wrap->Get(context, env->oninit_symbol()).ToLocal(&fn))
    return;

  if (fn->IsFunction()) {
    Local<Function> init = fn.As<Function>();
    if (init->Call(context, wrap, 0, nullptr).IsEmpty())
      return;
  }

  Local<Function> emit_message_fn;
  if (!GetEmitMessageFunction(context).ToLocal(&emit_message_fn))
    return;
  emit_message_fn_.Reset(env->isolate(), emit_message_fn);

  succeeded = true;
  Debug(this, "Created message port");
}

bool MessagePort::IsDetached() const {
  return data_ == nullptr || IsHandleClosing();
}

void MessagePort::TriggerAsync() {
  if (IsHandleClosing()) return;
  CHECK_EQ(uv_async_send(&async_), 0);
}

void MessagePort::Close(v8::Local<v8::Value> close_callback) {
  Debug(this, "Closing message port, data set = %d", static_cast<int>(!!data_));

  if (data_) {
    // Wrap this call with accessing the mutex, so that TriggerAsync()
    // can check IsHandleClosing() without race conditions.
    Mutex::ScopedLock sibling_lock(data_->mutex_);
    HandleWrap::Close(close_callback);
  } else {
    HandleWrap::Close(close_callback);
  }
}

void MessagePort::New(const FunctionCallbackInfo<Value>& args) {
  // This constructor just throws an error. Unfortunately, we can’t use V8’s
  // ConstructorBehavior::kThrow, as that also removes the prototype from the
  // class (i.e. makes it behave like an arrow function).
  Environment* env = Environment::GetCurrent(args);
  THROW_ERR_CONSTRUCT_CALL_INVALID(env);
}

MessagePort* MessagePort::New(
    Environment* env,
    Local<Context> context,
    std::unique_ptr<MessagePortData> data,
    std::shared_ptr<SiblingGroup> sibling_group) {
  Context::Scope context_scope(context);
  Local<FunctionTemplate> ctor_templ =
      GetMessagePortConstructorTemplate(env->isolate_data());

  // Construct a new instance, then assign the listener instance and possibly
  // the MessagePortData to it.
  Local<Object> instance;
  if (!ctor_templ->InstanceTemplate()->NewInstance(context).ToLocal(&instance))
    return nullptr;
  MessagePort* port = new MessagePort(env, context, instance);
  CHECK_NOT_NULL(port);
  if (port->IsHandleClosing()) {
    // Construction failed with an exception.
    return nullptr;
  }

  if (data) {
    CHECK(!sibling_group);
    port->Detach();
    port->data_ = std::move(data);

    // This lock is here to avoid race conditions with the `owner_` read
    // in AddToIncomingQueue(). (This would likely be unproblematic without it,
    // but it's better to be safe than sorry.)
    Mutex::ScopedLock lock(port->data_->mutex_);
    port->data_->owner_ = port;
    // If the existing MessagePortData object had pending messages, this is
    // the easiest way to run that queue.
    port->TriggerAsync();
  } else if (sibling_group) {
    sibling_group->Entangle(port->data_.get());
  }
  return port;
}

MaybeLocal<Value> MessagePort::ReceiveMessage(Local<Context> context,
                                              MessageProcessingMode mode,
                                              Local<Value>* port_list) {
  std::shared_ptr<Message> received;
  {
    // Get the head of the message queue.
    Mutex::ScopedLock lock(data_->mutex_);

    Debug(this, "MessagePort has message");

    bool wants_message =
        receiving_messages_ ||
        mode == MessageProcessingMode::kForceReadMessages;
    // We have nothing to do if:
    // - There are no pending messages
    // - We are not intending to receive messages, and the message we would
    //   receive is not the final "close" message.
    if (data_->incoming_messages_.empty() ||
        (!wants_message &&
         !data_->incoming_messages_.front()->IsCloseMessage())) {
      return env()->no_message_symbol();
    }

    received = data_->incoming_messages_.front();
    data_->incoming_messages_.pop_front();
  }

  if (received->IsCloseMessage()) {
    Close();
    return env()->no_message_symbol();
  }

  if (!env()->can_call_into_js()) return MaybeLocal<Value>();

  return received->Deserialize(env(), context, port_list);
}

void MessagePort::OnMessage(MessageProcessingMode mode) {
  Debug(this, "Running MessagePort::OnMessage()");
  // Maybe the async handle was triggered empty or more than needed.
  // The data_ could be freed or, the handle has been/is being closed.
  // A possible case for this, is transfer the MessagePort to another
  // context, it will call the constructor and trigger the async handle empty.
  // Because all data was sent from the preivous context.
  if (IsDetached()) return;

  HandleScope handle_scope(env()->isolate());
  Local<Context> context =
      object(env()->isolate())->GetCreationContextChecked();

  size_t processing_limit;
  if (mode == MessageProcessingMode::kNormalOperation) {
    Mutex::ScopedLock lock(data_->mutex_);
    processing_limit = std::max(data_->incoming_messages_.size(),
                                static_cast<size_t>(1000));
  } else {
    processing_limit = std::numeric_limits<size_t>::max();
  }

  // data_ can only ever be modified by the owner thread, so no need to lock.
  // However, the message port may be transferred while it is processing
  // messages, so we need to check that this handle still owns its `data_` field
  // on every iteration.
  while (data_) {
    if (processing_limit-- == 0) {
      // Prevent event loop starvation by only processing those messages without
      // interruption that were already present when the OnMessage() call was
      // first triggered, but at least 1000 messages because otherwise the
      // overhead of repeatedly triggering the uv_async_t instance becomes
      // noticeable, at least on Windows.
      // (That might require more investigation by somebody more familiar with
      // Windows.)
      TriggerAsync();
      return;
    }

    HandleScope handle_scope(env()->isolate());
    Context::Scope context_scope(context);
    Local<Function> emit_message = PersistentToLocal::Strong(emit_message_fn_);

    Local<Value> payload;
    Local<Value> port_list = Undefined(env()->isolate());
    Local<Value> message_error;
    Local<Value> argv[3];

    {
      // Catch any exceptions from parsing the message itself (not from
      // emitting it) as 'messageeror' events.
      TryCatchScope try_catch(env());
      if (!ReceiveMessage(context, mode, &port_list).ToLocal(&payload)) {
        if (try_catch.HasCaught() && !try_catch.HasTerminated())
          message_error = try_catch.Exception();
        goto reschedule;
      }
    }
    if (payload == env()->no_message_symbol()) break;

    if (!env()->can_call_into_js()) {
      Debug(this, "MessagePort drains queue because !can_call_into_js()");
      // In this case there is nothing to do but to drain the current queue.
      continue;
    }

    argv[0] = payload;
    argv[1] = port_list;
    argv[2] = env()->message_string();

    if (MakeCallback(emit_message, arraysize(argv), argv).IsEmpty()) {
    reschedule:
      if (!message_error.IsEmpty()) {
        argv[0] = message_error;
        argv[1] = Undefined(env()->isolate());
        argv[2] = env()->messageerror_string();
        USE(MakeCallback(emit_message, arraysize(argv), argv));
      }

      // Re-schedule OnMessage() execution in case of failure.
      if (data_)
        TriggerAsync();
      return;
    }
  }
}

void MessagePort::OnClose() {
  Debug(this, "MessagePort::OnClose()");
  if (data_) {
    // Detach() returns move(data_).
    Detach()->Disentangle();
  }
}

std::unique_ptr<MessagePortData> MessagePort::Detach() {
  CHECK(data_);
  Mutex::ScopedLock lock(data_->mutex_);
  data_->owner_ = nullptr;
  return std::move(data_);
}

BaseObject::TransferMode MessagePort::GetTransferMode() const {
  if (IsDetached()) return TransferMode::kDisallowCloneAndTransfer;
  return TransferMode::kTransferable;
}

std::unique_ptr<TransferData> MessagePort::TransferForMessaging() {
  Close();
  return Detach();
}

BaseObjectPtr<BaseObject> MessagePortData::Deserialize(
    Environment* env,
    Local<Context> context,
    std::unique_ptr<TransferData> self) {
  return BaseObjectPtr<MessagePort> { MessagePort::New(
      env, context,
      static_unique_pointer_cast<MessagePortData>(std::move(self))) };
}

Maybe<bool> MessagePort::PostMessage(Environment* env,
                                     Local<Context> context,
                                     Local<Value> message_v,
                                     const TransferList& transfer_v) {
  Isolate* isolate = env->isolate();
  Local<Object> obj = object(isolate);

  std::shared_ptr<Message> msg = std::make_shared<Message>();

  // Per spec, we need to both check if transfer list has the source port, and
  // serialize the input message, even if the MessagePort is closed or detached.

  Maybe<bool> serialization_maybe =
      msg->Serialize(env, context, message_v, transfer_v, obj);
  if (data_ == nullptr) {
    return serialization_maybe;
  }
  if (serialization_maybe.IsNothing()) {
    return Nothing<bool>();
  }

  std::string error;
  Maybe<bool> res = data_->Dispatch(msg, &error);
  if (res.IsNothing())
    return res;

  if (!error.empty())
    ProcessEmitWarning(env, error.c_str());

  return res;
}

Maybe<bool> MessagePortData::Dispatch(
    std::shared_ptr<Message> message,
    std::string* error) {
  if (!group_) {
    if (error != nullptr)
      *error = "MessagePortData is not entangled.";
    return Nothing<bool>();
  }
  return group_->Dispatch(this, message, error);
}

static Maybe<bool> ReadIterable(Environment* env,
                                Local<Context> context,
                                // NOLINTNEXTLINE(runtime/references)
                                TransferList& transfer_list,
                                Local<Value> object) {
  if (!object->IsObject()) return Just(false);

  if (object->IsArray()) {
    Local<Array> arr = object.As<Array>();
    size_t length = arr->Length();
    transfer_list.AllocateSufficientStorage(length);
    for (size_t i = 0; i < length; i++) {
      if (!arr->Get(context, i).ToLocal(&transfer_list[i]))
        return Nothing<bool>();
    }
    return Just(true);
  }

  Isolate* isolate = env->isolate();
  Local<Value> iterator_method;
  if (!object.As<Object>()->Get(context, Symbol::GetIterator(isolate))
      .ToLocal(&iterator_method)) return Nothing<bool>();
  if (!iterator_method->IsFunction()) return Just(false);

  Local<Value> iterator;
  if (!iterator_method.As<Function>()->Call(context, object, 0, nullptr)
      .ToLocal(&iterator)) return Nothing<bool>();
  if (!iterator->IsObject()) return Just(false);

  Local<Value> next;
  if (!iterator.As<Object>()->Get(context, env->next_string()).ToLocal(&next))
    return Nothing<bool>();
  if (!next->IsFunction()) return Just(false);

  std::vector<Local<Value>> entries;
  while (env->can_call_into_js()) {
    Local<Value> result;
    if (!next.As<Function>()->Call(context, iterator, 0, nullptr)
        .ToLocal(&result)) return Nothing<bool>();
    if (!result->IsObject()) return Just(false);

    Local<Value> done;
    if (!result.As<Object>()->Get(context, env->done_string()).ToLocal(&done))
      return Nothing<bool>();
    if (done->BooleanValue(isolate)) break;

    Local<Value> val;
    if (!result.As<Object>()->Get(context, env->value_string()).ToLocal(&val))
      return Nothing<bool>();
    entries.push_back(val);
  }

  if (!entries.empty()) {
    transfer_list.AllocateSufficientStorage(entries.size());
    std::copy(entries.begin(), entries.end(), &transfer_list[0]);
  }

  return Just(true);
}

bool GetTransferList(Environment* env,
                     Local<Context> context,
                     Local<Value> transfer_list_v,
                     TransferList* transfer_list_out) {
  if (transfer_list_v->IsNullOrUndefined()) {
    // Browsers ignore null or undefined, and otherwise accept an array or an
    // options object.
    return true;
  }

  if (!transfer_list_v->IsObject()) {
    THROW_ERR_INVALID_ARG_TYPE(
        env, "Optional transferList argument must be an iterable");
    return false;
  }

  bool was_iterable;
  if (!ReadIterable(env, context, *transfer_list_out, transfer_list_v)
           .To(&was_iterable))
    return false;
  if (!was_iterable) {
    Local<Value> transfer_option;
    if (!transfer_list_v.As<Object>()
             ->Get(context, env->transfer_string())
             .ToLocal(&transfer_option))
      return false;
    if (!transfer_option->IsUndefined()) {
      if (!ReadIterable(env, context, *transfer_list_out, transfer_option)
               .To(&was_iterable))
        return false;
      if (!was_iterable) {
        THROW_ERR_INVALID_ARG_TYPE(
            env, "Optional options.transfer argument must be an iterable");
        return false;
      }
    }
  }

  return true;
}

void MessagePort::PostMessage(const FunctionCallbackInfo<Value>& args) {
  Environment* env = Environment::GetCurrent(args);
  Local<Object> obj = args.This();
  Local<Context> context = obj->GetCreationContextChecked();

  if (args.Length() == 0) {
    return THROW_ERR_MISSING_ARGS(env, "Not enough arguments to "
                                       "MessagePort.postMessage");
  }

  TransferList transfer_list;
  if (!GetTransferList(env, context, args[1], &transfer_list)) {
    return;
  }
  MessagePort* port = Unwrap<MessagePort>(args.This());
  // Even if the backing MessagePort object has already been deleted, we still
  // want to serialize the message to ensure spec-compliant behavior w.r.t.
  // transfers.
  if (port == nullptr || port->IsHandleClosing()) {
    Message msg;
    USE(msg.Serialize(env, context, args[0], transfer_list, obj));
    return;
  }

  Maybe<bool> res = port->PostMessage(env, context, args[0], transfer_list);
  if (res.IsJust())
    args.GetReturnValue().Set(res.FromJust());
}

void MessagePort::Start() {
  Debug(this, "Start receiving messages");
  receiving_messages_ = true;
  Mutex::ScopedLock lock(data_->mutex_);
  if (!data_->incoming_messages_.empty())
    TriggerAsync();
}

void MessagePort::Stop() {
  Debug(this, "Stop receiving messages");
  receiving_messages_ = false;
}

void MessagePort::Start(const FunctionCallbackInfo<Value>& args) {
  MessagePort* port;
  ASSIGN_OR_RETURN_UNWRAP(&port, args.This());
  if (!port->data_) {
    return;
  }
  port->Start();
}

void MessagePort::Stop(const FunctionCallbackInfo<Value>& args) {
  MessagePort* port;
  CHECK(args[0]->IsObject());
  ASSIGN_OR_RETURN_UNWRAP(&port, args[0].As<Object>());
  if (!port->data_) {
    return;
  }
  port->Stop();
}

void MessagePort::CheckType(const FunctionCallbackInfo<Value>& args) {
  Environment* env = Environment::GetCurrent(args);
  args.GetReturnValue().Set(
      GetMessagePortConstructorTemplate(env->isolate_data())
          ->HasInstance(args[0]));
}

void MessagePort::Drain(const FunctionCallbackInfo<Value>& args) {
  MessagePort* port;
  ASSIGN_OR_RETURN_UNWRAP(&port, args[0].As<Object>());
  port->OnMessage(MessageProcessingMode::kForceReadMessages);
}

void MessagePort::ReceiveMessage(const FunctionCallbackInfo<Value>& args) {
  Environment* env = Environment::GetCurrent(args);
  if (!args[0]->IsObject() ||
      !env->message_port_constructor_template()->HasInstance(args[0])) {
    return THROW_ERR_INVALID_ARG_TYPE(env,
        "The \"port\" argument must be a MessagePort instance");
  }
  MessagePort* port = Unwrap<MessagePort>(args[0].As<Object>());
  if (port == nullptr) {
    // Return 'no messages' for a closed port.
    args.GetReturnValue().Set(
        Environment::GetCurrent(args)->no_message_symbol());
    return;
  }

  MaybeLocal<Value> payload =
      port->ReceiveMessage(port->object()->GetCreationContextChecked(),
                           MessageProcessingMode::kForceReadMessages);
  if (!payload.IsEmpty())
    args.GetReturnValue().Set(payload.ToLocalChecked());
}

void MessagePort::MoveToContext(const FunctionCallbackInfo<Value>& args) {
  Environment* env = Environment::GetCurrent(args);
  if (!args[0]->IsObject() ||
      !env->message_port_constructor_template()->HasInstance(args[0])) {
    return THROW_ERR_INVALID_ARG_TYPE(env,
        "The \"port\" argument must be a MessagePort instance");
  }
  MessagePort* port = Unwrap<MessagePort>(args[0].As<Object>());
  if (port == nullptr || port->IsHandleClosing()) {
    Isolate* isolate = env->isolate();
    THROW_ERR_CLOSED_MESSAGE_PORT(isolate);
    return;
  }

  Local<Value> context_arg = args[1];
  ContextifyContext* context_wrapper;
  if (!context_arg->IsObject() ||
      (context_wrapper = ContextifyContext::ContextFromContextifiedSandbox(
          env, context_arg.As<Object>())) == nullptr) {
    return THROW_ERR_INVALID_ARG_TYPE(env, "Invalid context argument");
  }

  std::unique_ptr<MessagePortData> data;
  if (!port->IsDetached())
    data = port->Detach();

  Context::Scope context_scope(context_wrapper->context());
  MessagePort* target =
      MessagePort::New(env, context_wrapper->context(), std::move(data));
  if (target != nullptr)
    args.GetReturnValue().Set(target->object());
}

void MessagePort::Entangle(MessagePort* a, MessagePort* b) {
  MessagePortData::Entangle(a->data_.get(), b->data_.get());
}

void MessagePort::Entangle(MessagePort* a, MessagePortData* b) {
  MessagePortData::Entangle(a->data_.get(), b);
}

void MessagePort::MemoryInfo(MemoryTracker* tracker) const {
  tracker->TrackField("data", data_);
  tracker->TrackField("emit_message_fn", emit_message_fn_);
}

Local<FunctionTemplate> GetMessagePortConstructorTemplate(
    IsolateData* isolate_data) {
  // Factor generating the MessagePort JS constructor into its own piece
  // of code, because it is needed early on in the child environment setup.
  Local<FunctionTemplate> templ =
      isolate_data->message_port_constructor_template();
  if (!templ.IsEmpty())
    return templ;

  {
    Isolate* isolate = isolate_data->isolate();
    Local<FunctionTemplate> m = NewFunctionTemplate(isolate, MessagePort::New);
    m->SetClassName(isolate_data->message_port_constructor_string());
    m->InstanceTemplate()->SetInternalFieldCount(
        MessagePort::kInternalFieldCount);
    m->Inherit(HandleWrap::GetConstructorTemplate(isolate_data));

    SetProtoMethod(isolate, m, "postMessage", MessagePort::PostMessage);
    SetProtoMethod(isolate, m, "start", MessagePort::Start);

    isolate_data->set_message_port_constructor_template(m);
  }

  return GetMessagePortConstructorTemplate(isolate_data);
}

// static
BaseObjectPtr<JSTransferable> JSTransferable::Wrap(Environment* env,
                                                   Local<Object> target) {
  Local<Context> context = env->context();
  Local<Value> wrapper_val =
      target->GetPrivate(context, env->js_transferable_wrapper_private_symbol())
          .ToLocalChecked();
  DCHECK(wrapper_val->IsObject() || wrapper_val->IsUndefined());
  BaseObjectPtr<JSTransferable> wrapper;
  if (wrapper_val->IsObject()) {
    wrapper =
        BaseObjectPtr<JSTransferable>{Unwrap<JSTransferable>(wrapper_val)};
  } else {
    Local<Object> wrapper_obj = env->js_transferable_constructor_template()
                                    ->GetFunction(context)
                                    .ToLocalChecked()
                                    ->NewInstance(context)
                                    .ToLocalChecked();
    // Make sure the JSTransferable wrapper object is not garbage collected
    // until the strong BaseObjectPtr's reference count is decreased to 0.
    wrapper = MakeDetachedBaseObject<JSTransferable>(env, wrapper_obj, target);
    target
        ->SetPrivate(
            context, env->js_transferable_wrapper_private_symbol(), wrapper_obj)
        .ToChecked();
  }
  return wrapper;
}

// static
bool JSTransferable::IsJSTransferable(Environment* env,
                                      v8::Local<v8::Context> context,
                                      v8::Local<v8::Object> object) {
  return object->HasPrivate(context, env->transfer_mode_private_symbol())
      .ToChecked();
}

JSTransferable::JSTransferable(Environment* env,
                               Local<Object> obj,
                               Local<Object> target)
    : BaseObject(env, obj) {
  target_.Reset(env->isolate(), target);
}

JSTransferable::~JSTransferable() {
  HandleScope scope(env()->isolate());
  target_.Get(env()->isolate())
      ->DeletePrivate(env()->context(),
                      env()->js_transferable_wrapper_private_symbol());
}

Local<Object> JSTransferable::target() const {
  DCHECK(!target_.IsEmpty());
  return target_.Get(env()->isolate());
}

BaseObject::TransferMode JSTransferable::GetTransferMode() const {
  // Implement `kClone in this ? kCloneable : kTransferable`.
  HandleScope handle_scope(env()->isolate());
  errors::TryCatchScope ignore_exceptions(env());

  Local<Value> transfer_mode_val =
      target()
          ->GetPrivate(env()->context(), env()->transfer_mode_private_symbol())
          .ToLocalChecked();
  if (!transfer_mode_val->IsUint32()) {
    return TransferMode::kDisallowCloneAndTransfer;
  }
  return static_cast<TransferMode>(transfer_mode_val.As<v8::Uint32>()->Value());
}

std::unique_ptr<TransferData> JSTransferable::TransferForMessaging() {
  return TransferOrClone<TransferMode::kTransferable>();
}

std::unique_ptr<TransferData> JSTransferable::CloneForMessaging() const {
  return TransferOrClone<TransferMode::kCloneable>();
}

template <TransferMode mode>
std::unique_ptr<TransferData> JSTransferable::TransferOrClone() const {
  // Call `this[symbol]()` where `symbol` is `kClone` or `kTransfer`,
  // which should return an object with `data` and `deserializeInfo` properties;
  // `data` is written to the serializer later, and `deserializeInfo` is stored
  // on the `TransferData` instance as a string.
  HandleScope handle_scope(env()->isolate());
  Local<Context> context = env()->isolate()->GetCurrentContext();
  Local<Symbol> method_name = mode == TransferMode::kCloneable
                                  ? env()->messaging_clone_symbol()
                                  : env()->messaging_transfer_symbol();

  Local<Value> method;
  if (!target()->Get(context, method_name).ToLocal(&method) ||
      !method->IsFunction()) {
    return {};
  }
  Local<Value> result_v;
  if (!method.As<Function>()
           ->Call(context, target(), 0, nullptr)
           .ToLocal(&result_v) ||
      !result_v->IsObject()) {
    return {};
  }

  Local<Object> result = result_v.As<Object>();
  Local<Value> data;
  Local<Value> deserialize_info;
  if (!result->Get(context, env()->data_string()).ToLocal(&data) ||
      !result->Get(context, env()->deserialize_info_string())
           .ToLocal(&deserialize_info)) {
    return {};
  }
  Utf8Value deserialize_info_str(env()->isolate(), deserialize_info);
  if (*deserialize_info_str == nullptr) return {};
  return std::make_unique<Data>(*deserialize_info_str,
                                Global<Value>(env()->isolate(), data));
}

Maybe<BaseObjectList>
JSTransferable::NestedTransferables() const {
  // Call `this[kTransferList]()` and return the resulting list of BaseObjects.
  HandleScope handle_scope(env()->isolate());
  Local<Context> context = env()->isolate()->GetCurrentContext();
  Local<Symbol> method_name = env()->messaging_transfer_list_symbol();

  Local<Value> method;
  if (!target()->Get(context, method_name).ToLocal(&method)) {
    return Nothing<BaseObjectList>();
  }
  if (!method->IsFunction()) return Just(BaseObjectList {});

  Local<Value> list_v;
  if (!method.As<Function>()
           ->Call(context, target(), 0, nullptr)
           .ToLocal(&list_v)) {
    return Nothing<BaseObjectList>();
  }
  if (!list_v->IsArray()) return Just(BaseObjectList {});
  Local<Array> list = list_v.As<Array>();

  BaseObjectList ret;
  for (size_t i = 0; i < list->Length(); i++) {
    Local<Value> value;
    if (!list->Get(context, i).ToLocal(&value))
      return Nothing<BaseObjectList>();
    if (!value->IsObject()) {
      continue;
    }
    Local<Object> obj = value.As<Object>();
    if (BaseObject::IsBaseObject(env()->isolate_data(), obj)) {
      ret.emplace_back(Unwrap<BaseObject>(obj));
      continue;
    }
    if (!JSTransferable::IsJSTransferable(env(), context, obj)) {
      continue;
    }
    ret.emplace_back(JSTransferable::Wrap(env(), obj));
  }
  return Just(ret);
}

Maybe<bool> JSTransferable::FinalizeTransferRead(
    Local<Context> context, ValueDeserializer* deserializer) {
  // Call `this[kDeserialize](data)` where `data` comes from the return value
  // of `this[kTransfer]()` or `this[kClone]()`.
  HandleScope handle_scope(env()->isolate());
  Local<Value> data;
  if (!deserializer->ReadValue(context).ToLocal(&data)) return Nothing<bool>();

  Local<Symbol> method_name = env()->messaging_deserialize_symbol();
  Local<Value> method;
  if (!target()->Get(context, method_name).ToLocal(&method)) {
    return Nothing<bool>();
  }
  if (!method->IsFunction()) return Just(true);

  if (method.As<Function>()->Call(context, target(), 1, &data).IsEmpty()) {
    return Nothing<bool>();
  }
  return Just(true);
}

JSTransferable::Data::Data(std::string&& deserialize_info,
                           v8::Global<v8::Value>&& data)
    : deserialize_info_(std::move(deserialize_info)),
      data_(std::move(data)) {}

BaseObjectPtr<BaseObject> JSTransferable::Data::Deserialize(
    Environment* env,
    Local<Context> context,
    std::unique_ptr<TransferData> self) {
  // Create the JS wrapper object that will later be filled with data passed to
  // the `[kDeserialize]()` method on it. This split is necessary, because here
  // we need to create an object with the right prototype and internal fields,
  // but the actual JS data stored in the serialized data can only be read at
  // the end of the stream, after the main message has been read.

  if (context != env->context()) {
    THROW_ERR_MESSAGE_TARGET_CONTEXT_UNAVAILABLE(env);
    return {};
  }
  HandleScope handle_scope(env->isolate());
  Local<Value> info;
  if (!ToV8Value(context, deserialize_info_).ToLocal(&info)) return {};

  Local<Value> ret;
  CHECK(!env->messaging_deserialize_create_object().IsEmpty());
  if (!env->messaging_deserialize_create_object()
           ->Call(context, Null(env->isolate()), 1, &info)
           .ToLocal(&ret) ||
      !ret->IsObject()) {
    return {};
  }

  if (!JSTransferable::IsJSTransferable(env, context, ret.As<Object>())) {
    return {};
  }
  return JSTransferable::Wrap(env, ret.As<Object>());
}

Maybe<bool> JSTransferable::Data::FinalizeTransferWrite(
    Local<Context> context, ValueSerializer* serializer) {
  HandleScope handle_scope(context->GetIsolate());
  auto ret = serializer->WriteValue(context, PersistentToLocal::Strong(data_));
  data_.Reset();
  return ret;
}

std::shared_ptr<SiblingGroup> SiblingGroup::Get(const std::string& name) {
  Mutex::ScopedLock lock(SiblingGroup::groups_mutex_);
  std::shared_ptr<SiblingGroup> group;
  auto i = groups_.find(name);
  if (i == groups_.end() || i->second.expired()) {
    group = std::make_shared<SiblingGroup>(name);
    groups_[name] = group;
  } else {
    group = i->second.lock();
  }
  return group;
}

void SiblingGroup::CheckSiblingGroup(const std::string& name) {
  Mutex::ScopedLock lock(SiblingGroup::groups_mutex_);
  auto i = groups_.find(name);
  if (i != groups_.end() && i->second.expired())
    groups_.erase(name);
}

SiblingGroup::SiblingGroup(const std::string& name)
    : name_(name) { }

SiblingGroup::~SiblingGroup() {
  // If this is a named group, check to see if we can remove the group
  if (!name_.empty())
    CheckSiblingGroup(name_);
}

Maybe<bool> SiblingGroup::Dispatch(
    MessagePortData* source,
    std::shared_ptr<Message> message,
    std::string* error) {

  RwLock::ScopedReadLock lock(group_mutex_);

  // The source MessagePortData is not part of this group.
  if (ports_.find(source) == ports_.end()) {
    if (error != nullptr)
      *error = "Source MessagePort is not entangled with this group.";
    return Nothing<bool>();
  }

  // There are no destination ports.
  if (size() <= 1)
    return Just(false);

  // Transferables cannot be used when there is more
  // than a single destination.
  if (size() > 2 && message->has_transferables()) {
    if (error != nullptr)
      *error = "Transferables cannot be used with multiple destinations.";
    return Nothing<bool>();
  }

  for (MessagePortData* port : ports_) {
    if (port == source)
      continue;
    // This loop should only be entered if there's only a single destination
    for (const auto& transferable : message->transferables()) {
      if (port == transferable.get()) {
        if (error != nullptr) {
          *error = "The target port was posted to itself, and the "
                   "communication channel was lost";
        }
        return Just(true);
      }
    }
    port->AddToIncomingQueue(message);
  }

  return Just(true);
}

void SiblingGroup::Entangle(MessagePortData* port) {
  Entangle({ port });
}

void SiblingGroup::Entangle(std::initializer_list<MessagePortData*> ports) {
  RwLock::ScopedWriteLock lock(group_mutex_);
  for (MessagePortData* data : ports) {
    ports_.insert(data);
    CHECK(!data->group_);
    data->group_ = shared_from_this();
  }
}

void SiblingGroup::Disentangle(MessagePortData* data) {
  auto self = shared_from_this();  // Keep alive until end of function.
  RwLock::ScopedWriteLock lock(group_mutex_);
  ports_.erase(data);
  data->group_.reset();

  data->AddToIncomingQueue(std::make_shared<Message>());
  // If this is an anonymous group and there's another port, close it.
  if (size() == 1 && name_.empty())
    (*(ports_.begin()))->AddToIncomingQueue(std::make_shared<Message>());
}

SiblingGroup::Map SiblingGroup::groups_;
Mutex SiblingGroup::groups_mutex_;

namespace {

static void SetDeserializerCreateObjectFunction(
    const FunctionCallbackInfo<Value>& args) {
  Environment* env = Environment::GetCurrent(args);
  CHECK(args[0]->IsFunction());
  env->set_messaging_deserialize_create_object(args[0].As<Function>());
}

static void StructuredClone(const FunctionCallbackInfo<Value>& args) {
  Isolate* isolate = args.GetIsolate();
  Local<Context> context = isolate->GetCurrentContext();
  Realm* realm = Realm::GetCurrent(context);
  Environment* env = realm->env();

  if (args.Length() == 0) {
    return THROW_ERR_MISSING_ARGS(env, "The value argument must be specified");
  }

  Local<Value> value = args[0];

  TransferList transfer_list;
  if (!args[1]->IsNullOrUndefined()) {
    if (!args[1]->IsObject()) {
      return THROW_ERR_INVALID_ARG_TYPE(
          env, "The options argument must be either an object or undefined");
    }
    Local<Object> options = args[1].As<Object>();
    Local<Value> transfer_list_v;
    if (!options->Get(context, env->transfer_string())
             .ToLocal(&transfer_list_v)) {
      return;
    }

    // TODO(joyeecheung): implement this in JS land to avoid the C++ -> JS
    // cost to convert a sequence into an array.
    if (!GetTransferList(env, context, transfer_list_v, &transfer_list)) {
      return;
    }
  }

  std::shared_ptr<Message> msg = std::make_shared<Message>();
  Local<Value> result;
  if (msg->Serialize(env, context, value, transfer_list, Local<Object>())
          .IsNothing() ||
      !msg->Deserialize(env, context, nullptr).ToLocal(&result)) {
    return;
  }
  args.GetReturnValue().Set(result);
}

static void MessageChannel(const FunctionCallbackInfo<Value>& args) {
  Environment* env = Environment::GetCurrent(args);
  if (!args.IsConstructCall()) {
    THROW_ERR_CONSTRUCT_CALL_REQUIRED(env);
    return;
  }

  Local<Context> context = args.This()->GetCreationContextChecked();
  Context::Scope context_scope(context);

  MessagePort* port1 = MessagePort::New(env, context);
  if (port1 == nullptr) return;
  MessagePort* port2 = MessagePort::New(env, context);
  if (port2 == nullptr) {
    port1->Close();
    return;
  }

  MessagePort::Entangle(port1, port2);

  args.This()->Set(context, env->port1_string(), port1->object())
      .Check();
  args.This()->Set(context, env->port2_string(), port2->object())
      .Check();
}

static void BroadcastChannel(const FunctionCallbackInfo<Value>& args) {
  CHECK(args[0]->IsString());
  Environment* env = Environment::GetCurrent(args);
  Context::Scope context_scope(env->context());
  Utf8Value name(env->isolate(), args[0]);
  MessagePort* port =
      MessagePort::New(env, env->context(), {}, SiblingGroup::Get(*name));
  if (port != nullptr) {
    args.GetReturnValue().Set(port->object());
  }
}

static void CreatePerIsolateProperties(IsolateData* isolate_data,
                                       Local<ObjectTemplate> target) {
  Isolate* isolate = isolate_data->isolate();

  {
    SetConstructorFunction(isolate,
                           target,
                           "MessageChannel",
                           NewFunctionTemplate(isolate, MessageChannel));
  }

  {
    Local<FunctionTemplate> t = FunctionTemplate::New(isolate);
    t->InstanceTemplate()->SetInternalFieldCount(
        JSTransferable::kInternalFieldCount);
    t->SetClassName(OneByteString(isolate, "JSTransferable"));
    isolate_data->set_js_transferable_constructor_template(t);
  }

  SetConstructorFunction(isolate,
                         target,
                         isolate_data->message_port_constructor_string(),
                         GetMessagePortConstructorTemplate(isolate_data));

  // These are not methods on the MessagePort prototype, because
  // the browser equivalents do not provide them.
  SetMethod(isolate, target, "stopMessagePort", MessagePort::Stop);
  SetMethod(isolate, target, "checkMessagePort", MessagePort::CheckType);
  SetMethod(isolate, target, "drainMessagePort", MessagePort::Drain);
  SetMethod(
      isolate, target, "receiveMessageOnPort", MessagePort::ReceiveMessage);
  SetMethod(
      isolate, target, "moveMessagePortToContext", MessagePort::MoveToContext);
  SetMethod(isolate,
            target,
            "setDeserializerCreateObjectFunction",
            SetDeserializerCreateObjectFunction);
  SetMethod(isolate, target, "broadcastChannel", BroadcastChannel);
  SetMethod(isolate, target, "structuredClone", StructuredClone);
}

static void CreatePerContextProperties(Local<Object> target,
                                       Local<Value> unused,
                                       Local<Context> context,
                                       void* priv) {
  Environment* env = Environment::GetCurrent(context);
  {
    Local<Function> domexception = GetDOMException(context).ToLocalChecked();
    target
        ->Set(context,
              FIXED_ONE_BYTE_STRING(env->isolate(), "DOMException"),
              domexception)
        .Check();
  }
}

static void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
  registry->Register(MessageChannel);
  registry->Register(BroadcastChannel);
  registry->Register(MessagePort::New);
  registry->Register(MessagePort::PostMessage);
  registry->Register(MessagePort::Start);
  registry->Register(MessagePort::Stop);
  registry->Register(MessagePort::CheckType);
  registry->Register(MessagePort::Drain);
  registry->Register(MessagePort::ReceiveMessage);
  registry->Register(MessagePort::MoveToContext);
  registry->Register(SetDeserializerCreateObjectFunction);
  registry->Register(StructuredClone);
}

}  // anonymous namespace

}  // namespace worker
}  // namespace node

NODE_BINDING_CONTEXT_AWARE_INTERNAL(messaging,
                                    node::worker::CreatePerContextProperties)
NODE_BINDING_PER_ISOLATE_INIT(messaging,
                              node::worker::CreatePerIsolateProperties)
NODE_BINDING_EXTERNAL_REFERENCE(messaging,
                                node::worker::RegisterExternalReferences)
