Skip to content

Commit 4a94cc5

Browse files
author
Mihail Slavchev
authored
Merge pull request #473 from NativeScript/slavchev/modules-cache
Cache modules by unique combination of module path and basedir. This …
2 parents a88bfa4 + 52d010b commit 4a94cc5

2 files changed

Lines changed: 91 additions & 32 deletions

File tree

src/jni/Module.cpp

Lines changed: 53 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -166,18 +166,9 @@ void Module::RequireCallbackImpl(const v8::FunctionCallbackInfo<v8::Value>& args
166166

167167
string moduleName = ConvertToString(args[0].As<String>());
168168
string callingModuleDirName = ConvertToString(args[1].As<String>());
169-
170-
JEnv env;
171-
JniLocalRef jsModulename(env.NewStringUTF(moduleName.c_str()));
172-
JniLocalRef jsCallingModuleDirName(env.NewStringUTF(callingModuleDirName.c_str()));
173-
JniLocalRef jsModulePath(env.CallStaticObjectMethod(MODULE_CLASS, RESOLVE_PATH_METHOD_ID, (jstring) jsModulename, (jstring) jsCallingModuleDirName));
174-
175-
// cache the required modules by full path, not name only, since there might be some collisions with relative paths and names
176-
string modulePath = ArgConverter::jstringToString((jstring) jsModulePath);
177-
178169
auto isData = false;
179170

180-
auto moduleObj = LoadImpl(isolate, modulePath, isData);
171+
auto moduleObj = LoadImpl(isolate, moduleName, callingModuleDirName, isData);
181172

182173
if (isData)
183174
{
@@ -217,40 +208,64 @@ void Module::Load(const string& path)
217208
}
218209
}
219210

220-
Local<Object> Module::LoadImpl(Isolate *isolate, const string& path, bool& isData)
211+
Local<Object> Module::LoadImpl(Isolate *isolate, const string& moduleName, const string& baseDir, bool& isData)
221212
{
213+
auto pathKind = GetModulePathKind(moduleName);
214+
auto cachePathKey = (pathKind == ModulePathKind::Global) ? moduleName : (baseDir + "*" + moduleName);
215+
222216
Local<Object> result;
223217

224-
auto it = m_loadedModules.find(path);
218+
DEBUG_WRITE(">>LoadImpl cachePathKey=%s", cachePathKey.c_str());
219+
220+
auto it = m_loadedModules.find(cachePathKey);
225221

226222
if (it == m_loadedModules.end())
227223
{
228-
if (Util::EndsWith(path, ".js") || Util::EndsWith(path, ".so"))
229-
{
230-
isData = false;
231-
result = LoadModule(isolate, path);
232-
}
233-
else if (Util::EndsWith(path, ".json"))
224+
JEnv env;
225+
JniLocalRef jsModulename(env.NewStringUTF(moduleName.c_str()));
226+
JniLocalRef jsBaseDir(env.NewStringUTF(baseDir.c_str()));
227+
JniLocalRef jsModulePath(env.CallStaticObjectMethod(MODULE_CLASS, RESOLVE_PATH_METHOD_ID, (jstring) jsModulename, (jstring) jsBaseDir));
228+
229+
auto path = ArgConverter::jstringToString((jstring) jsModulePath);
230+
231+
auto it2 = m_loadedModules.find(path);
232+
233+
if (it2 == m_loadedModules.end())
234234
{
235-
isData = true;
236-
result = LoadData(isolate, path);
235+
if (Util::EndsWith(path, ".js") || Util::EndsWith(path, ".so"))
236+
{
237+
isData = false;
238+
result = LoadModule(isolate, path, cachePathKey);
239+
}
240+
else if (Util::EndsWith(path, ".json"))
241+
{
242+
isData = true;
243+
result = LoadData(isolate, path);
244+
}
245+
else
246+
{
247+
string errMsg = "Unsupported file extension: " + path;
248+
throw NativeScriptException(errMsg);
249+
}
237250
}
238251
else
239252
{
240-
string errMsg = "Unsupported file extension: " + path;
241-
throw NativeScriptException(errMsg);
253+
auto& cacheEntry = it2->second;
254+
isData = cacheEntry.isData;
255+
result = Local<Object>::New(isolate, *cacheEntry.obj);
242256
}
243257
}
244258
else
245259
{
246-
isData = Util::EndsWith(path, ".json");
247-
result = Local<Object>::New(isolate, *it->second);
260+
auto& cacheEntry = it->second;
261+
isData = cacheEntry.isData;
262+
result = Local<Object>::New(isolate, *cacheEntry.obj);
248263
}
249264

250265
return result;
251266
}
252267

