• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "base_object-inl.h"
2 #include "node_buffer.h"
3 #include "node_errors.h"
4 #include "node_external_reference.h"
5 #include "node_internals.h"
6 #include "util-inl.h"
7 
8 namespace node {
9 
10 using v8::Array;
11 using v8::ArrayBuffer;
12 using v8::Context;
13 using v8::Function;
14 using v8::FunctionCallbackInfo;
15 using v8::FunctionTemplate;
16 using v8::Integer;
17 using v8::Isolate;
18 using v8::Just;
19 using v8::Local;
20 using v8::Maybe;
21 using v8::MaybeLocal;
22 using v8::Nothing;
23 using v8::Object;
24 using v8::SharedArrayBuffer;
25 using v8::String;
26 using v8::Value;
27 using v8::ValueDeserializer;
28 using v8::ValueSerializer;
29 
30 namespace serdes {
31 
32 class SerializerContext : public BaseObject,
33                           public ValueSerializer::Delegate {
34  public:
35   SerializerContext(Environment* env,
36                     Local<Object> wrap);
37 
38   ~SerializerContext() override = default;
39 
40   void ThrowDataCloneError(Local<String> message) override;
41   Maybe<bool> WriteHostObject(Isolate* isolate, Local<Object> object) override;
42   Maybe<uint32_t> GetSharedArrayBufferId(
43       Isolate* isolate, Local<SharedArrayBuffer> shared_array_buffer) override;
44 
45   static void SetTreatArrayBufferViewsAsHostObjects(
46       const FunctionCallbackInfo<Value>& args);
47 
48   static void New(const FunctionCallbackInfo<Value>& args);
49   static void WriteHeader(const FunctionCallbackInfo<Value>& args);
50   static void WriteValue(const FunctionCallbackInfo<Value>& args);
51   static void ReleaseBuffer(const FunctionCallbackInfo<Value>& args);
52   static void TransferArrayBuffer(const FunctionCallbackInfo<Value>& args);
53   static void WriteUint32(const FunctionCallbackInfo<Value>& args);
54   static void WriteUint64(const FunctionCallbackInfo<Value>& args);
55   static void WriteDouble(const FunctionCallbackInfo<Value>& args);
56   static void WriteRawBytes(const FunctionCallbackInfo<Value>& args);
57 
58   SET_NO_MEMORY_INFO()
59   SET_MEMORY_INFO_NAME(SerializerContext)
60   SET_SELF_SIZE(SerializerContext)
61 
62  private:
63   ValueSerializer serializer_;
64 };
65 
66 class DeserializerContext : public BaseObject,
67                             public ValueDeserializer::Delegate {
68  public:
69   DeserializerContext(Environment* env,
70                       Local<Object> wrap,
71                       Local<Value> buffer);
72 
73   ~DeserializerContext() override = default;
74 
75   MaybeLocal<Object> ReadHostObject(Isolate* isolate) override;
76 
77   static void New(const FunctionCallbackInfo<Value>& args);
78   static void ReadHeader(const FunctionCallbackInfo<Value>& args);
79   static void ReadValue(const FunctionCallbackInfo<Value>& args);
80   static void TransferArrayBuffer(const FunctionCallbackInfo<Value>& args);
81   static void GetWireFormatVersion(const FunctionCallbackInfo<Value>& args);
82   static void ReadUint32(const FunctionCallbackInfo<Value>& args);
83   static void ReadUint64(const FunctionCallbackInfo<Value>& args);
84   static void ReadDouble(const FunctionCallbackInfo<Value>& args);
85   static void ReadRawBytes(const FunctionCallbackInfo<Value>& args);
86 
87   SET_NO_MEMORY_INFO()
88   SET_MEMORY_INFO_NAME(DeserializerContext)
89   SET_SELF_SIZE(DeserializerContext)
90 
91  private:
92   const uint8_t* data_;
93   const size_t length_;
94 
95   ValueDeserializer deserializer_;
96 };
97 
SerializerContext(Environment * env,Local<Object> wrap)98 SerializerContext::SerializerContext(Environment* env, Local<Object> wrap)
99   : BaseObject(env, wrap),
100     serializer_(env->isolate(), this) {
101   MakeWeak();
102 }
103 
ThrowDataCloneError(Local<String> message)104 void SerializerContext::ThrowDataCloneError(Local<String> message) {
105   Local<Value> args[1] = { message };
106   Local<Value> get_data_clone_error =
107       object()->Get(env()->context(),
108                     env()->get_data_clone_error_string())
109                       .ToLocalChecked();
110 
111   CHECK(get_data_clone_error->IsFunction());
112   MaybeLocal<Value> error =
113       get_data_clone_error.As<Function>()->Call(env()->context(),
114                                                 object(),
115                                                 arraysize(args),
116                                                 args);
117 
118   if (error.IsEmpty()) return;
119 
120   env()->isolate()->ThrowException(error.ToLocalChecked());
121 }
122 
GetSharedArrayBufferId(Isolate * isolate,Local<SharedArrayBuffer> shared_array_buffer)123 Maybe<uint32_t> SerializerContext::GetSharedArrayBufferId(
124     Isolate* isolate, Local<SharedArrayBuffer> shared_array_buffer) {
125   Local<Value> args[1] = { shared_array_buffer };
126   Local<Value> get_shared_array_buffer_id =
127       object()->Get(env()->context(),
128                     env()->get_shared_array_buffer_id_string())
129                       .ToLocalChecked();
130 
131   if (!get_shared_array_buffer_id->IsFunction()) {
132     return ValueSerializer::Delegate::GetSharedArrayBufferId(
133         isolate, shared_array_buffer);
134   }
135 
136   MaybeLocal<Value> id =
137       get_shared_array_buffer_id.As<Function>()->Call(env()->context(),
138                                                       object(),
139                                                       arraysize(args),
140                                                       args);
141 
142   if (id.IsEmpty()) return Nothing<uint32_t>();
143 
144   return id.ToLocalChecked()->Uint32Value(env()->context());
145 }
146 
WriteHostObject(Isolate * isolate,Local<Object> input)147 Maybe<bool> SerializerContext::WriteHostObject(Isolate* isolate,
148                                                Local<Object> input) {
149   MaybeLocal<Value> ret;
150   Local<Value> args[1] = { input };
151 
152   Local<Value> write_host_object =
153       object()->Get(env()->context(),
154                     env()->write_host_object_string()).ToLocalChecked();
155 
156   if (!write_host_object->IsFunction()) {
157     return ValueSerializer::Delegate::WriteHostObject(isolate, input);
158   }
159 
160   ret = write_host_object.As<Function>()->Call(env()->context(),
161                                                object(),
162                                                arraysize(args),
163                                                args);
164 
165   if (ret.IsEmpty())
166     return Nothing<bool>();
167 
168   return Just(true);
169 }
170 
New(const FunctionCallbackInfo<Value> & args)171 void SerializerContext::New(const FunctionCallbackInfo<Value>& args) {
172   Environment* env = Environment::GetCurrent(args);
173   if (!args.IsConstructCall()) {
174     return THROW_ERR_CONSTRUCT_CALL_REQUIRED(
175         env, "Class constructor Serializer cannot be invoked without 'new'");
176   }
177 
178   new SerializerContext(env, args.This());
179 }
180 
WriteHeader(const FunctionCallbackInfo<Value> & args)181 void SerializerContext::WriteHeader(const FunctionCallbackInfo<Value>& args) {
182   SerializerContext* ctx;
183   ASSIGN_OR_RETURN_UNWRAP(&ctx, args.Holder());
184   ctx->serializer_.WriteHeader();
185 }
186 
WriteValue(const FunctionCallbackInfo<Value> & args)187 void SerializerContext::WriteValue(const FunctionCallbackInfo<Value>& args) {
188   SerializerContext* ctx;
189   ASSIGN_OR_RETURN_UNWRAP(&ctx, args.Holder());
190   Maybe<bool> ret =
191       ctx->serializer_.WriteValue(ctx->env()->context(), args[0]);
192 
193   if (ret.IsJust()) args.GetReturnValue().Set(ret.FromJust());
194 }
195 
SetTreatArrayBufferViewsAsHostObjects(const FunctionCallbackInfo<Value> & args)196 void SerializerContext::SetTreatArrayBufferViewsAsHostObjects(
197     const FunctionCallbackInfo<Value>& args) {
198   SerializerContext* ctx;
199   ASSIGN_OR_RETURN_UNWRAP(&ctx, args.Holder());
200 
201   bool value = args[0]->BooleanValue(ctx->env()->isolate());
202   ctx->serializer_.SetTreatArrayBufferViewsAsHostObjects(value);
203 }
204 
ReleaseBuffer(const FunctionCallbackInfo<Value> & args)205 void SerializerContext::ReleaseBuffer(const FunctionCallbackInfo<Value>& args) {
206   SerializerContext* ctx;
207   ASSIGN_OR_RETURN_UNWRAP(&ctx, args.Holder());
208 
209   // Note: Both ValueSerializer and this Buffer::New() variant use malloc()
210   // as the underlying allocator.
211   std::pair<uint8_t*, size_t> ret = ctx->serializer_.Release();
212   auto buf = Buffer::New(ctx->env(),
213                          reinterpret_cast<char*>(ret.first),
214                          ret.second);
215 
216   if (!buf.IsEmpty()) {
217     args.GetReturnValue().Set(buf.ToLocalChecked());
218   }
219 }
220 
TransferArrayBuffer(const FunctionCallbackInfo<Value> & args)221 void SerializerContext::TransferArrayBuffer(
222     const FunctionCallbackInfo<Value>& args) {
223   SerializerContext* ctx;
224   ASSIGN_OR_RETURN_UNWRAP(&ctx, args.Holder());
225 
226   Maybe<uint32_t> id = args[0]->Uint32Value(ctx->env()->context());
227   if (id.IsNothing()) return;
228 
229   if (!args[1]->IsArrayBuffer())
230     return node::THROW_ERR_INVALID_ARG_TYPE(
231         ctx->env(), "arrayBuffer must be an ArrayBuffer");
232 
233   Local<ArrayBuffer> ab = args[1].As<ArrayBuffer>();
234   ctx->serializer_.TransferArrayBuffer(id.FromJust(), ab);
235   return;
236 }
237 
WriteUint32(const FunctionCallbackInfo<Value> & args)238 void SerializerContext::WriteUint32(const FunctionCallbackInfo<Value>& args) {
239   SerializerContext* ctx;
240   ASSIGN_OR_RETURN_UNWRAP(&ctx, args.Holder());
241 
242   Maybe<uint32_t> value = args[0]->Uint32Value(ctx->env()->context());
243   if (value.IsNothing()) return;
244 
245   ctx->serializer_.WriteUint32(value.FromJust());
246 }
247 
WriteUint64(const FunctionCallbackInfo<Value> & args)248 void SerializerContext::WriteUint64(const FunctionCallbackInfo<Value>& args) {
249   SerializerContext* ctx;
250   ASSIGN_OR_RETURN_UNWRAP(&ctx, args.Holder());
251 
252   Maybe<uint32_t> arg0 = args[0]->Uint32Value(ctx->env()->context());
253   Maybe<uint32_t> arg1 = args[1]->Uint32Value(ctx->env()->context());
254   if (arg0.IsNothing() || arg1.IsNothing())
255     return;
256 
257   uint64_t hi = arg0.FromJust();
258   uint64_t lo = arg1.FromJust();
259   ctx->serializer_.WriteUint64((hi << 32) | lo);
260 }
261 
WriteDouble(const FunctionCallbackInfo<Value> & args)262 void SerializerContext::WriteDouble(const FunctionCallbackInfo<Value>& args) {
263   SerializerContext* ctx;
264   ASSIGN_OR_RETURN_UNWRAP(&ctx, args.Holder());
265 
266   Maybe<double> value = args[0]->NumberValue(ctx->env()->context());
267   if (value.IsNothing()) return;
268 
269   ctx->serializer_.WriteDouble(value.FromJust());
270 }
271 
WriteRawBytes(const FunctionCallbackInfo<Value> & args)272 void SerializerContext::WriteRawBytes(const FunctionCallbackInfo<Value>& args) {
273   SerializerContext* ctx;
274   ASSIGN_OR_RETURN_UNWRAP(&ctx, args.Holder());
275 
276   if (!args[0]->IsArrayBufferView()) {
277     return node::THROW_ERR_INVALID_ARG_TYPE(
278         ctx->env(), "source must be a TypedArray or a DataView");
279   }
280 
281   ArrayBufferViewContents<char> bytes(args[0]);
282   ctx->serializer_.WriteRawBytes(bytes.data(), bytes.length());
283 }
284 
DeserializerContext(Environment * env,Local<Object> wrap,Local<Value> buffer)285 DeserializerContext::DeserializerContext(Environment* env,
286                                          Local<Object> wrap,
287                                          Local<Value> buffer)
288   : BaseObject(env, wrap),
289     data_(reinterpret_cast<const uint8_t*>(Buffer::Data(buffer))),
290     length_(Buffer::Length(buffer)),
291     deserializer_(env->isolate(), data_, length_, this) {
292   object()->Set(env->context(), env->buffer_string(), buffer).Check();
293 
294   MakeWeak();
295 }
296 
ReadHostObject(Isolate * isolate)297 MaybeLocal<Object> DeserializerContext::ReadHostObject(Isolate* isolate) {
298   Local<Value> read_host_object =
299       object()->Get(env()->context(),
300                     env()->read_host_object_string()).ToLocalChecked();
301 
302   if (!read_host_object->IsFunction()) {
303     return ValueDeserializer::Delegate::ReadHostObject(isolate);
304   }
305 
306   Isolate::AllowJavascriptExecutionScope allow_js(isolate);
307   MaybeLocal<Value> ret =
308       read_host_object.As<Function>()->Call(env()->context(),
309                                             object(),
310                                             0,
311                                             nullptr);
312 
313   if (ret.IsEmpty())
314     return MaybeLocal<Object>();
315 
316   Local<Value> return_value = ret.ToLocalChecked();
317   if (!return_value->IsObject()) {
318     env()->ThrowTypeError("readHostObject must return an object");
319     return MaybeLocal<Object>();
320   }
321 
322   return return_value.As<Object>();
323 }
324 
New(const FunctionCallbackInfo<Value> & args)325 void DeserializerContext::New(const FunctionCallbackInfo<Value>& args) {
326   Environment* env = Environment::GetCurrent(args);
327   if (!args.IsConstructCall()) {
328     return THROW_ERR_CONSTRUCT_CALL_REQUIRED(
329         env, "Class constructor Deserializer cannot be invoked without 'new'");
330   }
331 
332   if (!args[0]->IsArrayBufferView()) {
333     return node::THROW_ERR_INVALID_ARG_TYPE(
334         env, "buffer must be a TypedArray or a DataView");
335   }
336 
337   new DeserializerContext(env, args.This(), args[0]);
338 }
339 
ReadHeader(const FunctionCallbackInfo<Value> & args)340 void DeserializerContext::ReadHeader(const FunctionCallbackInfo<Value>& args) {
341   DeserializerContext* ctx;
342   ASSIGN_OR_RETURN_UNWRAP(&ctx, args.Holder());
343 
344   Maybe<bool> ret = ctx->deserializer_.ReadHeader(ctx->env()->context());
345 
346   if (ret.IsJust()) args.GetReturnValue().Set(ret.FromJust());
347 }
348 
ReadValue(const FunctionCallbackInfo<Value> & args)349 void DeserializerContext::ReadValue(const FunctionCallbackInfo<Value>& args) {
350   DeserializerContext* ctx;
351   ASSIGN_OR_RETURN_UNWRAP(&ctx, args.Holder());
352 
353   MaybeLocal<Value> ret = ctx->deserializer_.ReadValue(ctx->env()->context());
354 
355   if (!ret.IsEmpty()) args.GetReturnValue().Set(ret.ToLocalChecked());
356 }
357 
TransferArrayBuffer(const FunctionCallbackInfo<Value> & args)358 void DeserializerContext::TransferArrayBuffer(
359     const FunctionCallbackInfo<Value>& args) {
360   DeserializerContext* ctx;
361   ASSIGN_OR_RETURN_UNWRAP(&ctx, args.Holder());
362 
363   Maybe<uint32_t> id = args[0]->Uint32Value(ctx->env()->context());
364   if (id.IsNothing()) return;
365 
366   if (args[1]->IsArrayBuffer()) {
367     Local<ArrayBuffer> ab = args[1].As<ArrayBuffer>();
368     ctx->deserializer_.TransferArrayBuffer(id.FromJust(), ab);
369     return;
370   }
371 
372   if (args[1]->IsSharedArrayBuffer()) {
373     Local<SharedArrayBuffer> sab = args[1].As<SharedArrayBuffer>();
374     ctx->deserializer_.TransferSharedArrayBuffer(id.FromJust(), sab);
375     return;
376   }
377 
378   return node::THROW_ERR_INVALID_ARG_TYPE(
379       ctx->env(), "arrayBuffer must be an ArrayBuffer or SharedArrayBuffer");
380 }
381 
GetWireFormatVersion(const FunctionCallbackInfo<Value> & args)382 void DeserializerContext::GetWireFormatVersion(
383     const FunctionCallbackInfo<Value>& args) {
384   DeserializerContext* ctx;
385   ASSIGN_OR_RETURN_UNWRAP(&ctx, args.Holder());
386 
387   args.GetReturnValue().Set(ctx->deserializer_.GetWireFormatVersion());
388 }
389 
ReadUint32(const FunctionCallbackInfo<Value> & args)390 void DeserializerContext::ReadUint32(const FunctionCallbackInfo<Value>& args) {
391   DeserializerContext* ctx;
392   ASSIGN_OR_RETURN_UNWRAP(&ctx, args.Holder());
393 
394   uint32_t value;
395   bool ok = ctx->deserializer_.ReadUint32(&value);
396   if (!ok) return ctx->env()->ThrowError("ReadUint32() failed");
397   return args.GetReturnValue().Set(value);
398 }
399 
ReadUint64(const FunctionCallbackInfo<Value> & args)400 void DeserializerContext::ReadUint64(const FunctionCallbackInfo<Value>& args) {
401   DeserializerContext* ctx;
402   ASSIGN_OR_RETURN_UNWRAP(&ctx, args.Holder());
403 
404   uint64_t value;
405   bool ok = ctx->deserializer_.ReadUint64(&value);
406   if (!ok) return ctx->env()->ThrowError("ReadUint64() failed");
407 
408   uint32_t hi = static_cast<uint32_t>(value >> 32);
409   uint32_t lo = static_cast<uint32_t>(value);
410 
411   Isolate* isolate = ctx->env()->isolate();
412 
413   Local<Value> ret[] = {
414     Integer::NewFromUnsigned(isolate, hi),
415     Integer::NewFromUnsigned(isolate, lo)
416   };
417   return args.GetReturnValue().Set(Array::New(isolate, ret, arraysize(ret)));
418 }
419 
ReadDouble(const FunctionCallbackInfo<Value> & args)420 void DeserializerContext::ReadDouble(const FunctionCallbackInfo<Value>& args) {
421   DeserializerContext* ctx;
422   ASSIGN_OR_RETURN_UNWRAP(&ctx, args.Holder());
423 
424   double value;
425   bool ok = ctx->deserializer_.ReadDouble(&value);
426   if (!ok) return ctx->env()->ThrowError("ReadDouble() failed");
427   return args.GetReturnValue().Set(value);
428 }
429 
ReadRawBytes(const FunctionCallbackInfo<Value> & args)430 void DeserializerContext::ReadRawBytes(
431     const FunctionCallbackInfo<Value>& args) {
432   DeserializerContext* ctx;
433   ASSIGN_OR_RETURN_UNWRAP(&ctx, args.Holder());
434 
435   Maybe<int64_t> length_arg = args[0]->IntegerValue(ctx->env()->context());
436   if (length_arg.IsNothing()) return;
437   size_t length = length_arg.FromJust();
438 
439   const void* data;
440   bool ok = ctx->deserializer_.ReadRawBytes(length, &data);
441   if (!ok) return ctx->env()->ThrowError("ReadRawBytes() failed");
442 
443   const uint8_t* position = reinterpret_cast<const uint8_t*>(data);
444   CHECK_GE(position, ctx->data_);
445   CHECK_LE(position + length, ctx->data_ + ctx->length_);
446 
447   const uint32_t offset = static_cast<uint32_t>(position - ctx->data_);
448   CHECK_EQ(ctx->data_ + offset, position);
449 
450   args.GetReturnValue().Set(offset);
451 }
452 
Initialize(Local<Object> target,Local<Value> unused,Local<Context> context,void * priv)453 void Initialize(Local<Object> target,
454                 Local<Value> unused,
455                 Local<Context> context,
456                 void* priv) {
457   Environment* env = Environment::GetCurrent(context);
458   Isolate* isolate = env->isolate();
459 
460   Local<FunctionTemplate> ser =
461       NewFunctionTemplate(isolate, SerializerContext::New);
462 
463   ser->InstanceTemplate()->SetInternalFieldCount(
464       SerializerContext::kInternalFieldCount);
465   ser->Inherit(BaseObject::GetConstructorTemplate(env));
466 
467   SetProtoMethod(isolate, ser, "writeHeader", SerializerContext::WriteHeader);
468   SetProtoMethod(isolate, ser, "writeValue", SerializerContext::WriteValue);
469   SetProtoMethod(
470       isolate, ser, "releaseBuffer", SerializerContext::ReleaseBuffer);
471   SetProtoMethod(isolate,
472                  ser,
473                  "transferArrayBuffer",
474                  SerializerContext::TransferArrayBuffer);
475   SetProtoMethod(isolate, ser, "writeUint32", SerializerContext::WriteUint32);
476   SetProtoMethod(isolate, ser, "writeUint64", SerializerContext::WriteUint64);
477   SetProtoMethod(isolate, ser, "writeDouble", SerializerContext::WriteDouble);
478   SetProtoMethod(
479       isolate, ser, "writeRawBytes", SerializerContext::WriteRawBytes);
480   SetProtoMethod(isolate,
481                  ser,
482                  "_setTreatArrayBufferViewsAsHostObjects",
483                  SerializerContext::SetTreatArrayBufferViewsAsHostObjects);
484 
485   ser->ReadOnlyPrototype();
486   SetConstructorFunction(context, target, "Serializer", ser);
487 
488   Local<FunctionTemplate> des =
489       NewFunctionTemplate(isolate, DeserializerContext::New);
490 
491   des->InstanceTemplate()->SetInternalFieldCount(
492       DeserializerContext::kInternalFieldCount);
493   des->Inherit(BaseObject::GetConstructorTemplate(env));
494 
495   SetProtoMethod(isolate, des, "readHeader", DeserializerContext::ReadHeader);
496   SetProtoMethod(isolate, des, "readValue", DeserializerContext::ReadValue);
497   SetProtoMethod(isolate,
498                  des,
499                  "getWireFormatVersion",
500                  DeserializerContext::GetWireFormatVersion);
501   SetProtoMethod(isolate,
502                  des,
503                  "transferArrayBuffer",
504                  DeserializerContext::TransferArrayBuffer);
505   SetProtoMethod(isolate, des, "readUint32", DeserializerContext::ReadUint32);
506   SetProtoMethod(isolate, des, "readUint64", DeserializerContext::ReadUint64);
507   SetProtoMethod(isolate, des, "readDouble", DeserializerContext::ReadDouble);
508   SetProtoMethod(
509       isolate, des, "_readRawBytes", DeserializerContext::ReadRawBytes);
510 
511   des->SetLength(1);
512   des->ReadOnlyPrototype();
513   SetConstructorFunction(context, target, "Deserializer", des);
514 }
515 
RegisterExternalReferences(ExternalReferenceRegistry * registry)516 void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
517   registry->Register(SerializerContext::New);
518 
519   registry->Register(SerializerContext::WriteHeader);
520   registry->Register(SerializerContext::WriteValue);
521   registry->Register(SerializerContext::ReleaseBuffer);
522   registry->Register(SerializerContext::TransferArrayBuffer);
523   registry->Register(SerializerContext::WriteUint32);
524   registry->Register(SerializerContext::WriteUint64);
525   registry->Register(SerializerContext::WriteDouble);
526   registry->Register(SerializerContext::WriteRawBytes);
527   registry->Register(SerializerContext::SetTreatArrayBufferViewsAsHostObjects);
528 
529   registry->Register(DeserializerContext::New);
530   registry->Register(DeserializerContext::ReadHeader);
531   registry->Register(DeserializerContext::ReadValue);
532   registry->Register(DeserializerContext::GetWireFormatVersion);
533   registry->Register(DeserializerContext::TransferArrayBuffer);
534   registry->Register(DeserializerContext::ReadUint32);
535   registry->Register(DeserializerContext::ReadUint64);
536   registry->Register(DeserializerContext::ReadDouble);
537   registry->Register(DeserializerContext::ReadRawBytes);
538 }
539 
540 }  // namespace serdes
541 }  // namespace node
542 
543 NODE_BINDING_CONTEXT_AWARE_INTERNAL(serdes, node::serdes::Initialize)
544 NODE_BINDING_EXTERNAL_REFERENCE(serdes,
545                                 node::serdes::RegisterExternalReferences)
546