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: 168 213 78.9 %
Date: 2019-02-23 22:23:05 Branches: 47 104 45.2 %

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

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