Commit 86a89644 authored by Jérémy Lal's avatar Jérémy Lal

Merge tag 'upstream/2.4.0'

Upstream version 2.4.0

# gpg: Signature faite le sam. 10 sept. 2016 10:52:49 CEST
# gpg:                avec la clef RSA 6611C05EDD39F374
# gpg:                issuer "kapouer@melix.org"
# gpg: Bonne signature de « Jérémy Lal <kapouer@melix.org> » [ultime]
# gpg:                 alias « Jérémy Lal <jerry@edagames.com> » [ultime]
# gpg:                 alias « Jérémy Lal <jerry@eda.sarl> » [ultime]
parents 49ef935d b2239b77
# NAN ChangeLog
**Version 2.3.5: current Node 6.2.0, Node 12: 0.12.14, Node 10: 0.10.45, iojs: 3.3.1**
**Version 2.4.0: current Node 6.3.0, Node 12: 0.12.15, Node 10: 0.10.46, iojs: 3.3.1**
### 2.4.0 Jul 10 2016
- Feature: Rewrite Callback to add Callback::Reset c4cf44d61f8275cd5f7b0c911d7a806d4004f649
- Feature: AsyncProgressWorker: add template types for .send 1242c9a11a7ed481c8f08ec06316385cacc513d0
- Bugfix: Add constness to old Persistent comparison operators bd43cb9982c7639605d60fd073efe8cae165d9b2
### 2.3.5 May 31 2016
......
......@@ -35,6 +35,7 @@ LINT_SOURCES = \
test/cpp/accessors2.cpp \
test/cpp/asyncworker.cpp \
test/cpp/asyncprogressworker.cpp \
test/cpp/asyncprogressworkerstream.cpp \
test/cpp/asyncprogressworkersignal.cpp \
test/cpp/asyncworkererror.cpp \
test/cpp/buffer.cpp \
......
......@@ -3,7 +3,7 @@ Native Abstractions for Node.js
**A header file filled with macro and utility goodness for making add-on development for Node.js easier across versions 0.8, 0.10, 0.12, 1, 4, 5 and 6.**
***Current version: 2.3.5***
***Current version: 2.4.0***
*(See [CHANGELOG.md](https://github.com/nodejs/nan/blob/master/CHANGELOG.md) for complete ChangeLog)*
......@@ -244,7 +244,7 @@ NAN's `node::Buffer` helpers exist as the API has changed across supported Node
`Nan::AsyncWorker` and `Nan::AsyncProgressWorker` are helper classes that make working with asynchronous code easier.
- <a href="doc/asyncworker.md#api_nan_async_worker"><b><code>Nan::AsyncWorker</code></b></a>
- <a href="doc/asyncworker.md#api_nan_async_progress_worker"><b><code>Nan::AsyncProgressWorker</code></b></a>
- <a href="doc/asyncworker.md#api_nan_async_progress_worker"><b><code>Nan::AsyncProgressWorkerBase & Nan::AsyncProgressWorker</code></b></a>
- <a href="doc/asyncworker.md#api_nan_async_queue_worker"><b><code>Nan::AsyncQueueWorker</code></b></a>
### Strings & Bytes
......
......@@ -58,14 +58,17 @@ class AsyncWorker {
```
<a name="api_nan_async_progress_worker"></a>
### Nan::AsyncProgressWorker
### Nan::AsyncProgressWorkerBase & Nan::AsyncProgressWorker
`Nan::AsyncProgressWorker` is an _abstract_ class that extends `Nan::AsyncWorker` and adds additional progress reporting callbacks that can be used during the asynchronous work execution to provide progress data back to JavaScript.
`Nan::AsyncProgressWorkerBase` is an _abstract_ class template that extends `Nan::AsyncWorker` and adds additional progress reporting callbacks that can be used during the asynchronous work execution to provide progress data back to JavaScript.
Previously the definiton of `Nan::AsyncProgressWorker` only allowed sending `const char` data. Now extending `Nan::AsyncProgressWorker` will yield an instance of the implicit `Nan::AsyncProgressWorkerBase` template with type `<char>` for compatibility.
Definition:
```c++
class AsyncProgressWorker : public AsyncWorker {
template<class T>
class AsyncProgressWorkerBase<T> : public AsyncWorker {
public:
explicit AsyncProgressWorker(Callback *callback_);
......@@ -76,14 +79,16 @@ class AsyncProgressWorker : public AsyncWorker {
class ExecutionProgress {
public:
void Signal() const;
void Send(const char* data, size_t size) const;
void Send(const T* data, size_t size) const;
};
virtual void Execute(const ExecutionProgress& progress) = 0;
virtual void HandleProgressCallback(const char *data, size_t size) = 0;
virtual void HandleProgressCallback(const T *data, size_t size) = 0;
virtual void Destroy();
typedef AsyncProgressWorkerBase<T> AsyncProgressWorker;
```
<a name="api_nan_async_queue_worker"></a>
......
......@@ -35,6 +35,10 @@ class Callback {
bool IsEmpty() const;
void Reset(const v8::Local<v8::Function> &fn);
void Reset();
v8::Local<v8::Value> Call(v8::Local<v8::Object> target,
int argc,
v8::Local<v8::Value> argv[]) const;
......
......@@ -12,7 +12,7 @@
*
* MIT License <https://github.com/nodejs/nan/blob/master/LICENSE.md>
*
* Version 2.3.5: current Node 6.2.0, Node 12: 0.12.14, Node 10: 0.10.45, iojs: 3.3.1
* Version 2.4.0: current Node 6.3.0, Node 12: 0.12.15, Node 10: 0.10.46, iojs: 3.3.1
*
* See https://github.com/nodejs/nan for the latest update to this file
**********************************************************************************/
......@@ -1348,37 +1348,24 @@ typedef void NAN_INDEX_QUERY_RETURN_TYPE;
class Callback {
public:
Callback() {
HandleScope scope;
v8::Local<v8::Object> obj = New<v8::Object>();
handle.Reset(obj);
}
Callback() {}
explicit Callback(const v8::Local<v8::Function> &fn) {
HandleScope scope;
v8::Local<v8::Object> obj = New<v8::Object>();
handle.Reset(obj);
SetFunction(fn);
}
explicit Callback(const v8::Local<v8::Function> &fn) : handle_(fn) {}
~Callback() {
if (handle.IsEmpty()) return;
handle.Reset();
handle_.Reset();
}
bool operator==(const Callback &other) const {
HandleScope scope;
v8::Local<v8::Value> a = New(handle)->Get(kCallbackIndex);
v8::Local<v8::Value> b = New(other.handle)->Get(kCallbackIndex);
return a->StrictEquals(b);
return handle_ == other.handle_;
}
bool operator!=(const Callback &other) const {
return !this->operator==(other);
return !operator==(other);
}
inline
v8::Local<v8::Function> operator*() const { return this->GetFunction(); }
v8::Local<v8::Function> operator*() const { return GetFunction(); }
inline v8::Local<v8::Value> operator()(
v8::Local<v8::Object> target
......@@ -1393,20 +1380,25 @@ class Callback {
return this->Call(argc, argv);
}
// TODO(kkoopa): remove
inline void SetFunction(const v8::Local<v8::Function> &fn) {
HandleScope scope;
Set(New(handle), kCallbackIndex, fn);
Reset(fn);
}
inline void Reset(const v8::Local<v8::Function> &fn) {
handle_.Reset(fn);
}
inline void Reset() {
handle_.Reset();
}
inline v8::Local<v8::Function> GetFunction() const {
EscapableHandleScope scope;
return scope.Escape(New(handle)->Get(kCallbackIndex)
.As<v8::Function>());
return New(handle_);
}
inline bool IsEmpty() const {
HandleScope scope;
return New(handle)->Get(kCallbackIndex)->IsUndefined();
return handle_.IsEmpty();
}
inline v8::Local<v8::Value>
......@@ -1433,8 +1425,7 @@ class Callback {
private:
NAN_DISALLOW_ASSIGN_COPY_MOVE(Callback)
Persistent<v8::Object> handle;
static const uint32_t kCallbackIndex = 0;
Persistent<v8::Function> handle_;
#if (NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION)
v8::Local<v8::Value> Call_(v8::Isolate *isolate
......@@ -1443,8 +1434,7 @@ class Callback {
, v8::Local<v8::Value> argv[]) const {
EscapableHandleScope scope;
v8::Local<v8::Function> callback = New(handle)->
Get(kCallbackIndex).As<v8::Function>();
v8::Local<v8::Function> callback = New(handle_);
# if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION
return scope.Escape(New(node::MakeCallback(
isolate
......@@ -1469,8 +1459,7 @@ class Callback {
, v8::Local<v8::Value> argv[]) const {
EscapableHandleScope scope;
v8::Local<v8::Function> callback = New(handle)->
Get(kCallbackIndex).As<v8::Function>();
v8::Local<v8::Function> callback = New(handle_);
return scope.Escape(New(node::MakeCallback(
target
, callback
......@@ -1589,9 +1578,11 @@ class Callback {
char *errmsg_;
};
/* abstract */ class AsyncProgressWorker : public AsyncWorker {
template<class T>
/* abstract */ class AsyncProgressWorkerBase : public AsyncWorker {
public:
explicit AsyncProgressWorker(Callback *callback_)
explicit AsyncProgressWorkerBase(Callback *callback_)
: AsyncWorker(callback_), asyncdata_(NULL), asyncsize_(0) {
async = new uv_async_t;
uv_async_init(
......@@ -1604,7 +1595,7 @@ class Callback {
uv_mutex_init(&async_lock);
}
virtual ~AsyncProgressWorker() {
virtual ~AsyncProgressWorkerBase() {
uv_mutex_destroy(&async_lock);
delete[] asyncdata_;
......@@ -1612,12 +1603,12 @@ class Callback {
void WorkProgress() {
uv_mutex_lock(&async_lock);
char *data = asyncdata_;
T *data = asyncdata_;
size_t size = asyncsize_;
asyncdata_ = NULL;
uv_mutex_unlock(&async_lock);
// Dont send progress events after we've already completed.
// Don't send progress events after we've already completed.
if (callback) {
HandleProgressCallback(data, size);
}
......@@ -1625,24 +1616,24 @@ class Callback {
}
class ExecutionProgress {
friend class AsyncProgressWorker;
friend class AsyncProgressWorkerBase;
public:
void Signal() const {
uv_async_send(that_->async);
}
// You could do fancy generics with templates here.
void Send(const char* data, size_t size) const {
void Send(const T* data, size_t size) const {
that_->SendProgress_(data, size);
}
private:
explicit ExecutionProgress(AsyncProgressWorker* that) : that_(that) {}
explicit ExecutionProgress(AsyncProgressWorkerBase *that) : that_(that) {}
NAN_DISALLOW_ASSIGN_COPY_MOVE(ExecutionProgress)
AsyncProgressWorker* const that_;
AsyncProgressWorkerBase* const that_;
};
virtual void Execute(const ExecutionProgress& progress) = 0;
virtual void HandleProgressCallback(const char *data, size_t size) = 0;
virtual void HandleProgressCallback(const T *data, size_t size) = 0;
virtual void Destroy() {
uv_close(reinterpret_cast<uv_handle_t*>(async), AsyncClose_);
......@@ -1654,12 +1645,15 @@ class Callback {
Execute(progress);
}
void SendProgress_(const char *data, size_t size) {
char *new_data = new char[size];
memcpy(new_data, data, size);
void SendProgress_(const T *data, size_t size) {
T *new_data = new T[size];
{
T *it = new_data;
std::copy(data, data + size, it);
}
uv_mutex_lock(&async_lock);
char *old_data = asyncdata_;
T *old_data = asyncdata_;
asyncdata_ = new_data;
asyncsize_ = size;
uv_mutex_unlock(&async_lock);
......@@ -1669,24 +1663,28 @@ class Callback {
}
inline static NAUV_WORK_CB(AsyncProgress_) {
AsyncProgressWorker *worker =
static_cast<AsyncProgressWorker*>(async->data);
AsyncProgressWorkerBase *worker =
static_cast<AsyncProgressWorkerBase*>(async->data);
worker->WorkProgress();
}
inline static void AsyncClose_(uv_handle_t* handle) {
AsyncProgressWorker *worker =
static_cast<AsyncProgressWorker*>(handle->data);
AsyncProgressWorkerBase *worker =
static_cast<AsyncProgressWorkerBase*>(handle->data);
delete reinterpret_cast<uv_async_t*>(handle);
delete worker;
}
uv_async_t *async;
uv_mutex_t async_lock;
char *asyncdata_;
T *asyncdata_;
size_t asyncsize_;
};
// This ensures compatibility to the previous un-templated AsyncProgressWorker
// class definition.
typedef AsyncProgressWorkerBase<char> AsyncProgressWorker;
inline void AsyncExecute (uv_work_t* req) {
AsyncWorker *worker = static_cast<AsyncWorker*>(req->data);
worker->Execute();
......
......@@ -64,22 +64,22 @@ class PersistentBase {
inline void Empty() { persistent.Clear(); }
template<typename S>
inline bool operator==(const PersistentBase<S> &that) {
inline bool operator==(const PersistentBase<S> &that) const {
return this->persistent == that.persistent;
}
template<typename S>
inline bool operator==(const v8::Local<S> &that) {
inline bool operator==(const v8::Local<S> &that) const {
return this->persistent == that;
}
template<typename S>
inline bool operator!=(const PersistentBase<S> &that) {
inline bool operator!=(const PersistentBase<S> &that) const {
return !operator==(that);
}
template<typename S>
inline bool operator!=(const v8::Local<S> &that) {
inline bool operator!=(const v8::Local<S> &that) const {
return !operator==(that);
}
......
{
"name": "nan",
"version": "2.3.5",
"version": "2.4.0",
"description": "Native Abstractions for Node.js: C++ header for Node 0.8 -> 6 compatibility",
"main": "include_dirs.js",
"repository": {
......@@ -26,6 +26,7 @@
"commander": "^2.8.1",
"glob": "^5.0.14",
"node-gyp": "~3.0.1",
"readable-stream": "^2.1.4",
"tap": "~0.7.1",
"xtend": "~4.0.0"
},
......
......@@ -97,6 +97,10 @@
"target_name" : "asyncprogressworker"
, "sources" : [ "cpp/asyncprogressworker.cpp" ]
}
, {
"target_name" : "asyncprogressworkerstream"
, "sources" : [ "cpp/asyncprogressworkerstream.cpp" ]
}
, {
"target_name" : "asyncprogressworkersignal"
, "sources" : ["cpp/asyncprogressworkersignal.cpp"]
......
/*********************************************************************
* NAN - Native Abstractions for Node.js
*
* Copyright (c) 2016 NAN contributors
*
* MIT License <https://github.com/nodejs/nan/blob/master/LICENSE.md>
********************************************************************/
#ifndef _WIN32
#include <unistd.h>
#define Sleep(x) usleep((x)*1000)
#endif
#include <nan.h>
using namespace Nan; // NOLINT(build/namespaces)
// Custom data type: This serves as an example of how external
// libraries could be hooked in, populate their objects and send them to JS.
struct data_t {
int index;
int data;
};
// Unlike test/cpp/ayncprogressworker.cpp this test is explicitly templated.
template<typename T>
class ProgressWorker : public AsyncProgressWorkerBase<T> {
public:
ProgressWorker(
Callback *callback
, Callback *progress
, int milliseconds
, int iters)
: AsyncProgressWorkerBase<T>(callback), progress(progress)
, milliseconds(milliseconds), iters(iters) {}
~ProgressWorker() {}
void Execute (
const typename AsyncProgressWorkerBase<T>::ExecutionProgress& progress) {
data_t data;
for (int i = 0; i < iters; ++i) {
data.index = i;
data.data = i * 2;
progress.Send(&data, sizeof( data ));
Sleep(milliseconds);
}
}
void HandleProgressCallback(const T *data, size_t size) {
HandleScope scope;
v8::Local<v8::Object> obj = Nan::New<v8::Object>();
Nan::Set(
obj,
Nan::New("index").ToLocalChecked(),
New<v8::Integer>(data->index));
Nan::Set(
obj,
Nan::New("data").ToLocalChecked(),
New<v8::Integer>(data->data));
v8::Local<v8::Value> argv[] = { obj };
progress->Call(1, argv);
}
private:
Callback *progress;
int milliseconds;
int iters;
};
NAN_METHOD(DoProgress) {
Callback *progress = new Callback(info[2].As<v8::Function>());
Callback *callback = new Callback(info[3].As<v8::Function>());
AsyncQueueWorker(new ProgressWorker<data_t>(
callback
, progress
, To<uint32_t>(info[0]).FromJust()
, To<uint32_t>(info[1]).FromJust()));
}
NAN_MODULE_INIT(Init) {
Set(target
, New<v8::String>("a").ToLocalChecked()
, New<v8::FunctionTemplate>(DoProgress)->GetFunction());
}
NODE_MODULE(asyncprogressworkerstream, Init)
......@@ -41,6 +41,18 @@ NAN_METHOD(CallAsFunction) {
Callback(info[0].As<v8::Function>())();
}
NAN_METHOD(ResetUnset) {
Callback callback;
callback.Reset();
info.GetReturnValue().Set(callback.IsEmpty());
}
NAN_METHOD(ResetSet) {
Callback callback(info[0].As<v8::Function>());
callback.Reset();
info.GetReturnValue().Set(callback.IsEmpty());
}
NAN_MODULE_INIT(Init) {
Set(target
, New<v8::String>("globalContext").ToLocalChecked()
......@@ -66,6 +78,14 @@ NAN_MODULE_INIT(Init) {
, New<v8::String>("callAsFunction").ToLocalChecked()
, New<v8::FunctionTemplate>(CallAsFunction)->GetFunction()
);
Set(target
, New<v8::String>("resetUnset").ToLocalChecked()
, New<v8::FunctionTemplate>(ResetUnset)->GetFunction()
);
Set(target
, New<v8::String>("resetSet").ToLocalChecked()
, New<v8::FunctionTemplate>(ResetSet)->GetFunction()
);
}
NODE_MODULE(nancallback, Init)
/*********************************************************************
* NAN - Native Abstractions for Node.js
*
* Copyright (c) 2016 NAN contributors
*
* MIT License <https://github.com/nodejs/nan/blob/master/LICENSE.md>
********************************************************************/
const test = require('tap').test
, testRoot = require('path').resolve(__dirname, '..')
, bindings = require('bindings')({ module_root: testRoot, bindings: 'asyncprogressworkerstream' })
, util = require('util');
const nodeVersion = process.versions.node.split('.')
var Readable
if (nodeVersion[0] == 0 && nodeVersion[1] <= 8)
Readable = require('readable-stream')
else
Readable = require('stream').Readable
function StreamProgressWorker(t) {
Readable.call(this, {objectMode: true})
var self = this
// initialize stream from cpp on next tick
process.nextTick(function () {
var worker = bindings.a
worker(100, 5, function(i) {
self.push(i)
}, function () {
self.push(null)
})
})
}
util.inherits(StreamProgressWorker, Readable)
StreamProgressWorker.prototype._read = function (data) {
};
test('asyncprogressworker', function (t) {
var stream = new StreamProgressWorker(t)
var progressed = 0;
stream
.on('end', function() {
t.ok(progressed === 5, 'cpp should have sent 5 objects')
t.end()
})
.on('data', function(data) {
progressed++
console.log(data);
})
})
......@@ -12,7 +12,7 @@ const test = require('tap').test
, round = Math.round;
test('nancallback', function (t) {
t.plan(13)
t.plan(17)
var persistent = bindings;
t.type(persistent.globalContext, 'function');
......@@ -21,11 +21,15 @@ test('nancallback', function (t) {
t.type(persistent.compareCallbacks, 'function');
t.type(persistent.callDirect, 'function');
t.type(persistent.callAsFunction, 'function');
t.type(persistent.resetUnset, 'function');
t.type(persistent.resetSet, 'function');
persistent.globalContext(function () { t.ok(true); });
persistent.specificContext(function () { t.ok(true); });
persistent.customReceiver(function () { t.equal(this, process); }, process);
persistent.callDirect(function () { t.ok(true); });
persistent.callAsFunction(function () { t.ok(true); });
t.ok(persistent.resetUnset());
t.ok(persistent.resetSet(function () {}));
var round2 = Math.round
, x = function(param) { return param + 1; }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment