GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage/nodes/benchmark/out/../src/node_serdes.cc Lines: 186 209 89.0 %
Date: 2017-10-21 Branches: 50 106 47.2 %

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

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