Skip to content

Commit cf44fef

Browse files
committed
Merge pull request #141 from NativeScript/plamen5kov/refactor_require
Plamen5kov/refactor require
2 parents f503b69 + df32e10 commit cf44fef

File tree

8 files changed

+152
-201
lines changed

8 files changed

+152
-201
lines changed

src/jni/Constants.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ class Constants
1010

1111
const static char CLASS_NAME_LOCATION_SEPARATOR = '_';
1212

13+
static std::string APP_ROOT_FOLDER_PATH;
14+
1315
private:
1416
Constants() {}
1517
};

src/jni/MetadataNode.cpp

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1201,12 +1201,19 @@ bool MetadataNode::GetExtendLocation(string& extendLocation)
12011201
}
12021202

12031203
string srcFileName = ConvertToString(scriptName);
1204-
std::replace(srcFileName.begin(), srcFileName.end(), '/', '_');
1205-
std::replace(srcFileName.begin(), srcFileName.end(), '.', '_');
1204+
1205+
string hardcodedPathToSkip = Constants::APP_ROOT_FOLDER_PATH;
1206+
1207+
int startIndex = hardcodedPathToSkip.length();
1208+
int strToTakeLen = (srcFileName.length() - startIndex - 3); // 3 refers to .js at the end of file name
1209+
string fullPathToFile = srcFileName.substr(startIndex, strToTakeLen);
1210+
1211+
std::replace(fullPathToFile.begin(), fullPathToFile.end(), '/', '_');
1212+
std::replace(fullPathToFile.begin(), fullPathToFile.end(), '.', '_');
12061213
int lineNumber = frame->GetLineNumber();
12071214
if (lineNumber < 0)
12081215
{
1209-
extendLocationStream << srcFileName.c_str() << " unkown line number";
1216+
extendLocationStream << fullPathToFile.c_str() << " unkown line number";
12101217
extendLocation = extendLocationStream.str();
12111218
return false;
12121219
}
@@ -1219,13 +1226,13 @@ bool MetadataNode::GetExtendLocation(string& extendLocation)
12191226
int column = frame->GetColumn();
12201227
if (column < 0)
12211228
{
1222-
extendLocationStream << srcFileName.c_str() << " line:" << lineNumber << " unkown column number";
1229+
extendLocationStream << fullPathToFile.c_str() << " line:" << lineNumber << " unkown column number";
12231230
extendLocation = extendLocationStream.str();
12241231
return false;
12251232
}
12261233

12271234

1228-
extendLocationStream << "f" << srcFileName.c_str() << "_l" << lineNumber << "_c" << column << "__";
1235+
extendLocationStream << "f" << fullPathToFile.c_str() << "_l" << lineNumber << "_c" << column << "__";
12291236
//DEBUG_WRITE("EXTEND_LOCATION %s", extendLocationStream.str().c_str());
12301237
}
12311238
}

src/jni/NativeScriptRuntime.cpp

Lines changed: 98 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ using namespace v8;
2626
using namespace std;
2727
using namespace tns;
2828

