Skip to content

Commit

Permalink
Introduce SetCallHandler and SetCallAsFunctionHandler
Browse files Browse the repository at this point in the history
Fixes: #427
  • Loading branch information
kkoopa committed Oct 7, 2015
1 parent 9347dc9 commit 7764a9a
Show file tree
Hide file tree
Showing 7 changed files with 144 additions and 0 deletions.
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ LINT_SOURCES = \
test/cpp/returnnull.cpp \
test/cpp/returnundefined.cpp \
test/cpp/returnvalue.cpp \
test/cpp/setcallhandler.cpp \
test/cpp/settemplate.cpp \
test/cpp/strings.cpp \
test/cpp/symbols.cpp \
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ In order to expose functionality to JavaScript via a template, you must provide
- <a href="doc/methods.md#api_nan_set_template"><b><code>Nan::SetTemplate()</code></b></a>
- <a href="doc/methods.md#api_nan_set_prototype_template"><b><code>Nan::SetPrototypeTemplate()</code></b></a>
- <a href="doc/methods.md#api_nan_set_instance_template"><b><code>Nan::SetInstanceTemplate()</code></b></a>
- <a href="doc/methods.md#api_nan_set_call_handler"><b><code>Nan::SetCallHandler()</code></b></a>
- <a href="doc/methods.md#api_nan_set_call_as_function_handler"><b><code>Nan::SetCallAsFunctionHandler()</code></b></a>

### Scopes

Expand Down
30 changes: 30 additions & 0 deletions doc/methods.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ In order to expose functionality to JavaScript via a template, you must provide
- <a href="#api_nan_set_template"><b><code>Nan::SetTemplate()</code></b></a>
- <a href="#api_nan_set_prototype_template"><b><code>Nan::SetPrototypeTemplate()</code></b></a>
- <a href="#api_nan_set_instance_template"><b><code>Nan::SetInstanceTemplate()</code></b></a>
- <a href="#api_nan_set_call_handler"><b><code>Nan::SetCallHandler()</code></b></a>
- <a href="#api_nan_set_call_as_function_handler"><b><code>Nan::SetCallAsFunctionHandler()</code></b></a>

