SlideShare a Scribd company logo
1 of 34
Download to read offline
1 / 34
Writing Node.js Bindings
General Principles
Gabriel Schulhof
Intel Finland Oy
2 / 34
Assumption
● Make bindings simple – one-to-one
– Avoid abstractions in C++ – leave those for Javascript
– Benefit: Re-use C API documentation �
● C-specific artifacts need not be exposed to Javascript
– Function pointer context
– Variable length array via pointer-to-data plus length parameter
void some_api(
void *context,
void (*callback)(
void *context,
int someUsefulData));
or
void some_api(
SomeStructure *list,
size_t list_length);
struct Something {
SomeStructure *list;
size_t list_length;
};
3 / 34
General principles
● Trust data from the native side
● Validate data from the Javascript side
● Avoid argument juggling
– Require a certain number of arguments
– Require each argument to have a certain type
4 / 34
General principles – Stack
● Make the native call stack mimic Javascript
– The binding throws a Javascript exception if
parameter array length or parameter type validation
fails and returns immediately, without setting the
return value
– Helpers called by the binding throw a Javascript
exception and return false, indicating that the
binding is to return immediately because an
exception has occurred
5 / 34
General principles - Stack
bool some_helper_helper(...) {
...
if (something_broken) {
Nan::ThrowError("Something is broken!");
return false;
}
...
return true;
}
bool some_binding_helper(...) {
...
if (!some_helper_helper(...)) {
return false;
}
...
if (something_wrong) {
Nan::ThrowError("Something went wrong!");
return false;
}
...
return true;
}
NAN_METHOD(bind_some_function) {
/* Validate parameter list length and parameter types */
...
if (!some_binding_helper(...)) {
return;
}
...
info.GetReturnValue().Set(Nan::New(returnValue));
}
6 / 34
General principles - Data
● Write a pair of helpers for converting data
structures to/from Javascript. For example, for
this structure:
struct coordinates {
double lat;
double lon;
double alt;
};
7 / 34
General principles - Data
● C converter
– Returns true on success
– Throws Javascript exception and returns false on validation
error
– Accepts a pointer to a structure to fill out (destination) and a
Javascript object containing the Javascript equivalent of the
structure (jsSource)
– Creates a local variable of the structure type (local)
– Retrieves each structure member from jsSource, validates it,
and assigns it to local
– If all members of local are successfully assigned,
*destination = local;
return true;
8 / 34
General principles - Data
bool c_coordinates(
struct coordinates *destination,
Local<Object> jsSource) {
struct coordinates local;
Local<Value> jsLat = Nan::Get(jsSource,
Nan::New("lat").ToLocalChecked())
.ToLocalChecked();
if (!jsLat->IsNumber()) {
Nan::ThrowError("lat is not a number");
return false;
}
local.lat = Nan::To<double>(jsLat).FromJust();
// Same for "lon" and for "alt"
*destination = local;
return true;
}
Nan::Maybe
types
provide
additionalfailure
interception
9 / 34
General principles - Data
● Observation: Because they follow the signature
recommended in previous slides, functions of the form
c_structurename() as illustrated in the previous slide
can be composed if one structure contains one or more
other structures:
Local<Value> jsMoreDetails = Nan::Get(jsSource,
Nan::New("more_details").ToLocalChecked())
.ToLocalChecked();
if (!jsMoreDetails->IsObject()) {
Nan::ThrowError(
"more_details must be an object!");
return false;
}
if (!c_more_details(&(local.more_details),
Nan::To<Object>(jsMoreDetails).ToLocalChecked())) {
return false;
}
10 / 34
General principles - Data
● Javascript converter
– Returns a Javascript object
– Accepts a pointer to a C structure and a Javascript
object, which it returns. If absent, it creates a
Javascript object (done using C++ default
parameter value)
11 / 34
General principles - Data
● Observation: Javascript converters can also be
composed:
Nan::Set(jsDestination,
Nan::New("more_details").ToLocalChecked(),
js_more_details(source->more_details));
Local<Object> js_coordinates(
const struct coordinates *source,
Local<Object> jsDestination = Nan::New<Object>()) {
Nan::Set(jsDestination,
Nan::New("lat").ToLocalChecked(), Nan::New(source->lat));
Nan::Set(jsDestination,
Nan::New("lon").ToLocalChecked(), Nan::New(source->lon));
Nan::Set(jsDestination,
Nan::New("alt").ToLocalChecked(), Nan::New(source->alt));
return jsDestination;
}
12 / 34
Automating
● Parsing the header files with the usual suspects
– cat, grep, awk
– Project style conventions can come in handy
● What can be extracted?
– Precompiler constants
– Enums
● The result:
myAddon.SOME_CONSTANT;
myAddon.SomeEnum.SOME_ENUM_GREEN;
myAddon.SomeEnum.SOME_ENUM_BLUE;
13 / 34
The Simplest Binding
● Function takes primitive data types and returns
a primitive data type
double area_of_oval(double xRadius,
double yRadius);
NAN_METHOD(bind_area_of_oval) {
VALIDATE_ARGUMENT_COUNT(info, 2);
VALIDATE_ARGUMENT_TYPE(info, 0, IsNumber);
VALIDATE_ARGUMENT_TYPE(info, 1, IsNumber);
Info.GetReturnValue().Set(Nan::New(
area_of_oval(
Nan::To<double>(info[0]).FromJust(),
Nan::To<double>(info[1]).FromJust())));
}
14 / 34
Data
● Any parameter or return value that does not fit
in a primitive data type →pointers
– Structures
● Traversable
● The pointer itself is not important
● Who owns the pointer?→sometimes ambiguous
– Handles
● “magic”, in that the pointer's value is important
● The data to which the pointer refers is often opaque
● The pointer is given by the native side, and is requested
back on subsequent calls
15 / 34
Data-Structures
struct coordinates {
double latitude;
double longitude;
double altitude;
};
/* Both APIs return true on success */
bool find_restaurant_by_name(const char *name, struct coordinates *location);
bool restaurant_at_coordinates(const struct coordinates *location);
NAN_METHOD(bind_find_restaurant_by_name) {
VALIDATE_ARGUMENT_COUNT(info, 2);
VALIDATE_ARGUMENT_TYPE(info, 0, IsString);
VALIDATE_ARGUMENT_TYPE(info, 1, IsObject);
struct coordinates result;
bool returnValue = find_restaurant_by_name(
(const char *)*(String::Utf8Value(info[0])), &result);
if (returnValue) {
js_coordinates(&result,
Nan::To<Object>(info[1]).ToLocalChecked());
}
info.GetReturnValue().Set(Nan::New(returnValue));
}
16 / 34
Data-Structures
NAN_METHOD(bind_restaurant_at_coordinates) {
VALIDATE_ARGUMENT_COUNT(info, 1);
VALIDATE_ARGUMENT_TYPE(info, 0, IsObject);
struct coordinates;
if (!c_coordinates(&coordinates,
Nan::To<Object>(info[0]).ToLocalChecked())) {
return;
}
info.GetReturnValue().Set(
Nan::New(
restaurant_at_coordinates(&coordinates)));
}
17 / 34
Data-Handles
● “magic” value – structure behind it is often opaque
– Two APIs – one to get a new handle, one to give it back:
● open()/close()
● setTimeout()/clearTimeout()
– Overwrite the return value and you have a leak:
● fd = open(...); fd = -1;
● to = setTimeout(...); to = null;
● interval = setInterval(...); interval = null;
– Once you release the handle, if you attempt to use it or
release it again,
● nothing happens
● an error is returned
● segfault
18 / 34
Data-Handles
● How to bind? It's a pointer, so … array of bytes? Number?
– Bad, because we've chosen not to trust data from Javascript:
handle = getHandle(); handle[1] = 5;
● If only we could assign a property to an object that is not
visible from Javascript – and I don't mean
defineProperty() with enumerable: false because
that can still reveal pointer values
● V8 and NAN to the rescue with
SetInternalFieldCount()- Store a pointer inside a
Javascript object such that it is only accessible from C++
– Javascript objects are copied by reference, so we get the
semantics of the setTimeout() return value
19 / 34
Data-Handles
●
Let's create a class template for passing handles into Javascript.
We assign a void * to a Javascript object while giving the object a
nice-looking class name to boot. What do we need of the C++
class?
– Instantiation
Local<Object> MyJSHandle::New(void *handle);
– Give me back the native handle
void *MyJSHandle::Resolve(Local<Object> jsHandle);
– Gut the Javascript object of its native handle (invalidate)
●
We need that for the case where the native handle is gone but the Javascript object
is still around:
close(fd); /* accidentally */ close(fd);
So we need
Nan::SetInternalFieldPointer(jsHandle, 0, 0);
after which a second call to an API using the handle will either do nothing or throw
an exception – we can tell the handle is invalid → segfault averted
20 / 34
template <class T> class JSHandle {
static Nan::Persistent<v8::FunctionTemplate> &theTemplate() {
static Nan::Persistent<v8::FunctionTemplate> returnValue;
if (returnValue.IsEmpty()) {
v8::Local<v8::FunctionTemplate> theTemplate =
Nan::New<v8::FunctionTemplate>();
theTemplate
->SetClassName(Nan::New(T::jsClassName()).ToLocalChecked());
theTemplate->InstanceTemplate()->SetInternalFieldCount(1);
Nan::Set(Nan::GetFunction(theTemplate).ToLocalChecked(),
Nan::New("displayName").ToLocalChecked(),
Nan::New(T::jsClassName()).ToLocalChecked());
returnValue.Reset(theTemplate);
}
return returnValue;
}
public:
static v8::Local<v8::Object> New(void *data) {
v8::Local<v8::Object> returnValue =
Nan::GetFunction(Nan::New(theTemplate())).ToLocalChecked()
->NewInstance();
Nan::SetInternalFieldPointer(returnValue, 0, data);
return returnValue;
}
static void *Resolve(v8::Local<v8::Object> jsObject) {
void *returnValue = 0;
if (Nan::New(theTemplate())->HasInstance(jsObject)) {
returnValue = Nan::GetInternalFieldPointer(jsObject, 0);
}
if (!returnValue) {
Nan::ThrowTypeError((std::string("Object is not of type " +
T::jsClassName()).c_str());
}
return returnValue;
}
};
21 / 34
Data-Handles
● Usage:
● And in a binding:
class JSRemoteResourceHandle : public JSHandle<JSRemoteResourceHandle> {
public:
static const char *jsClassName() {return "RemoteResourceHandle";}
};
NAN_METHOD(new_handle) {
...
struct remote_resource_handle *remote =
get_remote_resource(...);
info.GetReturnValue().Set(
JSRemoteResourceHandle::New(remote));
}
NAN_METHOD(use_handle) {
Local<Object> jsHandle = Nan::To<Object>(info[0]).ToLocalChecked();
struct remote_resource_handle *remote =
JSRemoteResourceHandle::Resolve(jsHandle);
if (!remote) {
return;
}
do_something_with_remote_resource(remote, ...);
}
22 / 34
Data-Handles
● Important consideration: Avoid creating two different
Javascript handles for the same native handle. This
can happen in conjunction with callbacks, where the
C callback is given a copy of the handle as a
convenience:
Avoid creating a new Javascript object inside
operation_complete() via
JSRemoteResource::New(remote)
void remote_resource_set_int(
remote_resource *remote,
int newValue,
void (*operation_complete)(
void *context,
remote_resource *remote,
int result),
void *context);
23 / 34
Data-Handles
struct CallbackData {
Nan::Callback *callback;
Nan::Persistent<Object> *jsRemote;
};
void set_int_operation_complete(
void *context, remote_resource *remote,
int result) {
Nan::HandleScope scope;
struct CallbackData *data =
(struct CallbackData *)context;
Local<Value> arguments[2] = {
// JSRemoteHandle::New(remote)
Nan::New<Object>(*(data->jsRemote)),
Nan::New(result)
};
data->callback->Call(2, arguments);
...
}
24 / 34
Callbacks
● In C, functions cannot be created/destroyed at
runtime, so almost every API that takes a
callback has a void *context to distinguish
different callbacks
– Javascript is the king of context so we do not need
to expose this but instead use the context to store
at least the Javascript function that we're supposed
to call – because Javascript functions can be
created/destroyed at runtime
25 / 34
Callbacks
● Two kinds of callbacks
– Implicitly removed
● read();
● setTimeout();
– Explicitly removed
● setInterval();
● accept();
● These always come in a pair, forming a bracket
– one API to attach the callback, returning a handle
– one API to detach the callback using the handle to identify which
previously attached callback to detach
26 / 34
Callbacks
● Explicit and implicit removal are not mutually
exclusive – for example, the callback can return
a certain value to indicate that it is to be
removed implicitly
– Here, we want to avoid a kind of double-free –
where the Javascript callback releases the handle
via a call to the explicit API for releasing, and then
returns a value indicating that we are to release the
handle. We need to check that the handle is not
already released.
27 / 34
Callbacks-Implicit
struct CallbackData {
Nan::Callback *callback;
Nan::Persistent<Object> *jsRemote;
};
void set_int_operation_complete(
void *context, remote_resource *remote,
int result) {
Nan::HandleScope scope;
struct CallbackData *data =
(struct CallbackData *)context;
/* Call JS callback as shown previously */
delete data->callback;
data->jsRemote->Reset();
delete data->jsRemote;
delete data;
}
28 / 34
Callbacks - Explicit
● Structure like CallbackData stores everything
needed to clean up, and is itself stored inside a
JS handle. So, for an API like this
We create the following somewhat self-
referential structure
FileSystemWatch watch_file_name(
const char *file_name,
void (*file_changed)(void *context, const char *file_name, const int fileEvent),
void *context);
bool unwatch_file_name(FileSystemWatch watch);
struct CallbackData {
// This is a JSFileSystemWatch handle containing a pointer to
// this structure
Nan::Persistent<Object> *jsHandle;
Nan::Callback *jsCallback;
FileSystemWatch watch;
};
29 / 34
Callbacks - Explicit
NAN_METHOD(bind_watch_file_name) {
...
CallbackData *data = new CallbackData;
data->watch = watch_file_name(
(const char *)*String::Utf8Value(info[0]),
watch_file_name_event,
data);
data->jsCallback =
new Nan::Callback(Local<Function>::Cast(info[1]));
Local<Object> jsHandle =
JSFileSystemWatch::New(data);
data->jsHandle =
new Nan::Presistent<Object>(jsHandle);
info.GetReturnValue().Set(jsHandle);
}
30 / 34
Callbacks - Explicit
NAN_METHOD(bind_unwatch_file_name) {
CallbackData *data = (CallbackData *)
JSFileSystemWatch::Resolve(Nan::To<Object>(
info[0]).ToLocalChecked());
if (!data) {
return;
}
bool returnValue = unwatch_file_name(data->watch);
if (returnValue) {
delete data->jsCallback;
data->jsHandle->Reset();
delete data->jsHandle;
delete data;
}
info.GetReturnValue().Set(Nan::New(returnValue));
}
Semantics are API-dependent
31 / 34
Callbacks - Explicit
void watch_file_name_event(
void *context,
const char *file_name,
const int fileEvent) {
Nan::HandleScope scope;
CallbackData *data = (CallbackData *)context;
Local<Object> jsHandle =
Nan::New<Object>(*(data->jsHandle));
Local<Value> arguments[2] = {
Nan::New(file_name).ToLocalChecked(),
Nan::New(fileEvent)
};
data->jsCallback->Call(2, arguments);
}
32 / 34
Callbacks - Hybrid
● Can be removed explicitly as well as implicitly
– What if the Javascript callback removes the handle
explicitly and then returns a value indicating that the
handle is to be removed implicitly? →We can must
use ::Resolve()
33 / 34
Callbacks - Hybrid
bool watch_file_name_event(
void *context,
const char *file_name,
const int fileEvent) {
Nan::HandleScope scope;
CallbackData *data = (CallbackData *)context;
Local<Object> jsHandle = Nan::New<Object>(*(data->jsHandle));
Local<Value> arguments[2] = {
Nan::New(file_name).ToLocalChecked(),
Nan::New(fileEvent)
};
Local<Value> jsReturnValue = data->jsCallback->Call(2, arguments);
// validate returnValue and throw an exception if it's not a boolean
bool returnValue =
Nan::To<bool>(jsReturnValue).FromJust();
if (!returnValue) {
data = JSFileSystemWatch::Resolve(jsHandle);
// If data is not null, free it just like in bind_unwatch_file_name()
}
return returnValue;
}
34 / 34
Thanks!
● Thanks @nagineni for helping me hammer out some
of these issues
● Full text is at
https://github.com/gabrielschulhof/bindings-principles
Please
– file issues
– file PRs :)
● Syntax highlighting using pluma
Gabriel Schulhof <gabriel.schulhof@intel.com>

