constructor.h 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  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 SHELL_COMMON_GIN_HELPER_CONSTRUCTOR_H_
  5. #define 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::Callback by converting the Arguments
  11. // into native types. It relies on the function_template.h to provide helper
  12. // templates.
  13. inline WrappableBase* InvokeFactory(
  14. gin::Arguments* args,
  15. const base::Callback<WrappableBase*()>& callback) {
  16. return callback.Run();
  17. }
  18. template <typename P1>
  19. inline WrappableBase* InvokeFactory(
  20. gin::Arguments* args,
  21. const base::Callback<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::Callback<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::Callback<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::Callback<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::Callback<WrappableBase*(P1, P2, P3, P4, P5)>& callback) {
  70. typename CallbackParamTraits<P1>::LocalType a1;
  71. typename CallbackParamTraits<P2>::LocalType a2;
  72. typename CallbackParamTraits<P3>::LocalType a3;
  73. typename CallbackParamTraits<P4>::LocalType a4;
  74. typename CallbackParamTraits<P5>::LocalType a5;
  75. if (!gin_helper::GetNextArgument(args, 0, true, &a1) ||
  76. !gin_helper::GetNextArgument(args, 0, false, &a2) ||
  77. !gin_helper::GetNextArgument(args, 0, false, &a3) ||
  78. !gin_helper::GetNextArgument(args, 0, false, &a4) ||
  79. !gin_helper::GetNextArgument(args, 0, false, &a5))
  80. return nullptr;
  81. return callback.Run(a1, a2, a3, a4, a5);
  82. }
  83. template <typename P1,
  84. typename P2,
  85. typename P3,
  86. typename P4,
  87. typename P5,
  88. typename P6>
  89. inline WrappableBase* InvokeFactory(
  90. gin::Arguments* args,
  91. const base::Callback<WrappableBase*(P1, P2, P3, P4, P5, P6)>& callback) {
  92. typename CallbackParamTraits<P1>::LocalType a1;
  93. typename CallbackParamTraits<P2>::LocalType a2;
  94. typename CallbackParamTraits<P3>::LocalType a3;
  95. typename CallbackParamTraits<P4>::LocalType a4;
  96. typename CallbackParamTraits<P5>::LocalType a5;
  97. typename CallbackParamTraits<P6>::LocalType a6;
  98. if (!gin_helper::GetNextArgument(args, 0, true, &a1) ||
  99. !gin_helper::GetNextArgument(args, 0, false, &a2) ||
  100. !gin_helper::GetNextArgument(args, 0, false, &a3) ||
  101. !gin_helper::GetNextArgument(args, 0, false, &a4) ||
  102. !gin_helper::GetNextArgument(args, 0, false, &a5) ||
  103. !gin_helper::GetNextArgument(args, 0, false, &a6))
  104. return nullptr;
  105. return callback.Run(a1, a2, a3, a4, a5, a6);
  106. }
  107. template <typename Sig>
  108. void InvokeNew(const base::Callback<Sig>& factory,
  109. v8::Isolate* isolate,
  110. gin_helper::Arguments* args) {
  111. if (!args->IsConstructCall()) {
  112. args->ThrowError("Requires constructor call");
  113. return;
  114. }
  115. WrappableBase* object;
  116. {
  117. // Don't continue if the constructor throws an exception.
  118. v8::TryCatch try_catch(isolate);
  119. object = internal::InvokeFactory(args, factory);
  120. if (try_catch.HasCaught()) {
  121. try_catch.ReThrow();
  122. return;
  123. }
  124. }
  125. if (!object)
  126. args->ThrowError();
  127. return;
  128. }
  129. } // namespace internal
  130. // Create a FunctionTemplate that can be "new"ed in JavaScript.
  131. // It is user's responsibility to ensure this function is called for one type
  132. // only ONCE in the program's whole lifetime, otherwise we would have memory
  133. // leak.
  134. template <typename T, typename Sig>
  135. v8::Local<v8::Function> CreateConstructor(
  136. v8::Isolate* isolate,
  137. const base::RepeatingCallback<Sig>& func) {
  138. #ifndef NDEBUG
  139. static bool called = false;
  140. CHECK(!called) << "CreateConstructor can only be called for one type once";
  141. called = true;
  142. #endif
  143. v8::Local<v8::FunctionTemplate> templ = CreateFunctionTemplate(
  144. isolate, base::BindRepeating(&internal::InvokeNew<Sig>, func));
  145. templ->InstanceTemplate()->SetInternalFieldCount(1);
  146. T::BuildPrototype(isolate, templ);
  147. return templ->GetFunction(isolate->GetCurrentContext()).ToLocalChecked();
  148. }
  149. } // namespace gin_helper
  150. #endif // SHELL_COMMON_GIN_HELPER_CONSTRUCTOR_H_