|
| 1 | +# ABI Stability |
| 2 | + |
| 3 | +## Introduction |
| 4 | +An Application Binary Interface (ABI) is a way for programs to call functions |
| 5 | +and use data structures from other compiled programs. It is the compiled version |
| 6 | +of an Application Programming Interface (API). In other words, the headers files |
| 7 | +describing the classes, functions, data structures, enumerations, and constants |
| 8 | +which enable an application to perform a desired task correspond by way of |
| 9 | +compilation to a set of addresses and expected parameter values and memory |
| 10 | +structure sizes and layouts with which the provider of the ABI was compiled. |
| 11 | + |
| 12 | +The application using the ABI must be compiled such that the available |
| 13 | +addresses, expected parameter values, and memory structure sizes and layouts |
| 14 | +agree with those with which the ABI provider was compiled. This is usually |
| 15 | +accomplished by compiling against the headers provided by the ABI provider. |
| 16 | + |
| 17 | +Since the provider of the ABI and the user of the ABI may be compiled at |
| 18 | +different times with different versions of the compiler, a portion of the |
| 19 | +responsibility for ensuring ABI compatibility lies with the compiler. Different |
| 20 | +versions of the compiler, perhaps provided by different vendors, must all |
| 21 | +produce the same ABI from a header file with a certain content, and must produce |
| 22 | +code for the application using the ABI that accesses the API described in a |
| 23 | +given header according to the conventions of the ABI resulting from the |
| 24 | +description in the header. Modern compilers have a fairly good track record of |
| 25 | +not breaking the ABI compatibility of the applications they compile. |
| 26 | + |
| 27 | +The remaining responsibility for ensuring ABI compatibility lies with the team |
| 28 | +maintaining the header files which provide the API that results, upon |
| 29 | +compilation, in the ABI that is to remain stable. Changes to the header files |
| 30 | +can be made, but the nature of the changes has to be closely tracked to ensure |
| 31 | +that, upon compilation, the ABI does not change in a way that will render |
| 32 | +existing users of the ABI incompatible with the new version. |
| 33 | + |
| 34 | +## ABI Stability in Node.js |
| 35 | +Node.js provides header files maintained by several independent teams. For |
| 36 | +example, header files such as `node.h` and `node_buffer.h` are maintained by |
| 37 | +the Node.js team. `v8.h` is maintained by the V8 team, which, although in close |
| 38 | +co-operation with the Node.js team, is independent, and with its own schedule |
| 39 | +and priorities. Thus, the Node.js team has only partial control over the |
| 40 | +changes that are introduced in the headers the project provides. As a result, |
| 41 | +the Node.js project has adopted [semantic versioning](https://semver.org/). |
| 42 | +This ensures that the APIs provided by the project will result in a stable ABI |
| 43 | +for all minor and patch versions of Node.js released within one major version. |
| 44 | +In practice, this means that the Node.js project has committed itself to |
| 45 | +ensuring that a Node.js native addon compiled against a given major version of |
| 46 | +Node.js will load successfully when loaded by any Node.js minor or patch version |
| 47 | +within the major version against which it was compiled. |
| 48 | + |
| 49 | +## N-API |
| 50 | +Demand has arisen for equipping Node.js with an API that results in an ABI that |
| 51 | +remains stable across multiple Node.js major versions. The motivation for |
| 52 | +creating such an API is as follows: |
| 53 | +* The JavaScript language has remained compatible with itself since its very |
| 54 | +early days, whereas the ABI of the engine executing the JavaScript code changes |
| 55 | +with every major version of Node.js. This means that applications consisting of |
| 56 | +Node.js packages written entirely in JavaScript need not be recompiled, |
| 57 | +reinstalled, or redeployed as a new major version of Node.js is dropped into |
| 58 | +the production environment in which such applications run. In contrast, if an |
| 59 | +application depends on a package that contains a native addon, the application |
| 60 | +has to be recompiled, reinstalled, and redeployed whenever a new major version |
| 61 | +of Node.js is introduced into the production environment. This disparity |
| 62 | +between Node.js packages containing native addons and those that are written |
| 63 | +entirely in JavaScript has added to the maintenance burden of production |
| 64 | +systems which rely on native addons. |
| 65 | + |
| 66 | +* Other projects have started to produce JavaScript interfaces that are |
| 67 | +essentially alternative implementations of Node.js. Since these projects are |
| 68 | +usually built on a different JavaScript engine than V8, their native addons |
| 69 | +necessarily take on a different structure and use a different API. Nevertheless, |
| 70 | +using a single API for a native addon across different implementations of the |
| 71 | +Node.js JavaScript API would allow these projects to take advantage of the |
| 72 | +ecosystem of JavaScript packages that has accrued around Node.js. |
| 73 | + |
| 74 | +* Node.js may contain a different JavaScript engine in the future. This means |
| 75 | +that, externally, all Node.js interfaces would remain the same, but the V8 |
| 76 | +header file would be absent. Such a step would cause the disruption of the |
| 77 | +Node.js ecosystem in general, and that of the native addons in particular, if |
| 78 | +an API that is JavaScript engine agnostic is not first provided by Node.js and |
| 79 | +adopted by native addons. |
| 80 | + |
| 81 | +To these ends Node.js has introduced N-API in version 8.6.0 and marked it as a |
| 82 | +stable component of the project as of Node.js 8.12.0. The API is defined in the |
| 83 | +headers [`node_api.h`][] and [`node_api_types.h`][], and provides a forward- |
| 84 | +compatibility guarantee that crosses the Node.js major version boundary. The |
| 85 | +guarantee can be stated as follows: |
| 86 | + |
| 87 | +**A given version *n* of N-API will be available in the major version of |
| 88 | +Node.js in which it was published, and in all subsequent versions of Node.js, |
| 89 | +including subsequent major versions.** |
| 90 | + |
| 91 | +A native addon author can take advantage of the N-API forward compatibility |
| 92 | +guarantee by ensuring that the addon makes use only of APIs defined in |
| 93 | +`node_api.h` and data structures and constants defined in `node_api_types.h`. |
| 94 | +By doing so, the author facilitates adoption of their addon by indicating to |
| 95 | +production users that the maintenance burden for their application will increase |
| 96 | +no more by the addition of the native addon to their project than it would by |
| 97 | +the addition of a package written purely in JavaScript. |
| 98 | + |
| 99 | +N-API is versioned because new APIs are added from time to time. Unlike |
| 100 | +semantic versioning, N-API versioning is cumulative. That is, each version of |
| 101 | +N-API conveys the same meaning as a minor version in the semver system, meaning |
| 102 | +that all changes made to N-API will be backwards compatible. Additionally, new |
| 103 | +N-APIs are added under an experimental flag to give the community an opportunity |
| 104 | +to vet them in a production environment. Experimental status means that, |
| 105 | +although care has been taken to ensure that the new API will not have to be |
| 106 | +modified in an ABI-incompatible way in the future, it has not yet been |
| 107 | +sufficiently proven in production to be correct and useful as designed and, as |
| 108 | +such, may undergo ABI-incompatible changes before it is finally incorporated |
| 109 | +into a forthcoming version of N-API. That is, an experimental N-API is not yet |
| 110 | +covered by the forward compatibility guarantee. |
| 111 | + |
| 112 | +[`node_api.h`]: ../../src/node_api.h |
| 113 | +[`node_api_types.h`]: ../..src/node_api_types.h |
0 commit comments