More Related Content

What's hot

Constructors and Destructors
Constructors and DestructorsConstructors and Destructors
Constructors and DestructorsKeyur Vadodariya
 
What's New in C++ 11/14?
What's New in C++ 11/14?What's New in C++ 11/14?
What's New in C++ 11/14?Dina Goldshtein
 
Tutconstructordes
TutconstructordesTutconstructordes
TutconstructordesNiti Arora
 
C++: Constructor, Copy Constructor and Assignment operator
C++: Constructor, Copy Constructor and Assignment operatorC++: Constructor, Copy Constructor and Assignment operator
C++: Constructor, Copy Constructor and Assignment operatorJussi Pohjolainen
 
Constructor and Destructor
Constructor and DestructorConstructor and Destructor
Constructor and DestructorKamal Acharya
 
Exciting JavaScript - Part I
Exciting JavaScript - Part IExciting JavaScript - Part I
Exciting JavaScript - Part IEugene Lazutkin
 
Memory Management C++ (Peeling operator new() and delete())
Memory Management C++ (Peeling operator new() and delete())Memory Management C++ (Peeling operator new() and delete())
Memory Management C++ (Peeling operator new() and delete())Sameer Rathoud
 
Uncommon Design Patterns
Uncommon Design PatternsUncommon Design Patterns
Uncommon Design PatternsStefano Fago
 
