9
9
using namespace v8 ;
10
10
using namespace std ;
11
11
12
+ static std::map<v8::Isolate*, v8::Persistent<v8::Function>*> isolateToPersistentSmartJSONStringify = std::map<v8::Isolate*, v8::Persistent<v8::Function>*>();
13
+
12
14
string tns::ConvertToString (const Local<v8::String>& s) {
13
15
if (s.IsEmpty ()) {
14
16
return string ();
@@ -18,16 +20,87 @@ string tns::ConvertToString(const Local<v8::String>& s) {
18
20
}
19
21
}
20
22
23
+ Local<Function> GetSmartJSONStringifyFunction (Isolate* isolate) {
24
+ auto it = isolateToPersistentSmartJSONStringify.find (isolate);
25
+ if (it != isolateToPersistentSmartJSONStringify.end ()) {
26
+ auto smartStringifyPersistentFunction = it->second ;
27
+
28
+ return smartStringifyPersistentFunction->Get (isolate);
29
+ }
30
+
31
+ string smartStringifyFunctionScript =
32
+ " (function () {\n "
33
+ " function smartStringify(object) {\n "
34
+ " seen = [];\n "
35
+ " var replacer = function (key, value) {\n "
36
+ " if (value != null && typeof value == \" object\" ) {\n "
37
+ " if (seen.indexOf(value) >= 0) {\n "
38
+ " if (key) {\n "
39
+ " return \" [Circular]\" ;\n "
40
+ " }\n "
41
+ " return;\n "
42
+ " }\n "
43
+ " seen.push(value);\n "
44
+ " }\n "
45
+ " return value;\n "
46
+ " };\n "
47
+ " return JSON.stringify(object, replacer, 2);\n "
48
+ " }\n "
49
+ " return smartStringify;\n "
50
+ " })();" ;
51
+
52
+ auto source = tns::ArgConverter::ConvertToV8String (isolate, smartStringifyFunctionScript);
53
+ auto context = isolate->GetCurrentContext ();
54
+
55
+ Local<Script> script;
56
+ auto maybeScript = Script::Compile (context, source).ToLocal (&script);
57
+
58
+ if (script.IsEmpty ()) {
59
+ return Local<Function>();
60
+ }
61
+
62
+ Local<Value> result;
63
+ auto maybeResult = script->Run (context).ToLocal (&result);
64
+
65
+ if (result.IsEmpty () && !result->IsFunction ()) {
66
+ return Local<Function>();
67
+ }
68
+
69
+ auto smartStringifyFunction = result.As <Function>();
70
+
71
+ auto smartStringifyPersistentFunction = new Persistent<Function>(isolate, smartStringifyFunction);
72
+
73
+ isolateToPersistentSmartJSONStringify.insert (std::make_pair (isolate, smartStringifyPersistentFunction));
74
+
75
+ return smartStringifyPersistentFunction->Get (isolate);
76
+ }
77
+
21
78
Local<String> tns::JsonStringifyObject (Isolate* isolate, Handle<v8::Value> value) {
22
79
v8::HandleScope scope (isolate);
23
80
24
81
if (value.IsEmpty ()) {
25
82
return String::Empty (isolate);
26
83
}
27
84
85
+ Local<Function> smartJSONStringifyFunction = GetSmartJSONStringifyFunction (isolate);
86
+
87
+ if (!smartJSONStringifyFunction.IsEmpty ()) {
88
+ if (value->IsObject ()) {
89
+ v8::Local<v8::Value> resultValue;
90
+ v8::TryCatch tc;
91
+
92
+ Local<Value> args[] = { value->ToObject () };
93
+ auto success = smartJSONStringifyFunction->Call (isolate->GetCurrentContext (), Undefined (isolate), 1 , args).ToLocal (&resultValue);
94
+
95
+ if (success && !tc.HasCaught ()) {
96
+ return resultValue->ToString ();
97
+ }
98
+ }
99
+ }
100
+
28
101
v8::Local<v8::String> resultString;
29
102
v8::TryCatch tc;
30
- auto success = v8::JSON::Stringify (isolate->GetCurrentContext (), value->ToObject (isolate)).ToLocal (&resultString);
103
+ auto success = v8::JSON::Stringify (isolate->GetCurrentContext (), value->ToObject (isolate), ArgConverter::ConvertToV8String (isolate, " 2 " ) ).ToLocal (&resultString);
31
104
32
105
if (!success && tc.HasCaught ()) {
33
106
auto message = tc.Message ()->Get ();
@@ -123,4 +196,3 @@ bool tns::V8SetPrivateValue(Isolate* isolate, const Local<Object>& obj, const Lo
123
196
124
197
return res.FromMaybe (false );
125
198
}
126
-
0 commit comments