Skip to content

Commit 1bd1480

Browse files
committed
metadata generator compatibility and some bug fixes, introduce ObjCClass decorator to runtime
1 parent 14dd828 commit 1bd1480

29 files changed

+1861
-1117
lines changed

NativeScript/CMakeLists.txt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ elseif(TARGET_PLATFORM STREQUAL "ios-sim")
4444
set(TARGET_PLATFORM_IOS TRUE)
4545
set(TARGET_PLATFORM_SIM TRUE)
4646
set(SDK_NAME "iphonesimulator")
47-
set(CMAKE_OSX_ARCHITECTURES "arm64")
47+
set(CMAKE_OSX_ARCHITECTURES "arm64;x86_64")
4848
set(TARGET_PLATFORM_SPEC "ios-arm64_x86_64-simulator")
4949

5050
elseif(TARGET_PLATFORM STREQUAL "macos")
@@ -173,6 +173,11 @@ if(ENABLE_JS_RUNTIME)
173173
elseif(TARGET_ENGINE_QUICKJS)
174174
set(MI_BUILD_OBJECT OFF)
175175
set(MI_OVERRIDE OFF)
176+
set(MI_BUILD_SHARED OFF)
177+
set(MI_BUILD_TESTS OFF)
178+
179+
set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED "NO")
180+
176181
add_subdirectory(napi/quickjs/mimalloc-dev mimalloc)
177182

178183
include_directories(

NativeScript/NativeScript.h

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,31 +5,34 @@
55

66
extern "C"
77

8-
#endif // __cplusplus
8+
#endif // __cplusplus
99

10-
void objc_bridge_init(void *env, const char *metadata_path);
10+
void
11+
objc_bridge_init(void* env, const char* metadata_path, const void* metadata_ptr);
1112

1213
#ifdef __OBJC__
1314

1415
#import <Foundation/Foundation.h>
1516

17+
__attribute__((visibility("default")))
1618
@interface Config : NSObject
1719

18-
@property(nonatomic, retain) NSString *BaseDir;
19-
@property(nonatomic, retain) NSString *ApplicationPath;
20-
@property(nonatomic) void *MetadataPtr;
20+
@property(nonatomic, retain) NSString* BaseDir;
21+
@property(nonatomic, retain) NSString* ApplicationPath;
22+
@property(nonatomic) void* MetadataPtr;
2123
@property BOOL IsDebug;
2224
@property BOOL LogToSystemConsole;
2325
@property int ArgumentsCount;
24-
@property(nonatomic) char **Arguments;
26+
@property(nonatomic) char** Arguments;
2527

2628
@end
2729

30+
__attribute__((visibility("default")))
2831
@interface NativeScript : NSObject
2932

30-
- (instancetype)initWithConfig:(Config *)config;
31-
- (void)runScriptString:(NSString *)script runLoop:(BOOL)runLoop;
32-
- (void)restartWithConfig:(Config *)config;
33+
- (instancetype)initWithConfig:(Config*)config;
34+
- (void)runScriptString:(NSString*)script runLoop:(BOOL)runLoop;
35+
- (void)restartWithConfig:(Config*)config;
3336
- (void)shutdownRuntime;
3437

3538
/**
@@ -40,6 +43,6 @@ void objc_bridge_init(void *env, const char *metadata_path);
4043

4144
@end
4245

43-
#endif // __OBJC__
46+
#endif // __OBJC__
4447

4548
#endif /* NATIVESCRIPT_H */

NativeScript/ffi/Class.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ using namespace metagen;
1313

1414
namespace objc_bridge {
1515

16+
void setupObjCClassDecorator(napi_env env);
17+
1618
void initFastEnumeratorIteratorFactory(napi_env env,
1719
ObjCBridgeState *bridgeState);
1820

NativeScript/ffi/Class.mm

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,27 @@
9999
return nullptr;
100100
}
101101

102+
const char *ObjCClassDecorator = R"(
103+
globalThis.ObjCClass = function ObjCClass(...protocols) {
104+
return function (target) {
105+
if (target.ObjCProtocols) {
106+
target.ObjCProtocols.push(...protocols);
107+
} else {
108+
target.ObjCProtocols = protocols;
109+
}
110+
111+
return globalThis.NativeClass(target);
112+
};
113+
};
114+
)";
115+
116+
void setupObjCClassDecorator(napi_env env) {
117+
napi_value global, script;
118+
napi_get_global(env, &global);
119+
napi_create_string_utf8(env, ObjCClassDecorator, NAPI_AUTO_LENGTH, &script);
120+
napi_run_script(env, script, &global);
121+
}
122+
102123
char class_name[256];
103124

104125
// Get a Bridged Class by metadata offset, creating it if it doesn't exist.