C++ Memory Management
C++ Memory ManagementC++ Memory Management
C++ Memory ManagementAnil Bapat
 
Types of Constructor in C++
Types of Constructor in C++Types of Constructor in C++
Types of Constructor in C++Bhavik Vashi
 
classes & objects in cpp overview
classes & objects in cpp overviewclasses & objects in cpp overview
classes & objects in cpp overviewgourav kottawar
 
Oop Constructor Destructors Constructor Overloading lecture 2
Oop Constructor  Destructors Constructor Overloading lecture 2Oop Constructor  Destructors Constructor Overloading lecture 2
Oop Constructor Destructors Constructor Overloading lecture 2Abbas Ajmal
 
Introduction to Objective - C
Introduction to Objective - CIntroduction to Objective - C
Introduction to Objective - CJussi Pohjolainen
 
Constructor and Types of Constructors
Constructor and Types of ConstructorsConstructor and Types of Constructors
Constructor and Types of ConstructorsDhrumil Panchal
 

What's hot (20)

Memory management in c++
Memory management in c++Memory management in c++
Memory management in c++
 
Constructors and Destructors
Constructors and DestructorsConstructors and Destructors
Constructors and Destructors
 
What's New in C++ 11/14?
What's New in C++ 11/14?What's New in C++ 11/14?
What's New in C++ 11/14?
 
Tutconstructordes
TutconstructordesTutconstructordes
Tutconstructordes
 
Constructors and Destructors
Constructors and DestructorsConstructors and Destructors
Constructors and Destructors
 
C++: Constructor, Copy Constructor and Assignment operator
C++: Constructor, Copy Constructor and Assignment operatorC++: Constructor, Copy Constructor and Assignment operator
C++: Constructor, Copy Constructor and Assignment operator
 
