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 bool ReadSystemXpmState();
57 
58 // Maybe remove kPathSeparator when cpp17 is ready
59 #ifdef _WIN32
60     constexpr char kPathSeparator = '\\';
61 /* MAX_PATH is in characters, not bytes. Make sure we have enough headroom. */
62 #define PATH_MAX_BYTES (MAX_PATH * 4)
63 #else
64     constexpr char kPathSeparator = '/';
65 #define PATH_MAX_BYTES (PATH_MAX)
66 #endif
67 
68 // These should be used in our code as opposed to the native
69 // versions as they abstract out some platform and or
70 // compiler version specific functionality
71 // malloc(0) and realloc(ptr, 0) have implementation-defined behavior in
72 // that the standard allows them to either return a unique pointer or a
73 // nullptr for zero-sized allocation requests.  Normalize by always using
74 // a nullptr.
75 template <typename T>
76 inline T* UncheckedRealloc(T* pointer, size_t n);
77 template <typename T>
78 inline T* UncheckedMalloc(size_t n);
79 template <typename T>
80 inline T* UncheckedCalloc(size_t n);
81 
82 // Same things, but aborts immediately instead of returning nullptr when
83 // no memory is available.
84 template <typename T>
85 inline T* Realloc(T* pointer, size_t n);
86 template <typename T>
87 inline T* Malloc(size_t n);
88 template <typename T>
89 inline T* Calloc(size_t n);
90 
91 inline char* Malloc(size_t n);
92 inline char* Calloc(size_t n);
93 inline char* UncheckedMalloc(size_t n);
94 inline char* UncheckedCalloc(size_t n);
95 
96 template <typename T>
97 inline T MultiplyWithOverflowCheck(T a, T b);
98 
99 namespace per_process {
100 // Tells whether the per-process V8::Initialize() is called and
101 // if it is safe to call v8::Isolate::TryGetCurrent().
102 extern bool v8_initialized;
103 }  // namespace per_process
104 
105 // Used by the allocation functions when allocation fails.
106 // Thin wrapper around v8::Isolate::LowMemoryNotification() that checks
107 // whether V8 is initialized.
108 void LowMemoryNotification();
109 
110 // The reason that Assert() takes a struct argument instead of individual
111 // const char*s is to ease instruction cache pressure in calls from CHECK.
112 struct AssertionInfo {
113   const char* file_line;  // filename:line
114   const char* message;
115   const char* function;
116 };
117 [[noreturn]] void NODE_EXTERN_PRIVATE Assert(const AssertionInfo& info);
118 [[noreturn]] void NODE_EXTERN_PRIVATE Abort();
119 void DumpBacktrace(FILE* fp);
120 
121 // Windows 8+ does not like abort() in Release mode
122 #ifdef _WIN32
123 #define ABORT_NO_BACKTRACE() _exit(134)
124 #else
125 #define ABORT_NO_BACKTRACE() abort()
126 #endif
127 
128 #define ABORT() node::Abort()
129 
130 #define ERROR_AND_ABORT(expr)                                                 \
131   do {                                                                        \
132     /* Make sure that this struct does not end up in inline code, but      */ \
133     /* rather in a read-only data section when modifying this code.        */ \
134     static const node::AssertionInfo args = {                                 \
135       __FILE__ ":" STRINGIFY(__LINE__), #expr, PRETTY_FUNCTION_NAME           \
136     };                                                                        \
137     node::Assert(args);                                                       \
138   } while (0)
139 
140 #ifdef __GNUC__
141 #define LIKELY(expr) __builtin_expect(!!(expr), 1)
142 #define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
143 #define PRETTY_FUNCTION_NAME __PRETTY_FUNCTION__
144 #else
145 #define LIKELY(expr) expr
146 #define UNLIKELY(expr) expr
147 #define PRETTY_FUNCTION_NAME ""
148 #endif
149 
150 #define STRINGIFY_(x) #x
151 #define STRINGIFY(x) STRINGIFY_(x)
152 
153 #define CHECK(expr)                                                           \
154   do {                                                                        \
155     if (UNLIKELY(!(expr))) {                                                  \
156       ERROR_AND_ABORT(expr);                                                  \
157     }                                                                         \
158   } while (0)
159 
160 #define CHECK_EQ(a, b) CHECK((a) == (b))
161 #define CHECK_GE(a, b) CHECK((a) >= (b))
162 #define CHECK_GT(a, b) CHECK((a) > (b))
163 #define CHECK_LE(a, b) CHECK((a) <= (b))
164 #define CHECK_LT(a, b) CHECK((a) < (b))
165 #define CHECK_NE(a, b) CHECK((a) != (b))
166 #define CHECK_NULL(val) CHECK((val) == nullptr)
167 #define CHECK_NOT_NULL(val) CHECK((val) != nullptr)
168 #define CHECK_IMPLIES(a, b) CHECK(!(a) || (b))
169 
170 #ifdef DEBUG
171   #define DCHECK(expr) CHECK(expr)
172   #define DCHECK_EQ(a, b) CHECK((a) == (b))
173   #define DCHECK_GE(a, b) CHECK((a) >= (b))
174   #define DCHECK_GT(a, b) CHECK((a) > (b))
175   #define DCHECK_LE(a, b) CHECK((a) <= (b))
176   #define DCHECK_LT(a, b) CHECK((a) < (b))
177   #define DCHECK_NE(a, b) CHECK((a) != (b))
178   #define DCHECK_NULL(val) CHECK((val) == nullptr)
179   #define DCHECK_NOT_NULL(val) CHECK((val) != nullptr)
180   #define DCHECK_IMPLIES(a, b) CHECK(!(a) || (b))
181 #else
182   #define DCHECK(expr)
183   #define DCHECK_EQ(a, b)
184   #define DCHECK_GE(a, b)
185   #define DCHECK_GT(a, b)
186   #define DCHECK_LE(a, b)
187   #define DCHECK_LT(a, b)
188   #define DCHECK_NE(a, b)
189   #define DCHECK_NULL(val)
190   #define DCHECK_NOT_NULL(val)
191   #define DCHECK_IMPLIES(a, b)
192 #endif
193 
194 
195 #define UNREACHABLE(...)                                                      \
196   ERROR_AND_ABORT("Unreachable code reached" __VA_OPT__(": ") __VA_ARGS__)
197 
198 // ECMA262 20.1.2.6 Number.MAX_SAFE_INTEGER (2^53-1)
199 constexpr int64_t kMaxSafeJsInteger = 9007199254740991;
200 
201 inline bool IsSafeJsInt(v8::Local<v8::Value> v);
202 
203 // TAILQ-style intrusive list node.
204 template <typename T>
205 class ListNode;
206 
207 // TAILQ-style intrusive list head.
208 template <typename T, ListNode<T> (T::*M)>
209 class ListHead;
210 
211 template <typename T>
212 class ListNode {
213  public:
214   inline ListNode();
215   inline ~ListNode();
216   inline void Remove();
217   inline bool IsEmpty() const;
218 
219   ListNode(const ListNode&) = delete;
220   ListNode& operator=(const ListNode&) = delete;
221 
222  private:
223   template <typename U, ListNode<U> (U::*M)> friend class ListHead;
224   friend int GenDebugSymbols();
225   ListNode* prev_;
226   ListNode* next_;
227 };
228 
229 template <typename T, ListNode<T> (T::*M)>
230 class ListHead {
231  public:
232   class Iterator {
233    public:
234     inline T* operator*() const;
235     inline const Iterator& operator++();
236     inline bool operator!=(const Iterator& that) const;
237 
238    private:
239     friend class ListHead;
240     inline explicit Iterator(ListNode<T>* node);
241     ListNode<T>* node_;
242   };
243 
244   inline ListHead() = default;
245   inline ~ListHead();
246   inline void PushBack(T* element);
247   inline void PushFront(T* element);
248   inline bool IsEmpty() const;
249   inline T* PopFront();
250   inline Iterator begin() const;
251   inline Iterator end() const;
252 
253   ListHead(const ListHead&) = delete;
254   ListHead& operator=(const ListHead&) = delete;
255 
256  private:
257   friend int GenDebugSymbols();
258   ListNode<T> head_;
259 };
260 
261 // The helper is for doing safe downcasts from base types to derived types.
262 template <typename Inner, typename Outer>
263 class ContainerOfHelper {
264  public:
265   inline ContainerOfHelper(Inner Outer::*field, Inner* pointer);
266   template <typename TypeName>
267   inline operator TypeName*() const;
268  private:
269   Outer* const pointer_;
270 };
271 
272 // Calculate the address of the outer (i.e. embedding) struct from
273 // the interior pointer to a data member.
274 template <typename Inner, typename Outer>
275 constexpr ContainerOfHelper<Inner, Outer> ContainerOf(Inner Outer::*field,
276                                                       Inner* pointer);
277 
278 class KVStore {
279  public:
280   KVStore() = default;
281   virtual ~KVStore() = default;
282   KVStore(const KVStore&) = delete;
283   KVStore& operator=(const KVStore&) = delete;
284   KVStore(KVStore&&) = delete;
285   KVStore& operator=(KVStore&&) = delete;
286 
287   virtual v8::MaybeLocal<v8::String> Get(v8::Isolate* isolate,
288                                          v8::Local<v8::String> key) const = 0;
289   virtual v8::Maybe<std::string> Get(const char* key) const = 0;
290   virtual void Set(v8::Isolate* isolate,
291                    v8::Local<v8::String> key,
292                    v8::Local<v8::String> value) = 0;
293   virtual int32_t Query(v8::Isolate* isolate,
294                         v8::Local<v8::String> key) const = 0;
295   virtual int32_t Query(const char* key) const = 0;
296   virtual void Delete(v8::Isolate* isolate, v8::Local<v8::String> key) = 0;
297   virtual v8::Local<v8::Array> Enumerate(v8::Isolate* isolate) const = 0;
298 
299   virtual std::shared_ptr<KVStore> Clone(v8::Isolate* isolate) const;
300   virtual v8::Maybe<bool> AssignFromObject(v8::Local<v8::Context> context,
301                                            v8::Local<v8::Object> entries);
302   v8::Maybe<bool> AssignToObject(v8::Isolate* isolate,
303                                  v8::Local<v8::Context> context,
304                                  v8::Local<v8::Object> object);
305 
306   static std::shared_ptr<KVStore> CreateMapKVStore();
307 };
308 
309 // Convenience wrapper around v8::String::NewFromOneByte().
310 inline v8::Local<v8::String> OneByteString(v8::Isolate* isolate,
311                                            const char* data,
312                                            int length = -1);
313 
314 // For the people that compile with -funsigned-char.
315 inline v8::Local<v8::String> OneByteString(v8::Isolate* isolate,
316                                            const signed char* data,
317                                            int length = -1);
318 
319 inline v8::Local<v8::String> OneByteString(v8::Isolate* isolate,
320                                            const unsigned char* data,
321                                            int length = -1);
322 
323 // Used to be a macro, hence the uppercase name.
324 template <int N>
FIXED_ONE_BYTE_STRING( v8::Isolate* isolate, const char(&data)[N])325 inline v8::Local<v8::String> FIXED_ONE_BYTE_STRING(
326     v8::Isolate* isolate,
327     const char(&data)[N]) {
328   return OneByteString(isolate, data, N - 1);
329 }
330 
331 template <std::size_t N>
FIXED_ONE_BYTE_STRING( v8::Isolate* isolate, const std::array<char, N>& arr)332 inline v8::Local<v8::String> FIXED_ONE_BYTE_STRING(
333     v8::Isolate* isolate,
334     const std::array<char, N>& arr) {
335   return OneByteString(isolate, arr.data(), N - 1);
336 }
337 
338 
339 
340 // Swaps bytes in place. nbytes is the number of bytes to swap and must be a
341 // multiple of the word size (checked by function).
342 inline void SwapBytes16(char* data, size_t nbytes);
343 inline void SwapBytes32(char* data, size_t nbytes);
344 inline void SwapBytes64(char* data, size_t nbytes);
345 
346 // tolower() is locale-sensitive.  Use ToLower() instead.
347 inline char ToLower(char c);
348 inline std::string ToLower(const std::string& in);
349 
350 // toupper() is locale-sensitive.  Use ToUpper() instead.
351 inline char ToUpper(char c);
352 inline std::string ToUpper(const std::string& in);
353 
354 // strcasecmp() is locale-sensitive.  Use StringEqualNoCase() instead.
355 inline bool StringEqualNoCase(const char* a, const char* b);
356 
357 // strncasecmp() is locale-sensitive.  Use StringEqualNoCaseN() instead.
358 inline bool StringEqualNoCaseN(const char* a, const char* b, size_t length);
359 
360 template <typename T, size_t N>
361 constexpr size_t arraysize(const T (&)[N]) {
362   return N;
363 }
364 
365 template <typename T, size_t N>
366 constexpr size_t strsize(const T (&)[N]) {
367   return N - 1;
368 }
369 
370 // Allocates an array of member type T. For up to kStackStorageSize items,
371 // the stack is used, otherwise malloc().
372 template <typename T, size_t kStackStorageSize = 1024>
373 class MaybeStackBuffer {
374  public:
out() const375   const T* out() const {
376     return buf_;
377   }
378 
out()379   T* out() {
380     return buf_;
381   }
382 
383   // operator* for compatibility with `v8::String::(Utf8)Value`
operator *()384   T* operator*() {
385     return buf_;
386   }
387 
operator *() const388   const T* operator*() const {
389     return buf_;
390   }
391 
operator [](size_t index)392   T& operator[](size_t index) {
393     CHECK_LT(index, length());
394     return buf_[index];
395   }
396 
operator [](size_t index) const397   const T& operator[](size_t index) const {
398     CHECK_LT(index, length());
399     return buf_[index];
400   }
401 
length() const402   size_t length() const {
403     return length_;
404   }
405 
406   // Current maximum capacity of the buffer with which SetLength() can be used
407   // without first calling AllocateSufficientStorage().
capacity() const408   size_t capacity() const {
409     return capacity_;
410   }
411 
412   // Make sure enough space for `storage` entries is available.
413   // This method can be called multiple times throughout the lifetime of the
414   // buffer, but once this has been called Invalidate() cannot be used.
415   // Content of the buffer in the range [0, length()) is preserved.
416   void AllocateSufficientStorage(size_t storage);
417 
SetLength(size_t length)418   void SetLength(size_t length) {
419     // capacity() returns how much memory is actually available.
420     CHECK_LE(length, capacity());
421     length_ = length;
422   }
423 
SetLengthAndZeroTerminate(size_t length)424   void SetLengthAndZeroTerminate(size_t length) {
425     // capacity() returns how much memory is actually available.
426     CHECK_LE(length + 1, capacity());
427     SetLength(length);
428 
429     // T() is 0 for integer types, nullptr for pointers, etc.
430     buf_[length] = T();
431   }
432 
433   // Make dereferencing this object return nullptr.
434   // This method can be called multiple times throughout the lifetime of the
435   // buffer, but once this has been called AllocateSufficientStorage() cannot
436   // be used.
Invalidate()437   void Invalidate() {
438     CHECK(!IsAllocated());
439     capacity_ = 0;
440     length_ = 0;
441     buf_ = nullptr;
442   }
443 
444   // If the buffer is stored in the heap rather than on the stack.
IsAllocated() const445   bool IsAllocated() const {
446     return !IsInvalidated() && buf_ != buf_st_;
447   }
448 
449   // If Invalidate() has been called.
IsInvalidated() const450   bool IsInvalidated() const {
451     return buf_ == nullptr;
452   }
453 
454   // Release ownership of the malloc'd buffer.
455   // Note: This does not free the buffer.
Release()456   void Release() {
457     CHECK(IsAllocated());
458     buf_ = buf_st_;
459     length_ = 0;
460     capacity_ = arraysize(buf_st_);
461   }
462 
MaybeStackBuffer()463   MaybeStackBuffer()
464       : length_(0), capacity_(arraysize(buf_st_)), buf_(buf_st_) {
465     // Default to a zero-length, null-terminated buffer.
466     buf_[0] = T();
467   }
468 
MaybeStackBuffer(size_t storage)469   explicit MaybeStackBuffer(size_t storage) : MaybeStackBuffer() {
470     AllocateSufficientStorage(storage);
471   }
472 
~MaybeStackBuffer()473   ~MaybeStackBuffer() {
474     if (IsAllocated())
475       free(buf_);
476   }
477 
ToString() const478   inline std::basic_string<T> ToString() const { return {out(), length()}; }
ToStringView() const479   inline std::basic_string_view<T> ToStringView() const {
480     return {out(), length()};
481   }
482 
483  private:
484   size_t length_;
485   // capacity of the malloc'ed buf_
486   size_t capacity_;
487   T* buf_;
488   T buf_st_[kStackStorageSize];
489 };
490 
491 // Provides access to an ArrayBufferView's storage, either the original,
492 // or for small data, a copy of it. This object's lifetime is bound to the
493 // original ArrayBufferView's lifetime.
494 template <typename T, size_t kStackStorageSize = 64>
495 class ArrayBufferViewContents {
496  public:
497   ArrayBufferViewContents() = default;
498 
499   ArrayBufferViewContents(const ArrayBufferViewContents&) = delete;
500   void operator=(const ArrayBufferViewContents&) = delete;
501 
502   explicit inline ArrayBufferViewContents(v8::Local<v8::Value> value);
503   explicit inline ArrayBufferViewContents(v8::Local<v8::Object> value);
504   explicit inline ArrayBufferViewContents(v8::Local<v8::ArrayBufferView> abv);
505   inline void Read(v8::Local<v8::ArrayBufferView> abv);
506   inline void ReadValue(v8::Local<v8::Value> buf);
507 
WasDetached() const508   inline bool WasDetached() const { return was_detached_; }
data() const509   inline const T* data() const { return data_; }
length() const510   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   bool was_detached_ = false;
524 };
525 
526 class Utf8Value : public MaybeStackBuffer<char> {
527  public:
528   explicit Utf8Value(v8::Isolate* isolate, v8::Local<v8::Value> value);
529 
operator ==(const char* a) const530   inline bool operator==(const char* a) const { return strcmp(out(), a) == 0; }
operator !=(const char* a) const531   inline bool operator!=(const char* a) const { return !(*this == a); }
532 };
533 
534 class TwoByteValue : public MaybeStackBuffer<uint16_t> {
535  public:
536   explicit TwoByteValue(v8::Isolate* isolate, v8::Local<v8::Value> value);
537 };
538 
539 class BufferValue : public MaybeStackBuffer<char> {
540  public:
541   explicit BufferValue(v8::Isolate* isolate, v8::Local<v8::Value> value);
542 
ToString() const543   inline std::string ToString() const { return std::string(out(), length()); }
544 };
545 
546 #define SPREAD_BUFFER_ARG(val, name)                                           \
547   CHECK((val)->IsArrayBufferView());                                           \
548   v8::Local<v8::ArrayBufferView> name = (val).As<v8::ArrayBufferView>();       \
549   const size_t name##_offset = name->ByteOffset();                             \
550   const size_t name##_length = name->ByteLength();                             \
551   char* const name##_data =                                                    \
552       static_cast<char*>(name->Buffer()->Data()) + name##_offset;              \
553   if (name##_length > 0) CHECK_NE(name##_data, nullptr);
554 
555 // Use this when a variable or parameter is unused in order to explicitly
556 // silence a compiler warning about that.
USE(T&&)557 template <typename T> inline void USE(T&&) {}
558 
559 template <typename Fn>
560 struct OnScopeLeaveImpl {
561   Fn fn_;
562   bool active_;
563 
OnScopeLeaveImplnode::OnScopeLeaveImpl564   explicit OnScopeLeaveImpl(Fn&& fn) : fn_(std::move(fn)), active_(true) {}
~OnScopeLeaveImplnode::OnScopeLeaveImpl565   ~OnScopeLeaveImpl() { if (active_) fn_(); }
566 
567   OnScopeLeaveImpl(const OnScopeLeaveImpl& other) = delete;
568   OnScopeLeaveImpl& operator=(const OnScopeLeaveImpl& other) = delete;
OnScopeLeaveImplnode::OnScopeLeaveImpl569   OnScopeLeaveImpl(OnScopeLeaveImpl&& other)
570     : fn_(std::move(other.fn_)), active_(other.active_) {
571     other.active_ = false;
572   }
573 };
574 
575 // Run a function when exiting the current scope. Used like this:
576 // auto on_scope_leave = OnScopeLeave([&] {
577 //   // ... run some code ...
578 // });
579 template <typename Fn>
OnScopeLeave(Fn&& fn)580 inline MUST_USE_RESULT OnScopeLeaveImpl<Fn> OnScopeLeave(Fn&& fn) {
581   return OnScopeLeaveImpl<Fn>{std::move(fn)};
582 }
583 
584 // Simple RAII wrapper for contiguous data that uses malloc()/free().
585 template <typename T>
586 struct MallocedBuffer {
587   T* data;
588   size_t size;
589 
releasenode::MallocedBuffer590   T* release() {
591     T* ret = data;
592     data = nullptr;
593     return ret;
594   }
595 
Truncatenode::MallocedBuffer596   void Truncate(size_t new_size) {
597     CHECK_LE(new_size, size);
598     size = new_size;
599   }
600 
Reallocnode::MallocedBuffer601   void Realloc(size_t new_size) {
602     Truncate(new_size);
603     data = UncheckedRealloc(data, new_size);
604   }
605 
is_emptynode::MallocedBuffer606   bool is_empty() const { return data == nullptr; }
607 
MallocedBuffernode::MallocedBuffer608   MallocedBuffer() : data(nullptr), size(0) {}
MallocedBuffernode::MallocedBuffer609   explicit MallocedBuffer(size_t size) : data(Malloc<T>(size)), size(size) {}
MallocedBuffernode::MallocedBuffer610   MallocedBuffer(T* data, size_t size) : data(data), size(size) {}
MallocedBuffernode::MallocedBuffer611   MallocedBuffer(MallocedBuffer&& other) : data(other.data), size(other.size) {
612     other.data = nullptr;
613   }
operator =node::MallocedBuffer614   MallocedBuffer& operator=(MallocedBuffer&& other) {
615     this->~MallocedBuffer();
616     return *new(this) MallocedBuffer(std::move(other));
617   }
~MallocedBuffernode::MallocedBuffer618   ~MallocedBuffer() {
619     free(data);
620   }
621   MallocedBuffer(const MallocedBuffer&) = delete;
622   MallocedBuffer& operator=(const MallocedBuffer&) = delete;
623 };
624 
625 template <typename T>
626 class NonCopyableMaybe {
627  public:
NonCopyableMaybe()628   NonCopyableMaybe() : empty_(true) {}
NonCopyableMaybe(T&& value)629   explicit NonCopyableMaybe(T&& value)
630       : empty_(false),
631         value_(std::move(value)) {}
632 
IsEmpty() const633   bool IsEmpty() const {
634     return empty_;
635   }
636 
get() const637   const T* get() const {
638     return empty_ ? nullptr : &value_;
639   }
640 
operator ->() const641   const T* operator->() const {
642     CHECK(!empty_);
643     return &value_;
644   }
645 
Release()646   T&& Release() {
647     CHECK_EQ(empty_, false);
648     empty_ = true;
649     return std::move(value_);
650   }
651 
652  private:
653   bool empty_;
654   T value_;
655 };
656 
657 // Test whether some value can be called with ().
658 template <typename T, typename = void>
659 struct is_callable : std::is_function<T> { };
660 
661 template <typename T>
662 struct is_callable<T, typename std::enable_if<
663     std::is_same<decltype(void(&T::operator())), void>::value
664     >::type> : std::true_type { };
665 
666 template <typename T, void (*function)(T*)>
667 struct FunctionDeleter {
operator ()node::FunctionDeleter668   void operator()(T* pointer) const { function(pointer); }
669   typedef std::unique_ptr<T, FunctionDeleter> Pointer;
670 };
671 
672 template <typename T, void (*function)(T*)>
673 using DeleteFnPtr = typename FunctionDeleter<T, function>::Pointer;
674 
675 std::vector<std::string_view> SplitString(const std::string_view in,
676                                           const std::string_view delim);
677 
678 inline v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context,
679                                            std::string_view str,
680                                            v8::Isolate* isolate = nullptr);
681 template <typename T, typename test_for_number =
682     typename std::enable_if<std::numeric_limits<T>::is_specialized, bool>::type>
683 inline v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context,
684                                            const T& number,
685                                            v8::Isolate* isolate = nullptr);
686 template <typename T>
687 inline v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context,
688                                            const std::vector<T>& vec,
689                                            v8::Isolate* isolate = nullptr);
690 template <typename T>
691 inline v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context,
692                                            const std::set<T>& set,
693                                            v8::Isolate* isolate = nullptr);
694 template <typename T, typename U>
695 inline v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context,
696                                            const std::unordered_map<T, U>& map,
697                                            v8::Isolate* isolate = nullptr);
698 
699 // These macros expects a `Isolate* isolate` and a `Local<Context> context`
700 // to be in the scope.
701 #define READONLY_PROPERTY(obj, name, value)                                    \
702   do {                                                                         \
703     obj->DefineOwnProperty(                                                    \
704            context, FIXED_ONE_BYTE_STRING(isolate, name), value, v8::ReadOnly) \
705         .Check();                                                              \
706   } while (0)
707 
708 #define READONLY_DONT_ENUM_PROPERTY(obj, name, var)                            \
709   do {                                                                         \
710     obj->DefineOwnProperty(                                                    \
711            context,                                                            \
712            OneByteString(isolate, name),                                       \
713            var,                                                                \
714            static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum))    \
715         .Check();                                                              \
716   } while (0)
717 
718 #define READONLY_FALSE_PROPERTY(obj, name)                                     \
719   READONLY_PROPERTY(obj, name, v8::False(isolate))
720 
721 #define READONLY_TRUE_PROPERTY(obj, name)                                      \
722   READONLY_PROPERTY(obj, name, v8::True(isolate))
723 
724 #define READONLY_STRING_PROPERTY(obj, name, str)                               \
725   READONLY_PROPERTY(obj, name, ToV8Value(context, str).ToLocalChecked())
726 
727 // Variation on NODE_DEFINE_CONSTANT that sets a String value.
728 #define NODE_DEFINE_STRING_CONSTANT(target, name, constant)                    \
729   do {                                                                         \
730     v8::Isolate* isolate = target->GetIsolate();                               \
731     v8::Local<v8::String> constant_name =                                      \
732         v8::String::NewFromUtf8(isolate, name).ToLocalChecked();               \
733     v8::Local<v8::String> constant_value =                                     \
734         v8::String::NewFromUtf8(isolate, constant).ToLocalChecked();           \
735     v8::PropertyAttribute constant_attributes =                                \
736         static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete);     \
737     target                                                                     \
738         ->DefineOwnProperty(isolate->GetCurrentContext(),                      \
739                             constant_name,                                     \
740                             constant_value,                                    \
741                             constant_attributes)                               \
742         .Check();                                                              \
743   } while (0)
744 
745 enum class Endianness { LITTLE, BIG };
746 
GetEndianness()747 inline Endianness GetEndianness() {
748   // Constant-folded by the compiler.
749   const union {
750     uint8_t u8[2];
751     uint16_t u16;
752   } u = {{1, 0}};
753   return u.u16 == 1 ? Endianness::LITTLE : Endianness::BIG;
754 }
755 
IsLittleEndian()756 inline bool IsLittleEndian() {
757   return GetEndianness() == Endianness::LITTLE;
758 }
759 
IsBigEndian()760 inline bool IsBigEndian() {
761   return GetEndianness() == Endianness::BIG;
762 }
763 
764 // Round up a to the next highest multiple of b.
765 template <typename T>
RoundUp(T a, T b)766 constexpr T RoundUp(T a, T b) {
767   return a % b != 0 ? a + b - (a % b) : a;
768 }
769 
770 // Align ptr to an `alignment`-bytes boundary.
771 template <typename T, typename U>
AlignUp(T* ptr, U alignment)772 constexpr T* AlignUp(T* ptr, U alignment) {
773   return reinterpret_cast<T*>(
774       RoundUp(reinterpret_cast<uintptr_t>(ptr), alignment));
775 }
776 
777 class SlicedArguments : public MaybeStackBuffer<v8::Local<v8::Value>> {
778  public:
779   inline explicit SlicedArguments(
780       const v8::FunctionCallbackInfo<v8::Value>& args, size_t start = 0);
781 };
782 
783 // Convert a v8::PersistentBase, e.g. v8::Global, to a Local, with an extra
784 // optimization for strong persistent handles.
785 class PersistentToLocal {
786  public:
787   // If persistent.IsWeak() == false, then do not call persistent.Reset()
788   // while the returned Local<T> is still in scope, it will destroy the
789   // reference to the object.
790   template <class TypeName>
Default( v8::Isolate* isolate, const v8::PersistentBase<TypeName>& persistent)791   static inline v8::Local<TypeName> Default(
792       v8::Isolate* isolate,
793       const v8::PersistentBase<TypeName>& persistent) {
794     if (persistent.IsWeak()) {
795       return PersistentToLocal::Weak(isolate, persistent);
796     } else {
797       return PersistentToLocal::Strong(persistent);
798     }
799   }
800 
801   // Unchecked conversion from a non-weak Persistent<T> to Local<T>,
802   // use with care!
803   //
804   // Do not call persistent.Reset() while the returned Local<T> is still in
805   // scope, it will destroy the reference to the object.
806   template <class TypeName>
Strong( const v8::PersistentBase<TypeName>& persistent)807   static inline v8::Local<TypeName> Strong(
808       const v8::PersistentBase<TypeName>& persistent) {
809     DCHECK(!persistent.IsWeak());
810     return *reinterpret_cast<v8::Local<TypeName>*>(
811         const_cast<v8::PersistentBase<TypeName>*>(&persistent));
812   }
813 
814   template <class TypeName>
Weak( v8::Isolate* isolate, const v8::PersistentBase<TypeName>& persistent)815   static inline v8::Local<TypeName> Weak(
816       v8::Isolate* isolate,
817       const v8::PersistentBase<TypeName>& persistent) {
818     return v8::Local<TypeName>::New(isolate, persistent);
819   }
820 };
821 
822 // Can be used as a key for std::unordered_map when lookup performance is more
823 // important than size and the keys are statically used to avoid redundant hash
824 // computations.
825 class FastStringKey {
826  public:
827   constexpr explicit FastStringKey(std::string_view name);
828 
829   struct Hash {
830     constexpr size_t operator()(const FastStringKey& key) const;
831   };
832   constexpr bool operator==(const FastStringKey& other) const;
833 
834   constexpr std::string_view as_string_view() const;
835 
836  private:
837   static constexpr size_t HashImpl(std::string_view str);
838 
839   const std::string_view name_;
840   const size_t cached_hash_;
841 };
842 
843 // Like std::static_pointer_cast but for unique_ptr with the default deleter.
844 template <typename T, typename U>
static_unique_pointer_cast(std::unique_ptr<U>&& ptr)845 std::unique_ptr<T> static_unique_pointer_cast(std::unique_ptr<U>&& ptr) {
846   return std::unique_ptr<T>(static_cast<T*>(ptr.release()));
847 }
848 
849 #define MAYBE_FIELD_PTR(ptr, field) ptr == nullptr ? nullptr : &(ptr->field)
850 
851 // Returns a non-zero code if it fails to open or read the file,
852 // aborts if it fails to close the file.
853 int ReadFileSync(std::string* result, const char* path);
854 
855 v8::Local<v8::FunctionTemplate> NewFunctionTemplate(
856     v8::Isolate* isolate,
857     v8::FunctionCallback callback,
858     v8::Local<v8::Signature> signature = v8::Local<v8::Signature>(),
859     v8::ConstructorBehavior behavior = v8::ConstructorBehavior::kAllow,
860     v8::SideEffectType side_effect = v8::SideEffectType::kHasSideEffect,
861     const v8::CFunction* c_function = nullptr);
862 
863 // Convenience methods for NewFunctionTemplate().
864 void SetMethod(v8::Local<v8::Context> context,
865                v8::Local<v8::Object> that,
866                const char* name,
867                v8::FunctionCallback callback);
868 // Similar to SetProtoMethod but without receiver signature checks.
869 void SetMethod(v8::Isolate* isolate,
870                v8::Local<v8::Template> that,
871                const char* name,
872                v8::FunctionCallback callback);
873 
874 void SetFastMethod(v8::Local<v8::Context> context,
875                    v8::Local<v8::Object> that,
876                    const char* name,
877                    v8::FunctionCallback slow_callback,
878                    const v8::CFunction* c_function);
879 void SetFastMethodNoSideEffect(v8::Local<v8::Context> context,
880                                v8::Local<v8::Object> that,
881                                const char* name,
882                                v8::FunctionCallback slow_callback,
883                                const v8::CFunction* c_function);
884 
885 void SetProtoMethod(v8::Isolate* isolate,
886                     v8::Local<v8::FunctionTemplate> that,
887                     const char* name,
888                     v8::FunctionCallback callback);
889 
890 void SetInstanceMethod(v8::Isolate* isolate,
891                        v8::Local<v8::FunctionTemplate> that,
892                        const char* name,
893                        v8::FunctionCallback callback);
894 
895 // Safe variants denote the function has no side effects.
896 void SetMethodNoSideEffect(v8::Local<v8::Context> context,
897                            v8::Local<v8::Object> that,
898                            const char* name,
899                            v8::FunctionCallback callback);
900 void SetProtoMethodNoSideEffect(v8::Isolate* isolate,
901                                 v8::Local<v8::FunctionTemplate> that,
902                                 const char* name,
903                                 v8::FunctionCallback callback);
904 
905 enum class SetConstructorFunctionFlag {
906   NONE,
907   SET_CLASS_NAME,
908 };
909 
910 void SetConstructorFunction(v8::Local<v8::Context> context,
911                             v8::Local<v8::Object> that,
912                             const char* name,
913                             v8::Local<v8::FunctionTemplate> tmpl,
914                             SetConstructorFunctionFlag flag =
915                                 SetConstructorFunctionFlag::SET_CLASS_NAME);
916 
917 void SetConstructorFunction(v8::Local<v8::Context> context,
918                             v8::Local<v8::Object> that,
919                             v8::Local<v8::String> name,
920                             v8::Local<v8::FunctionTemplate> tmpl,
921                             SetConstructorFunctionFlag flag =
922                                 SetConstructorFunctionFlag::SET_CLASS_NAME);
923 
924 }  // namespace node
925 
926 #endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
927 
928 #endif  // SRC_UTIL_H_
929