123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. /*********************************************************************
  2. * NAN - Native Abstractions for Node.js
  3. *
  4. * Copyright (c) 2018 NAN contributors
  5. *
  6. * MIT License <https://github.com/nodejs/nan/blob/master/LICENSE.md>
  7. ********************************************************************/
  8. #ifndef NAN_JSON_H_
  9. #define NAN_JSON_H_
  10. #if NODE_MODULE_VERSION < NODE_0_12_MODULE_VERSION
  11. #define NAN_JSON_H_NEED_PARSE 1
  12. #else
  13. #define NAN_JSON_H_NEED_PARSE 0
  14. #endif // NODE_MODULE_VERSION < NODE_0_12_MODULE_VERSION
  15. #if NODE_MODULE_VERSION >= NODE_7_0_MODULE_VERSION
  16. #define NAN_JSON_H_NEED_STRINGIFY 0
  17. #else
  18. #define NAN_JSON_H_NEED_STRINGIFY 1
  19. #endif // NODE_MODULE_VERSION >= NODE_7_0_MODULE_VERSION
  20. class JSON {
  21. public:
  22. JSON() {
  23. #if NAN_JSON_H_NEED_PARSE + NAN_JSON_H_NEED_STRINGIFY
  24. Nan::HandleScope scope;
  25. Nan::MaybeLocal<v8::Value> maybe_global_json = Nan::Get(
  26. Nan::GetCurrentContext()->Global(),
  27. Nan::New("JSON").ToLocalChecked()
  28. );
  29. assert(!maybe_global_json.IsEmpty() && "global JSON is empty");
  30. v8::Local<v8::Value> val_global_json = maybe_global_json.ToLocalChecked();
  31. assert(val_global_json->IsObject() && "global JSON is not an object");
  32. Nan::MaybeLocal<v8::Object> maybe_obj_global_json =
  33. Nan::To<v8::Object>(val_global_json);
  34. assert(!maybe_obj_global_json.IsEmpty() && "global JSON object is empty");
  35. v8::Local<v8::Object> global_json = maybe_obj_global_json.ToLocalChecked();
  36. #if NAN_JSON_H_NEED_PARSE
  37. Nan::MaybeLocal<v8::Value> maybe_parse_method = Nan::Get(
  38. global_json, Nan::New("parse").ToLocalChecked()
  39. );
  40. assert(!maybe_parse_method.IsEmpty() && "JSON.parse is empty");
  41. v8::Local<v8::Value> parse_method = maybe_parse_method.ToLocalChecked();
  42. assert(parse_method->IsFunction() && "JSON.parse is not a function");
  43. parse_cb_.Reset(parse_method.As<v8::Function>());
  44. #endif // NAN_JSON_H_NEED_PARSE
  45. #if NAN_JSON_H_NEED_STRINGIFY
  46. Nan::MaybeLocal<v8::Value> maybe_stringify_method = Nan::Get(
  47. global_json, Nan::New("stringify").ToLocalChecked()
  48. );
  49. assert(!maybe_stringify_method.IsEmpty() && "JSON.stringify is empty");
  50. v8::Local<v8::Value> stringify_method =
  51. maybe_stringify_method.ToLocalChecked();
  52. assert(
  53. stringify_method->IsFunction() && "JSON.stringify is not a function"
  54. );
  55. stringify_cb_.Reset(stringify_method.As<v8::Function>());
  56. #endif // NAN_JSON_H_NEED_STRINGIFY
  57. #endif // NAN_JSON_H_NEED_PARSE + NAN_JSON_H_NEED_STRINGIFY
  58. }
  59. inline
  60. Nan::MaybeLocal<v8::Value> Parse(v8::Local<v8::String> json_string) {
  61. Nan::EscapableHandleScope scope;
  62. #if NAN_JSON_H_NEED_PARSE
  63. return scope.Escape(parse(json_string));
  64. #else
  65. Nan::MaybeLocal<v8::Value> result;
  66. #if NODE_MODULE_VERSION >= NODE_0_12_MODULE_VERSION && \
  67. NODE_MODULE_VERSION <= IOJS_2_0_MODULE_VERSION
  68. result = v8::JSON::Parse(json_string);
  69. #else
  70. #if NODE_MODULE_VERSION > NODE_6_0_MODULE_VERSION
  71. v8::Local<v8::Context> context_or_isolate = Nan::GetCurrentContext();
  72. #else
  73. v8::Isolate* context_or_isolate = v8::Isolate::GetCurrent();
  74. #endif // NODE_MODULE_VERSION > NODE_6_0_MODULE_VERSION
  75. result = v8::JSON::Parse(context_or_isolate, json_string);
  76. #endif // NODE_MODULE_VERSION >= NODE_0_12_MODULE_VERSION &&
  77. // NODE_MODULE_VERSION <= IOJS_2_0_MODULE_VERSION
  78. if (result.IsEmpty()) return v8::Local<v8::Value>();
  79. return scope.Escape(result.ToLocalChecked());
  80. #endif // NAN_JSON_H_NEED_PARSE
  81. }
  82. inline
  83. Nan::MaybeLocal<v8::String> Stringify(v8::Local<v8::Object> json_object) {
  84. Nan::EscapableHandleScope scope;
  85. Nan::MaybeLocal<v8::String> result =
  86. #if NAN_JSON_H_NEED_STRINGIFY
  87. Nan::To<v8::String>(stringify(json_object));
  88. #else
  89. v8::JSON::Stringify(Nan::GetCurrentContext(), json_object);
  90. #endif // NAN_JSON_H_NEED_STRINGIFY
  91. if (result.IsEmpty()) return v8::Local<v8::String>();
  92. return scope.Escape(result.ToLocalChecked());
  93. }
  94. inline
  95. Nan::MaybeLocal<v8::String> Stringify(v8::Local<v8::Object> json_object,
  96. v8::Local<v8::String> gap) {
  97. Nan::EscapableHandleScope scope;
  98. Nan::MaybeLocal<v8::String> result =
  99. #if NAN_JSON_H_NEED_STRINGIFY
  100. Nan::To<v8::String>(stringify(json_object, gap));
  101. #else
  102. v8::JSON::Stringify(Nan::GetCurrentContext(), json_object, gap);
  103. #endif // NAN_JSON_H_NEED_STRINGIFY
  104. if (result.IsEmpty()) return v8::Local<v8::String>();
  105. return scope.Escape(result.ToLocalChecked());
  106. }
  107. private:
  108. NAN_DISALLOW_ASSIGN_COPY_MOVE(JSON)
  109. #if NAN_JSON_H_NEED_PARSE
  110. Nan::Callback parse_cb_;
  111. #endif // NAN_JSON_H_NEED_PARSE
  112. #if NAN_JSON_H_NEED_STRINGIFY
  113. Nan::Callback stringify_cb_;
  114. #endif // NAN_JSON_H_NEED_STRINGIFY
  115. #if NAN_JSON_H_NEED_PARSE
  116. inline v8::Local<v8::Value> parse(v8::Local<v8::Value> arg) {
  117. assert(!parse_cb_.IsEmpty() && "parse_cb_ is empty");
  118. AsyncResource resource("nan:JSON.parse");
  119. return parse_cb_.Call(1, &arg, &resource).FromMaybe(v8::Local<v8::Value>());
  120. }
  121. #endif // NAN_JSON_H_NEED_PARSE
  122. #if NAN_JSON_H_NEED_STRINGIFY
  123. inline v8::Local<v8::Value> stringify(v8::Local<v8::Value> arg) {
  124. assert(!stringify_cb_.IsEmpty() && "stringify_cb_ is empty");
  125. AsyncResource resource("nan:JSON.stringify");
  126. return stringify_cb_.Call(1, &arg, &resource)
  127. .FromMaybe(v8::Local<v8::Value>());
  128. }
  129. inline v8::Local<v8::Value> stringify(v8::Local<v8::Value> arg,
  130. v8::Local<v8::String> gap) {
  131. assert(!stringify_cb_.IsEmpty() && "stringify_cb_ is empty");
  132. v8::Local<v8::Value> argv[] = {
  133. arg,
  134. Nan::Null(),
  135. gap
  136. };
  137. AsyncResource resource("nan:JSON.stringify");
  138. return stringify_cb_.Call(3, argv, &resource)
  139. .FromMaybe(v8::Local<v8::Value>());
  140. }
  141. #endif // NAN_JSON_H_NEED_STRINGIFY
  142. };
  143. #endif // NAN_JSON_H_