From d3800f927083e51755ed09a2bf5a8211342bb5e1 Mon Sep 17 00:00:00 2001 From: raub Date: Wed, 17 Jan 2018 11:58:44 +0300 Subject: [PATCH] whole refactor wip --- README.md | 261 +++++++++++++++++++++++++++++++++++++++- _del.bat | 1 + _rd.bat | 1 + addon-tools.gypi | 12 ++ include/addon-tools.hpp | 12 +- index.js | 44 ++++++- package.json | 12 +- 7 files changed, 330 insertions(+), 13 deletions(-) create mode 100644 _del.bat create mode 100644 _rd.bat create mode 100644 addon-tools.gypi diff --git a/README.md b/README.md index 445c2fa..04ae73b 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,259 @@ -# node-addon-tools -A set of extra macros for node addons, shipped as C++ header file. +# Addon Tools + + +## 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.h includes it +// #include // nan.h includes it +#include +``` + +with + +``` +#include +``` + +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` 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 target) { + ... + Local 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/*.*"' +] } ], +``` diff --git a/_del.bat b/_del.bat new file mode 100644 index 0000000..1cd56ed --- /dev/null +++ b/_del.bat @@ -0,0 +1 @@ +del /f /q %* diff --git a/_rd.bat b/_rd.bat new file mode 100644 index 0000000..0f065b0 --- /dev/null +++ b/_rd.bat @@ -0,0 +1 @@ +rd /S /Q %* diff --git a/addon-tools.gypi b/addon-tools.gypi new file mode 100644 index 0000000..45c8399 --- /dev/null +++ b/addon-tools.gypi @@ -0,0 +1,12 @@ +{ + 'variables': { + '_rd' : ' + + #define NAN_HS Nan::HandleScope scope; @@ -10,15 +13,12 @@ #define JS_STR(...) Nan::New(__VA_ARGS__).ToLocalChecked() -#define JS_INT(val) Nan::New(val) -#define JS_NUM(val) Nan::New(val) -#define JS_EXT(val) Nan::New(reinterpret_cast(val)) +#define JS_INT(val) Nan::New(val) +#define JS_NUM(val) Nan::New(val) +#define JS_EXT(val) Nan::New(reinterpret_cast(val)) #define JS_BOOL(val) (val) ? Nan::True() : Nan::False() -#define JS_RETHROW(tc) v8::Local::New(tc.Exception()); - - #define REQ_ARGS(N) \ if (info.Length() < (N)) \ return Nan::ThrowTypeError("Expected at least " #N " arguments"); diff --git a/index.js b/index.js index 8078d53..462e914 100644 --- a/index.js +++ b/index.js @@ -1,5 +1,45 @@ '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`, + +}; diff --git a/package.json b/package.json index 8f02104..4328f1f 100644 --- a/package.json +++ b/package.json @@ -1,14 +1,17 @@ { "name": "node-addon-tools-raub", "author": "Luis Blanco ", - "description": "A set of extra macros for node addons, shipped as C++ header file.", - "version": "0.0.5", + "description": "A set of extra tools for Node.js addons.", + "version": "0.0.6", "main": "index.js", "keywords": [ "node", "addon", "header", - "include" + "include", + "platform", + "build", + "paths", ], "maintainers": [ { @@ -21,5 +24,8 @@ "repository": { "type": "git", "url": "https://github.com/raub/node-addon-tools.git" + }, + "dependencies": { + "nan": "2.8.0" } }