whole refactor wip
This commit is contained in:
parent
6b2249706e
commit
d3800f9270
261
README.md
261
README.md
|
@ -1,2 +1,259 @@
|
||||||
# node-addon-tools
|
# Addon Tools
|
||||||
A set of extra macros for node addons, shipped as C++ header file.
|
|
||||||
|
|
||||||
|
## Synopsis
|
||||||
|
|
||||||
|
This is a set of helpers for simplification and standardization of addons and
|
||||||
|
dependency packages.
|
||||||
|
|
||||||
|
* Contains helpers of following types: GYP, C++, JS, BAT(Windows).
|
||||||
|
* Platforms: win x32/x64, linux x32/x64, mac x64.
|
||||||
|
* Useful links: [V8 Ref](https://v8docs.nodesource.com/node-0.8/d2/dc3/namespacev8.html),
|
||||||
|
[Nan Docs](https://github.com/nodejs/nan#api),
|
||||||
|
[GYP Docs](https://gyp.gsrc.io/docs/UserDocumentation.md).
|
||||||
|
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
`npm i -s node-addon-tools-raub`
|
||||||
|
|
||||||
|
|
||||||
|
## Contents
|
||||||
|
[addon-tools.gypi](#addon-tools_gypi)
|
||||||
|
[include/addon-tools.hpp](#include_addon-tools_hpp)
|
||||||
|
[index.js](#index_js)
|
||||||
|
[\_rd.bat / \_del.bat](#_rd.bat-_-_del.bat)
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## addon-tools.gypi
|
||||||
|
|
||||||
|
Include this gyp file into your `bindings.gyp`.
|
||||||
|
|
||||||
|
```
|
||||||
|
'includes': [ '<!(node -e "require(\'node-addon-tools-raub\').gypi")' ],
|
||||||
|
```
|
||||||
|
|
||||||
|
This will add Nan and Addon Tools include paths to all your targets. Also variables
|
||||||
|
`_rd` and `_del` are set for convenience.
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## include/addon-tools.hpp
|
||||||
|
|
||||||
|
There is a C++ header file, `addon-tools.hpp`, shipped with this package. It
|
||||||
|
introduces several useful macros and utilities. Also it includes Nan automatically,
|
||||||
|
so that you can replace.
|
||||||
|
|
||||||
|
```
|
||||||
|
// #include <v8.h> // node.h includes it
|
||||||
|
// #include <node.h> // nan.h includes it
|
||||||
|
#include <nan.h>
|
||||||
|
```
|
||||||
|
|
||||||
|
with
|
||||||
|
|
||||||
|
```
|
||||||
|
#include <addon-tools.hpp>
|
||||||
|
```
|
||||||
|
|
||||||
|
In gyp, the include directory should be set for your addon to know where to get it.
|
||||||
|
As it was mentioned above, this can be done automatically. Also an actual path to the
|
||||||
|
directory is exported from the module and is accessible like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
require('node-addon-tools-raub').include
|
||||||
|
```
|
||||||
|
|
||||||
|
In the file, currently there are following helpers:
|
||||||
|
|
||||||
|
|
||||||
|
#### Handle scope
|
||||||
|
|
||||||
|
* `NAN_HS` - creates a HandleScope. Also, you do not need them within `NAN_METHOD`,
|
||||||
|
`NAN_SETTER`, and `NAN_GETTER`, as it is stated in
|
||||||
|
[Nan doc](https://github.com/nodejs/nan/blob/master/doc/methods.md#api_nan_method).
|
||||||
|
So it is most likely to be used in native callbacks.
|
||||||
|
|
||||||
|
```
|
||||||
|
void windowFocusCB(GLFWwindow *window, int focused) { NAN_HS;
|
||||||
|
...
|
||||||
|
}
|
||||||
|
...
|
||||||
|
glfwSetWindowFocusCallback(window, windowFocusCB);
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
#### Method return
|
||||||
|
|
||||||
|
* RET_VALUE(VAL) - set method return value
|
||||||
|
* RET_UNDEFINED - set method return value as undefined
|
||||||
|
|
||||||
|
|
||||||
|
#### New JS value
|
||||||
|
|
||||||
|
* JS_STR(...) - create a string value
|
||||||
|
* JS_INT(val) - create an integer value
|
||||||
|
* JS_NUM(val) - create a numeric value
|
||||||
|
* JS_EXT(val) - create an external (pointer) value
|
||||||
|
* JS_BOOL(val) - create a boolean value
|
||||||
|
|
||||||
|
|
||||||
|
#### Method check
|
||||||
|
|
||||||
|
These checks throw JS TypeError if not passed. Here `T` is always used as a typename
|
||||||
|
in error messages. `C` is
|
||||||
|
[v8::Value](https://v8docs.nodesource.com/node-0.8/dc/d0a/classv8_1_1_value.html)
|
||||||
|
check method, like `IsObject()`. `I` is the index of argument as in `info[I]`,
|
||||||
|
starting from `0`.
|
||||||
|
|
||||||
|
* REQ_ARGS(N) - check if at least `N` arguments passed
|
||||||
|
* IS_ARG_EMPTY(I) - check if argument `I` is `undefined` or `null`
|
||||||
|
* CHECK_REQ_ARG(I, C, T) - check if argument `I` is approved by `C` check.
|
||||||
|
* CHECK_LET_ARG(I, C, T) - check if argument `I` is approved by `C` check or empty.
|
||||||
|
* CTOR_CHECK(T) - check if method is called as a constructor
|
||||||
|
* SETTER_CHECK(C, T) - check if setter `value` is approved by `C` check.
|
||||||
|
|
||||||
|
|
||||||
|
#### Method arguments
|
||||||
|
|
||||||
|
Two types of argument retrieval are supported: `REQ_` and `LET_`. The difference
|
||||||
|
is that `LET_` allows the argument to be empty, using some zero-default in this case.
|
||||||
|
`I` is the index of argument as in `info[I]`,
|
||||||
|
starting from `0`. `VAR` is the name of the `Local<Value>` variable to be created.
|
||||||
|
|
||||||
|
* REQ_UTF8_ARG(I, VAR)
|
||||||
|
* LET_UTF8_ARG(I, VAR)
|
||||||
|
* REQ_INT32_ARG(I, VAR)
|
||||||
|
* LET_INT32_ARG(I, VAR)
|
||||||
|
* REQ_BOOL_ARG(I, VAR)
|
||||||
|
* LET_BOOL_ARG(I, VAR)
|
||||||
|
* REQ_UINT32_ARG(I, VAR)
|
||||||
|
* LET_UINT32_ARG(I, VAR)
|
||||||
|
* REQ_OFFS_ARG(I, VAR)
|
||||||
|
* LET_OFFS_ARG(I, VAR)
|
||||||
|
* REQ_DOUBLE_ARG(I, VAR)
|
||||||
|
* LET_DOUBLE_ARG(I, VAR)
|
||||||
|
* REQ_FLOAT_ARG(I, VAR)
|
||||||
|
* LET_FLOAT_ARG(I, VAR)
|
||||||
|
* REQ_EXT_ARG(I, VAR)
|
||||||
|
* LET_EXT_ARG(I, VAR)
|
||||||
|
* REQ_FUN_ARG(I, VAR)
|
||||||
|
* REQ_OBJ_ARG(I, VAR)
|
||||||
|
* REQ_ARRV_ARG(I, VAR)
|
||||||
|
|
||||||
|
```
|
||||||
|
NAN_METHOD(testScene) {
|
||||||
|
|
||||||
|
REQ_UINT32_ARG(0, width);
|
||||||
|
REQ_UINT32_ARG(1, height);
|
||||||
|
LET_FLOAT_ARG(2, z);
|
||||||
|
// Variables created: unsigned int width, height; float z;
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
#### Set properties
|
||||||
|
|
||||||
|
Set-helpers for string and numeric keys. String keys are converted to JS strings
|
||||||
|
automatically.
|
||||||
|
|
||||||
|
* SET_PROP(OBJ, KEY, VAL)
|
||||||
|
* SET_I(ARR, I, VAL)
|
||||||
|
|
||||||
|
|
||||||
|
#### Set object accessors
|
||||||
|
|
||||||
|
Simplified accessor assignment, adds accessors of NAME for OBJ. Read accessor is
|
||||||
|
assumed to have the name `NAME+'Getter'` and write accessor is `NAME+'Setter'`.
|
||||||
|
|
||||||
|
* ACCESSOR_RW(OBJ, NAME) - add read and write accessors of NAME for OBJ.
|
||||||
|
* ACCESSOR_R(OBJ, NAME) - read-only property.
|
||||||
|
|
||||||
|
```
|
||||||
|
void MyClass::init(Handle<Object> target) {
|
||||||
|
...
|
||||||
|
Local<ObjectTemplate> proto = ctor->PrototypeTemplate();
|
||||||
|
ACCESSOR_RW(proto, message);
|
||||||
|
...
|
||||||
|
}
|
||||||
|
NAN_GETTER(MyClass::messageGetter) { ...
|
||||||
|
NAN_SETTER(MyClass::messageSetter) { ...
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
#### Setter argument
|
||||||
|
|
||||||
|
Useful addition to NAN_SETTER macro.
|
||||||
|
|
||||||
|
* SETTER_UTF8_ARG
|
||||||
|
* SETTER_INT32_ARG
|
||||||
|
* SETTER_BOOL_ARG
|
||||||
|
* SETTER_UINT32_ARG
|
||||||
|
* SETTER_OFFS_ARG
|
||||||
|
* SETTER_DOUBLE_ARG
|
||||||
|
* SETTER_FLOAT_ARG
|
||||||
|
* SETTER_EXT_ARG
|
||||||
|
* SETTER_FUN_ARG
|
||||||
|
* SETTER_OBJ_ARG
|
||||||
|
|
||||||
|
```
|
||||||
|
NAN_SETTER(MyClass::messageSetter) { SETTER_UTF8_ARG;
|
||||||
|
// Variable created: Nan::Utf8String v;
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
#### Data retrieval
|
||||||
|
|
||||||
|
* `T *getArrayData(value, num = NULL)` - extracts TypedArray data of any type from
|
||||||
|
the given JS value. Does not accept Array, checked with `IsArrayBufferView()`.
|
||||||
|
Returns `NULL` for empty JS values. For unacceptable values throws TypeError.
|
||||||
|
|
||||||
|
|
||||||
|
* `BYTE *getImageData(value)` - if value is a TypedArray, then the result of
|
||||||
|
`getArrayData(value)` is returned. Otherwise if value has `'data'` property, it's
|
||||||
|
content is then returned as `node::Buffer`. Returns `NULL` for empty JS values.
|
||||||
|
For unacceptable values throws TypeError.
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## index.js
|
||||||
|
|
||||||
|
Exports:
|
||||||
|
* `paths(dir)` - function. Returns a set of platform dependent paths depending on
|
||||||
|
input `dir`.
|
||||||
|
* `bin` - platform binary path.
|
||||||
|
* `rem` - a space-separated list of binary paths to be cleaned on this platform.
|
||||||
|
* `include` - include directory for this `dir`.
|
||||||
|
* `root` - where `'node-addon-tools-raub'` module is situated.
|
||||||
|
* `include` - `'node-addon-tools-raub'` own 'include' directory.
|
||||||
|
* `_rd` - the location of `'_rd.bat'` file.
|
||||||
|
* `_del` - the location of `'_del.bat'` file.
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## \_rd.bat / \_del.bat
|
||||||
|
|
||||||
|
Windows-only utilities. Because in gyp any `/` on Windows is converted to `\`, it is
|
||||||
|
impossible to put correct commands for file/directory removal. Those need such
|
||||||
|
parameters as `/Q`, but gyp makes them `\Q` which is inappropriate. So these files
|
||||||
|
simply contain their respective commands with all necessary parameters, avoiding any
|
||||||
|
conflict with gyp.
|
||||||
|
|
||||||
|
```
|
||||||
|
...
|
||||||
|
[ 'OS=="mac"', { 'action' : [
|
||||||
|
'rm',
|
||||||
|
'<(module_root_dir)/build/Release/obj.target/addon/cpp/bindings.o',
|
||||||
|
'<(module_root_dir)/build/Release/addon.node'
|
||||||
|
] } ],
|
||||||
|
[ 'OS=="win"', { 'action' : [
|
||||||
|
'<(_del) "<(module_root_dir)/build/Release/addon.*" && ' +
|
||||||
|
'<(_del) "<(module_root_dir)/build/Release/obj/addon/*.*"'
|
||||||
|
] } ],
|
||||||
|
```
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
'variables': {
|
||||||
|
'_rd' : '<!(node -e "console.log(require(\'node-addon-tools-raub\')._rd)")',
|
||||||
|
'_del' : '<!(node -e "console.log(require(\'node-addon-tools-raub\')._del)")',
|
||||||
|
},
|
||||||
|
'target_defaults': {
|
||||||
|
'include_dirs': [
|
||||||
|
'<!(node -e "require(\'nan\')")',
|
||||||
|
'<!(node -e "console.log(require(\'node-addon-tools-raub\').include)")',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}
|
|
@ -2,6 +2,9 @@
|
||||||
#define _ADDON_TOOLS_HPP_
|
#define _ADDON_TOOLS_HPP_
|
||||||
|
|
||||||
|
|
||||||
|
#include <nan.h>
|
||||||
|
|
||||||
|
|
||||||
#define NAN_HS Nan::HandleScope scope;
|
#define NAN_HS Nan::HandleScope scope;
|
||||||
|
|
||||||
|
|
||||||
|
@ -10,15 +13,12 @@
|
||||||
|
|
||||||
|
|
||||||
#define JS_STR(...) Nan::New<String>(__VA_ARGS__).ToLocalChecked()
|
#define JS_STR(...) Nan::New<String>(__VA_ARGS__).ToLocalChecked()
|
||||||
#define JS_INT(val) Nan::New<v8::Integer>(val)
|
#define JS_INT(val) Nan::New<Integer>(val)
|
||||||
#define JS_NUM(val) Nan::New<v8::Number>(val)
|
#define JS_NUM(val) Nan::New<Number>(val)
|
||||||
#define JS_EXT(val) Nan::New<v8::External>(reinterpret_cast<void*>(val))
|
#define JS_EXT(val) Nan::New<External>(reinterpret_cast<void*>(val))
|
||||||
#define JS_BOOL(val) (val) ? Nan::True() : Nan::False()
|
#define JS_BOOL(val) (val) ? Nan::True() : Nan::False()
|
||||||
|
|
||||||
|
|
||||||
#define JS_RETHROW(tc) v8::Local<v8::Value>::New(tc.Exception());
|
|
||||||
|
|
||||||
|
|
||||||
#define REQ_ARGS(N) \
|
#define REQ_ARGS(N) \
|
||||||
if (info.Length() < (N)) \
|
if (info.Length() < (N)) \
|
||||||
return Nan::ThrowTypeError("Expected at least " #N " arguments");
|
return Nan::ThrowTypeError("Expected at least " #N " arguments");
|
||||||
|
|
44
index.js
44
index.js
|
@ -1,5 +1,45 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
console.log(`${__dirname}/include`);
|
|
||||||
|
|
||||||
module.exports = __dirname;
|
const allDirs = ['bin_win32', 'bin_win64', 'bin_linux32', 'bin_linux64', 'bin_mac64'];
|
||||||
|
|
||||||
|
const platformDirs = {
|
||||||
|
get win32() { return process.arch === 'x64' ? 'bin_win64' : 'bin_win32'; },
|
||||||
|
get linux() { return process.arch === 'x64' ? 'bin_linux64' : 'bin_linux32'; },
|
||||||
|
get darwin() { return 'bin_mac64'; },
|
||||||
|
};
|
||||||
|
|
||||||
|
const binDir = platformDirs[process.platform];
|
||||||
|
|
||||||
|
const remDirs = allDirs.splice(allDirs.indexOf(binDir), 1);
|
||||||
|
|
||||||
|
|
||||||
|
const paths = dir => {
|
||||||
|
|
||||||
|
const binPath = `${dir}/${binDir}`;
|
||||||
|
|
||||||
|
if (process.platform === 'win32') {
|
||||||
|
process.env.path = `${process.env.path ? `${process.env.path};` : ''}${binPath}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
bin : binPath,
|
||||||
|
rem : remDirs.map(k => `${dir.replace(/\\/g, '/')}/${k}`).join(' '),
|
||||||
|
include : `${dir}/include`,
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
|
||||||
|
paths,
|
||||||
|
|
||||||
|
root : __dirname,
|
||||||
|
gypi : `${__dirname}/addon-tools.gypi`,
|
||||||
|
include : `${__dirname}/include`,
|
||||||
|
|
||||||
|
_rd :`${__dirname}/_rd.bat`,
|
||||||
|
_del :`${__dirname}/_del.bat`,
|
||||||
|
|
||||||
|
};
|
||||||
|
|
12
package.json
12
package.json
|
@ -1,14 +1,17 @@
|
||||||
{
|
{
|
||||||
"name": "node-addon-tools-raub",
|
"name": "node-addon-tools-raub",
|
||||||
"author": "Luis Blanco <raubtierxxx@gmail.com>",
|
"author": "Luis Blanco <raubtierxxx@gmail.com>",
|
||||||
"description": "A set of extra macros for node addons, shipped as C++ header file.",
|
"description": "A set of extra tools for Node.js addons.",
|
||||||
"version": "0.0.5",
|
"version": "0.0.6",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"node",
|
"node",
|
||||||
"addon",
|
"addon",
|
||||||
"header",
|
"header",
|
||||||
"include"
|
"include",
|
||||||
|
"platform",
|
||||||
|
"build",
|
||||||
|
"paths",
|
||||||
],
|
],
|
||||||
"maintainers": [
|
"maintainers": [
|
||||||
{
|
{
|
||||||
|
@ -21,5 +24,8 @@
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/raub/node-addon-tools.git"
|
"url": "https://github.com/raub/node-addon-tools.git"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"nan": "2.8.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue