[RFC] Provide facilities for JS<->C++ conversion
Nobody has claimed this yet.
- Dominant language
- C++
- Stars
- 3.4k
- Forks
- 531
- Avg merge
- 21m
- Merged PRs (30d)
- 1
Description
Background
I have written some node addons, and I feel kind of pain in converting JS to C++ and back in the API bindings. So I plan to write some utility APIs that can help me do the conversion stuff automatically (one time and save forever). I think Nan is the best place for these APIs rather than creating a new separate module (and more developers will benefit from it ;)).
Here is a proposal to provide new JS<->C++ facilities in NAN that make it easier to marshal types between JavaScript and C++.
Feedback and comments are welcome. If the community accepts the proposal, I'm happy to contribute it :-).
Problem
When writing a native node addon, developers need to write some defending code in their API bindings:
- Check whether the passed arguments are valid (e.g. the numbers of arguments, the type of arguments are expected).
- If they are valid, then convert them from V8 types to native C++ types (using raw V8 APIs or Nan APIs).
Although Nan has already provided two helpers Nan::To and Nan::New, which converts V8 types to C++ types and back, but they don't fully solve the problem:
- Only basic native number types (
bool,uint32,int32,int64,double) are supported. - Developers still need to check availability for each argument separately.
Proposed Solution
This proposal is to add two functions in Nan which would make it easier to marshal types between JavaScript and C++, so that developers won't need to re-implement their JS<->C++ bindings.
The APIs are defined below:
// Currently Supported template types:
// * basic native types: int32, int64, bool, double, uint32
// * std::string
// * std::vector<T>
// We could provide some interfaces allowing developers to support their own C++ types.
//
// Convert V8's arguments to C++ native types. Returns false if fails.
//
// An example of a JS function "add(a, b)" which takes two Integer parameters.
// NAN_METHOD(Add) {
// int a, b;
// if (FromV8Argument(info, &a, &b)) {
// // Do anything with a, b.
// }
// }
template<typename... Args>
bool FromV8Argument(Nan::NAN_METHOD_ARGS_TYPE v8_args, Args*... args);
// Convert the supported C++ native types to V8 types.
// Similar to NAN::New(), but it supports more types.
template<typename T>
v8::Local<v8::Value> ToV8Value(T value);
With the help of these two functions, writing JS bindings could be easier, and most of the messy stuff of converting V8 types to C++ types is done automatically and carefully.
The original code without using FromV8Argument:
NAN_METHOD(add) {
if (!info[0]->IsNumber() || !info[1]->IsNumber()) {
Nan::ThrowTypeError("Wrong arguments");
return;
}
double arg0 = info[0]->NumberValue();
double arg1 = info[1]->NumberValue();
info.GetReturnValue().Set(Nan::New(arg0 + arg1));
}
The code using FromV8Argument:
NAN_METHOD(add) {
double arg0, arg1;
if (!Nan::FromV8Arguments(info, &arg0, &arg1)) {
Nan::ThrowTypeError("Wrong arguments");
return;
}
info.GetReturnValue().Set(Nan::New(arg0 + arg1));
}
Again, suggestions are welcome.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reviewing the existing Nan::To and Nan::New helpers, then compare them with the proposed FromV8Argument and ToV8Value signatures and examples. Before implementation, resolve the supported-type set and custom-type interface; done means the RFC has an accepted API and corresponding implementation scope.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp, javascript, node.js
- Domain
- api, developer-experience
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100