SampleCxxModule.cpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. /*
  2. * Copyright (c) Facebook, Inc. and its affiliates.
  3. *
  4. * This source code is licensed under the MIT license found in the
  5. * LICENSE file in the root directory of this source tree.
  6. */
  7. #include "SampleCxxModule.h"
  8. #include <cxxreact/JsArgumentHelpers.h>
  9. #include <glog/logging.h>
  10. #include <memory>
  11. #include <thread>
  12. using namespace folly;
  13. namespace facebook {
  14. namespace xplat {
  15. namespace samples {
  16. std::string Sample::hello() {
  17. LOG(WARNING) << "glog: hello, world";
  18. return "hello";
  19. }
  20. double Sample::add(double a, double b) {
  21. return a + b;
  22. }
  23. std::string Sample::concat(const std::string &a, const std::string &b) {
  24. return a + b;
  25. }
  26. std::string Sample::repeat(int count, const std::string &str) {
  27. std::string ret;
  28. for (int i = 0; i < count; i++) {
  29. ret += str;
  30. }
  31. return ret;
  32. }
  33. void Sample::save(std::map<std::string, std::string> dict) {
  34. state_ = std::move(dict);
  35. }
  36. std::map<std::string, std::string> Sample::load() {
  37. return state_;
  38. }
  39. void Sample::except() {
  40. // TODO mhorowitz #7128529: There's no way to automatically test this
  41. // right now.
  42. // throw std::runtime_error("oops");
  43. }
  44. void Sample::call_later(int msec, std::function<void()> f) {
  45. std::thread t([=] {
  46. std::this_thread::sleep_for(std::chrono::milliseconds(msec));
  47. f();
  48. });
  49. t.detach();
  50. }
  51. double Sample::twice(double n) {
  52. return n * 2;
  53. }
  54. SampleCxxModule::SampleCxxModule(std::unique_ptr<Sample> sample)
  55. : sample_(std::move(sample)) {}
  56. std::string SampleCxxModule::getName() {
  57. return "Sample";
  58. }
  59. auto SampleCxxModule::getConstants() -> std::map<std::string, folly::dynamic> {
  60. return {
  61. {"one", 1},
  62. {"two", 2},
  63. {"animal", "fox"},
  64. };
  65. }
  66. auto SampleCxxModule::getMethods() -> std::vector<Method> {
  67. return {
  68. Method("hello", [this] { sample_->hello(); }),
  69. Method(
  70. "add",
  71. [this](dynamic args, Callback cb) {
  72. LOG(WARNING) << "Sample: add => "
  73. << sample_->add(
  74. jsArgAsDouble(args, 0), jsArgAsDouble(args, 1));
  75. cb({sample_->add(jsArgAsDouble(args, 0), jsArgAsDouble(args, 1))});
  76. }),
  77. Method(
  78. "concat",
  79. [this](dynamic args, Callback cb) {
  80. cb({sample_->concat(
  81. jsArgAsString(args, 0), jsArgAsString(args, 1))});
  82. }),
  83. Method(
  84. "repeat",
  85. [this](dynamic args, Callback cb) {
  86. cb({sample_->repeat(
  87. (int)jsArgAsInt(args, 0), jsArgAsString(args, 1))});
  88. }),
  89. Method("save", this, &SampleCxxModule::save),
  90. Method("load", this, &SampleCxxModule::load),
  91. Method(
  92. "call_later",
  93. [this](dynamic args, Callback cb) {
  94. sample_->call_later((int)jsArgAsInt(args, 0), [cb] { cb({}); });
  95. }),
  96. Method("except", [this] { sample_->except(); }),
  97. Method(
  98. "twice",
  99. [this](dynamic args) -> dynamic {
  100. return sample_->twice(jsArgAsDouble(args, 0));
  101. },
  102. SyncTag),
  103. Method(
  104. "syncHello",
  105. [this]() -> dynamic {
  106. sample_->hello();
  107. return nullptr;
  108. },
  109. SyncTag),
  110. Method(
  111. "addIfPositiveAsPromise",
  112. [](dynamic args, Callback cb, Callback cbError) {
  113. auto a = jsArgAsDouble(args, 0);
  114. auto b = jsArgAsDouble(args, 1);
  115. if (a < 0 || b < 0) {
  116. cbError({"Negative number!"});
  117. } else {
  118. cb({a + b});
  119. }
  120. }),
  121. Method(
  122. "addIfPositiveAsAsync",
  123. [](dynamic args, Callback cb, Callback cbError) {
  124. auto a = jsArgAsDouble(args, 0);
  125. auto b = jsArgAsDouble(args, 1);
  126. if (a < 0 || b < 0) {
  127. cbError({"Negative number!"});
  128. } else {
  129. cb({a + b});
  130. }
  131. },
  132. AsyncTag),
  133. };
  134. }
  135. void SampleCxxModule::save(folly::dynamic args) {
  136. std::map<std::string, std::string> m;
  137. for (const auto &p : jsArgN(args, 0, &dynamic::items)) {
  138. m.emplace(
  139. jsArg(p.first, &dynamic::asString, "map key"),
  140. jsArg(p.second, &dynamic::asString, "map value"));
  141. }
  142. sample_->save(std::move(m));
  143. }
  144. void SampleCxxModule::load(__unused folly::dynamic args, Callback cb) {
  145. dynamic d = dynamic::object;
  146. for (const auto &p : sample_->load()) {
  147. d.insert(p.first, p.second);
  148. }
  149. cb({d});
  150. }
  151. } // namespace samples
  152. } // namespace xplat
  153. } // namespace facebook
  154. // By convention, the function name should be the same as the class name.
  155. facebook::xplat::module::CxxModule *SampleCxxModule() {
  156. return new facebook::xplat::samples::SampleCxxModule(
  157. std::make_unique<facebook::xplat::samples::Sample>());
  158. }