Constructor and Destructor
Constructor and DestructorConstructor and Destructor
Constructor and Destructor
 
Constructors & destructors
Constructors & destructorsConstructors & destructors
Constructors & destructors
 
Exciting JavaScript - Part I
Exciting JavaScript - Part IExciting JavaScript - Part I
Exciting JavaScript - Part I
 
Memory Management C++ (Peeling operator new() and delete())
Memory Management C++ (Peeling operator new() and delete())Memory Management C++ (Peeling operator new() and delete())
Memory Management C++ (Peeling operator new() and delete())
 
Uncommon Design Patterns
Uncommon Design PatternsUncommon Design Patterns
Uncommon Design Patterns
 
C++ Memory Management
C++ Memory ManagementC++ Memory Management
C++ Memory Management
 
Types of Constructor in C++
Types of Constructor in C++Types of Constructor in C++
Types of Constructor in C++
 
Memory Management In C++
Memory Management In C++Memory Management In C++
Memory Management In C++
 
classes & objects in cpp overview
classes & objects in cpp overviewclasses & objects in cpp overview
classes & objects in cpp overview
 
Constructor and destructor
Constructor  and  destructor Constructor  and  destructor
Constructor and destructor
 
Constructors destructors
Constructors destructorsConstructors destructors
Constructors destructors
 
Oop Constructor Destructors Constructor Overloading lecture 2
Oop Constructor  Destructors Constructor Overloading lecture 2Oop Constructor  Destructors Constructor Overloading lecture 2
Oop Constructor Destructors Constructor Overloading lecture 2
 
Introduction to Objective - C
Introduction to Objective - CIntroduction to Objective - C
Introduction to Objective - C
 
Constructor and Types of Constructors
Constructor and Types of ConstructorsConstructor and Types of Constructors
Constructor and Types of Constructors
 

Similar to Writing Node.js Bindings - General Principles - Gabriel Schulhof

Core2 Document - Java SCORE Overview.pptx.pdf
Core2 Document - Java SCORE Overview.pptx.pdfCore2 Document - Java SCORE Overview.pptx.pdf
Core2 Document - Java SCORE Overview.pptx.pdfThchTrngGia
 
Need Help with this Java Assignment. Program should be done in JAVA .pdf
Need Help with this Java Assignment. Program should be done in JAVA .pdfNeed Help with this Java Assignment. Program should be done in JAVA .pdf
Need Help with this Java Assignment. Program should be done in JAVA .pdfarchiesgallery
 
Dotnet unit 4
Dotnet unit 4Dotnet unit 4
Dotnet unit 4007laksh
 
Code is not text! How graph technologies can help us to understand our code b...
Code is not text! How graph technologies can help us to understand our code b...Code is not text! How graph technologies can help us to understand our code b...
Code is not text! How graph technologies can help us to understand our code b...Andreas Dewes
 
4Developers 2018: Ile (nie) wiesz o strukturach w .NET (Łukasz Pyrzyk)
4Developers 2018: Ile (nie) wiesz o strukturach w .NET (Łukasz Pyrzyk)4Developers 2018: Ile (nie) wiesz o strukturach w .NET (Łukasz Pyrzyk)
4Developers 2018: Ile (nie) wiesz o strukturach w .NET (Łukasz Pyrzyk)PROIDEA
 
Exploiting GPU's for Columnar DataFrrames by Kiran Lonikar
Exploiting GPU's for Columnar DataFrrames by Kiran LonikarExploiting GPU's for Columnar DataFrrames by Kiran Lonikar
Exploiting GPU's for Columnar DataFrrames by Kiran LonikarSpark Summit
 
C++aptitude questions and answers
C++aptitude questions and answersC++aptitude questions and answers
C++aptitude questions and answerssheibansari
 
C++11: Feel the New Language
C++11: Feel the New LanguageC++11: Feel the New Language
C++11: Feel the New Languagemspline
 
Lazy vs. Eager Loading Strategies in JPA 2.1
Lazy vs. Eager Loading Strategies in JPA 2.1Lazy vs. Eager Loading Strategies in JPA 2.1
Lazy vs. Eager Loading Strategies in JPA 2.1Patrycja Wegrzynowicz
 
Applying Compiler Techniques to Iterate At Blazing Speed
Applying Compiler Techniques to Iterate At Blazing SpeedApplying Compiler Techniques to Iterate At Blazing Speed
Applying Compiler Techniques to Iterate At Blazing SpeedPascal-Louis Perez
 
Lo Mejor Del Pdc2008 El Futrode C#
Lo Mejor Del Pdc2008 El Futrode C#Lo Mejor Del Pdc2008 El Futrode C#
Lo Mejor Del Pdc2008 El Futrode C#Juan Pablo
 
NET Systems Programming Learned the Hard Way.pptx
NET Systems Programming Learned the Hard Way.pptxNET Systems Programming Learned the Hard Way.pptx
NET Systems Programming Learned the Hard Way.pptxpetabridge
 
Kapacitor - Real Time Data Processing Engine
Kapacitor - Real Time Data Processing EngineKapacitor - Real Time Data Processing Engine
Kapacitor - Real Time Data Processing EnginePrashant Vats
 

Similar to Writing Node.js Bindings - General Principles - Gabriel Schulhof (20)

Core2 Document - Java SCORE Overview.pptx.pdf
Core2 Document - Java SCORE Overview.pptx.pdfCore2 Document - Java SCORE Overview.pptx.pdf
Core2 Document - Java SCORE Overview.pptx.pdf
 
Day 1
Day 1Day 1
Day 1
 
Writing MySQL UDFs
Writing MySQL UDFsWriting MySQL UDFs
Writing MySQL UDFs
 
Need Help with this Java Assignment. Program should be done in JAVA .pdf
Need Help with this Java Assignment. Program should be done in JAVA .pdfNeed Help with this Java Assignment. Program should be done in JAVA .pdf
Need Help with this Java Assignment. Program should be done in JAVA .pdf
 
Dotnet unit 4
Dotnet unit 4Dotnet unit 4
Dotnet unit 4
 
Code is not text! How graph technologies can help us to understand our code b...
Code is not text! How graph technologies can help us to understand our code b...Code is not text! How graph technologies can help us to understand our code b...
Code is not text! How graph technologies can help us to understand our code b...
 
4Developers 2018: Ile (nie) wiesz o strukturach w .NET (Łukasz Pyrzyk)
4Developers 2018: Ile (nie) wiesz o strukturach w .NET (Łukasz Pyrzyk)4Developers 2018: Ile (nie) wiesz o strukturach w .NET (Łukasz Pyrzyk)
4Developers 2018: Ile (nie) wiesz o strukturach w .NET (Łukasz Pyrzyk)
 