253-
Local<Object> Module::LoadModule(Isolate *isolate, const string& modulePath)
268+
Local<Object> Module::LoadModule(Isolate *isolate, const string& modulePath, const string& moduleCacheKey)
254269
{
255270
Local<Object> result;
256271

@@ -262,7 +277,7 @@ Local<Object> Module::LoadModule(Isolate *isolate, const string& modulePath)
262277
moduleObj->Set(ConvertToV8String("filename"), fullRequiredModulePath);
263278

264279
auto poModuleObj = new Persistent<Object>(isolate, moduleObj);
265-
TempModule tempModule(this, modulePath, poModuleObj);
280+
TempModule tempModule(this, modulePath, moduleCacheKey, poModuleObj);
266281

267282
TryCatch tc;
268283

@@ -469,6 +484,18 @@ void Module::SaveScriptCache(const ScriptCompiler::Source& source, const std::st
469484
File::WriteBinary(cachePath, source.GetCachedData()->data, length);
470485
}
471486

487+
Module::ModulePathKind Module::GetModulePathKind(const std::string& path)
488+
{
489+
ModulePathKind kind;
490+
switch (path[0])
491+
{
492+
case '.': kind = ModulePathKind::Relative; break;
493+
case '/': kind = ModulePathKind::Absolute; break;
494+
default: kind = ModulePathKind::Global; break;
495+
}
496+
return kind;
497+
}
498+
472499
jclass Module::MODULE_CLASS = nullptr;
473500
jmethodID Module::RESOLVE_PATH_METHOD_ID = nullptr;
474501

src/jni/Module.h

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ namespace tns
2626
void Load(const std::string& path);
2727

2828
private:
29+
enum class ModulePathKind;
30+
31+
struct ModuleCacheEntry;
32+
2933
static void RequireCallback(const v8::FunctionCallbackInfo<v8::Value>& args);
3034

3135
static void RequireNativeCallback(const v8::FunctionCallbackInfo<v8::Value>& args);
@@ -34,9 +38,9 @@ namespace tns
3438

3539
v8::Local<v8::String> WrapModuleContent(const std::string& path);
3640

37-
v8::Local<v8::Object> LoadImpl(v8::Isolate *isolate, const std::string& path, bool& isData);
41+
v8::Local<v8::Object> LoadImpl(v8::Isolate *isolate, const std::string& moduleName, const std::string& baseDir, bool& isData);
3842

39-
v8::Local<v8::Object> LoadModule(v8::Isolate *isolate, const std::string& path);
43+
v8::Local<v8::Object> LoadModule(v8::Isolate *isolate, const std::string& path, const std::string& moduleCacheKey);
4044

4145
v8::Local<v8::Object> LoadData(v8::Isolate *isolate, const std::string& path);
4246

@@ -48,6 +52,8 @@ namespace tns
4852

4953
void SaveScriptCache(const v8::ScriptCompiler::Source& source, const std::string& path);
5054

55+
ModulePathKind GetModulePathKind(const std::string& path);
56+
5157
static jclass MODULE_CLASS;
5258
static jmethodID RESOLVE_PATH_METHOD_ID;
5359
static const char* MODULE_PROLOGUE;
@@ -57,22 +63,24 @@ namespace tns
5763
v8::Persistent<v8::Function> *m_requireFunction;
5864
v8::Persistent<v8::Function> *m_requireFactoryFunction;
5965
std::map<std::string, v8::Persistent<v8::Function>*> m_requireCache;
60-
std::map<std::string, v8::Persistent<v8::Object>*> m_loadedModules;
66+
std::map<std::string, ModuleCacheEntry> m_loadedModules;
6167

6268
class TempModule
6369
{
6470
public:
65-
TempModule(Module* module, const std::string& modulePath, v8::Persistent<v8::Object> *poModuleObj)
66-
:m_module(module), m_dispose(true), m_modulePath(modulePath), m_poModuleObj(poModuleObj)
71+
TempModule(Module* module, const std::string& modulePath, const std::string& cacheKey, v8::Persistent<v8::Object> *poModuleObj)
72+
:m_module(module), m_dispose(true), m_modulePath(modulePath), m_cacheKey(cacheKey), m_poModuleObj(poModuleObj)
6773
{
68-
m_module->m_loadedModules.insert(make_pair(m_modulePath, m_poModuleObj));
74+
m_module->m_loadedModules.insert(make_pair(m_modulePath, ModuleCacheEntry(m_poModuleObj)));
75+
m_module->m_loadedModules.insert(make_pair(m_cacheKey, ModuleCacheEntry(m_poModuleObj)));
6976
}
7077

7178
~TempModule()
7279
{
7380
if (m_dispose)
7481
{
7582
m_module->m_loadedModules.erase(m_modulePath);
83+
m_module->m_loadedModules.erase(m_cacheKey);
7684
}
7785
}
7886

@@ -85,8 +93,32 @@ namespace tns
8593
bool m_dispose;
8694
Module *m_module;
8795
std::string m_modulePath;
96+
std::string m_cacheKey;
8897
v8::Persistent<v8::Object> *m_poModuleObj;
8998
};
99+
100+
struct ModuleCacheEntry
101+
{
102+
ModuleCacheEntry(v8::Persistent<v8::Object> *_obj)
103+
: obj(_obj), isData(false)
104+
{
105+
}
106+
107+
ModuleCacheEntry(v8::Persistent<v8::Object> *_obj, bool _isData)
108+
: obj(_obj), isData(_isData)
109+
{
110+
}
111+
112+
bool isData;
113+
v8::Persistent<v8::Object> *obj;
114+
};
115+
116+
enum class ModulePathKind
117+
{
118+
Global,
119+
Relative,
120+
Absolute
121+
};
90122
};
91123
}
92124

0 commit comments

Comments
 (0)