Skip to content

Instantly share code, notes, and snippets.

@gabrielschulhof
Created June 27, 2019 17:02
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save gabrielschulhof/fcfdf47703f9ee21a7eebbc1600c49c4 to your computer and use it in GitHub Desktop.
Save gabrielschulhof/fcfdf47703f9ee21a7eebbc1600c49c4 to your computer and use it in GitHub Desktop.
Send modules to native
const addon = require('bindings')('addon');
addon.receiveModule('fs', require('fs'));
addon.receiveModule('crypto', require('crypto'));
console.log(addon.sendModule('fs') === require('fs'));
console.log(addon.sendModule('crypto') === require('crypto'));
#include "napi.h"
#include <unordered_map>
using Napi::Error;
typedef struct {
std::unordered_map<std::string, Napi::ObjectReference> modules;
} AddonData;
void ReceiveModule(const Napi::CallbackInfo& info) {
AddonData* addon_data = static_cast<AddonData*>(info.Data());
std::string name = info[0].As<Napi::String>();
addon_data->modules[name] = Napi::Persistent(info[1].As<Napi::Object>());
}
Napi::Value SendModule(const Napi::CallbackInfo& info) {
AddonData* addon_data = static_cast<AddonData*>(info.Data());
std::string name = info[0].As<Napi::String>();
return addon_data->modules[name].Value();
}
static void DeleteAddonData(napi_env env, void* data, void* hint) {
(void) env;
(void) hint;
delete static_cast<AddonData*>(data);
}
Napi::Object Init(Napi::Env env, Napi::Object exports) {
AddonData* addon_data = new AddonData;
NAPI_THROW_IF_FAILED(env,
napi_wrap(env, exports, addon_data, DeleteAddonData, nullptr, nullptr),
exports);
exports["receiveModule"] =
Napi::Function::New(env, ReceiveModule, "receiveModule", addon_data);
exports["sendModule"] =
Napi::Function::New(env, SendModule, "sendModule", addon_data);
return exports;
}
NODE_API_MODULE(NODE_GYP_MODULE_NAME, Init)
@sudhakar3697
Copy link

Hi,
If I try to access any function from the Object passed in N-API, I get an error saying 'not a member'. How do I access it?

Thank you.

@gabrielschulhof
Copy link
Author

@sudhakar3697 can you show me the code that is failing for you?

@sudhakar3697
Copy link

sudhakar3697 commented Aug 30, 2019

#include <napi.h>

Napi::String test(const Napi::CallbackInfo& info) {
  Napi::Env env = info.Env();
  Napi::Object module=info[0].As<Napi::Object>();
  Napi::Object y=module.require('os');
  return y.homedir();
}

Napi::Object init(Napi::Env env, Napi::Object exports) {
    exports.Set(Napi::String::New(env, "test"), Napi::Function::New(env, test));
    return exports;
};

NODE_API_MODULE(NODE_GYP_MODULE_NAME, init)

@sudhakar3697
Copy link

image

Thank you :)

@sudhakar3697
Copy link

sudhakar3697 commented Aug 30, 2019

This is how I try to access the module.

const addon = require('./addon')
console.log(addon.test(module))

@gabrielschulhof
Copy link
Author

@sudhakar3697 the members of module are not C++ members, but JavaScript members. So, you need to do this (not tested):

Napi::Function require = module.Get("require").As<Napi::Function>();
Napi::Value os = require.Call({Napi::String::New(env, "os")});
Napi::Value homedirFn = os.Get("homedir").As<Napi::Function>();
return homedirFn.Call({});

@sudhakar3697
Copy link

Now I get 'Get': is not a member of 'Napi::Value'.

Thank you.

@gabrielschulhof
Copy link
Author

Oh, right, because os is a Napi::Value.

Napi::Object os = require.Call({Napi::String::New(env, "os")}).As<Napi::Object>();

and then do the rest.

@sudhakar3697
Copy link

Thank you very much :).

Works great.

#include <napi.h>

Napi::Value test(const Napi::CallbackInfo &info)
{
  Napi::Env env = info.Env();
  Napi::Object module = info[0].As<Napi::Object>();
  Napi::Function require = module.Get("require").As<Napi::Function>();
  Napi::Object os = require.Call({Napi::String::New(env, "os")}).As<Napi::Object>();
  Napi::Function homedirFn = os.Get("homedir").As<Napi::Function>();
  return homedirFn.Call({});
}

Napi::Object init(Napi::Env env, Napi::Object exports)
{
  exports.Set(Napi::String::New(env, "test"), Napi::Function::New(env, test));
  return exports;
};

NODE_API_MODULE(NODE_GYP_MODULE_NAME, init)

@sudhakar3697
Copy link

sudhakar3697 commented Aug 30, 2019

How do you see this approach for protecting the source code (Business-critical like licensing)?

Thank you.

@gabrielschulhof
Copy link
Author

I don't understand the question. Are you concerned about what license you should use for the example code I wrote above? If so, feel free to use the code in any way you see fit. You need not credit me as the author.

@sudhakar3697
Copy link

No, I am asking if I can this approach of using js in N-API to protect the source code.

@gabrielschulhof
Copy link
Author

In general, what can be done in JS should be done in JS. It's much faster, and a lot simpler. Do in C++ only what cannot be done without using C++.

@gabrielschulhof
Copy link
Author

... if I understood your question correctly.

@sudhakar3697
Copy link

Okay.Thank you :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment