Skip to content

Commit 7ab180a

Browse files
authored
feat: allow embedding into existing apple host projects (#231)
1 parent 4cd869d commit 7ab180a

13 files changed

+191
-22
lines changed

NativeScript/NativeScript.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@
1515
@interface NativeScript : NSObject
1616

1717
- (instancetype)initWithConfig:(Config*)config;
18+
- (void)runScriptString: (NSString*) script runLoop: (BOOL) runLoop;
19+
- (void)restartWithConfig:(Config*)config;
20+
- (void)shutdownRuntime;
21+
1822
/**
1923
WARNING: this method does not return in most applications. (UIApplicationMain)
2024
*/

NativeScript/NativeScript.mm

Lines changed: 54 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,63 @@ @implementation Config
2121

2222
@implementation NativeScript
2323

24-
std::unique_ptr<Runtime> runtime_;
24+
extern char defaultStartOfMetadataSection __asm("section$start$__DATA$__TNSMetadata");
2525

26-
- (instancetype)initWithConfig:(Config*)config {
26+
- (void)runScriptString: (NSString*) script runLoop: (BOOL) runLoop {
27+
28+
std::string cppString = std::string([script UTF8String]);
29+
runtime_->RunScript(cppString);
2730

31+
if (runLoop) {
32+
CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, true);
33+
}
34+
35+
36+
tns::Tasks::Drain();
37+
38+
}
39+
40+
std::unique_ptr<Runtime> runtime_;
41+
42+
- (void)runMainApplication {
43+
runtime_->RunMainScript();
44+
45+
CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, true);
46+
tns::Tasks::Drain();
47+
}
48+
49+
- (bool)liveSync {
50+
if (runtime_ == nullptr) {
51+
return false;
52+
}
53+
54+
Isolate* isolate = runtime_->GetIsolate();
55+
return tns::LiveSync(isolate);
56+
}
57+
58+
- (void)shutdownRuntime {
59+
if (RuntimeConfig.IsDebug) {
60+
Console::DetachInspectorClient();
61+
}
62+
tns::Tasks::ClearTasks();
63+
if (runtime_ != nullptr) {
64+
runtime_ = nullptr;
65+
}
66+
}
67+
68+
- (instancetype)initializeWithConfig:(Config*)config {
2869
if (self = [super init]) {
2970
RuntimeConfig.BaseDir = [config.BaseDir UTF8String];
3071
if (config.ApplicationPath != nil) {
3172
RuntimeConfig.ApplicationPath = [[config.BaseDir stringByAppendingPathComponent:config.ApplicationPath] UTF8String];
3273
} else {
3374
RuntimeConfig.ApplicationPath = [[config.BaseDir stringByAppendingPathComponent:@"app"] UTF8String];
3475
}
35-
RuntimeConfig.MetadataPtr = [config MetadataPtr];
76+
if (config.MetadataPtr != nil) {
77+
RuntimeConfig.MetadataPtr = [config MetadataPtr];
78+
} else {
79+
RuntimeConfig.MetadataPtr = &defaultStartOfMetadataSection;
80+
}
3681
RuntimeConfig.IsDebug = [config IsDebug];
3782
RuntimeConfig.LogToSystemConsole = [config LogToSystemConsole];
3883

@@ -58,26 +103,19 @@ - (instancetype)initWithConfig:(Config*)config {
58103
Console::AttachInspectorClient(inspectorClient);
59104
}
60105
}
61-
62106
return self;
63107

64108
}
65109

66-
- (void)runMainApplication {
67-
runtime_->RunMainScript();
68-
69-
CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, true);
110+
- (instancetype)initWithConfig:(Config*)config {
111+
return [self initializeWithConfig:config];
112+
}
70113

71-
tns::Tasks::Drain();
114+
- (void)restartWithConfig:(Config*)config {
115+
[self shutdownRuntime];
116+
[self initializeWithConfig:config];
72117
}
73118

