Skip to content

Commit a07edb8

Browse files
committed
Remove most globals
1 parent 1c232ce commit a07edb8

File tree

3 files changed

+72
-45
lines changed

3 files changed

+72
-45
lines changed

js.cpp

Lines changed: 32 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,6 @@
99

1010
void KeyDBExecuteCallback(const v8::FunctionCallbackInfo<v8::Value>& args);
1111

12-
thread_local v8::Isolate *isolate = nullptr;
13-
thread_local v8::Persistent<v8::ObjectTemplate, v8::CopyablePersistentTraits<v8::ObjectTemplate>> tls_global;
14-
thread_local v8::Persistent<v8::Context, v8::CopyablePersistentTraits<v8::Context>> tls_context;
15-
1612
void javascript_initialize()
1713
{
1814
v8::V8::InitializeICUDefaultLocation("keydb-server");
@@ -31,30 +27,34 @@ void javascript_shutdown()
3127
class HotScript
3228
{
3329
v8::Persistent<v8::Script> m_script;
30+
size_t m_cch;
3431
BYTE m_hash[SHA256_BLOCK_SIZE];
3532

3633
public:
37-
HotScript(const char *rgch, size_t cch, v8::Local<v8::Script> script)
38-
: m_script(isolate, script)
34+
HotScript(v8::Isolate *isolate, const char *rgch, size_t cch, v8::Local<v8::Script> script)
35+
: m_script(isolate, script), m_cch(cch)
3936
{
4037
SHA256_CTX ctx;
4138
sha256_init(&ctx);
4239
sha256_update(&ctx, (BYTE*)rgch, cch);
4340
sha256_final(&ctx, m_hash);
4441
}
4542

46-
bool FGetScript(const char *rgch, size_t cch, v8::Local<v8::Script> *pscriptOut)
43+
bool FGetScript(v8::Isolate *isolate, const char *rgch, size_t cch, v8::Local<v8::Script> *pscriptOut)
4744
{
45+
if (cch != m_cch)
46+
return false;
47+
4848
BYTE hashT[SHA256_BLOCK_SIZE];
4949
SHA256_CTX ctx;
5050
sha256_init(&ctx);
5151
sha256_update(&ctx, (BYTE*)rgch, cch);
5252
sha256_final(&ctx, hashT);
5353

54-
return FGetScript(hashT, pscriptOut);
54+
return FGetScript(isolate, hashT, pscriptOut);
5555
}
5656

57-
bool FGetScript(const BYTE *hash, v8::Local<v8::Script> *pscriptOut)
57+
bool FGetScript(v8::Isolate *isolate, const BYTE *hash, v8::Local<v8::Script> *pscriptOut)
5858
{
5959
if (memcmp(m_hash, hash, SHA256_BLOCK_SIZE))
6060
return false;
@@ -93,6 +93,9 @@ class StackPopper
9393
}
9494
};
9595

96+
JSContext::JSContext()
97+
{}
98+
9699
std::experimental::filesystem::path find_module(std::experimental::filesystem::path name)
97100
{
98101
std::experimental::filesystem::path path;
@@ -119,11 +122,15 @@ std::experimental::filesystem::path find_module(std::experimental::filesystem::p
119122
} while (!wdir.empty());
120123
}
121124

122-
static void RequireCallback(const v8::FunctionCallbackInfo<v8::Value>& args)
125+
/*static*/ void JSContext::RequireCallback(const v8::FunctionCallbackInfo<v8::Value>& args)
123126
{
124127
static thread_local std::stack<std::experimental::filesystem::path> stackpath;
128+
v8::Isolate *isolate = args.GetIsolate();
125129

126130
if (args.Length() != 1) return;
131+
132+
JSContext *jscontext = (JSContext*)isolate->GetData(0);
133+
127134
v8::HandleScope scope(isolate);
128135
v8::Local<v8::Value> arg = args[0];
129136
v8::String::Utf8Value utf8Path(isolate, arg);
@@ -171,7 +178,7 @@ static void RequireCallback(const v8::FunctionCallbackInfo<v8::Value>& args)
171178
return; // Failed to read file
172179
}
173180

174-
v8::Local<v8::ObjectTemplate> global = v8::Local<v8::ObjectTemplate>::New(isolate, tls_global);
181+
v8::Local<v8::ObjectTemplate> global = v8::Local<v8::ObjectTemplate>::New(isolate, jscontext->m_global);
175182
v8::Local<v8::Context> context = v8::Context::New(isolate, nullptr, global);
176183

177184
v8::ScriptOrigin origin(arg, // specifier
@@ -226,7 +233,7 @@ static void RequireCallback(const v8::FunctionCallbackInfo<v8::Value>& args)
226233
}
227234

228235

229-
void javascript_hooks_initialize(v8::Local<v8::ObjectTemplate> &keydb_obj)
236+
void JSContext::javascript_hooks_initialize(v8::Local<v8::ObjectTemplate> &keydb_obj)
230237
{
231238
keydb_obj->Set(v8::String::NewFromUtf8(isolate, "log", v8::NewStringType::kNormal)
232239
.ToLocalChecked(),
@@ -237,7 +244,7 @@ void javascript_hooks_initialize(v8::Local<v8::ObjectTemplate> &keydb_obj)
237244
v8::FunctionTemplate::New(isolate, KeyDBExecuteCallback));
238245
}
239246

240-
void javascript_thread_initialize()
247+
void JSContext::initialize()
241248
{
242249
v8::Isolate::CreateParams create_params;
243250
create_params.array_buffer_allocator = v8::ArrayBuffer::Allocator::NewDefaultAllocator();
@@ -270,11 +277,13 @@ void javascript_thread_initialize()
270277
.ToLocalChecked(),
271278
module);
272279

273-
tls_global = v8::Persistent<v8::ObjectTemplate, v8::CopyablePersistentTraits<v8::ObjectTemplate>>(isolate, global);
274-
tls_context = v8::Persistent<v8::Context, v8::CopyablePersistentTraits<v8::Context>>(isolate, v8::Context::New(isolate, nullptr, global));
280+
281+
isolate->SetData(0, this);
282+
m_global = v8::Persistent<v8::ObjectTemplate, v8::CopyablePersistentTraits<v8::ObjectTemplate>>(isolate, global);
283+
m_context = v8::Persistent<v8::Context, v8::CopyablePersistentTraits<v8::Context>>(isolate, v8::Context::New(isolate, nullptr, global));
275284
}
276285

