Skip to content

Commit 7764a9a

Browse files
committed
Introduce SetCallHandler and SetCallAsFunctionHandler
Fixes: #427
1 parent 9347dc9 commit 7764a9a

File tree

7 files changed

+144
-0
lines changed

7 files changed

+144
-0
lines changed

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ LINT_SOURCES = \
6161
test/cpp/returnnull.cpp \
6262
test/cpp/returnundefined.cpp \
6363
test/cpp/returnvalue.cpp \
64+
test/cpp/setcallhandler.cpp \
6465
test/cpp/settemplate.cpp \
6566
test/cpp/strings.cpp \
6667
test/cpp/symbols.cpp \

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ In order to expose functionality to JavaScript via a template, you must provide
9797
- <a href="doc/methods.md#api_nan_set_template"><b><code>Nan::SetTemplate()</code></b></a>
9898
- <a href="doc/methods.md#api_nan_set_prototype_template"><b><code>Nan::SetPrototypeTemplate()</code></b></a>
9999
- <a href="doc/methods.md#api_nan_set_instance_template"><b><code>Nan::SetInstanceTemplate()</code></b></a>
100+
- <a href="doc/methods.md#api_nan_set_call_handler"><b><code>Nan::SetCallHandler()</code></b></a>
101+
- <a href="doc/methods.md#api_nan_set_call_as_function_handler"><b><code>Nan::SetCallAsFunctionHandler()</code></b></a>
100102

101103
### Scopes
102104

doc/methods.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ In order to expose functionality to JavaScript via a template, you must provide
3030
- <a href="#api_nan_set_template"><b><code>Nan::SetTemplate()</code></b></a>
3131
- <a href="#api_nan_set_prototype_template"><b><code>Nan::SetPrototypeTemplate()</code></b></a>
3232
- <a href="#api_nan_set_instance_template"><b><code>Nan::SetInstanceTemplate()</code></b></a>
33+
- <a href="#api_nan_set_call_handler"><b><code>Nan::SetCallHandler()</code></b></a>
34+
- <a href="#api_nan_set_call_as_function_handler"><b><code>Nan::SetCallAsFunctionHandler()</code></b></a>
3335

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

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

628+
<a name="api_nan_set_call_handler"></a>
629+
### Nan::SetCallHandler()
630+
631+
Set the call-handler callback for a `v8::FunctionTemplate`.
632+
This callback is called whenever the function created from this FunctionTemplate is called.
633+
634+
Signature:
635+
636+
```c++
637+
void Nan::SetCallHandler(v8::Local<v8::FunctionTemplate> templ, Nan::FunctionCallback callback, v8::Local<v8::Value> data = v8::Local<v8::Value>())
638+
```
639+
640+
Calls the `FunctionTemplate`'s [`SetCallHandler()`](https://v8docs.nodesource.com/io.js-3.0/d8/d83/classv8_1_1_function_template.html#a26cf14e36aa1a47091b98536d08ea821).
641+
642+
<a name="api_nan_set_call_as_function_handler"></a>
643+
### Nan::SetCallAsFunctionHandler()
644+
645+
Sets the callback to be used when calling instances created from the `v8::ObjectTemplate` as a function.
646+
If no callback is set, instances behave like normal JavaScript objects that cannot be called as a function.
647+
648+
Signature:
649+
650+
```c++
651+
void Nan::SetCallAsFunctionHandler(v8::Local<v8::ObjectTemplate> templ, Nan::FunctionCallback callback, v8::Local<v8::Value> data = v8::Local<v8::Value>())
652+
```
653+
654+
Calls the `ObjectTemplate`'s [`SetCallAsFunctionHandler()`](https://v8docs.nodesource.com/io.js-3.0/db/d5f/classv8_1_1_object_template.html#ae0a0e72fb0c5e5f32e255fe5bcc7316a).
655+

nan.h

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2085,6 +2085,49 @@ inline void SetIndexedPropertyHandler(
20852085
#endif
20862086
}
20872087

