1010
1111namespace node {
1212
13+ typedef size_t AliasedBufferInfo;
14+
1315/* *
1416 * Do not use this class directly when creating instances of it - use the
1517 * Aliased*Array defined at the end of this file instead.
@@ -28,7 +30,14 @@ namespace node {
2830 * observed. Any notification APIs will be left as a future exercise.
2931 */
3032
31- enum class AliasedBufferType { kNew , kCopy , kShared , kAssigned };
33+ enum class AliasedBufferType {
34+ kNew ,
35+ kCopy ,
36+ kShared ,
37+ kAssigned ,
38+ kToBeDeserialized ,
39+ kDeserialized
40+ };
3241
3342template <class NativeT ,
3443 class V8T ,
@@ -38,25 +47,51 @@ class AliasedBufferBase {
3847 public:
3948 static std::unordered_set<AliasedBufferBase*> buffers;
4049
41- inline AliasedBufferBase (v8::Isolate* isolate, const size_t count)
50+ inline AliasedBufferBase (v8::Isolate* isolate,
51+ const size_t count,
52+ const AliasedBufferInfo* info = nullptr )
4253 : isolate_(isolate),
4354 count_(count),
4455 byte_offset_(0 ),
4556 type_(AliasedBufferType::kNew ) {
4657 buffers.insert (this );
47- CHECK_GT (count, 0 );
4858 const v8::HandleScope handle_scope (isolate_);
49- const size_t size_in_bytes =
50- MultiplyWithOverflowCheck (sizeof (NativeT), count);
59+ if (info == nullptr ) {
60+ CHECK_GT (count, 0 );
61+ const size_t size_in_bytes =
62+ MultiplyWithOverflowCheck (sizeof (NativeT), count);
63+
64+ // allocate v8 ArrayBuffer
65+ v8::Local<v8::ArrayBuffer> ab =
66+ v8::ArrayBuffer::New (isolate_, size_in_bytes);
67+ buffer_ = static_cast <NativeT*>(ab->GetBackingStore ()->Data ());
68+
69+ // allocate v8 TypedArray
70+ v8::Local<V8T> js_array = V8T::New (ab, byte_offset_, count);
71+ js_array_ = v8::Global<V8T>(isolate, js_array);
72+ } else {
73+ // To be deserialized later when context is available
74+ type_ = AliasedBufferType::kToBeDeserialized ;
75+ info_ = info;
76+ buffer_ = nullptr ;
77+ }
78+ }
5179
52- // allocate v8 ArrayBuffer
53- v8::Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New (
54- isolate_, size_in_bytes );
55- buffer_ = static_cast <NativeT*>(ab-> GetBackingStore ()-> Data ());
80+ AliasedBufferInfo Serialize (v8::Local<v8::Context> context,
81+ v8::SnapshotCreator* creator) {
82+ return creator-> AddData (context, GetJSArray () );
83+ }
5684
57- // allocate v8 TypedArray
58- v8::Local<V8T> js_array = V8T::New (ab, byte_offset_, count);
59- js_array_ = v8::Global<V8T>(isolate, js_array);
85+ inline void Deserialize (v8::Local<v8::Context> context) {
86+ DCHECK_EQ (type_, AliasedBufferType::kToBeDeserialized );
87+ v8::Local<V8T> arr =
88+ context->GetDataFromSnapshotOnce <V8T>(*info_).ToLocalChecked ();
89+ DCHECK_EQ (count_, arr->Length ());
90+ byte_offset_ = arr->ByteOffset ();
91+ buffer_ = static_cast <NativeT*>(arr->Buffer ()->GetBackingStore ()->Data ());
92+ js_array_.Reset (isolate_, arr);
93+ info_ = nullptr ;
94+ type_ = AliasedBufferType::kDeserialized ;
6095 }
6196
6297 /* *
@@ -80,19 +115,34 @@ class AliasedBufferBase {
80115 buffers.insert (this );
81116 const v8::HandleScope handle_scope (isolate_);
82117
118+ if (backing_buffer.type () == AliasedBufferType::kToBeDeserialized ) {
119+ type_ = AliasedBufferType::kToBeDeserialized ;
120+ buffer_ = nullptr ;
121+ return ;
122+ }
123+ CreateView (backing_buffer);
124+ }
125+
126+ inline void CreateView (
127+ const AliasedBufferBase<uint8_t , v8::Uint8Array>& backing_buffer) {
83128 v8::Local<v8::ArrayBuffer> ab = backing_buffer.GetArrayBuffer ();
84129
85130 // validate that the byte_offset is aligned with sizeof(NativeT)
86- CHECK_EQ (byte_offset & (sizeof (NativeT) - 1 ), 0 );
131+ CHECK_EQ (byte_offset_ & (sizeof (NativeT) - 1 ), 0 );
87132 // validate this fits inside the backing buffer
88- CHECK_LE (MultiplyWithOverflowCheck (sizeof (NativeT), count ),
89- ab->ByteLength () - byte_offset );
133+ CHECK_LE (MultiplyWithOverflowCheck (sizeof (NativeT), count_ ),
134+ ab->ByteLength () - byte_offset_ );
90135
91136 buffer_ = reinterpret_cast <NativeT*>(
92- const_cast <uint8_t *>(backing_buffer.GetNativeBuffer () + byte_offset));
137+ const_cast <uint8_t *>(backing_buffer.GetNativeBuffer () + byte_offset_));
138+
139+ v8::Local<V8T> js_array = V8T::New (ab, byte_offset_, count_);
140+ js_array_ = v8::Global<V8T>(isolate_, js_array);
93141
94- v8::Local<V8T> js_array = V8T::New (ab, byte_offset, count);
95- js_array_ = v8::Global<V8T>(isolate, js_array);
142+ if (type_ == AliasedBufferType::kToBeDeserialized ) {
143+ type_ = AliasedBufferType::kShared ;
144+ info_ = nullptr ;
145+ }
96146 }
97147
98148 AliasedBufferBase (const AliasedBufferBase& that)
@@ -102,12 +152,14 @@ class AliasedBufferBase {
102152 buffer_(that.buffer_),
103153 type_(AliasedBufferType::kCopy ) {
104154 buffers.insert (this );
155+ DCHECK_NE (type_, AliasedBufferType::kToBeDeserialized );
105156 js_array_ = v8::Global<V8T>(that.isolate_ , that.GetJSArray ());
106157 }
107158
108159 inline ~AliasedBufferBase () { buffers.erase (this ); }
109160
110161 AliasedBufferBase& operator =(AliasedBufferBase&& that) noexcept {
162+ DCHECK_NE (type_, AliasedBufferType::kToBeDeserialized );
111163 this ->~AliasedBufferBase ();
112164 isolate_ = that.isolate_ ;
113165 count_ = that.count_ ;
@@ -174,6 +226,7 @@ class AliasedBufferBase {
174226 * Get the underlying v8 TypedArray overlayed on top of the native buffer
175227 */
176228 v8::Local<V8T> GetJSArray () const {
229+ DCHECK_NE (type_, AliasedBufferType::kToBeDeserialized );
177230 return js_array_.Get (isolate_);
178231 }
179232
@@ -190,6 +243,7 @@ class AliasedBufferBase {
190243 * through the GetValue/SetValue/operator[] methods
191244 */
192245 inline const NativeT* GetNativeBuffer () const {
246+ DCHECK_NE (type_, AliasedBufferType::kToBeDeserialized );
193247 return buffer_;
194248 }
195249
@@ -205,13 +259,15 @@ class AliasedBufferBase {
205259 */
206260 inline void SetValue (const size_t index, NativeT value) {
207261 DCHECK_LT (index, count_);
262+ DCHECK_NE (type_, AliasedBufferType::kToBeDeserialized );
208263 buffer_[index] = value;
209264 }
210265
211266 /* *
212267 * Get value at position index
213268 */
214269 inline const NativeT GetValue (const size_t index) const {
270+ DCHECK_NE (type_, AliasedBufferType::kToBeDeserialized );
215271 DCHECK_LT (index, count_);
216272 return buffer_[index];
217273 }
@@ -220,6 +276,7 @@ class AliasedBufferBase {
220276 * Effectively, a synonym for GetValue/SetValue
221277 */
222278 Reference operator [](size_t index) {
279+ DCHECK_NE (type_, AliasedBufferType::kToBeDeserialized );
223280 return Reference (this , index);
224281 }
225282
@@ -279,6 +336,7 @@ class AliasedBufferBase {
279336 NativeT* buffer_;
280337 v8::Global<V8T> js_array_;
281338 AliasedBufferType type_;
339+ const AliasedBufferInfo* info_ = nullptr ;
282340};
283341
284342template <class NativeT , class V8T , typename Trait>
0 commit comments