diff --git a/.gitignore b/.gitignore
index 535e588..89eb7b3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,11 +1,8 @@
-.idea
.cproject
-.project
+.idea
.lock-wscript
-build*/
.DS_Store
-Debug/
+.project
node_modules/
package-lock.json
-binary/
*.log
diff --git a/.npmignore b/.npmignore
index 8ebed11..899fcd7 100644
--- a/.npmignore
+++ b/.npmignore
@@ -1,15 +1,12 @@
-*.log
.cproject
-.eslintrc
-.gitignore
.idea
.lock-wscript
+.DS_Store
.project
-binary/
-build*/
-CPPLINT.cfg
-Debug/
-examples/
+node_modules/
package-lock.json
+.gitignore
+CPPLINT.cfg
+.eslintrc
test/
-qt/
+*.log
diff --git a/.travis.yml b/.travis.yml
index 1913e0b..5553916 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,7 +1,7 @@
language: node_js
node_js:
- - "10.13.0"
+ - "10.16.1"
matrix:
diff --git a/README.md b/README.md
index 6252415..72b0f6e 100644
--- a/README.md
+++ b/README.md
@@ -14,14 +14,15 @@ This is a part of [Node3D](https://github.com/node-3d) project.
Helpers for Node.js addons and dependency packages:
-* `consoleLog()` C++ implementation.
-* `EventEmitter` C++ implementation.
* C++ macros and shortcuts.
+* `consoleLog()` C++ helper.
+* `eventEmit()` C++ helper.
+* `getData()` C++ helper.
* Crossplatform commands for GYP: `cp`, `rm`, `mkdir`.
-* Regarded platforms: win x32/x64, linux x64, mac x64.
+* Supported platforms (x64): Windows, Linux, OSX.
-Useful links: [V8 Ref](https://v8.paulfryzel.com/docs/master/),
-[Nan Docs](https://github.com/nodejs/nan#api),
+Useful links: [N-API Docs](https://nodejs.org/api/n-api.html),
+[Napi Docs](https://github.com/nodejs/node-addon-api/blob/master/doc/setup.md),
[GYP Docs](https://gyp.gsrc.io/docs/UserDocumentation.md).
---
@@ -37,10 +38,10 @@ Useful links: [V8 Ref](https://v8.paulfryzel.com/docs/master/),
[Crossplatform commands](#crossplatform-commands)
-[Class EventEmitter](#class-eventemitter)
-
[Function consoleLog](#function-consolelog)
+[Function eventEmit](#function-eventEmit)
+
---
@@ -49,85 +50,39 @@ Useful links: [V8 Ref](https://v8.paulfryzel.com/docs/master/),
### binding.gyp
-
+### Crossplatform commands
-Crossplatform commands
-
- ```
- 'variables': {
- 'rm' : '
+```
+'variables': {
+ 'rm' : '
+### Addon binary directory
-Addon binary directory
-
- ```
- 'variables': {
- 'binary' : '
+```
+'variables': {
+ 'binary' : '
+### Include directories
-Include directories
-
- ```
- 'include_dirs': [
- '
+```
+ 'include_dirs': [
+ '
-
-Remove intermediates
-
- ```
- [ 'OS=="linux"', { 'action' : [
- '<(rm)',
- '<(module_root_dir)/build/Release/obj.target/addon/cpp/addon.o',
- '<(module_root_dir)/build/Release/addon.node'
- ] } ],
- [ 'OS=="mac"', { 'action' : [
- '<(rm)',
- '<(module_root_dir)/build/Release/obj.target/addon/cpp/addon.o',
- '<(module_root_dir)/build/Release/addon.node'
- ] } ],
- [ 'OS=="win"', { 'action' : [
- '<(rm)',
- '<(module_root_dir)/build/Release/addon.*',
- '<(module_root_dir)/build/Release/obj/addon/*.*'
- ] } ],
- ```
-
- Build-files can be removed in a separate build-step with `<(rm)`. Those are
- usually PDB and OBJ files, which are rather big. However, in case of a hardcore
- debug session you might want to comment this out.
-
-
+Those are the directory paths to C++ include files for Addon Tools and Napi
+(which is preinstalled with Addon Tools)
### Binary dependency package
@@ -137,7 +92,6 @@ would encourage you to abide by the following rules:
* Your binary directories are:
- * bin-win32
* bin-win64
* bin-linux64
* bin-mac64
diff --git a/download.js b/download.js
new file mode 100644
index 0000000..6db717d
--- /dev/null
+++ b/download.js
@@ -0,0 +1,28 @@
+'use strict';
+
+const https = require('https');
+const http = require('http');
+
+const WritableBuffer = require('./writable-buffer');
+
+
+const protocols = { http, https };
+
+
+module.exports = url => new Promise((res, rej) => {
+
+ url = url.toLowerCase();
+
+ const stream = new WritableBuffer();
+ const proto = protocols[url.match(/^https?/)[0]];
+
+ proto.get(url, response => {
+
+ response.pipe(stream);
+
+ response.on('end', () => res(stream.get()));
+ response.on('error', err => rej(err));
+
+ });
+
+});
diff --git a/examples/addon/.eslintrc b/examples/addon/.eslintrc
deleted file mode 100644
index c3126e7..0000000
--- a/examples/addon/.eslintrc
+++ /dev/null
@@ -1,116 +0,0 @@
-{
- "root": true,
- "env": {
- "node" : true,
- "es6" : true,
- "mocha" : true
- },
- "globals": {
- "expect" : true,
- "chai" : true,
- "sinon" : true
- },
- "extends": ["eslint:recommended"],
- "parserOptions": {
- "ecmaVersion": 8,
- "ecmaFeatures": {
- "experimentalObjectRestSpread": true
- }
- },
- "rules": {
- "arrow-parens": ["error", "as-needed"],
- "no-trailing-spaces": [
- "error",
- {
- "skipBlankLines": true
- }
- ],
- "indent": [
- "error",
- "tab",
- {
- "SwitchCase": 1
- }
- ],
- "linebreak-style": [
- "error",
- "unix"
- ],
- "max-len": ["error", 110],
- "quotes": [
- "error",
- "single"
- ],
- "semi": [
- "error",
- "always"
- ],
- "no-multiple-empty-lines": ["error", { "max": 3, "maxEOF": 1, "maxBOF": 1 }],
- "keyword-spacing": ["error", { "before": true, "after": true }],
- "space-before-blocks": ["error"],
- "space-before-function-paren": ["error", {"anonymous": "always", "named": "never", "asyncArrow": "always"}],
- "space-infix-ops": ["error"],
- "space-unary-ops": [
- "error", {
- "words": true,
- "nonwords": false,
- "overrides": {
- "!": true
- }
- }
- ],
- "spaced-comment": [0],
- "camelcase": ["error"],
- "no-tabs": [0],
- "comma-dangle": [0],
- "global-require": [0],
- "func-names": [0],
- "no-param-reassign": [0],
- "no-underscore-dangle": [0],
- "no-restricted-syntax": [
- "error",
- {
- "selector": "LabeledStatement",
- "message": "Labels are a form of GOTO; using them makes code confusing and hard to maintain and understand."
- },
- {
- "selector": "WithStatement",
- "message": "`with` is disallowed in strict mode because it makes code impossible to predict and optimize."
- }
- ],
- "no-mixed-operators": [0],
- "no-plusplus": [0],
- "comma-spacing": [0],
- "default-case": [0],
- "no-shadow": [0],
- "no-console": [0],
- "key-spacing": [0],
- "no-return-assign": [0],
- "consistent-return": [0],
- "class-methods-use-this": [0],
- "no-multi-spaces": [
- "error",
- {
- "exceptions": {
- "VariableDeclarator": true,
- "Property": true,
- "ImportDeclaration": true
- }
- }
- ],
- "array-callback-return": [0],
- "no-use-before-define": [
- "error",
- {
- "functions": false,
- "classes": true,
- "variables": true
- }
- ],
- "padded-blocks": [0],
- "space-in-parens": [0],
- "valid-jsdoc": [0],
- "no-unused-expressions": [0],
- "import/no-dynamic-require": [0]
- }
-}
diff --git a/examples/addon/.gitignore b/examples/addon/.gitignore
deleted file mode 100644
index 5e2be6a..0000000
--- a/examples/addon/.gitignore
+++ /dev/null
@@ -1,12 +0,0 @@
-.idea
-.cproject
-.project
-.lock-wscript
-build*/
-bin-*/
-.DS_Store
-Debug/
-node_modules/
-package-lock.json
-binary/
-*.log
diff --git a/examples/addon/.npmignore b/examples/addon/.npmignore
deleted file mode 100644
index 827bee8..0000000
--- a/examples/addon/.npmignore
+++ /dev/null
@@ -1,16 +0,0 @@
-*.log
-.cproject
-.eslintrc
-.gitignore
-.idea
-.lock-wscript
-.project
-binary/
-bin-*/
-build*/
-CPPLINT.cfg
-Debug/
-examples/
-package-lock.json
-test/
-qt/
diff --git a/examples/addon/CPPLINT.cfg b/examples/addon/CPPLINT.cfg
deleted file mode 100644
index 9becc1c..0000000
--- a/examples/addon/CPPLINT.cfg
+++ /dev/null
@@ -1,15 +0,0 @@
-set noparent
-linelength=110
-filter=-legal/copyright
-filter=-build/include_order
-filter=-build/header_guard
-filter=-build/namespaces
-filter=-build/include_what_you_use
-filter=-whitespace/blank_line
-filter=-whitespace/comments
-filter=-whitespace/tab
-filter=-whitespace/end_of_line
-filter=-whitespace/indent
-filter=-whitespace/operators
-filter=-whitespace/parens
-filter=-readability/todo
diff --git a/examples/addon/binding.gyp b/examples/addon/binding.gyp
deleted file mode 100644
index 1f0863b..0000000
--- a/examples/addon/binding.gyp
+++ /dev/null
@@ -1,91 +0,0 @@
-{
- 'variables': {
- 'rm' : '
-
-#include
-
-#include "example.hpp"
-
-
-extern "C" {
-
-
-void init(V8_VAR_OBJ target) {
-
- EventEmitter::init(target);
-
- Example::init(target);
-
-}
-
-
-NODE_MODULE(example, init);
-
-
-} // extern "C"
diff --git a/examples/addon/cpp/example.cpp b/examples/addon/cpp/example.cpp
deleted file mode 100644
index fd046bb..0000000
--- a/examples/addon/cpp/example.cpp
+++ /dev/null
@@ -1,105 +0,0 @@
-#include
-
-#include "example.hpp"
-
-
-using namespace v8;
-using namespace node;
-using namespace std;
-
-
-// ------ Aux macros
-
-#define THIS_EXAMPLE \
- Example *example = ObjectWrap::Unwrap(info.This());
-
-#define THIS_CHECK \
- if (example->_isDestroyed) return;
-
-
-// ------ Constructor and Destructor
-
-Example::Example() : EventEmitter() {
-
- _isDestroyed = false;
-
-}
-
-
-Example::~Example() {
-
- _destroy();
-
-}
-
-
-NAN_METHOD(Example::cppOn) { THIS_EXAMPLE; THIS_CHECK;
-
- REQ_STR_ARG(0, name);
- REQ_FUN_ARG(1, cb);
-
- example->on(*name, cb);
-
-}
-
-
-// ------ System methods and props for ObjectWrap
-
-V8_STORE_FT Example::_protoExample;
-V8_STORE_FUNC Example::_ctorExample;
-
-
-void Example::init(V8_VAR_OBJ target) {
-
- V8_VAR_FT proto = Nan::New(newCtor);
-
- // class AudioBufferSourceNode inherits AudioScheduledSourceNode
- V8_VAR_FT parent = Nan::New(EventEmitter::_protoEventEmitter);
- proto->Inherit(parent);
-
- proto->InstanceTemplate()->SetInternalFieldCount(1);
- proto->SetClassName(JS_STR("Example"));
-
- // -------- dynamic
- Nan::SetPrototypeMethod(proto, "destroy", destroy);
- Nan::SetPrototypeMethod(proto, "cppOn", cppOn);
-
- // -------- static
- V8_VAR_FUNC ctor = Nan::GetFunction(proto).ToLocalChecked();
-
- _protoExample.Reset(proto);
- _ctorExample.Reset(ctor);
-
- Nan::Set(target, JS_STR("Example"), ctor);
-
-}
-
-
-NAN_METHOD(Example::newCtor) {
-
- CTOR_CHECK("EventEmitter");
-
- Example *example = new Example();
- example->Wrap(info.This());
-
- RET_VALUE(info.This());
-
-}
-
-
-void Example::_destroy() { DES_CHECK;
-
- _isDestroyed = true;
-
- EventEmitter::_destroy();
-
-}
-
-
-NAN_METHOD(Example::destroy) { THIS_EXAMPLE; THIS_CHECK;
-
- example->emit("destroy");
-
- example->_destroy();
-
-}
diff --git a/examples/addon/cpp/example.hpp b/examples/addon/cpp/example.hpp
deleted file mode 100644
index a250946..0000000
--- a/examples/addon/cpp/example.hpp
+++ /dev/null
@@ -1,39 +0,0 @@
-#ifndef _EXAMPLE_HPP_
-#define _EXAMPLE_HPP_
-
-
-#include
-
-
-class Example : public EventEmitter {
-
-public:
-
- ~Example();
-
- static void init(V8_VAR_OBJ target);
-
-
-protected:
-
- Example();
-
- void _destroy();
-
- static V8_STORE_FT _protoExample;
- static V8_STORE_FUNC _ctorExample;
-
- bool _isDestroyed;
-
-
-private:
-
- static NAN_METHOD(newCtor);
- static NAN_METHOD(destroy);
-
- static NAN_METHOD(cppOn);
-
-};
-
-
-#endif // _EXAMPLE_HPP_
diff --git a/examples/addon/index.js b/examples/addon/index.js
deleted file mode 100644
index 04c0ba3..0000000
--- a/examples/addon/index.js
+++ /dev/null
@@ -1,65 +0,0 @@
-'use strict';
-
-const { Example, EventEmitter } = require('./core');
-
-console.log('Example', Example);
-
-
-const example = new Example();
-
-console.log('example 0', example, 'instanceof EventEmitter', example instanceof EventEmitter);
-
-console.log('static listenerCount', EventEmitter.listenerCount);
-
-console.log('listenerCount', example.listenerCount);
-console.log('addListener', example.addListener);
-console.log('emit', example.emit);
-console.log('eventNames', example.eventNames);
-console.log('getMaxListeners', example.getMaxListeners);
-console.log('listeners', example.listeners);
-console.log('on', example.on);
-console.log('once', example.once);
-console.log('prependListener', example.prependListener);
-console.log('prependOnceListener', example.prependOnceListener);
-console.log('removeAllListeners', example.removeAllListeners);
-console.log('removeListener', example.removeListener);
-console.log('setMaxListeners', example.setMaxListeners);
-console.log('rawListeners', example.rawListeners);
-console.log('destroy', example.destroy);
-
-
-example.on('evt1', (arg1, arg2) => {
- console.log('EVT1', arg1, arg2, example.eventNames());
-});
-
-example.once('evt2', (arg1, arg2) => {
- console.log('EVT2', arg1, arg2, example.eventNames());
-});
-
-
-example.emit('evt1', 111, '221');
-example.emit('evt1', 112, '222');
-
-console.log('example.eventNames 1', example.eventNames());
-
-example.emit('evt2', 111, '221');
-
-console.log('example.eventNames 2', example.eventNames());
-
-example.emit('evt2', 112, '222');
-
-
-console.log('example 1', example);
-
-
-example.setMaxListeners(2);
-example.on('max1', () => {});
-example.on('max1', () => {});
-example.on('max1', () => {});
-
-example.on('cpp-on', (arg1, arg2) => {
- console.log('CPP_ON', arg1, arg2, example.eventNames());
-});
-example.emit('cpp-on', 555, 'abc');
-
-module.exports = Example;
diff --git a/examples/addon/package.json b/examples/addon/package.json
deleted file mode 100644
index 0d3dd95..0000000
--- a/examples/addon/package.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "name": "example",
- "version": "0.0.0",
- "private": true,
- "main": "index.js",
- "dependencies": {
- "addon-tools-raub": "https://github.com/node-3d/addon-tools-raub.git"
- }
-}
diff --git a/examples/deps/.gitignore b/examples/deps/.gitignore
deleted file mode 100644
index 744f3bd..0000000
--- a/examples/deps/.gitignore
+++ /dev/null
@@ -1,9 +0,0 @@
-node_modules
-*.log
-build*
-.DS_Store
-*.pro.user
-*.exp
-*.pdb
-*.ilk
-package-lock.json
diff --git a/examples/deps/.npmignore b/examples/deps/.npmignore
deleted file mode 100644
index d8b5772..0000000
--- a/examples/deps/.npmignore
+++ /dev/null
@@ -1,11 +0,0 @@
-node_modules
-*.log
-build*
-.DS_Store
-*.pro.user
-*.exp
-*.pdb
-*.ilk
-.gitignore
-package-lock.json
-test
diff --git a/examples/deps/bin-linux64/.keep b/examples/deps/bin-linux64/.keep
deleted file mode 100644
index e69de29..0000000
diff --git a/examples/deps/bin-mac64/.keep b/examples/deps/bin-mac64/.keep
deleted file mode 100644
index e69de29..0000000
diff --git a/examples/deps/bin-win32/.keep b/examples/deps/bin-win32/.keep
deleted file mode 100644
index e69de29..0000000
diff --git a/examples/deps/bin-win64/.keep b/examples/deps/bin-win64/.keep
deleted file mode 100644
index e69de29..0000000
diff --git a/examples/deps/binding.gyp b/examples/deps/binding.gyp
deleted file mode 100644
index 2170073..0000000
--- a/examples/deps/binding.gyp
+++ /dev/null
@@ -1,21 +0,0 @@
-{
- 'variables': {
- 'rm' : '
+#include
-#define NAN_HS Nan::HandleScope scope;
+#define NAPI_ENV Napi::Env env = info.Env();
+#define NAPI_HS Napi::HandleScope scope(env);
-#define RET_VALUE(VAL) info.GetReturnValue().Set(VAL);
-#define RET_UNDEFINED RET_VALUE(Nan::Undefined());
+#define JS_STR(val) Napi::String::New(env, val)
+#define JS_NUM(val) Napi::Number::New(env, static_cast(val))
+#define JS_EXT(val) Napi::External::New(env, reinterpret_cast(val))
+#define JS_BOOL(val) Napi::Boolean::New(env, val)
+#define JS_FUN(val) Napi::Function::Function(env, val)
+#define JS_OBJ(val) Napi::Object::Object(env, val)
-typedef v8::Local V8_VAR_VAL;
-typedef v8::Local V8_VAR_OBJ;
-typedef v8::Local V8_VAR_ARR;
-typedef v8::Local V8_VAR_ABV;
-typedef v8::Local V8_VAR_STR;
-typedef v8::Local V8_VAR_FUNC;
-typedef v8::Local V8_VAR_EXT;
-typedef v8::Local V8_VAR_FT;
-typedef v8::Local V8_VAR_OT;
-
-typedef Nan::Persistent V8_STORE_FT;
-typedef Nan::Persistent V8_STORE_FUNC;
-typedef Nan::Persistent V8_STORE_OBJ;
-typedef Nan::Persistent V8_STORE_VAL;
-
-
-#define JS_STR(...) Nan::New(__VA_ARGS__).ToLocalChecked()
-#define JS_UTF8(...) Nan::New(__VA_ARGS__).ToLocalChecked()
-#define JS_INT(val) Nan::New(val)
-#define JS_INT32(val) Nan::New(val)
-#define JS_UINT32(val) Nan::New(val)
-#define JS_NUM(val) Nan::New(val)
-#define JS_OFFS(val) Nan::New(static_cast(val))
-#define JS_FLOAT(val) Nan::New(val)
-#define JS_DOUBLE(val) Nan::New(val)
-#define JS_EXT(val) Nan::New(reinterpret_cast(val))
-#define JS_BOOL(val) (val) ? Nan::True() : Nan::False()
-#define JS_FUN(val) Nan::New(val)
-#define JS_OBJ(val) Nan::New(val)
-
-
-#define RET_STR(...) RET_VALUE(JS_STR(__VA_ARGS__))
-#define RET_UTF8(...) RET_VALUE(JS_UTF8(__VA_ARGS__))
-#define RET_INT(val) RET_VALUE(JS_INT(val))
-#define RET_INT32(val) RET_VALUE(JS_INT32(val))
-#define RET_UINT32(val) RET_VALUE(JS_UINT32(val))
+#define RET_VALUE(VAL) return VAL;
+#define RET_UNDEFINED RET_VALUE(env.Undefined())
+#define RET_NULL RET_VALUE(env.Null())
+#define RET_STR(val) RET_VALUE(JS_STR(val))
#define RET_NUM(val) RET_VALUE(JS_NUM(val))
-#define RET_OFFS(val) RET_VALUE(JS_OFFS(val))
-#define RET_FLOAT(val) RET_VALUE(JS_FLOAT(val))
-#define RET_DOUBLE(val) RET_VALUE(JS_DOUBLE(val))
#define RET_EXT(val) RET_VALUE(JS_EXT(val))
#define RET_BOOL(val) RET_VALUE(JS_BOOL(val))
#define RET_FUN(val) RET_VALUE(JS_FUN(val))
#define RET_OBJ(val) RET_VALUE(JS_OBJ(val))
+#define JS_THROW(val) \
+ Napi::Error::New(env, val).ThrowAsJavaScriptException();
+
+
#define REQ_ARGS(N) \
- if (info.Length() < (N)) \
- return Nan::ThrowTypeError("Expected at least " #N " arguments");
+ if (info.Length() < (N)) { \
+ JS_THROW("Expected at least " #N " arguments"); \
+ }
-#define IS_ARG_EMPTY(I) (info[I]->IsNull() || info[I]->IsUndefined())
+#define IS_EMPTY(val) (val.IsNull() || val.IsUndefined())
+#define IS_ARG_EMPTY(I) IS_EMPTY(info[I])
+
#define CHECK_REQ_ARG(I, C, T) \
- if (info.Length() <= (I) || ! info[I]->C) \
- return Nan::ThrowTypeError("Argument " #I " must be " T);
+ if (info.Length() <= (I) || ! info[I].C) { \
+ JS_THROW("Argument " #I " must be of type `" T "`"); \
+ }
#define CHECK_LET_ARG(I, C, T) \
- if ( ! (IS_ARG_EMPTY(I) || info[I]->C) ) \
- return Nan::ThrowTypeError("Argument " #I " must be " T " or null");
+ if ( ! (IS_ARG_EMPTY(I) || info[I].C) ) { \
+ JS_THROW( \
+ "Argument " #I \
+ " must be of type `" T \
+ "` or be `null`/`undefined`" \
+ ); \
+ }
-#define REQ_UTF8_ARG(I, VAR) \
- CHECK_REQ_ARG(I, IsString(), "string"); \
- Nan::Utf8String VAR(info[I]);
+#define REQ_STR_ARG(I, VAR) \
+ CHECK_REQ_ARG(I, IsString(), "String"); \
+ std::string VAR = info[I].ToString().Utf8Value();
-#define LET_UTF8_ARG(I, VAR) \
- CHECK_LET_ARG(I, IsString(), "string"); \
- Nan::Utf8String VAR(JS_STR(""));
+#define USE_STR_ARG(I, VAR, DEF) \
+ CHECK_LET_ARG(I, IsString(), "String"); \
+ std::string VAR = IS_ARG_EMPTY(I) ? (DEF) : info[I].ToString().Utf8Value();
+
+#define LET_STR_ARG(I, VAR) USE_STR_ARG(I, VAR, "")
-#define REQ_STR_ARG(I, VAR) REQ_UTF8_ARG(I, VAR)
-#define LET_STR_ARG(I, VAR) LET_UTF8_ARG(I, VAR)
#define REQ_INT32_ARG(I, VAR) \
- CHECK_REQ_ARG(I, IsInt32(), "int32"); \
- int VAR = info[I].As()->Value();
+ CHECK_REQ_ARG(I, IsNumber(), "Int32"); \
+ int VAR = info[I].ToNumber().Int32Value();
+
+#define USE_INT32_ARG(I, VAR, DEF) \
+ CHECK_LET_ARG(I, IsNumber(), "Int32"); \
+ int VAR = IS_ARG_EMPTY(I) ? (DEF) : info[I].Int32Value();
+
+#define LET_INT32_ARG(I, VAR) USE_INT32_ARG(I, VAR, 0)
+
+#define REQ_INT_ARG(I, VAR) REQ_INT32_ARG(I, VAR)
+#define USE_INT_ARG(I, VAR, DEF) USE_INT32_ARG(I, VAR, DEF)
+#define LET_INT_ARG(I, VAR) LET_INT32_ARG(I, VAR)
+
-#define LET_INT32_ARG(I, VAR) \
- CHECK_LET_ARG(I, IsInt32(), "int32"); \
- int VAR = IS_ARG_EMPTY(I) ? 0 : info[I].As()->Value();
-
#define REQ_UINT32_ARG(I, VAR) \
- CHECK_REQ_ARG(I, IsUint32(), "uint32"); \
- unsigned int VAR = info[I].As()->Value();
+ CHECK_REQ_ARG(I, IsNumber(), "Uint32"); \
+ unsigned int VAR = info[I].ToNumber().Uint32Value();
-#define LET_UINT32_ARG(I, VAR) \
- CHECK_LET_ARG(I, IsUint32(), "uint32"); \
- unsigned int VAR = IS_ARG_EMPTY(I) ? 0 : info[I].As()->Value();
+#define USE_UINT32_ARG(I, VAR, DEF) \
+ CHECK_LET_ARG(I, IsNumber(), "Uint32"); \
+ unsigned int VAR = IS_ARG_EMPTY(I) \
+ ? (DEF) \
+ : info[I].ToNumber().Uint32Value();
+
+#define LET_UINT32_ARG(I, VAR) USE_UINT32_ARG(I, VAR, 0)
+
+#define REQ_UINT_ARG(I, VAR) REQ_UINT_ARG(I, VAR)
+#define USE_UINT_ARG(I, VAR, DEF) USE_UINT32_ARG(I, VAR, DEF)
+#define LET_UINT_ARG(I, VAR) LET_UINT32_ARG(I, VAR)
-#define REQ_INT_ARG(I, VAR) LET_INT32_ARG(I, VAR)
-#define LET_INT_ARG(I, VAR) REQ_UINT32_ARG(I, VAR)
#define REQ_BOOL_ARG(I, VAR) \
- CHECK_REQ_ARG(I, IsBoolean(), "bool"); \
- bool VAR = info[I].As()->Value();
+ CHECK_REQ_ARG(I, IsBoolean(), "Bool"); \
+ bool VAR = info[I].ToBoolean().Value();
+
+#define USE_BOOL_ARG(I, VAR, DEF) \
+ CHECK_LET_ARG(I, IsBoolean(), "Bool"); \
+ bool VAR = IS_ARG_EMPTY(I) ? (DEF) : info[I].ToBoolean().Value();
+
+#define LET_BOOL_ARG(I, VAR) USE_BOOL_ARG(I, VAR, false)
-#define LET_BOOL_ARG(I, VAR) \
- CHECK_LET_ARG(I, IsBoolean(), "bool"); \
- bool VAR = IS_ARG_EMPTY(I) ? false : info[I].As()->Value();
#define REQ_OFFS_ARG(I, VAR) \
- CHECK_REQ_ARG(I, IsNumber(), "number"); \
- size_t VAR = static_cast(info[I].As()->Value());
+ CHECK_REQ_ARG(I, IsNumber(), "Number"); \
+ size_t VAR = static_cast(info[I].ToNumber().DoubleValue());
-#define LET_OFFS_ARG(I, VAR) \
- CHECK_LET_ARG(I, IsNumber(), "number"); \
- size_t VAR = IS_ARG_EMPTY(I) ? 0 : static_cast( \
- info[I].As()->Value() \
- );
+#define USE_OFFS_ARG(I, VAR, DEF) \
+ CHECK_LET_ARG(I, IsNumber(), "Number"); \
+ size_t VAR = IS_ARG_EMPTY(I) \
+ ? (DEF) \
+ : static_cast(info[I].ToNumber().DoubleValue());
+
+#define LET_OFFS_ARG(I, VAR) USE_OFFS_ARG(I, VAR, 0)
#define REQ_DOUBLE_ARG(I, VAR) \
- CHECK_REQ_ARG(I, IsNumber(), "number"); \
- double VAR = info[I].As()->Value();
+ CHECK_REQ_ARG(I, IsNumber(), "Number"); \
+ double VAR = info[I].ToNumber().DoubleValue();
-#define LET_DOUBLE_ARG(I, VAR) \
- CHECK_LET_ARG(I, IsNumber(), "number"); \
- double VAR = IS_ARG_EMPTY(I) ? 0.0 : info[I].As()->Value();
+#define USE_DOUBLE_ARG(I, VAR, DEF) \
+ CHECK_LET_ARG(I, IsNumber(), "Number"); \
+ double VAR = IS_ARG_EMPTY(I) ? (DEF) : info[I].ToNumber().DoubleValue();
+
+#define LET_DOUBLE_ARG(I, VAR) USE_DOUBLE_ARG(I, VAR, 0.0)
#define REQ_FLOAT_ARG(I, VAR) \
- CHECK_REQ_ARG(I, IsNumber(), "number"); \
- float VAR = static_cast(info[I].As()->Value());
+ CHECK_REQ_ARG(I, IsNumber(), "Number"); \
+ float VAR = info[I].ToNumber().FloatValue();
-#define LET_FLOAT_ARG(I, VAR) \
- CHECK_LET_ARG(I, IsNumber(), "number"); \
- float VAR = IS_ARG_EMPTY(I) ? 0.f : static_cast( \
- info[I].As()->Value() \
- );
+#define USE_FLOAT_ARG(I, VAR, DEF) \
+ CHECK_LET_ARG(I, IsNumber(), "Number"); \
+ float VAR = IS_ARG_EMPTY(I) ? (DEF) : info[I].ToNumber().FloatValue();
+
+#define LET_FLOAT_ARG(I, VAR) USE_FLOAT_ARG(I, VAR, 0.f)
#define REQ_EXT_ARG(I, VAR) \
- CHECK_REQ_ARG(I, IsExternal(), "void*"); \
- V8_VAR_EXT VAR = V8_VAR_EXT::Cast(info[I]);
+ CHECK_REQ_ARG(I, IsExternal(), "Pointer"); \
+ Napi::External VAR = info[I].As();
-#define LET_EXT_ARG(I, VAR) \
- CHECK_LET_ARG(I, IsExternal(), "number"); \
- V8_VAR_EXT VAR = IS_ARG_EMPTY(I) ? JS_EXT(nullptr) : V8_VAR_EXT::Cast(info[I]);
+#define USE_EXT_ARG(I, VAR, DEF) \
+ CHECK_LET_ARG(I, IsExternal(), "Pointer"); \
+ Napi::External VAR = IS_ARG_EMPTY(I) ? (DEF) : info[I].As();
+
+#define LET_EXT_ARG(I, VAR) USE_EXT_ARG(I, VAR, JS_EXT(nullptr))
#define REQ_FUN_ARG(I, VAR) \
- CHECK_REQ_ARG(I, IsFunction(), "function"); \
- V8_VAR_FUNC VAR = V8_VAR_FUNC::Cast(info[I]);
+ CHECK_REQ_ARG(I, IsFunction(), "Function"); \
+ Napi::Function VAR = info[I].As();
#define REQ_OBJ_ARG(I, VAR) \
- CHECK_REQ_ARG(I, IsObject(), "object"); \
- V8_VAR_OBJ VAR = V8_VAR_OBJ::Cast(info[I]);
+ CHECK_REQ_ARG(I, IsObject(), "Object"); \
+ Napi::Object VAR = info[I].As();
+
+#define USE_OBJ_ARG(I, VAR, DEF) \
+ CHECK_LET_ARG(I, IsObject(), "Object"); \
+ Napi::Object VAR = IS_ARG_EMPTY(I) ? (DEF) : info[I].As();
+
+#define LET_OBJ_ARG(I, VAR) USE_OBJ_ARG(I, VAR, info[I].As())
+
+
+#define REQ_OBJ_ARG(I, VAR) \
+ CHECK_REQ_ARG(I, IsObject(), "Object"); \
+ Napi::Object VAR = info[I].As();
+
+#define USE_OBJ_ARG(I, VAR, DEF) \
+ CHECK_LET_ARG(I, IsObject(), "Object"); \
+ Napi::Object VAR = IS_ARG_EMPTY(I) ? (DEF) : info[I].As();
+
+#define LET_OBJ_ARG(I, VAR) USE_OBJ_ARG(I, VAR, info[I].As())
#define REQ_ARRV_ARG(I, VAR) \
- REQ_OBJ_ARG(I, _obj_##VAR); \
- if( ! _obj_##VAR->IsArrayBufferView() ) \
- return Nan::ThrowTypeError("Argument " #I " must be an array buffer");\
- V8_VAR_ABV VAR = V8_VAR_ABV::Cast(_obj_##VAR);
+ CHECK_REQ_ARG(I, IsArrayBuffer(), "Object"); \
+ Napi::ArrayBuffer VAR = info[I].As();
-#define SET_PROP(OBJ, KEY, VAL) OBJ->Set(JS_STR(KEY), VAL);
-#define SET_I(ARR, I, VAL) ARR->Set(I, VAL);
+#define REQ_BUF_ARG(I, VAR) \
+ CHECK_REQ_ARG(I, IsBuffer(), "Buffer"); \
+ Napi::Buffer VAR = info[I].As< Napi::Buffer >();
#define CTOR_CHECK(T) \
if ( ! info.IsConstructCall() ) \
- return Nan::ThrowTypeError(T " must be called with the 'new' keyword.");
+ JS_THROW(T " must be called with the 'new' keyword.");
#define DES_CHECK \
if (_isDestroyed) return;
+#define THIS_CHECK \
+ NAPI_ENV; \
+ if (_isDestroyed) RET_UNDEFINED;
+
#define SETTER_CHECK(C, T) \
- if ( ! value->C ) \
- return Nan::ThrowTypeError("Value must be " T);
+ if ( ! value.C ) \
+ JS_THROW("Value must be " T);
-#define ACCESSOR_RW(OBJ, NAME) \
- Nan::SetAccessor(OBJ, JS_STR(#NAME), NAME ## Getter, NAME ## Setter);
+#define JS_METHOD(NAME) Napi::Value NAME(const Napi::CallbackInfo &info)
+#define JS_GETTER(NAME) Napi::Value NAME(const Napi::CallbackInfo &info)
+#define JS_SETTER(NAME) \
+ void NAME(const Napi::CallbackInfo &info, const Napi::Value &value)
-#define ACCESSOR_R(OBJ, NAME) \
- Nan::SetAccessor(OBJ, JS_STR(#NAME), NAME ## Getter);
+#define ACCESSOR_RW(CLASS, NAME) \
+ InstanceAccessor(#NAME, &CLASS::NAME ## Getter, &CLASS::NAME ## Setter)
+
+#define ACCESSOR_R(CLASS, NAME) \
+ InstanceAccessor(#NAME, &CLASS::NAME ## Getter, nullptr)
+
+#define ACCESSOR_M(CLASS, NAME) \
+ InstanceMethod(#NAME, &CLASS::NAME)
-#define SETTER_UTF8_ARG \
- SETTER_CHECK(IsString(), "string"); \
- Nan::Utf8String v(value);
-
-#define SETTER_STR_ARG SETTER_UTF8_ARG
+#define SETTER_STR_ARG \
+ SETTER_CHECK(IsNumber(), "String"); \
+ std::string v = value.ToString().Utf8Value();
#define SETTER_INT32_ARG \
- SETTER_CHECK(IsInt32(), "int32"); \
- int v = value.As()->Value();
+ SETTER_CHECK(IsNumber(), "Int32"); \
+ int v = value.ToNumber().Int32Value();
#define SETTER_INT_ARG SETTER_INT32_ARG
#define SETTER_BOOL_ARG \
- SETTER_CHECK(IsBoolean(), "bool"); \
- bool v = value.As()->Value();
+ SETTER_CHECK(IsBoolean(), "Bool"); \
+ bool v = value.ToBoolean().Value();
#define SETTER_UINT32_ARG \
- SETTER_CHECK(IsUint32(), "uint32"); \
- unsigned int v = value.As()->Value();
+ SETTER_CHECK(IsNumber(), "Uint32"); \
+ unsigned int v = value.ToNumber().Uint32Value();
+
+#define SETTER_UINT_ARG SETTER_UINT32_ARG
#define SETTER_OFFS_ARG \
- SETTER_CHECK(IsNumber(), "number"); \
- size_t v = static_cast(value.As()->Value());
+ SETTER_CHECK(IsNumber(), "Number"); \
+ size_t v = static_cast(value.ToNumber().DoubleValue());
#define SETTER_DOUBLE_ARG \
- SETTER_CHECK(IsNumber(), "number"); \
- double v = value.As()->Value();
+ SETTER_CHECK(IsNumber(), "Number"); \
+ double v = value.ToNumber().DoubleValue();
#define SETTER_FLOAT_ARG \
- SETTER_CHECK(IsNumber(), "number"); \
- float v = static_cast(value.As()->Value());
+ SETTER_CHECK(IsNumber(), "Number"); \
+ float v = value.ToNumber().FloatValue();
#define SETTER_EXT_ARG \
- SETTER_CHECK(IsExternal(), "void*"); \
- V8_VAR_EXT v = V8_VAR_EXT::Cast(value);
+ SETTER_CHECK(IsExternal(), "Pointer"); \
+ Napi::External v = value.As();
#define SETTER_FUN_ARG \
- SETTER_CHECK(IsFunction(), "function"); \
- V8_VAR_FUNC v = V8_VAR_FUNC::Cast(value);
+ SETTER_CHECK(IsFunction(), "Function"); \
+ Napi::Function v = value.As()
#define SETTER_OBJ_ARG \
- SETTER_CHECK(IsObject(), "object"); \
- V8_VAR_OBJ v = V8_VAR_OBJ::Cast(value);
+ SETTER_CHECK(IsObject(), "Object"); \
+ Napi::Object v = value.As()
#define SETTER_ARRV_ARG \
- SETTER_CHECK(IsObject(), "object"); \
- V8_VAR_OBJ _obj_v = V8_VAR_OBJ::Cast(value); \
- if( ! _obj_v->IsArrayBufferView() ) \
- return Nan::ThrowTypeError("The value must be an array buffer"); \
- V8_VAR_ABV v = V8_VAR_ABV::Cast(_obj_v);
-
+ SETTER_CHECK(IsArrayBuffer(), "TypedArray"); \
+ Napi::ArrayBuffer v = value.As();
+
+
+#define GET_AND_THROW_LAST_ERROR() \
+ do { \
+ const napi_extended_error_info *error_info; \
+ napi_get_last_error_info((env), &error_info); \
+ bool is_pending; \
+ napi_is_exception_pending((env), &is_pending); \
+ /* If an exception is already pending, don't rethrow it */ \
+ if (!is_pending) { \
+ const char* error_message = error_info->error_message != NULL \
+ ? error_info->error_message \
+ : "empty error message"; \
+ JS_THROW(error_message); \
+ } \
+ } while (0)
+
+#define NAPI_CALL(the_call, ATE) \
+ do { \
+ if ((the_call) != napi_ok) { \
+ GET_AND_THROW_LAST_ERROR(); \
+ ATE; \
+ } \
+ } while (0)
+
+#define JS_RUN_3(code, VAR, ATE) \
+ napi_value __RESULT_ ## VAR; \
+ NAPI_CALL( \
+ napi_run_script(env, napi_value(JS_STR(code)), &__RESULT_ ## VAR), \
+ ATE \
+ ); \
+ Napi::Value VAR(env, __RESULT_ ## VAR);
+
+#define JS_RUN_2(code, VAR) JS_RUN_3(code, VAR, return)
+#define JS_RUN JS_RUN_3
template
-inline Type* getArrayData(V8_VAR_OBJ obj, int *num = nullptr) {
+inline Type* getArrayData(Napi::Env env, Napi::Object obj, int *num = nullptr) {
Type *data = nullptr;
@@ -254,32 +318,68 @@ inline Type* getArrayData(V8_VAR_OBJ obj, int *num = nullptr) {
*num = 0;
}
- if ( ! obj->IsArrayBufferView() ) {
- Nan::ThrowError("Argument must be a TypedArray.");
+ if ( ! obj.IsArrayBuffer() ) {
+ JS_THROW("Argument must be of type `TypedArray`.");
return data;
}
- V8_VAR_ABV arr = V8_VAR_ABV::Cast(obj);
+ Napi::ArrayBuffer arr = obj.As();
if (num) {
- *num = arr->ByteLength() / sizeof(Type);
+ *num = arr.ByteLength() / sizeof(Type);
}
- data = reinterpret_cast(arr->Buffer()->GetContents().Data());
+ data = static_cast(arr.Data());
+
+ return data;
+
+}
+
+template
+inline Type* getBufferData(Napi::Env env, Napi::Object obj, int *num = nullptr) {
+
+ Type *data = nullptr;
+
+ if (num) {
+ *num = 0;
+ }
+
+ if ( ! obj.IsBuffer() ) {
+ JS_THROW("Argument must be of type `Buffer`.");
+ return data;
+ }
+
+ Napi::Buffer arr = obj.As< Napi::Buffer >();
+ if (num) {
+ *num = arr.Length() / sizeof(Type);
+ }
+ data = arr.Data();
return data;
}
-inline void *getData(V8_VAR_OBJ obj) {
+inline void *getData(Napi::Env env, Napi::Object obj) {
void *pixels = nullptr;
- if (obj->IsArrayBufferView()) {
- pixels = getArrayData(obj);
- } else if (obj->Has(JS_STR("data"))) {
- V8_VAR_VAL data = Nan::Get(obj, JS_STR("data")).ToLocalChecked();
- if ( ! data->IsNullOrUndefined() ) {
- pixels = node::Buffer::Data(data);
+ if (obj.IsArrayBuffer()) {
+ pixels = getArrayData(env, obj);
+ } else if (obj.IsTypedArray()) {
+ pixels = getArrayData(
+ env,
+ obj.As().ArrayBuffer()
+ );
+ } else if (obj.Has("data")) {
+ Napi::Object data = obj.Get("data").As();
+ if (data.IsArrayBuffer()) {
+ pixels = getArrayData(env, data);
+ } else if (data.IsBuffer()) {
+ pixels = getBufferData(env, data);
+ } else if (data.IsTypedArray()) {
+ pixels = getArrayData(
+ env,
+ data.As().ArrayBuffer()
+ );
}
}
@@ -288,28 +388,49 @@ inline void *getData(V8_VAR_OBJ obj) {
}
-inline void consoleLog(int argc, V8_VAR_VAL *argv) {
+inline void consoleLog(Napi::Env env, int argc, Napi::Value *argv) {
- V8_VAR_STR code = JS_STR("((...args) => console.log(...args))");
+ JS_RUN_2("((...args) => console.log(...args))", log);
+ std::vector args;
+ for (int i = 0; i < argc; i++) {
+ args.push_back(napi_value(argv[i]));
+ }
- v8::Local log = v8::Script::Compile(
- Nan::GetCurrentContext(), code
- ).ToLocalChecked()->Run(
- Nan::GetCurrentContext()
- ).ToLocalChecked();
- Nan::Callback logCb(Nan::To(log).ToLocalChecked());
-
- Nan::AsyncResource async("consoleLog()");
-
- logCb.Call(argc, argv, &async);
+ log.As().Call(napi_value(env.Null()), args);
}
-inline void consoleLog(const std::string &message) {
+inline void consoleLog(Napi::Env env, const std::string &message) {
- V8_VAR_VAL arg = JS_STR(message);
- consoleLog(1, &arg);
+ Napi::Value arg = JS_STR(message);
+ consoleLog(env, 1, &arg);
+
+}
+
+
+inline void eventEmit(
+ Napi::Env env,
+ Napi::Object that,
+ const std::string &name,
+ int argc = 0,
+ Napi::Value *argv = nullptr
+) {
+
+ if ( ! that.Has("emit") ) {
+ return;
+ }
+
+ Napi::String eventName = JS_STR(name);
+ Napi::Function thatEmit = that.Get("emit").As();
+
+ std::vector args;
+ args.push_back(napi_value(eventName));
+ for (int i = 0; i < argc; i++) {
+ args.push_back(napi_value(argv[i]));
+ }
+
+ thatEmit.Call(napi_value(that), args);
}
diff --git a/include/event-emitter.hpp b/include/event-emitter.hpp
deleted file mode 100644
index e5a2f1a..0000000
--- a/include/event-emitter.hpp
+++ /dev/null
@@ -1,723 +0,0 @@
-#ifndef _EVENT_EMITTER_
-#define _EVENT_EMITTER_
-
-
-#include
-
-#include
-#include