277-
std::string prettyPrintException(v8::TryCatch &trycatch)
286+
std::string JSContext::prettyPrintException(v8::TryCatch &trycatch)
278287
{
279288
auto e = trycatch.Exception();
280289
v8::Local<v8::Context> context = v8::Local<v8::Context>::New(isolate, isolate->GetCurrentContext());
@@ -292,7 +301,7 @@ std::string prettyPrintException(v8::TryCatch &trycatch)
292301
return str;
293302
}
294303

295-
v8::Local<v8::Value> javascript_run(v8::Local<v8::Context> &context, v8::Local<v8::Script> &script)
304+
v8::Local<v8::Value> JSContext::run(v8::Local<v8::Context> &context, v8::Local<v8::Script> &script)
296305
{
297306
// Run the script to get the result.
298307
v8::Context::Scope context_scope(context);
@@ -314,16 +323,16 @@ v8::Local<v8::Value> javascript_run(v8::Local<v8::Context> &context, v8::Local<v
314323
return result;
315324
}
316325

317-
v8::Local<v8::Value> javascript_run(v8::Local<v8::Context> &context, const char *rgch, size_t cch)
326+
v8::Local<v8::Value> JSContext::run(const char *rgch, size_t cch)
318327
{
319-
static thread_local HotScript *hotscript = nullptr;
320328
v8::TryCatch trycatch(isolate);
321329

322330
// Enter the context for compiling and running the hello world script.
331+
v8::Local<v8::Context> context = v8::Local<v8::Context>::New(isolate, m_context);
323332
v8::Context::Scope context_scope(context);
324333

325334
v8::Local<v8::Script> script;
326-
if (hotscript == nullptr || !hotscript->FGetScript(rgch, cch, &script))
335+
if (m_sphotscript == nullptr || !m_sphotscript->FGetScript(isolate, rgch, cch, &script))
327336
{
328337
// Create a string containing the JavaScript source code.
329338
v8::Local<v8::String> sourceText =
@@ -345,13 +354,12 @@ v8::Local<v8::Value> javascript_run(v8::Local<v8::Context> &context, const char
345354
}
346355
throw std::nullptr_t();
347356
}
348-
delete hotscript;
349-
hotscript = new HotScript(rgch, cch, script);
357+
m_sphotscript = std::make_unique<HotScript>(isolate, rgch, cch, script);
350358
}
351-
return javascript_run(context, script);
359+
return run(context, script);
352360
}
353361

354-
void javascript_thread_shutdown()
362+
JSContext::~JSContext()
355363
{
356364
isolate->Dispose();
357365
}

js.h

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,31 @@
33
#include <string>
44
#include <v8.h>
55