29-
// init
3029
void NativeScriptRuntime::Init(JavaVM *jvm, ObjectManager *objectManager)
3130
{
3231
NativeScriptRuntime::jvm = jvm;
@@ -735,6 +734,103 @@ void NativeScriptRuntime::CreateGlobalCastFunctions(const Handle<ObjectTemplate>
735734
}
736735

737736

737+
void NativeScriptRuntime::CompileAndRun(string modulePath, bool& hasError, Handle<Object>& moduleObj, bool isBootstrapCall)
738+
{
739+
auto isolate = Isolate::GetCurrent();
740+
741+
Local < Value > exportObj = Object::New(isolate);
742+
auto tmpExportObj = new Persistent<Object>(isolate, exportObj.As<Object>());
743+
loadedModules.insert(make_pair(modulePath, tmpExportObj));
744+
745+
TryCatch tc;
746+
747+
auto scriptText = Require::LoadModule(modulePath);
748+
749+
DEBUG_WRITE("Compiling script (module %s)", modulePath.c_str());
750+
Local < String > fullRequiredModulePath = ConvertToV8String(modulePath);
751+
auto script = Script::Compile(scriptText, fullRequiredModulePath);
752+
DEBUG_WRITE("Compiled script (module %s)", modulePath.c_str());
753+
754+
if (ExceptionUtil::GetInstance()->HandleTryCatch(tc, "Script " + modulePath + " contains compilation errors!"))
755+
{
756+
loadedModules.erase(modulePath);
757+
tmpExportObj->Reset();
758+
delete tmpExportObj;
759+
hasError = true;
760+
}
761+
else if (script.IsEmpty())
762+
{
763+
//think about more descriptive message -> [script_name] was empty
764+
DEBUG_WRITE("%s was empty", modulePath.c_str());
765+
}
766+
else
767+
{
768+
DEBUG_WRITE("Running script (module %s)", modulePath.c_str());
769+
770+
TryCatch tcRequire;
771+
772+
Local < Function > f = script->Run().As<Function>();
773+
if (ExceptionUtil::GetInstance()->HandleTryCatch(tc))
774+
{
775+
DEBUG_WRITE("Exception was handled in java code");
776+
}
777+
778+
//this is done so the initial bootstrap function is persistent (and to keep old logic)
779+
if(isBootstrapCall) {
780+
auto persistentAppModule = new Persistent<Object>(isolate, f);
781+
}
782+
783+
auto result = f->Call(Object::New(isolate), 1, &exportObj);
784+
if(ExceptionUtil::GetInstance()->HandleTryCatch(tc))
785+
{
786+
DEBUG_WRITE("Exception was handled in java code");
787+
}
788+
else
789+
{
790+
moduleObj = result.As<Object>();
791+
}
792+
793+
// introducing isBootstrapCall in order to save the flow as it was (latter on we can think about including the following code for the bootstrap (initial) call
794+
if(!isBootstrapCall) {
795+
DEBUG_WRITE("After Running script (module %s)", modulePath.c_str());
796+
797+
if (ExceptionUtil::GetInstance()->HandleTryCatch(tcRequire))
798+
{
799+
loadedModules.erase(modulePath);
800+
tmpExportObj->Reset();
801+
delete tmpExportObj;
802+
hasError = true;
803+
tcRequire.ReThrow();
804+
}
805+
else
806+
{
807+
if (moduleObj.IsEmpty())
808+
{
809+
auto objectTemplate = ObjectTemplate::New();
810+
moduleObj = objectTemplate->NewInstance();
811+
}
812+
813+
DEBUG_WRITE("Script completed (module %s)", modulePath.c_str());
814+
815+
if (!moduleObj->StrictEquals(exportObj))
816+
{
817+
loadedModules.erase(modulePath);
818+
tmpExportObj->Reset();
819+
delete tmpExportObj;
820+
821+
auto persistentModuleObject = new Persistent<Object>(isolate, moduleObj.As<Object>());
822+
823+
loadedModules.insert(make_pair(modulePath, persistentModuleObject));
824+
}
825+
}
826+
}
827+
}
828+
if (tc.HasCaught())
829+
{
830+
tc.ReThrow();
831+
}
832+
}
833+
738834
void NativeScriptRuntime::RequireCallback(const v8::FunctionCallbackInfo<v8::Value>& args)
739835
{
740836
SET_PROFILER_FRAME();
@@ -782,67 +878,7 @@ void NativeScriptRuntime::RequireCallback(const v8::FunctionCallbackInfo<v8::Val
782878

783879
if (it == loadedModules.end())
784880
{
785-
Local<Value> exportObj = Object::New(isolate);
786-
auto tmpExportObj = new Persistent<Object>(isolate, exportObj.As<Object>());
787-
loadedModules.insert(make_pair(modulePath, tmpExportObj));
788-
789-
TryCatch tc;
790-
auto scriptText = Require::LoadModule(modulePath);
791-
792-
DEBUG_WRITE("Compiling script (module %s)", moduleName.c_str());
793-
auto script = Script::Compile(scriptText, args[0].As<String>());
794-
DEBUG_WRITE("Compiled script (module %s)", moduleName.c_str());
795-
796-
if(ExceptionUtil::GetInstance()->HandleTryCatch(tc)){
797-
loadedModules.erase(modulePath);
798-
tmpExportObj->Reset();
799-
delete tmpExportObj;
800-
hasError = true;
801-
}
802-
else {
803-
DEBUG_WRITE("Running script (module %s)", moduleName.c_str());
804-
805-
TryCatch tcRequire;
806-
807-
Local<Function> f = script->Run().As<Function>();
808-
auto result = f->Call(Object::New(isolate), 1, &exportObj);
809-
810-
moduleObj = result.As<Object>();
811-
812-
DEBUG_WRITE("After Running script (module %s)", moduleName.c_str());
813-
814-
if(ExceptionUtil::GetInstance()->HandleTryCatch(tcRequire)){
815-
loadedModules.erase(modulePath);
816-
tmpExportObj->Reset();
817-
delete tmpExportObj;
818-
hasError = true;
819-
tcRequire.ReThrow();
820-
}
821-
else {
822-
if (moduleObj.IsEmpty())
823-
{
824-
auto objectTemplate = ObjectTemplate::New();
825-
moduleObj = objectTemplate->NewInstance();
826-
}
827-
828-
DEBUG_WRITE("Script completed (module %s)", moduleName.c_str());
829-
830-
if (!moduleObj->StrictEquals(exportObj))
831-
{
832-
loadedModules.erase(modulePath);
833-
tmpExportObj->Reset();
834-
delete tmpExportObj;
835-
836-
auto persistentModuleObject = new Persistent<Object>(isolate, moduleObj.As<Object>());
837-
838-
loadedModules.insert(make_pair(modulePath, persistentModuleObject));
839-
}
840-
}
841-
}
842-
if (tc.HasCaught())
843-
{
844-
tc.ReThrow();
845-
}
881+
CompileAndRun(modulePath, hasError, moduleObj, false/*is bootstrap call*/);
846882
}
847883
else
848884
{

src/jni/NativeScriptRuntime.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,8 @@ namespace tns
8888

8989
static void CreateTopLevelNamespaces(const v8::Handle<v8::Object>& global);
9090

91+
static void CompileAndRun(std::string modulePath, bool& hasError, v8::Handle<v8::Object>& moduleObj, bool isBootstrapCall);
92+
9193
static MetadataTreeNode *metadataRoot;
9294

9395
static jclass PlatformClass;

src/jni/com_tns_Platform.cpp

Lines changed: 13 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ int count = 0;
3838
Context::Scope *context_scope = nullptr;
3939
bool tns::LogEnabled = true;
4040
Isolate *g_isolate = nullptr;
41+
std::string Constants::APP_ROOT_FOLDER_PATH = "";
4142

4243
ObjectManager *g_objectManager = nullptr;
4344

@@ -177,78 +178,29 @@ extern "C" void Java_com_tns_Platform_initNativeScript(JNIEnv *_env, jobject obj
177178
PrepareV8Runtime(isolate, env, filesPath, packageName);
178179

179180
NativeScriptRuntime::APP_FILES_DIR = ArgConverter::jstringToString(filesPath);
181+
Constants::APP_ROOT_FOLDER_PATH = NativeScriptRuntime::APP_FILES_DIR + "/app/";
180182
}
181183

182-
extern "C" void Java_com_tns_Platform_runNativeScript(JNIEnv *_env, jobject obj, jstring appModuleName, jstring appCode)
184+
extern "C" void Java_com_tns_Platform_runNativeScript(JNIEnv *_env, jobject obj, jstring appModuleName)
183185
{
184186
JEnv env(_env);
185-
186187
auto isolate = g_isolate;
187188
Isolate::Scope isolate_scope(isolate);
188189

189-
TryCatch tc;
190-
191190
HandleScope handleScope(isolate);
192-
auto context = Local<Context>::New(isolate, *PrimaryContext);
193-
194-
jstring retval;
195-
jboolean isCopy;
196-
197-
const char* code = env.GetStringUTFChars(appCode, &isCopy);
198-
199-
auto cmd = ConvertToV8String(code);
200-
201-
env.ReleaseStringUTFChars(appCode, code);
202-
203-
DEBUG_WRITE("Compiling script");
204191

205-
auto moduleName = ArgConverter::jstringToV8String(appModuleName);
192+
Handle<Object> moduleObject;
193+
string modulePath = ArgConverter::jstringToString(appModuleName);
194+
bool hasError = false;
206195

207-
auto script = Script::Compile(cmd, moduleName);
208-
209-
DEBUG_WRITE("Compile script");
210-
211-
if (ExceptionUtil::GetInstance()->HandleTryCatch(tc, "Bootstrap script has error(s)."))
212-
{
213-
DEBUG_WRITE("Exception was handled in java code");
214-
}
215-
else if (script.IsEmpty())
216-
{
217-
DEBUG_WRITE("Bootstrap was empty");
218-
}
219-
else
220-
{
221-
DEBUG_WRITE("Running script");
222-
223-
auto appModuleObj = script->Run();
224-
if (ExceptionUtil::GetInstance()->HandleTryCatch(tc))
225-
{
226-
DEBUG_WRITE("Exception was handled in java code");
227-
}
228-
else if (!appModuleObj.IsEmpty() && appModuleObj->IsFunction())
229-
{
230-
auto moduleFunc = appModuleObj.As<Function>();
231-
Handle<Value> exportsObj = Object::New(isolate);
232-
auto thiz = Object::New(isolate);
233-
auto res = moduleFunc->Call(thiz, 1, &exportsObj);
234-
235-
if(ExceptionUtil::GetInstance()->HandleTryCatch(tc))
236-
{
237-
DEBUG_WRITE("Exception was handled in java code");
238-
}
239-
else
240-
{
241-
// TODO: Why do we need this line?
242-
auto persistentAppModuleObject = new Persistent<Object>(Isolate::GetCurrent(), appModuleObj.As<Object>());
243-
}
244-
}
245-
else
246-
{
247-
ExceptionUtil::GetInstance()->ThrowExceptionToJava(tc, "Error running NativeScript bootstrap code.");
248-
}
249-
}
196+
NativeScriptRuntime::CompileAndRun(modulePath, hasError, moduleObject, true /*is bootstrap call*/);
250197

251-
//NativeScriptRuntime::loadedModules.insert(make_pair(appModuleName, persistentAppModuleObject));
198+
/*
199+
* moduleObject (export module) can be set to js variable but currently we start the script implicitly without returning the moduleObject (just calling it)
200+
*
201+
* we can do something like
202+
* var appModule = require("app"); //but currently we call the appModule only once Platform.run() and no one else has access to it
203+
*/
252204

253205
//DEBUG_WRITE("Forcing V8 garbage collection");
254206
//while (!V8::IdleNotification());

0 commit comments

Comments
 (0)