SlideShare uma empresa Scribd logo
1 de 34
Baixar para ler 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>

Mais conteúdo relacionado

Mais procurados

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
 

Mais procurados (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
 

Semelhante a 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
 

Semelhante a 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
 

Mais de 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
 

Mais de 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
 

Último

Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationSafe Software
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 
Story boards and shot lists for my a level piece
Story boards and shot lists for my a level pieceStory boards and shot lists for my a level piece
Story boards and shot lists for my a level piececharlottematthew16
 
Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clashcharlottematthew16
 
Search Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfSearch Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfRankYa
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxhariprasad279825
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024Lorenzo Miniero
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Enterprise Knowledge
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticscarlostorres15106
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenHervé Boutemy
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Manik S Magar
 
My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024The Digital Insurer
 
Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsMiki Katsuragi
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfAddepto
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Patryk Bandurski
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationRidwan Fadjar
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brandgvaughan
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Scott Keck-Warren
 

Último (20)

Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 
Story boards and shot lists for my a level piece
Story boards and shot lists for my a level pieceStory boards and shot lists for my a level piece
Story boards and shot lists for my a level piece
 
Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clash
 
Search Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfSearch Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdf
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptx
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
 
DMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special EditionDMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special Edition
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache Maven
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!
 
My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024
 
Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering Tips
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdf
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 Presentation
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brand
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024
 

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>