#ifndef SRC_ALLOCATED_BUFFER_INL_H_ #define SRC_ALLOCATED_BUFFER_INL_H_ #include "allocated_buffer.h" #include "base_object-inl.h" #include "node_buffer.h" #include "env-inl.h" #include "uv.h" #include "v8.h" #include "util-inl.h" #include "node_internals.h" namespace node { // It's a bit awkward to define this Buffer::New() overload here, but it // avoids a circular dependency with node_internals.h. namespace Buffer { v8::MaybeLocal New(Environment* env, v8::Local ab, size_t byte_offset, size_t length); } NoArrayBufferZeroFillScope::NoArrayBufferZeroFillScope( IsolateData* isolate_data) : node_allocator_(isolate_data->node_allocator()) { if (node_allocator_ != nullptr) node_allocator_->zero_fill_field()[0] = 0; } NoArrayBufferZeroFillScope::~NoArrayBufferZeroFillScope() { if (node_allocator_ != nullptr) node_allocator_->zero_fill_field()[0] = 1; } AllocatedBuffer AllocatedBuffer::AllocateManaged( Environment* env, size_t size) { NoArrayBufferZeroFillScope no_zero_fill_scope(env->isolate_data()); std::unique_ptr bs = v8::ArrayBuffer::NewBackingStore(env->isolate(), size); return AllocatedBuffer(env, std::move(bs)); } AllocatedBuffer::AllocatedBuffer( Environment* env, std::unique_ptr bs) : env_(env), backing_store_(std::move(bs)) {} AllocatedBuffer::AllocatedBuffer( Environment* env, uv_buf_t buffer) : env_(env) { if (buffer.base == nullptr) return; auto map = env->released_allocated_buffers(); auto it = map->find(buffer.base); CHECK_NE(it, map->end()); backing_store_ = std::move(it->second); map->erase(it); } void AllocatedBuffer::Resize(size_t len) { if (len == 0) { backing_store_ = v8::ArrayBuffer::NewBackingStore(env_->isolate(), 0); return; } NoArrayBufferZeroFillScope no_zero_fill_scope(env_->isolate_data()); backing_store_ = v8::BackingStore::Reallocate( env_->isolate(), std::move(backing_store_), len); } uv_buf_t AllocatedBuffer::release() { if (data() == nullptr) return uv_buf_init(nullptr, 0); CHECK_NOT_NULL(env_); uv_buf_t ret = uv_buf_init(data(), size()); env_->released_allocated_buffers()->emplace( ret.base, std::move(backing_store_)); return ret; } char* AllocatedBuffer::data() { if (!backing_store_) return nullptr; return static_cast(backing_store_->Data()); } const char* AllocatedBuffer::data() const { if (!backing_store_) return nullptr; return static_cast(backing_store_->Data()); } size_t AllocatedBuffer::size() const { if (!backing_store_) return 0; return backing_store_->ByteLength(); } void AllocatedBuffer::clear() { backing_store_.reset(); } v8::MaybeLocal AllocatedBuffer::ToBuffer() { v8::Local ab = ToArrayBuffer(); return Buffer::New(env_, ab, 0, ab->ByteLength()) .FromMaybe(v8::Local()); } v8::Local AllocatedBuffer::ToArrayBuffer() { return v8::ArrayBuffer::New(env_->isolate(), std::move(backing_store_)); } } // namespace node #endif // SRC_ALLOCATED_BUFFER_INL_H_