Skip to content

N-api (node-addon-api) #161

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 60 commits into from
Apr 3, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
12f48ef
N-API port initial implementation (WIP)
artemp Nov 16, 2018
8e796ce
clang-format
artemp Nov 16, 2018
54e1cac
default init `name_`
artemp Nov 16, 2018
8a5fe79
default construct `name_` in initialiser list to address :
artemp Nov 16, 2018
f762f77
clang-format
artemp Nov 16, 2018
da9be93
mode clang-format
artemp Nov 16, 2018
1c8d735
remove extra init (tidy)
artemp Nov 19, 2018
5727b02
make ctor explicit
artemp Nov 19, 2018
85d952b
pass Function by const-ref
artemp Nov 19, 2018
6219f17
annotate with NOLINT + fix passing Function by const-ref in standalon…
artemp Nov 19, 2018
45da8d2
clang-format
artemp Nov 19, 2018
9843b9a
default 'in-class' init member variable `name_` to placate g++
artemp Nov 19, 2018
4df69fc
remove LTO flags on linux builds
artemp Nov 21, 2018
ac12e37
Revert "remove LTO flags on linux builds" - doh!
artemp Nov 21, 2018
4ee2e66
Merge branch 'master' into n-api
artemp Nov 23, 2018
bfe8b4c
fix .clang-format
artemp Nov 26, 2018
27b9d1d
reimplement CPU intensive task and factor out into separate header
artemp Nov 26, 2018
ae1df1d
more cleaning up
artemp Nov 26, 2018
f56151f
remove redundant `override` c++11
artemp Nov 26, 2018
8aa7626
fix comment
artemp Mar 26, 2020
b95d393
Make simpler
artemp Mar 27, 2020
6854cf2
Update npm packages
artemp Mar 30, 2020
b914a10
add link to docs
artemp Mar 30, 2020
b10c91b
Remove Nan references + update link
artemp Mar 30, 2020
17de6e2
remove node-6 builds
artemp Mar 30, 2020
6258ccf
Allocate new Buffer and copy data into it.
artemp Mar 30, 2020
2277119
Add empty dtor to avoid memory leaks + make AsyncHelloWorker non-copy…
artemp Mar 30, 2020
0e9c970
clang-format
artemp Mar 30, 2020
8f37517
clang-tidy
artemp Mar 30, 2020
ea29acc
require mode-addon-api >= 2.0.0
artemp Mar 30, 2020
d4e6284
Take ownership of underlying data (NOTE: clang-tidy doesn't like this:)
artemp Mar 30, 2020
952946f
Add missing return statements
artemp Mar 31, 2020
2accc64
Use latest (HEAD) hode-addon-api module (fixes SIGILL crash in "Contr…
artemp Mar 31, 2020
79f2507
Fix test - use exact error message match
artemp Mar 31, 2020
88f37e5
sleep for 100ms to speed up tests running time
artemp Mar 31, 2020
586e60f
Store name_ member variable by value + clang tidy
artemp Mar 31, 2020
e769844
clang-format
artemp Mar 31, 2020
2520ace
Initialize result_
artemp Mar 31, 2020
cb186eb
c++ style
artemp Mar 31, 2020
6d08efe
Return std::unique_ptr<std::vector<char>> and stop abusing std::strin…
artemp Apr 1, 2020
4f5883f
update to use std::vector<char> + add gsl::owner<T> implementation +…
artemp Apr 1, 2020
bd6bdb6
Only target node v10 and v12
artemp Apr 1, 2020
eaa4fbf
tidy .travis.yml
artemp Apr 1, 2020
9eb4ab5
Revert "tidy .travis.yml"
artemp Apr 1, 2020
0c6c1fb
Revert "Only target node v10 and v12"
artemp Apr 1, 2020
3c8dfb6
Fix (hopefully) .travis.yml syntax
artemp Apr 1, 2020
826dd48
Update node versions
artemp Apr 1, 2020
c926694
Add AsyncHelloWorker_v2 implementation which uses `GetResult` method …
artemp Apr 1, 2020
d2cb818
add node v13 targets
artemp Apr 1, 2020
885b623
clang-format
artemp Apr 1, 2020
11e9edb
Don't rely on order of args evaluation which is implemetation defined…
artemp Apr 2, 2020
65da09a
Makefile - better target name
artemp Apr 2, 2020
7c717d9
Update link [skip ci]
artemp Apr 2, 2020
5cb4747
attempt to fix coverage problem
Apr 2, 2020
e88d774
suppress OS X specific leak
Apr 2, 2020
72cc593
remove references to nan in readme
Apr 2, 2020
8cb4609
Merge remote-tracking branch 'origin/master' into n-api
artemp Apr 3, 2020
da256b3
avoid re-running npm install when no needed
Apr 3, 2020
a454a21
use correct mason-js module
Apr 3, 2020
4a013d3
update deps
Apr 3, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .clang-format
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ BraceWrapping:
BeforeElse: true
IndentBraces: false
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Attach
BreakBeforeBraces: Custom
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
ColumnLimit: 0
Expand Down Expand Up @@ -72,7 +72,7 @@ PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Left
ReflowComments: true
SortIncludes: true
SortIncludes: false
SpaceAfterCStyleCast: false
SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: ControlStatements
Expand Down
40 changes: 32 additions & 8 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@ language: node_js

sudo: false

# enable c++11/14 builds
addons:
apt:
sources: [ 'ubuntu-toolchain-r-test' ]
packages: [ 'libstdc++-4.9-dev' ]
packages: [ 'libstdc++-5-dev' ]

install:
- node -v
Expand Down Expand Up @@ -35,7 +34,7 @@ matrix:

## ** Builds that are published **

# linux cfi build node v6/release
# linux cfi build node v10/release
- os: linux
env: BUILDTYPE=release TOOLSET=cfi CXXFLAGS="-fsanitize=cfi -fvisibility=hidden" LDFLAGS="-fsanitize=cfi"
node_js: 10
Expand All @@ -51,6 +50,22 @@ matrix:
- os: linux
env: BUILDTYPE=debug
node_js: 10
# linux publishable node v12/release
- os: linux
env: BUILDTYPE=release
node_js: 12
# linux publishable node v12/debug
- os: linux
env: BUILDTYPE=debug
node_js: 12
# linux publishable node v13/release
- os: linux
env: BUILDTYPE=release
node_js: 13
# linux publishable node v13/debug
- os: linux
env: BUILDTYPE=debug
node_js: 13
# osx publishable node v10/release
- os: osx
osx_image: xcode9.3
Expand All @@ -61,7 +76,7 @@ matrix:
osx_image: xcode9.3
env: BUILDTYPE=release
node_js: 12
# linux sanitizer build node v6/debug
# linux sanitizer build node v10/debug
- os: linux
env: BUILDTYPE=debug TOOLSET=asan
node_js: 10
Expand All @@ -71,7 +86,8 @@ matrix:
- make sanitize
# Overrides `before_script` (tests are already run in `make sanitize`)
before_script:
# osx sanitizer build node v6/debug
- true
# osx sanitizer build node v10/debug
- os: osx
env: BUILDTYPE=debug TOOLSET=asan
node_js: 10
Expand All @@ -81,7 +97,7 @@ matrix:
- make sanitize
# Overrides `before_script` (tests are already run in `make sanitize`)
before_script:

- true
## ** Builds that do not get published **

# g++ build (default builds all use clang++)
Expand All @@ -100,6 +116,7 @@ matrix:
- make ${BUILDTYPE}
# Overrides `script` to disable publishing
script:
- true
# Coverage build
- os: linux
env: BUILDTYPE=debug CXXFLAGS="--coverage" LDFLAGS="--coverage"
Expand All @@ -108,8 +125,11 @@ matrix:
script:
- export PATH=$(pwd)/mason_packages/.link/bin/:${PATH}
- which llvm-cov
- pip install --user codecov
- codecov --gcov-exec "llvm-cov gcov -l"
- curl -S -f https://codecov.io/bash -o codecov
- chmod +x codecov
# Workaround until we can avoid problem after https://github.com/travis-ci/travis-build/pull/1263 lands
- PATH=$(echo "$PATH" | sed 's/.\/node_modules\/.bin://')
- ./codecov -x "llvm-cov gcov" -Z
# Clang format build
- os: linux
# can be generic since we don't need nodejs to run formatting
Expand All @@ -123,8 +143,10 @@ matrix:
- make format
# Overrides `before_script`, no need to run tests
before_script:
- true
# Overrides `script` to disable publishing
script:
- true
# Clang tidy build
- os: linux
env: CLANG_TIDY
Expand All @@ -138,5 +160,7 @@ matrix:
- make tidy
# Overrides `before_script`, no need to run tests
before_script:
- true
# Overrides `script` to disable publishing
script:
- true
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ export WERROR ?= true
# just typing `make` will call `make release`
default: release

node_modules/nan:
node_modules/node-addon-api:
npm install --ignore-scripts

mason_packages/headers: node_modules/nan
mason_packages/headers: node_modules/node-addon-api
node_modules/.bin/mason-js install

mason_packages/.link/include: mason_packages/headers
Expand Down
9 changes: 4 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
![dancing skel](https://mapbox.s3.amazonaws.com/cpp-assets/node-cpp-skel-readme_blue.png)
[![Build Status](https://travis-ci.org/mapbox/node-cpp-skel.svg?branch=master)](https://travis-ci.org/mapbox/node-cpp-skel)
[![codecov](https://codecov.io/gh/mapbox/node-cpp-skel/branch/master/graph/badge.svg)](https://codecov.io/gh/mapbox/node-cpp-skel)

A skeleton for binding C++ libraries to Node.js using [Nan](https://github.com/nodejs/nan). This is a small, helper repository that generates simple `HelloWorld` Javascript example constructors. The examples have a number of methods to demonstrate different ways to use Nan for building particular types of functionality (i.e. asynchronous functions). Use this repo as both a template for your own code as well as a learning tool if you're just starting to develop Node/C++ Addons.
A skeleton for building a C++ addon for Node.js. This is a small, helper repository that generates simple `HelloWorld` Javascript example constructors. The examples have a number of methods to demonstrate different ways to use the Node C+ API for building particular types of functionality (i.e. asynchronous functions). Use this repo as both a template for your own code as well as a learning tool if you're just starting to develop Node/C++ Addons.

**Why port C++ to Node.js?**. That's a great question! C++ is a high performance language that allows you to execute operations without clogging up the event loop. Node.js is single-threaded, which blocks execution. Even in highly optimized javascript code it may be impossible to improve performance. Passing heavy operations into C++ and subsequently into C++ workers can greatly improve the overall runtime of the code. Porting C++ code to Node.js is also referred to as creating an ["Addon"](https://github.com/mapbox/cpp/blob/master/node-cpp.md).

**Nan**: Nan is used in many C++ => Node.js port projects, such as [node-mapnik](https://github.com/mapnik/node-mapnik), [node-osrm](https://github.com/Project-OSRM/node-osrm), and [node-osmium](https://github.com/osmcode/node-osmium). More examples of how to port C++ libraries to node can be found at [nodejs.org/api/addons.html](https://nodejs.org/api/addons.html). See https://nodesource.com/blog/c-add-ons-for-nodejs-v4/ for a detailed summary of the origins of Nan.

[![Build Status](https://travis-ci.org/mapbox/node-cpp-skel.svg?branch=master)](https://travis-ci.org/mapbox/node-cpp-skel)
[![codecov](https://codecov.io/gh/mapbox/node-cpp-skel/branch/master/graph/badge.svg)](https://codecov.io/gh/mapbox/node-cpp-skel)
More examples of how to port C++ libraries to node can be found at [nodejs.org/api/addons.html](https://nodejs.org/api/addons.html).

# What's in the box? :package:

Expand Down
2 changes: 1 addition & 1 deletion binding.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
# It's a variable to make easy to pass to
# cflags (linux) and xcode (mac)
'system_includes': [
"-isystem <(module_root_dir)/<!(node -e \"require('nan')\")",
"-isystem <!@(node -p \"require('node-addon-api').include.slice(1,-1)\")",
"-isystem <(module_root_dir)/mason_packages/.link/include/"
],
# Flags we pass to the compiler to ensure the compiler
Expand Down
8 changes: 4 additions & 4 deletions docs/extended-tour.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ This skeleton includes a few examples of how you might design your application,


### When would you use a standalone function?
A standalone function is a function that exists at the top level of the module scope rather than as a member of an object that is instantiated. So if your module is `wonderful`, a standalone function would be called like `wonderful.callme()`.
A standalone function is a function that exists at the top level of the module scope rather than as a member of an object that is instantiated. So if your module is `wonderful`, a standalone function would be called like `wonderful.callme()`.

A standalone function makes sense when the only data needed by the function can be easily passed as arguments. When it is not easy or clean to pass data as arguments then you should consider encapsulation, for example, exposing a function as a member of an object. One of the benefits of creating a standalone function is that it can help [separate concerns](https://en.wikipedia.org/wiki/Separation_of_concerns), which is mainly a stylistic design decision.

Expand All @@ -32,12 +32,12 @@ Example:
### When would you use an object/class?
Create an object/class when you need to do some kind of data preprocessing before going into the thread pool. It's best to write your code so that the preprocessing happens _once_ as a separate operation, then continues through to the thread pool after the preprocessing is finished and the object is ready. Examples:
- [node-mapnik](https://github.com/mapnik/node-mapnik/blob/fe80ce5d79c0e90cfbb5a2b992bf0ae2b8f88198/src/mapnik_map.hpp#L20): we create a Map object once, then use the object multiple times for rendering each vector tile.
- [node-addon-examples](https://github.com/nodejs/node-addon-examples/tree/master/6_object_wrap/nan) for another example of what an object-focused Addon looks like.
- [node-addon-examples](https://github.com/nodejs/node-addon-examples/tree/master/6_object_wrap/node-addon-api) for another example of what an object-focused Addon looks like.

Objects/Classes are useful when you start doing more complex operations and need to consider performance more heavily, when performance constraints start to matter. Use classes to compute the value of something once, rather than every time you call a function.

One step further is using an asynchronous object or class, which enables you to pass data into the threadpool. The aim is to process data in the threadpool in the most efficient way possible. [Efficiency](https://github.com/mapbox/cpp/blob/master/glossary.md#efficiency) and high performance are the main goals of the `HelloObjectAsync` example in this skel. The `HelloObjectAsync` example demonstrates high load, when _many_ objects in _many_ threads are being allocated. This scenario is where reducing unnecessary allocations really pays off, and is also why this example uses "move semantics" for even better performance.
- **Move semantics**: move semantics avoid data being copied (allocating memory), to limit unnecessary memory allocation, and are most useful when working with big data.
- **Move semantics**: move semantics avoid data being copied (allocating memory), to limit unnecessary memory allocation, and are most useful when working with big data.

Other thoughts related to move semantics:
- Always best to use move semantics instead of passing by reference, espeically with objects like [`std::string`](http://shaharmike.com/cpp/std-string/), which can be expensive.
Expand Down Expand Up @@ -175,7 +175,7 @@ This binary file `../lib/binding/module.node` is what `require()` points to with

# Clang Tools

This skeleton uses two clang/llvm tools for automated formatting and static fixes.
This skeleton uses two clang/llvm tools for automated formatting and static fixes.

Each of these tools run within their own [Travis jobs](https://github.com/mapbox/node-cpp-skel/blob/master/.travis.yml). You can disable these Travis jobs if you'd like, by commenting them out in `.travis.yml`. This may be necessary if you're porting this skel into an already-existing project that triggers tons of clang-tidy errors, and you'd like to work through them gradually while still actively iterating on other parts of your code.

Expand Down
Loading