Exploiting GPU's for Columnar DataFrrames by Kiran Lonikar
Exploiting GPU's for Columnar DataFrrames by Kiran LonikarExploiting GPU's for Columnar DataFrrames by Kiran Lonikar
Exploiting GPU's for Columnar DataFrrames by Kiran Lonikar
 
C++aptitude questions and answers
C++aptitude questions and answersC++aptitude questions and answers
C++aptitude questions and answers
 
C++11: Feel the New Language
C++11: Feel the New LanguageC++11: Feel the New Language
C++11: Feel the New Language
 
Lazy vs. Eager Loading Strategies in JPA 2.1
Lazy vs. Eager Loading Strategies in JPA 2.1Lazy vs. Eager Loading Strategies in JPA 2.1
Lazy vs. Eager Loading Strategies in JPA 2.1
 
Sqlapi0.1
Sqlapi0.1Sqlapi0.1
Sqlapi0.1
 
stack.pptx
stack.pptxstack.pptx
stack.pptx
 
Treinamento Qt básico - aula II
Treinamento Qt básico - aula IITreinamento Qt básico - aula II
Treinamento Qt básico - aula II
 
Applying Compiler Techniques to Iterate At Blazing Speed
Applying Compiler Techniques to Iterate At Blazing SpeedApplying Compiler Techniques to Iterate At Blazing Speed
Applying Compiler Techniques to Iterate At Blazing Speed
 
Lo Mejor Del Pdc2008 El Futrode C#
Lo Mejor Del Pdc2008 El Futrode C#Lo Mejor Del Pdc2008 El Futrode C#
Lo Mejor Del Pdc2008 El Futrode C#
 
Lambdas puzzler - Peter Lawrey
Lambdas puzzler - Peter LawreyLambdas puzzler - Peter Lawrey
Lambdas puzzler - Peter Lawrey
 
Day 2
Day 2Day 2
Day 2
 
NET Systems Programming Learned the Hard Way.pptx
NET Systems Programming Learned the Hard Way.pptxNET Systems Programming Learned the Hard Way.pptx
NET Systems Programming Learned the Hard Way.pptx
 
Kapacitor - Real Time Data Processing Engine
Kapacitor - Real Time Data Processing EngineKapacitor - Real Time Data Processing Engine
Kapacitor - Real Time Data Processing Engine
 

More from WithTheBest

Riccardo Vittoria
Riccardo VittoriaRiccardo Vittoria
Riccardo VittoriaWithTheBest
 
Recreating history in virtual reality
Recreating history in virtual realityRecreating history in virtual reality
Recreating history in virtual realityWithTheBest
 
Engaging and sharing your VR experience
Engaging and sharing your VR experienceEngaging and sharing your VR experience
Engaging and sharing your VR experienceWithTheBest
 
How to survive the early days of VR as an Indie Studio
How to survive the early days of VR as an Indie StudioHow to survive the early days of VR as an Indie Studio
How to survive the early days of VR as an Indie StudioWithTheBest
 
Mixed reality 101
Mixed reality 101 Mixed reality 101
Mixed reality 101 WithTheBest
 
Unlocking Human Potential with Immersive Technology
Unlocking Human Potential with Immersive TechnologyUnlocking Human Potential with Immersive Technology
Unlocking Human Potential with Immersive TechnologyWithTheBest
 
Building your own video devices
Building your own video devicesBuilding your own video devices
Building your own video devicesWithTheBest
 
Maximizing performance of 3 d user generated assets in unity
Maximizing performance of 3 d user generated assets in unityMaximizing performance of 3 d user generated assets in unity
Maximizing performance of 3 d user generated assets in unityWithTheBest
 
Haptics & amp; null space vr
Haptics & amp; null space vrHaptics & amp; null space vr
Haptics & amp; null space vrWithTheBest
 
How we use vr to break the laws of physics
How we use vr to break the laws of physicsHow we use vr to break the laws of physics
How we use vr to break the laws of physicsWithTheBest
 
The Virtual Self
The Virtual Self The Virtual Self
The Virtual Self WithTheBest
 
You dont have to be mad to do VR and AR ... but it helps
You dont have to be mad to do VR and AR ... but it helpsYou dont have to be mad to do VR and AR ... but it helps
You dont have to be mad to do VR and AR ... but it helpsWithTheBest
 
Omnivirt overview
Omnivirt overviewOmnivirt overview
Omnivirt overviewWithTheBest
 
VR Interactions - Jason Jerald
VR Interactions - Jason JeraldVR Interactions - Jason Jerald
VR Interactions - Jason JeraldWithTheBest
 
Japheth Funding your startup - dating the devil
Japheth  Funding your startup - dating the devilJapheth  Funding your startup - dating the devil
Japheth Funding your startup - dating the devilWithTheBest
 
Transported vr the virtual reality platform for real estate
Transported vr the virtual reality platform for real estateTransported vr the virtual reality platform for real estate
Transported vr the virtual reality platform for real estateWithTheBest
 
Measuring Behavior in VR - Rob Merki Cognitive VR
Measuring Behavior in VR - Rob Merki Cognitive VRMeasuring Behavior in VR - Rob Merki Cognitive VR
Measuring Behavior in VR - Rob Merki Cognitive VRWithTheBest
 
Global demand for Mixed Realty (VR/AR) content is about to explode.
Global demand for Mixed Realty (VR/AR) content is about to explode. Global demand for Mixed Realty (VR/AR) content is about to explode.
Global demand for Mixed Realty (VR/AR) content is about to explode. WithTheBest
 
VR, a new technology over 40,000 years old
VR, a new technology over 40,000 years oldVR, a new technology over 40,000 years old
VR, a new technology over 40,000 years oldWithTheBest
 

More from WithTheBest (20)

Riccardo Vittoria
Riccardo VittoriaRiccardo Vittoria
Riccardo Vittoria
 
Recreating history in virtual reality
Recreating history in virtual realityRecreating history in virtual reality
Recreating history in virtual reality
 
Engaging and sharing your VR experience
Engaging and sharing your VR experienceEngaging and sharing your VR experience
Engaging and sharing your VR experience
 
How to survive the early days of VR as an Indie Studio
How to survive the early days of VR as an Indie StudioHow to survive the early days of VR as an Indie Studio
How to survive the early days of VR as an Indie Studio
 
Mixed reality 101
Mixed reality 101 Mixed reality 101
Mixed reality 101
 
Unlocking Human Potential with Immersive Technology
Unlocking Human Potential with Immersive TechnologyUnlocking Human Potential with Immersive Technology
Unlocking Human Potential with Immersive Technology
 
Building your own video devices
Building your own video devicesBuilding your own video devices
Building your own video devices
 
