GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage-daily/nodes/benchmark/out/../src/node_serdes.cc Lines: 179 227 78.9 %
Date: 2020-06-24 22:13:30 Branches: 45 100 45.0 %

Line Branch Exec Source
1
#include "node_internals.h"
2
#include "node_buffer.h"
3
#include "node_errors.h"
4
#include "util-inl.h"
5
#include "base_object-inl.h"
6
7
namespace node {
8
9
using v8::Array;
10
using v8::ArrayBuffer;
11
using v8::Context;
12
using v8::Function;
13
using v8::FunctionCallbackInfo;
14
using v8::FunctionTemplate;
15
using v8::Integer;
16
using v8::Isolate;
17
using v8::Just;
18
using v8::Local;
19
using v8::Maybe;
20
using v8::MaybeLocal;
21
using v8::Nothing;
22
using v8::Object;
23
using v8::SharedArrayBuffer;
24
using v8::String;
25
using v8::Value;
26
using v8::ValueDeserializer;
27
using v8::ValueSerializer;
28
29
namespace {
30
31
class SerializerContext : public BaseObject,
32
                          public ValueSerializer::Delegate {
33
 public:
34
  SerializerContext(Environment* env,
35
                    Local<Object> wrap);
36
37
516
  ~SerializerContext() override = default;
38
39
  void ThrowDataCloneError(Local<String> message) override;
40
  Maybe<bool> WriteHostObject(Isolate* isolate, Local<Object> object) override;
41
  Maybe<uint32_t> GetSharedArrayBufferId(
42
      Isolate* isolate, Local<SharedArrayBuffer> shared_array_buffer) override;
43
44
  static void SetTreatArrayBufferViewsAsHostObjects(
45
      const FunctionCallbackInfo<Value>& args);
46
47
  static void New(const FunctionCallbackInfo<Value>& args);
48
  static void WriteHeader(const FunctionCallbackInfo<Value>& args);
49
  static void WriteValue(const FunctionCallbackInfo<Value>& args);
50
  static void ReleaseBuffer(const FunctionCallbackInfo<Value>& args);
51
  static void TransferArrayBuffer(const FunctionCallbackInfo<Value>& args);
52
  static void WriteUint32(const FunctionCallbackInfo<Value>& args);
53
  static void WriteUint64(const FunctionCallbackInfo<Value>& args);
54
  static void WriteDouble(const FunctionCallbackInfo<Value>& args);
55
  static void WriteRawBytes(const FunctionCallbackInfo<Value>& args);
56
57
  SET_NO_MEMORY_INFO()
58
  SET_MEMORY_INFO_NAME(SerializerContext)
59
  SET_SELF_SIZE(SerializerContext)
60
61
 private:
62
  ValueSerializer serializer_;
63
};
64
65
class DeserializerContext : public BaseObject,
66
                            public ValueDeserializer::Delegate {
67
 public:
68
  DeserializerContext(Environment* env,
69
                      Local<Object> wrap,
70
                      Local<Value> buffer);
71
72
572
  ~DeserializerContext() override = default;
73
74
  MaybeLocal<Object> ReadHostObject(Isolate* isolate) override;
75
76
  static void New(const FunctionCallbackInfo<Value>& args);
77
  static void ReadHeader(const FunctionCallbackInfo<Value>& args);
78
  static void ReadValue(const FunctionCallbackInfo<Value>& args);
79
  static void TransferArrayBuffer(const FunctionCallbackInfo<Value>& args);
80
  static void GetWireFormatVersion(const FunctionCallbackInfo<Value>& args);
81
  static void ReadUint32(const FunctionCallbackInfo<Value>& args);
82
  static void ReadUint64(const FunctionCallbackInfo<Value>& args);
83
  static void ReadDouble(const FunctionCallbackInfo<Value>& args);
84
  static void ReadRawBytes(const FunctionCallbackInfo<Value>& args);
85
86
  SET_NO_MEMORY_INFO()
87
  SET_MEMORY_INFO_NAME(DeserializerContext)
88
  SET_SELF_SIZE(DeserializerContext)
89
90
 private:
91
  const uint8_t* data_;
92
  const size_t length_;
93
94
  ValueDeserializer deserializer_;
95
};
96
97
258
SerializerContext::SerializerContext(Environment* env, Local<Object> wrap)
98
  : BaseObject(env, wrap),
99
258
    serializer_(env->isolate(), this) {
100
258
  MakeWeak();
101
258
}
102
103
2
void SerializerContext::ThrowDataCloneError(Local<String> message) {
104
4
  Local<Value> args[1] = { message };
105
  Local<Value> get_data_clone_error =
106
6
      object()->Get(env()->context(),
107
8
                    env()->get_data_clone_error_string())
108
2
                      .ToLocalChecked();
109
110
2
  CHECK(get_data_clone_error->IsFunction());
111
  MaybeLocal<Value> error =
112
4
      get_data_clone_error.As<Function>()->Call(env()->context(),
113
                                                object(),
114
2
                                                arraysize(args),
115
8
                                                args);
116
117
2
  if (error.IsEmpty()) return;
118
119
2
  env()->isolate()->ThrowException(error.ToLocalChecked());
120
}
121
122
Maybe<uint32_t> SerializerContext::GetSharedArrayBufferId(
123
    Isolate* isolate, Local<SharedArrayBuffer> shared_array_buffer) {
124
  Local<Value> args[1] = { shared_array_buffer };
125
  Local<Value> get_shared_array_buffer_id =
126
      object()->Get(env()->context(),
127
                    env()->get_shared_array_buffer_id_string())
128
                      .ToLocalChecked();
129
130
  if (!get_shared_array_buffer_id->IsFunction()) {
131
    return ValueSerializer::Delegate::GetSharedArrayBufferId(
132
        isolate, shared_array_buffer);
133
  }
134
135
  MaybeLocal<Value> id =
136
      get_shared_array_buffer_id.As<Function>()->Call(env()->context(),
137
                                                      object(),
138
                                                      arraysize(args),
139
                                                      args);
140
141
  if (id.IsEmpty()) return Nothing<uint32_t>();
142
143
  return id.ToLocalChecked()->Uint32Value(env()->context());
144
}
145
146
35
Maybe<bool> SerializerContext::WriteHostObject(Isolate* isolate,
147
                                               Local<Object> input) {
148
  MaybeLocal<Value> ret;
149
70
  Local<Value> args[1] = { input };
150
151
  Local<Value> write_host_object =
152
105
      object()->Get(env()->context(),
153
175
                    env()->write_host_object_string()).ToLocalChecked();
154
155
35
  if (!write_host_object->IsFunction()) {
156
    return ValueSerializer::Delegate::WriteHostObject(isolate, input);
157
  }
158
159
70
  ret = write_host_object.As<Function>()->Call(env()->context(),
160
                                               object(),
161
35
                                               arraysize(args),
162
140
                                               args);
163
164
35
  if (ret.IsEmpty())
165
2
    return Nothing<bool>();
166
167
33
  return Just(true);
168
}
169
170
258
void SerializerContext::New(const FunctionCallbackInfo<Value>& args) {
171
258
  Environment* env = Environment::GetCurrent(args);
172
173
258
  new SerializerContext(env, args.This());
174
258
}
175
176
258
void SerializerContext::WriteHeader(const FunctionCallbackInfo<Value>& args) {
177
  SerializerContext* ctx;
178
258
  ASSIGN_OR_RETURN_UNWRAP(&ctx, args.Holder());
179
258
  ctx->serializer_.WriteHeader();
180
}
181
182
265
void SerializerContext::WriteValue(const FunctionCallbackInfo<Value>& args) {
183
  SerializerContext* ctx;
184
265
  ASSIGN_OR_RETURN_UNWRAP(&ctx, args.Holder());
185
  Maybe<bool> ret =
186
265
      ctx->serializer_.WriteValue(ctx->env()->context(), args[0]);
187
188
1048
  if (ret.IsJust()) args.GetReturnValue().Set(ret.FromJust());
189
}
190
191
257
void SerializerContext::SetTreatArrayBufferViewsAsHostObjects(
192
    const FunctionCallbackInfo<Value>& args) {
193
  SerializerContext* ctx;
194
257
  ASSIGN_OR_RETURN_UNWRAP(&ctx, args.Holder());
195
196
771
  bool value = args[0]->BooleanValue(ctx->env()->isolate());
197
257
  ctx->serializer_.SetTreatArrayBufferViewsAsHostObjects(value);
198
}
199
200
253
void SerializerContext::ReleaseBuffer(const FunctionCallbackInfo<Value>& args) {
201
  SerializerContext* ctx;
202
253
  ASSIGN_OR_RETURN_UNWRAP(&ctx, args.Holder());
203
204
  // Note: Both ValueSerializer and this Buffer::New() variant use malloc()
205
  // as the underlying allocator.
206
253
  std::pair<uint8_t*, size_t> ret = ctx->serializer_.Release();
207
  auto buf = Buffer::New(ctx->env(),
208
253
                         reinterpret_cast<char*>(ret.first),
209
506
                         ret.second);
210
211
253
  if (!buf.IsEmpty()) {
212
506
    args.GetReturnValue().Set(buf.ToLocalChecked());
213
  }
214
}
215
216
void SerializerContext::TransferArrayBuffer(
217
    const FunctionCallbackInfo<Value>& args) {
218
  SerializerContext* ctx;
219
  ASSIGN_OR_RETURN_UNWRAP(&ctx, args.Holder());
220
221
  Maybe<uint32_t> id = args[0]->Uint32Value(ctx->env()->context());
222
  if (id.IsNothing()) return;
223
224
  if (!args[1]->IsArrayBuffer())
225
    return node::THROW_ERR_INVALID_ARG_TYPE(
226
        ctx->env(), "arrayBuffer must be an ArrayBuffer");
227
228
  Local<ArrayBuffer> ab = args[1].As<ArrayBuffer>();
229
  ctx->serializer_.TransferArrayBuffer(id.FromJust(), ab);
230
  return;
231
}
232
233
67
void SerializerContext::WriteUint32(const FunctionCallbackInfo<Value>& args) {
234
  SerializerContext* ctx;
235
67
  ASSIGN_OR_RETURN_UNWRAP(&ctx, args.Holder());
236
237
201
  Maybe<uint32_t> value = args[0]->Uint32Value(ctx->env()->context());
238
67
  if (value.IsNothing()) return;
239
240
67
  ctx->serializer_.WriteUint32(value.FromJust());
241
}
242
243
1
void SerializerContext::WriteUint64(const FunctionCallbackInfo<Value>& args) {
244
  SerializerContext* ctx;
245
1
  ASSIGN_OR_RETURN_UNWRAP(&ctx, args.Holder());
246
247
3
  Maybe<uint32_t> arg0 = args[0]->Uint32Value(ctx->env()->context());
248
3
  Maybe<uint32_t> arg1 = args[1]->Uint32Value(ctx->env()->context());
249

2
  if (arg0.IsNothing() || arg1.IsNothing())
250
    return;
251
252
1
  uint64_t hi = arg0.FromJust();
253
1
  uint64_t lo = arg1.FromJust();
254
1
  ctx->serializer_.WriteUint64((hi << 32) | lo);
255
}
256
257
1
void SerializerContext::WriteDouble(const FunctionCallbackInfo<Value>& args) {
258
  SerializerContext* ctx;
259
1
  ASSIGN_OR_RETURN_UNWRAP(&ctx, args.Holder());
260
261
3
  Maybe<double> value = args[0]->NumberValue(ctx->env()->context());
262
1
  if (value.IsNothing()) return;
263
264
1
  ctx->serializer_.WriteDouble(value.FromJust());
265
}
266
267
34
void SerializerContext::WriteRawBytes(const FunctionCallbackInfo<Value>& args) {
268
  SerializerContext* ctx;
269
35
  ASSIGN_OR_RETURN_UNWRAP(&ctx, args.Holder());
270
271
68
  if (!args[0]->IsArrayBufferView()) {
272
1
    return node::THROW_ERR_INVALID_ARG_TYPE(
273
1
        ctx->env(), "source must be a TypedArray or a DataView");
274
  }
275
276
33
  ArrayBufferViewContents<char> bytes(args[0]);
277
33
  ctx->serializer_.WriteRawBytes(bytes.data(), bytes.length());
278
}
279
280
286
DeserializerContext::DeserializerContext(Environment* env,
281
                                         Local<Object> wrap,
282
286
                                         Local<Value> buffer)
283
  : BaseObject(env, wrap),
284
286
    data_(reinterpret_cast<const uint8_t*>(Buffer::Data(buffer))),
285
286
    length_(Buffer::Length(buffer)),
286
858
    deserializer_(env->isolate(), data_, length_, this) {
287
1144
  object()->Set(env->context(), env->buffer_string(), buffer).Check();
288
289
286
  MakeWeak();
290
286
}
291
292
43
MaybeLocal<Object> DeserializerContext::ReadHostObject(Isolate* isolate) {
293
  Local<Value> read_host_object =
294
129
      object()->Get(env()->context(),
295
215
                    env()->read_host_object_string()).ToLocalChecked();
296
297
43
  if (!read_host_object->IsFunction()) {
298
    return ValueDeserializer::Delegate::ReadHostObject(isolate);
299
  }
300
301
86
  Isolate::AllowJavascriptExecutionScope allow_js(isolate);
302
  MaybeLocal<Value> ret =
303
86
      read_host_object.As<Function>()->Call(env()->context(),
304
                                            object(),
305
                                            0,
306
172
                                            nullptr);
307
308
43
  if (ret.IsEmpty())
309
    return MaybeLocal<Object>();
310
311
43
  Local<Value> return_value = ret.ToLocalChecked();
312
43
  if (!return_value->IsObject()) {
313
    env()->ThrowTypeError("readHostObject must return an object");
314
    return MaybeLocal<Object>();
315
  }
316
317
43
  return return_value.As<Object>();
318
}
319
320
288
void DeserializerContext::New(const FunctionCallbackInfo<Value>& args) {
321
288
  Environment* env = Environment::GetCurrent(args);
322
323
576
  if (!args[0]->IsArrayBufferView()) {
324
    return node::THROW_ERR_INVALID_ARG_TYPE(
325
2
        env, "buffer must be a TypedArray or a DataView");
326
  }
327
328
572
  new DeserializerContext(env, args.This(), args[0]);
329
}
330
331
286
void DeserializerContext::ReadHeader(const FunctionCallbackInfo<Value>& args) {
332
  DeserializerContext* ctx;
333
286
  ASSIGN_OR_RETURN_UNWRAP(&ctx, args.Holder());
334
335
286
  Maybe<bool> ret = ctx->deserializer_.ReadHeader(ctx->env()->context());
336
337
1144
  if (ret.IsJust()) args.GetReturnValue().Set(ret.FromJust());
338
}
339
340
294
void DeserializerContext::ReadValue(const FunctionCallbackInfo<Value>& args) {
341
  DeserializerContext* ctx;
342
294
  ASSIGN_OR_RETURN_UNWRAP(&ctx, args.Holder());
343
344
294
  MaybeLocal<Value> ret = ctx->deserializer_.ReadValue(ctx->env()->context());
345
346
882
  if (!ret.IsEmpty()) args.GetReturnValue().Set(ret.ToLocalChecked());
347
}
348
349
void DeserializerContext::TransferArrayBuffer(
350
    const FunctionCallbackInfo<Value>& args) {
351
  DeserializerContext* ctx;
352
  ASSIGN_OR_RETURN_UNWRAP(&ctx, args.Holder());
353
354
  Maybe<uint32_t> id = args[0]->Uint32Value(ctx->env()->context());
355
  if (id.IsNothing()) return;
356
357
  if (args[1]->IsArrayBuffer()) {
358
    Local<ArrayBuffer> ab = args[1].As<ArrayBuffer>();
359
    ctx->deserializer_.TransferArrayBuffer(id.FromJust(), ab);
360
    return;
361
  }
362
363
  if (args[1]->IsSharedArrayBuffer()) {
364
    Local<SharedArrayBuffer> sab = args[1].As<SharedArrayBuffer>();
365
    ctx->deserializer_.TransferSharedArrayBuffer(id.FromJust(), sab);
366
    return;
367
  }
368
369
  return node::THROW_ERR_INVALID_ARG_TYPE(
370
      ctx->env(), "arrayBuffer must be an ArrayBuffer or SharedArrayBuffer");
371
}
372
373
1
void DeserializerContext::GetWireFormatVersion(
374
    const FunctionCallbackInfo<Value>& args) {
375
  DeserializerContext* ctx;
376
1
  ASSIGN_OR_RETURN_UNWRAP(&ctx, args.Holder());
377
378
3
  args.GetReturnValue().Set(ctx->deserializer_.GetWireFormatVersion());
379
}
380
381
87
void DeserializerContext::ReadUint32(const FunctionCallbackInfo<Value>& args) {
382
  DeserializerContext* ctx;
383
87
  ASSIGN_OR_RETURN_UNWRAP(&ctx, args.Holder());
384
385
  uint32_t value;
386
87
  bool ok = ctx->deserializer_.ReadUint32(&value);
387
87
  if (!ok) return ctx->env()->ThrowError("ReadUint32() failed");
388
261
  return args.GetReturnValue().Set(value);
389
}
390
391
1
void DeserializerContext::ReadUint64(const FunctionCallbackInfo<Value>& args) {
392
  DeserializerContext* ctx;
393
1
  ASSIGN_OR_RETURN_UNWRAP(&ctx, args.Holder());
394
395
  uint64_t value;
396
1
  bool ok = ctx->deserializer_.ReadUint64(&value);
397
1
  if (!ok) return ctx->env()->ThrowError("ReadUint64() failed");
398
399
1
  uint32_t hi = static_cast<uint32_t>(value >> 32);
400
1
  uint32_t lo = static_cast<uint32_t>(value);
401
402
1
  Isolate* isolate = ctx->env()->isolate();
403
404
  Local<Value> ret[] = {
405
    Integer::NewFromUnsigned(isolate, hi),
406
    Integer::NewFromUnsigned(isolate, lo)
407
3
  };
408
3
  return args.GetReturnValue().Set(Array::New(isolate, ret, arraysize(ret)));
409
}
410
411
1
void DeserializerContext::ReadDouble(const FunctionCallbackInfo<Value>& args) {
412
  DeserializerContext* ctx;
413
1
  ASSIGN_OR_RETURN_UNWRAP(&ctx, args.Holder());
414
415
  double value;
416
1
  bool ok = ctx->deserializer_.ReadDouble(&value);
417
1
  if (!ok) return ctx->env()->ThrowError("ReadDouble() failed");
418
3
  return args.GetReturnValue().Set(value);
419
}
420
421
43
void DeserializerContext::ReadRawBytes(
422
    const FunctionCallbackInfo<Value>& args) {
423
  DeserializerContext* ctx;
424
43
  ASSIGN_OR_RETURN_UNWRAP(&ctx, args.Holder());
425
426
129
  Maybe<int64_t> length_arg = args[0]->IntegerValue(ctx->env()->context());
427
43
  if (length_arg.IsNothing()) return;
428
43
  size_t length = length_arg.FromJust();
429
430
  const void* data;
431
43
  bool ok = ctx->deserializer_.ReadRawBytes(length, &data);
432
43
  if (!ok) return ctx->env()->ThrowError("ReadRawBytes() failed");
433
434
43
  const uint8_t* position = reinterpret_cast<const uint8_t*>(data);
435
43
  CHECK_GE(position, ctx->data_);
436
43
  CHECK_LE(position + length, ctx->data_ + ctx->length_);
437
438
43
  const uint32_t offset = position - ctx->data_;
439
43
  CHECK_EQ(ctx->data_ + offset, position);
440
441
86
  args.GetReturnValue().Set(offset);
442
}
443
444
524
void Initialize(Local<Object> target,
445
                Local<Value> unused,
446
                Local<Context> context,
447
                void* priv) {
448
524
  Environment* env = Environment::GetCurrent(context);
449
  Local<FunctionTemplate> ser =
450
524
      env->NewFunctionTemplate(SerializerContext::New);
451
452
1572
  ser->InstanceTemplate()->SetInternalFieldCount(
453
524
      SerializerContext::kInternalFieldCount);
454
1048
  ser->Inherit(BaseObject::GetConstructorTemplate(env));
455
456
524
  env->SetProtoMethod(ser, "writeHeader", SerializerContext::WriteHeader);
457
524
  env->SetProtoMethod(ser, "writeValue", SerializerContext::WriteValue);
458
524
  env->SetProtoMethod(ser, "releaseBuffer", SerializerContext::ReleaseBuffer);
459
  env->SetProtoMethod(ser,
460
                      "transferArrayBuffer",
461
524
                      SerializerContext::TransferArrayBuffer);
462
524
  env->SetProtoMethod(ser, "writeUint32", SerializerContext::WriteUint32);
463
524
  env->SetProtoMethod(ser, "writeUint64", SerializerContext::WriteUint64);
464
524
  env->SetProtoMethod(ser, "writeDouble", SerializerContext::WriteDouble);
465
524
  env->SetProtoMethod(ser, "writeRawBytes", SerializerContext::WriteRawBytes);
466
  env->SetProtoMethod(ser,
467
                      "_setTreatArrayBufferViewsAsHostObjects",
468
524
                      SerializerContext::SetTreatArrayBufferViewsAsHostObjects);
469
470
  Local<String> serializerString =
471
524
      FIXED_ONE_BYTE_STRING(env->isolate(), "Serializer");
472
524
  ser->SetClassName(serializerString);
473
1048
  target->Set(env->context(),
474
              serializerString,
475
2620
              ser->GetFunction(env->context()).ToLocalChecked()).Check();
476
477
  Local<FunctionTemplate> des =
478
524
      env->NewFunctionTemplate(DeserializerContext::New);
479
480
1572
  des->InstanceTemplate()->SetInternalFieldCount(
481
524
      DeserializerContext::kInternalFieldCount);
482
1048
  des->Inherit(BaseObject::GetConstructorTemplate(env));
483
484
524
  env->SetProtoMethod(des, "readHeader", DeserializerContext::ReadHeader);
485
524
  env->SetProtoMethod(des, "readValue", DeserializerContext::ReadValue);
486
  env->SetProtoMethod(des,
487
                      "getWireFormatVersion",
488
524
                      DeserializerContext::GetWireFormatVersion);
489
  env->SetProtoMethod(des,
490
                      "transferArrayBuffer",
491
524
                      DeserializerContext::TransferArrayBuffer);
492
524
  env->SetProtoMethod(des, "readUint32", DeserializerContext::ReadUint32);
493
524
  env->SetProtoMethod(des, "readUint64", DeserializerContext::ReadUint64);
494
524
  env->SetProtoMethod(des, "readDouble", DeserializerContext::ReadDouble);
495
524
  env->SetProtoMethod(des, "_readRawBytes", DeserializerContext::ReadRawBytes);
496
497
  Local<String> deserializerString =
498
524
      FIXED_ONE_BYTE_STRING(env->isolate(), "Deserializer");
499
524
  des->SetClassName(deserializerString);
500
1048
  target->Set(env->context(),
501
              deserializerString,
502
2620
              des->GetFunction(env->context()).ToLocalChecked()).Check();
503
524
}
504
505
}  // anonymous namespace
506
}  // namespace node
507
508
4398
NODE_MODULE_CONTEXT_AWARE_INTERNAL(serdes, node::Initialize)