Skip to content

Commit db025af

Browse files
committed
simplify loading nativescript node-api native addon, implement timers in hermes runtime, fix initializers returning null, hermes runtime can load .node files
1 parent 9d01da1 commit db025af

File tree

8 files changed

+134
-33
lines changed

8 files changed

+134
-33
lines changed

packages/macos/lib/native.js

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -20,24 +20,16 @@ if (typeof interop === "undefined") {
2020
metaURL = "file://" + metaURL;
2121
}
2222

23-
let functions;
24-
if (typeof Deno === "object") {
25-
const { dlopen } = await import("node:process");
26-
functions = dlopen(
27-
{ exports: {} },
28-
new URL(path, metaURL).pathname,
29-
).exports;
30-
} else {
31-
functions = {};
32-
process.dlopen(
33-
{ exports: functions },
34-
new URL(path, metaURL).pathname,
35-
);
36-
}
23+
const module = { exports: {} };
24+
25+
// deno-lint-ignore no-process-globals
26+
process.dlopen(
27+
module,
28+
new URL(path, metaURL).pathname,
29+
);
3730

38-
functions.init(
39-
typeof Deno === "object"
40-
? Deno.env.get("METADATA_PATH")
41-
: process.env.METADATA_PATH,
31+
module.exports.init(
32+
// deno-lint-ignore no-process-globals
33+
process.env.METADATA_PATH,
4234
);
4335
}

runtime/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ elseif(TARGET_PLATFORM STREQUAL "macos")
4343
set(CMAKE_OSX_DEPLOYMENT_TARGET "13.0")
4444
set(TARGET_PLATFORM_MACOS TRUE)
4545
set(SDK_NAME "macosx")
46-
set(CMAKE_OSX_ARCHITECTURES "arm64")
46+
set(CMAKE_OSX_ARCHITECTURES "arm64;x86_64")
4747
set(NS_BRIDGE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../packages/macos/build/macos/Release)
4848
set(TARGET_PLATFORM_SPEC "macos-arm64_x86_64")
4949
else()

runtime/include/Require.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ class Require {
1111
static Require *init(napi_env env, std::string &path, std::string &tilde);
1212

1313
static napi_value createRequire(napi_env env, std::string &path,
14-
std::string &tilde, Require **pRequire = nullptr);
14+
std::string &tilde,
15+
Require **pRequire = nullptr);
1516

1617
static void finalize(napi_env env, void *data, void *hint);
1718

runtime/include/Timers.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#ifndef TIMERS_H
22
#define TIMERS_H
33

4-
#include "js_native_api.h"
4+
#include "js_native_api_types.h"
55

66
namespace charon {
77

@@ -10,6 +10,8 @@ class Timers {
1010
static void init(napi_env env);
1111

1212
static napi_value setTimeout(napi_env env, napi_callback_info cbinfo);
13+
static napi_value setInterval(napi_env env, napi_callback_info cbinfo);
14+
static napi_value clearTimer(napi_env env, napi_callback_info cbinfo);
1315
};
1416

1517
} // namespace charon

runtime/src/Require.cpp

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
#include "Require.h"
22
#include "NapiUtil.h"
3-
#include "js_native_api.h"
3+
#include <dlfcn.h>
44
#include <iostream>
55
#include <string>
6-
#include <dlfcn.h>
76

