1
1
#include " js.h"
2
2
#include " redismodule.h"
3
+ #include < vector>
4
+ #include < v8.h>
5
+
6
+ thread_local RedisModuleCtx *g_ctx = nullptr ;
7
+ extern thread_local v8::Isolate *isolate;
8
+ extern thread_local v8::Persistent<v8::ObjectTemplate, v8::CopyablePersistentTraits<v8::ObjectTemplate>> tls_global;
9
+
10
+ static void ProcessCallReply (v8::Local<v8::Value> &dst, v8::Isolate* isolate, RedisModuleCallReply *reply)
11
+ {
12
+ const char *rgchReply;
13
+ size_t cchReply;
14
+
15
+ switch (RedisModule_CallReplyType (reply))
16
+ {
17
+ case REDISMODULE_REPLY_STRING:
18
+ rgchReply = RedisModule_CallReplyStringPtr (reply, &cchReply);
19
+ dst = v8::String::NewFromUtf8 (isolate, rgchReply, v8::NewStringType::kNormal , cchReply).ToLocalChecked ();
20
+ break ;
21
+
22
+ case REDISMODULE_REPLY_INTEGER:
23
+ {
24
+ long long val = RedisModule_CallReplyInteger (reply);
25
+ dst = v8::BigInt::New (isolate, val);
26
+ break ;
27
+ }
28
+
29
+ case REDISMODULE_REPLY_ARRAY:
30
+ {
31
+ size_t celem = RedisModule_CallReplyLength (reply);
32
+
33
+ auto array = v8::Array::New (isolate, celem);
34
+ for (size_t ielem = 0 ; ielem < celem; ++ielem)
35
+ {
36
+ RedisModuleCallReply *replyArray = RedisModule_CallReplyArrayElement (reply, ielem);
37
+ v8::Local<v8::Value> val;
38
+ ProcessCallReply (val, isolate, replyArray);
39
+ v8::Maybe<bool > result = array->Set (isolate->GetCurrentContext (), ielem, val);
40
+ bool fResult ;
41
+ if (!result.To (&fResult ) || !fResult )
42
+ {
43
+ RedisModule_Log (g_ctx, " warning" , " Failed to process array result" );
44
+ }
45
+ }
46
+ dst = array;
47
+ break ;
48
+ }
49
+
50
+ default :
51
+ rgchReply = RedisModule_CallReplyProto (reply, &cchReply);
52
+ dst = v8::String::NewFromUtf8 (isolate, rgchReply, v8::NewStringType::kNormal , cchReply).ToLocalChecked ();
53
+ }
54
+ }
55
+
56
+ void KeyDBExecuteCallback (const v8::FunctionCallbackInfo<v8::Value>& args)
57
+ {
58
+ if (args.Length () < 1 ) return ;
59
+ v8::Isolate* isolate = args.GetIsolate ();
60
+ v8::HandleScope scope (isolate);
61
+ v8::Local<v8::Value> vfnName = args[0 ];
62
+ v8::String::Utf8Value fnName (isolate, vfnName);
63
+
64
+ std::vector<RedisModuleString*> vecstrs;
65
+ for (size_t iarg = 1 ; iarg < args.Length (); ++iarg)
66
+ {
67
+ v8::String::Utf8Value argument (isolate, args[iarg]);
68
+ vecstrs.push_back (RedisModule_CreateString (g_ctx, *argument, argument.length ()));
69
+ }
70
+
71
+ RedisModuleCallReply *reply = RedisModule_Call (g_ctx, *fnName, " v" , vecstrs.data (), vecstrs.size ());
72
+
73
+ if (reply != nullptr )
74
+ {
75
+ v8::Local<v8::Value> result;
76
+ ProcessCallReply (result, isolate, reply);
77
+ args.GetReturnValue ().Set (result);
78
+
79
+ RedisModule_FreeCallReply (reply);
80
+ }
81
+ else
82
+ {
83
+ isolate->ThrowException (v8::String::NewFromUtf8 (isolate, " Invalid Command" ).ToLocalChecked ());
84
+ }
85
+
86
+ for (auto str : vecstrs)
87
+ RedisModule_FreeString (g_ctx, str);
88
+ }
89
+
90
+
91
+ static void processResult (RedisModuleCtx *ctx, v8::Local<v8::Context> &v8ctx, v8::Local<v8::Value> &result)
92
+ {
93
+ if (result->IsArray ())
94
+ {
95
+ v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast (result);
96
+ RedisModule_ReplyWithArray (g_ctx, array->Length ());
97
+ for (size_t ielem = 0 ; ielem < array->Length (); ++ielem)
98
+ {
99
+ auto maybe = array->Get (v8ctx, ielem);
100
+ v8::Local<v8::Value> val;
101
+ if (maybe.ToLocal (&val))
102
+ processResult (ctx, v8ctx, val);
103
+ else
104
+ RedisModule_ReplyWithNull (ctx);
105
+ }
106
+ }
107
+ else
108
+ {
109
+ v8::String::Utf8Value utf8 (isolate, result);
110
+ RedisModule_ReplyWithCString (ctx, *utf8);
111
+ }
112
+ }
3
113
4
114
int evaljs_command (RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
5
115
{
@@ -9,23 +119,36 @@ int evaljs_command(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
9
119
return REDISMODULE_ERR;
10
120
}
11
121
122
+ if (isolate == nullptr )
123
+ javascript_thread_initialize ();
124
+
12
125
size_t cch = 0 ;
13
126
const char *rgch = RedisModule_StringPtrLen (argv[1 ], &cch);
14
127
try
15
128
{
16
- std::string strRes = javascript_run (rgch, cch);
17
- RedisModule_ReplyWithCString (ctx, strRes.c_str ());
129
+ g_ctx = ctx;
130
+ v8::Isolate::Scope isolate_scope (isolate);
131
+ // Create a stack-allocated handle scope.
132
+ v8::HandleScope handle_scope (isolate);
133
+ // Create a new context.
134
+ v8::Local<v8::ObjectTemplate> global = v8::Local<v8::ObjectTemplate>::New (isolate, tls_global);
135
+ v8::Local<v8::Context> context = v8::Context::New (isolate, nullptr , global);
136
+ v8::Local<v8::Value> result = javascript_run (context, rgch, cch);
137
+ processResult (ctx, context, result);
18
138
}
19
139
catch (std::string strerr)
20
140
{
21
141
RedisModule_ReplyWithError (ctx, strerr.c_str ());
142
+ g_ctx = nullptr ;
22
143
return REDISMODULE_ERR;
23
144
}
24
145
catch (std::nullptr_t )
25
146
{
26
147
RedisModule_ReplyWithError (ctx, " Unknown Error" );
148
+ g_ctx = nullptr ;
27
149
return REDISMODULE_ERR;
28
150
}
151
+ g_ctx = nullptr ;
29
152
return REDISMODULE_OK;
30
153
}
31
154
0 commit comments