Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions binding.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,7 @@
'./src/shadow_node.cpp',
],
'include_dirs': [
'.',
"<!(node -e \"require('nan')\")",
'<!@(node -p "require(\"node-addon-api\").include")',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I notice that a consistent failure on Actions https://github.com/RobotWebTools/rclnodejs/actions/runs/13857494263/job/38777515813?pr=1088#step:7:25, can you pass the compiling locally?

'<(ros_include_root)',
],
'cflags!': [
Expand Down Expand Up @@ -129,7 +128,11 @@
"defines": ["NODE_RUNTIME_ELECTRON=1"]
}
],
]
],
'dependencies': [
'scripts/config.js',
'<!(node -p "require(\"node-addon-api\").gyp")',
],
}
]
}
57 changes: 25 additions & 32 deletions src/addon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

#include <nan.h>
#include <node_api.h>

#include "macros.hpp"
#include "rcl_action_bindings.hpp"
Expand All @@ -23,18 +23,20 @@
#include "rcutils/macros.h"
#include "shadow_node.hpp"

bool IsRunningInElectronRenderer() {
auto global = Nan::GetCurrentContext()->Global();
auto process =
Nan::To<v8::Object>(Nan::Get(global, Nan::New("process").ToLocalChecked())
.ToLocalChecked())
.ToLocalChecked();
auto process_type =
Nan::Get(process, Nan::New("type").ToLocalChecked()).ToLocalChecked();
return process_type->StrictEquals(Nan::New("renderer").ToLocalChecked());
bool IsRunningInElectronRenderer(napi_env env) {
napi_value global, process, process_type;
napi_get_global(env, &global);
napi_get_named_property(env, global, "process", &process);
napi_get_named_property(env, process, "type", &process_type);

bool is_renderer;
napi_value renderer_str;
napi_create_string_utf8(env, "renderer", NAPI_AUTO_LENGTH, &renderer_str);
napi_strict_equals(env, process_type, renderer_str, &is_renderer);
return is_renderer;
}

void InitModule(v8::Local<v8::Object> exports) {
void InitModule(napi_env env, napi_value exports) {
// workaround process name mangling by chromium
//
// rcl logging uses `program_invocation_name` to determine the log file,
Expand All @@ -43,42 +45,33 @@ void InitModule(v8::Local<v8::Object> exports) {
// occurence of ' -' with the null terminator. see:
// https://unix.stackexchange.com/questions/432419/unexpected-non-null-encoding-of-proc-pid-cmdline
#if defined(__linux__) && defined(__GLIBC__)
if (IsRunningInElectronRenderer()) {
if (IsRunningInElectronRenderer(env)) {
auto prog_name = program_invocation_name;
auto end = strstr(prog_name, " -");
assert(end);
prog_name[end - prog_name] = 0;
}
#endif

v8::Local<v8::Context> context = exports->GetIsolate()->GetCurrentContext();
napi_value context;
napi_get_value_string_utf8(env, exports, "context", &context, NULL, NULL);

for (uint32_t i = 0; i < rclnodejs::binding_methods.size(); i++) {
Nan::Set(
exports, Nan::New(rclnodejs::binding_methods[i].name).ToLocalChecked(),
Nan::New<v8::FunctionTemplate>(rclnodejs::binding_methods[i].function)
->GetFunction(context)
.ToLocalChecked());
napi_value func;
napi_create_function(env, NULL, 0, rclnodejs::binding_methods[i].function, NULL, &func);
napi_set_named_property(env, exports, rclnodejs::binding_methods[i].name, func);
}

for (uint32_t i = 0; i < rclnodejs::action_binding_methods.size(); i++) {
Nan::Set(
exports,
Nan::New(rclnodejs::action_binding_methods[i].name).ToLocalChecked(),
Nan::New<v8::FunctionTemplate>(
rclnodejs::action_binding_methods[i].function)
->GetFunction(context)
.ToLocalChecked());
napi_value func;
napi_create_function(env, NULL, 0, rclnodejs::action_binding_methods[i].function, NULL, &func);
napi_set_named_property(env, exports, rclnodejs::action_binding_methods[i].name, func);
}

for (uint32_t i = 0; i < rclnodejs::lifecycle_binding_methods.size(); i++) {
Nan::Set(
exports,
Nan::New(rclnodejs::lifecycle_binding_methods[i].name).ToLocalChecked(),
Nan::New<v8::FunctionTemplate>(
rclnodejs::lifecycle_binding_methods[i].function)
->GetFunction(context)
.ToLocalChecked());
napi_value func;
napi_create_function(env, NULL, 0, rclnodejs::lifecycle_binding_methods[i].function, NULL, &func);
napi_set_named_property(env, exports, rclnodejs::lifecycle_binding_methods[i].name, func);
}

rclnodejs::ShadowNode::Init(exports);
Expand Down
83 changes: 34 additions & 49 deletions src/rcl_action_bindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,21 +95,16 @@ NAN_METHOD(ActionCreateClient) {
}
}

NAN_METHOD(ActionCreateServer) {
v8::Local<v8::Context> currentContent = Nan::GetCurrentContext();
RclHandle* node_handle = RclHandle::Unwrap<RclHandle>(
Nan::To<v8::Object>(info[0]).ToLocalChecked());
Napi::Value ActionCreateServer(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
RclHandle* node_handle = RclHandle::Unwrap<RclHandle>(info[0].As<Napi::Object>());
rcl_node_t* node = reinterpret_cast<rcl_node_t*>(node_handle->ptr());
RclHandle* clock_handle = RclHandle::Unwrap<RclHandle>(
Nan::To<v8::Object>(info[1]).ToLocalChecked());
RclHandle* clock_handle = RclHandle::Unwrap<RclHandle>(info[1].As<Napi::Object>());
rcl_clock_t* clock = reinterpret_cast<rcl_clock_t*>(clock_handle->ptr());
std::string action_name(
*Nan::Utf8String(info[2]->ToString(currentContent).ToLocalChecked()));
std::string interface_name(
*Nan::Utf8String(info[3]->ToString(currentContent).ToLocalChecked()));
std::string package_name(
*Nan::Utf8String(info[4]->ToString(currentContent).ToLocalChecked()));
int64_t result_timeout = info[10]->IntegerValue(currentContent).FromJust();
std::string action_name = info[2].As<Napi::String>().Utf8Value();
std::string interface_name = info[3].As<Napi::String>().Utf8Value();
std::string package_name = info[4].As<Napi::String>().Utf8Value();
int64_t result_timeout = info[10].As<Napi::Number>().Int64Value();

const rosidl_action_type_support_t* ts =
GetActionTypeSupport(package_name, interface_name);
Expand Down Expand Up @@ -160,29 +155,24 @@ NAN_METHOD(ActionCreateServer) {
THROW_ERROR_IF_NOT_EQUAL(RCL_RET_OK, ret, rcl_get_error_string().str);
});

info.GetReturnValue().Set(js_obj);
return js_obj;
} else {
Nan::ThrowError(GetErrorMessageAndClear().c_str());
Napi::Error::New(env, GetErrorMessageAndClear()).ThrowAsJavaScriptException();
return env.Undefined();
}
}

NAN_METHOD(ActionServerIsAvailable) {
RclHandle* node_handle = RclHandle::Unwrap<RclHandle>(
Nan::To<v8::Object>(info[0]).ToLocalChecked());
rcl_node_t* node = reinterpret_cast<rcl_node_t*>(node_handle->ptr());
RclHandle* action_client_handle = RclHandle::Unwrap<RclHandle>(
Nan::To<v8::Object>(info[1]).ToLocalChecked());
rcl_action_client_t* action_client =
reinterpret_cast<rcl_action_client_t*>(action_client_handle->ptr());
Napi::Value ActionServerIsAvailable(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
RclHandle* action_server_handle = RclHandle::Unwrap<RclHandle>(info[0].As<Napi::Object>());
rcl_action_server_t* action_server =
reinterpret_cast<rcl_action_server_t*>(action_server_handle->ptr());
rcl_action_goal_info_t* buffer = reinterpret_cast<rcl_action_goal_info_t*>(
node::Buffer::Data(info[1].As<Napi::Object>()));

bool is_available;
THROW_ERROR_IF_NOT_EQUAL(
RCL_RET_OK,
rcl_action_server_is_available(node, action_client, &is_available),
rcl_get_error_string().str);
bool exists = rcl_action_server_goal_exists(action_server, buffer);

v8::Local<v8::Boolean> result = Nan::New<v8::Boolean>(is_available);
info.GetReturnValue().Set(result);
return Napi::Boolean::New(env, exists);
}

NAN_METHOD(ActionSendGoalRequest) {
Expand Down Expand Up @@ -687,35 +677,31 @@ NAN_METHOD(ActionServerGoalExists) {
info.GetReturnValue().Set(result);
}

NAN_METHOD(ActionExpireGoals) {
v8::Local<v8::Context> currentContent = Nan::GetCurrentContext();
RclHandle* action_server_handle = RclHandle::Unwrap<RclHandle>(
Nan::To<v8::Object>(info[0]).ToLocalChecked());
Napi::Value ActionExpireGoals(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
RclHandle* action_server_handle = RclHandle::Unwrap<RclHandle>(info[0].As<Napi::Object>());
rcl_action_server_t* action_server =
reinterpret_cast<rcl_action_server_t*>(action_server_handle->ptr());
int64_t max_num_goals = info[1]->IntegerValue(currentContent).FromJust();
int64_t max_num_goals = info[1].As<Napi::Number>().Int64Value();
rcl_action_goal_info_t* buffer = reinterpret_cast<rcl_action_goal_info_t*>(
node::Buffer::Data(Nan::To<v8::Object>(info[2]).ToLocalChecked()));
node::Buffer::Data(info[2].As<Napi::Object>()));

size_t num_expired;
THROW_ERROR_IF_NOT_EQUAL(rcl_action_expire_goals(action_server, buffer,
max_num_goals, &num_expired),
RCL_RET_OK, rcl_get_error_string().str);

v8::Local<v8::Integer> result =
Nan::New<v8::Integer>(static_cast<int32_t>(num_expired));
info.GetReturnValue().Set(result);
return Napi::Number::New(env, static_cast<int32_t>(num_expired));
}

NAN_METHOD(ActionGetClientNamesAndTypesByNode) {
v8::Local<v8::Context> currentContent = Nan::GetCurrentContext();
RclHandle* node_handle = RclHandle::Unwrap<RclHandle>(
Nan::To<v8::Object>(info[0]).ToLocalChecked());
Napi::Value ActionGetClientNamesAndTypesByNode(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
RclHandle* node_handle = RclHandle::Unwrap<RclHandle>(info[0].As<Napi::Object>());
rcl_node_t* node = reinterpret_cast<rcl_node_t*>(node_handle->ptr());
std::string node_name =
*Nan::Utf8String(info[1]->ToString(currentContent).ToLocalChecked());
info[1].As<Napi::String>().Utf8Value();
std::string node_namespace =
*Nan::Utf8String(info[2]->ToString(currentContent).ToLocalChecked());
info[2].As<Napi::String>().Utf8Value();

rcl_names_and_types_t names_and_types =
rcl_get_zero_initialized_names_and_types();
Expand All @@ -726,15 +712,14 @@ NAN_METHOD(ActionGetClientNamesAndTypesByNode) {
node_namespace.c_str(), &names_and_types),
"Failed to action client names and types.");

v8::Local<v8::Array> result_list =
Nan::New<v8::Array>(names_and_types.names.size);
ExtractNamesAndTypes(names_and_types, &result_list);
Napi::Array result_list = Napi::Array::New(env, names_and_types.names.size);
ExtractNamesAndTypes(env, names_and_types, result_list);

THROW_ERROR_IF_NOT_EQUAL(RCL_RET_OK,
rcl_names_and_types_fini(&names_and_types),
"Failed to destroy names_and_types");

info.GetReturnValue().Set(result_list);
return result_list;
}

NAN_METHOD(ActionGetServerNamesAndTypesByNode) {
Expand Down
Loading
Loading