87
napi_value Require::createRequire(napi_env env, std::string &path,
98
std::string &tilde, Require **pRequire) {
@@ -83,7 +82,8 @@ typedef napi_value napi_module_register_fn(napi_env env, napi_value exports);
8382
napi_value Require::require(napi_env env, std::string &spec) {
8483
std::string path = resolve(spec);
8584

86-
if (path.ends_with(".node") || path.ends_with(".dylib") || path.ends_with(".so")) {
85+
if (path.ends_with(".node") || path.ends_with(".dylib") ||
86+
path.ends_with(".so")) {
8787
void *handle = dlopen(path.c_str(), RTLD_GLOBAL | RTLD_LAZY);
8888
if (!handle) {
8989
std::cerr << "error in dlopen: " << dlerror() << std::endl;
@@ -177,15 +177,9 @@ napi_value Require::require(napi_env env, std::string &spec) {
177177
napi_create_string_utf8(env, dirname.c_str(), NAPI_AUTO_LENGTH, &__dirname);
178178

179179
napi_value argv[5] = {exports, require, module, __filename, __dirname};
180-
181-
// std::cout << "napi_call_function(env: " << env << ", global: " << global << ", func: " << func << ", argc: 5, argv: " << argv[0] << ", " << argv[1] << ", " << argv[2] << ", " << argv[3] << ", " << argv[4] << ", result: " << result << std::endl;
182-
183-
std::cout << "require eval: " << path << std::endl;
184-
180+
185181
status = napi_call_function(env, global, func, 5, argv, &result);
186182

187-
std::cout << "require eval done: " << path << std::endl;
188-
189183
if (status != napi_ok) {
190184
const napi_extended_error_info *info;
191185
napi_get_last_error_info(env, &info);

runtime/src/Timers.mm

Lines changed: 92 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#include "Timers.h"
55
#import <Foundation/Foundation.h>
6+
#include <objc/runtime.h>
67

78
namespace charon {
89

@@ -22,9 +23,39 @@
2223
.attributes = napi_default,
2324
.data = nullptr,
2425
},
26+
{
27+
.utf8name = "setInterval",
28+
.name = nullptr,
29+
.method = setInterval,
30+
.getter = nullptr,
31+
.setter = nullptr,
32+
.value = nullptr,
33+
.attributes = napi_default,
34+
.data = nullptr,
35+
},
36+
{
37+
.utf8name = "clearTimeout",
38+
.name = nullptr,
39+
.method = clearTimer,
40+
.getter = nullptr,
41+
.setter = nullptr,
42+
.value = nullptr,
43+
.attributes = napi_default,
44+
.data = nullptr,
45+
},
46+
{
47+
.utf8name = "clearInterval",
48+
.name = nullptr,
49+
.method = clearTimer,
50+
.getter = nullptr,
51+
.setter = nullptr,
52+
.value = nullptr,
53+
.attributes = napi_default,
54+
.data = nullptr,
55+
},
2556
};
2657

27-
napi_define_properties(env, global, 1, properties);
58+
napi_define_properties(env, global, 4, properties);
2859
}
2960

3061
napi_value Timers::setTimeout(napi_env env, napi_callback_info cbinfo) {
@@ -42,16 +73,21 @@
4273

4374
NSTimer *timer = [NSTimer
4475
timerWithTimeInterval:interval
45-
repeats:false
76+
repeats:NO
4677
block:^(NSTimer *timer) {
4778
napi_value global, callbackValue;
4879
napi_get_global(env, &global);
4980
napi_get_reference_value(env, callback, &callbackValue);
5081
napi_call_function(env, global, callbackValue, 0,
5182
nullptr, nullptr);
5283
napi_delete_reference(env, callback);
84+
objc_setAssociatedObject(timer, "callback", nil,
85+
OBJC_ASSOCIATION_ASSIGN);
5386
}];
5487

88+
objc_setAssociatedObject(timer, "callback", (id)callback,
89+
OBJC_ASSOCIATION_ASSIGN);
90+
5591
napi_value result;
5692
napi_create_int64(env, (int64_t)timer, &result);
5793

@@ -60,6 +96,60 @@
6096
return result;
6197
}
6298

99+
napi_value Timers::setInterval(napi_env env, napi_callback_info cbinfo) {
100+
size_t argc = 2;
101+
napi_value argv[2];
102+
napi_get_cb_info(env, cbinfo, &argc, argv, nullptr, nullptr);
103+
104+
double ms;
105+
napi_get_value_double(env, argv[1], &ms);
106+
107+
NSTimeInterval interval = ms / 1000;
108+
109+
napi_ref callback;
110+
napi_create_reference(env, argv[0], 1, &callback);
111+
112+
NSTimer *timer = [NSTimer
113+
timerWithTimeInterval:interval
114+
repeats:YES
115+
block:^(NSTimer *timer) {
116+
napi_value global, callbackValue;
117+
napi_get_global(env, &global);
118+
napi_get_reference_value(env, callback, &callbackValue);
119+
napi_call_function(env, global, callbackValue, 0,
120+
nullptr, nullptr);
121+
}];
122+
123+
objc_setAssociatedObject(timer, "callback", (id)callback,
124+
OBJC_ASSOCIATION_ASSIGN);
125+
126+
napi_value result;
127+
napi_create_int64(env, (int64_t)timer, &result);
128+
129+
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
130+
131+
return result;
132+
}
133+
134+
napi_value Timers::clearTimer(napi_env env, napi_callback_info cbinfo) {
135+
size_t argc = 1;
136+
napi_value argv[1];
137+
napi_get_cb_info(env, cbinfo, &argc, argv, nullptr, nullptr);
138+
139+
int64_t timer;
140+
napi_get_value_int64(env, argv[0], &timer);
141+
142+
NSTimer *t = (NSTimer *)timer;
143+
[t invalidate];
144+
145+
napi_ref callback = (napi_ref)objc_getAssociatedObject(t, "callback");
146+
if (callback != nil) {
147+
napi_delete_reference(env, callback);
148+
}
149+
150+
return nullptr;
151+
}
152+
63153
} // namespace charon
64154

65155
#endif // __APPLE__

runtime/test.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,24 @@ const { test } = require("./mod.js");
44

55
test();
66

7+
const id = setTimeout(() => {
8+
console.log("timeout");
9+
}, 1000);
10+
11+
clearTimeout(id);
12+
13+
const int = setInterval(() => {
14+
console.log("interval");
15+
}, 1000);
16+
17+
setTimeout(() => {
18+
clearInterval(int);
19+
}, 5000);
20+
721
console.log(new Error().stack);
822

23+
NSApplicationMain(0, null);
24+
925
// const timer = NSTimer.scheduledTimerWithTimeIntervalRepeatsBlock(1, true, () => {
1026
// console.log("timer");
1127
// timer.invalidate();

src/ClassMember.mm

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,12 @@ inline void objcNativeCall(napi_env env, napi_value jsThis, Cif *cif, id self,
254254
}
255255
}
256256

257+
if (rvalue == nil) {
258+
napi_value result;
259+
napi_get_null(env, &result);
260+
return result;
261+
}
262+
257263
napi_value constructor = jsThis;
258264
if (!method->classMethod)
259265
napi_get_named_property(env, jsThis, "constructor", &constructor);

0 commit comments

Comments
 (0)