6-
void javascript_initialize();
7-
void javascript_thread_initialize();
8-
void javascript_shutdown();
9-
void javascript_thread_shutdown();
6+
class HotScript;
7+
class JSContext
8+
{
9+
v8::Isolate *isolate = nullptr;
10+
v8::Persistent<v8::ObjectTemplate, v8::CopyablePersistentTraits<v8::ObjectTemplate>> m_global;
11+
v8::Persistent<v8::Context, v8::CopyablePersistentTraits<v8::Context>> m_context;
12+
13+
public:
14+
JSContext();
15+
~JSContext();
16+
17+
void initialize();
18+
v8::Local<v8::Value> run(const char *rgch, size_t cch);
19+
v8::Local<v8::Context> getCurrentContext() { return v8::Local<v8::Context>::New(isolate, m_context); }
20+
v8::Isolate *getIsolate() { return isolate; }
1021

11-
v8::Local<v8::Value> javascript_run(v8::Local<v8::Context> &context, const char *rgch, size_t cch);
22+
protected:
23+
v8::Local<v8::Value> run(v8::Local<v8::Context> &context, v8::Local<v8::Script> &script);
24+
std::string prettyPrintException(v8::TryCatch &trycatch);
25+
void javascript_hooks_initialize(v8::Local<v8::ObjectTemplate> &keydb_obj);
26+
27+
static void RequireCallback(const v8::FunctionCallbackInfo<v8::Value>& args);
28+
29+
std::unique_ptr<HotScript> m_sphotscript;
30+
};
31+
32+
void javascript_initialize();
33+
void javascript_shutdown();

module.cpp

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,8 @@
55
#include <v8.h>
66
#include <math.h>
77

8-
thread_local RedisModuleCtx *g_ctx = nullptr;
9-
extern thread_local v8::Isolate *isolate;
10-
extern thread_local v8::Persistent<v8::ObjectTemplate, v8::CopyablePersistentTraits<v8::ObjectTemplate>> tls_global;
11-
extern thread_local v8::Persistent<v8::Context> tls_context;
8+
RedisModuleCtx *g_ctx = nullptr;
9+
JSContext *g_jscontext = nullptr;
1210

1311
static void ProcessCallReply(v8::Local<v8::Value> &dst, v8::Isolate* isolate, RedisModuleCallReply *reply)
1412
{
@@ -91,7 +89,7 @@ void KeyDBExecuteCallback(const v8::FunctionCallbackInfo<v8::Value>& args)
9189
}
9290

9391

94-
static void processResult(RedisModuleCtx *ctx, v8::Local<v8::Context> &v8ctx, v8::Local<v8::Value> &result)
92+
static void processResult(RedisModuleCtx *ctx, v8::Isolate *isolate, v8::Local<v8::Context> &v8ctx, v8::Local<v8::Value> &result)
9593
{
9694
if (result->IsArray())
9795
{
@@ -102,7 +100,7 @@ static void processResult(RedisModuleCtx *ctx, v8::Local<v8::Context> &v8ctx, v8
102100
auto maybe = array->Get(v8ctx, ielem);
103101
v8::Local<v8::Value> val;
104102
if (maybe.ToLocal(&val))
105-
processResult(ctx, v8ctx, val);
103+
processResult(ctx, isolate, v8ctx, val);
106104
else
107105
RedisModule_ReplyWithNull(ctx);
108106
}
@@ -138,22 +136,21 @@ int evaljs_command(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
138136
return REDISMODULE_ERR;
139137
}
140138

141-
if (isolate == nullptr)
142-
javascript_thread_initialize();
139+
if (g_jscontext == nullptr)
140+
{
141+
g_jscontext = new JSContext();
142+
g_jscontext->initialize();
143+
}
143144

144145
size_t cch = 0;
145146
const char *rgch = RedisModule_StringPtrLen(argv[1], &cch);
146147
try
147148
{
148149
g_ctx = ctx;
149-
v8::Isolate::Scope isolate_scope(isolate);
150-
// Create a stack-allocated handle scope.
151-
v8::HandleScope handle_scope(isolate);
152-
// Create a new context.
153-
v8::Local<v8::ObjectTemplate> global = v8::Local<v8::ObjectTemplate>::New(isolate, tls_global);
154-
v8::Local<v8::Context> context = v8::Local<v8::Context>::New(isolate, tls_context);
155-
v8::Local<v8::Value> result = javascript_run(context, rgch, cch);
156-
processResult(ctx, context, result);
150+
v8::HandleScope scope(g_jscontext->getIsolate());
151+
v8::Local<v8::Value> result = g_jscontext->run(rgch, cch);
152+
auto context = g_jscontext->getCurrentContext();
153+
processResult(ctx, g_jscontext->getIsolate(), context, result);
157154
}
158155
catch (std::string strerr)
159156
{

0 commit comments

Comments
 (0)