📝 Farewell iostream

This commit is contained in:
raub 2018-05-05 16:59:11 +03:00
parent e244be7bea
commit 8dc8431017
3 changed files with 73 additions and 28 deletions

View File

@ -7,6 +7,7 @@ This is a part of [Node3D](https://github.com/node-3d) project.
Helpers for Node.js addons and dependency packages: Helpers for Node.js addons and dependency packages:
* `consoleLog()` C++ implementation.
* `EventEmitter` C++ implementation. * `EventEmitter` C++ implementation.
* C++ macros and shortcuts. * C++ macros and shortcuts.
* Crossplatform commands for GYP: `cp`, `rm`, `mkdir`. * Crossplatform commands for GYP: `cp`, `rm`, `mkdir`.
@ -36,6 +37,8 @@ Useful links: [V8 Ref](https://v8docs.nodesource.com/node-0.8/d2/dc3/namespacev8
[Class EventEmitter](#class-eventemitter) [Class EventEmitter](#class-eventemitter)
[Function consoleLog](#function-consolelog)
--- ---
@ -668,7 +671,7 @@ For Windows the `/y` flag was embedded.
--- ---
## class EventEmitter ## Class EventEmitter
A C++ implementation of [Events API](https://nodejs.org/api/events.html). A C++ implementation of [Events API](https://nodejs.org/api/events.html).
@ -750,3 +753,23 @@ void Example::init(Handle<Object> target) {
``` ```
</details> </details>
---
## Function consoleLog
In C++ addons, the use of **iostream** is discouraged because **Node.js** has its own
perspective on **stdout** behavior.
At first it may look as if `cout << "msg" << endl;` works nice, but it doesn't.
After a while, it just ceases on a midword, and you end up thinking something has
broken really hard in your addon.
To overcome this, we can use some V8 `eval` magic to make a real `console.log`
call from C++ land. And this is where `consoleLog` comes into play.
* `inline void consoleLog(int argc, V8_VAR_VAL *argv)` - a generic logger,
receives any set of arguments.
* `inline void consoleLog(const std::string &message)` - an alias to log a single
string.

View File

@ -287,4 +287,24 @@ inline void *getImageData(v8::Local<v8::Value> arg) {
} }
inline void consoleLog(int argc, V8_VAR_VAL *argv) {
V8_VAR_STR code = JS_STR("((...args) => console.log(...args))");
V8_VAR_FUNC log = V8_VAR_FUNC::Cast(v8::Script::Compile(code)->Run());
Nan::Callback logCb(log);
Nan::AsyncResource async("consoleLog()");
logCb.Call(argc, argv, &async);
}
inline void consoleLog(const std::string &message) {
V8_VAR_VAL arg = JS_STR(message);
consoleLog(1, &arg);
}
#endif // _ADDON_TOOLS_HPP_ #endif // _ADDON_TOOLS_HPP_

View File

@ -7,7 +7,6 @@
#include <string> #include <string>
#include <map> #include <map>
#include <deque> #include <deque>
#include <iostream> // -> std::cout << "..." << std::endl;
#define THIS_EVENT_EMITTER \ #define THIS_EVENT_EMITTER \
@ -308,6 +307,33 @@ private:
} }
static inline void _reportListeners(
const std::string &name,
int numListeners,
int maxListeners
) {
std::string msg = "EventEmitter Warning: too many listeners (";
msg += std::to_string(numListeners);
msg += " > ";
msg += std::to_string(maxListeners);
msg += ") on '";
msg += name;
msg += "' event, possible memory leak.\n";
// Some JS magic to retrieve the call stack
V8_VAR_STR code = JS_STR(
"(new Error()).stack.split('\\n').slice(2).join('\\n')"
);
V8_VAR_STR stack = V8_VAR_STR::Cast(
v8::Script::Compile(code)->Run()
);
Nan::Utf8String stackStr(stack);
msg += *stackStr;
consoleLog(msg);
}
static inline void _addListener( static inline void _addListener(
const Nan::FunctionCallbackInfo<v8::Value> &info, const Nan::FunctionCallbackInfo<v8::Value> &info,
@ -331,19 +357,7 @@ private:
if (eventEmitter->_maxListeners > 0 && count > eventEmitter->_maxListeners) { if (eventEmitter->_maxListeners > 0 && count > eventEmitter->_maxListeners) {
std::cout << "EventEmitter Warning: too many listeners ("; _reportListeners(name, count, eventEmitter->_maxListeners);
std::cout << count << " > " << eventEmitter->_maxListeners << ") on '";
std::cout << name << "' event, possible memory leak." << std::endl;
// Some JS magic to retrieve the call stack
V8_VAR_STR code = JS_STR(
"(new Error()).stack.split('\\n').slice(1).join('\\n')"
);
V8_VAR_STR stack = V8_VAR_STR::Cast(
v8::Script::Compile(code)->Run()
);
Nan::Utf8String stackStr(stack);
std::cout << *stackStr << std::endl;
} }
@ -393,19 +407,7 @@ private:
if (eventEmitter->_maxListeners > 0 && count > eventEmitter->_maxListeners) { if (eventEmitter->_maxListeners > 0 && count > eventEmitter->_maxListeners) {
std::cout << "EventEmitter Warning: too many listeners ("; _reportListeners(name, count, eventEmitter->_maxListeners);
std::cout << count << " > " << eventEmitter->_maxListeners << ") on '";
std::cout << name << "' event, possible memory leak." << std::endl;
// Some JS magic to retrieve the call stack
V8_VAR_STR code = JS_STR(
"(new Error()).stack.split('\\n').slice(1).join('\\n')"
);
V8_VAR_STR stack = V8_VAR_STR::Cast(
v8::Script::Compile(code)->Run()
);
Nan::Utf8String stackStr(stack);
std::cout << *stackStr << std::endl;
} }