GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: util.h Lines: 134 134 100.0 %
Date: 2022-09-22 04:22:24 Branches: 34 46 73.9 %

Line Branch Exec Source
1
// Copyright Joyent, Inc. and other Node contributors.
2
//
3
// Permission is hereby granted, free of charge, to any person obtaining a
4
// copy of this software and associated documentation files (the
5
// "Software"), to deal in the Software without restriction, including
6
// without limitation the rights to use, copy, modify, merge, publish,
7
// distribute, sublicense, and/or sell copies of the Software, and to permit
8
// persons to whom the Software is furnished to do so, subject to the
9
// following conditions:
10
//
11
// The above copyright notice and this permission notice shall be included
12
// in all copies or substantial portions of the Software.
13
//
14
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20
// USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22
#ifndef SRC_UTIL_H_
23
#define SRC_UTIL_H_
24
25
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
26
27
#include "v8.h"
28
29
#include "node.h"
30
31
#include <climits>
32
#include <cstddef>
33
#include <cstdio>
34
#include <cstdlib>
35
#include <cstring>
36
37
#include <array>
38
#include <limits>
39
#include <memory>
40
#include <string>
41
#include <string_view>
42
#include <type_traits>
43
#include <set>
44
#include <unordered_map>
45
#include <utility>
46
#include <vector>
47
48
#ifdef __GNUC__
49
#define MUST_USE_RESULT __attribute__((warn_unused_result))
50
#else
51
#define MUST_USE_RESULT
52
#endif
53
54
namespace node {
55
56
// Maybe remove kPathSeparator when cpp17 is ready
57
#ifdef _WIN32
58
    constexpr char kPathSeparator = '\\';
59
/* MAX_PATH is in characters, not bytes. Make sure we have enough headroom. */
60
#define PATH_MAX_BYTES (MAX_PATH * 4)
61
#else
62
    constexpr char kPathSeparator = '/';
63
#define PATH_MAX_BYTES (PATH_MAX)
64
#endif
65
66
// These should be used in our code as opposed to the native
67
// versions as they abstract out some platform and or
68
// compiler version specific functionality
69
// malloc(0) and realloc(ptr, 0) have implementation-defined behavior in
70
// that the standard allows them to either return a unique pointer or a
71
// nullptr for zero-sized allocation requests.  Normalize by always using
72
// a nullptr.
73
template <typename T>
74
inline T* UncheckedRealloc(T* pointer, size_t n);
75
template <typename T>
76
inline T* UncheckedMalloc(size_t n);
77
template <typename T>
78
inline T* UncheckedCalloc(size_t n);
79
80
// Same things, but aborts immediately instead of returning nullptr when
81
// no memory is available.
82
template <typename T>
83
inline T* Realloc(T* pointer, size_t n);
84
template <typename T>
85
inline T* Malloc(size_t n);
86
template <typename T>
87
inline T* Calloc(size_t n);
88
89
inline char* Malloc(size_t n);
90
inline char* Calloc(size_t n);
91
inline char* UncheckedMalloc(size_t n);
92
inline char* UncheckedCalloc(size_t n);
93
94
template <typename T>
95
inline T MultiplyWithOverflowCheck(T a, T b);
96
97
namespace per_process {
98
// Tells whether the per-process V8::Initialize() is called and
99
// if it is safe to call v8::Isolate::TryGetCurrent().
100
extern bool v8_initialized;
101
}  // namespace per_process
102
103
// Used by the allocation functions when allocation fails.
104
// Thin wrapper around v8::Isolate::LowMemoryNotification() that checks
105
// whether V8 is initialized.
106
void LowMemoryNotification();
107
108
// The reason that Assert() takes a struct argument instead of individual
109
// const char*s is to ease instruction cache pressure in calls from CHECK.
110
struct AssertionInfo {
111
  const char* file_line;  // filename:line
112
  const char* message;
113
  const char* function;
114
};
115
[[noreturn]] void NODE_EXTERN_PRIVATE Assert(const AssertionInfo& info);
116
[[noreturn]] void NODE_EXTERN_PRIVATE Abort();
117
void DumpBacktrace(FILE* fp);
118
119
// Windows 8+ does not like abort() in Release mode
120
#ifdef _WIN32
121
#define ABORT_NO_BACKTRACE() _exit(134)
122
#else
123
#define ABORT_NO_BACKTRACE() abort()
124
#endif
125
126
#define ABORT() node::Abort()
127
128
#define ERROR_AND_ABORT(expr)                                                 \
129
  do {                                                                        \
130
    /* Make sure that this struct does not end up in inline code, but      */ \
131
    /* rather in a read-only data section when modifying this code.        */ \
132
    static const node::AssertionInfo args = {                                 \
133
      __FILE__ ":" STRINGIFY(__LINE__), #expr, PRETTY_FUNCTION_NAME           \
134
    };                                                                        \
135
    node::Assert(args);                                                       \
136
  } while (0)
137
138
#ifdef __GNUC__
139
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
140
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
141
#define PRETTY_FUNCTION_NAME __PRETTY_FUNCTION__
142
#else
143
#define LIKELY(expr) expr
144
#define UNLIKELY(expr) expr
145
#define PRETTY_FUNCTION_NAME ""
146
#endif
147
148
#define STRINGIFY_(x) #x
149
#define STRINGIFY(x) STRINGIFY_(x)
150
151
#define CHECK(expr)                                                           \
152
  do {                                                                        \
153
    if (UNLIKELY(!(expr))) {                                                  \
154
      ERROR_AND_ABORT(expr);                                                  \
155
    }                                                                         \
156
  } while (0)
157
158
#define CHECK_EQ(a, b) CHECK((a) == (b))
159
#define CHECK_GE(a, b) CHECK((a) >= (b))
160
#define CHECK_GT(a, b) CHECK((a) > (b))
161
#define CHECK_LE(a, b) CHECK((a) <= (b))
162
#define CHECK_LT(a, b) CHECK((a) < (b))
163
#define CHECK_NE(a, b) CHECK((a) != (b))
164
#define CHECK_NULL(val) CHECK((val) == nullptr)
165
#define CHECK_NOT_NULL(val) CHECK((val) != nullptr)
166
#define CHECK_IMPLIES(a, b) CHECK(!(a) || (b))
167
168
#ifdef DEBUG
169
  #define DCHECK(expr) CHECK(expr)
170
  #define DCHECK_EQ(a, b) CHECK((a) == (b))
171
  #define DCHECK_GE(a, b) CHECK((a) >= (b))
172
  #define DCHECK_GT(a, b) CHECK((a) > (b))
173
  #define DCHECK_LE(a, b) CHECK((a) <= (b))
174
  #define DCHECK_LT(a, b) CHECK((a) < (b))
175
  #define DCHECK_NE(a, b) CHECK((a) != (b))
176
  #define DCHECK_NULL(val) CHECK((val) == nullptr)
177
  #define DCHECK_NOT_NULL(val) CHECK((val) != nullptr)
178
  #define DCHECK_IMPLIES(a, b) CHECK(!(a) || (b))
179
#else
180
  #define DCHECK(expr)
181
  #define DCHECK_EQ(a, b)
182
  #define DCHECK_GE(a, b)
183
  #define DCHECK_GT(a, b)
184
  #define DCHECK_LE(a, b)
185
  #define DCHECK_LT(a, b)
186
  #define DCHECK_NE(a, b)
187
  #define DCHECK_NULL(val)
188
  #define DCHECK_NOT_NULL(val)
189
  #define DCHECK_IMPLIES(a, b)
190
#endif
191
192
193
#define UNREACHABLE(...)                                                      \
194
  ERROR_AND_ABORT("Unreachable code reached" __VA_OPT__(": ") __VA_ARGS__)
195
196
// ECMA262 20.1.2.6 Number.MAX_SAFE_INTEGER (2^53-1)
197
constexpr int64_t kMaxSafeJsInteger = 9007199254740991;
198
199
inline bool IsSafeJsInt(v8::Local<v8::Value> v);
200
201
// TAILQ-style intrusive list node.
202
template <typename T>
203
class ListNode;
204
205
// TAILQ-style intrusive list head.
206
template <typename T, ListNode<T> (T::*M)>
207
class ListHead;
208
209
template <typename T>
210
class ListNode {
211
 public:
212
  inline ListNode();
213
  inline ~ListNode();
214
  inline void Remove();
215
  inline bool IsEmpty() const;
216
217
  ListNode(const ListNode&) = delete;
218
  ListNode& operator=(const ListNode&) = delete;
219
220
 private:
221
  template <typename U, ListNode<U> (U::*M)> friend class ListHead;
222
  friend int GenDebugSymbols();
223
  ListNode* prev_;
224
  ListNode* next_;
225
};
226
227
template <typename T, ListNode<T> (T::*M)>
228
class ListHead {
229
 public:
230
  class Iterator {
231
   public:
232
    inline T* operator*() const;
233
    inline const Iterator& operator++();
234
    inline bool operator!=(const Iterator& that) const;
235
236
   private:
237
    friend class ListHead;
238
    inline explicit Iterator(ListNode<T>* node);
239
    ListNode<T>* node_;
240
  };
241
242
25237
  inline ListHead() = default;
243
  inline ~ListHead();
244
  inline void PushBack(T* element);
245
  inline void PushFront(T* element);
246
  inline bool IsEmpty() const;
247
  inline T* PopFront();
248
  inline Iterator begin() const;
249
  inline Iterator end() const;
250
251
  ListHead(const ListHead&) = delete;
252
  ListHead& operator=(const ListHead&) = delete;
253
254
 private:
255
  friend int GenDebugSymbols();
256
  ListNode<T> head_;
257
};
258
259
// The helper is for doing safe downcasts from base types to derived types.
260
template <typename Inner, typename Outer>
261
class ContainerOfHelper {
262
 public:
263
  inline ContainerOfHelper(Inner Outer::*field, Inner* pointer);
264
  template <typename TypeName>
265
  inline operator TypeName*() const;
266
 private:
267
  Outer* const pointer_;
268
};
269
270
// Calculate the address of the outer (i.e. embedding) struct from
271
// the interior pointer to a data member.
272
template <typename Inner, typename Outer>
273
constexpr ContainerOfHelper<Inner, Outer> ContainerOf(Inner Outer::*field,
274
                                                      Inner* pointer);
275
276
class KVStore {
277
 public:
278
6561
  KVStore() = default;
279
11976
  virtual ~KVStore() = default;
280
  KVStore(const KVStore&) = delete;
281
  KVStore& operator=(const KVStore&) = delete;
282
  KVStore(KVStore&&) = delete;
283
  KVStore& operator=(KVStore&&) = delete;
284
285
  virtual v8::MaybeLocal<v8::String> Get(v8::Isolate* isolate,
286
                                         v8::Local<v8::String> key) const = 0;
287
  virtual v8::Maybe<std::string> Get(const char* key) const = 0;
288
  virtual void Set(v8::Isolate* isolate,
289
                   v8::Local<v8::String> key,
290
                   v8::Local<v8::String> value) = 0;
291
  virtual int32_t Query(v8::Isolate* isolate,
292
                        v8::Local<v8::String> key) const = 0;
293
  virtual int32_t Query(const char* key) const = 0;
294
  virtual void Delete(v8::Isolate* isolate, v8::Local<v8::String> key) = 0;
295
  virtual v8::Local<v8::Array> Enumerate(v8::Isolate* isolate) const = 0;
296
297
  virtual std::shared_ptr<KVStore> Clone(v8::Isolate* isolate) const;
298
  virtual v8::Maybe<bool> AssignFromObject(v8::Local<v8::Context> context,
299
                                           v8::Local<v8::Object> entries);
300
301
  static std::shared_ptr<KVStore> CreateMapKVStore();
302
};
303
304
// Convenience wrapper around v8::String::NewFromOneByte().
305
inline v8::Local<v8::String> OneByteString(v8::Isolate* isolate,
306
                                           const char* data,
307
                                           int length = -1);
308
309
// For the people that compile with -funsigned-char.
310
inline v8::Local<v8::String> OneByteString(v8::Isolate* isolate,
311
                                           const signed char* data,
312
                                           int length = -1);
313
314
inline v8::Local<v8::String> OneByteString(v8::Isolate* isolate,
315
                                           const unsigned char* data,
316
                                           int length = -1);
317
318
// Used to be a macro, hence the uppercase name.
319
template <int N>
320
6262029
inline v8::Local<v8::String> FIXED_ONE_BYTE_STRING(
321
    v8::Isolate* isolate,
322
    const char(&data)[N]) {
323
6262029
  return OneByteString(isolate, data, N - 1);
324
}
325
326
template <std::size_t N>
327
664
inline v8::Local<v8::String> FIXED_ONE_BYTE_STRING(
328
    v8::Isolate* isolate,
329
    const std::array<char, N>& arr) {
330
664
  return OneByteString(isolate, arr.data(), N - 1);
331
}
332
333
334
335
// Swaps bytes in place. nbytes is the number of bytes to swap and must be a
336
// multiple of the word size (checked by function).
337
inline void SwapBytes16(char* data, size_t nbytes);
338
inline void SwapBytes32(char* data, size_t nbytes);
339
inline void SwapBytes64(char* data, size_t nbytes);
340
341
// tolower() is locale-sensitive.  Use ToLower() instead.
342
inline char ToLower(char c);
343
inline std::string ToLower(const std::string& in);
344
345
// toupper() is locale-sensitive.  Use ToUpper() instead.
346
inline char ToUpper(char c);
347
inline std::string ToUpper(const std::string& in);
348
349
// strcasecmp() is locale-sensitive.  Use StringEqualNoCase() instead.
350
inline bool StringEqualNoCase(const char* a, const char* b);
351
352
// strncasecmp() is locale-sensitive.  Use StringEqualNoCaseN() instead.
353
inline bool StringEqualNoCaseN(const char* a, const char* b, size_t length);
354
355
template <typename T, size_t N>
356
11833774
constexpr size_t arraysize(const T (&)[N]) {
357
11833774
  return N;
358
}
359
360
template <typename T, size_t N>
361
constexpr size_t strsize(const T (&)[N]) {
362
  return N - 1;
363
}
364
365
// Allocates an array of member type T. For up to kStackStorageSize items,
366
// the stack is used, otherwise malloc().
367
template <typename T, size_t kStackStorageSize = 1024>
368
class MaybeStackBuffer {
369
 public:
370
6040
  const T* out() const {
371
6040
    return buf_;
372
  }
373
374
6403113
  T* out() {
375
6403113
    return buf_;
376
  }
377
378
  // operator* for compatibility with `v8::String::(Utf8)Value`
379
9495865
  T* operator*() {
380
9495865
    return buf_;
381
  }
382
383
30446
  const T* operator*() const {
384
30446
    return buf_;
385
  }
386
387
3050729
  T& operator[](size_t index) {
388
3050729
    CHECK_LT(index, length());
389
3050729
    return buf_[index];
390
  }
391
392
11182
  const T& operator[](size_t index) const {
393
11182
    CHECK_LT(index, length());
394
11182
    return buf_[index];
395
  }
396
397
11263264
  size_t length() const {
398
11263264
    return length_;
399
  }
400
401
  // Current maximum capacity of the buffer with which SetLength() can be used
402
  // without first calling AllocateSufficientStorage().
403
19171566
  size_t capacity() const {
404
19171566
    return capacity_;
405
  }
406
407
  // Make sure enough space for `storage` entries is available.
408
  // This method can be called multiple times throughout the lifetime of the
409
  // buffer, but once this has been called Invalidate() cannot be used.
410
  // Content of the buffer in the range [0, length()) is preserved.
411
6745067
  void AllocateSufficientStorage(size_t storage) {
412
6745067
    CHECK(!IsInvalidated());
413
6745067
    if (storage > capacity()) {
414
287774
      bool was_allocated = IsAllocated();
415
287774
      T* allocated_ptr = was_allocated ? buf_ : nullptr;
416
287774
      buf_ = Realloc(allocated_ptr, storage);
417
287774
      capacity_ = storage;
418

287774
      if (!was_allocated && length_ > 0)
419
4
        memcpy(buf_, buf_st_, length_ * sizeof(buf_[0]));
420
    }
421
422
6745067
    length_ = storage;
423
6745067
  }
424
425
6258553
  void SetLength(size_t length) {
426
    // capacity() returns how much memory is actually available.
427
6258553
    CHECK_LE(length, capacity());
428
6258553
    length_ = length;
429
6258553
  }
430
431
9204070
  void SetLengthAndZeroTerminate(size_t length) {
432
    // capacity() returns how much memory is actually available.
433
9204070
    CHECK_LE(length + 1, capacity());
434
9204070
    SetLength(length);
435
436
    // T() is 0 for integer types, nullptr for pointers, etc.
437
9204070
    buf_[length] = T();
438
9204070
  }
439
440
  // Make dereferencing this object return nullptr.
441
  // This method can be called multiple times throughout the lifetime of the
442
  // buffer, but once this has been called AllocateSufficientStorage() cannot
443
  // be used.
444
2
  void Invalidate() {
445
2
    CHECK(!IsAllocated());
446
2
    capacity_ = 0;
447
2
    length_ = 0;
448
2
    buf_ = nullptr;
449
2
  }
450
451
  // If the buffer is stored in the heap rather than on the stack.
452
9190132
  bool IsAllocated() const {
453

9190132
    return !IsInvalidated() && buf_ != buf_st_;
454
  }
455
456
  // If Invalidate() has been called.
457
16392835
  bool IsInvalidated() const {
458
16392835
    return buf_ == nullptr;
459
  }
460
461
  // Release ownership of the malloc'd buffer.
462
  // Note: This does not free the buffer.
463
726
  void Release() {
464
726
    CHECK(IsAllocated());
465
726
    buf_ = buf_st_;
466
726
    length_ = 0;
467
726
    capacity_ = arraysize(buf_st_);
468
726
  }
469
470
8379957
  MaybeStackBuffer()
471
138742197
      : length_(0), capacity_(arraysize(buf_st_)), buf_(buf_st_) {
472
    // Default to a zero-length, null-terminated buffer.
473
8379957
    buf_[0] = T();
474
8379957
  }
475
476
501502
  explicit MaybeStackBuffer(size_t storage) : MaybeStackBuffer() {
477
501502
    AllocateSufficientStorage(storage);
478
501502
  }
479
480
8891758
  ~MaybeStackBuffer() {
481
8891758
    if (IsAllocated())
482
287869
      free(buf_);
483
8891758
  }
484
485
 private:
486
  size_t length_;
487
  // capacity of the malloc'ed buf_
488
  size_t capacity_;
489
  T* buf_;
490
  T buf_st_[kStackStorageSize];
491
};
492
493
// Provides access to an ArrayBufferView's storage, either the original,
494
// or for small data, a copy of it. This object's lifetime is bound to the
495
// original ArrayBufferView's lifetime.
496
template <typename T, size_t kStackStorageSize = 64>
497
class ArrayBufferViewContents {
498
 public:
499
1246
  ArrayBufferViewContents() = default;
500
501
  ArrayBufferViewContents(const ArrayBufferViewContents&) = delete;
502
  void operator=(const ArrayBufferViewContents&) = delete;
503
504
  explicit inline ArrayBufferViewContents(v8::Local<v8::Value> value);
505
  explicit inline ArrayBufferViewContents(v8::Local<v8::Object> value);
506
  explicit inline ArrayBufferViewContents(v8::Local<v8::ArrayBufferView> abv);
507
  inline void Read(v8::Local<v8::ArrayBufferView> abv);
508
509
186735
  inline const T* data() const { return data_; }
510
474628
  inline size_t length() const { return length_; }
511
512
 private:
513
  // Declaring operator new and delete as deleted is not spec compliant.
514
  // Therefore, declare them private instead to disable dynamic alloc.
515
  void* operator new(size_t size);
516
  void* operator new[](size_t size);
517
  void operator delete(void*, size_t);
518
  void operator delete[](void*, size_t);
519
520
  T stack_storage_[kStackStorageSize];
521
  T* data_ = nullptr;
522
  size_t length_ = 0;
523
};
524
525
class Utf8Value : public MaybeStackBuffer<char> {
526
 public:
527
  explicit Utf8Value(v8::Isolate* isolate, v8::Local<v8::Value> value);
528
529
1079
  inline std::string ToString() const { return std::string(out(), length()); }
530
531
4961
  inline bool operator==(const char* a) const {
532
4961
    return strcmp(out(), a) == 0;
533
  }
534
};
535
536
class TwoByteValue : public MaybeStackBuffer<uint16_t> {
537
 public:
538
  explicit TwoByteValue(v8::Isolate* isolate, v8::Local<v8::Value> value);
539
};
540
541
class BufferValue : public MaybeStackBuffer<char> {
542
 public:
543
  explicit BufferValue(v8::Isolate* isolate, v8::Local<v8::Value> value);
544
545
  inline std::string ToString() const { return std::string(out(), length()); }
546
};
547
548
#define SPREAD_BUFFER_ARG(val, name)                                           \
549
  CHECK((val)->IsArrayBufferView());                                           \
550
  v8::Local<v8::ArrayBufferView> name = (val).As<v8::ArrayBufferView>();       \
551
  const size_t name##_offset = name->ByteOffset();                             \
552
  const size_t name##_length = name->ByteLength();                             \
553
  char* const name##_data =                                                    \
554
      static_cast<char*>(name->Buffer()->Data()) + name##_offset;              \
555
  if (name##_length > 0) CHECK_NE(name##_data, nullptr);
556
557
// Use this when a variable or parameter is unused in order to explicitly
558
// silence a compiler warning about that.
559
5262931
template <typename T> inline void USE(T&&) {}
560
561
template <typename Fn>
562
struct OnScopeLeaveImpl {
563
  Fn fn_;
564
  bool active_;
565
566
3541438
  explicit OnScopeLeaveImpl(Fn&& fn) : fn_(std::move(fn)), active_(true) {}
567
1787429
  ~OnScopeLeaveImpl() { if (active_) fn_(); }
568
569
  OnScopeLeaveImpl(const OnScopeLeaveImpl& other) = delete;
570
  OnScopeLeaveImpl& operator=(const OnScopeLeaveImpl& other) = delete;
571
  OnScopeLeaveImpl(OnScopeLeaveImpl&& other)
572
    : fn_(std::move(other.fn_)), active_(other.active_) {
573
    other.active_ = false;
574
  }
575
  OnScopeLeaveImpl& operator=(OnScopeLeaveImpl&& other) {
576
    if (this == &other) return *this;
577
    this->~OnScopeLeave();
578
    new (this)OnScopeLeaveImpl(std::move(other));
579
    return *this;
580
  }
581
};
582
583
// Run a function when exiting the current scope. Used like this:
584
// auto on_scope_leave = OnScopeLeave([&] {
585
//   // ... run some code ...
586
// });
587
template <typename Fn>
588
3541438
inline MUST_USE_RESULT OnScopeLeaveImpl<Fn> OnScopeLeave(Fn&& fn) {
589
3541438
  return OnScopeLeaveImpl<Fn>{std::move(fn)};
590
}
591
592
// Simple RAII wrapper for contiguous data that uses malloc()/free().
593
template <typename T>
594
struct MallocedBuffer {
595
  T* data;
596
  size_t size;
597
598
  T* release() {
599
    T* ret = data;
600
    data = nullptr;
601
    return ret;
602
  }
603
604
  void Truncate(size_t new_size) {
605
    CHECK(new_size <= size);
606
    size = new_size;
607
  }
608
609
  void Realloc(size_t new_size) {
610
    Truncate(new_size);
611
    data = UncheckedRealloc(data, new_size);
612
  }
613
614
76619
  inline bool is_empty() const { return data == nullptr; }
615
616
112877
  MallocedBuffer() : data(nullptr), size(0) {}
617
980
  explicit MallocedBuffer(size_t size) : data(Malloc<T>(size)), size(size) {}
618
76634
  MallocedBuffer(T* data, size_t size) : data(data), size(size) {}
619
189483
  MallocedBuffer(MallocedBuffer&& other) : data(other.data), size(other.size) {
620
189483
    other.data = nullptr;
621
189483
  }
622
76658
  MallocedBuffer& operator=(MallocedBuffer&& other) {
623
76658
    this->~MallocedBuffer();
624
76658
    return *new(this) MallocedBuffer(std::move(other));
625
  }
626
379917
  ~MallocedBuffer() {
627
379917
    free(data);
628
379917
  }
629
  MallocedBuffer(const MallocedBuffer&) = delete;
630
  MallocedBuffer& operator=(const MallocedBuffer&) = delete;
631
};
632
633
template <typename T>
634
class NonCopyableMaybe {
635
 public:
636
5005
  NonCopyableMaybe() : empty_(true) {}
637
4317
  explicit NonCopyableMaybe(T&& value)
638
      : empty_(false),
639
8634
        value_(std::move(value)) {}
640
641
8574
  bool IsEmpty() const {
642
8574
    return empty_;
643
  }
644
645
1504
  const T* get() const {
646
1504
    return empty_ ? nullptr : &value_;
647
  }
648
649
24
  const T* operator->() const {
650
24
    CHECK(!empty_);
651
24
    return &value_;
652
  }
653
654
4222
  T&& Release() {
655
4222
    CHECK_EQ(empty_, false);
656
4222
    empty_ = true;
657
4222
    return std::move(value_);
658
  }
659
660
 private:
661
  bool empty_;
662
  T value_;
663
};
664
665
// Test whether some value can be called with ().
666
template <typename T, typename = void>
667
struct is_callable : std::is_function<T> { };
668
669
template <typename T>
670
struct is_callable<T, typename std::enable_if<
671
    std::is_same<decltype(void(&T::operator())), void>::value
672
    >::type> : std::true_type { };
673
674
template <typename T, void (*function)(T*)>
675
struct FunctionDeleter {
676
191073
  void operator()(T* pointer) const { function(pointer); }
677
  typedef std::unique_ptr<T, FunctionDeleter> Pointer;
678
};
679
680
template <typename T, void (*function)(T*)>
681
using DeleteFnPtr = typename FunctionDeleter<T, function>::Pointer;
682
683
std::vector<std::string> SplitString(const std::string& in,
684
                                     char delim,
685
                                     bool skipEmpty = true);
686
687
inline v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context,
688
                                           std::string_view str,
689
                                           v8::Isolate* isolate = nullptr);
690
template <typename T, typename test_for_number =
691
    typename std::enable_if<std::numeric_limits<T>::is_specialized, bool>::type>
692
inline v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context,
693
                                           const T& number,
694
                                           v8::Isolate* isolate = nullptr);