2088+
inline void SetCallHandler(
2089+
v8::Local<v8::FunctionTemplate> tpl
2090+
, FunctionCallback callback
2091+
, v8::Local<v8::Value> data = v8::Local<v8::Value>()) {
2092+
HandleScope scope;
2093+
2094+
v8::Local<v8::ObjectTemplate> otpl = New<v8::ObjectTemplate>();
2095+
otpl->SetInternalFieldCount(imp::kFunctionFieldCount);
2096+
v8::Local<v8::Object> obj = NewInstance(otpl).ToLocalChecked();
2097+
2098+
obj->SetInternalField(
2099+
imp::kFunctionIndex
2100+
, New<v8::External>(reinterpret_cast<void *>(callback)));
2101+
2102+
if (!data.IsEmpty()) {
2103+
obj->SetInternalField(imp::kDataIndex, data);
2104+
}
2105+
2106+
tpl->SetCallHandler(imp::FunctionCallbackWrapper, obj);
2107+
}
2108+
2109+
2110+
inline void SetCallAsFunctionHandler(
2111+
v8::Local<v8::ObjectTemplate> tpl,
2112+
FunctionCallback callback,
2113+
v8::Local<v8::Value> data = v8::Local<v8::Value>()) {
2114+
HandleScope scope;
2115+
2116+
v8::Local<v8::ObjectTemplate> otpl = New<v8::ObjectTemplate>();
2117+
otpl->SetInternalFieldCount(imp::kFunctionFieldCount);
2118+
v8::Local<v8::Object> obj = NewInstance(otpl).ToLocalChecked();
2119+
2120+
obj->SetInternalField(
2121+
imp::kFunctionIndex
2122+
, New<v8::External>(reinterpret_cast<void *>(callback)));
2123+
2124+
if (!data.IsEmpty()) {
2125+
obj->SetInternalField(imp::kDataIndex, data);
2126+
}
2127+
2128+
tpl->SetCallAsFunctionHandler(imp::FunctionCallbackWrapper, obj);
2129+
}
2130+
20882131
//=== Weak Persistent Handling =================================================
20892132

20902133
#include "nan_weak.h" // NOLINT(build/include)

test/binding.gyp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,4 +136,8 @@
136136
"target_name" : "wrappedobjectfactory"
137137
, "sources" : [ "cpp/wrappedobjectfactory.cpp" ]
138138
}
139+
, {
140+
"target_name" : "setcallhandler"
141+
, "sources" : [ "cpp/setcallhandler.cpp" ]
142+
}
139143
]}

test/cpp/setcallhandler.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*********************************************************************
2+
* NAN - Native Abstractions for Node.js
3+
*
4+
* Copyright (c) 2015 NAN contributors
5+
*
6+
* MIT License <https://github.com/nodejs/nan/blob/master/LICENSE.md>
7+
********************************************************************/
8+
9+
#include <nan.h>
10+
11+
using namespace Nan; // NOLINT(build/namespaces)
12+
13+
NAN_METHOD(CallHandler) {
14+
info.GetReturnValue().Set(12);
15+
}
16+
17+
NAN_METHOD(CallHandlerSetter) {
18+
v8::Local<v8::FunctionTemplate> tpl = New<v8::FunctionTemplate>();
19+
SetCallHandler(tpl, CallHandler);
20+
info.GetReturnValue().Set(GetFunction(tpl).ToLocalChecked());
21+
}
22+
23+
NAN_METHOD(CallAsFunctionHandler) {
24+
info.GetReturnValue().Set(15);
25+
}
26+
27+
NAN_METHOD(CallAsFunctionHandlerSetter) {
28+
v8::Local<v8::ObjectTemplate> tpl = New<v8::ObjectTemplate>();
29+
SetCallAsFunctionHandler(tpl, CallAsFunctionHandler);
30+
info.GetReturnValue().Set(NewInstance(tpl).ToLocalChecked());
31+
}
32+
33+
NAN_MODULE_INIT(Init) {
34+
Set(target
35+
, New("a").ToLocalChecked()
36+
, New<v8::FunctionTemplate>(CallHandlerSetter)->GetFunction()
37+
);
38+
Set(target
39+
, New("b").ToLocalChecked()
40+
, New<v8::FunctionTemplate>(CallAsFunctionHandlerSetter)->GetFunction()
41+
);
42+
}
43+
44+
NODE_MODULE(setcallhandler, Init)
45+

test/js/setcallhandler-test.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/*********************************************************************
2+
* NAN - Native Abstractions for Node.js
3+
*
4+
* Copyright (c) 2015 NAN contributors
5+
*
6+
* MIT License <https://github.com/nodejs/nan/blob/master/LICENSE.md>
7+
********************************************************************/
8+
9+
const test = require('tap').test
10+
, testRoot = require('path').resolve(__dirname, '..')
11+
, bindings = require('bindings')({ module_root: testRoot, bindings: 'setcallhandler' });
12+
13+
test('setcallhandler', function (t) {
14+
t.plan(4);
15+
t.type(bindings.a, 'function');
16+
t.type(bindings.b, 'function');
17+
t.equal(bindings.a()(), 12);
18+
t.equal(bindings.b()(), 15);
19+
});

0 commit comments

Comments
 (0)