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
{{ message }}
Repository navigation
[discussion] integrating nan or similar with io.js #349
nan has done wonders for the community, but there are still missing bits. If these can be addressed there is a good desire to bring this into io.js itself. This thread should serve as a discussion on what are all the missing bits, what we can do about them and how to eventually get this into io.js.
The most prominent issue is lack of ABI compatibility. Needing to recompile with every new release, especially now with more frequent V8 updates, is difficult. @bnoordhuis mentioned that using templates is not a good form of ABI compatibility because they don't play well with the linker. (Ben, if you have any additional thoughts on this please feel free to include anything I've missed).
I'll start by noting that not using templates leads to very clumsy code, and since V8 makes heavy use of templates, this would require not directly exposing anything from V8. Otherwise the issue of ABI compatibility will reemerge.
This is a separate effort to NAN and will be until it can completely replace NAN and we can deprecate it - even then we'll probably have overlap while people adjust
Let's start simple and unambitious
We're going to have to accept a world similar to NAN where the API/ABI will have to change over time to adapt to a changing upstream API but the benefit will be that you're dealing with a single API to code against
People are going to want to reach around to V8 regardless of how sophisticated this is, we need to accept that and possibly make allowances for it, the problem with https://github.com/tjfontaine/node-addon-layer as I see it is that it goes too far in one leap and makes no allowances for anything but standard uses (the typical "framework problem"); this and item (2) above are the main reasons I've advocated for the NAN approach over the addon-layer approach in the past
The continued instability from V8 is getting me down, they seem to have an endless appetite to screw with their API and therefore screw users of the C++ API, maybe it's the frustration with having to deal with permanent backward compatibility in JS to ES1 that forces them to take it out on the C++ API. @domenic says he's going to take this up with the V8 team but at this stage I'm much more willing to support efforts to detach Node from V8 as a direct dependency.
Chakra introduces an interesting dynamic here and we may want to engage the Microsoft team on this effort given what they've had to go through to make their shim
Three things I believe could be done without templates and be ABI compliant:
Local<Value> with a few methods. Such as Is{Undefined,Null,True,etc.}(), BooleanValue(), NumberValue(), etc. The hurdle to overcome would be casting to other types, and supporting all those APIs.
typedef void (*FunctionCallback)(const FunctionCallbackInfo<Value>& info) could be a normal function call. info[i] could be an array of values, and since they're all initially Local<Values> the naive implementation would be supported. The problematic would be all calls that return Local<Object>.
Buffers are pretty straight forward. This should even be possible using our Local<Value> abstraction, and in fact would be most compatible that way because currently it requires a Local<Object> and in the future will require a Local<Uint8Array>. Possibly something like the following (warning, this is very C-ish):
Would definitely want a code generator to generate the code for all the ensuing virtually identical wrapper functions with different types. It would be nice if one could get at the resulting C++ code after template processing, but before compilation.
Have a look at how Python 3 is doing it. Python is also dynamically typed, and everything is an object, but I have to say that writing addons for it is rather painful.
Also, I think the bar for a useful addon API should be set higher than trivial. If you can only do trivial things, you might as well just set up a socket or pipe of sorts and communicate between JavaScript and the real world through that.
So to clarify I was simply saying we start small, experiment and see how well it works. If it works at all.
One important thing is that if we want to truly achieve ABI compatibility then the exposed API needs to be written in C. There have been more than a few people smarter than myself that have expressed that C++ doesn't do well at maintaining proper memory structures when compiled with different compilers, or even different versions of the same compiler.
I agree that we have to start simple, implementation-wise. However, that initial implementation needs to scale up to offering a richer feature set.
It does not need to be written in C as such, it's just the external functions (and data) that need to be "C" exported. Without C++, how would the the wrappers interact with v8?
One important thing is that if we want to truly achieve ABI compatibility then the exposed API needs to be written in C. There have been more than a few people smarter than myself that have expressed that C++ doesn't do well at maintaining proper memory structures when compiled with different compilers, or even different versions of the same compiler.
Structures/classes don't have to be a problem when you don't use features such as virtual methods, multiple inheritance, member function pointers, etc.
I suppose name mangling could be an issue for people that mix C++11 code with pre-C++11 code. You can work around it by building everything with -fabi-version=6 but that requires that you use a recent compiler.
So, what we'd essentially want is to wrap v8's C++ exports in C exports to get a stable ABI and then have a (NAN-derived) header library on top of that which would restore the C++ nature of V8's API by mapping to the C exports.
Microsoft appears to have created a V8 compatible C++ API facade for Chakra. While it is a nice piece of engineering, it also has the disadvantage of trying to keep up with a constantly changing V8 API that is not managed by the node project.
I like the javascript engine wrapper C API idea proposed by @trevnorris. Node itself and node native modules could only use this C API. That way the javascript engine (V8, Spidermonkey, Duktape, JavascriptCore or other) could be made to be pluggable at runtime depending on the needs of the user. Native node modules compiled against this hypothetical C API could work against any such runtime-pluggable engine without recompilation due to its more stable ABI.
However, one downside with such a javascript engine C API would be that it would impose a little bit of overhead on every javascript <=> c++ operation as compared to header-only inline C++ classes or C macros. Even so, I still think it is worth the cost for the maintainability and the flexibility it would offer.
@kzc After doing testing in this area I'm fairly confident that we'd be able to do this with very little overhead. At least minimal enough where users wouldn't feel it in their JS code.
Clearly yes. The overhead of context switching from JavaScript to C++ drowns
out everything else.
On Friday 15 May 2015 03:06:11 Trevor Norris wrote:
@kzc After doing testing in this area I'm fairly confident that we'd be able
to do this with very little overhead. At least minimal enough where users
wouldn't feel it in their JS code.
Reply to this email directly or view it on GitHub: #349 (comment)
I would suggest you to check the changes to V8's GC over time. There are no thousands of ways for GC and not a long standing best one. This is a delicate place that may change from one version to another. Even if you have no interest for other JS engines, taking other engines into reference would help the final interface less vulnerable.
I don't understand the implication here with respect to needing abstract behaviors to be listed for compatibility.
I feel like the proposal is moving from "let's create an abstraction layer from how node currently works" to "let's rethink the fundamental architecture to accommodate all possible variances". I'm skeptical that would fly with the TSC.
There's functionality that Node needs. Like knowing specific information about the life of an object. I remember a few years ago Ben attempted to implement node on top of SM, but found it wasn't possible to keep feature parity. Node won't sacrifice features to achieve an abstraction. The majority of the community doesn't care about the abstraction. We need to make the case why it's in their best interest to do so. Regardless of preventing V8 breakage, if features are gimped then it won't be welcome.
a few years ago Ben attempted to implement node on top of SM, but found it wasn't possible to keep feature parity.
@trevnorris, what v8 feature(s) specifically? JXCore is a working Node fork on top of an engine abstraction API supporting both SM and V8. So it's clearly possible.
Are you suggesting that the node foundation would only entertain supporting non-v8 engines only if they were wrapped by a v8-compatible C++ API as Microsoft has done with Chakra? But even so, the v8 API is a moving target - hence this discussion to have an engine agnostic API wrapper.
The majority of the community doesn't care about the abstraction. We need to make the case why it's in their best interest to do so.
I agree.
Here's the case as I see it for a "simple native binding", based on templates or similar:
(1) Simplifies your native code. No need to learn a JS engine API, V8 or abstracted or otherwise. Just use the native types supported by the binding layer and everything works. Easy to use, easy to get right.
(2) Isolates you from V8 API breakage.
(3) Makes it easier to support other JS engines.
Most module authors don't care much about (3). They care about (1) and (2). Done properly, I think this could be compelling enough to make them want to use it.
@kzc It was years ago, and most likely that whatever was lacking at the time now exists. And in terms of V8, I'm saying that no existing functionality can can't be sacrificed because some VM doesn't support it. The abstraction needs to allow all public APIs to continue working as they do today.
@geoffkizer Those are good points, and it sounds like you are more directly addressing native module compatibility. The discussion does seem to have diverged into whether all of core should be abstracted or just the module interface. Which are you looking for?
@geoffkizer I've mentioned on my previous comments a bit. JXcore's embedding interface is JS engine independent. API The approach can be improved and used for native add-ons.
I have no desire for Node to try and satisfy all the implementation differences between engines.
I don't understand the implication here with respect to needing abstract behaviors to be listed for compatibility.
@bmeck What I was saying that; we better know the implementation differences among the engines, so we know what is minimalistic and less likely to be broken. I agree with the documentation part.
I feel like the proposal is moving from "let's create an abstraction layer from how node currently works" to "let's rethink the fundamental architecture to accommodate all possible variances".
I thought the discussion was a minimalistic API for native addons.
@kzc I'm only considering the APIs we have direct control over. Don't care about the V8 API.
@obastemur This thread has gotten long, and wires were crossed somewhere. Thought that some of this discussion had shifted to removing V8 from core. Native modules is a much easier target. Thanks for clarifying.
Agree it's been a long thread. Luckily, many experienced developers participating on this discussion. How about prepare and share a minimalistic API (coverage) that is compatible to the engines discussed here.
We might have a better picture on the actual facts / problems. Moreover, we may see if it's reasonable or not.
I can spend some time / or collaborate on the initial list upcoming days.
For everyone's information, the API WG repo has been created. I'm still writing the initial README, but feel free to join if you wish to get involved: https://github.com/nodejs/api
I plan for all communication possible to be async. So submit issues and whatnot and we'll get things going.
Everyone, @obastemur was awesome enough to write up the first PR for the API WG. This has to do w/ the native API, and those that have participated in this thread are more qualified to give feedback from myself: nodejs/api#4
A bit outdated but just saw this discussion.I am trying to put up a cross platform native addon. I can't tell how hard it is to catch up with all the changes and differences. Looking forward to see a common API!
I think the pressing need is to abstract the module interface, so that's what I think we should focus on.
@kzc It was years ago, and most likely that whatever was lacking at the time now exists. And in terms of V8, I'm saying that no existing functionality can can't be sacrificed because some VM doesn't support it. The abstraction needs to allow all public APIs to continue working as they do today.
@trevnorris nothing new with spider monkey. @obastemur implemented the missing features into spider.
Activity
kkoopa commentedon May 13, 2015
I'll start by noting that not using templates leads to very clumsy code, and since V8 makes heavy use of templates, this would require not directly exposing anything from V8. Otherwise the issue of ABI compatibility will reemerge.
rvagg commentedon May 14, 2015
Some initial randomish thoughts:
trevnorris commentedon May 14, 2015
Three things I believe could be done without templates and be ABI compliant:
Local<Value>with a few methods. Such asIs{Undefined,Null,True,etc.}(),BooleanValue(),NumberValue(), etc. The hurdle to overcome would be casting to other types, and supporting all those APIs.typedef void (*FunctionCallback)(const FunctionCallbackInfo<Value>& info)could be a normal function call.info[i]could be an array of values, and since they're all initiallyLocal<Values>the naive implementation would be supported. The problematic would be all calls that returnLocal<Object>.Local<Value>abstraction, and in fact would be most compatible that way because currently it requires aLocal<Object>and in the future will require aLocal<Uint8Array>. Possibly something like the following (warning, this is very C-ish):kkoopa commentedon May 14, 2015
Would definitely want a code generator to generate the code for all the ensuing virtually identical wrapper functions with different types. It would be nice if one could get at the resulting C++ code after template processing, but before compilation.
Have a look at how Python 3 is doing it. Python is also dynamically typed, and everything is an object, but I have to say that writing addons for it is rather painful.
Also, I think the bar for a useful addon API should be set higher than trivial. If you can only do trivial things, you might as well just set up a socket or pipe of sorts and communicate between JavaScript and the real world through that.
trevnorris commentedon May 14, 2015
@kkoopa
I was just echoing @rvagg's sentiment of:
So to clarify I was simply saying we start small, experiment and see how well it works. If it works at all.
One important thing is that if we want to truly achieve ABI compatibility then the exposed API needs to be written in C. There have been more than a few people smarter than myself that have expressed that C++ doesn't do well at maintaining proper memory structures when compiled with different compilers, or even different versions of the same compiler.
kkoopa commentedon May 14, 2015
I agree that we have to start simple, implementation-wise. However, that initial implementation needs to scale up to offering a richer feature set.
It does not need to be written in C as such, it's just the external functions (and data) that need to be "C" exported. Without C++, how would the the wrappers interact with v8?
trevnorris commentedon May 14, 2015
Agreed. I should have made my following statement more clear:
So yes. I completely agree. It's just the user facing API that should be C.
kkoopa commentedon May 14, 2015
Something like this should do.
https://github.com/martine/v8c/blob/v8c/src/v8c.cc
On May 14, 2015 10:46:57 PM EEST, Trevor Norris notifications@github.com wrote:
trevnorris commentedon May 14, 2015
@kkoopa good stuff. we'd just have to extend it to support current APIs like
Buffer.kkoopa commentedon May 14, 2015
And new V8. Notice that this project has been abandoned for 6 years.
On May 14, 2015 11:00:11 PM EEST, Trevor Norris notifications@github.com wrote:
bnoordhuis commentedon May 14, 2015
Structures/classes don't have to be a problem when you don't use features such as virtual methods, multiple inheritance, member function pointers, etc.
I suppose name mangling could be an issue for people that mix C++11 code with pre-C++11 code. You can work around it by building everything with
-fabi-version=6but that requires that you use a recent compiler.kkoopa commentedon May 14, 2015
So, what we'd essentially want is to wrap v8's C++ exports in C exports to get a stable ABI and then have a (NAN-derived) header library on top of that which would restore the C++ nature of V8's API by mapping to the C exports.
Something like this:
kzc commentedon May 15, 2015
Microsoft appears to have created a V8 compatible C++ API facade for Chakra. While it is a nice piece of engineering, it also has the disadvantage of trying to keep up with a constantly changing V8 API that is not managed by the node project.
I like the javascript engine wrapper C API idea proposed by @trevnorris. Node itself and node native modules could only use this C API. That way the javascript engine (V8, Spidermonkey, Duktape, JavascriptCore or other) could be made to be pluggable at runtime depending on the needs of the user. Native node modules compiled against this hypothetical C API could work against any such runtime-pluggable engine without recompilation due to its more stable ABI.
However, one downside with such a javascript engine C API would be that it would impose a little bit of overhead on every javascript <=> c++ operation as compared to header-only inline C++ classes or C macros. Even so, I still think it is worth the cost for the maintainability and the flexibility it would offer.
trevnorris commentedon May 15, 2015
@kzc After doing testing in this area I'm fairly confident that we'd be able to do this with very little overhead. At least minimal enough where users wouldn't feel it in their JS code.
kkoopa commentedon May 15, 2015
Clearly yes. The overhead of context switching from JavaScript to C++ drowns
out everything else.
On Friday 15 May 2015 03:06:11 Trevor Norris wrote:
71 remaining items
geoffkizer commentedon Jun 17, 2015
@obastemur: how do you get rid of handle<> and local<>?
bmeck commentedon Jun 17, 2015
@obastemur
I don't understand the implication here with respect to needing abstract behaviors to be listed for compatibility.
trevnorris commentedon Jun 17, 2015
I feel like the proposal is moving from "let's create an abstraction layer from how node currently works" to "let's rethink the fundamental architecture to accommodate all possible variances". I'm skeptical that would fly with the TSC.
There's functionality that Node needs. Like knowing specific information about the life of an object. I remember a few years ago Ben attempted to implement node on top of SM, but found it wasn't possible to keep feature parity. Node won't sacrifice features to achieve an abstraction. The majority of the community doesn't care about the abstraction. We need to make the case why it's in their best interest to do so. Regardless of preventing V8 breakage, if features are gimped then it won't be welcome.
kzc commentedon Jun 17, 2015
@trevnorris, what v8 feature(s) specifically? JXCore is a working Node fork on top of an engine abstraction API supporting both SM and V8. So it's clearly possible.
Are you suggesting that the node foundation would only entertain supporting non-v8 engines only if they were wrapped by a v8-compatible C++ API as Microsoft has done with Chakra? But even so, the v8 API is a moving target - hence this discussion to have an engine agnostic API wrapper.
geoffkizer commentedon Jun 17, 2015
I agree.
Here's the case as I see it for a "simple native binding", based on templates or similar:
(1) Simplifies your native code. No need to learn a JS engine API, V8 or abstracted or otherwise. Just use the native types supported by the binding layer and everything works. Easy to use, easy to get right.
(2) Isolates you from V8 API breakage.
(3) Makes it easier to support other JS engines.
Most module authors don't care much about (3). They care about (1) and (2). Done properly, I think this could be compelling enough to make them want to use it.
trevnorris commentedon Jun 17, 2015
@kzc It was years ago, and most likely that whatever was lacking at the time now exists. And in terms of V8, I'm saying that no existing functionality
cancan't be sacrificed because some VM doesn't support it. The abstraction needs to allow all public APIs to continue working as they do today.@geoffkizer Those are good points, and it sounds like you are more directly addressing native module compatibility. The discussion does seem to have diverged into whether all of core should be abstracted or just the module interface. Which are you looking for?
EDIT: Fixed typo
obastemur commentedon Jun 17, 2015
@geoffkizer I've mentioned on my previous comments a bit. JXcore's embedding interface is JS engine independent. API The approach can be improved and used for native add-ons.
@bmeck What I was saying that; we better know the implementation differences among the engines, so we know what is minimalistic and less likely to be broken. I agree with the documentation part.
I thought the discussion was a minimalistic API for native addons.
kzc commentedon Jun 17, 2015
@trevnorris do you consider the (ever changing) v8 API to be part of Node's public API? Where is the line drawn for the public API?
trevnorris commentedon Jun 17, 2015
@kzc I'm only considering the APIs we have direct control over. Don't care about the V8 API.
@obastemur This thread has gotten long, and wires were crossed somewhere. Thought that some of this discussion had shifted to removing V8 from core. Native modules is a much easier target. Thanks for clarifying.
obastemur commentedon Jun 17, 2015
Agree it's been a long thread. Luckily, many experienced developers participating on this discussion. How about prepare and share a minimalistic API (coverage) that is compatible to the engines discussed here.
We might have a better picture on the actual facts / problems. Moreover, we may see if it's reasonable or not.
I can spend some time / or collaborate on the initial list upcoming days.
geoffkizer commentedon Jun 18, 2015
@trevnorris:
I think the pressing need is to abstract the module interface, so that's what I think we should focus on.
That's what I meant above re "abstracted user facing API"; I should have said "abstracted user facing module API" to be clearer.
trevnorris commentedon Jun 18, 2015
For anyone that's participated, I'll be writing up a summary of what these abstractions are attempting to achieve on nodejs/node#1993
Basically we're just in the process of properly forming a WG to handle these things.
trevnorris commentedon Jun 24, 2015
For everyone's information, the API WG repo has been created. I'm still writing the initial README, but feel free to join if you wish to get involved: https://github.com/nodejs/api
I plan for all communication possible to be async. So submit issues and whatnot and we'll get things going.
trevnorris commentedon Jun 30, 2015
Everyone, @obastemur was awesome enough to write up the first PR for the API WG. This has to do w/ the native API, and those that have participated in this thread are more qualified to give feedback from myself: nodejs/api#4
Ben007 commentedon Nov 13, 2015
A bit outdated but just saw this discussion.I am trying to put up a cross platform native addon. I can't tell how hard it is to catch up with all the changes and differences. Looking forward to see a common API!
@geoffkizer exactly.
@trevnorris nothing new with spider monkey. @obastemur implemented the missing features into spider.