1 # v8+: Node.js addon C++ to C boundary layer
   2 
   3 This layer offers a way to write at least simple Node.js addons in C without
   4 all the horrible C++ goop you'd otherwise be expected to use.  That goop
   5 still exists, but you don't have to write it.  More importantly, you can
   6 write your module in a sane programming environment, avoiding the confusing
   7 and error-prone C++ semantics.
   8 
   9 ## Usage
  10 
  11 Unlike most Node.js modules, v8+ does nothing by itself.  It is intended to
  12 be used as a build-time dependency of your native addon, providing you with
  13 an alternate programming environment.
  14 
  15 For full docs, read the source code.
  16 
  17 ## Node.js Support
  18 
  19 v8+ works with, and has been tested to some extent with, Node.js 0.6.18 and
  20 0.8.1.  It most likely works with other micro versions in the 0.6 and 0.8
  21 series as well.  Note that this does not mean you can necessarily expect an
  22 addon built against a particular minor release of Node.js to work with any
  23 other minor release of Node.js.
  24 
  25 ## Building and Installing
  26 
  27 The v8+ source code is compiled into your module directly along with your
  28 code.  There is no separate v8+ library or node module, so the v8+ source,
  29 tools, and makefiles are required to be present at the time your module is
  30 built.  They are not required at runtime.
  31 
  32 Normally, your addon module will depend on the v8plus package and install it
  33 using npm.  The v8+ makefiles are set up to accommodate the installation of
  34 v8+ anywhere `node(1)` would be able to find it using `require()` if it were
  35 a normal JavaScript module, so simply including it as a dependency in your
  36 `package.json` will work correctly.  In addition, you will need to create a
  37 (normally trivial) makefile for your module that includes the makefiles
  38 distributed as part of v8+.  Once you have done so, it is sufficient to run
  39 `gmake` to generate the native loadable module used by Node.js.
  40 
  41 The overall outline for creating a v8+ module looks something like this:
  42 
  43 1. Write the C code that does whatever your module does.  Be sure to
  44 \#include "v8plus_glue.h".  Do not include any other v8+ headers.
  45 
  46 2. Create an appropriate `package.json` file.  See below for details.
  47 
  48 3. Create a skeleton makefile.  See below for details.
  49 
  50 4. Create a JSON file defining the error codes your module will use.  See
  51 Errors below.
  52 
  53 You should not (and need not) modify either of the delivered makefiles;
  54 override the definitions in Makefile.v8plus.defs in your makefile as
  55 appropriate.
  56 
  57 ### Packaging Considerations
  58 
  59 There are two essential properties your `package.json` must contain in order
  60 to use v8+ with npm:
  61 
  62 1. A dependency on `v8plus`.
  63 
  64 2. An appropriate script entry for building your module.  It is strongly
  65    recommended that you use something like the following:
  66 
  67         "postinstall": "gmake $(eval echo ${MAKE_OVERRIDES})"
  68 
  69 This will allow someone building your module to set make variables by adding
  70 them to the `MAKE_OVERRIDES` environment variable; e.g.,
  71 
  72         $ MAKE_OVERRIDES="CTFCONVERT=/bin/true CTFMERGE=/bin/true" npm install
  73 
  74 ### Tying into the Makefiles
  75 
  76 The makefiles shipped with v8+ do the great majority of the heavy lifting
  77 for you.  A minimally functional makefile for your addon must contain four
  78 things:
  79 
  80 1. Variable definitions for `V8PLUS` and `PREFIX_NODE`.  Alternately, you
  81    may choose to provide these on the command line or via the environment.
  82    It is recommended that these assignments be made exactly as follows,
  83    which will cause the addon to be built against the `node` that is found
  84    first in your path:
  85 
  86         PREFIX_NODE := $(shell dirname `bash -c 'hash node; hash -t node'`)/..
  87         V8PLUS :=      $(shell $(PREFIX_NODE)/bin/node -e 'require("v8plus");')
  88 
  89    Note that the mechanism for finding `node` will not work correctly if
  90    yours is a symlink.  This invocation of node(1) uses a v8+ mechanism to
  91    locate v8+ sources anywhere that node(1) can find them and should not be
  92    modified unless you want to test an alternate v8+.
  93 
  94 2. The exact line:
  95 
  96         include $(V8PLUS)/Makefile.v8plus.defs
  97 
  98 3. Variable assignments specific to your module.  In particular, you must
  99    define `SRCS`, `MODULE`, and `ERRNO_JSON`.  Additional customisation is
 100    optional.
 101 
 102 4. The exact line:
 103 
 104         include $(V8PLUS)/Makefile.v8plus.targ
 105 
 106 Additional arbitrary customisation is possible using standard makefile
 107 syntax; most things that are useful to change already have variables defined
 108 in `Makefile.v8plus.defs` whose values you may append to or override.  For
 109 example, you may cause additional system libraries to be linked in by
 110 appending `-lname` to the `LIBS` variable.  By default, the makefiles assume
 111 that your sources are located in the `src` subdirectory of your module, and
 112 that you want the sole output of the build process to be called
 113 `$(MODULE).node` and located in the `lib` subdirectory.  This can be changed
 114 by overriding the `MODULE_DIR` variable.
 115 
 116 A simple example makefile may be found in the `examples/` subdirectory, and
 117 additional examples may be found in existing consumers; see Consumers below.
 118 The GNU people also provide a good manual for make if you get really stuck;
 119 see <http://www.gnu.org/software/make/manual/make.html>.  In general,
 120 writing the necessary makefile fragment is expected to be as easy as or
 121 easier than the equivalent task using `node-waf` or `node-gyp`, so if you're
 122 finding it unexpectedly difficult or complicated there's probably an easier
 123 way.
 124 
 125 The makefiles follow GNU make syntax; other makes may not work but patches
 126 that correct this are generally welcome (in particular, Sun make and GNU
 127 make have different and incompatible ways to set a variable from the output
 128 of a shell command, and there is no way I know to accommodate both).
 129 
 130 ### Binary Interface
 131 
 132 By default, the resulting object is linked with the `-zdefs` option, which
 133 will cause the build to fail if any unresolved symbols remain.  In order to
 134 accommodate this, a mapfile specifying the available global symbols in your
 135 `node` binary is automatically generated as part of the build process.  This
 136 makes it much easier to debug missing libraries; otherwise, a module with
 137 unresolved symbols will fail to load at runtime with no useful explanation.
 138 Mapfile generation probably works only on illumos-derived systems.  Patches
 139 that add support for other linkers are welcome.
 140 
 141 Your module will have all symbols (other than `init`, which is used directly
 142 by Node.js) reduced to local visibility, which is strongly recommended.  If
 143 for some reason you want your module's symbols to be visible to Node.js or
 144 to other modules, you will have to modify the script that generates the
 145 mapfile.  See the `$(MAPFILE)` target in `Makefile.v8plus.targ`.
 146 
 147 ## API
 148 
 149 Your module is an object factory that instantiates and returns native
 150 objects, to which a fixed set of methods is attached as properties.  The
 151 constructor, destructor, and methods all correspond 1-1 with C functions.
 152 In addition, you may create additional class methods associated with the
 153 native module itself, each of which will also have a 1-1 relationship to a
 154 set of C functions.
 155 
 156 This functionality is generally sufficient to interface with the system in
 157 useful ways, but it is by no means exhaustive.  Architectural limitations
 158 are noted throughout the documentation.
 159 
 160 Subsequent sections describe the API in greater detail, along with most of
 161 the C functions that v8+ provides.  Some utility functions may not be listed
 162 here; see `v8plus_glue.h` for additional commentary and functions that are
 163 available to you.
 164 
 165 ### Constructors, Methods, and Functions
 166 
 167 The interface between your module and v8+ consists of a handful of objects
 168 with fixed types and names.  These are:
 169 
 170         const v8plus_c_ctor_f v8plus_ctor = my_ctor;
 171         const v8plus_c_dtor_f v8plus_dtor = my_dtor;
 172         const char *v8plus_js_factory_name = "_new";
 173         const char *v8plus_js_class_name = "MyObjectBinding";
 174         const v8plus_method_descr_t v8plus_methods[] = {
 175                 {
 176                         md_name: "_my_method",
 177                         md_c_func: my_method
 178                 },
 179                 ...
 180         };
 181         const uint_t v8plus_method_count =
 182             sizeof (v8plus_methods) / sizeof (v8plus_methods[0]);
 183 
 184         const v8plus_static_descr_t v8plus_static_methods[] = {
 185                 {
 186                         sd_name: "_my_function",
 187                         sd_c_func: my_function
 188                 },
 189                 ...
 190         };
 191         const uint_t v8plus_static_method_count =
 192             sizeof (v8plus_static_methods) / sizeof (v8plus_static_methods[0]);
 193 
 194 All of these must be present even if they have zero length or are NULL.  The
 195 prototypes and semantics of each function type are as follows:
 196 
 197 ### nvlist_t *v8plus_c_ctor_f(const nvlist_t *ap, void **opp)
 198 
 199 The constructor is responsible for creating the C object corresponding to
 200 the native JavaScript object being created.  It is not a true constructor in
 201 that you are actually an object factory; the C++ function associated with
 202 the JavaScript constructor is called for you.  Your encoded arguments are in
 203 `ap`.  Allocate and populate a C object, stuff it into `*opp`, and return
 204 `v8plus_void()`.  If you need to throw an exception you can do so by
 205 returning `v8plus_error()` or one of its wrappers, or by setting
 206 `_v8plus_errno` using one of those functions and then returning an nvlist
 207 with an `err` member representing a decorated exception.
 208 
 209 ### void v8plus_c_dtor_f(void *op)
 210 
 211 Free the C object `op` and anything else associated with it.  Your object is
 212 going away.  This function may be empty if the constructor did not allocate
 213 any memory (i.e., `op` is not a pointer to dynamically allocated memory).
 214 
 215 ### nvlist_t *v8plus_c_method_f(void *op, const nvlist_t *ap)
 216 
 217 When the JavaScript method is called in the context of your object, the
 218 corresponding C function is invoked.  `op` is the C object associated with
 219 the JavaScript object, and `ap` is the encoded list of arguments to the
 220 function.  Return an encoded object with a `res` member, or use one of the
 221 error/exception patterns.
 222 
 223 ### nvlist_t *v8plus_c_static_method_f(const nvlist_t *ap)
 224 
 225 In addition to methods on the native objects returned by your constructor,
 226 you can also provide a set of functions on the native binding object itself.
 227 This may be useful for providing bindings to libraries for which no object
 228 representation makes sense, or that have functions that operate outside the
 229 context of any particular object.  Your arguments are once again encoded in
 230 `ap`, and your return values are an object containing `res` or an error.
 231 
 232 ### Argument Handling
 233 
 234 When JavaScript objects cross the boundary from C++ to C, they are converted
 235 from v8 C++ objects into C nvlists.  This means that they are effectively
 236 passed by value, unlike in JavaScript or in native addons written in C++.
 237 The arguments to the JavaScript function are treated as an array and
 238 marshalled into a single nvlist whose properties are named "0", "1", and so
 239 on.  Each such property is encoded as follows:
 240 
 241 - numbers and Number objects (regardless of size): double
 242 - strings and String objects: UTF-8 encoded C string
 243 - booleans and Boolean objects: boolean_value
 244 - undefined: boolean
 245 - null: byte, value 0
 246 - Objects, including Arrays: nvlist with own properties as members and the
 247 member ".__v8plus_type" set to the object's JavaScript type name.  Note
 248 that the member name itself begins with a . to reduce the likelihood of a
 249 collision with an actual JavaScript member name.
 250 - JavaScript Functions are passed in a format suitable for use with
 251   `nvlist_lookup_jsfunc()` and `v8plus_args()` with the V8PLUS_TYPE_JSFUNC
 252   token.  This type is restricted; see below.
 253 
 254 Because JavaScript arrays may be sparse, we cannot use the libnvpair array
 255 types.  Consider them reserved for internal use.  JavaScript Arrays are
 256 represented as they really are in JavaScript: objects with properties whose
 257 names happen to be integers.
 258 
 259 Other data types cannot be represented and will result in a TypeError
 260 being thrown.  If your object has methods that need other argument types,
 261 you cannot use v8+.
 262 
 263 Side effects within the VM, including modification of the arguments, are
 264 not supported.  If you need them, you cannot use v8+.
 265 
 266 While the standard libnvpair functions may be used to inspect the arguments
 267 to a method or function, v8+ also provides the `v8plus_args()` and
 268 `v8plus_typeof()` convenience functions, which simplify checking the types
 269 and obtaining the values of arguments.
 270 
 271 ### int v8plus_args(const nvlist_t *lp, uint_t flags, v8plus_type_t t, ...)
 272 
 273 This function checks `lp` for the exact sequence of arguments specified by
 274 the list of types provided in the parameter list.  If `V8PLUS_ARG_F_NOEXTRA`
 275 is set in `flags`, the list of arguments must match exactly, with no
 276 additional arguments.  The parameter list must be terminated by
 277 `V8PLUS_TYPE_NONE`.
 278 
 279 Following `flags` is a list of argument data types and, for most data types,
 280 pointers to locations at which the native C value of that argument should be
 281 stored.  The following JavaScript argument data types are supported; for
 282 each, the parameter immediately following the data type parameter must be of
 283 the indicated C type.  This parameter may be `NULL`, in which case the value
 284 will not be stored anywhere.
 285 
 286 - V8PLUS_TYPE_NONE: used to terminate the parameter list only
 287 - V8PLUS_TYPE_STRING: char **
 288 - V8PLUS_TYPE_NUMBER: double *
 289 - V8PLUS_TYPE_BOOLEAN: boolean_t *
 290 - V8PLUS_TYPE_JSFUNC: v8plus_jsfunc_t *
 291 - V8PLUS_TYPE_OBJECT: nvlist_t **
 292 - V8PLUS_TYPE_NULL: no parameter
 293 - V8PLUS_TYPE_UNDEFINED: no parameter
 294 - V8PLUS_TYPE_INVALID: data_type_t (see below)
 295 - V8PLUS_TYPE_ANY: nvpair_t **
 296 - V8PLUS_TYPE_STRNUMBER64: uint64_t *
 297 - V8PLUS_TYPE_INL_OBJECT: illegal
 298 
 299 In most cases, the behaviour is straightforward: the value pointer parameter
 300 provides a location into which the C value of the specified argument should
 301 be stored.  If the entire argument list matches the template, each
 302 argument's C value is stored in its respective location.  If not, no values
 303 are stored, in the return value locations, `_v8plus_errno` is set
 304 appropriately, and -1 is returned.
 305 
 306 Three data types warrant further explanation: an argument of type
 307 `V8PLUS_TYPE_INVALID` is any argument that may or may not match one of the
 308 acceptable types.  Its nvpair data type tag is stored and the argument
 309 treated as matching.  The value is ignored.  `V8PLUS_TYPE_STRNUMBER64` is
 310 used with strings that should be interpreted as 64-bit unsigned integers.
 311 If the argument is not a string, or is not parseable as a 64-bit unsigned
 312 integer, the argument will be treated as a mismatch.  Finally,
 313 `V8PLUS_TYPE_INL_OBJECT` is not supported with `v8plus_args()`; JavaScript
 314 objects in the argument list must be individually inspected as nvlists.
 315 
 316 A simple example:
 317 
 318         double_t d;
 319         boolean_t b;
 320         char *s;
 321         v8plus_jsfunc_t f;
 322 
 323         /*
 324          * This function requires exactly four arguments: a number, a
 325          * boolean, a string, and a callback function.  It is not acceptable
 326          * to pass superfluous arguments to it.
 327          */
 328         if (v8plus_args(ap, V8PLUS_ARG_F_NOEXTRA,
 329             V8PLUS_TYPE_NUMBER, &d,
 330             V8PLUS_TYPE_BOOLEAN, &b,
 331             V8PLUS_TYPE_STRING, &s,
 332             V8PLUS_TYPE_JSFUNC, &f,
 333             V8PLUS_TYPE_NONE) != 0)
 334                 return (NULL);
 335 
 336 ### v8plus_type_t v8plus_typeof(const nvpair_t *pp)
 337 
 338 This function simply returns the v8+ data type corresponding to the
 339 name/value pair `pp`.  If the value's type does not match the v8+ encoding
 340 rules, `V8PLUS_TYPE_INVALID` is returned.  This function cannot fail and
 341 does not modify `_v8plus_errno`.
 342 
 343 ### Returning Values
 344 
 345 Similarly, when returning data across the boundary from C to C++, a
 346 pointer to an nvlist must be returned.  This object will be decoded in
 347 the same manner as described above and returned to the JavaScript caller
 348 of your method.  Note that booleans, strings, and numbers will be encoded
 349 as their primitive types, not objects.  If you need to return something
 350 containing these object types, you cannot use v8+.  Other data types
 351 cannot be represented.  If you need to return them, you cannot use v8+.
 352 
 353 The nvlist being returned must have one of two members: "res", an nvpair
 354 containing the result of the call to be returned, or "err", an nvlist
 355 containing members to be added to an exception.  You may return a value of
 356 any decodable type, and likewise may decorate an exception with properties
 357 of any decodable type.
 358 
 359 For convenience, you may return v8plus_void() instead of an nvlist,
 360 which indicates successful execution of a function that returns nothing.
 361 
 362 In addition, the `v8plus_obj()` routine is available for instantiating
 363 JavaScript objects to return.
 364 
 365 ### nvlist_t *v8plus_void(void)
 366 
 367 This function clears `_v8plus_errno` and returns NULL.  This is used to
 368 indicate to internal v8+ code that the method or function should not return
 369 a value.
 370 
 371 ### nvlist_t *v8plus_obj(v8plus_type_t t, ...)
 372 
 373 This function creates and populates an nvlist conforming to the encoding
 374 rules of v8+ for returning a value or creating an exception.  It can be used
 375 to create anything from a single encoded value to arbitrarily nested
 376 objects.  It is essentially the inverse of `v8plus_args()` above, with a few
 377 differences:
 378 
 379 - It cannot be used to encode invalid or illegal data types.
 380 - It accepts native C values, not pointers to them.
 381 - Each value must be named.
 382 - It can be used to encode nested objects inline using
 383   `V8PLUS_TYPE_INL_OBJECT`, followed by type, name, value triples,
 384   terminated with `V8PLUS_TYPE_NONE`.
 385 
 386 This function can fail due to out-of-memory conditions, invalid or
 387 unsupported data types, or, most commonly, programmer error in casting the
 388 arguments to the correct type.  *It is extremely important that data values,
 389 particularly integers, be cast to the appropriate type (double) when passed
 390 into this function!*
 391 
 392 Following is a list of types and the C data types corresponding to their
 393 values:
 394 
 395 - V8PLUS_TYPE_NONE: used to terminate the parameter list only
 396 - V8PLUS_TYPE_STRING: char *
 397 - V8PLUS_TYPE_NUMBER: double
 398 - V8PLUS_TYPE_BOOLEAN: boolean_t
 399 - V8PLUS_TYPE_JSFUNC: v8plus_jsfunc_t
 400 - V8PLUS_TYPE_OBJECT: nvlist_t *
 401 - V8PLUS_TYPE_NULL: no parameter
 402 - V8PLUS_TYPE_UNDEFINED: no parameter
 403 - V8PLUS_TYPE_ANY: nvpair_t *
 404 - V8PLUS_TYPE_STRNUMBER64: uint64_t
 405 - V8PLUS_TYPE_INL_OBJECT: NONE-terminated type/value list
 406 
 407 A simple example, in which we return a JavaScript object with two members,
 408 one number and one embedded object with a 64-bit integer property.  Note
 409 that if this function fails, we will return `NULL` with `_v8plus_errno` set
 410 appropriately, so v8+ will generate and throw an appropriate exception.
 411 
 412         int x;
 413         const char *s;
 414 
 415         ...
 416         return (v8plus_obj(
 417             V8PLUS_TYPE_INL_OBJECT, "res",
 418                 V8PLUS_TYPE_NUMBER, "value", (double)x,
 419                 V8PLUS_TYPE_INL_OBJECT, "detail",
 420                     V8PLUS_TYPE_STRNUMBER64, "value64", s,
 421                     V8PLUS_TYPE_NONE,
 422                 V8PLUS_TYPE_NONE,
 423             V8PLUS_TYPE_NONE));
 424 
 425 The JSON representation of this object would be:
 426 
 427         {
 428                 "res": {
 429                         "value": <x>,
 430                         "detail": {
 431                                 "value64": "<s>"
 432                         }
 433                 }
 434         }
 435 
 436 ### v8plus_obj_setprops(nvlist_t *lp, v8plus_type_t t, ...)
 437 
 438 You can also add or replace the values of properties in an existing nvlist,
 439 whether created using `nvlist_alloc()` directly or via `v8plus_obj()`.  The
 440 effect is very similar to `nvlist_merge()`, where the second list is created
 441 on the fly from your argument list.  The interpretation of the argument list
 442 is the same as for `v8plus_obj()`, and the two functions are implemented
 443 using the same logic.
 444 
 445 ### Exceptions
 446 
 447 If you are unable to create an nvlist to hold exception data, or you want a
 448 generic exception to be thrown, return the value returned by v8plus_error().
 449 In this case, the error code will be translated to an exception type and the
 450 message string will be used as the message member of the exception.  Other
 451 members will not be present in the exception unless you also return an
 452 nvlist containing an 'err' member (or, from a constructor, any nvlist) Only
 453 basic v8-provided exception types can be thrown; if your addon needs to
 454 throw some other kind of exception, you will need to either use v8 directly
 455 or catch and re-throw from a JavaScript wrapper.
 456 
 457 ## Errors
 458 
 459 The v8plus_errno_t enumerated type and a family of utility functions are
 460 automatically generated by generrno.js from a simple JSON file.  The schema
 461 of this file is as follows:
 462 
 463         {
 464                 "error_base": <string>,
 465                 "errors": [
 466                 {
 467                         "code": <string>,
 468                         "msg": <string>,
 469                         "exception": <string>
 470                 },
 471                 ...  ]
 472         }
 473 
 474 For each entry in the errors array, an identifier V8PLUSERR_code will be
 475 added to v8plus_errno_t.  By convention, code should be all upper case.  The
 476 default error message (present in JavaScript exceptions if a more specific
 477 error message is not provided to v8plus_error()) is given by the msg
 478 property.  The exception property must be one of "Error", "TypeError",
 479 "ReferenceError", "RangeError", or "SyntaxError"; i.e., the standard
 480 exception types available in v8.  This is the type of exception that will be
 481 generated and thrown when a C function returns NULL with this error code
 482 set.  In addition, the built-in error codes V8PLUSERR_NOMEM,
 483 V8PLUSERR_YOUSUCK, and V8PLUSERR_UNKNOWN are available for your use,
 484 indicating an out of memory condition, programmer error (e.g., failure of
 485 something you would assert in JavaScript), and an error code that cannot be
 486 translated, respectively.
 487 
 488 Set the make variable ERRNO_JSON to the name of this file.
 489 
 490 To set the value of `_v8plus_errno`, use one of the following functions.  It
 491 is a bug to manipulate this variable directly.
 492 
 493 ### nvlist_t *v8plus_verror(v8plus_errno_t e, const char *fmt, va_list)
 494 
 495 This is the varargs analogue to `v8plus_error()` and has identical
 496 semantics.  Use this if you want to wrap manipulation of the v8+ error state
 497 within your own varargs functions.
 498 
 499 ### nvlist_t *v8plus_error(v8plus_errno_t e, const char *fmt, ...)
 500 
 501 This function sets the value of `_v8plus_errno` to `e` and sets the
 502 associated error message string to the formatted string `fmt` using the
 503 argument list that follows.  The format string and arguments are interpreted
 504 as by `vsnprintf(3c)`.  NULL is returned, suitable for returning directly
 505 from a C function that provides a method if no exception decoration is
 506 required.
 507 
 508 If `fmt` is NULL, a generic default message is used; for consumer-defined
 509 error codes, that message is the one provided in `errno.json`.
 510 
 511 ### nvlist_t *v8plus_nverr(int errno, const char *propname)
 512 
 513 This function sets the value of `_v8plus_errno` to a value mapped from the
 514 system error code `errno` and sets the error message to a non-localised
 515 explanation of the problem.  The string `propname`, if non-NULL, is
 516 indicated in the message as the name of the nvlist property being
 517 manipulated when the error occurred.  NULL is returned.
 518 
 519 ### nvlist_t *v8plus_syserr(int errno, const char *fmt, ...)
 520 
 521 Analogous to `v8plus_error()`, this function instead sets the error code to
 522 a mapped value derived from the system error code `errno`.  Not all error
 523 codes can be mapped; those that are not known are mapped onto
 524 `V8PLUSERR_UNKNOWN`.  This function's semantics are otherwise identical to
 525 those of `v8plus_error()`.
 526 
 527 ### void v8plus_panic(const char *fmt, ...) __NORETURN
 528 
 529 This function indicates a fatal runtime error.  The format string `fmt` and
 530 subsequent arguments are interpreted as by `vsnprintf(3c)` and written to
 531 standard error, which is then flushed.  `abort(3c)` or similar is then
 532 invoked to terminate the Node.js process in which the addon is running.  Use
 533 of this function should be limited to those circumstances in which an
 534 internal inconsistency has been detected that renders further progress
 535 hazardous to user data or impossible.
 536 
 537 ### Asynchrony
 538 
 539 There are two main types of asynchrony supported by v8+.  The first is the
 540 deferred work model (using `uv_queue_work()` or the deprecated
 541 `eio_custom()` mechanisms) frequently written about and demonstrated by
 542 various practitioners around the world.  In this model, your method or
 543 function takes a callback argument and returns immediately after enqueuing a
 544 task to run on one of the threads in the Node.js worker thread pool.  That
 545 task consists of a C function to be run on the worker thread, which may not
 546 use any V8 (or v8+) state, and a function to be run in the main event loop
 547 thread when that task has completed.  The latter function is normally
 548 expected to invoke the caller's original callback.  In v8+, this takes the
 549 following form:
 550 
 551         void *
 552         async_worker(void *cop, void *ctxp)
 553         {
 554                 my_object_t *op = cop;
 555                 my_context_t *cp = ctxp;
 556                 my_result_t *rp = ...;
 557 
 558                 /*
 559                  * In thread pool context -- do not call any of the
 560                  * following functions:
 561                  * v8plus_obj_hold()
 562                  * v8plus_obj_rele()
 563                  * v8plus_jsfunc_hold()
 564                  * v8plus_jsfunc_rele()
 565                  * v8plus_call()
 566                  * v8plus_method_call_direct()
 567                  * v8plus_defer()
 568                  *
 569                  * If you touch anything inside op, you may need locking to
 570                  * protect against functions called in the main thread.
 571                  */
 572                 ...
 573 
 574                 return (rp);
 575         }
 576 
 577         void
 578         async_completion(void *cop, void *ctxp, void *resp)
 579         {
 580                 my_object_t *op = cop;
 581                 my_context_t *cp = ctxp;
 582                 my_result_t *rp = resp;
 583                 nvlist_t *cbap;
 584                 nvlist_t *cbrp;
 585 
 586                 ...
 587                 cbap = v8plus_obj(
 588                     V8PLUS_TYPE_WHATEVER, "0", rp->mr_value,
 589                     V8PLUS_TYPE_NONE);
 590 
 591                 if (cbap != NULL) {
 592                         cbrp = v8plus_call(cp->mc_callback, cbap);
 593                         nvlist_free(cbap);
 594                         nvlist_free(cbrp);
 595                 }
 596 
 597                 v8plus_jsfunc_rele(cp->mc_callback);
 598                 free(cp);
 599                 free(rp);
 600         }
 601 
 602         nvlist_t *
 603         async(void *cop, const nvlist_t *ap)
 604         {
 605                 my_object_t *op = cop;
 606                 v8plus_jsfunc_t cb;
 607                 my_context_t *cp = malloc(sizeof (my_context_t));
 608                 ...
 609                 if (v8plus_args(ap, 0, V8PLUS_TYPE_JSFUNC, &cb,
 610                     V8PLUS_TYPE_NONE) != 0) {
 611                         free(cp);
 612                         return (NULL);
 613                 }
 614 
 615                 v8plus_jsfunc_hold(cb);
 616                 cp->mc_callback = cb;
 617                 v8plus_defer(op, cp, async_worker, async_completion);
 618 
 619                 return (v8plus_void());
 620         }
 621 
 622 This mechanism uses `uv_queue_work()` and as such will tie up one of the
 623 worker threads in the pool for as long as `async_worker` is running.
 624 
 625 The other asynchronous mechanism is the Node.js `EventEmitter` model.  This
 626 model requires some assistance from JavaScript code, because v8+ native
 627 objects do not inherit from `EventEmitter`.  To make this work, you will
 628 need to create a JavaScript object (the object your consumers actually use)
 629 that inherits from `EventEmitter`, hang your native object off this object,
 630 and populate the native object with an appropriate method that will cause
 631 the JavaScript object to emit events when the native object invokes that
 632 method.  A simple example might look like this:
 633 
 634         var util = require('util');
 635         var binding = require('./native_binding');
 636         var events = require('events');
 637 
 638         function
 639         MyObjectWrapper()
 640         {
 641                 var self = this;
 642 
 643                 events.EventEmitter.call(this);
 644                 this._native = binding._create.apply(this,
 645                     Array.prototype.slice.call(arguments));
 646                 this._native._emit = function () {
 647                         var args = Array.prototype.slice.call(arguments);
 648                         self.emit.apply(self, args);
 649                 };
 650         }
 651         util.inherits(MyObjectWrapper, events.EventEmitter);
 652 
 653 Then, in C code, you must arrange for libuv to call a C function in the
 654 context of the main event loop.  The function `v8plus_method_call()` is safe
 655 to call from any thread: depending on the context in which it is invoked, it
 656 will either make the call directly or queue the call in the main event loop
 657 and block on a reply.  Simply arrange to call back into your JavaScript
 658 object when you wish to post an event:
 659 
 660         nvlist_t *eap;
 661         nvlist_t *erp;
 662         my_object_t *op = ...;
 663         ...
 664         eap = v8plus_obj(
 665             V8PLUS_TYPE_STRING, "0", "my_event",
 666             ...,
 667             V8PLUS_TYPE_NONE);
 668 
 669         if (eap != NULL) {
 670                 erp = v8plus_method_call(op, "_emit", eap);
 671                 nvlist_free(eap);
 672                 nvlist_free(erp);
 673         }
 674 
 675 This example will generate an event named "my_event" and propagate it to
 676 listeners registered with the `MyObjectWrapper` instance.  If additional
 677 arguments are associated with the event, they may be added to `eap` and will
 678 also be passed along to listeners as arguments to their callbacks.
 679 
 680 ### void v8plus_obj_hold(const void *op)
 681 
 682 Places a hold on the V8 representation of the specified C object.  This is
 683 rarely necessary; `v8plus_defer()` performs this action for you, but other
 684 asynchronous mechanisms may require it.  If you are returning from a method
 685 call but have stashed a reference to the object somewhere and are not
 686 calling `v8plus_defer()`, you must call this first.  Holds and releases must
 687 be balanced.  Use of the object within a thread after releasing is a bug.
 688 
 689 ### void v8plus_obj_rele(const void *op)
 690 
 691 Releases a hold placed by `v8plus_obj_hold()`.
 692 
 693 ### void v8plus_jsfunc_hold(v8plus_jsfunc_t f)
 694 
 695 Places a hold on the V8 representation of the specified JavaScript function.
 696 This is required when returning from a C function that has stashed a
 697 reference to the function, typically to use it asynchronously as a callback.
 698 All holds must be balanced with a release.  Because a single hold is placed
 699 on such objects when passed to you in an argument list (and released for you
 700 when you return), it is legal to reference and even to invoke such a
 701 function without first placing an additional hold on it.
 702 
 703 ### void v8plus_jsfunc_rele(v8plus_jsfunc_t f)
 704 
 705 Releases a hold placed by `v8plus_jsfunc_hold()`.
 706 
 707 ### void v8plus_defer(void *op, void *ctx, worker, completion)
 708 
 709 Enqueues work to be performed in the Node.js shared thread pool.  The object
 710 `op` and context `ctx` are passed as arguments to `worker` executing in a
 711 thread from that pool.  The same two arguments, along with the worker's
 712 return value, are passed to `completion` executing in the main event loop
 713 thread.  See example above.
 714 
 715 ### nvlist_t *v8plus_call(v8plus_jsfunc_t f, const nvlist_t *ap)
 716 
 717 Calls the JavaScript function referred to by `f` with encoded arguments
 718 `ap`.  The return value is the encoded return value of the function.  The
 719 argument and return value encoding match the encodings that are used by C
 720 functions that provide methods.
 721 
 722 ### nvlist_t *v8plus_method_call(void *op, const char *name, const nvlist_t *ap)
 723 
 724 Calls the method named by `name` in the native object `op` with encoded
 725 argument list `ap`.  The method must exist and must be a JavaScript
 726 function.  Such functions may be attached by JavaScript code as in the event
 727 emitter example above.  The effects of using this function to call a native
 728 method are undefined.
 729 
 730 As JavaScript functions must be called from the event loop thread,
 731 `v8plus_method_call()` contains logic to determine whether we are in the
 732 correct context or not.  If we are running on some other thread we will
 733 queue the request and sleep, waiting for the event loop thread to make the
 734 call.  In the simple case, where we are already in the correct thread, we
 735 make the call directly.
 736 
 737 ## FAQ
 738 
 739 - Why?
 740 
 741 Because C++ is garbage.  Writing good software is challenging enough without
 742 trying to understand a bunch of implicit side effects or typing templated
 743 identifiers that can't fit in 80 columns without falling afoul of the
 744 language's ambiguous grammar.  Don't get me started.
 745 
 746 - Why not use [FFI](https://github.com/rbranson/node-ffi)?
 747 
 748 FFI is really cool; it offers us the ability to use C libraries without
 749 writing bindings at all.  However, it also exposes a lot of C nastiness to
 750 JavaScript code, essentially placing the interface boundary in consuming
 751 code itself.  This pretty much breaks the JavaScript interface model --
 752 for example, you can't really have a function that inspects the types of its
 753 arguments -- and requires you to write an additional C library anyway if you
 754 want or need to do something natively that's not quite what the C library
 755 already does.  Of course, one could use it to write "bindings" in JavaScript
 756 that actually look like a JavaScript interface, which may end up being the
 757 best answer, especially if those are autogenerated from CTF!  In short, v8+
 758 and FFI are different approaches to the problem.  Use whichever fits your
 759 need, and note that they're not mutually exclusive, either.
 760 
 761 - What systems can I use this on?
 762 
 763 [illumos](http://illumos.org) distributions, or possibly other platforms
 764 with a working libnvpair.  I'm sorry if your system doesn't have it; it's
 765 open source and pretty easy to port.
 766 
 767 There is an OSX port; see [the ZFS port's
 768 implementation](http://code.google.com/p/maczfs/source/browse/#git%2Fusr%2Fsrc%2Flib%2Flibnvpair).
 769 Unfortunately this port lacks the requisite support for floating-point data
 770 (DATA_TYPE_DOUBLE) but you could easily add that from the illumos sources.
 771 
 772 - What about node-waf and node-gyp?
 773 
 774 Fuck python, fuck WAF, and fuck all the hipster douchebags for whom make is
 775 too hard, too old, or "too Unixy".  Make is simple, easy to use, and
 776 extremely reliable.  It was building big, important pieces of software when
 777 your parents were young, and it Just Works.  If you don't like using make
 778 here, you probably don't want to use v8+ either, so just go away.  Write
 779 your CoffeeScript VM in something else, and gyp-scons-waf-rake your way to
 780 an Instagram retirement in Bali with all your hipster douchebag friends.
 781 Just don't bother me about it, because I don't care.
 782 
 783 - Why is Node failing in dlopen()?
 784 
 785 Most likely, your module has a typo or needs to be linked with a library.
 786 Normally, shared objects like Node addons should be linked with -zdefs so that
 787 these problems are found at build time, but Node doesn't deliver a mapfile
 788 specifying its API so you're left with a bunch of undefined symbols you just
 789 have to hope are defined somewhere in your node process's address space.  If
 790 they aren't, you're boned.  LD_DEBUG=all will help you find the missing
 791 symbol(s).
 792 
 793 As of 0.0.2, v8+ builds a mapfile for your node binary at the time you build
 794 your addon.  It does not attempt to restrict the visibility of any symbols,
 795 so you will not be warned if your addon is using private or deprecated
 796 functionality in V8 or Node.js.  Your build will, however, fail if you've
 797 neglected to link in any required libraries, typo'd a symbol name, etc.
 798 
 799 - Why use the old init() instead of NODE_MODULE()?
 800 
 801 Because NODE_MODULE() is a macro that can't be passed another macro as the
 802 name of your addon.  Using it would therefore require the source to v8+ to
 803 be generated at build time to match your module's name, which is
 804 inconvenient.  There may be a way to work around this.
 805 
 806 - Why can't I see my exception's decorative properties in JavaScript?
 807 
 808 Be careful when decorating exceptions.  There are several built-in hidden
 809 properties; if you decorate the exception with a property with the same
 810 name, you will change the hidden property's value but it will still be
 811 hidden.  This almost certainly is not what you want, so you should prefix
 812 the decorative property names with something unique to your module to avoid
 813 stepping on V8's (or JavaScript's) property namespace.
 814 
 815 - What if the factory model doesn't work for me?
 816 
 817 See "License" below.  Note also that one can export plain functions as well.
 818 
 819 - Why do I always die with "invalid property type -3621" (or other garbage)?
 820 
 821 You are passing an object with the wrong C type to `v8plus_obj()`.  Like
 822 all varargs functions, it cannot tell the correct size or type of the
 823 objects you have passed it; they must match the preceding type argument or
 824 it will not work correctly.  In this particular case, you've most likely
 825 done something like:
 826 
 827         int foo = 0xdead;
 828 
 829         v8plus_obj(V8PLUS_TYPE_NUMBER, "foo", foo, V8PLUS_TYPE_NONE);
 830 
 831 An 'int' is 4 bytes in size, and the compiler reserves 4 bytes on the stack
 832 and sticks the value of foo there.  When `v8plus_obj` goes to read it, it
 833 sees that the type is V8PLUS_TYPE_NUMBER, casts the address of the next
 834 argument slot to a `double *`, and dereferences it, then moves the argument
 835 list pointer ahead by the size of a double.  Unfortunately, a double
 836 is usually 8 bytes long, meaning that (a) the value of the property is going
 837 to be comprised of the integer-encoded foo appended to the next data type,
 838 and (b) the next data type is going to be read from either undefined memory
 839 or from part of the address of the name of the next property.  To cure this,
 840 always make sure that you cast your integral arguments properly when using
 841 V8PLUS_TYPE_NUMBER:
 842 
 843         v8plus_obj(V8PLUS_TYPE_NUMBER, "foo", (double)foo, V8PLUS_TYPE_NONE);
 844 
 845 ## License
 846 
 847 MIT.
 848 
 849 ## Bugs
 850 
 851 See <https://github.com/wesolows/v8plus/issues>.
 852 
 853 ## Consumers
 854 
 855 This is an incomplete list of native addons known to be using v8+.  If your
 856 addon uses v8+, please let me know and I will include it here.
 857 
 858 - <https://github.com/wesolows/node-contract>