You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I am building a C++ plugin for nodejs, and we would like to be able to return a Javascript Map() object to the user. The version of nodejs that we are using clearly supports Map(), but I have been unable to find any support for creating, iterating, or indexing Map objects.
The documentation at https://nodejs.org/api/n-api.html contains no mentions of Map objects at all. The word "map" only appears once on this page and is not used in any context that applies to the collection.
Yes – at this moment, N-API does not provide any wrapper for Map or Set. You can still use them like regular JS objects though, i.e. use the Map constructor to create objects from N-API and call .set() for adding entries to it.
I understand. It's awkward and less efficient to have JS compile code fragments every time I need to do something like this, though. Do you have any idea when this will be available? Is there a design spec that just needs implementing?
That being said, an approach that I think might be a bit nicer and also be worth exploring would be to create C++ wrappers for Map and Set that use the existing set of N-API primitives, and cache methods like set/delete so they only need to be retrieved once (note that either way, compiling JS code is not required here at all). That could even be provided as a header-only library on npm, with one big advantage being that it would also work across all existing supported Node.js versions.
I wouldn't be against contributing something. I'd have to clear it with my manager and see where our priorities are.
That being said, the C++ solution you mentioned is very interesting. However I don't see how it would work. First of all, the items in the Map() are not exposed as properties. (I've already tried that.) So I don't know how I would iterate (get_all_property_names doesn't work, I've tried that.)
I assume I'd use napi_new_instance() to create a new map, but I don't see how I would get the constructor for the Map. If you have some pointers, I would appreciate it. Thanks for your time!
Here’s an example addon that creates a wrapper for Map, sets an entry in the Map, then lists all entries and returns the first one. It’s obviously not very complete or pretty, but I think the idea might become clear. Things like the methods could also be cached in the constructor here.
@addaleax is there a similar way of getting a handle to the set of keys of an object? I'm trying to implement an iterator for Napi::Object at nodejs/node-addon-api#930 but currently, I'm keeping a full Napi::Array of keys inside the iterator, which feels incorrect. 😕
@RaisinTen I don’t think there’s any way to do that, really, no. You can only get a list of all keys at once, unless you use things like for (... in ...).
Activity
addaleax commentedon Apr 6, 2021
Yes – at this moment, N-API does not provide any wrapper for
MaporSet. You can still use them like regular JS objects though, i.e. use theMapconstructor to create objects from N-API and call.set()for adding entries to it.nadiasvertex commentedon Apr 6, 2021
I understand. It's awkward and less efficient to have JS compile code fragments every time I need to do something like this, though. Do you have any idea when this will be available? Is there a design spec that just needs implementing?
addaleax commentedon Apr 6, 2021
@nadiasvertex I guess you could open a ticket in https://github.com/nodejs/node/issues, if you’d like to see this implemented (or are interested in implementing it yourself).
That being said, an approach that I think might be a bit nicer and also be worth exploring would be to create C++ wrappers for
MapandSetthat use the existing set of N-API primitives, and cache methods likeset/deleteso they only need to be retrieved once (note that either way, compiling JS code is not required here at all). That could even be provided as a header-only library on npm, with one big advantage being that it would also work across all existing supported Node.js versions.nadiasvertex commentedon Apr 6, 2021
I wouldn't be against contributing something. I'd have to clear it with my manager and see where our priorities are.
That being said, the C++ solution you mentioned is very interesting. However I don't see how it would work. First of all, the items in the Map() are not exposed as properties. (I've already tried that.) So I don't know how I would iterate (get_all_property_names doesn't work, I've tried that.)
I assume I'd use napi_new_instance() to create a new map, but I don't see how I would get the constructor for the Map. If you have some pointers, I would appreciate it. Thanks for your time!
addaleax commentedon Apr 6, 2021
Here’s an example addon that creates a wrapper for
Map, sets an entry in the Map, then lists all entries and returns the first one. It’s obviously not very complete or pretty, but I think the idea might become clear. Things like the methods could also be cached in the constructor here.nadiasvertex commentedon Apr 6, 2021
That's very helpful, thanks!
RaisinTen commentedon Apr 7, 2021
@addaleax is there a similar way of getting a handle to the set of keys of an object? I'm trying to implement an iterator for Napi::Object at nodejs/node-addon-api#930 but currently, I'm keeping a full Napi::Array of keys inside the iterator, which feels incorrect. 😕
addaleax commentedon Apr 7, 2021
@RaisinTen I don’t think there’s any way to do that, really, no. You can only get a list of all keys at once, unless you use things like
for (... in ...).