695
template <typename T>
696
inline v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context,
697
                                           const std::vector<T>& vec,
698
                                           v8::Isolate* isolate = nullptr);
699
template <typename T>
700
inline v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context,
701
                                           const std::set<T>& set,
702
                                           v8::Isolate* isolate = nullptr);
703
template <typename T, typename U>
704
inline v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context,
705
                                           const std::unordered_map<T, U>& map,
706
                                           v8::Isolate* isolate = nullptr);
707
708
// These macros expects a `Isolate* isolate` and a `Local<Context> context`
709
// to be in the scope.
710
#define READONLY_PROPERTY(obj, name, value)                                    \
711
  do {                                                                         \
712
    obj->DefineOwnProperty(                                                    \
713
           context, FIXED_ONE_BYTE_STRING(isolate, name), value, v8::ReadOnly) \
714
        .Check();                                                              \
715
  } while (0)
716
717
#define READONLY_DONT_ENUM_PROPERTY(obj, name, var)                            \
718
  do {                                                                         \
719
    obj->DefineOwnProperty(                                                    \
720
           context,                                                            \
721
           OneByteString(isolate, name),                                       \
722
           var,                                                                \
723
           static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum))    \
724
        .Check();                                                              \
725
  } while (0)
726
727
#define READONLY_FALSE_PROPERTY(obj, name)                                     \
728
  READONLY_PROPERTY(obj, name, v8::False(isolate))
