1- #include < Foundation/Foundation.h>
21#include " NativeScript.h"
2+ #include < Foundation/Foundation.h>
33#include " inspector/JsV8InspectorClient.h"
44#include " runtime/Console.h"
5- #include " runtime/RuntimeConfig.h"
65#include " runtime/Helpers.h"
76#include " runtime/Runtime.h"
7+ #include " runtime/RuntimeConfig.h"
88#include " runtime/Tasks.h"
99
1010using namespace v8 ;
1111using namespace tns ;
1212
13+ namespace tns {
14+ // External flag from Runtime.mm to track JavaScript errors
15+ extern bool jsErrorOccurred;
16+ }
17+
1318@implementation Config
1419
1520@synthesize BaseDir;
@@ -23,99 +28,110 @@ @implementation NativeScript
2328
2429extern char defaultStartOfMetadataSection __asm (" section$start$__DATA$__TNSMetadata" );
2530
26- - (void )runScriptString : (NSString *) script runLoop : (BOOL ) runLoop {
31+ - (void )runScriptString : (NSString *)script runLoop : (BOOL )runLoop {
32+ std::string cppString = std::string ([script UTF8String ]);
33+ runtime_->RunScript (cppString);
2734
28- std::string cppString = std::string ([script UTF8String ]);
29- runtime_->RunScript (cppString);
30-
31- if (runLoop) {
32- CFRunLoopRunInMode (kCFRunLoopDefaultMode , 0 , true );
33- }
34-
35-
36- tns::Tasks::Drain ();
35+ if (runLoop) {
36+ CFRunLoopRunInMode (kCFRunLoopDefaultMode , 0 , true );
37+ }
3738
39+ tns::Tasks::Drain ();
3840}
3941
4042std::unique_ptr<Runtime> runtime_;
4143
4244- (void )runMainApplication {
43- runtime_->RunMainScript ();
45+ runtime_->RunMainScript ();
4446
45- CFRunLoopRunInMode (kCFRunLoopDefaultMode , 0 , true );
46- tns::Tasks::Drain ();
47+ // In debug mode, if JavaScript errors occurred, keep the app alive indefinitely
48+ // This prevents iOS from terminating the app and allows hot-reload to work
49+ if (RuntimeConfig.IsDebug && jsErrorOccurred) {
50+ // Log(@"Debug mode - JavaScript errors detected, entering infinite run loop to prevent app termination");
51+
52+ while (true ) {
53+ CFRunLoopRunInMode (kCFRunLoopDefaultMode , 0.1 , true );
54+ tns::Tasks::Drain ();
55+ }
56+ // Note: This line is never reached in debug mode with errors
57+ }
58+
59+ // Normal execution path (no errors or release mode)
60+ CFRunLoopRunInMode (kCFRunLoopDefaultMode , 0 , true );
61+ tns::Tasks::Drain ();
4762}
4863
4964- (bool )liveSync {
50- if (runtime_ == nullptr ) {
51- return false ;
52- }
65+ if (runtime_ == nullptr ) {
66+ return false ;
67+ }
5368
54- Isolate* isolate = runtime_->GetIsolate ();
55- return tns::LiveSync (isolate);
69+ Isolate* isolate = runtime_->GetIsolate ();
70+ return tns::LiveSync (isolate);
5671}
5772
5873- (void )shutdownRuntime {
59- if (RuntimeConfig.IsDebug ) {
60- Console::DetachInspectorClient ();
61- }
62- tns::Tasks::ClearTasks ();
63- if (runtime_ != nullptr ) {
64- runtime_ = nullptr ;
65- }
74+ if (RuntimeConfig.IsDebug ) {
75+ Console::DetachInspectorClient ();
76+ }
77+ tns::Tasks::ClearTasks ();
78+ if (runtime_ != nullptr ) {
79+ runtime_ = nullptr ;
80+ }
6681}
6782
6883- (instancetype )initializeWithConfig : (Config*)config {
69- if (self = [super init ]) {
70- RuntimeConfig.BaseDir = [config.BaseDir UTF8String ];
71- if (config.ApplicationPath != nil ) {
72- RuntimeConfig.ApplicationPath = [[config.BaseDir stringByAppendingPathComponent: config.ApplicationPath] UTF8String ];
73- } else {
74- RuntimeConfig.ApplicationPath = [[config.BaseDir stringByAppendingPathComponent: @" app" ] UTF8String ];
75- }
76- if (config.MetadataPtr != nil ) {
77- RuntimeConfig.MetadataPtr = [config MetadataPtr ];
78- } else {
79- RuntimeConfig.MetadataPtr = &defaultStartOfMetadataSection;
80- }
81- RuntimeConfig.IsDebug = [config IsDebug ];
82- RuntimeConfig.LogToSystemConsole = [config LogToSystemConsole ];
83-
84- Runtime::Initialize ();
85- runtime_ = nullptr ;
86- runtime_ = std::make_unique<Runtime>();
87-
88- std::chrono::high_resolution_clock::time_point t1 = std::chrono::high_resolution_clock::now ();
89- Isolate* isolate = runtime_->CreateIsolate ();
90- v8::Locker l (isolate);
91- runtime_->Init (isolate);
92- std::chrono::high_resolution_clock::time_point t2 = std::chrono::high_resolution_clock::now ();
93- auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(t2 - t1).count ();
94- printf (" Runtime initialization took %llims (version %s, V8 version %s)\n " , duration, NATIVESCRIPT_VERSION, V8::GetVersion ());
95-
96- if (config.IsDebug ) {
97- Isolate::Scope isolate_scope (isolate);
98- HandleScope handle_scope (isolate);
99- v8_inspector::JsV8InspectorClient* inspectorClient = new v8_inspector::JsV8InspectorClient (runtime_.get ());
100- inspectorClient->init ();
101- inspectorClient->registerModules ();
102- inspectorClient->connect ([config ArgumentsCount ], [config Arguments ]);
103- Console::AttachInspectorClient (inspectorClient);
104- }
84+ if (self = [super init ]) {
85+ RuntimeConfig.BaseDir = [config.BaseDir UTF8String ];
86+ if (config.ApplicationPath != nil ) {
87+ RuntimeConfig.ApplicationPath =
88+ [[config.BaseDir stringByAppendingPathComponent: config.ApplicationPath] UTF8String ];
89+ } else {
90+ RuntimeConfig.ApplicationPath =
91+ [[config.BaseDir stringByAppendingPathComponent: @" app" ] UTF8String ];
92+ }
93+ if (config.MetadataPtr != nil ) {
94+ RuntimeConfig.MetadataPtr = [config MetadataPtr ];
95+ } else {
96+ RuntimeConfig.MetadataPtr = &defaultStartOfMetadataSection;
97+ }
98+ RuntimeConfig.IsDebug = [config IsDebug ];
99+ RuntimeConfig.LogToSystemConsole = [config LogToSystemConsole ];
100+
101+ Runtime::Initialize ();
102+ runtime_ = nullptr ;
103+ runtime_ = std::make_unique<Runtime>();
104+
105+ std::chrono::high_resolution_clock::time_point t1 = std::chrono::high_resolution_clock::now ();
106+ Isolate* isolate = runtime_->CreateIsolate ();
107+ v8::Locker l (isolate);
108+ runtime_->Init (isolate);
109+ std::chrono::high_resolution_clock::time_point t2 = std::chrono::high_resolution_clock::now ();
110+ auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(t2 - t1).count ();
111+ printf (" Runtime initialization took %llims (version %s, V8 version %s)\n " , duration,
112+ NATIVESCRIPT_VERSION, V8::GetVersion ());
113+
114+ if (config.IsDebug ) {
115+ Isolate::Scope isolate_scope (isolate);
116+ HandleScope handle_scope (isolate);
117+ v8_inspector::JsV8InspectorClient* inspectorClient =
118+ new v8_inspector::JsV8InspectorClient (runtime_.get ());
119+ inspectorClient->init ();
120+ inspectorClient->registerModules ();
121+ inspectorClient->connect ([config ArgumentsCount ], [config Arguments ]);
122+ Console::AttachInspectorClient (inspectorClient);
105123 }
106- return self;
107-
124+ }
125+ return self;
108126}
109127
110128- (instancetype )initWithConfig : (Config*)config {
111- return [self initializeWithConfig: config];
129+ return [self initializeWithConfig: config];
112130}
113131
114132- (void )restartWithConfig : (Config*)config {
115- [self shutdownRuntime ];
116- [self initializeWithConfig: config];
133+ [self shutdownRuntime ];
134+ [self initializeWithConfig: config];
117135}
118136
119-
120-
121137@end
0 commit comments