V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
v8-util.h
1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef V8_UTIL_H_
6 #define V8_UTIL_H_
7 
8 #include "v8.h" // NOLINT(build/include)
9 #include <assert.h>
10 #include <map>
11 #include <vector>
12 
20 namespace v8 {
21 
22 typedef uintptr_t PersistentContainerValue;
23 static const uintptr_t kPersistentContainerNotFound = 0;
24 enum PersistentContainerCallbackType {
25  kNotWeak,
26  // These correspond to v8::WeakCallbackType
27  kWeakWithParameter,
28  kWeakWithInternalFields
29 };
30 
37 template<typename K, typename V>
38 class StdMapTraits {
39  public:
40  // STL map & related:
41  typedef std::map<K, PersistentContainerValue> Impl;
42  typedef typename Impl::iterator Iterator;
43 
44  static bool Empty(Impl* impl) { return impl->empty(); }
45  static size_t Size(Impl* impl) { return impl->size(); }
46  static void Swap(Impl& a, Impl& b) { std::swap(a, b); } // NOLINT
47  static Iterator Begin(Impl* impl) { return impl->begin(); }
48  static Iterator End(Impl* impl) { return impl->end(); }
49  static K Key(Iterator it) { return it->first; }
50  static PersistentContainerValue Value(Iterator it) { return it->second; }
51  static PersistentContainerValue Set(Impl* impl, K key,
53  std::pair<Iterator, bool> res = impl->insert(std::make_pair(key, value));
54  PersistentContainerValue old_value = kPersistentContainerNotFound;
55  if (!res.second) {
56  old_value = res.first->second;
57  res.first->second = value;
58  }
59  return old_value;
60  }
61  static PersistentContainerValue Get(Impl* impl, K key) {
62  Iterator it = impl->find(key);
63  if (it == impl->end()) return kPersistentContainerNotFound;
64  return it->second;
65  }
66  static PersistentContainerValue Remove(Impl* impl, K key) {
67  Iterator it = impl->find(key);
68  if (it == impl->end()) return kPersistentContainerNotFound;
69  PersistentContainerValue value = it->second;
70  impl->erase(it);
71  return value;
72  }
73 };
74 
75 
84 template<typename K, typename V>
86  public:
87  // Weak callback & friends:
88  static const PersistentContainerCallbackType kCallbackType = kNotWeak;
90  MapType;
91  typedef void WeakCallbackDataType;
92 
93  static WeakCallbackDataType* WeakCallbackParameter(
94  MapType* map, const K& key, Local<V> value) {
95  return nullptr;
96  }
97  static MapType* MapFromWeakCallbackInfo(
99  return nullptr;
100  }
101  static K KeyFromWeakCallbackInfo(
103  return K();
104  }
105  static void DisposeCallbackData(WeakCallbackDataType* data) { }
106  static void Dispose(Isolate* isolate, Global<V> value, K key) {}
107 };
108 
109 
110 template <typename K, typename V>
111 class DefaultGlobalMapTraits : public StdMapTraits<K, V> {
112  private:
113  template <typename T>
114  struct RemovePointer;
115 
116  public:
117  // Weak callback & friends:
118  static const PersistentContainerCallbackType kCallbackType = kNotWeak;
120  typedef void WeakCallbackDataType;
121 
122  static WeakCallbackDataType* WeakCallbackParameter(MapType* map, const K& key,
123  Local<V> value) {
124  return nullptr;
125  }
126  static MapType* MapFromWeakCallbackInfo(
128  return nullptr;
129  }
130  static K KeyFromWeakCallbackInfo(
132  return K();
133  }
134  static void DisposeCallbackData(WeakCallbackDataType* data) {}
135  static void OnWeakCallback(
137  static void Dispose(Isolate* isolate, Global<V> value, K key) {}
138  // This is a second pass callback, so SetSecondPassCallback cannot be called.
139  static void DisposeWeak(const WeakCallbackInfo<WeakCallbackDataType>& data) {}
140 
141  private:
142  template <typename T>
143  struct RemovePointer<T*> {
144  typedef T Type;
145  };
146 };
147 
148 
159 template <typename K, typename V, typename Traits>
161  public:
162  Isolate* GetIsolate() { return isolate_; }
163 
167  size_t Size() { return Traits::Size(&impl_); }
168 
172  bool IsWeak() { return Traits::kCallbackType != kNotWeak; }
173 
177  Local<V> Get(const K& key) {
178  return Local<V>::New(isolate_, FromVal(Traits::Get(&impl_, key)));
179  }
180 
184  bool Contains(const K& key) {
185  return Traits::Get(&impl_, key) != kPersistentContainerNotFound;
186  }
187 
192  bool SetReturnValue(const K& key,
193  ReturnValue<Value> returnValue) {
194  return SetReturnValueFromVal(&returnValue, Traits::Get(&impl_, key));
195  }
196 
202  assert(Contains(key));
203  V8::RegisterExternallyReferencedObject(
204  reinterpret_cast<internal::Address*>(FromVal(Traits::Get(&impl_, key))),
205  reinterpret_cast<internal::Isolate*>(GetIsolate()));
206  }
207 
211  Global<V> Remove(const K& key) {
212  return Release(Traits::Remove(&impl_, key)).Pass();
213  }
214 
219  void Clear() {
220  typedef typename Traits::Iterator It;
221  HandleScope handle_scope(isolate_);
222  // TODO(dcarney): figure out if this swap and loop is necessary.
223  while (!Traits::Empty(&impl_)) {
224  typename Traits::Impl impl;
225  Traits::Swap(impl_, impl);
226  for (It i = Traits::Begin(&impl); i != Traits::End(&impl); ++i) {
227  Traits::Dispose(isolate_, Release(Traits::Value(i)).Pass(),
228  Traits::Key(i));
229  }
230  }
231  }
232 
238  public:
239  PersistentValueReference() : value_(kPersistentContainerNotFound) { }
241  : value_(other.value_) { }
242 
243  Local<V> NewLocal(Isolate* isolate) const {
244  return Local<V>::New(isolate, FromVal(value_));
245  }
246  bool IsEmpty() const {
247  return value_ == kPersistentContainerNotFound;
248  }
249  template<typename T>
250  bool SetReturnValue(ReturnValue<T> returnValue) {
251  return SetReturnValueFromVal(&returnValue, value_);
252  }
253  void Reset() {
254  value_ = kPersistentContainerNotFound;
255  }
256  void operator=(const PersistentValueReference& other) {
257  value_ = other.value_;
258  }
259 
260  private:
261  friend class PersistentValueMapBase;
262  friend class PersistentValueMap<K, V, Traits>;
263  friend class GlobalValueMap<K, V, Traits>;
264 
266  : value_(value) { }
267 
268  void operator=(PersistentContainerValue value) {
269  value_ = value;
270  }
271 
273  };
274 
286  return PersistentValueReference(Traits::Get(&impl_, key));
287  }
288 
289  protected:
290  explicit PersistentValueMapBase(Isolate* isolate) : isolate_(isolate) {}
291 
292  ~PersistentValueMapBase() { Clear(); }
293 
294  Isolate* isolate() { return isolate_; }
295  typename Traits::Impl* impl() { return &impl_; }
296 
297  static V* FromVal(PersistentContainerValue v) {
298  return reinterpret_cast<V*>(v);
299  }
300 
301  static PersistentContainerValue ClearAndLeak(Global<V>* persistent) {
302  V* v = persistent->val_;
303  persistent->val_ = nullptr;
304  return reinterpret_cast<PersistentContainerValue>(v);
305  }
306 
307  static PersistentContainerValue Leak(Global<V>* persistent) {
308  return reinterpret_cast<PersistentContainerValue>(persistent->val_);
309  }
310 
317  Global<V> p;
318  p.val_ = FromVal(v);
319  if (Traits::kCallbackType != kNotWeak && p.IsWeak()) {
320  Traits::DisposeCallbackData(
321  p.template ClearWeak<typename Traits::WeakCallbackDataType>());
322  }
323  return p.Pass();
324  }
325 
326  void RemoveWeak(const K& key) {
327  Global<V> p;
328  p.val_ = FromVal(Traits::Remove(&impl_, key));
329  p.Reset();
330  }
331 
332  private:
333  PersistentValueMapBase(PersistentValueMapBase&);
334  void operator=(PersistentValueMapBase&);
335 
336  static bool SetReturnValueFromVal(ReturnValue<Value>* returnValue,
337  PersistentContainerValue value) {
338  bool hasValue = value != kPersistentContainerNotFound;
339  if (hasValue) {
340  returnValue->SetInternal(
341  *reinterpret_cast<internal::Address*>(FromVal(value)));
342  }
343  return hasValue;
344  }
345 
346  Isolate* isolate_;
347  typename Traits::Impl impl_;
348 };
349 
350 
351 template <typename K, typename V, typename Traits>
352 class PersistentValueMap : public PersistentValueMapBase<K, V, Traits> {
353  public:
354  explicit PersistentValueMap(Isolate* isolate)
356 
357  typedef
360 
366  Global<V> Set(const K& key, Local<V> value) {
367  Global<V> persistent(this->isolate(), value);
368  return SetUnique(key, &persistent);
369  }
370 
374  Global<V> Set(const K& key, Global<V> value) {
375  return SetUnique(key, &value);
376  }
377 
382  Global<V> SetUnique(const K& key, Global<V>* persistent) {
383  if (Traits::kCallbackType != kNotWeak) {
384  WeakCallbackType callback_type =
385  Traits::kCallbackType == kWeakWithInternalFields
386  ? WeakCallbackType::kInternalFields
387  : WeakCallbackType::kParameter;
388  Local<V> value(Local<V>::New(this->isolate(), *persistent));
389  persistent->template SetWeak<typename Traits::WeakCallbackDataType>(
390  Traits::WeakCallbackParameter(this, key, value), WeakCallback,
391  callback_type);
392  }
393  PersistentContainerValue old_value =
394  Traits::Set(this->impl(), key, this->ClearAndLeak(persistent));
395  return this->Release(old_value).Pass();
396  }
397 
402  Global<V> Set(const K& key, Global<V> value,
403  PersistentValueReference* reference) {
404  *reference = this->Leak(&value);
405  return SetUnique(key, &value);
406  }
407 
408  private:
409  static void WeakCallback(
411  if (Traits::kCallbackType != kNotWeak) {
412  PersistentValueMap<K, V, Traits>* persistentValueMap =
413  Traits::MapFromWeakCallbackInfo(data);
414  K key = Traits::KeyFromWeakCallbackInfo(data);
415  Traits::Dispose(data.GetIsolate(),
416  persistentValueMap->Remove(key).Pass(), key);
417  Traits::DisposeCallbackData(data.GetParameter());
418  }
419  }
420 };
421 
422 
423 template <typename K, typename V, typename Traits>
424 class GlobalValueMap : public PersistentValueMapBase<K, V, Traits> {
425  public:
426  explicit GlobalValueMap(Isolate* isolate)
428 
429  typedef
432 
438  Global<V> Set(const K& key, Local<V> value) {
439  Global<V> persistent(this->isolate(), value);
440  return SetUnique(key, &persistent);
441  }
442 
446  Global<V> Set(const K& key, Global<V> value) {
447  return SetUnique(key, &value);
448  }
449 
454  Global<V> SetUnique(const K& key, Global<V>* persistent) {
455  if (Traits::kCallbackType != kNotWeak) {
456  WeakCallbackType callback_type =
457  Traits::kCallbackType == kWeakWithInternalFields
458  ? WeakCallbackType::kInternalFields
459  : WeakCallbackType::kParameter;
460  Local<V> value(Local<V>::New(this->isolate(), *persistent));
461  persistent->template SetWeak<typename Traits::WeakCallbackDataType>(
462  Traits::WeakCallbackParameter(this, key, value), OnWeakCallback,
463  callback_type);
464  }
465  PersistentContainerValue old_value =
466  Traits::Set(this->impl(), key, this->ClearAndLeak(persistent));
467  return this->Release(old_value).Pass();
468  }
469 
474  Global<V> Set(const K& key, Global<V> value,
475  PersistentValueReference* reference) {
476  *reference = this->Leak(&value);
477  return SetUnique(key, &value);
478  }
479 
480  private:
481  static void OnWeakCallback(
483  if (Traits::kCallbackType != kNotWeak) {
484  auto map = Traits::MapFromWeakCallbackInfo(data);
485  K key = Traits::KeyFromWeakCallbackInfo(data);
486  map->RemoveWeak(key);
487  Traits::OnWeakCallback(data);
488  data.SetSecondPassCallback(SecondWeakCallback);
489  }
490  }
491 
492  static void SecondWeakCallback(
493  const WeakCallbackInfo<typename Traits::WeakCallbackDataType>& data) {
494  Traits::DisposeWeak(data);
495  }
496 };
497 
498 
506 template<typename K, typename V,
507  typename Traits = DefaultPersistentValueMapTraits<K, V> >
508 class StdPersistentValueMap : public PersistentValueMap<K, V, Traits> {
509  public:
510  explicit StdPersistentValueMap(Isolate* isolate)
512 };
513 
514 
522 template <typename K, typename V,
523  typename Traits = DefaultGlobalMapTraits<K, V> >
524 class StdGlobalValueMap : public GlobalValueMap<K, V, Traits> {
525  public:
526  explicit StdGlobalValueMap(Isolate* isolate)
527  : GlobalValueMap<K, V, Traits>(isolate) {}
528 };
529 
530 
532  public:
533  typedef std::vector<PersistentContainerValue> Impl;
534 
535  static void Append(Impl* impl, PersistentContainerValue value) {
536  impl->push_back(value);
537  }
538  static bool IsEmpty(const Impl* impl) {
539  return impl->empty();
540  }
541  static size_t Size(const Impl* impl) {
542  return impl->size();
543  }
544  static PersistentContainerValue Get(const Impl* impl, size_t i) {
545  return (i < impl->size()) ? impl->at(i) : kPersistentContainerNotFound;
546  }
547  static void ReserveCapacity(Impl* impl, size_t capacity) {
548  impl->reserve(capacity);
549  }
550  static void Clear(Impl* impl) {
551  impl->clear();
552  }
553 };
554 
555 
566 template<typename V, typename Traits = DefaultPersistentValueVectorTraits>
568  public:
569  explicit PersistentValueVector(Isolate* isolate) : isolate_(isolate) { }
570 
572  Clear();
573  }
574 
578  void Append(Local<V> value) {
579  Global<V> persistent(isolate_, value);
580  Traits::Append(&impl_, ClearAndLeak(&persistent));
581  }
582 
586  void Append(Global<V> persistent) {
587  Traits::Append(&impl_, ClearAndLeak(&persistent));
588  }
589 
593  bool IsEmpty() const {
594  return Traits::IsEmpty(&impl_);
595  }
596 
600  size_t Size() const {
601  return Traits::Size(&impl_);
602  }
603 
607  Local<V> Get(size_t index) const {
608  return Local<V>::New(isolate_, FromVal(Traits::Get(&impl_, index)));
609  }
610 
614  void Clear() {
615  size_t length = Traits::Size(&impl_);
616  for (size_t i = 0; i < length; i++) {
617  Global<V> p;
618  p.val_ = FromVal(Traits::Get(&impl_, i));
619  }
620  Traits::Clear(&impl_);
621  }
622 
627  void ReserveCapacity(size_t capacity) {
628  Traits::ReserveCapacity(&impl_, capacity);
629  }
630 
631  private:
632  static PersistentContainerValue ClearAndLeak(Global<V>* persistent) {
633  V* v = persistent->val_;
634  persistent->val_ = nullptr;
635  return reinterpret_cast<PersistentContainerValue>(v);
636  }
637 
638  static V* FromVal(PersistentContainerValue v) {
639  return reinterpret_cast<V*>(v);
640  }
641 
642  Isolate* isolate_;
643  typename Traits::Impl impl_;
644 };
645 
646 } // namespace v8
647 
648 #endif // V8_UTIL_H
Global< V > Set(const K &key, Global< V > value)
Definition: v8-util.h:446
size_t Size() const
Definition: v8-util.h:600
bool IsEmpty() const
Definition: v8-util.h:593
Definition: v8.h:94
Global< V > Set(const K &key, Global< V > value, PersistentValueReference *reference)
Definition: v8-util.h:402
Global< V > SetUnique(const K &key, Global< V > *persistent)
Definition: v8-util.h:382
V8_INLINE bool IsWeak() const
Definition: v8.h:9460
Global< V > Set(const K &key, Global< V > value)
Definition: v8-util.h:374
static Global< V > Release(PersistentContainerValue v)
Definition: v8-util.h:316
Definition: v8.h:2119
Definition: v8.h:85
void ReserveCapacity(size_t capacity)
Definition: v8-util.h:627
PersistentValueReference GetReference(const K &key)
Definition: v8-util.h:285
Local< V > Get(const K &key)
Definition: v8-util.h:177
Definition: libplatform.h:13
Global< V > Set(const K &key, Local< V > value)
Definition: v8-util.h:438
bool SetReturnValue(const K &key, ReturnValue< Value > returnValue)
Definition: v8-util.h:192
void RegisterExternallyReferencedObject(K &key)
Definition: v8-util.h:201
Definition: v8.h:3740
Local< V > Get(size_t index) const
Definition: v8-util.h:607
Global< V > Set(const K &key, Local< V > value)
Definition: v8-util.h:366
static V8_INLINE Local< T > New(Isolate *isolate, Local< T > that)
Definition: v8.h:9365
Global< V > Set(const K &key, Global< V > value, PersistentValueReference *reference)
Definition: v8-util.h:474
void Append(Local< V > value)
Definition: v8-util.h:578
Global< V > Remove(const K &key)
Definition: v8-util.h:211
Global< V > SetUnique(const K &key, Global< V > *persistent)
Definition: v8-util.h:454
V8_INLINE void Reset()
Definition: v8.h:9469
Global Pass()
Definition: v8.h:802
bool Contains(const K &key)
Definition: v8-util.h:184
void Append(Global< V > persistent)
Definition: v8-util.h:586