74-
- (bool)liveSync {
75-
if (runtime_ == nullptr) {
76-
return false;
77-
}
78119

79-
Isolate* isolate = runtime_->GetIsolate();
80-
return tns::LiveSync(isolate);
81-
}
82120

83121
@end

NativeScript/metadata-arm64.bin

8.41 MB
Binary file not shown.

NativeScript/runtime/Console.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ void Console::AttachInspectorClient(v8_inspector::JsV8InspectorClient* aInspecto
3939
inspector = aInspector;
4040
}
4141

42+
void Console::DetachInspectorClient() {
43+
inspector = nullptr;
44+
}
45+
4246
void Console::LogCallback(const FunctionCallbackInfo<Value>& args) {
4347
// TODO: implement 'forceLog' override option like android has, to force logs in prod if desired
4448
if (!RuntimeConfig.LogToSystemConsole) {

NativeScript/runtime/Console.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ class Console {
1111
public:
1212
static void Init(v8::Local<v8::Context> context);
1313
static void AttachInspectorClient(v8_inspector::JsV8InspectorClient* inspector);
14+
static void DetachInspectorClient();
1415
private:
1516
using ConsoleAPIType = v8_inspector::ConsoleAPIType;
1617

NativeScript/runtime/ModuleInternal.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ class ModuleInternal {
1010
public:
1111
ModuleInternal(v8::Local<v8::Context> context);
1212
bool RunModule(v8::Isolate* isolate, std::string path);
13+
void RunScript(v8::Isolate* isolate, std::string script);
14+
1315
private:
1416
static void RequireCallback(const v8::FunctionCallbackInfo<v8::Value>& info);
1517
v8::Local<v8::Function> GetRequireFunction(v8::Isolate* isolate, const std::string& dirName);
@@ -23,6 +25,8 @@ class ModuleInternal {
2325
v8::ScriptCompiler::CachedData* LoadScriptCache(const std::string& path);
2426
void SaveScriptCache(const v8::Local<v8::Script> script, const std::string& path);
2527
std::string GetCacheFileName(const std::string& path);
28+
v8::MaybeLocal<v8::Value> RunScriptString(v8::Isolate* isolate, v8::Local<v8::Context> context, const std::string script);
29+
2630

2731
std::unique_ptr<v8::Persistent<v8::Function>> requireFunction_;
2832
std::unique_ptr<v8::Persistent<v8::Function>> requireFactoryFunction_;

NativeScript/runtime/ModuleInternal.mm

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,28 @@
283283
return script;
284284
}
285285

286+
MaybeLocal<Value> ModuleInternal::RunScriptString(Isolate* isolate, Local<Context> context, const std::string scriptString) {
287+
ScriptCompiler::CompileOptions options = ScriptCompiler::kNoCompileOptions;
288+
ScriptCompiler::Source source(tns::ToV8String(isolate, scriptString));
289+
TryCatch tc(isolate);
290+
Local<Script> script = ScriptCompiler::Compile(context, &source, options).ToLocalChecked();
291+
MaybeLocal<Value> result = script->Run(context);
292+
return result;
293+
}
294+
295+
296+
void ModuleInternal::RunScript(Isolate* isolate, std::string script) {
297+
std::shared_ptr<Caches> cache = Caches::Get(isolate);
298+
Local<Context> context = cache->GetContext();
299+
Local<Object> globalObject = context->Global();
300+
Local<Value> requireObj;
301+
bool success = globalObject->Get(context, ToV8String(isolate, "require")).ToLocal(&requireObj);
302+
tns::Assert(success && requireObj->IsFunction(), isolate);
303+
Local<Value> result;
304+
this->RunScriptString(isolate, context, script);
305+
}
306+
307+
286308
Local<v8::String> ModuleInternal::WrapModuleContent(Isolate* isolate, const std::string& path) {
287309
return tns::ReadModule(isolate, path);
288310
}

NativeScript/runtime/Runtime.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ class Runtime {
3131
}
3232

3333
void RunModule(const std::string moduleName);
34+
35+
void RunScript(const std::string script);
3436

3537
static void Initialize();
3638

NativeScript/runtime/Runtime.mm

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,15 @@ void DisposeIsolateWhenPossible(Isolate* isolate) {
303303
this->moduleInternal_->RunModule(isolate, moduleName);
304304
}
305305

306+
void Runtime::RunScript(const std::string script) {
307+
Isolate* isolate = this->GetIsolate();
308+
v8::Locker locker(isolate);
309+
Isolate::Scope isolate_scope(isolate);
310+
HandleScope handle_scope(isolate);
311+
this->moduleInternal_->RunScript(isolate, script);
312+
}
313+
314+
306315
Isolate* Runtime::GetIsolate() {
307316
return this->isolate_;
308317
}

NativeScript/runtime/Tasks.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ void Tasks::Drain() {
1616
}
1717
}
1818

19+
void Tasks::ClearTasks() {
20+
tasks_.clear();
21+
}
22+
1923
std::vector<std::function<void()>> Tasks::tasks_;
2024

2125
}

NativeScript/runtime/Tasks.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ class Tasks {
1010
public:
1111
static void Register(std::function<void()> task);
1212
static void Drain();
13+
static void ClearTasks();
1314
private:
1415
static std::vector<std::function<void()>> tasks_;
1516
};

build_nativescript.sh

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,20 @@ xcodebuild -project v8ios.xcodeproj \
6161
-configuration Release clean \
6262
$QUIET
6363

64+
if $BUILD_CATALYST; then
65+
checkpoint "Building NativeScript for Mac Catalyst"
66+
xcodebuild archive -project v8ios.xcodeproj \
67+
-scheme "NativeScript" \
68+
-configuration Release \
69+
-destination "platform=macOS,variant=Mac Catalyst" \
70+
$QUIET \
71+
EXCLUDED_ARCHS="x86_64" \
72+
SKIP_INSTALL=NO \
73+
BUILD_LIBRARIES_FOR_DISTRIBUTION=YES \
74+
INCLUDE_DEFAULT_METADATA=$INCLUDE_DEFAULT_METADATA\
75+
-archivePath $DIST/intermediates/NativeScript.maccatalyst.xcarchive
76+
fi
77+
6478
if $BUILD_SIMULATOR; then
6579
checkpoint "Building NativeScript for iphone simulators (multi-arch)"
6680
xcodebuild archive -project v8ios.xcodeproj \
@@ -71,7 +85,8 @@ xcodebuild archive -project v8ios.xcodeproj \
7185
EXCLUDED_ARCHS="i386" \
7286
DEVELOPMENT_TEAM=$DEV_TEAM \
7387
SKIP_INSTALL=NO \
74-
BUILD_LIBRARY_FOR_DISTRIBUTION=YES \
88+
BUILD_LIBRARIES_FOR_DISTRIBUTION=YES \
89+
INCLUDE_DEFAULT_METADATA=$INCLUDE_DEFAULT_METADATA\
7590
-archivePath $DIST/intermediates/NativeScript.iphonesimulator.xcarchive
7691
fi
7792

@@ -85,7 +100,8 @@ xcodebuild archive -project v8ios.xcodeproj \
85100
EXCLUDED_ARCHS="armv7" \
86101
DEVELOPMENT_TEAM=$DEV_TEAM \
87102
SKIP_INSTALL=NO \
88-
BUILD_LIBRARY_FOR_DISTRIBUTION=YES \
103+
BUILD_LIBRARIES_FOR_DISTRIBUTION=YES \
104+
INCLUDE_DEFAULT_METADATA=$INCLUDE_DEFAULT_METADATA\
89105
-archivePath $DIST/intermediates/NativeScript.iphoneos.xcarchive
90106
fi
91107

0 commit comments

Comments
 (0)