Maximizing performance of 3 d user generated assets in unity
Maximizing performance of 3 d user generated assets in unityMaximizing performance of 3 d user generated assets in unity
Maximizing performance of 3 d user generated assets in unity
 
Wizdish rovr
Wizdish rovrWizdish rovr
Wizdish rovr
 
Haptics & amp; null space vr
Haptics & amp; null space vrHaptics & amp; null space vr
Haptics & amp; null space vr
 
How we use vr to break the laws of physics
How we use vr to break the laws of physicsHow we use vr to break the laws of physics
How we use vr to break the laws of physics
 
The Virtual Self
The Virtual Self The Virtual Self
The Virtual Self
 
You dont have to be mad to do VR and AR ... but it helps
You dont have to be mad to do VR and AR ... but it helpsYou dont have to be mad to do VR and AR ... but it helps
You dont have to be mad to do VR and AR ... but it helps
 
Omnivirt overview
Omnivirt overviewOmnivirt overview
Omnivirt overview
 
VR Interactions - Jason Jerald
VR Interactions - Jason JeraldVR Interactions - Jason Jerald
VR Interactions - Jason Jerald
 
Japheth Funding your startup - dating the devil
Japheth  Funding your startup - dating the devilJapheth  Funding your startup - dating the devil
Japheth Funding your startup - dating the devil
 
Transported vr the virtual reality platform for real estate
Transported vr the virtual reality platform for real estateTransported vr the virtual reality platform for real estate
Transported vr the virtual reality platform for real estate
 
Measuring Behavior in VR - Rob Merki Cognitive VR
Measuring Behavior in VR - Rob Merki Cognitive VRMeasuring Behavior in VR - Rob Merki Cognitive VR
Measuring Behavior in VR - Rob Merki Cognitive VR
 
Global demand for Mixed Realty (VR/AR) content is about to explode.
Global demand for Mixed Realty (VR/AR) content is about to explode. Global demand for Mixed Realty (VR/AR) content is about to explode.
Global demand for Mixed Realty (VR/AR) content is about to explode.
 
VR, a new technology over 40,000 years old
VR, a new technology over 40,000 years oldVR, a new technology over 40,000 years old
VR, a new technology over 40,000 years old
 

Recently uploaded

MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MIND CTI
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobeapidays
 
Vector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptxVector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptxRemote DBA Services
 
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...Angeliki Cooney
 
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...apidays
 
Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)Zilliz
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAndrey Devyatkin
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxRustici Software
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProduct Anonymous
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherRemote DBA Services
 
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...apidays
 
ICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesrafiqahmad00786416
 
Platformless Horizons for Digital Adaptability
Platformless Horizons for Digital AdaptabilityPlatformless Horizons for Digital Adaptability
Platformless Horizons for Digital AdaptabilityWSO2
 
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...apidays
 
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...Zilliz
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FMESafe Software
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfsudhanshuwaghmare1
 

Recently uploaded (20)

MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
Vector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptxVector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptx
 
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
 
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
 
Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptx
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
 
ICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesICT role in 21st century education and its challenges
ICT role in 21st century education and its challenges
 
Understanding the FAA Part 107 License ..
Understanding the FAA Part 107 License ..Understanding the FAA Part 107 License ..
Understanding the FAA Part 107 License ..
 
Platformless Horizons for Digital Adaptability
Platformless Horizons for Digital AdaptabilityPlatformless Horizons for Digital Adaptability
Platformless Horizons for Digital Adaptability
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
 
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 

