Skip to content

Commit 3fd2932

Browse files
committed
feat: add React Native UIKit runtime primitives
1 parent f3d0b3f commit 3fd2932

48 files changed

Lines changed: 27881 additions & 1941 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

HANDOFF.md

Lines changed: 1309 additions & 0 deletions
Large diffs are not rendered by default.

NativeScript/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,7 @@ if(ENABLE_JS_RUNTIME)
323323
runtime/modules/app/App.mm
324324
runtime/modules/web/Web.mm
325325
runtime/NativeScript.mm
326+
cli/BundleLoader.mm
326327
runtime/RuntimeConfig.cpp
327328
runtime/modules/url/ada/ada.cpp
328329
runtime/modules/url/URL.cpp

NativeScript/cli/BundleLoader.mm

Lines changed: 101 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,148 @@
11
#include "BundleLoader.h"
22
#include <Foundation/Foundation.h>
3+
#include <mach-o/dyld.h>
4+
#include <stdlib.h>
35

46
// Check if Resources/app/ exists, then load package.json["main"] || app/index.js full file path
57

6-
std::string resolveMainPath() {
8+
static NSString* resourcesPathForExecutable(NSString* executablePath) {
9+
if (executablePath == nil || [executablePath length] == 0) {
10+
return nil;
11+
}
12+
13+
NSString* standardizedPath = [executablePath stringByStandardizingPath];
14+
NSString* macOSPath = [standardizedPath stringByDeletingLastPathComponent];
15+
NSString* contentsPath = [macOSPath stringByDeletingLastPathComponent];
16+
if ([[macOSPath lastPathComponent] isEqualToString:@"MacOS"] &&
17+
[[contentsPath lastPathComponent] isEqualToString:@"Contents"]) {
18+
return [contentsPath stringByAppendingPathComponent:@"Resources"];
19+
}
20+
21+
return nil;
22+
}
23+
24+
static bool shouldLogBundleResolution() {
25+
return getenv("NS_BUNDLE_LOADER_DEBUG") != nullptr;
26+
}
27+
28+
static void addCandidatePath(NSMutableArray<NSString*>* candidates, NSString* path) {
29+
if (path == nil || [path length] == 0) {
30+
return;
31+
}
32+
33+
NSString* standardizedPath = [path stringByStandardizingPath];
34+
if (![candidates containsObject:standardizedPath]) {
35+
[candidates addObject:standardizedPath];
36+
}
37+
}
38+
39+
static std::string resolveMainPathInResources(NSString* resourcesPath) {
740
NSFileManager* fileManager = [NSFileManager defaultManager];
8-
NSString* resourcesPath = [[NSBundle mainBundle] resourcePath];
941
NSString* appPath = [resourcesPath stringByAppendingPathComponent:@"app"];
1042
BOOL isDir;
1143

1244
if ([fileManager fileExistsAtPath:appPath isDirectory:&isDir] && isDir) {
45+
if (shouldLogBundleResolution()) {
46+
NSLog(@"NativeScript BundleLoader checking app path: %@", appPath);
47+
}
1348
NSString* packageJsonPath = [appPath stringByAppendingPathComponent:@"package.json"];
1449
if ([fileManager fileExistsAtPath:packageJsonPath]) {
1550
NSData* jsonData = [NSData dataWithContentsOfFile:packageJsonPath];
16-
NSError* error;
51+
NSError* error = nil;
1752
NSDictionary* packageDict = [NSJSONSerialization JSONObjectWithData:jsonData
1853
options:0
1954
error:&error];
2055
if (error == nil) {
2156
NSString* mainEntry = packageDict[@"main"];
57+
if (shouldLogBundleResolution()) {
58+
NSLog(@"NativeScript BundleLoader package main: %@ from %@", mainEntry, packageJsonPath);
59+
}
2260
if (mainEntry != nil) {
2361
NSString* mainPath = [appPath stringByAppendingPathComponent:mainEntry];
2462
if ([fileManager fileExistsAtPath:mainPath]) {
63+
if (shouldLogBundleResolution()) {
64+
NSLog(@"NativeScript BundleLoader resolved main: %@", mainPath);
65+
}
2566
return std::string([mainPath UTF8String]);
2667
}
2768

2869
if ([[mainEntry pathExtension] length] == 0) {
2970
NSString* mainPathMjs = [mainPath stringByAppendingPathExtension:@"mjs"];
3071
if ([fileManager fileExistsAtPath:mainPathMjs]) {
72+
if (shouldLogBundleResolution()) {
73+
NSLog(@"NativeScript BundleLoader resolved main: %@", mainPathMjs);
74+
}
3175
return std::string([mainPathMjs UTF8String]);
3276
}
3377

3478
NSString* mainPathJs = [mainPath stringByAppendingPathExtension:@"js"];
3579
if ([fileManager fileExistsAtPath:mainPathJs]) {
80+
if (shouldLogBundleResolution()) {
81+
NSLog(@"NativeScript BundleLoader resolved main: %@", mainPathJs);
82+
}
3683
return std::string([mainPathJs UTF8String]);
3784
}
3885
}
3986
}
87+
} else if (shouldLogBundleResolution()) {
88+
NSLog(@"NativeScript BundleLoader failed to parse %@: %@", packageJsonPath, error);
4089
}
4190
}
4291

4392
// Fallback to app/index.js
4493
NSString* indexPath = [appPath stringByAppendingPathComponent:@"index.js"];
4594
if ([fileManager fileExistsAtPath:indexPath]) {
95+
if (shouldLogBundleResolution()) {
96+
NSLog(@"NativeScript BundleLoader resolved fallback main: %@", indexPath);
97+
}
4698
return std::string([indexPath UTF8String]);
4799
}
100+
} else if (shouldLogBundleResolution()) {
101+
NSLog(@"NativeScript BundleLoader skipped resources path: %@ appPath=%@ exists=%d isDir=%d",
102+
resourcesPath,
103+
appPath,
104+
[fileManager fileExistsAtPath:appPath],
105+
isDir);
106+
}
107+
108+
return "";
109+
}
110+
111+
std::string resolveMainPath() {
112+
NSMutableArray<NSString*>* candidates = [NSMutableArray array];
113+
addCandidatePath(candidates, [[NSBundle mainBundle] resourcePath]);
114+
addCandidatePath(candidates, resourcesPathForExecutable([[NSBundle mainBundle] executablePath]));
115+
116+
NSArray<NSString*>* arguments = [[NSProcessInfo processInfo] arguments];
117+
if ([arguments count] > 0) {
118+
addCandidatePath(candidates, resourcesPathForExecutable([arguments objectAtIndex:0]));
119+
}
120+
121+
uint32_t executablePathLength = 0;
122+
_NSGetExecutablePath(nullptr, &executablePathLength);
123+
if (executablePathLength > 0) {
124+
char* executablePathBuffer = static_cast<char*>(malloc(executablePathLength));
125+
if (executablePathBuffer != nullptr) {
126+
if (_NSGetExecutablePath(executablePathBuffer, &executablePathLength) == 0) {
127+
addCandidatePath(candidates, resourcesPathForExecutable([NSString stringWithUTF8String:executablePathBuffer]));
128+
}
129+
free(executablePathBuffer);
130+
}
131+
}
132+
133+
NSString* currentDirectory = [[NSFileManager defaultManager] currentDirectoryPath];
134+
addCandidatePath(candidates, currentDirectory);
135+
addCandidatePath(candidates, [currentDirectory stringByAppendingPathComponent:@"Resources"]);
136+
addCandidatePath(candidates, [[currentDirectory stringByDeletingLastPathComponent] stringByAppendingPathComponent:@"Resources"]);
137+
138+
for (NSString* resourcesPath in candidates) {
139+
if (shouldLogBundleResolution()) {
140+
NSLog(@"NativeScript BundleLoader candidate resources: %@", resourcesPath);
141+
}
142+
std::string mainPath = resolveMainPathInResources(resourcesPath);
143+
if (!mainPath.empty()) {
144+
return mainPath;
145+
}
48146
}
49147

50148
return "";

NativeScript/ffi/hermes/NativeApiJsiReactNative.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,8 @@ inline NativeApiJsiConfig MakeReactNativeNativeApiJsiConfig(
6262
config.metadataPath = metadataPath;
6363
config.metadataPtr = metadataPtr;
6464
config.globalName = globalName;
65-
config.installGlobalSymbols = true;
65+
config.installGlobalSymbols = false;
66+
config.indexRuntimePointers = false;
6667
config.invokeCallbacksOnNativeCallerThread = true;
6768
config.scheduler = std::make_shared<ReactNativeCallInvokerScheduler>(
6869
std::move(jsInvoker), std::move(uiInvoker));

NativeScript/ffi/shared/NativeApiBackendConfig.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,10 @@ struct NativeApiBackendConfig {
2323
std::function<void(std::function<void()>)> runtimeCallbackInvoker = nullptr;
2424
std::function<void(std::function<void()>)> jsThreadCallbackInvoker = nullptr;
2525
std::function<void(std::function<void()>)> jsThreadAsyncCallbackInvoker = nullptr;
26+
std::function<bool()> callbackInvocationAllowed = nullptr;
2627
bool invokeCallbacksOnNativeCallerThread = false;
2728
bool installGlobalSymbols = false;
29+
bool indexRuntimePointers = true;
2830
};
2931

3032
} // namespace nativescript

0 commit comments

Comments
 (0)