dictionary.h 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. // Copyright (c) 2019 GitHub, Inc.
  2. // Use of this source code is governed by the MIT license that can be
  3. // found in the LICENSE file.
  4. #ifndef SHELL_COMMON_GIN_HELPER_DICTIONARY_H_
  5. #define SHELL_COMMON_GIN_HELPER_DICTIONARY_H_
  6. #include <type_traits>
  7. #include "gin/dictionary.h"
  8. #include "shell/common/gin_converters/std_converter.h"
  9. #include "shell/common/gin_helper/function_template.h"
  10. namespace gin_helper {
  11. // Adds a few more extends methods to gin::Dictionary.
  12. //
  13. // Note that as the destructor of gin::Dictionary is not virtual, and we want to
  14. // convert between 2 types, we must not add any member.
  15. class Dictionary : public gin::Dictionary {
  16. public:
  17. Dictionary() : gin::Dictionary(nullptr) {}
  18. Dictionary(v8::Isolate* isolate, v8::Local<v8::Object> object)
  19. : gin::Dictionary(isolate, object) {}
  20. // Allow implicitly converting from gin::Dictionary, as it is absolutely
  21. // safe in this case.
  22. Dictionary(const gin::Dictionary& dict) // NOLINT(runtime/explicit)
  23. : gin::Dictionary(dict) {}
  24. // Differences from the Get method in gin::Dictionary:
  25. // 1. This is a const method;
  26. // 2. It checks whether the key exists before reading;
  27. // 3. It accepts arbitrary type of key.
  28. template <typename K, typename V>
  29. bool Get(const K& key, V* out) const {
  30. // Check for existence before getting, otherwise this method will always
  31. // returns true when T == v8::Local<v8::Value>.
  32. v8::Local<v8::Context> context = isolate()->GetCurrentContext();
  33. v8::Local<v8::Value> v8_key = gin::ConvertToV8(isolate(), key);
  34. v8::Local<v8::Value> value;
  35. v8::Maybe<bool> result = GetHandle()->Has(context, v8_key);
  36. if (result.IsJust() && result.FromJust() &&
  37. GetHandle()->Get(context, v8_key).ToLocal(&value))
  38. return gin::ConvertFromV8(isolate(), value, out);
  39. return false;
  40. }
  41. // Differences from the Set method in gin::Dictionary:
  42. // 1. It accepts arbitrary type of key.
  43. template <typename K, typename V>
  44. bool Set(const K& key, const V& val) {
  45. v8::Local<v8::Value> v8_value;
  46. if (!gin::TryConvertToV8(isolate(), val, &v8_value))
  47. return false;
  48. v8::Maybe<bool> result =
  49. GetHandle()->Set(isolate()->GetCurrentContext(),
  50. gin::ConvertToV8(isolate(), key), v8_value);
  51. return !result.IsNothing() && result.FromJust();
  52. }
  53. template <typename T>
  54. bool GetHidden(base::StringPiece key, T* out) const {
  55. v8::Local<v8::Context> context = isolate()->GetCurrentContext();
  56. v8::Local<v8::Private> privateKey =
  57. v8::Private::ForApi(isolate(), gin::StringToV8(isolate(), key));
  58. v8::Local<v8::Value> value;
  59. v8::Maybe<bool> result = GetHandle()->HasPrivate(context, privateKey);
  60. if (result.IsJust() && result.FromJust() &&
  61. GetHandle()->GetPrivate(context, privateKey).ToLocal(&value))
  62. return gin::ConvertFromV8(isolate(), value, out);
  63. return false;
  64. }
  65. template <typename T>
  66. bool SetHidden(base::StringPiece key, T val) {
  67. v8::Local<v8::Value> v8_value;
  68. if (!gin::TryConvertToV8(isolate(), val, &v8_value))
  69. return false;
  70. v8::Local<v8::Context> context = isolate()->GetCurrentContext();
  71. v8::Local<v8::Private> privateKey =
  72. v8::Private::ForApi(isolate(), gin::StringToV8(isolate(), key));
  73. v8::Maybe<bool> result =
  74. GetHandle()->SetPrivate(context, privateKey, v8_value);
  75. return !result.IsNothing() && result.FromJust();
  76. }
  77. template <typename T>
  78. bool SetMethod(base::StringPiece key, const T& callback) {
  79. auto context = isolate()->GetCurrentContext();
  80. auto templ = CallbackTraits<T>::CreateTemplate(isolate(), callback);
  81. return GetHandle()
  82. ->Set(context, gin::StringToV8(isolate(), key),
  83. templ->GetFunction(context).ToLocalChecked())
  84. .ToChecked();
  85. }
  86. template <typename T>
  87. bool SetReadOnly(base::StringPiece key, const T& val) {
  88. v8::Local<v8::Value> v8_value;
  89. if (!gin::TryConvertToV8(isolate(), val, &v8_value))
  90. return false;
  91. v8::Maybe<bool> result = GetHandle()->DefineOwnProperty(
  92. isolate()->GetCurrentContext(), gin::StringToV8(isolate(), key),
  93. v8_value, v8::ReadOnly);
  94. return !result.IsNothing() && result.FromJust();
  95. }
  96. // Note: If we plan to add more Set methods, consider adding an option instead
  97. // of copying code.
  98. template <typename T>
  99. bool SetReadOnlyNonConfigurable(base::StringPiece key, T val) {
  100. v8::Local<v8::Value> v8_value;
  101. if (!gin::TryConvertToV8(isolate(), val, &v8_value))
  102. return false;
  103. v8::Maybe<bool> result = GetHandle()->DefineOwnProperty(
  104. isolate()->GetCurrentContext(), gin::StringToV8(isolate(), key),
  105. v8_value,
  106. static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete));
  107. return !result.IsNothing() && result.FromJust();
  108. }
  109. bool Has(base::StringPiece key) const {
  110. v8::Maybe<bool> result = GetHandle()->Has(isolate()->GetCurrentContext(),
  111. gin::StringToV8(isolate(), key));
  112. return !result.IsNothing() && result.FromJust();
  113. }
  114. bool Delete(base::StringPiece key) {
  115. v8::Maybe<bool> result = GetHandle()->Delete(
  116. isolate()->GetCurrentContext(), gin::StringToV8(isolate(), key));
  117. return !result.IsNothing() && result.FromJust();
  118. }
  119. bool IsEmpty() const { return isolate() == nullptr || GetHandle().IsEmpty(); }
  120. v8::Local<v8::Object> GetHandle() const {
  121. return gin::ConvertToV8(isolate(),
  122. *static_cast<const gin::Dictionary*>(this))
  123. .As<v8::Object>();
  124. }
  125. private:
  126. // DO NOT ADD ANY DATA MEMBER.
  127. };
  128. } // namespace gin_helper
  129. namespace gin {
  130. template <>
  131. struct Converter<gin_helper::Dictionary> {
  132. static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
  133. gin_helper::Dictionary val) {
  134. return val.GetHandle();
  135. }
  136. static bool FromV8(v8::Isolate* isolate,
  137. v8::Local<v8::Value> val,
  138. gin_helper::Dictionary* out) {
  139. gin::Dictionary gdict(isolate);
  140. if (!ConvertFromV8(isolate, val, &gdict))
  141. return false;
  142. *out = gin_helper::Dictionary(gdict);
  143. return true;
  144. }
  145. };
  146. } // namespace gin
  147. #endif // SHELL_COMMON_GIN_HELPER_DICTIONARY_H_