• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <set>
41 #include <string>
42 #include <string_view>
43 #include <type_traits>
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   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   KVStore() = default;
279   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   v8::Maybe<bool> AssignToObject(v8::Isolate* isolate,
301                                  v8::Local<v8::Context> context,
302                                  v8::Local<v8::Object> object);
303 
304   static std::shared_ptr<KVStore> CreateMapKVStore();
305 };
306 
307 // Convenience wrapper around v8::String::NewFromOneByte().
308 inline v8::Local<v8::String> OneByteString(v8::Isolate* isolate,
309                                            const char* data,
310                                            int length = -1);
311 
312 // For the people that compile with -funsigned-char.
313 inline v8::Local<v8::String> OneByteString(v8::Isolate* isolate,
314                                            const signed char* data,
315                                            int length = -1);
316 
317 inline v8::Local<v8::String> OneByteString(v8::Isolate* isolate,
318                                            const unsigned char* data,
319                                            int length = -1);
320 
321 // Used to be a macro, hence the uppercase name.
322 template <int N>
FIXED_ONE_BYTE_STRING(v8::Isolate * isolate,const char (& data)[N])323 inline v8::Local<v8::String> FIXED_ONE_BYTE_STRING(
324     v8::Isolate* isolate,
325     const char(&data)[N]) {
326   return OneByteString(isolate, data, N - 1);
327 }
328 
329 template <std::size_t N>
FIXED_ONE_BYTE_STRING(v8::Isolate * isolate,const std::array<char,N> & arr)330 inline v8::Local<v8::String> FIXED_ONE_BYTE_STRING(
331     v8::Isolate* isolate,
332     const std::array<char, N>& arr) {
333   return OneByteString(isolate, arr.data(), N - 1);
334 }
335 
336 
337 
338 // Swaps bytes in place. nbytes is the number of bytes to swap and must be a
339 // multiple of the word size (checked by function).
340 inline void SwapBytes16(char* data, size_t nbytes);
341 inline void SwapBytes32(char* data, size_t nbytes);
342 inline void SwapBytes64(char* data, size_t nbytes);
343 
344 // tolower() is locale-sensitive.  Use ToLower() instead.
345 inline char ToLower(char c);
346 inline std::string ToLower(const std::string& in);
347 
348 // toupper() is locale-sensitive.  Use ToUpper() instead.
349 inline char ToUpper(char c);
350 inline std::string ToUpper(const std::string& in);
351 
352 // strcasecmp() is locale-sensitive.  Use StringEqualNoCase() instead.
353 inline bool StringEqualNoCase(const char* a, const char* b);
354 
355 // strncasecmp() is locale-sensitive.  Use StringEqualNoCaseN() instead.
356 inline bool StringEqualNoCaseN(const char* a, const char* b, size_t length);
357 
358 template <typename T, size_t N>
arraysize(const T (&)[N])359 constexpr size_t arraysize(const T (&)[N]) {
360   return N;
361 }
362 
363 template <typename T, size_t N>
strsize(const T (&)[N])364 constexpr size_t strsize(const T (&)[N]) {
365   return N - 1;
366 }
367 
368 // Allocates an array of member type T. For up to kStackStorageSize items,
369 // the stack is used, otherwise malloc().
370 template <typename T, size_t kStackStorageSize = 1024>
371 class MaybeStackBuffer {
372  public:
out()373   const T* out() const {
374     return buf_;
375   }
376 
out()377   T* out() {
378     return buf_;
379   }
380 
381   // operator* for compatibility with `v8::String::(Utf8)Value`
382   T* operator*() {
383     return buf_;
384   }
385 
386   const T* operator*() const {
387     return buf_;
388   }
389 
390   T& operator[](size_t index) {
391     CHECK_LT(index, length());
392     return buf_[index];
393   }
394 
395   const T& operator[](size_t index) const {
396     CHECK_LT(index, length());
397     return buf_[index];
398   }
399 
length()400   size_t length() const {
401     return length_;
402   }
403 
404   // Current maximum capacity of the buffer with which SetLength() can be used
405   // without first calling AllocateSufficientStorage().
capacity()406   size_t capacity() const {
407     return capacity_;
408   }
409 
410   // Make sure enough space for `storage` entries is available.
411   // This method can be called multiple times throughout the lifetime of the
412   // buffer, but once this has been called Invalidate() cannot be used.
413   // Content of the buffer in the range [0, length()) is preserved.
414   void AllocateSufficientStorage(size_t storage);
415 
SetLength(size_t length)416   void SetLength(size_t length) {
417     // capacity() returns how much memory is actually available.
418     CHECK_LE(length, capacity());
419     length_ = length;
420   }
421 
SetLengthAndZeroTerminate(size_t length)422   void SetLengthAndZeroTerminate(size_t length) {
423     // capacity() returns how much memory is actually available.
424     CHECK_LE(length + 1, capacity());
425     SetLength(length);
426 
427     // T() is 0 for integer types, nullptr for pointers, etc.
428     buf_[length] = T();
429   }
430 
431   // Make dereferencing this object return nullptr.
432   // This method can be called multiple times throughout the lifetime of the
433   // buffer, but once this has been called AllocateSufficientStorage() cannot
434   // be used.
Invalidate()435   void Invalidate() {
436     CHECK(!IsAllocated());
437     capacity_ = 0;
438     length_ = 0;
439     buf_ = nullptr;
440   }
441 
442   // If the buffer is stored in the heap rather than on the stack.
IsAllocated()443   bool IsAllocated() const {
444     return !IsInvalidated() && buf_ != buf_st_;
445   }
446 
447   // If Invalidate() has been called.
IsInvalidated()448   bool IsInvalidated() const {
449     return buf_ == nullptr;
450   }
451 
452   // Release ownership of the malloc'd buffer.
453   // Note: This does not free the buffer.
Release()454   void Release() {
455     CHECK(IsAllocated());
456     buf_ = buf_st_;
457     length_ = 0;
458     capacity_ = arraysize(buf_st_);
459   }
460 
MaybeStackBuffer()461   MaybeStackBuffer()
462       : length_(0), capacity_(arraysize(buf_st_)), buf_(buf_st_) {
463     // Default to a zero-length, null-terminated buffer.
464     buf_[0] = T();
465   }
466 
MaybeStackBuffer(size_t storage)467   explicit MaybeStackBuffer(size_t storage) : MaybeStackBuffer() {
468     AllocateSufficientStorage(storage);
469   }
470 
~MaybeStackBuffer()471   ~MaybeStackBuffer() {
472     if (IsAllocated())
473       free(buf_);
474   }
475 
ToString()476   inline std::basic_string<T> ToString() const { return {out(), length()}; }
ToStringView()477   inline std::basic_string_view<T> ToStringView() const {
478     return {out(), length()};
479   }
480 
481  private:
482   size_t length_;
483   // capacity of the malloc'ed buf_
484   size_t capacity_;
485   T* buf_;
486   T buf_st_[kStackStorageSize];
487 };
488 
489 // Provides access to an ArrayBufferView's storage, either the original,
490 // or for small data, a copy of it. This object's lifetime is bound to the
491 // original ArrayBufferView's lifetime.
492 template <typename T, size_t kStackStorageSize = 64>
493 class ArrayBufferViewContents {
494  public:
495   ArrayBufferViewContents() = default;
496 
497   ArrayBufferViewContents(const ArrayBufferViewContents&) = delete;
498   void operator=(const ArrayBufferViewContents&) = delete;
499 
500   explicit inline ArrayBufferViewContents(v8::Local<v8::Value> value);
501   explicit inline ArrayBufferViewContents(v8::Local<v8::Object> value);
502   explicit inline ArrayBufferViewContents(v8::Local<v8::ArrayBufferView> abv);
503   inline void Read(v8::Local<v8::ArrayBufferView> abv);
504   inline void ReadValue(v8::Local<v8::Value> buf);
505 
WasDetached()506   inline bool WasDetached() const { return was_detached_; }
data()507   inline const T* data() const { return data_; }
length()508   inline size_t length() const { return length_; }
509 
510  private:
511   // Declaring operator new and delete as deleted is not spec compliant.
512   // Therefore, declare them private instead to disable dynamic alloc.
513   void* operator new(size_t size);
514   void* operator new[](size_t size);
515   void operator delete(void*, size_t);
516   void operator delete[](void*, size_t);
517 
518   T stack_storage_[kStackStorageSize];
519   T* data_ = nullptr;
520   size_t length_ = 0;
521   bool was_detached_ = false;
522 };
523 
524 class Utf8Value : public MaybeStackBuffer<char> {
525  public:
526   explicit Utf8Value(v8::Isolate* isolate, v8::Local<v8::Value> value);
527 
528   inline bool operator==(const char* a) const { return strcmp(out(), a) == 0; }
529   inline bool operator!=(const char* a) const { return !(*this == a); }
530 };
531 
532 class TwoByteValue : public MaybeStackBuffer<uint16_t> {
533  public:
534   explicit TwoByteValue(v8::Isolate* isolate, v8::Local<v8::Value> value);
535 };
536 
537 class BufferValue : public MaybeStackBuffer<char> {
538  public:
539   explicit BufferValue(v8::Isolate* isolate, v8::Local<v8::Value> value);
540 
ToString()541   inline std::string ToString() const { return std::string(out(), length()); }
542 };
543 
544 #define SPREAD_BUFFER_ARG(val, name)                                           \
545   CHECK((val)->IsArrayBufferView());                                           \
546   v8::Local<v8::ArrayBufferView> name = (val).As<v8::ArrayBufferView>();       \
547   const size_t name##_offset = name->ByteOffset();                             \
548   const size_t name##_length = name->ByteLength();                             \
549   char* const name##_data =                                                    \
550       static_cast<char*>(name->Buffer()->Data()) + name##_offset;              \
551   if (name##_length > 0) CHECK_NE(name##_data, nullptr);
552 
553 // Use this when a variable or parameter is unused in order to explicitly
554 // silence a compiler warning about that.
USE(T &&)555 template <typename T> inline void USE(T&&) {}
556 
557 template <typename Fn>
558 struct OnScopeLeaveImpl {
559   Fn fn_;
560   bool active_;
561 
OnScopeLeaveImplOnScopeLeaveImpl562   explicit OnScopeLeaveImpl(Fn&& fn) : fn_(std::move(fn)), active_(true) {}
~OnScopeLeaveImplOnScopeLeaveImpl563   ~OnScopeLeaveImpl() { if (active_) fn_(); }
564 
565   OnScopeLeaveImpl(const OnScopeLeaveImpl& other) = delete;
566   OnScopeLeaveImpl& operator=(const OnScopeLeaveImpl& other) = delete;
OnScopeLeaveImplOnScopeLeaveImpl567   OnScopeLeaveImpl(OnScopeLeaveImpl&& other)
568     : fn_(std::move(other.fn_)), active_(other.active_) {
569     other.active_ = false;
570   }
571   OnScopeLeaveImpl& operator=(OnScopeLeaveImpl&& other) {
572     if (this == &other) return *this;
573     this->~OnScopeLeave();
574     new (this)OnScopeLeaveImpl(std::move(other));
575     return *this;
576   }
577 };
578 
579 // Run a function when exiting the current scope. Used like this:
580 // auto on_scope_leave = OnScopeLeave([&] {
581 //   // ... run some code ...
582 // });
583 template <typename Fn>
OnScopeLeave(Fn && fn)584 inline MUST_USE_RESULT OnScopeLeaveImpl<Fn> OnScopeLeave(Fn&& fn) {
585   return OnScopeLeaveImpl<Fn>{std::move(fn)};
586 }
587 
588 // Simple RAII wrapper for contiguous data that uses malloc()/free().
589 template <typename T>
590 struct MallocedBuffer {
591   T* data;
592   size_t size;
593 
releaseMallocedBuffer594   T* release() {
595     T* ret = data;
596     data = nullptr;
597     return ret;
598   }
599 
TruncateMallocedBuffer600   void Truncate(size_t new_size) {
601     CHECK_LE(new_size, size);
602     size = new_size;
603   }
604 
ReallocMallocedBuffer605   void Realloc(size_t new_size) {
606     Truncate(new_size);
607     data = UncheckedRealloc(data, new_size);
608   }
609 
is_emptyMallocedBuffer610   bool is_empty() const { return data == nullptr; }
611 
MallocedBufferMallocedBuffer612   MallocedBuffer() : data(nullptr), size(0) {}
MallocedBufferMallocedBuffer613   explicit MallocedBuffer(size_t size) : data(Malloc<T>(size)), size(size) {}
MallocedBufferMallocedBuffer614   MallocedBuffer(T* data, size_t size) : data(data), size(size) {}
MallocedBufferMallocedBuffer615   MallocedBuffer(MallocedBuffer&& other) : data(other.data), size(other.size) {
616     other.data = nullptr;
617   }
618   MallocedBuffer& operator=(MallocedBuffer&& other) {
619     this->~MallocedBuffer();
620     return *new(this) MallocedBuffer(std::move(other));
621   }
~MallocedBufferMallocedBuffer622   ~MallocedBuffer() {
623     free(data);
624   }
625   MallocedBuffer(const MallocedBuffer&) = delete;
626   MallocedBuffer& operator=(const MallocedBuffer&) = delete;
627 };
628 
629 template <typename T>
630 class NonCopyableMaybe {
631  public:
NonCopyableMaybe()632   NonCopyableMaybe() : empty_(true) {}
NonCopyableMaybe(T && value)633   explicit NonCopyableMaybe(T&& value)
634       : empty_(false),
635         value_(std::move(value)) {}
636 
IsEmpty()637   bool IsEmpty() const {
638     return empty_;
639   }
640 
get()641   const T* get() const {
642     return empty_ ? nullptr : &value_;
643   }
644 
645   const T* operator->() const {
646     CHECK(!empty_);
647     return &value_;
648   }
649 
Release()650   T&& Release() {
651     CHECK_EQ(empty_, false);
652     empty_ = true;
653     return std::move(value_);
654   }
655 
656  private:
657   bool empty_;
658   T value_;
659 };
660 
661 // Test whether some value can be called with ().
662 template <typename T, typename = void>
663 struct is_callable : std::is_function<T> { };
664 
665 template <typename T>
666 struct is_callable<T, typename std::enable_if<
667     std::is_same<decltype(void(&T::operator())), void>::value
668     >::type> : std::true_type { };
669 
670 template <typename T, void (*function)(T*)>
671 struct FunctionDeleter {
672   void operator()(T* pointer) const { function(pointer); }
673   typedef std::unique_ptr<T, FunctionDeleter> Pointer;
674 };
675 
676 template <typename T, void (*function)(T*)>
677 using DeleteFnPtr = typename FunctionDeleter<T, function>::Pointer;
678 
679 std::vector<std::string_view> SplitString(const std::string_view in,
680                                           const std::string_view delim);
681 
682 inline v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context,
683                                            std::string_view str,
684                                            v8::Isolate* isolate = nullptr);
685 template <typename T, typename test_for_number =
686     typename std::enable_if<std::numeric_limits<T>::is_specialized, bool>::type>
687 inline v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context,
688                                            const T& number,
689                                            v8::Isolate* isolate = nullptr);
690 template <typename T>
691 inline v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context,
692                                            const std::vector<T>& vec,
693                                            v8::Isolate* isolate = nullptr);
694 template <typename T>
695 inline v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context,
696                                            const std::set<T>& set,
697                                            v8::Isolate* isolate = nullptr);
698 template <typename T, typename U>
699 inline v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context,
700                                            const std::unordered_map<T, U>& map,
701                                            v8::Isolate* isolate = nullptr);
702 
703 // These macros expects a `Isolate* isolate` and a `Local<Context> context`
704 // to be in the scope.
705 #define READONLY_PROPERTY(obj, name, value)                                    \
706   do {                                                                         \
707     obj->DefineOwnProperty(                                                    \
708            context, FIXED_ONE_BYTE_STRING(isolate, name), value, v8::ReadOnly) \
709         .Check();                                                              \
710   } while (0)
711 
712 #define READONLY_DONT_ENUM_PROPERTY(obj, name, var)                            \
713   do {                                                                         \
714     obj->DefineOwnProperty(                                                    \
715            context,                                                            \
716            OneByteString(isolate, name),                                       \
717            var,                                                                \
718            static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum))    \
719         .Check();                                                              \
720   } while (0)
721 
722 #define READONLY_FALSE_PROPERTY(obj, name)                                     \
723   READONLY_PROPERTY(obj, name, v8::False(isolate))
724 
725 #define READONLY_TRUE_PROPERTY(obj, name)                                      \
726   READONLY_PROPERTY(obj, name, v8::True(isolate))
727 
728 #define READONLY_STRING_PROPERTY(obj, name, str)                               \
729   READONLY_PROPERTY(obj, name, ToV8Value(context, str).ToLocalChecked())
730 
731 // Variation on NODE_DEFINE_CONSTANT that sets a String value.
732 #define NODE_DEFINE_STRING_CONSTANT(target, name, constant)                    \
733   do {                                                                         \
734     v8::Isolate* isolate = target->GetIsolate();                               \
735     v8::Local<v8::String> constant_name =                                      \
736         v8::String::NewFromUtf8(isolate, name).ToLocalChecked();               \
737     v8::Local<v8::String> constant_value =                                     \
738         v8::String::NewFromUtf8(isolate, constant).ToLocalChecked();           \
739     v8::PropertyAttribute constant_attributes =                                \
740         static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete);     \
741     target                                                                     \
742         ->DefineOwnProperty(isolate->GetCurrentContext(),                      \
743                             constant_name,                                     \
744                             constant_value,                                    \
745                             constant_attributes)                               \
746         .Check();                                                              \
747   } while (0)
748 
749 enum class Endianness { LITTLE, BIG };
750 
751 inline Endianness GetEndianness() {
752   // Constant-folded by the compiler.
753   const union {
754     uint8_t u8[2];
755     uint16_t u16;
756   } u = {{1, 0}};
757   return u.u16 == 1 ? Endianness::LITTLE : Endianness::BIG;
758 }
759 
760 inline bool IsLittleEndian() {
761   return GetEndianness() == Endianness::LITTLE;
762 }
763 
764 inline bool IsBigEndian() {
765   return GetEndianness() == Endianness::BIG;
766 }
767 
768 // Round up a to the next highest multiple of b.
769 template <typename T>
770 constexpr T RoundUp(T a, T b) {
771   return a % b != 0 ? a + b - (a % b) : a;
772 }
773 
774 // Align ptr to an `alignment`-bytes boundary.
775 template <typename T, typename U>
776 constexpr T* AlignUp(T* ptr, U alignment) {
777   return reinterpret_cast<T*>(
778       RoundUp(reinterpret_cast<uintptr_t>(ptr), alignment));
779 }
780 
781 class SlicedArguments : public MaybeStackBuffer<v8::Local<v8::Value>> {
782  public:
783   inline explicit SlicedArguments(
784       const v8::FunctionCallbackInfo<v8::Value>& args, size_t start = 0);
785 };
786 
787 // Convert a v8::PersistentBase, e.g. v8::Global, to a Local, with an extra
788 // optimization for strong persistent handles.
789 class PersistentToLocal {
790  public:
791   // If persistent.IsWeak() == false, then do not call persistent.Reset()
792   // while the returned Local<T> is still in scope, it will destroy the
793   // reference to the object.
794   template <class TypeName>
795   static inline v8::Local<TypeName> Default(
796       v8::Isolate* isolate,
797       const v8::PersistentBase<TypeName>& persistent) {
798     if (persistent.IsWeak()) {
799       return PersistentToLocal::Weak(isolate, persistent);
800     } else {
801       return PersistentToLocal::Strong(persistent);
802     }
803   }
804 
805   // Unchecked conversion from a non-weak Persistent<T> to Local<T>,
806   // use with care!
807   //
808   // Do not call persistent.Reset() while the returned Local<T> is still in
809   // scope, it will destroy the reference to the object.
810   template <class TypeName>
811   static inline v8::Local<TypeName> Strong(
812       const v8::PersistentBase<TypeName>& persistent) {
813     DCHECK(!persistent.IsWeak());
814     return *reinterpret_cast<v8::Local<TypeName>*>(
815         const_cast<v8::PersistentBase<TypeName>*>(&persistent));
816   }
817 
818   template <class TypeName>
819   static inline v8::Local<TypeName> Weak(
820       v8::Isolate* isolate,
821       const v8::PersistentBase<TypeName>& persistent) {
822     return v8::Local<TypeName>::New(isolate, persistent);
823   }
824 };
825 
826 // Can be used as a key for std::unordered_map when lookup performance is more
827 // important than size and the keys are statically used to avoid redundant hash
828 // computations.
829 class FastStringKey {
830  public:
831   constexpr explicit FastStringKey(std::string_view name);
832 
833   struct Hash {
834     constexpr size_t operator()(const FastStringKey& key) const;
835   };
836   constexpr bool operator==(const FastStringKey& other) const;
837 
838   constexpr std::string_view as_string_view() const;
839 
840  private:
841   static constexpr size_t HashImpl(std::string_view str);
842 
843   const std::string_view name_;
844   const size_t cached_hash_;
845 };
846 
847 // Like std::static_pointer_cast but for unique_ptr with the default deleter.
848 template <typename T, typename U>
849 std::unique_ptr<T> static_unique_pointer_cast(std::unique_ptr<U>&& ptr) {
850   return std::unique_ptr<T>(static_cast<T*>(ptr.release()));
851 }
852 
853 #define MAYBE_FIELD_PTR(ptr, field) ptr == nullptr ? nullptr : &(ptr->field)
854 
855 // Returns a non-zero code if it fails to open or read the file,
856 // aborts if it fails to close the file.
857 int ReadFileSync(std::string* result, const char* path);
858 
859 v8::Local<v8::FunctionTemplate> NewFunctionTemplate(
860     v8::Isolate* isolate,
861     v8::FunctionCallback callback,
862     v8::Local<v8::Signature> signature = v8::Local<v8::Signature>(),
863     v8::ConstructorBehavior behavior = v8::ConstructorBehavior::kAllow,
864     v8::SideEffectType side_effect = v8::SideEffectType::kHasSideEffect,
865     const v8::CFunction* c_function = nullptr);
866 
867 // Convenience methods for NewFunctionTemplate().
868 void SetMethod(v8::Local<v8::Context> context,
869                v8::Local<v8::Object> that,
870                const char* name,
871                v8::FunctionCallback callback);
872 
873 void SetFastMethod(v8::Local<v8::Context> context,
874                    v8::Local<v8::Object> that,
875                    const char* name,
876                    v8::FunctionCallback slow_callback,
877                    const v8::CFunction* c_function);
878 void SetFastMethodNoSideEffect(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_
928