729
730
#define READONLY_TRUE_PROPERTY(obj, name)                                      \
731
  READONLY_PROPERTY(obj, name, v8::True(isolate))
732
733
#define READONLY_STRING_PROPERTY(obj, name, str)                               \
734
  READONLY_PROPERTY(obj, name, ToV8Value(context, str).ToLocalChecked())
735
736
// Variation on NODE_DEFINE_CONSTANT that sets a String value.
737
#define NODE_DEFINE_STRING_CONSTANT(target, name, constant)                    \
738
  do {                                                                         \
739
    v8::Isolate* isolate = target->GetIsolate();                               \
740
    v8::Local<v8::String> constant_name =                                      \
741
        v8::String::NewFromUtf8(isolate, name).ToLocalChecked();               \
742
    v8::Local<v8::String> constant_value =                                     \
743
        v8::String::NewFromUtf8(isolate, constant).ToLocalChecked();           \
744
    v8::PropertyAttribute constant_attributes =                                \
745
        static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete);     \
746
    target                                                                     \
747
        ->DefineOwnProperty(isolate->GetCurrentContext(),                      \
748
                            constant_name,                                     \
749
                            constant_value,                                    \
750
                            constant_attributes)                               \
751
        .Check();                                                              \
752
  } while (0)
753
754
enum class Endianness { LITTLE, BIG };
755
756
8816
inline Endianness GetEndianness() {
757
  // Constant-folded by the compiler.
758
  const union {
759
    uint8_t u8[2];
760
    uint16_t u16;
761
8816
  } u = {{1, 0}};
762
8816
  return u.u16 == 1 ? Endianness::LITTLE : Endianness::BIG;
763
}
764
765
1
inline bool IsLittleEndian() {
766
1
  return GetEndianness() == Endianness::LITTLE;
767
}
768
769
8815
inline bool IsBigEndian() {
770
8815
  return GetEndianness() == Endianness::BIG;
771
}
772
773
// Round up a to the next highest multiple of b.
774
template <typename T>
775
166442
constexpr T RoundUp(T a, T b) {
776
166442
  return a % b != 0 ? a + b - (a % b) : a;
777
}
778
779
// Align ptr to an `alignment`-bytes boundary.
780
template <typename T, typename U>
781
24070
constexpr T* AlignUp(T* ptr, U alignment) {
782
  return reinterpret_cast<T*>(
783
24070
      RoundUp(reinterpret_cast<uintptr_t>(ptr), alignment));
784
}
785
786
class SlicedArguments : public MaybeStackBuffer<v8::Local<v8::Value>> {
787
 public:
788
  inline explicit SlicedArguments(
789
      const v8::FunctionCallbackInfo<v8::Value>& args, size_t start = 0);
790
};
791
792
// Convert a v8::PersistentBase, e.g. v8::Global, to a Local, with an extra
793
// optimization for strong persistent handles.
794
class PersistentToLocal {
795
 public:
796
  // If persistent.IsWeak() == false, then do not call persistent.Reset()
797
  // while the returned Local<T> is still in scope, it will destroy the
798
  // reference to the object.
799
  template <class TypeName>
800
6836616
  static inline v8::Local<TypeName> Default(
801
      v8::Isolate* isolate,
802
      const v8::PersistentBase<TypeName>& persistent) {
803
6836616
    if (persistent.IsWeak()) {
804
4491219
      return PersistentToLocal::Weak(isolate, persistent);
805
    } else {
806
2345397
      return PersistentToLocal::Strong(persistent);
807
    }
808
  }
809
810
  // Unchecked conversion from a non-weak Persistent<T> to Local<T>,
811
  // use with care!
812
  //
813
  // Do not call persistent.Reset() while the returned Local<T> is still in
814
  // scope, it will destroy the reference to the object.
815
  template <class TypeName>
816
36164159
  static inline v8::Local<TypeName> Strong(
817
      const v8::PersistentBase<TypeName>& persistent) {
818
    DCHECK(!persistent.IsWeak());
819
    return *reinterpret_cast<v8::Local<TypeName>*>(
820
36164159
        const_cast<v8::PersistentBase<TypeName>*>(&persistent));
821
  }
822
823
  template <class TypeName>
824
2368997
  static inline v8::Local<TypeName> Weak(
825
      v8::Isolate* isolate,
826
      const v8::PersistentBase<TypeName>& persistent) {
827
2368997
    return v8::Local<TypeName>::New(isolate, persistent);
828
  }
829
};
830
831
// Can be used as a key for std::unordered_map when lookup performance is more
832
// important than size and the keys are statically used to avoid redundant hash
833
// computations.
834
class FastStringKey {
835
 public:
836
  constexpr explicit FastStringKey(const char* name);
837
838
  struct Hash {
839
    constexpr size_t operator()(const FastStringKey& key) const;
840
  };
841
  constexpr bool operator==(const FastStringKey& other) const;
842
843
  constexpr const char* c_str() const;
844
845
 private:
846
  static constexpr size_t HashImpl(const char* str);
847
848
  const char* name_;
849
  size_t cached_hash_;
850
};
851
852
// Like std::static_pointer_cast but for unique_ptr with the default deleter.
853
template <typename T, typename U>
854
10750
std::unique_ptr<T> static_unique_pointer_cast(std::unique_ptr<U>&& ptr) {
855
10750
  return std::unique_ptr<T>(static_cast<T*>(ptr.release()));
856
}
857
858
#define MAYBE_FIELD_PTR(ptr, field) ptr == nullptr ? nullptr : &(ptr->field)
859
860
// Returns a non-zero code if it fails to open or read the file,
861
// aborts if it fails to close the file.
862
int ReadFileSync(std::string* result, const char* path);
863
864
v8::Local<v8::FunctionTemplate> NewFunctionTemplate(
865
    v8::Isolate* isolate,
866
    v8::FunctionCallback callback,
867
    v8::Local<v8::Signature> signature = v8::Local<v8::Signature>(),
868
    v8::ConstructorBehavior behavior = v8::ConstructorBehavior::kAllow,
869
    v8::SideEffectType side_effect = v8::SideEffectType::kHasSideEffect,
870
    const v8::CFunction* c_function = nullptr);
871
872
// Convenience methods for NewFunctionTemplate().
873
void SetMethod(v8::Local<v8::Context> context,
874
               v8::Local<v8::Object> that,
875
               const char* name,
876
               v8::FunctionCallback callback);
877
878
void SetFastMethod(v8::Local<v8::Context> context,
879
                   v8::Local<v8::Object> that,
880
                   const char* name,
881
                   v8::FunctionCallback slow_callback,
882
                   const v8::CFunction* c_function);
883
884
void SetProtoMethod(v8::Isolate* isolate,
885
                    v8::Local<v8::FunctionTemplate> that,
886
                    const char* name,
887
                    v8::FunctionCallback callback);
888
889
void SetInstanceMethod(v8::Isolate* isolate,
890
                       v8::Local<v8::FunctionTemplate> that,
891
                       const char* name,
892
                       v8::FunctionCallback callback);
893
894
// Safe variants denote the function has no side effects.
895
void SetMethodNoSideEffect(v8::Local<v8::Context> context,
896
                           v8::Local<v8::Object> that,
897
                           const char* name,
898
                           v8::FunctionCallback callback);
899
void SetProtoMethodNoSideEffect(v8::Isolate* isolate,
900
                                v8::Local<v8::FunctionTemplate> that,
901
                                const char* name,
902
                                v8::FunctionCallback callback);
903
904
enum class SetConstructorFunctionFlag {
905
  NONE,
906
  SET_CLASS_NAME,
907
};
908
909
void SetConstructorFunction(v8::Local<v8::Context> context,
910
                            v8::Local<v8::Object> that,
911
                            const char* name,
912
                            v8::Local<v8::FunctionTemplate> tmpl,
913
                            SetConstructorFunctionFlag flag =
914
                                SetConstructorFunctionFlag::SET_CLASS_NAME);
915
916
void SetConstructorFunction(v8::Local<v8::Context> context,
917
                            v8::Local<v8::Object> that,
918
                            v8::Local<v8::String> name,
919
                            v8::Local<v8::FunctionTemplate> tmpl,
920
                            SetConstructorFunctionFlag flag =
921
                                SetConstructorFunctionFlag::SET_CLASS_NAME);
922
923
}  // namespace node
924
925
#endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
926
927
#endif  // SRC_UTIL_H_