N-API

writing node modules like it's 2018

@jupp0r

Native Addons

V8 is Google's open source high-performance JavaScript engine, written in C++ and used in Chromium, Node.js and multiple other embedding applications.

V8 Bindings

#include <node.h>

using v8::FunctionCallbackInfo;
using v8::Isolate;
using v8::Local;
using v8::Object;
using v8::String;
using v8::Value;

void Method(const FunctionCallbackInfo<Value>& args) {
  Isolate* isolate = args.GetIsolate();
  args.GetReturnValue()
      .Set(String::NewFromUtf8(isolate, "world"));
}

void init(Local<Object> exports) {
  NODE_SET_METHOD(exports, "hello", Method);
}

NODE_MODULE(addon, init)

V8 deprecations

NAN - Native Abstractions for Node

#include <nan.h>

using v8::FunctionTemplate;
using v8::Handle;
using v8::Object;
using v8::String;
using Nan::GetFunction;
using Nan::New;
using Nan::Set;

NAN_MODULE_INIT(Init) {
  Set(target, New<String>("hello").ToLocalChecked(),
    GetFunction(New<FunctionTemplate>(Method))
      .ToLocalChecked());
}

NAN_METHOD(Method) {
  info.GetReturnValue().Set(New<String>("world"));
}

NODE_MODULE(addon, Init)

API compatibility but not ABI compatibility

Developers are currently unable to use Node.js on devices running Windows on ARM [...]. We decided to fill this gap by allowing Node.js to take advantage of running with the Chakra JavaScript engine [...].

Today we hit that major milestone on our roadmap by submitting a pull request to Node.js mainline to enable Node.js to work with ChakraCore.

What happens to native node modules?

Summary so far

1. V8 breaks modules a lot

2. Each JS Engine has their own bindings

Enter
N-API

N-API is an API for building native Addons. It is independent from the underlying JavaScript runtime (ex V8) and is maintained as part of Node.js itself. This API will be Application Binary Interface (ABI) stable across versions of Node.js.

 

#include <node_api.h>

NAPI_METHOD(Method) {
  napi_value ret;
  napi_create_string_utf8(env, "world", -1, &ret); 
  return ret;
}

void init(napi_env env,
          napi_value exports,
          napi_value module,
          void* priv) {
  napi_status status;
  napi_property_descriptor desc =
    {"hello", Method, 0, 0, 0, napi_default, 0};
  status = napi_define_properties(env,
                                  exports,
                                  1,
                                  &desc);
}

NAPI_MODULE(addon, init)
#include <napi.h>

using namespace Napi;

Value Method(const CallbackInfo& info) {
  return String::New(info.Env(), "world");
}

void init(Env env,
          Object exports,
          Object module) {
  exports["hello"] =
       Function::New(env, Method);
}

NODE_API_MODULE(addon, init)

Performance?

Coverage

* based on 30 most depended-on native modules

This is in node 8.0*

* behind the --napi-modules feature toggle

API is not stable yet

References

Thanks!
Questions?

Node API

By Jupp Müller

Node API

  • 2,660