| /********************************************************************* |
| * NAN - Native Abstractions for Node.js |
| * |
| * Copyright (c) 2018 NAN contributors |
| * |
| * MIT License <https://github.com/nodejs/nan/blob/master/LICENSE.md> |
| ********************************************************************/ |
| |
| #ifndef NAN_JSON_H_ |
| #define NAN_JSON_H_ |
| |
| #if NODE_MODULE_VERSION < NODE_0_12_MODULE_VERSION |
| #define NAN_JSON_H_NEED_PARSE 1 |
| #else |
| #define NAN_JSON_H_NEED_PARSE 0 |
| #endif // NODE_MODULE_VERSION < NODE_0_12_MODULE_VERSION |
| |
| #if NODE_MODULE_VERSION >= NODE_7_0_MODULE_VERSION |
| #define NAN_JSON_H_NEED_STRINGIFY 0 |
| #else |
| #define NAN_JSON_H_NEED_STRINGIFY 1 |
| #endif // NODE_MODULE_VERSION >= NODE_7_0_MODULE_VERSION |
| |
| class JSON { |
| public: |
| JSON() { |
| #if NAN_JSON_H_NEED_PARSE + NAN_JSON_H_NEED_STRINGIFY |
| Nan::HandleScope scope; |
| |
| Nan::MaybeLocal<v8::Value> maybe_global_json = Nan::Get( |
| Nan::GetCurrentContext()->Global(), |
| Nan::New("JSON").ToLocalChecked() |
| ); |
| |
| assert(!maybe_global_json.IsEmpty() && "global JSON is empty"); |
| v8::Local<v8::Value> val_global_json = maybe_global_json.ToLocalChecked(); |
| |
| assert(val_global_json->IsObject() && "global JSON is not an object"); |
| Nan::MaybeLocal<v8::Object> maybe_obj_global_json = |
| Nan::To<v8::Object>(val_global_json); |
| |
| assert(!maybe_obj_global_json.IsEmpty() && "global JSON object is empty"); |
| v8::Local<v8::Object> global_json = maybe_obj_global_json.ToLocalChecked(); |
| |
| #if NAN_JSON_H_NEED_PARSE |
| Nan::MaybeLocal<v8::Value> maybe_parse_method = Nan::Get( |
| global_json, Nan::New("parse").ToLocalChecked() |
| ); |
| |
| assert(!maybe_parse_method.IsEmpty() && "JSON.parse is empty"); |
| v8::Local<v8::Value> parse_method = maybe_parse_method.ToLocalChecked(); |
| |
| assert(parse_method->IsFunction() && "JSON.parse is not a function"); |
| parse_cb_.Reset(parse_method.As<v8::Function>()); |
| #endif // NAN_JSON_H_NEED_PARSE |
| |
| #if NAN_JSON_H_NEED_STRINGIFY |
| Nan::MaybeLocal<v8::Value> maybe_stringify_method = Nan::Get( |
| global_json, Nan::New("stringify").ToLocalChecked() |
| ); |
| |
| assert(!maybe_stringify_method.IsEmpty() && "JSON.stringify is empty"); |
| v8::Local<v8::Value> stringify_method = |
| maybe_stringify_method.ToLocalChecked(); |
| |
| assert( |
| stringify_method->IsFunction() && "JSON.stringify is not a function" |
| ); |
| stringify_cb_.Reset(stringify_method.As<v8::Function>()); |
| #endif // NAN_JSON_H_NEED_STRINGIFY |
| #endif // NAN_JSON_H_NEED_PARSE + NAN_JSON_H_NEED_STRINGIFY |
| } |
| |
| inline |
| Nan::MaybeLocal<v8::Value> Parse(v8::Local<v8::String> json_string) { |
| Nan::EscapableHandleScope scope; |
| #if NAN_JSON_H_NEED_PARSE |
| return scope.Escape(parse(json_string)); |
| #else |
| Nan::MaybeLocal<v8::Value> result; |
| #if NODE_MODULE_VERSION >= NODE_0_12_MODULE_VERSION && \ |
| NODE_MODULE_VERSION <= IOJS_2_0_MODULE_VERSION |
| result = v8::JSON::Parse(json_string); |
| #else |
| #if NODE_MODULE_VERSION > NODE_6_0_MODULE_VERSION |
| v8::Local<v8::Context> context_or_isolate = Nan::GetCurrentContext(); |
| #else |
| v8::Isolate* context_or_isolate = v8::Isolate::GetCurrent(); |
| #endif // NODE_MODULE_VERSION > NODE_6_0_MODULE_VERSION |
| result = v8::JSON::Parse(context_or_isolate, json_string); |
| #endif // NODE_MODULE_VERSION >= NODE_0_12_MODULE_VERSION && |
| // NODE_MODULE_VERSION <= IOJS_2_0_MODULE_VERSION |
| if (result.IsEmpty()) return v8::Local<v8::Value>(); |
| return scope.Escape(result.ToLocalChecked()); |
| #endif // NAN_JSON_H_NEED_PARSE |
| } |
| |
| inline |
| Nan::MaybeLocal<v8::String> Stringify(v8::Local<v8::Object> json_object) { |
| Nan::EscapableHandleScope scope; |
| Nan::MaybeLocal<v8::String> result = |
| #if NAN_JSON_H_NEED_STRINGIFY |
| Nan::To<v8::String>(stringify(json_object)); |
| #else |
| v8::JSON::Stringify(Nan::GetCurrentContext(), json_object); |
| #endif // NAN_JSON_H_NEED_STRINGIFY |
| if (result.IsEmpty()) return v8::Local<v8::String>(); |
| return scope.Escape(result.ToLocalChecked()); |
| } |
| |
| inline |
| Nan::MaybeLocal<v8::String> Stringify(v8::Local<v8::Object> json_object, |
| v8::Local<v8::String> gap) { |
| Nan::EscapableHandleScope scope; |
| Nan::MaybeLocal<v8::String> result = |
| #if NAN_JSON_H_NEED_STRINGIFY |
| Nan::To<v8::String>(stringify(json_object, gap)); |
| #else |
| v8::JSON::Stringify(Nan::GetCurrentContext(), json_object, gap); |
| #endif // NAN_JSON_H_NEED_STRINGIFY |
| if (result.IsEmpty()) return v8::Local<v8::String>(); |
| return scope.Escape(result.ToLocalChecked()); |
| } |
| |
| private: |
| NAN_DISALLOW_ASSIGN_COPY_MOVE(JSON) |
| #if NAN_JSON_H_NEED_PARSE |
| Nan::Callback parse_cb_; |
| #endif // NAN_JSON_H_NEED_PARSE |
| #if NAN_JSON_H_NEED_STRINGIFY |
| Nan::Callback stringify_cb_; |
| #endif // NAN_JSON_H_NEED_STRINGIFY |
| |
| #if NAN_JSON_H_NEED_PARSE |
| inline v8::Local<v8::Value> parse(v8::Local<v8::Value> arg) { |
| assert(!parse_cb_.IsEmpty() && "parse_cb_ is empty"); |
| AsyncResource resource("nan:JSON.parse"); |
| return parse_cb_.Call(1, &arg, &resource).FromMaybe(v8::Local<v8::Value>()); |
| } |
| #endif // NAN_JSON_H_NEED_PARSE |
| |
| #if NAN_JSON_H_NEED_STRINGIFY |
| inline v8::Local<v8::Value> stringify(v8::Local<v8::Value> arg) { |
| assert(!stringify_cb_.IsEmpty() && "stringify_cb_ is empty"); |
| AsyncResource resource("nan:JSON.stringify"); |
| return stringify_cb_.Call(1, &arg, &resource) |
| .FromMaybe(v8::Local<v8::Value>()); |
| } |
| |
| inline v8::Local<v8::Value> stringify(v8::Local<v8::Value> arg, |
| v8::Local<v8::String> gap) { |
| assert(!stringify_cb_.IsEmpty() && "stringify_cb_ is empty"); |
| |
| v8::Local<v8::Value> argv[] = { |
| arg, |
| Nan::Null(), |
| gap |
| }; |
| AsyncResource resource("nan:JSON.stringify"); |
| return stringify_cb_.Call(3, argv, &resource) |
| .FromMaybe(v8::Local<v8::Value>()); |
| } |
| #endif // NAN_JSON_H_NEED_STRINGIFY |
| }; |
| |
| #endif // NAN_JSON_H_ |