1 #ifndef SRC_NODE_BLOB_H_
2 #define SRC_NODE_BLOB_H_
3 
4 #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
5 
6 #include "async_wrap.h"
7 #include "base_object.h"
8 #include "env.h"
9 #include "memory_tracker.h"
10 #include "node_internals.h"
11 #include "node_snapshotable.h"
12 #include "node_worker.h"
13 #include "v8.h"
14 
15 #include <string>
16 #include <unordered_map>
17 #include <vector>
18 
19 namespace node {
20 
21 struct BlobEntry {
22   std::shared_ptr<v8::BackingStore> store;
23   size_t length;
24   size_t offset;
25 };
26 
27 class Blob : public BaseObject {
28  public:
29   static void RegisterExternalReferences(
30       ExternalReferenceRegistry* registry);
31 
32   static void Initialize(
33       v8::Local<v8::Object> target,
34       v8::Local<v8::Value> unused,
35       v8::Local<v8::Context> context,
36       void* priv);
37 
38   static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
39   static void ToArrayBuffer(const v8::FunctionCallbackInfo<v8::Value>& args);
40   static void ToSlice(const v8::FunctionCallbackInfo<v8::Value>& args);
41   static void StoreDataObject(const v8::FunctionCallbackInfo<v8::Value>& args);
42   static void GetDataObject(const v8::FunctionCallbackInfo<v8::Value>& args);
43   static void RevokeDataObject(const v8::FunctionCallbackInfo<v8::Value>& args);
44 
45   static v8::Local<v8::FunctionTemplate> GetConstructorTemplate(
46       Environment* env);
47 
48   static BaseObjectPtr<Blob> Create(Environment* env,
49                                     const std::vector<BlobEntry>& store,
50                                     size_t length);
51 
52   static bool HasInstance(Environment* env, v8::Local<v8::Value> object);
53 
entries() const54   const std::vector<BlobEntry>& entries() const { return store_; }
55 
56   void MemoryInfo(MemoryTracker* tracker) const override;
57   SET_MEMORY_INFO_NAME(Blob)
58   SET_SELF_SIZE(Blob)
59 
60   // Copies the contents of the Blob into an ArrayBuffer.
61   v8::MaybeLocal<v8::Value> GetArrayBuffer(Environment* env);
62 
63   BaseObjectPtr<Blob> Slice(Environment* env, size_t start, size_t end);
64 
length() const65   inline size_t length() const { return length_; }
66 
67   class BlobTransferData : public worker::TransferData {
68    public:
BlobTransferData( const std::vector<BlobEntry>& store, size_t length)69     explicit BlobTransferData(
70         const std::vector<BlobEntry>& store,
71       size_t length)
72         : store_(store),
73           length_(length) {}
74 
75     BaseObjectPtr<BaseObject> Deserialize(
76         Environment* env,
77         v8::Local<v8::Context> context,
78         std::unique_ptr<worker::TransferData> self) override;
79 
80     SET_MEMORY_INFO_NAME(BlobTransferData)
81     SET_SELF_SIZE(BlobTransferData)
82     SET_NO_MEMORY_INFO()
83 
84    private:
85     std::vector<BlobEntry> store_;
86     size_t length_ = 0;
87   };
88 
89   BaseObject::TransferMode GetTransferMode() const override;
90   std::unique_ptr<worker::TransferData> CloneForMessaging() const override;
91 
92   Blob(
93       Environment* env,
94       v8::Local<v8::Object> obj,
95       const std::vector<BlobEntry>& store,
96       size_t length);
97 
98  private:
99   std::vector<BlobEntry> store_;
100   size_t length_ = 0;
101 };
102 
103 class FixedSizeBlobCopyJob : public AsyncWrap, public ThreadPoolWork {
104  public:
105   enum class Mode {
106     SYNC,
107     ASYNC
108   };
109 
110   static void RegisterExternalReferences(
111       ExternalReferenceRegistry* registry);
112   static void Initialize(Environment* env, v8::Local<v8::Object> target);
113   static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
114   static void Run(const v8::FunctionCallbackInfo<v8::Value>& args);
115 
116   bool IsNotIndicativeOfMemoryLeakAtExit() const override {
117     return true;
118   }
119 
120   void DoThreadPoolWork() override;
121   void AfterThreadPoolWork(int status) override;
122 
mode() const123   Mode mode() const { return mode_; }
124 
125   void MemoryInfo(MemoryTracker* tracker) const override;
126   SET_MEMORY_INFO_NAME(FixedSizeBlobCopyJob)
127   SET_SELF_SIZE(FixedSizeBlobCopyJob)
128 
129  private:
130   FixedSizeBlobCopyJob(
131     Environment* env,
132     v8::Local<v8::Object> object,
133     Blob* blob,
134     Mode mode = Mode::ASYNC);
135 
136   Mode mode_;
137   std::vector<BlobEntry> source_;
138   std::shared_ptr<v8::BackingStore> destination_;
139   size_t length_ = 0;
140 };
141 
142 class BlobBindingData : public SnapshotableObject {
143  public:
144   explicit BlobBindingData(Realm* realm, v8::Local<v8::Object> wrap);
145 
146   using InternalFieldInfo = InternalFieldInfoBase;
147 
148   SERIALIZABLE_OBJECT_METHODS()
149 
150   SET_BINDING_ID(blob_binding_data)
151 
152   void MemoryInfo(MemoryTracker* tracker) const override;
153   SET_SELF_SIZE(BlobBindingData)
154   SET_MEMORY_INFO_NAME(BlobBindingData)
155 
156   struct StoredDataObject : public MemoryRetainer {
157     BaseObjectPtr<Blob> blob;
158     size_t length;
159     std::string type;
160 
161     StoredDataObject() = default;
162 
163     StoredDataObject(
164         const BaseObjectPtr<Blob>& blob_,
165         size_t length_,
166         const std::string& type_);
167 
168     void MemoryInfo(MemoryTracker* tracker) const override;
169     SET_SELF_SIZE(StoredDataObject)
170     SET_MEMORY_INFO_NAME(StoredDataObject)
171   };
172 
173   void store_data_object(
174       const std::string& uuid,
175       const StoredDataObject& object);
176 
177   void revoke_data_object(const std::string& uuid);
178 
179   StoredDataObject get_data_object(const std::string& uuid);
180 
181  private:
182   std::unordered_map<std::string, StoredDataObject> data_objects_;
183 };
184 
185 }  // namespace node
186 
187 #endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
188 #endif  // SRC_NODE_BLOB_H_
189