Writing Node.js Bindings - General Principles - Gabriel Schulhof

  • 1. 1 / 34 Writing Node.js Bindings General Principles Gabriel Schulhof Intel Finland Oy
  • 2. 2 / 34 Assumption ● Make bindings simple – one-to-one – Avoid abstractions in C++ – leave those for Javascript – Benefit: Re-use C API documentation � ● C-specific artifacts need not be exposed to Javascript – Function pointer context – Variable length array via pointer-to-data plus length parameter void some_api( void *context, void (*callback)( void *context, int someUsefulData)); or void some_api( SomeStructure *list, size_t list_length); struct Something { SomeStructure *list; size_t list_length; };
  • 3. 3 / 34 General principles ● Trust data from the native side ● Validate data from the Javascript side ● Avoid argument juggling – Require a certain number of arguments – Require each argument to have a certain type
  • 4. 4 / 34 General principles – Stack ● Make the native call stack mimic Javascript – The binding throws a Javascript exception if parameter array length or parameter type validation fails and returns immediately, without setting the return value – Helpers called by the binding throw a Javascript exception and return false, indicating that the binding is to return immediately because an exception has occurred
  • 5. 5 / 34 General principles - Stack bool some_helper_helper(...) { ... if (something_broken) { Nan::ThrowError("Something is broken!"); return false; } ... return true; } bool some_binding_helper(...) { ... if (!some_helper_helper(...)) { return false; } ... if (something_wrong) { Nan::ThrowError("Something went wrong!"); return false; } ... return true; } NAN_METHOD(bind_some_function) { /* Validate parameter list length and parameter types */ ... if (!some_binding_helper(...)) { return; } ... info.GetReturnValue().Set(Nan::New(returnValue)); }
  • 6. 6 / 34 General principles - Data ● Write a pair of helpers for converting data structures to/from Javascript. For example, for this structure: struct coordinates { double lat; double lon; double alt; };
  • 7. 7 / 34 General principles - Data ● C converter – Returns true on success – Throws Javascript exception and returns false on validation error – Accepts a pointer to a structure to fill out (destination) and a Javascript object containing the Javascript equivalent of the structure (jsSource) – Creates a local variable of the structure type (local) – Retrieves each structure member from jsSource, validates it, and assigns it to local – If all members of local are successfully assigned, *destination = local; return true;
  • 8. 8 / 34 General principles - Data bool c_coordinates( struct coordinates *destination, Local<Object> jsSource) { struct coordinates local; Local<Value> jsLat = Nan::Get(jsSource, Nan::New("lat").ToLocalChecked()) .ToLocalChecked(); if (!jsLat->IsNumber()) { Nan::ThrowError("lat is not a number"); return false; } local.lat = Nan::To<double>(jsLat).FromJust(); // Same for "lon" and for "alt" *destination = local; return true; } Nan::Maybe types provide additionalfailure interception
  • 9. 9 / 34 General principles - Data ● Observation: Because they follow the signature recommended in previous slides, functions of the form c_structurename() as illustrated in the previous slide can be composed if one structure contains one or more other structures: Local<Value> jsMoreDetails = Nan::Get(jsSource, Nan::New("more_details").ToLocalChecked()) .ToLocalChecked(); if (!jsMoreDetails->IsObject()) { Nan::ThrowError( "more_details must be an object!"); return false; } if (!c_more_details(&(local.more_details), Nan::To<Object>(jsMoreDetails).ToLocalChecked())) { return false; }
  • 10. 10 / 34 General principles - Data ● Javascript converter – Returns a Javascript object – Accepts a pointer to a C structure and a Javascript object, which it returns. If absent, it creates a Javascript object (done using C++ default parameter value)
  • 11. 11 / 34 General principles - Data ● Observation: Javascript converters can also be composed: Nan::Set(jsDestination, Nan::New("more_details").ToLocalChecked(), js_more_details(source->more_details)); Local<Object> js_coordinates( const struct coordinates *source, Local<Object> jsDestination = Nan::New<Object>()) { Nan::Set(jsDestination, Nan::New("lat").ToLocalChecked(), Nan::New(source->lat)); Nan::Set(jsDestination, Nan::New("lon").ToLocalChecked(), Nan::New(source->lon)); Nan::Set(jsDestination, Nan::New("alt").ToLocalChecked(), Nan::New(source->alt)); return jsDestination; }
  • 12. 12 / 34 Automating ● Parsing the header files with the usual suspects – cat, grep, awk – Project style conventions can come in handy ● What can be extracted? – Precompiler constants – Enums ● The result: myAddon.SOME_CONSTANT; myAddon.SomeEnum.SOME_ENUM_GREEN; myAddon.SomeEnum.SOME_ENUM_BLUE;
  • 13. 13 / 34 The Simplest Binding ● Function takes primitive data types and returns a primitive data type double area_of_oval(double xRadius, double yRadius); NAN_METHOD(bind_area_of_oval) { VALIDATE_ARGUMENT_COUNT(info, 2); VALIDATE_ARGUMENT_TYPE(info, 0, IsNumber); VALIDATE_ARGUMENT_TYPE(info, 1, IsNumber); Info.GetReturnValue().Set(Nan::New( area_of_oval( Nan::To<double>(info[0]).FromJust(), Nan::To<double>(info[1]).FromJust()))); }
  • 14. 14 / 34 Data ● Any parameter or return value that does not fit in a primitive data type →pointers – Structures ● Traversable ● The pointer itself is not important ● Who owns the pointer?→sometimes ambiguous – Handles ● “magic”, in that the pointer's value is important ● The data to which the pointer refers is often opaque ● The pointer is given by the native side, and is requested back on subsequent calls
  • 15. 15 / 34 Data-Structures struct coordinates { double latitude; double longitude; double altitude; }; /* Both APIs return true on success */ bool find_restaurant_by_name(const char *name, struct coordinates *location); bool restaurant_at_coordinates(const struct coordinates *location); NAN_METHOD(bind_find_restaurant_by_name) { VALIDATE_ARGUMENT_COUNT(info, 2); VALIDATE_ARGUMENT_TYPE(info, 0, IsString); VALIDATE_ARGUMENT_TYPE(info, 1, IsObject); struct coordinates result; bool returnValue = find_restaurant_by_name( (const char *)*(String::Utf8Value(info[0])), &result); if (returnValue) { js_coordinates(&result, Nan::To<Object>(info[1]).ToLocalChecked()); } info.GetReturnValue().Set(Nan::New(returnValue)); }
  • 16. 16 / 34 Data-Structures NAN_METHOD(bind_restaurant_at_coordinates) { VALIDATE_ARGUMENT_COUNT(info, 1); VALIDATE_ARGUMENT_TYPE(info, 0, IsObject); struct coordinates; if (!c_coordinates(&coordinates, Nan::To<Object>(info[0]).ToLocalChecked())) { return; } info.GetReturnValue().Set( Nan::New( restaurant_at_coordinates(&coordinates))); }
  • 17. 17 / 34 Data-Handles ● “magic” value – structure behind it is often opaque – Two APIs – one to get a new handle, one to give it back: ● open()/close() ● setTimeout()/clearTimeout() – Overwrite the return value and you have a leak: ● fd = open(...); fd = -1; ● to = setTimeout(...); to = null; ● interval = setInterval(...); interval = null; – Once you release the handle, if you attempt to use it or release it again, ● nothing happens ● an error is returned ● segfault
  • 18. 18 / 34 Data-Handles ● How to bind? It's a pointer, so … array of bytes? Number? – Bad, because we've chosen not to trust data from Javascript: handle = getHandle(); handle[1] = 5; ● If only we could assign a property to an object that is not visible from Javascript – and I don't mean defineProperty() with enumerable: false because that can still reveal pointer values ● V8 and NAN to the rescue with SetInternalFieldCount()- Store a pointer inside a Javascript object such that it is only accessible from C++ – Javascript objects are copied by reference, so we get the semantics of the setTimeout() return value
  • 19. 19 / 34 Data-Handles ● Let's create a class template for passing handles into Javascript. We assign a void * to a Javascript object while giving the object a nice-looking class name to boot. What do we need of the C++ class? – Instantiation Local<Object> MyJSHandle::New(void *handle); – Give me back the native handle void *MyJSHandle::Resolve(Local<Object> jsHandle); – Gut the Javascript object of its native handle (invalidate) ● We need that for the case where the native handle is gone but the Javascript object is still around: close(fd); /* accidentally */ close(fd); So we need Nan::SetInternalFieldPointer(jsHandle, 0, 0); after which a second call to an API using the handle will either do nothing or throw an exception – we can tell the handle is invalid → segfault averted
  • 20. 20 / 34 template <class T> class JSHandle { static Nan::Persistent<v8::FunctionTemplate> &theTemplate() { static Nan::Persistent<v8::FunctionTemplate> returnValue; if (returnValue.IsEmpty()) { v8::Local<v8::FunctionTemplate> theTemplate = Nan::New<v8::FunctionTemplate>(); theTemplate ->SetClassName(Nan::New(T::jsClassName()).ToLocalChecked()); theTemplate->InstanceTemplate()->SetInternalFieldCount(1); Nan::Set(Nan::GetFunction(theTemplate).ToLocalChecked(), Nan::New("displayName").ToLocalChecked(), Nan::New(T::jsClassName()).ToLocalChecked()); returnValue.Reset(theTemplate); } return returnValue; } public: static v8::Local<v8::Object> New(void *data) { v8::Local<v8::Object> returnValue = Nan::GetFunction(Nan::New(theTemplate())).ToLocalChecked() ->NewInstance(); Nan::SetInternalFieldPointer(returnValue, 0, data); return returnValue; } static void *Resolve(v8::Local<v8::Object> jsObject) { void *returnValue = 0; if (Nan::New(theTemplate())->HasInstance(jsObject)) { returnValue = Nan::GetInternalFieldPointer(jsObject, 0); } if (!returnValue) { Nan::ThrowTypeError((std::string("Object is not of type " + T::jsClassName()).c_str()); } return returnValue; } };
  • 21. 21 / 34 Data-Handles ● Usage: ● And in a binding: class JSRemoteResourceHandle : public JSHandle<JSRemoteResourceHandle> { public: static const char *jsClassName() {return "RemoteResourceHandle";} }; NAN_METHOD(new_handle) { ... struct remote_resource_handle *remote = get_remote_resource(...); info.GetReturnValue().Set( JSRemoteResourceHandle::New(remote)); } NAN_METHOD(use_handle) { Local<Object> jsHandle = Nan::To<Object>(info[0]).ToLocalChecked(); struct remote_resource_handle *remote = JSRemoteResourceHandle::Resolve(jsHandle); if (!remote) { return; } do_something_with_remote_resource(remote, ...); }
  • 22. 22 / 34 Data-Handles ● Important consideration: Avoid creating two different Javascript handles for the same native handle. This can happen in conjunction with callbacks, where the C callback is given a copy of the handle as a convenience: Avoid creating a new Javascript object inside operation_complete() via JSRemoteResource::New(remote) void remote_resource_set_int( remote_resource *remote, int newValue, void (*operation_complete)( void *context, remote_resource *remote, int result), void *context);
  • 23. 23 / 34 Data-Handles struct CallbackData { Nan::Callback *callback; Nan::Persistent<Object> *jsRemote; }; void set_int_operation_complete( void *context, remote_resource *remote, int result) { Nan::HandleScope scope; struct CallbackData *data = (struct CallbackData *)context; Local<Value> arguments[2] = { // JSRemoteHandle::New(remote) Nan::New<Object>(*(data->jsRemote)), Nan::New(result) }; data->callback->Call(2, arguments); ... }
  • 24. 24 / 34 Callbacks ● In C, functions cannot be created/destroyed at runtime, so almost every API that takes a callback has a void *context to distinguish different callbacks – Javascript is the king of context so we do not need to expose this but instead use the context to store at least the Javascript function that we're supposed to call – because Javascript functions can be created/destroyed at runtime
  • 25. 25 / 34 Callbacks ● Two kinds of callbacks – Implicitly removed ● read(); ● setTimeout(); – Explicitly removed ● setInterval(); ● accept(); ● These always come in a pair, forming a bracket – one API to attach the callback, returning a handle – one API to detach the callback using the handle to identify which previously attached callback to detach
  • 26. 26 / 34 Callbacks ● Explicit and implicit removal are not mutually exclusive – for example, the callback can return a certain value to indicate that it is to be removed implicitly – Here, we want to avoid a kind of double-free – where the Javascript callback releases the handle via a call to the explicit API for releasing, and then returns a value indicating that we are to release the handle. We need to check that the handle is not already released.
  • 27. 27 / 34 Callbacks-Implicit struct CallbackData { Nan::Callback *callback; Nan::Persistent<Object> *jsRemote; }; void set_int_operation_complete( void *context, remote_resource *remote, int result) { Nan::HandleScope scope; struct CallbackData *data = (struct CallbackData *)context; /* Call JS callback as shown previously */ delete data->callback; data->jsRemote->Reset(); delete data->jsRemote; delete data; }
  • 28. 28 / 34 Callbacks - Explicit ● Structure like CallbackData stores everything needed to clean up, and is itself stored inside a JS handle. So, for an API like this We create the following somewhat self- referential structure FileSystemWatch watch_file_name( const char *file_name, void (*file_changed)(void *context, const char *file_name, const int fileEvent), void *context); bool unwatch_file_name(FileSystemWatch watch); struct CallbackData { // This is a JSFileSystemWatch handle containing a pointer to // this structure Nan::Persistent<Object> *jsHandle; Nan::Callback *jsCallback; FileSystemWatch watch; };
  • 29. 29 / 34 Callbacks - Explicit NAN_METHOD(bind_watch_file_name) { ... CallbackData *data = new CallbackData; data->watch = watch_file_name( (const char *)*String::Utf8Value(info[0]), watch_file_name_event, data); data->jsCallback = new Nan::Callback(Local<Function>::Cast(info[1])); Local<Object> jsHandle = JSFileSystemWatch::New(data); data->jsHandle = new Nan::Presistent<Object>(jsHandle); info.GetReturnValue().Set(jsHandle); }
  • 30. 30 / 34 Callbacks - Explicit NAN_METHOD(bind_unwatch_file_name) { CallbackData *data = (CallbackData *) JSFileSystemWatch::Resolve(Nan::To<Object>( info[0]).ToLocalChecked()); if (!data) { return; } bool returnValue = unwatch_file_name(data->watch); if (returnValue) { delete data->jsCallback; data->jsHandle->Reset(); delete data->jsHandle; delete data; } info.GetReturnValue().Set(Nan::New(returnValue)); } Semantics are API-dependent
  • 31. 31 / 34 Callbacks - Explicit void watch_file_name_event( void *context, const char *file_name, const int fileEvent) { Nan::HandleScope scope; CallbackData *data = (CallbackData *)context; Local<Object> jsHandle = Nan::New<Object>(*(data->jsHandle)); Local<Value> arguments[2] = { Nan::New(file_name).ToLocalChecked(), Nan::New(fileEvent) }; data->jsCallback->Call(2, arguments); }
  • 32. 32 / 34 Callbacks - Hybrid ● Can be removed explicitly as well as implicitly – What if the Javascript callback removes the handle explicitly and then returns a value indicating that the handle is to be removed implicitly? →We can must use ::Resolve()
  • 33. 33 / 34 Callbacks - Hybrid bool watch_file_name_event( void *context, const char *file_name, const int fileEvent) { Nan::HandleScope scope; CallbackData *data = (CallbackData *)context; Local<Object> jsHandle = Nan::New<Object>(*(data->jsHandle)); Local<Value> arguments[2] = { Nan::New(file_name).ToLocalChecked(), Nan::New(fileEvent) }; Local<Value> jsReturnValue = data->jsCallback->Call(2, arguments); // validate returnValue and throw an exception if it's not a boolean bool returnValue = Nan::To<bool>(jsReturnValue).FromJust(); if (!returnValue) { data = JSFileSystemWatch::Resolve(jsHandle); // If data is not null, free it just like in bind_unwatch_file_name() } return returnValue; }
  • 34. 34 / 34 Thanks! ● Thanks @nagineni for helping me hammer out some of these issues ● Full text is at https://github.com/gabrielschulhof/bindings-principles Please – file issues – file PRs :) ● Syntax highlighting using pluma Gabriel Schulhof <gabriel.schulhof@intel.com>