#include "external_copy_handle.h" #include "external_copy/external_copy.h" using namespace v8; using std::shared_ptr; using std::unique_ptr; namespace ivm { /** * Transferable wrapper */ ExternalCopyHandle::ExternalCopyTransferable::ExternalCopyTransferable(std::shared_ptr value) : value(std::move(value)) {} auto ExternalCopyHandle::ExternalCopyTransferable::TransferIn() -> Local { return ClassHandle::NewInstance(value); } /** * ExternalCopyHandle implementation */ ExternalCopyHandle::ExternalCopyHandle(shared_ptr value) : value(std::move(value)), size{this->value->Size()} { Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(size); } ExternalCopyHandle::~ExternalCopyHandle() { Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(-size); } static std::unique_ptr ExternalCopyHandle_New_Wrapper( v8::Local value, v8::MaybeLocal options ) { return ExternalCopyHandle::New(value, options); } auto ExternalCopyHandle::Definition() -> Local { return Inherit(MakeClass( "ExternalCopy", ConstructorFunction{}, "totalExternalSize", StaticAccessor{}, "copy", MemberFunction{}, "copyInto", MemberFunction{}, "release", MemberFunction{} )); } auto ExternalCopyHandle::TransferOut() -> unique_ptr { return std::make_unique(value); } auto ExternalCopyHandle::New(Local value, MaybeLocal maybe_options) -> unique_ptr { Local options; bool transfer_out = false; ArrayRange transfer_list; if (maybe_options.ToLocal(&options)) { transfer_out = ReadOption(options, StringTable::Get().transferOut, false); transfer_list = ReadOption(options, StringTable::Get().transferList, {}); } return std::make_unique(shared_ptr(ExternalCopy::Copy(value, transfer_out, transfer_list))); } void ExternalCopyHandle::CheckDisposed() const { if (!value) { throw RuntimeGenericError("Copy has been released"); } } /** * JS API functions */ auto ExternalCopyHandle::TotalExternalSizeGetter() -> Local { return Number::New(Isolate::GetCurrent(), ExternalCopy::TotalExternalSize()); } auto ExternalCopyHandle::Copy(MaybeLocal maybe_options) -> Local { CheckDisposed(); bool release = ReadOption(maybe_options, StringTable::Get().release, false); bool transfer_in = ReadOption(maybe_options, StringTable::Get().transferIn, false); Local ret = value->CopyIntoCheckHeap(transfer_in); if (release) { Release(); } return ret; } auto ExternalCopyHandle::CopyInto(MaybeLocal maybe_options) -> Local { CheckDisposed(); bool release = ReadOption(maybe_options, StringTable::Get().release, false); bool transfer_in = ReadOption(maybe_options, StringTable::Get().transferIn, false); Local ret = ClassHandle::NewInstance(value, transfer_in); if (release) { Release(); } return ret; } auto ExternalCopyHandle::Release() -> Local { CheckDisposed(); Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(-std::exchange(size, 0)); value.reset(); return Undefined(Isolate::GetCurrent()); } /** * ExternalCopyIntoHandle implementation */ ExternalCopyIntoHandle::ExternalCopyIntoTransferable::ExternalCopyIntoTransferable(shared_ptr value, bool transfer_in) : value(std::move(value)), transfer_in(transfer_in) {} auto ExternalCopyIntoHandle::ExternalCopyIntoTransferable::TransferIn() -> Local { return value->CopyIntoCheckHeap(transfer_in); } ExternalCopyIntoHandle::ExternalCopyIntoHandle(shared_ptr value, bool transfer_in) : value(std::move(value)), transfer_in(transfer_in) {} auto ExternalCopyIntoHandle::Definition() -> Local { return Inherit(MakeClass("ExternalCopyInto", nullptr)); } auto ExternalCopyIntoHandle::TransferOut() -> unique_ptr { if (!value) { throw RuntimeGenericError("The return value of `copyInto()` should only be used once"); } return std::make_unique(std::move(value), transfer_in); } } // namespace ivm