constructor.h 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. // Copyright (c) 2018 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 ELECTRON_SHELL_COMMON_GIN_HELPER_CONSTRUCTOR_H_
  5. #define ELECTRON_SHELL_COMMON_GIN_HELPER_CONSTRUCTOR_H_
  6. #include "shell/common/gin_helper/function_template.h"
  7. #include "shell/common/gin_helper/wrappable_base.h"
  8. namespace gin_helper {
  9. namespace internal {
  10. // This set of templates invokes a base::RepeatingCallback by converting the
  11. // Arguments into native types. It relies on the function_template.h to provide
  12. // helper templates.
  13. inline WrappableBase* InvokeFactory(
  14. gin::Arguments* args,
  15. const base::RepeatingCallback<WrappableBase*()>& callback) {
  16. return callback.Run();
  17. }
  18. template <typename P1>
  19. inline WrappableBase* InvokeFactory(
  20. gin::Arguments* args,
  21. const base::RepeatingCallback<WrappableBase*(P1)>& callback) {
  22. typename CallbackParamTraits<P1>::LocalType a1;
  23. if (!gin_helper::GetNextArgument(args, 0, true, &a1))
  24. return nullptr;
  25. return callback.Run(a1);
  26. }
  27. template <typename P1, typename P2>
  28. inline WrappableBase* InvokeFactory(
  29. gin::Arguments* args,
  30. const base::RepeatingCallback<WrappableBase*(P1, P2)>& callback) {
  31. typename CallbackParamTraits<P1>::LocalType a1;
  32. typename CallbackParamTraits<P2>::LocalType a2;
  33. if (!gin_helper::GetNextArgument(args, 0, true, &a1) ||
  34. !gin_helper::GetNextArgument(args, 0, false, &a2))
  35. return nullptr;
  36. return callback.Run(a1, a2);
  37. }
  38. template <typename P1, typename P2, typename P3>
  39. inline WrappableBase* InvokeFactory(
  40. gin::Arguments* args,
  41. const base::RepeatingCallback<WrappableBase*(P1, P2, P3)>& callback) {
  42. typename CallbackParamTraits<P1>::LocalType a1;
  43. typename CallbackParamTraits<P2>::LocalType a2;
  44. typename CallbackParamTraits<P3>::LocalType a3;
  45. if (!gin_helper::GetNextArgument(args, 0, true, &a1) ||
  46. !gin_helper::GetNextArgument(args, 0, false, &a2) ||
  47. !gin_helper::GetNextArgument(args, 0, false, &a3))
  48. return nullptr;
  49. return callback.Run(a1, a2, a3);
  50. }
  51. template <typename P1, typename P2, typename P3, typename P4>
  52. inline WrappableBase* InvokeFactory(
  53. gin::Arguments* args,
  54. const base::RepeatingCallback<WrappableBase*(P1, P2, P3, P4)>& callback) {
  55. typename CallbackParamTraits<P1>::LocalType a1;
  56. typename CallbackParamTraits<P2>::LocalType a2;
  57. typename CallbackParamTraits<P3>::LocalType a3;
  58. typename CallbackParamTraits<P4>::LocalType a4;
  59. if (!gin_helper::GetNextArgument(args, 0, true, &a1) ||
  60. !gin_helper::GetNextArgument(args, 0, false, &a2) ||
  61. !gin_helper::GetNextArgument(args, 0, false, &a3) ||
  62. !gin_helper::GetNextArgument(args, 0, false, &a4))
  63. return nullptr;
  64. return callback.Run(a1, a2, a3, a4);
  65. }
  66. template <typename P1, typename P2, typename P3, typename P4, typename P5>
  67. inline WrappableBase* InvokeFactory(
  68. gin::Arguments* args,
  69. const base::RepeatingCallback<WrappableBase*(P1, P2, P3, P4, P5)>&
  70. callback) {
  71. typename CallbackParamTraits<P1>::LocalType a1;
  72. typename CallbackParamTraits<P2>::LocalType a2;
  73. typename CallbackParamTraits<P3>::LocalType a3;
  74. typename CallbackParamTraits<P4>::LocalType a4;
  75. typename CallbackParamTraits<P5>::LocalType a5;
  76. if (!gin_helper::GetNextArgument(args, 0, true, &a1) ||
  77. !gin_helper::GetNextArgument(args, 0, false, &a2) ||
  78. !gin_helper::GetNextArgument(args, 0, false, &a3) ||
  79. !gin_helper::GetNextArgument(args, 0, false, &a4) ||
  80. !gin_helper::GetNextArgument(args, 0, false, &a5))
  81. return nullptr;
  82. return callback.Run(a1, a2, a3, a4, a5);
  83. }
  84. template <typename P1,
  85. typename P2,
  86. typename P3,
  87. typename P4,
  88. typename P5,
  89. typename P6>
  90. inline WrappableBase* InvokeFactory(
  91. gin::Arguments* args,
  92. const base::RepeatingCallback<WrappableBase*(P1, P2, P3, P4, P5, P6)>&
  93. callback) {
  94. typename CallbackParamTraits<P1>::LocalType a1;
  95. typename CallbackParamTraits<P2>::LocalType a2;
  96. typename CallbackParamTraits<P3>::LocalType a3;
  97. typename CallbackParamTraits<P4>::LocalType a4;
  98. typename CallbackParamTraits<P5>::LocalType a5;
  99. typename CallbackParamTraits<P6>::LocalType a6;
  100. if (!gin_helper::GetNextArgument(args, 0, true, &a1) ||
  101. !gin_helper::GetNextArgument(args, 0, false, &a2) ||
  102. !gin_helper::GetNextArgument(args, 0, false, &a3) ||
  103. !gin_helper::GetNextArgument(args, 0, false, &a4) ||
  104. !gin_helper::GetNextArgument(args, 0, false, &a5) ||
  105. !gin_helper::GetNextArgument(args, 0, false, &a6))
  106. return nullptr;
  107. return callback.Run(a1, a2, a3, a4, a5, a6);
  108. }
  109. template <typename Sig>
  110. void InvokeNew(const base::RepeatingCallback<Sig>& factory,
  111. v8::Isolate* isolate,
  112. gin_helper::Arguments* args) {
  113. if (!args->IsConstructCall()) {
  114. args->ThrowError("Requires constructor call");
  115. return;
  116. }
  117. WrappableBase* object;
  118. {
  119. // Don't continue if the constructor throws an exception.
  120. v8::TryCatch try_catch(isolate);
  121. object = internal::InvokeFactory(args, factory);
  122. if (try_catch.HasCaught()) {
  123. try_catch.ReThrow();
  124. return;
  125. }
  126. }
  127. if (!object)
  128. args->ThrowError();
  129. return;
  130. }
  131. } // namespace internal
  132. // Create a FunctionTemplate that can be "new"ed in JavaScript.
  133. // It is user's responsibility to ensure this function is called for one type
  134. // only ONCE in the program's whole lifetime, otherwise we would have memory
  135. // leak.
  136. template <typename T, typename Sig>
  137. v8::Local<v8::Function> CreateConstructor(
  138. v8::Isolate* isolate,
  139. const base::RepeatingCallback<Sig>& func) {
  140. #ifndef NDEBUG
  141. static bool called = false;
  142. CHECK(!called) << "CreateConstructor can only be called for one type once";
  143. called = true;
  144. #endif
  145. v8::Local<v8::FunctionTemplate> templ = gin_helper::CreateFunctionTemplate(
  146. isolate, base::BindRepeating(&internal::InvokeNew<Sig>, func));
  147. templ->InstanceTemplate()->SetInternalFieldCount(1);
  148. T::BuildPrototype(isolate, templ);
  149. return templ->GetFunction(isolate->GetCurrentContext()).ToLocalChecked();
  150. }
  151. } // namespace gin_helper
  152. #endif // ELECTRON_SHELL_COMMON_GIN_HELPER_CONSTRUCTOR_H_