<a name="api_nan_function_callback_info"></a>
### Nan::FunctionCallbackInfo
Expand Down Expand Up @@ -623,3 +625,31 @@ void Nan::SetInstanceTemplate(v8::Local<v8::FunctionTemplate> templ,

Calls the `FunctionTemplate`'s _InstanceTemplate's_ [`Set()`](https://v8docs.nodesource.com/io.js-3.0/db/df7/classv8_1_1_template.html#a2db6a56597bf23c59659c0659e564ddf).

<a name="api_nan_set_call_handler"></a>
### Nan::SetCallHandler()

Set the call-handler callback for a `v8::FunctionTemplate`.
This callback is called whenever the function created from this FunctionTemplate is called.

Signature:

```c++
void Nan::SetCallHandler(v8::Local<v8::FunctionTemplate> templ, Nan::FunctionCallback callback, v8::Local<v8::Value> data = v8::Local<v8::Value>())
```
Calls the `FunctionTemplate`'s [`SetCallHandler()`](https://v8docs.nodesource.com/io.js-3.0/d8/d83/classv8_1_1_function_template.html#a26cf14e36aa1a47091b98536d08ea821).
<a name="api_nan_set_call_as_function_handler"></a>
### Nan::SetCallAsFunctionHandler()
Sets the callback to be used when calling instances created from the `v8::ObjectTemplate` as a function.
If no callback is set, instances behave like normal JavaScript objects that cannot be called as a function.
Signature:
```c++
void Nan::SetCallAsFunctionHandler(v8::Local<v8::ObjectTemplate> templ, Nan::FunctionCallback callback, v8::Local<v8::Value> data = v8::Local<v8::Value>())
```

Calls the `ObjectTemplate`'s [`SetCallAsFunctionHandler()`](https://v8docs.nodesource.com/io.js-3.0/db/d5f/classv8_1_1_object_template.html#ae0a0e72fb0c5e5f32e255fe5bcc7316a).

43 changes: 43 additions & 0 deletions nan.h
Original file line number Diff line number Diff line change
Expand Up @@ -2085,6 +2085,49 @@ inline void SetIndexedPropertyHandler(
#endif
}

inline void SetCallHandler(
v8::Local<v8::FunctionTemplate> tpl
, FunctionCallback callback
, v8::Local<v8::Value> data = v8::Local<v8::Value>()) {
HandleScope scope;

v8::Local<v8::ObjectTemplate> otpl = New<v8::ObjectTemplate>();
otpl->SetInternalFieldCount(imp::kFunctionFieldCount);
v8::Local<v8::Object> obj = NewInstance(otpl).ToLocalChecked();

obj->SetInternalField(
imp::kFunctionIndex
, New<v8::External>(reinterpret_cast<void *>(callback)));

if (!data.IsEmpty()) {
obj->SetInternalField(imp::kDataIndex, data);
}

tpl->SetCallHandler(imp::FunctionCallbackWrapper, obj);
}


inline void SetCallAsFunctionHandler(
v8::Local<v8::ObjectTemplate> tpl,
FunctionCallback callback,
v8::Local<v8::Value> data = v8::Local<v8::Value>()) {
HandleScope scope;

v8::Local<v8::ObjectTemplate> otpl = New<v8::ObjectTemplate>();
otpl->SetInternalFieldCount(imp::kFunctionFieldCount);
v8::Local<v8::Object> obj = NewInstance(otpl).ToLocalChecked();

obj->SetInternalField(
imp::kFunctionIndex
, New<v8::External>(reinterpret_cast<void *>(callback)));

if (!data.IsEmpty()) {
obj->SetInternalField(imp::kDataIndex, data);
}

tpl->SetCallAsFunctionHandler(imp::FunctionCallbackWrapper, obj);
}

//=== Weak Persistent Handling =================================================

#include "nan_weak.h" // NOLINT(build/include)
Expand Down
4 changes: 4 additions & 0 deletions test/binding.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -136,4 +136,8 @@
"target_name" : "wrappedobjectfactory"
, "sources" : [ "cpp/wrappedobjectfactory.cpp" ]
}
, {
"target_name" : "setcallhandler"
, "sources" : [ "cpp/setcallhandler.cpp" ]
}
]}
45 changes: 45 additions & 0 deletions test/cpp/setcallhandler.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*********************************************************************
* NAN - Native Abstractions for Node.js
*
* Copyright (c) 2015 NAN contributors
*
* MIT License <https://github.com/nodejs/nan/blob/master/LICENSE.md>
********************************************************************/

#include <nan.h>

using namespace Nan; // NOLINT(build/namespaces)

NAN_METHOD(CallHandler) {
info.GetReturnValue().Set(12);
}

NAN_METHOD(CallHandlerSetter) {
v8::Local<v8::FunctionTemplate> tpl = New<v8::FunctionTemplate>();
SetCallHandler(tpl, CallHandler);
info.GetReturnValue().Set(GetFunction(tpl).ToLocalChecked());
}

NAN_METHOD(CallAsFunctionHandler) {
info.GetReturnValue().Set(15);
}

NAN_METHOD(CallAsFunctionHandlerSetter) {
v8::Local<v8::ObjectTemplate> tpl = New<v8::ObjectTemplate>();
SetCallAsFunctionHandler(tpl, CallAsFunctionHandler);
info.GetReturnValue().Set(NewInstance(tpl).ToLocalChecked());
}

NAN_MODULE_INIT(Init) {
Set(target
, New("a").ToLocalChecked()
, New<v8::FunctionTemplate>(CallHandlerSetter)->GetFunction()
);
Set(target
, New("b").ToLocalChecked()
, New<v8::FunctionTemplate>(CallAsFunctionHandlerSetter)->GetFunction()
);
}

NODE_MODULE(setcallhandler, Init)

19 changes: 19 additions & 0 deletions test/js/setcallhandler-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*********************************************************************
* NAN - Native Abstractions for Node.js
*
* Copyright (c) 2015 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: 'setcallhandler' });

test('setcallhandler', function (t) {
t.plan(4);
t.type(bindings.a, 'function');
t.type(bindings.b, 'function');
t.equal(bindings.a()(), 12);
t.equal(bindings.b()(), 15);
});

0 comments on commit 7764a9a

Please sign in to comment.