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