NativeScript/ffi/ObjCBridge.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ typedef enum ObjectOwnership {
4242

4343
class ObjCBridgeState {
4444
public:
45-
ObjCBridgeState(napi_env env, const char *metadata_path = nullptr);
45+
ObjCBridgeState(napi_env env, const char *metadata_path = nullptr, const void *metadata_ptr = nullptr);
4646
~ObjCBridgeState();
4747

4848
static inline ObjCBridgeState *InstanceData(napi_env env) {

NativeScript/ffi/ObjCBridge.mm

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -55,30 +55,35 @@ void finalize_bridge_data(napi_env env, void* data, void* hint) {
5555
auto buffer = (uint8_t*)malloc(size);
5656
fread(buffer, 1, size, f);
5757
fclose(f);
58-
return new MDMetadataReader(buffer, size);
58+
return new MDMetadataReader(buffer);
5959
}
6060

61-
ObjCBridgeState::ObjCBridgeState(napi_env env, const char* metadata_path) {
61+
ObjCBridgeState::ObjCBridgeState(napi_env env, const char* metadata_path,
62+
const void* metadata_ptr) {
6263
napi_set_instance_data(env, this, finalize_bridge_data, nil);
6364

6465
self_dl = dlopen(nullptr, RTLD_NOW);
6566

66-
#ifdef EMBED_METADATA_SIZE
67-
if (metadata_path != nullptr) {
68-
metadata = loadMetadataFromFile(metadata_path);
67+
if (metadata_ptr) {
68+
metadata = new MDMetadataReader((void*)metadata_ptr);
6969
} else {
70-
metadata = new MDMetadataReader((void*)embedded_metadata, EMBED_METADATA_SIZE);
71-
}
70+
#ifdef EMBED_METADATA_SIZE
71+
if (metadata_path != nullptr) {
72+
metadata = loadMetadataFromFile(metadata_path);
73+
} else {
74+
metadata = new MDMetadataReader((void*)embedded_metadata, EMBED_METADATA_SIZE);
75+
}
7276
#else
73-
unsigned long segmentSize = 0;
74-
auto segmentData = getsegmentdata((const mach_header_64*)_dyld_get_image_header(0),
75-
"__objc_metadata", &segmentSize);
76-
if (segmentData != nullptr) {
77-
metadata = new MDMetadataReader(segmentData, segmentSize);
78-
} else {
79-
metadata = loadMetadataFromFile(metadata_path);
80-
}
77+
unsigned long segmentSize = 0;
78+
auto segmentData = getsegmentdata((const mach_header_64*)_dyld_get_image_header(0),
79+
"__objc_metadata", &segmentSize);
80+
if (segmentData != nullptr) {
81+
metadata = new MDMetadataReader(segmentData);
82+
} else {
83+
metadata = loadMetadataFromFile(metadata_path);
84+
}
8185
#endif
86+
}
8287

8388
objc_autoreleasePool = objc_autoreleasePoolPush();
8489
}
@@ -143,7 +148,7 @@ void finalize_bridge_data(napi_env env, void* data, void* hint) {
143148
metadata_path = (char*)malloc(len + 1);
144149
napi_get_value_string_utf8(env, argv[0], (char*)metadata_path, len + 1, &len);
145150
}
146-
objc_bridge_init(env, metadata_path);
151+
objc_bridge_init(env, metadata_path, nullptr);
147152
return nullptr;
148153
}
149154

@@ -153,10 +158,10 @@ void finalize_bridge_data(napi_env env, void* data, void* hint) {
153158
return exports;
154159
}
155160

156-
NAPI_EXPORT void objc_bridge_init(void* _env, const char* metadata_path) {
161+
NAPI_EXPORT void objc_bridge_init(void* _env, const char* metadata_path, const void* metadata_ptr) {
157162
napi_env env = (napi_env)_env;
158163

159-
ObjCBridgeState* bridgeState = new ObjCBridgeState(env, metadata_path);
164+
ObjCBridgeState* bridgeState = new ObjCBridgeState(env, metadata_path, metadata_ptr);
160165

161166
napi_value objc;
162167
napi_create_object(env, &objc);
@@ -202,6 +207,8 @@ NAPI_EXPORT void objc_bridge_init(void* _env, const char* metadata_path) {
202207

203208
napi_define_properties(env, global, 3, globalProperties);
204209

210+
setupObjCClassDecorator(env);
211+
205212
initProxyFactory(env, bridgeState);
206213
initFastEnumeratorIteratorFactory(env, bridgeState);
207214

NativeScript/ffi/Struct.mm

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,8 @@
5252

5353
void ObjCBridgeState::registerUnionGlobals(napi_env env, napi_value global) {
5454
MDSectionOffset offset = metadata->unionsOffset;
55-
while (offset < metadata->size) {
56-
// Sometimes there is padding after file ends.
55+
while (true) {
56+
// It's the last section, always ends with 4 bytes of 0.
5757
if (metadata->getOffset(offset) == 0) break;
5858
MDSectionOffset originalOffset = offset;
5959
auto name = metadata->getString(offset);

NativeScript/napi/v8/v8-api.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -354,10 +354,14 @@ inline napi_status Unwrap(napi_env env, napi_value js_object, void** result,
354354
}
355355

356356
if (obj->IsFunction()) {
357-
obj = obj->Get(context, v8::String::NewFromUtf8(env->isolate, "prototype")
357+
auto newObj = obj->Get(context, v8::String::NewFromUtf8(env->isolate, "prototype")
358358
.ToLocalChecked())
359359
.ToLocalChecked()
360360
.As<v8::Object>();
361+
362+
if (!newObj->IsUndefined()) {
363+
obj = newObj;
364+
}
361365
}
362366

363367
bool isInternalField = obj->InternalFieldCount() > 0;
@@ -375,7 +379,9 @@ inline napi_status Unwrap(napi_env env, napi_value js_object, void** result,
375379
auto pkey = v8::Private::ForApi(
376380
env->isolate,
377381
v8::String::NewFromUtf8(env->isolate, "napi_private").ToLocalChecked());
378-
auto val = obj->GetPrivate(context, pkey).ToLocalChecked();
382+
auto maybe_value = obj->GetPrivate(context, pkey);
383+
CHECK_MAYBE_EMPTY_WITH_PREAMBLE(env, maybe_value, napi_generic_failure);
384+
v8::Local<v8::Value> val = maybe_value.ToLocalChecked();
379385
RETURN_STATUS_IF_FALSE(env, val->IsExternal(), napi_invalid_arg);
380386
reference =
381387
static_cast<v8impl::Reference*>(val.As<v8::External>()->Value());

0 commit comments

Comments
 (0)