--- old/./Makefile	2013-10-21 19:08:23.576195909 +0000
+++ new/./Makefile	2013-10-21 19:08:23.592603001 +0000
@@ -179,10 +179,10 @@
 	    gmake DESTDIR=$(PROTO) install)
 	touch $@
 
-0-livesrc-stamp: src/bootparams.c
+0-livesrc-stamp: src/bootparams.c 0-illumos-stamp 0-extra-stamp
 	(cd $(ROOT)/src && \
-	    gmake DESTDIR=$(PROTO) && \
-	    gmake DESTDIR=$(PROTO) install)
+	    gmake NATIVEDIR=$(STRAP_PROTO) DESTDIR=$(PROTO) && \
+	    gmake NATIVEDIR=$(STRAP_PROTO) DESTDIR=$(PROTO) install)
 	touch $@
 
 0-man-stamp:
--- old/src/Makefile	2013-10-21 19:08:23.865465957 +0000
+++ new/src/Makefile	2013-10-21 19:08:23.878710595 +0000
@@ -116,6 +116,15 @@
 $(KSTAT.NODE) :	LIBS +=		-lkstat
 
 #
+# The lockfd Node add-on is based on v8plus, which has its own system of
+# Makefiles.
+#
+LOCKFD_BINDING.NODE =		node-lockfd/lib/lockfd_binding.node
+
+LOCKFD_SRC_DIR =		$(PWD)/node-lockfd/src
+LOCKFD_V8PLUS_DIR =		$(PWD)/node-lockfd/node_modules/v8plus
+
+#
 # The dtrace-provider add-on uses a combination of C, assembly and C++ files in
 # multiple directories.
 #
@@ -314,6 +323,7 @@
 	$(EXPAT.NODE) \
 	$(DTRACE_PROVIDER.NODE) \
 	$(KSTAT.NODE) \
+	$(LOCKFD_BINDING.NODE) \
 	$(MICROTIME.NODE) \
 	$(SYSLOG.NODE) \
 	$(SQLITE3_BINDINGS.NODE) \
@@ -344,6 +354,8 @@
 	mkdir -m 0755 -p $(PREFIX_NODE)/node_modules
 	cp -Pr node_modules/* $(PREFIX_NODE)/node_modules
 	cp $(KSTAT.NODE) $(PREFIX_NODE)/node_modules/
+	cp node-lockfd/lib/index.js $(PREFIX_NODE)/node_modules/lockfd.js
+	cp $(LOCKFD_BINDING.NODE) $(PREFIX_NODE)/node_modules/lockfd_binding.node
 	cp $(MICROTIME.NODE) $(PREFIX_NODE)/node_modules/
 	rm -rf $(DESTDIR)/usr/vm
 	cp -PR vm $(DESTDIR)/usr/
@@ -462,6 +474,7 @@
 	-rm -f $(TARGETS) $(SMARTDC_TARGETS) $(SMARTDC_LIB_TARGETS) *.o \
 	    $(CLEANFILES)
 	-rm -rf node-sqlite3/build
+	cd $(LOCKFD_SRC_DIR) && $(MAKE) clean
 
 include Makefile.targ
 
@@ -496,6 +509,23 @@
 	$(GXX) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@ $< $(LIBS)
 
 #
+# node-lockfd is built using the v8plus-based Makefile contained within the
+# project.  We use LD_OPTIONS, here, to induce the linker to include libc,
+# which gcc as configured in proto.strap does not, but which other C compilers
+# generally do.
+#
+$(LOCKFD_BINDING.NODE): FRC
+	cd $(LOCKFD_SRC_DIR) && \
+	LD_OPTIONS=-lc \
+	$(MAKE) \
+		CC=$(GCC) CXX=$(GXX) \
+		PREFIX_NODE=$(PREFIX_NODE) \
+		NODE_EXEC=$(NODE_EXEC) \
+		V8PLUS=$(LOCKFD_V8PLUS_DIR) \
+		CTFCONVERT=$(CTFCONVERT) \
+		CTFMERGE=$(CTFMERGE)
+
+#
 # The next two are used to build libusdt files into
 # $(DTRACE_PROVIDER_OBJDIR)/libusdt/*.o, instead of building libusdt.a
 #
@@ -553,3 +583,5 @@
 
 $(ZUTIL_BINDINGS.NODE): $(ZUTIL_BINDINGS_OBJS)
 	$(GXX) $(LDFLAGS) -o $@ $(ZUTIL_BINDINGS_OBJS) $(LIBS)
+
+FRC:
--- old/src/Makefile.defs	2013-10-21 19:08:24.133225165 +0000
+++ new/src/Makefile.defs	2013-10-21 19:08:24.146442063 +0000
@@ -23,18 +23,24 @@
 
 BASE =		$(PWD)
 DESTDIR =	$(BASE)/../proto
+NATIVEDIR =	$(BASE)/../proto.strap
+ILLUMOS_SRC =	$(BASE)/../projects/illumos/usr/src
 
 ifeq ($(shell uname -s),Darwin)
 MAKE =		make
 PATH =		$(DESTDIR)/usr/bin:/bin:/usr/bin:/usr/sbin:/sbin:/opt/local/bin
 else
 MAKE =		gmake
-PATH =		$(DESTDIR)/usr/bin:/usr/bin:/usr/sbin:/sbin:/opt/local/bin
+PATH =		$(NATIVEDIR)/usr/bin:/usr/bin:/usr/sbin:/sbin:/opt/local/bin
 endif
 
 PARALLEL =	-j128
-GCC =		$(DESTDIR)/usr/bin/gcc
-GXX =		$(DESTDIR)/usr/bin/g++
+GCC =		$(NATIVEDIR)/usr/bin/gcc
+GXX =		$(NATIVEDIR)/usr/bin/g++
+
+CTFBINDIR =	$(ILLUMOS_SRC)/tools/proto/root_i386-nd/opt/onbld/bin/i386
+CTFMERGE =	$(CTFBINDIR)/ctfmerge
+CTFCONVERT =	$(CTFBINDIR)/ctfconvert
 
 SYSINCDIRS =	/usr/include
 SYSLIBDIRS =	/usr/lib /lib
@@ -44,6 +50,7 @@
 		    -Wl,-zfatal-warnings
 
 PREFIX_NODE =	$(DESTDIR)/usr/node/0.8
+NODE_EXEC =	$(NATIVEDIR)/usr/node/0.8/bin/node
 
 DEBUG_FLAGS =	-g
 WARN_FLAGS =	-Wall -Wextra -Werror
--- old/src/manifest	2013-10-21 19:08:24.415296764 +0000
+++ new/src/manifest	2013-10-21 19:08:24.427991244 +0000
@@ -402,6 +402,8 @@
 f usr/node/0.8/node_modules/dtrace-provider.node 0444 root bin
 f usr/node/0.8/node_modules/getopt.js 0444 root bin
 f usr/node/0.8/node_modules/kstat.node 0444 root bin
+f usr/node/0.8/node_modules/lockfd.js 0444 root bin
+f usr/node/0.8/node_modules/lockfd_binding.node 0444 root bin
 f usr/node/0.8/node_modules/microtime.node 0444 root bin
 f usr/node/0.8/node_modules/onlyif.js 0444 root bin
 f usr/node/0.8/node_modules/sprintf.js 0444 root bin
--- /dev/null	2013-10-21 19:08:24.000000000 +0000
+++ new/src/node-lockfd/.gitignore	2013-10-21 19:08:24.742138744 +0000
@@ -0,0 +1,4 @@
+src/*.o
+src/v8plus_errno.[ch]
+lib/*.node
+src/mapfile_node
--- /dev/null	2013-10-21 19:08:24.000000000 +0000
+++ new/src/node-lockfd/LICENSE	2013-10-21 19:08:24.909761650 +0000
@@ -0,0 +1,18 @@
+Copyright (c) 2013, Joyent, Inc. All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--- /dev/null	2013-10-21 19:08:25.000000000 +0000
+++ new/src/node-lockfd/README.md	2013-10-21 19:08:25.069074095 +0000
@@ -0,0 +1,48 @@
+# node-lockfd
+
+A trivial wrapper around `fcntl(F_SETLK)` (or `F_SETLKW`).  Presently allows
+a synchronous or asynchronous call to get a whole-file, exclusive, advisory
+write lock on a file, or to block until one is possible.
+
+This module has been crafted specifically to work on SmartOS, and may not work
+anywhere else.  Please see [fcntl(2)](http://illumos.org/man/2/fcntl) for more
+details on the locking semantics.  In general, the lock will be released when
+either the file descriptor is closed, or the process exits.  The manual page
+contains information on exceptions to this behaviour.
+
+## Usage
+
+### lockfd(fd, callback)
+
+Will attempt to lock the open file descriptor `fd` as described above.  Once
+the lock is acquired, or an error condition manifests, `callback(err)` will be
+called.
+
+### lockfdSync(fd)
+
+Synchronous version of `lockfd(fd)`.
+
+## Examples
+
+```javascript
+var mod_fs = require('fs');
+var mod_lockfd = require('lockfd');
+
+var fd = mod_fs.openSync('/tmp/.lockfile', 'r+');
+console.error('open fd %d', fd);
+
+console.error('locking file...');
+mod_lockfd.lockfdSync(fd);
+console.log('locked.');
+
+/*
+ * Do work...
+ */
+
+mod_fs.closeSync(fd);
+process.exit(0);
+```
+
+## License
+
+MIT.
--- /dev/null	2013-10-21 19:08:25.000000000 +0000
+++ new/src/node-lockfd/lib/index.js	2013-10-21 19:08:25.209823974 +0000
@@ -0,0 +1,63 @@
+/* vim: set syntax=javascript ts=8 sts=8 sw=8 noet: */
+
+var BINDING = require('./lockfd_binding');
+
+function
+check_arg(pos, name, value, type)
+{
+	if (typeof (value) !== type) {
+		throw (new Error('argument #' + pos + ' (' + name +
+		    ') must be of type ' + type));
+	}
+}
+
+function
+lockfd(fd, callback)
+{
+	check_arg(1, 'fd', fd, 'number');
+	check_arg(2, 'callback', callback, 'function');
+
+	BINDING.lock_fd(fd, "write", false, function (ret, errno, errmsg) {
+		if (ret === -1) {
+			var err = new Error('File Locking Error: ' + errmsg);
+			err.__errno = errno;
+
+			callback(err);
+			return;
+		}
+
+		callback(null);
+	});
+}
+
+function
+lockfdSync(fd)
+{
+	var cb_fired = false;
+	var err;
+
+	check_arg(1, 'fd', fd, 'number');
+
+	BINDING.lock_fd(fd, "write", true, function (ret, errno, errmsg) {
+		cb_fired = true;
+
+		if (ret === -1) {
+			err = new Error('File Locking Error: ' + errmsg);
+			err.__errno = errno;
+			return;
+		}
+	});
+
+	if (!cb_fired) {
+		throw (new Error('lockfdSync: CALLBACK NOT FIRED'));
+	} else if (err) {
+		throw (err);
+	}
+
+	return (null);
+}
+
+module.exports = {
+	lockfd: lockfd,
+	lockfdSync: lockfdSync
+};
--- /dev/null	2013-10-21 19:08:25.000000000 +0000
+++ new/src/node-lockfd/node_modules/v8plus/.npmignore	2013-10-21 19:08:25.355984694 +0000
@@ -0,0 +1,10 @@
+examples/example.node
+examples/example.o
+examples/v8plus_csup.o
+examples/v8plus_errno.c
+examples/v8plus_errno.h
+examples/v8plus_errno.o
+examples/v8plus_objectwrap.o
+examples/v8plus_subr.o
+node_modules/
+mapfile_node
--- /dev/null	2013-10-21 19:08:25.000000000 +0000
+++ new/src/node-lockfd/node_modules/v8plus/Makefile.v8plus.defs	2013-10-21 19:08:25.499846298 +0000
@@ -0,0 +1,78 @@
+#
+# Copyright (c) 2012 Joyent, Inc.  All rights reserved.
+#
+
+#
+# V8PLUS and PREFIX_NODE must be defined in consumer's makefiles.
+# See documentation.
+#
+#PREFIX_NODE :=	$(shell dirname `bash -c 'hash node; hash -t node'`)/..
+#V8PLUS :=	$(shell $(PREFIX_NODE)/bin/node -e 'require("v8plus");')
+
+CC =		gcc
+CXX =		g++
+CTFCONVERT =	/opt/onbld/bin/i386/ctfconvert
+CTFMERGE =	/opt/onbld/bin/i386/ctfmerge
+CTF_LABEL =	v8plus_0.0.1
+
+NODE_EXEC =	$(PREFIX_NODE)/bin/node
+
+MODULE_DIR =	../lib
+
+DEBUG_FLAGS =	-g
+WARN_FLAGS =	-Wall -Wextra -Werror
+PIC_FLAGS =	-fPIC
+OPT_FLAGS =	-O2
+C_STDFLAGS =	-std=c99
+CXX_STDFLAGS =	-std=c++0x
+
+CFLAGS =	$(DEBUG_FLAGS) \
+		$(WARN_FLAGS) \
+		$(PIC_FLAGS) \
+		$(OPT_FLAGS) \
+		$(C_STDFLAGS)
+CXXFLAGS =	$(DEBUG_FLAGS) \
+		$(WARN_FLAGS) \
+		$(PIC_FLAGS) \
+		$(OPT_FLAGS) \
+		$(CXX_STDFLAGS)
+
+STD_DEFS =	-D_GNU_SOURCE
+NODE_DEFS =	-DBUILDING_NODE_EXTENSION
+LF64_DEFS =	-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64
+PIC_DEFS =	-DPIC
+NODE_INCS =	-isystem $(PREFIX_NODE)/include/node -I. -I$(V8PLUS)
+
+CPPFLAGS =	$(STD_DEFS) $(NODE_DEFS) $(LF64_DEFS) $(PIC_DEFS) $(NODE_INCS)
+CXXPPFLAGS =	$(CPPFLAGS)
+
+SHARED_FLAGS =	-shared
+ZTEXT =		-Wl,-ztext
+ZDEFS =		-Wl,-zdefs
+NODE_LIBDIR =	-L$(PREFIX_NODE)/lib
+MAPFILES =	$(MAPFILE)
+
+LDFLAGS =	$(SHARED_FLAGS) $(ZTEXT) $(ZDEFS) $(NODE_LIBDIR)
+LDFLAGS +=	$(MAPFILES:%=-Wl,-M,%)
+LIBS =		-lnvpair
+
+OBJS.c =	$(SRCS:.c=.o)
+OBJS =		$(OBJS.c:.cc=.o)
+
+OBJS +=		\
+		v8plus_csup.o \
+		v8plus_errno.o \
+		v8plus_objectwrap.o \
+		v8plus_subr.o
+
+GENERRNO_JS =	$(V8PLUS)/generrno.js
+GENERRNO =	NODE_PATH=$(V8PLUS)/node_modules \
+		    $(NODE_EXEC) $(GENERRNO_JS)
+
+ERRNO_H =	v8plus_errno.h
+ERRNO_C =	v8plus_errno.c
+
+MAPFILE =	mapfile_node
+
+CTFCONVERT.o =	$(CTFCONVERT) -l $(CTF_LABEL) $@
+CTFMERGE.node =	$(CTFMERGE) -l $(CTF_LABEL) -o $@ $(OBJS)
--- /dev/null	2013-10-21 19:08:25.000000000 +0000
+++ new/src/node-lockfd/node_modules/v8plus/Makefile.v8plus.targ	2013-10-21 19:08:25.648328305 +0000
@@ -0,0 +1,45 @@
+#
+# Copyright (c) 2012 Joyent, Inc.  All rights reserved.
+#
+
+all: $(MODULE_DIR)/$(MODULE).node
+
+$(ERRNO_C): $(GENERRNO_JS) $(ERRNO_JSON)
+	$(GENERRNO) -c -o $@ $(ERRNO_JSON)
+
+$(ERRNO_H): $(GENERRNO_JS) $(ERRNO_JSON)
+	$(GENERRNO) -h -o $@ $(ERRNO_JSON)
+
+$(OBJS): $(ERRNO_H)
+
+$(MODULE_DIR)/$(MODULE).node: $(OBJS) $(MAPFILE)
+	$(CXX) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
+	$(CTFMERGE.node)
+
+%.o: %.c
+	$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $<
+	$(CTFCONVERT) -l $(CTF_LABEL) $@
+
+%.o: %.cc
+	$(CXX) $(CXXPPFLAGS) $(CXXFLAGS) -c -o $@ $<
+
+%.o: $(V8PLUS)/%.c
+	$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $<
+	$(CTFCONVERT.o)
+
+%.o: $(V8PLUS)/%.cc
+	$(CXX) $(CXXPPFLAGS) $(CXXFLAGS) -c -o $@ $<
+
+$(MAPFILE): $(PREFIX_NODE)/bin/node
+	/usr/bin/nm -ghnp $< | \
+	    (printf "\$$mapfile_version 2\n\nSYMBOL_SCOPE {\n\tglobal:\n"; \
+	    awk '$$2 != "U" { print "\t\t" $$3 "\t{ FLAGS = EXTERN };" }'; \
+	    printf "\t\tinit;\n\tlocal:\n\t\t*;\n};") > $@
+
+.PHONY: clean
+
+clean:
+	-rm -f $(OBJS) $(ERRNO_C) $(ERRNO_H)
+
+clobber: clean
+	-rm -f $(MODULE_DIR)/$(MODULE).node $(MAPFILE)
--- /dev/null	2013-10-21 19:08:25.000000000 +0000
+++ new/src/node-lockfd/node_modules/v8plus/README.md	2013-10-21 19:08:25.780998778 +0000
@@ -0,0 +1,871 @@
+# v8+: Node.js addon C++ to C boundary layer
+
+This layer offers a way to write at least simple Node.js addons in C without
+all the horrible C++ goop you'd otherwise be expected to use.  That goop
+still exists, but you don't have to write it.  More importantly, you can
+write your module in a sane programming environment, avoiding the confusing
+and error-prone C++ semantics.
+
+## Usage
+
+Unlike most Node.js modules, v8+ does nothing by itself.  It is intended to
+be used as a build-time dependency of your native addon, providing you with
+an alternate programming environment.
+
+For full docs, read the source code.
+
+## Node.js Support
+
+v8+ works with, and has been tested to some extent with, Node.js 0.6.18 and
+0.8.1.  It most likely works with other micro versions in the 0.6 and 0.8
+series as well.  Note that this does not mean you can necessarily expect an
+addon built against a particular minor release of Node.js to work with any
+other minor release of Node.js.
+
+## Building and Installing
+
+The v8+ source code is compiled into your module directly along with your
+code.  There is no separate v8+ library or node module, so the v8+ source,
+tools, and makefiles are required to be present at the time your module is
+built.  They are not required at runtime.
+
+Normally, your addon module will depend on the v8plus package and install it
+using npm.  The v8+ makefiles are set up to accommodate the installation of
+v8+ anywhere `node(1)` would be able to find it using `require()` if it were
+a normal JavaScript module, so simply including it as a dependency in your
+`package.json` will work correctly.  In addition, you will need to create a
+(normally trivial) makefile for your module that includes the makefiles
+distributed as part of v8+.  Once you have done so, it is sufficient to run
+`gmake` to generate the native loadable module used by Node.js.
+
+The overall outline for creating a v8+ module looks something like this:
+
+1. Write the C code that does whatever your module does.  Be sure to
+\#include "v8plus_glue.h".  Do not include any other v8+ headers.
+
+2. Create an appropriate `package.json` file.  See below for details.
+
+3. Create a skeleton makefile.  See below for details.
+
+4. Create a JSON file defining the error codes your module will use.  See
+Errors below.
+
+You should not (and need not) modify either of the delivered makefiles;
+override the definitions in Makefile.v8plus.defs in your makefile as
+appropriate.
+
+### Packaging Considerations
+
+There are two essential properties your `package.json` must contain in order
+to use v8+ with npm:
+
+1. A dependency on `v8plus`.
+
+2. An appropriate script entry for building your module.  It is strongly
+   recommended that you use something like the following:
+
+        "postinstall": "gmake $(eval echo ${MAKE_OVERRIDES})"
+
+This will allow someone building your module to set make variables by adding
+them to the `MAKE_OVERRIDES` environment variable; e.g.,
+
+        $ MAKE_OVERRIDES="CTFCONVERT=/bin/true CTFMERGE=/bin/true" npm install
+
+### Tying into the Makefiles
+
+The makefiles shipped with v8+ do the great majority of the heavy lifting
+for you.  A minimally functional makefile for your addon must contain four
+things:
+
+1. Variable definitions for `V8PLUS` and `PREFIX_NODE`.  Alternately, you
+   may choose to provide these on the command line or via the environment.
+   It is recommended that these assignments be made exactly as follows,
+   which will cause the addon to be built against the `node` that is found
+   first in your path:
+
+        PREFIX_NODE := $(shell dirname `bash -c 'hash node; hash -t node'`)/..
+        V8PLUS :=      $(shell $(PREFIX_NODE)/bin/node -e 'require("v8plus");')
+
+   Note that the mechanism for finding `node` will not work correctly if
+   yours is a symlink.  This invocation of node(1) uses a v8+ mechanism to
+   locate v8+ sources anywhere that node(1) can find them and should not be
+   modified unless you want to test an alternate v8+.
+
+2. The exact line:
+
+        include $(V8PLUS)/Makefile.v8plus.defs
+
+3. Variable assignments specific to your module.  In particular, you must
+   define `SRCS`, `MODULE`, and `ERRNO_JSON`.  Additional customisation is
+   optional.
+
+4. The exact line:
+
+        include $(V8PLUS)/Makefile.v8plus.targ
+
+Additional arbitrary customisation is possible using standard makefile
+syntax; most things that are useful to change already have variables defined
+in `Makefile.v8plus.defs` whose values you may append to or override.  For
+example, you may cause additional system libraries to be linked in by
+appending `-lname` to the `LIBS` variable.  By default, the makefiles assume
+that your sources are located in the `src` subdirectory of your module, and
+that you want the sole output of the build process to be called
+`$(MODULE).node` and located in the `lib` subdirectory.  This can be changed
+by overriding the `MODULE_DIR` variable.
+
+A simple example makefile may be found in the `examples/` subdirectory, and
+additional examples may be found in existing consumers; see Consumers below.
+The GNU people also provide a good manual for make if you get really stuck;
+see <http://www.gnu.org/software/make/manual/make.html>.  In general,
+writing the necessary makefile fragment is expected to be as easy as or
+easier than the equivalent task using `node-waf` or `node-gyp`, so if you're
+finding it unexpectedly difficult or complicated there's probably an easier
+way.
+
+The makefiles follow GNU make syntax; other makes may not work but patches
+that correct this are generally welcome (in particular, Sun make and GNU
+make have different and incompatible ways to set a variable from the output
+of a shell command, and there is no way I know to accommodate both).
+
+### Binary Interface
+
+By default, the resulting object is linked with the `-zdefs` option, which
+will cause the build to fail if any unresolved symbols remain.  In order to
+accommodate this, a mapfile specifying the available global symbols in your
+`node` binary is automatically generated as part of the build process.  This
+makes it much easier to debug missing libraries; otherwise, a module with
+unresolved symbols will fail to load at runtime with no useful explanation.
+Mapfile generation probably works only on illumos-derived systems.  Patches
+that add support for other linkers are welcome.
+
+Your module will have all symbols (other than `init`, which is used directly
+by Node.js) reduced to local visibility, which is strongly recommended.  If
+for some reason you want your module's symbols to be visible to Node.js or
+to other modules, you will have to modify the script that generates the
+mapfile.  See the `$(MAPFILE)` target in `Makefile.v8plus.targ`.
+
+## API
+
+Your module is an object factory that instantiates and returns native
+objects, to which a fixed set of methods is attached as properties.  The
+constructor, destructor, and methods all correspond 1-1 with C functions.
+In addition, you may create additional class methods associated with the
+native module itself, each of which will also have a 1-1 relationship to a
+set of C functions.
+
+This functionality is generally sufficient to interface with the system in
+useful ways, but it is by no means exhaustive.  Architectural limitations
+are noted throughout the documentation.
+
+Subsequent sections describe the API in greater detail, along with most of
+the C functions that v8+ provides.  Some utility functions may not be listed
+here; see `v8plus_glue.h` for additional commentary and functions that are
+available to you.
+
+### Constructors, Methods, and Functions
+
+The interface between your module and v8+ consists of a handful of objects
+with fixed types and names.  These are:
+
+	const v8plus_c_ctor_f v8plus_ctor = my_ctor;
+	const v8plus_c_dtor_f v8plus_dtor = my_dtor;
+	const char *v8plus_js_factory_name = "_new";
+	const char *v8plus_js_class_name = "MyObjectBinding";
+	const v8plus_method_descr_t v8plus_methods[] = {
+	        {
+	                md_name: "_my_method",
+	                md_c_func: my_method
+	        },
+		...
+	};
+	const uint_t v8plus_method_count =
+	    sizeof (v8plus_methods) / sizeof (v8plus_methods[0]);
+
+	const v8plus_static_descr_t v8plus_static_methods[] = {
+	        {
+	                sd_name: "_my_function",
+	                sd_c_func: my_function
+	        },
+		...
+	};
+	const uint_t v8plus_static_method_count =
+	    sizeof (v8plus_static_methods) / sizeof (v8plus_static_methods[0]);
+
+All of these must be present even if they have zero length or are NULL.  The
+prototypes and semantics of each function type are as follows:
+
+### nvlist_t *v8plus_c_ctor_f(const nvlist_t *ap, void **opp)
+
+The constructor is responsible for creating the C object corresponding to
+the native JavaScript object being created.  It is not a true constructor in
+that you are actually an object factory; the C++ function associated with
+the JavaScript constructor is called for you.  Your encoded arguments are in
+`ap`.  Allocate and populate a C object, stuff it into `*opp`, and return
+`v8plus_void()`.  If you need to throw an exception you can do so by
+returning `v8plus_error()` or one of its wrappers, or by setting
+`_v8plus_errno` using one of those functions and then returning an nvlist
+with an `err` member representing a decorated exception.
+
+### void v8plus_c_dtor_f(void *op)
+
+Free the C object `op` and anything else associated with it.  Your object is
+going away.  This function may be empty if the constructor did not allocate
+any memory (i.e., `op` is not a pointer to dynamically allocated memory).
+
+### nvlist_t *v8plus_c_method_f(void *op, const nvlist_t *ap)
+
+When the JavaScript method is called in the context of your object, the
+corresponding C function is invoked.  `op` is the C object associated with
+the JavaScript object, and `ap` is the encoded list of arguments to the
+function.  Return an encoded object with a `res` member, or use one of the
+error/exception patterns.
+
+### nvlist_t *v8plus_c_static_method_f(const nvlist_t *ap)
+
+In addition to methods on the native objects returned by your constructor,
+you can also provide a set of functions on the native binding object itself.
+This may be useful for providing bindings to libraries for which no object
+representation makes sense, or that have functions that operate outside the
+context of any particular object.  Your arguments are once again encoded in
+`ap`, and your return values are an object containing `res` or an error.
+
+### Argument Handling
+
+When JavaScript objects cross the boundary from C++ to C, they are converted
+from v8 C++ objects into C nvlists.  This means that they are effectively
+passed by value, unlike in JavaScript or in native addons written in C++.
+The arguments to the JavaScript function are treated as an array and
+marshalled into a single nvlist whose properties are named "0", "1", and so
+on.  Each such property is encoded as follows:
+
+- numbers and Number objects (regardless of size): double
+- strings and String objects: UTF-8 encoded C string
+- booleans and Boolean objects: boolean_value
+- undefined: boolean
+- null: byte, value 0
+- Objects, including Arrays: nvlist with own properties as members and the
+member ".__v8plus_type" set to the object's JavaScript type name.  Note
+that the member name itself begins with a . to reduce the likelihood of a
+collision with an actual JavaScript member name.
+- JavaScript Functions are passed in a format suitable for use with
+  `nvlist_lookup_jsfunc()` and `v8plus_args()` with the V8PLUS_TYPE_JSFUNC
+  token.  This type is restricted; see below.
+
+Because JavaScript arrays may be sparse, we cannot use the libnvpair array
+types.  Consider them reserved for internal use.  JavaScript Arrays are
+represented as they really are in JavaScript: objects with properties whose
+names happen to be integers.
+
+Other data types cannot be represented and will result in a TypeError
+being thrown.  If your object has methods that need other argument types,
+you cannot use v8+.
+
+Side effects within the VM, including modification of the arguments, are
+not supported.  If you need them, you cannot use v8+.
+
+While the standard libnvpair functions may be used to inspect the arguments
+to a method or function, v8+ also provides the `v8plus_args()` and
+`v8plus_typeof()` convenience functions, which simplify checking the types
+and obtaining the values of arguments.
+
+### int v8plus_args(const nvlist_t *lp, uint_t flags, v8plus_type_t t, ...)
+
+This function checks `lp` for the exact sequence of arguments specified by
+the list of types provided in the parameter list.  If `V8PLUS_ARG_F_NOEXTRA`
+is set in `flags`, the list of arguments must match exactly, with no
+additional arguments.  The parameter list must be terminated by
+`V8PLUS_TYPE_NONE`.
+
+Following `flags` is a list of argument data types and, for most data types,
+pointers to locations at which the native C value of that argument should be
+stored.  The following JavaScript argument data types are supported; for
+each, the parameter immediately following the data type parameter must be of
+the indicated C type.  This parameter may be `NULL`, in which case the value
+will not be stored anywhere.
+
+- V8PLUS_TYPE_NONE: used to terminate the parameter list only
+- V8PLUS_TYPE_STRING: char **
+- V8PLUS_TYPE_NUMBER: double *
+- V8PLUS_TYPE_BOOLEAN: boolean_t *
+- V8PLUS_TYPE_JSFUNC: v8plus_jsfunc_t *
+- V8PLUS_TYPE_OBJECT: nvlist_t **
+- V8PLUS_TYPE_NULL: no parameter
+- V8PLUS_TYPE_UNDEFINED: no parameter
+- V8PLUS_TYPE_INVALID: data_type_t (see below)
+- V8PLUS_TYPE_ANY: nvpair_t **
+- V8PLUS_TYPE_STRNUMBER64: uint64_t *
+- V8PLUS_TYPE_INL_OBJECT: illegal
+
+In most cases, the behaviour is straightforward: the value pointer parameter
+provides a location into which the C value of the specified argument should
+be stored.  If the entire argument list matches the template, each
+argument's C value is stored in its respective location.  If not, no values
+are stored, in the return value locations, `_v8plus_errno` is set
+appropriately, and -1 is returned.
+
+Three data types warrant further explanation: an argument of type
+`V8PLUS_TYPE_INVALID` is any argument that may or may not match one of the
+acceptable types.  Its nvpair data type tag is stored and the argument
+treated as matching.  The value is ignored.  `V8PLUS_TYPE_STRNUMBER64` is
+used with strings that should be interpreted as 64-bit unsigned integers.
+If the argument is not a string, or is not parseable as a 64-bit unsigned
+integer, the argument will be treated as a mismatch.  Finally,
+`V8PLUS_TYPE_INL_OBJECT` is not supported with `v8plus_args()`; JavaScript
+objects in the argument list must be individually inspected as nvlists.
+
+A simple example:
+
+	double_t d;
+	boolean_t b;
+	char *s;
+	v8plus_jsfunc_t f;
+
+	/*
+	 * This function requires exactly four arguments: a number, a
+	 * boolean, a string, and a callback function.  It is not acceptable
+	 * to pass superfluous arguments to it.
+	 */
+	if (v8plus_args(ap, V8PLUS_ARG_F_NOEXTRA,
+	    V8PLUS_TYPE_NUMBER, &d,
+	    V8PLUS_TYPE_BOOLEAN, &b,
+	    V8PLUS_TYPE_STRING, &s,
+	    V8PLUS_TYPE_JSFUNC, &f,
+	    V8PLUS_TYPE_NONE) != 0)
+		return (NULL);
+
+### v8plus_type_t v8plus_typeof(const nvpair_t *pp)
+
+This function simply returns the v8+ data type corresponding to the
+name/value pair `pp`.  If the value's type does not match the v8+ encoding
+rules, `V8PLUS_TYPE_INVALID` is returned.  This function cannot fail and
+does not modify `_v8plus_errno`.
+
+### Returning Values
+
+Similarly, when returning data across the boundary from C to C++, a
+pointer to an nvlist must be returned.  This object will be decoded in
+the same manner as described above and returned to the JavaScript caller
+of your method.  Note that booleans, strings, and numbers will be encoded
+as their primitive types, not objects.  If you need to return something
+containing these object types, you cannot use v8+.  Other data types
+cannot be represented.  If you need to return them, you cannot use v8+.
+
+The nvlist being returned must have one of two members: "res", an nvpair
+containing the result of the call to be returned, or "err", an nvlist
+containing members to be added to an exception.  You may return a value of
+any decodable type, and likewise may decorate an exception with properties
+of any decodable type.
+
+For convenience, you may return v8plus_void() instead of an nvlist,
+which indicates successful execution of a function that returns nothing.
+
+In addition, the `v8plus_obj()` routine is available for instantiating
+JavaScript objects to return.
+
+### nvlist_t *v8plus_void(void)
+
+This function clears `_v8plus_errno` and returns NULL.  This is used to
+indicate to internal v8+ code that the method or function should not return
+a value.
+
+### nvlist_t *v8plus_obj(v8plus_type_t t, ...)
+
+This function creates and populates an nvlist conforming to the encoding
+rules of v8+ for returning a value or creating an exception.  It can be used
+to create anything from a single encoded value to arbitrarily nested
+objects.  It is essentially the inverse of `v8plus_args()` above, with a few
+differences:
+
+- It cannot be used to encode invalid or illegal data types.
+- It accepts native C values, not pointers to them.
+- Each value must be named.
+- It can be used to encode nested objects inline using
+  `V8PLUS_TYPE_INL_OBJECT`, followed by type, name, value triples,
+  terminated with `V8PLUS_TYPE_NONE`.
+
+This function can fail due to out-of-memory conditions, invalid or
+unsupported data types, or, most commonly, programmer error in casting the
+arguments to the correct type.  *It is extremely important that data values,
+particularly integers, be cast to the appropriate type (double) when passed
+into this function!*
+
+Following is a list of types and the C data types corresponding to their
+values:
+
+- V8PLUS_TYPE_NONE: used to terminate the parameter list only
+- V8PLUS_TYPE_STRING: char *
+- V8PLUS_TYPE_NUMBER: double
+- V8PLUS_TYPE_BOOLEAN: boolean_t
+- V8PLUS_TYPE_JSFUNC: v8plus_jsfunc_t
+- V8PLUS_TYPE_OBJECT: nvlist_t *
+- V8PLUS_TYPE_NULL: no parameter
+- V8PLUS_TYPE_UNDEFINED: no parameter
+- V8PLUS_TYPE_ANY: nvpair_t *
+- V8PLUS_TYPE_STRNUMBER64: uint64_t
+- V8PLUS_TYPE_INL_OBJECT: NONE-terminated type/value list
+
+A simple example, in which we return a JavaScript object with two members,
+one number and one embedded object with a 64-bit integer property.  Note
+that if this function fails, we will return `NULL` with `_v8plus_errno` set
+appropriately, so v8+ will generate and throw an appropriate exception.
+
+	int x;
+	const char *s;
+
+	...
+	return (v8plus_obj(
+	    V8PLUS_TYPE_INL_OBJECT, "res",
+		V8PLUS_TYPE_NUMBER, "value", (double)x,
+		V8PLUS_TYPE_INL_OBJECT, "detail",
+		    V8PLUS_TYPE_STRNUMBER64, "value64", s,
+		    V8PLUS_TYPE_NONE,
+		V8PLUS_TYPE_NONE,
+	    V8PLUS_TYPE_NONE));
+
+The JSON representation of this object would be:
+
+	{
+		"res": {
+			"value": <x>,
+			"detail": {
+				"value64": "<s>"
+			}
+		}
+	}
+
+### v8plus_obj_setprops(nvlist_t *lp, v8plus_type_t t, ...)
+
+You can also add or replace the values of properties in an existing nvlist,
+whether created using `nvlist_alloc()` directly or via `v8plus_obj()`.  The
+effect is very similar to `nvlist_merge()`, where the second list is created
+on the fly from your argument list.  The interpretation of the argument list
+is the same as for `v8plus_obj()`, and the two functions are implemented
+using the same logic.
+
+### Exceptions
+
+If you are unable to create an nvlist to hold exception data, or you want a
+generic exception to be thrown, return the value returned by v8plus_error().
+In this case, the error code will be translated to an exception type and the
+message string will be used as the message member of the exception.  Other
+members will not be present in the exception unless you also return an
+nvlist containing an 'err' member (or, from a constructor, any nvlist) Only
+basic v8-provided exception types can be thrown; if your addon needs to
+throw some other kind of exception, you will need to either use v8 directly
+or catch and re-throw from a JavaScript wrapper.
+
+## Errors
+
+The v8plus_errno_t enumerated type and a family of utility functions are
+automatically generated by generrno.js from a simple JSON file.  The schema
+of this file is as follows:
+
+	{
+		"error_base": <string>,
+		"errors": [
+		{
+			"code": <string>,
+			"msg": <string>,
+			"exception": <string>
+		},
+		...  ]
+	}
+
+For each entry in the errors array, an identifier V8PLUSERR_code will be
+added to v8plus_errno_t.  By convention, code should be all upper case.  The
+default error message (present in JavaScript exceptions if a more specific
+error message is not provided to v8plus_error()) is given by the msg
+property.  The exception property must be one of "Error", "TypeError",
+"ReferenceError", "RangeError", or "SyntaxError"; i.e., the standard
+exception types available in v8.  This is the type of exception that will be
+generated and thrown when a C function returns NULL with this error code
+set.  In addition, the built-in error codes V8PLUSERR_NOMEM,
+V8PLUSERR_YOUSUCK, and V8PLUSERR_UNKNOWN are available for your use,
+indicating an out of memory condition, programmer error (e.g., failure of
+something you would assert in JavaScript), and an error code that cannot be
+translated, respectively.
+
+Set the make variable ERRNO_JSON to the name of this file.
+
+To set the value of `_v8plus_errno`, use one of the following functions.  It
+is a bug to manipulate this variable directly.
+
+### nvlist_t *v8plus_verror(v8plus_errno_t e, const char *fmt, va_list)
+
+This is the varargs analogue to `v8plus_error()` and has identical
+semantics.  Use this if you want to wrap manipulation of the v8+ error state
+within your own varargs functions.
+
+### nvlist_t *v8plus_error(v8plus_errno_t e, const char *fmt, ...)
+
+This function sets the value of `_v8plus_errno` to `e` and sets the
+associated error message string to the formatted string `fmt` using the
+argument list that follows.  The format string and arguments are interpreted
+as by `vsnprintf(3c)`.  NULL is returned, suitable for returning directly
+from a C function that provides a method if no exception decoration is
+required.
+
+If `fmt` is NULL, a generic default message is used; for consumer-defined
+error codes, that message is the one provided in `errno.json`.
+
+### nvlist_t *v8plus_nverr(int errno, const char *propname)
+
+This function sets the value of `_v8plus_errno` to a value mapped from the
+system error code `errno` and sets the error message to a non-localised
+explanation of the problem.  The string `propname`, if non-NULL, is
+indicated in the message as the name of the nvlist property being
+manipulated when the error occurred.  NULL is returned.
+
+### nvlist_t *v8plus_syserr(int errno, const char *fmt, ...)
+
+Analogous to `v8plus_error()`, this function instead sets the error code to
+a mapped value derived from the system error code `errno`.  Not all error
+codes can be mapped; those that are not known are mapped onto
+`V8PLUSERR_UNKNOWN`.  This function's semantics are otherwise identical to
+those of `v8plus_error()`.
+
+### void v8plus_panic(const char *fmt, ...) __NORETURN
+
+This function indicates a fatal runtime error.  The format string `fmt` and
+subsequent arguments are interpreted as by `vsnprintf(3c)` and written to
+standard error, which is then flushed.  `abort(3c)` or similar is then
+invoked to terminate the Node.js process in which the addon is running.  Use
+of this function should be limited to those circumstances in which an
+internal inconsistency has been detected that renders further progress
+hazardous to user data or impossible.
+
+### Asynchrony
+
+There are two main types of asynchrony supported by v8+.  The first is the
+deferred work model (using `uv_queue_work()` or the deprecated
+`eio_custom()` mechanisms) frequently written about and demonstrated by
+various practitioners around the world.  In this model, your method or
+function takes a callback argument and returns immediately after enqueuing a
+task to run on one of the threads in the Node.js worker thread pool.  That
+task consists of a C function to be run on the worker thread, which may not
+use any V8 (or v8+) state, and a function to be run in the main event loop
+thread when that task has completed.  The latter function is normally
+expected to invoke the caller's original callback.  In v8+, this takes the
+following form:
+
+	void *
+	async_worker(void *cop, void *ctxp)
+	{
+		my_object_t *op = cop;
+		my_context_t *cp = ctxp;
+		my_result_t *rp = ...;
+
+		/*
+		 * In thread pool context -- do not call any of the
+		 * following functions:
+		 * v8plus_obj_hold()
+		 * v8plus_obj_rele_direct()
+		 * v8plus_jsfunc_hold()
+		 * v8plus_jsfunc_rele_direct()
+		 * v8plus_call_direct()
+		 * v8plus_method_call_direct()
+		 * v8plus_defer()
+		 *
+		 * If you touch anything inside op, you may need locking to
+		 * protect against functions called in the main thread.
+		 */
+		...
+
+		return (rp);
+	}
+
+	void
+	async_completion(void *cop, void *ctxp, void *resp)
+	{
+		my_object_t *op = cop;
+		my_context_t *cp = ctxp;
+		my_result_t *rp = resp;
+		nvlist_t *cbap;
+		nvlist_t *cbrp;
+
+		...
+		cbap = v8plus_obj(
+		    V8PLUS_TYPE_WHATEVER, "0", rp->mr_value,
+		    V8PLUS_TYPE_NONE);
+
+		if (cbap != NULL) {
+			cbrp = v8plus_call(cp->mc_callback, cbap);
+			nvlist_free(cbap);
+			nvlist_free(cbrp);
+		}
+
+		v8plus_jsfunc_rele(cp->mc_callback);
+		free(cp);
+		free(rp);
+	}
+
+	nvlist_t *
+	async(void *cop, const nvlist_t *ap)
+	{
+		my_object_t *op = cop;
+		v8plus_jsfunc_t cb;
+		my_context_t *cp = malloc(sizeof (my_context_t));
+		...
+		if (v8plus_args(ap, 0, V8PLUS_TYPE_JSFUNC, &cb,
+		    V8PLUS_TYPE_NONE) != 0) {
+			free(cp);
+			return (NULL);
+		}
+
+		v8plus_jsfunc_hold(cb);
+		cp->mc_callback = cb;
+		v8plus_defer(op, cp, async_worker, async_completion);
+
+		return (v8plus_void());
+	}
+
+This mechanism uses `uv_queue_work()` and as such will tie up one of the
+worker threads in the pool for as long as `async_worker` is running.
+
+The other asynchronous mechanism is the Node.js `EventEmitter` model.  This
+model requires some assistance from JavaScript code, because v8+ native
+objects do not inherit from `EventEmitter`.  To make this work, you will
+need to create a JavaScript object (the object your consumers actually use)
+that inherits from `EventEmitter`, hang your native object off this object,
+and populate the native object with an appropriate method that will cause
+the JavaScript object to emit events when the native object invokes that
+method.  A simple example might look like this:
+
+	var util = require('util');
+	var binding = require('./native_binding');
+	var events = require('events');
+
+	function
+	MyObjectWrapper()
+	{
+		var self = this;
+
+		events.EventEmitter.call(this);
+		this._native = binding._create.apply(this,
+		    Array.prototype.slice.call(arguments));
+		this._native._emit = function () {
+			var args = Array.prototype.slice.call(arguments);
+			self.emit.apply(self, args);
+		};
+	}
+	util.inherits(MyObjectWrapper, events.EventEmitter);
+
+Then, in C code, you must arrange for libuv to call a C function in the
+context of the main event loop.  The function `v8plus_method_call()` is safe
+to call from any thread: depending on the context in which it is invoked, it
+will either make the call directly or queue the call in the main event loop
+and block on a reply.  Simply arrange to call back into your JavaScript
+object when you wish to post an event:
+
+	nvlist_t *eap;
+	nvlist_t *erp;
+	my_object_t *op = ...;
+	...
+	eap = v8plus_obj(
+	    V8PLUS_TYPE_STRING, "0", "my_event",
+	    ...,
+	    V8PLUS_TYPE_NONE);
+
+	if (eap != NULL) {
+		erp = v8plus_method_call(op, "_emit", eap);
+		nvlist_free(eap);
+		nvlist_free(erp);
+	}
+
+This example will generate an event named "my_event" and propagate it to
+listeners registered with the `MyObjectWrapper` instance.  If additional
+arguments are associated with the event, they may be added to `eap` and will
+also be passed along to listeners as arguments to their callbacks.
+
+### void v8plus_obj_hold(const void *op)
+
+Places a hold on the V8 representation of the specified C object.  This is
+rarely necessary; `v8plus_defer()` performs this action for you, but other
+asynchronous mechanisms may require it.  If you are returning from a method
+call but have stashed a reference to the object somewhere and are not
+calling `v8plus_defer()`, you must call this first.  Holds and releases must
+be balanced.  Use of the object within a thread after releasing is a bug.
+
+### void v8plus_obj_rele(const void *op)
+
+Releases a hold placed by `v8plus_obj_hold()`.  This function may be called
+safely from any thread; releases from threads other than the main event loop
+are non-blocking and will occur some time in the future.
+
+### void v8plus_jsfunc_hold(v8plus_jsfunc_t f)
+
+Places a hold on the V8 representation of the specified JavaScript function.
+This is required when returning from a C function that has stashed a
+reference to the function, typically to use it asynchronously as a callback.
+All holds must be balanced with a release.  Because a single hold is placed
+on such objects when passed to you in an argument list (and released for you
+when you return), it is legal to reference and even to invoke such a
+function without first placing an additional hold on it.
+
+### void v8plus_jsfunc_rele(v8plus_jsfunc_t f)
+
+Releases a hold placed by `v8plus_jsfunc_hold()`.  This function may be called
+safely from any thread; releases from threads other than the main event loop
+thread are non-blocking and will occur some time in the future.
+
+### void v8plus_defer(void *op, void *ctx, worker, completion)
+
+Enqueues work to be performed in the Node.js shared thread pool.  The object
+`op` and context `ctx` are passed as arguments to `worker` executing in a
+thread from that pool.  The same two arguments, along with the worker's
+return value, are passed to `completion` executing in the main event loop
+thread.  See example above.
+
+### nvlist_t *v8plus_call(v8plus_jsfunc_t f, const nvlist_t *ap)
+
+Calls the JavaScript function referred to by `f` with encoded arguments
+`ap`.  The return value is the encoded return value of the function.  The
+argument and return value encoding match the encodings that are used by C
+functions that provide methods.
+
+As JavaScript functions must be called from the event loop thread,
+`v8plus_call()` contains logic to determine whether we are in the
+correct context or not.  If we are running on some other thread we will
+queue the request and sleep, waiting for the event loop thread to make the
+call.  In the simple case, where we are already in the correct thread, we
+make the call directly.
+
+Note that when passing JavaScript functions around as callbacks, you must use
+first use `v8plus_jsfunc_hold()` from within the main event loop thread.  Once
+finished with the function, you may pass it to `v8plus_jsfunc_rele()` from any
+thread to clean up.
+
+### nvlist_t *v8plus_method_call(void *op, const char *name, const nvlist_t *ap)
+
+Calls the method named by `name` in the native object `op` with encoded
+argument list `ap`.  The method must exist and must be a JavaScript
+function.  Such functions may be attached by JavaScript code as in the event
+emitter example above.  The effects of using this function to call a native
+method are undefined.
+
+When called from threads other than the main event loop thread,
+`v8plus_method_call()` uses the same queue-and-block logic as described above
+in `v8plus_call()`.
+
+## FAQ
+
+- Why?
+
+Because C++ is garbage.  Writing good software is challenging enough without
+trying to understand a bunch of implicit side effects or typing templated
+identifiers that can't fit in 80 columns without falling afoul of the
+language's ambiguous grammar.  Don't get me started.
+
+- Why not use [FFI](https://github.com/rbranson/node-ffi)?
+
+FFI is really cool; it offers us the ability to use C libraries without
+writing bindings at all.  However, it also exposes a lot of C nastiness to
+JavaScript code, essentially placing the interface boundary in consuming
+code itself.  This pretty much breaks the JavaScript interface model --
+for example, you can't really have a function that inspects the types of its
+arguments -- and requires you to write an additional C library anyway if you
+want or need to do something natively that's not quite what the C library
+already does.  Of course, one could use it to write "bindings" in JavaScript
+that actually look like a JavaScript interface, which may end up being the
+best answer, especially if those are autogenerated from CTF!  In short, v8+
+and FFI are different approaches to the problem.  Use whichever fits your
+need, and note that they're not mutually exclusive, either.
+
+- What systems can I use this on?
+
+[illumos](http://illumos.org) distributions, or possibly other platforms
+with a working libnvpair.  I'm sorry if your system doesn't have it; it's
+open source and pretty easy to port.
+
+There is an OSX port; see [the ZFS port's
+implementation](http://code.google.com/p/maczfs/source/browse/#git%2Fusr%2Fsrc%2Flib%2Flibnvpair).
+Unfortunately this port lacks the requisite support for floating-point data
+(DATA_TYPE_DOUBLE) but you could easily add that from the illumos sources.
+
+- What about node-waf and node-gyp?
+
+Fuck python, fuck WAF, and fuck all the hipster douchebags for whom make is
+too hard, too old, or "too Unixy".  Make is simple, easy to use, and
+extremely reliable.  It was building big, important pieces of software when
+your parents were young, and it Just Works.  If you don't like using make
+here, you probably don't want to use v8+ either, so just go away.  Write
+your CoffeeScript VM in something else, and gyp-scons-waf-rake your way to
+an Instagram retirement in Bali with all your hipster douchebag friends.
+Just don't bother me about it, because I don't care.
+
+- Why is Node failing in dlopen()?
+
+Most likely, your module has a typo or needs to be linked with a library.
+Normally, shared objects like Node addons should be linked with -zdefs so that
+these problems are found at build time, but Node doesn't deliver a mapfile
+specifying its API so you're left with a bunch of undefined symbols you just
+have to hope are defined somewhere in your node process's address space.  If
+they aren't, you're boned.  LD_DEBUG=all will help you find the missing
+symbol(s).
+
+As of 0.0.2, v8+ builds a mapfile for your node binary at the time you build
+your addon.  It does not attempt to restrict the visibility of any symbols,
+so you will not be warned if your addon is using private or deprecated
+functionality in V8 or Node.js.  Your build will, however, fail if you've
+neglected to link in any required libraries, typo'd a symbol name, etc.
+
+- Why use the old init() instead of NODE_MODULE()?
+
+Because NODE_MODULE() is a macro that can't be passed another macro as the
+name of your addon.  Using it would therefore require the source to v8+ to
+be generated at build time to match your module's name, which is
+inconvenient.  There may be a way to work around this.
+
+- Why can't I see my exception's decorative properties in JavaScript?
+
+Be careful when decorating exceptions.  There are several built-in hidden
+properties; if you decorate the exception with a property with the same
+name, you will change the hidden property's value but it will still be
+hidden.  This almost certainly is not what you want, so you should prefix
+the decorative property names with something unique to your module to avoid
+stepping on V8's (or JavaScript's) property namespace.
+
+- What if the factory model doesn't work for me?
+
+See "License" below.  Note also that one can export plain functions as well.
+
+- Why do I always die with "invalid property type -3621" (or other garbage)?
+
+You are passing an object with the wrong C type to `v8plus_obj()`.  Like
+all varargs functions, it cannot tell the correct size or type of the
+objects you have passed it; they must match the preceding type argument or
+it will not work correctly.  In this particular case, you've most likely
+done something like:
+
+	int foo = 0xdead;
+
+	v8plus_obj(V8PLUS_TYPE_NUMBER, "foo", foo, V8PLUS_TYPE_NONE);
+
+An 'int' is 4 bytes in size, and the compiler reserves 4 bytes on the stack
+and sticks the value of foo there.  When `v8plus_obj` goes to read it, it
+sees that the type is V8PLUS_TYPE_NUMBER, casts the address of the next
+argument slot to a `double *`, and dereferences it, then moves the argument
+list pointer ahead by the size of a double.  Unfortunately, a double
+is usually 8 bytes long, meaning that (a) the value of the property is going
+to be comprised of the integer-encoded foo appended to the next data type,
+and (b) the next data type is going to be read from either undefined memory
+or from part of the address of the name of the next property.  To cure this,
+always make sure that you cast your integral arguments properly when using
+V8PLUS_TYPE_NUMBER:
+
+	v8plus_obj(V8PLUS_TYPE_NUMBER, "foo", (double)foo, V8PLUS_TYPE_NONE);
+
+## License
+
+MIT.
+
+## Bugs
+
+See <https://github.com/joyent/v8plus/issues>.
+
+## Consumers
+
+This is an incomplete list of native addons known to be using v8+.  If your
+addon uses v8+, please let me know and I will include it here.
+
+- <https://github.com/joyent/node-contract>
--- /dev/null	2013-10-21 19:08:25.000000000 +0000
+++ new/src/node-lockfd/node_modules/v8plus/examples/Makefile	2013-10-21 19:08:25.922596742 +0000
@@ -0,0 +1,21 @@
+#
+# Copyright (c) 2012 Joyent, Inc.  All rights reserved.
+#
+
+V8PLUS =	..
+
+include $(V8PLUS)/Makefile.v8plus.defs
+
+MODULE =	example
+MODULE_DIR =	.
+
+SRCS =	\
+		example.c
+
+ERRNO_JSON =	errno.json
+
+PREFIX_NODE =	/opt/local
+CC =		/opt/local/bin/gcc
+CXX =		/opt/local/bin/g++
+
+include $(V8PLUS)/Makefile.v8plus.targ
--- /dev/null	2013-10-21 19:08:26.000000000 +0000
+++ new/src/node-lockfd/node_modules/v8plus/examples/errno.json	2013-10-21 19:08:26.075856531 +0000
@@ -0,0 +1,19 @@
+{
+	"error_base": "0x2000",
+	"errors": [
+	{
+		"code": "IMPRECISE",
+		"msg": "numerical value lacks adequate precision",
+		"exception": "TypeError"
+	},
+	{
+		"code": "RANGE",
+		"msg": "value out of range",
+		"exception": "RangeError"
+	},
+	{
+		"code": "MALFORMED",
+		"msg": "value is malformed or unparseable",
+		"exception": "TypeError"
+	} ]
+}
--- /dev/null	2013-10-21 19:08:26.000000000 +0000
+++ new/src/node-lockfd/node_modules/v8plus/examples/example.c	2013-10-21 19:08:26.218023303 +0000
@@ -0,0 +1,336 @@
+/*
+ * Copyright (c) 2012 Joyent, Inc.  All rights reserved.
+ */
+
+#include <sys/ccompile.h>
+#include <stdlib.h>
+#include <float.h>
+#include <errno.h>
+#include <libnvpair.h>
+#include "example.h"
+
+static nvlist_t *
+example_set_impl(example_t *ep, nvpair_t *pp)
+{
+	double dv;
+	const char *sv;
+	const char *ev;
+	uint64_t v;
+
+	switch (v8plus_typeof(pp)) {
+	case V8PLUS_TYPE_NUMBER:
+		(void) nvpair_value_double(pp, &dv);
+		if (dv > (1ULL << DBL_MANT_DIG) - 1) {
+			return (v8plus_error(V8PLUSERR_IMPRECISE,
+			    "large number lacks integer precision"));
+		}
+		ep->e_val = (uint64_t)dv;
+		break;
+	case V8PLUS_TYPE_STRING:
+		(void) nvpair_value_string(pp, (char **)&sv);
+		errno = 0;
+		v = (uint64_t)strtoull(sv, (char **)&ev, 0);
+		if (errno == ERANGE) {
+			return (v8plus_error(V8PLUSERR_RANGE,
+			    "value '%s' is out of range", sv));
+		}
+		if (ev != NULL && *ev != '\0') {
+			return (v8plus_error(V8PLUSERR_MALFORMED,
+			    "value '%s' is malformed", sv));
+		}
+		ep->e_val = v;
+		break;
+	case V8PLUS_TYPE_UNDEFINED:
+		ep->e_val = 0;
+		break;
+	default:
+		return (v8plus_error(V8PLUSERR_BADARG,
+		    "argument 0 is of incorrect type %d", v8plus_typeof(pp)));
+	}
+
+	return (v8plus_void());
+}
+
+static nvlist_t *
+example_ctor(const nvlist_t *ap, void **epp)
+{
+	nvpair_t *pp;
+	example_t *ep;
+
+	if (v8plus_args(ap, V8PLUS_ARG_F_NOEXTRA, V8PLUS_TYPE_NONE) != 0 &&
+	    v8plus_args(ap, V8PLUS_ARG_F_NOEXTRA,
+	    V8PLUS_TYPE_ANY, &pp, V8PLUS_TYPE_NONE) != 0)
+		return (NULL);
+
+	if ((ep = malloc(sizeof (example_t))) == NULL)
+		return (v8plus_error(V8PLUSERR_NOMEM, NULL));
+
+	(void) example_set_impl(ep, pp);
+	if (_v8plus_errno != V8PLUSERR_NOERROR) {
+		free(ep);
+		return (NULL);
+	}
+
+	*epp = ep;
+
+	return (v8plus_void());
+}
+
+static void
+example_dtor(void *op)
+{
+	free(op);
+}
+
+static nvlist_t *
+example_set(void *op, const nvlist_t *ap)
+{
+	nvpair_t *pp;
+	example_t *ep = op;
+
+	if (v8plus_args(ap, V8PLUS_ARG_F_NOEXTRA,
+	    V8PLUS_TYPE_ANY, &pp,
+	    V8PLUS_TYPE_NONE) != 0)
+		return (NULL);
+
+	(void) example_set_impl(ep, pp);
+	if (_v8plus_errno != V8PLUSERR_NOERROR)
+		return (NULL);
+
+	return (v8plus_void());
+}
+
+static nvlist_t *
+example_add(void *op, const nvlist_t *ap)
+{
+	example_t *ep = op;
+	example_t ae;
+	nvpair_t *pp;
+	nvlist_t *eap;
+	nvlist_t *erp;
+
+	if (v8plus_args(ap, V8PLUS_ARG_F_NOEXTRA,
+	    V8PLUS_TYPE_ANY, &pp, V8PLUS_TYPE_NONE) != 0)
+		return (NULL);
+
+	(void) example_set_impl(&ae, pp);
+	if (_v8plus_errno != V8PLUSERR_NOERROR)
+		return (NULL);
+
+	ep->e_val += ae.e_val;
+
+	eap = v8plus_obj(V8PLUS_TYPE_STRING, "0", "add", V8PLUS_TYPE_NONE);
+	if (eap != NULL) {
+		erp = v8plus_method_call(op, "__emit", eap);
+		nvlist_free(eap);
+		nvlist_free(erp);
+	}
+
+	return (v8plus_void());
+}
+
+static nvlist_t *
+example_static_add(const nvlist_t *ap)
+{
+	example_t ae0, ae1;
+	nvpair_t *pp0, *pp1;
+	uint64_t rv;
+
+	if (v8plus_args(ap, V8PLUS_ARG_F_NOEXTRA,
+	    V8PLUS_TYPE_ANY, &pp0,
+	    V8PLUS_TYPE_ANY, &pp1,
+	    V8PLUS_TYPE_NONE) != 0)
+		return (NULL);
+
+	(void) example_set_impl(&ae0, pp0);
+	if (_v8plus_errno != V8PLUSERR_NOERROR)
+		return (NULL);
+
+	(void) example_set_impl(&ae1, pp1);
+	if (_v8plus_errno != V8PLUSERR_NOERROR)
+		return (NULL);
+
+	rv = ae0.e_val + ae1.e_val;
+
+	return (v8plus_obj(
+	    V8PLUS_TYPE_STRNUMBER64, "res", rv,
+	    V8PLUS_TYPE_NONE));
+}
+
+static nvlist_t *
+example_multiply(void *op, const nvlist_t *ap)
+{
+	example_t *ep = op;
+	example_t ae;
+	nvpair_t *pp;
+
+	if (v8plus_args(ap, V8PLUS_ARG_F_NOEXTRA,
+	    V8PLUS_TYPE_ANY, &pp, V8PLUS_TYPE_NONE) != 0)
+		return (NULL);
+
+	(void) example_set_impl(&ae, pp);
+	if (_v8plus_errno != V8PLUSERR_NOERROR)
+		return (NULL);
+
+	ep->e_val *= ae.e_val;
+
+	return (v8plus_void());
+}
+
+typedef struct async_multiply_ctx {
+	example_t amc_operand;
+	uint64_t amc_result;
+	v8plus_jsfunc_t amc_cb;
+} async_multiply_ctx_t;
+
+static void *
+async_multiply_worker(void *op, void *ctx)
+{
+	example_t *ep = op;
+	async_multiply_ctx_t *cp = ctx;
+	example_t *ap = &cp->amc_operand;
+
+	cp->amc_result = ep->e_val * ap->e_val;
+
+	return (NULL);
+}
+
+static void
+async_multiply_done(void *op, void *ctx, void *res __UNUSED)
+{
+	async_multiply_ctx_t *cp = ctx;
+	example_t *ep = op;
+	nvlist_t *rp;
+	nvlist_t *ap;
+
+	ep->e_val = cp->amc_result;
+	ap = v8plus_obj(V8PLUS_TYPE_NONE);
+	if (ap != NULL) {
+		rp = v8plus_call(cp->amc_cb, ap);
+		nvlist_free(ap);
+		nvlist_free(rp);
+	}
+
+	v8plus_jsfunc_rele(cp->amc_cb);
+	free(cp);
+}
+
+static nvlist_t *
+example_multiplyAsync(void *op, const nvlist_t *ap)
+{
+	nvpair_t *pp;
+	v8plus_jsfunc_t cb;
+	async_multiply_ctx_t *cp;
+
+	if (v8plus_args(ap, V8PLUS_ARG_F_NOEXTRA,
+	    V8PLUS_TYPE_ANY, &pp,
+	    V8PLUS_TYPE_JSFUNC, &cb,
+	    V8PLUS_TYPE_NONE) != 0)
+		return (NULL);
+
+	if ((cp = malloc(sizeof (async_multiply_ctx_t))) == NULL)
+		return (v8plus_error(V8PLUSERR_NOMEM, "no memory for context"));
+
+	(void) example_set_impl(&cp->amc_operand, pp);
+	if (_v8plus_errno != V8PLUSERR_NOERROR) {
+		free(cp);
+		return (NULL);
+	}
+
+	v8plus_jsfunc_hold(cb);
+	cp->amc_cb = cb;
+
+	v8plus_defer(op, cp, async_multiply_worker, async_multiply_done);
+
+	return (v8plus_void());
+}
+
+static nvlist_t *
+example_toString(void *op, const nvlist_t *ap)
+{
+	example_t *ep = op;
+	nvpair_t *pp;
+
+	/*
+	 * Example of decorated exceptions.  Not strictly needed.
+	 */
+	if (v8plus_args(ap, 0,
+	    V8PLUS_TYPE_ANY, &pp, V8PLUS_TYPE_NONE) == 0) {
+		(void) v8plus_error(V8PLUSERR_EXTRAARG, NULL);
+		return (v8plus_obj(
+		    V8PLUS_TYPE_INL_OBJECT, "err",
+			V8PLUS_TYPE_NUMBER, "example_argument", (double)0,
+			V8PLUS_TYPE_NUMBER, "example_type",
+			    (double)v8plus_typeof(pp),
+			V8PLUS_TYPE_NONE,
+		    V8PLUS_TYPE_NONE));
+	}
+
+	return (v8plus_obj(
+	    V8PLUS_TYPE_STRNUMBER64, "res", (uint64_t)ep->e_val,
+	    V8PLUS_TYPE_NONE));
+}
+
+static nvlist_t *
+example_static_object(const nvlist_t *ap __UNUSED)
+{
+	return (v8plus_obj(
+	    V8PLUS_TYPE_INL_OBJECT, "res",
+		V8PLUS_TYPE_NUMBER, "fred", (double)555.5,
+		V8PLUS_TYPE_STRING, "barney", "the sky is blue",
+		V8PLUS_TYPE_INL_OBJECT, "betty",
+		    V8PLUS_TYPE_STRING, "bert", "ernie",
+		    V8PLUS_TYPE_BOOLEAN, "coffeescript_is_a_joke", B_TRUE,
+		    V8PLUS_TYPE_NONE,
+		V8PLUS_TYPE_NULL, "wilma",
+		V8PLUS_TYPE_UNDEFINED, "pebbles",
+		V8PLUS_TYPE_NUMBER, "bam-bam", (double)-32,
+		V8PLUS_TYPE_STRNUMBER64, "dino", 0x1234567812345678ULL,
+		V8PLUS_TYPE_NONE,
+	    V8PLUS_TYPE_NONE));
+}
+
+/*
+ * v8+ boilerplate
+ */
+const v8plus_c_ctor_f v8plus_ctor = example_ctor;
+const v8plus_c_dtor_f v8plus_dtor = example_dtor;
+const char *v8plus_js_factory_name = "create";
+const char *v8plus_js_class_name = "Example";
+const v8plus_method_descr_t v8plus_methods[] = {
+	{
+		md_name: "set",
+		md_c_func: example_set
+	},
+	{
+		md_name: "add",
+		md_c_func: example_add
+	},
+	{
+		md_name: "multiply",
+		md_c_func: example_multiply
+	},
+	{
+		md_name: "toString",
+		md_c_func: example_toString
+	},
+	{
+		md_name: "multiplyAsync",
+		md_c_func: example_multiplyAsync
+	}
+};
+const uint_t v8plus_method_count =
+    sizeof (v8plus_methods) / sizeof (v8plus_methods[0]);
+
+const v8plus_static_descr_t v8plus_static_methods[] = {
+	{
+		sd_name: "static_add",
+		sd_c_func: example_static_add
+	},
+	{
+		sd_name: "static_object",
+		sd_c_func: example_static_object
+	}
+};
+const uint_t v8plus_static_method_count =
+    sizeof (v8plus_static_methods) / sizeof (v8plus_static_methods[0]);
--- /dev/null	2013-10-21 19:08:26.000000000 +0000
+++ new/src/node-lockfd/node_modules/v8plus/examples/example.h	2013-10-21 19:08:26.362648696 +0000
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2012 Joyent, Inc.  All rights reserved.
+ */
+
+#ifndef _EXAMPLE_H
+#define	_EXAMPLE_H
+
+#include <sys/types.h>
+#include "v8plus_glue.h"
+
+#ifdef	__cplusplus
+extern "C" {
+#endif	/* __cplusplus */
+
+typedef struct example {
+	uint64_t e_val;
+} example_t;
+
+#ifdef	__cplusplus
+}
+#endif	/* __cplusplus */
+
+#endif	/* _EXAMPLE_H */
--- /dev/null	2013-10-21 19:08:26.000000000 +0000
+++ new/src/node-lockfd/node_modules/v8plus/examples/test.js	2013-10-21 19:08:26.510278731 +0000
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2012 Joyent, Inc.  All rights reserved.
+ */
+
+/*
+ * 'example' is a native C module that provides a partial implementation of
+ * an unsigned 64-bit integer type.  This is a simple consumer that
+ * demonstrates creation and manipulation of these objects, which should be
+ * self-explanatory.  See example.c for the implementation.
+ */
+
+var example = require('./example');
+var util = require('util');
+var EventEmitter = require('events').EventEmitter;
+
+var e = example.create();
+var f = example.create('8000000000');
+
+console.log('e = ' + e.toString());
+console.log('f = ' + f.toString());
+
+e.add(132);
+console.log('e = ' + e.toString());
+
+try {
+	e.set(0x1111111111111111);
+} catch (e) {
+	console.log('got exception: ' + e.name + ' (' + e.message + ')');
+}
+
+e.set('0x1111111111111111');
+console.log('e = ' + e.toString());
+
+e.multiply(5);
+console.log('e = ' + e.toString());
+
+try {
+	e.toString(33, 'fred');
+} catch (e) {
+	console.log('got exception: ' + e.name + ' (' + e.message + ')');
+	console.log(util.inspect(e, false, null));
+}
+
+e.set(50000000);
+f.set(22222222);
+e.multiply(f.toString());
+console.log('e = ' + e.toString());
+console.log('f = ' + f.toString());
+
+e.set(33);
+e.multiplyAsync(100, function () {
+	console.log('background e = ' + e.toString());
+});
+
+function
+Wrapper(ex)
+{
+	var self = this;
+
+	ex.__emit = function (name) {
+		var args = Array.prototype.slice.call(arguments);
+		self.emit.apply(self, args);
+	};
+}
+
+util.inherits(Wrapper, EventEmitter);
+
+var g = example.create('543');
+var gw = new Wrapper(g);
+
+gw.on('add', function () {
+	console.log('someone added something');
+});
+
+g.add(200);
+g.add(300);
+g.add(400);
+
+console.log('1000000000000000000 + 3333333333333333333 = ' +
+    example.static_add('1000000000000000000', '3333333333333333333'));
+
+console.log(example.static_object());
--- /dev/null	2013-10-21 19:08:26.000000000 +0000
+++ new/src/node-lockfd/node_modules/v8plus/generrno.js	2013-10-21 19:08:26.649219444 +0000
@@ -0,0 +1,229 @@
+#! /usr/bin/env node
+
+/*
+ * Copyright (c) 2012 Joyent, Inc.  All rights reserved.
+ */
+
+var util = require('util');
+var fs = require('fs');
+var mod_getopt = require('posix-getopt');
+
+var prologue =
+    '/*\n' +
+    ' * STOP!\n' +
+    ' *\n' +
+    ' * Do not edit this file.  It is automatically generated by generrno.\n' +
+    ' */\n\n';
+
+var guard_prologue =
+    '#ifndef\t_V8PLUS_ERRNO_H\n' +
+    '#define\t_V8PLUS_ERRNO_H\n\n' +
+    '#ifdef\t__cplusplus\n' +
+    'extern "C" {\n' +
+    '#endif\t/* __cplusplus */\n';
+
+var decl_prologue =
+    '#define\tV8PLUS_ERRNO_BASE\t%s\n\n' +
+    'typedef enum _v8plus_errno {\n' +
+    '\tV8PLUSERR_NOERROR = 0,\n' +
+    '\tV8PLUSERR_%s = V8PLUS_ERRNO_BASE + 1,\n';
+
+var decl_one =
+    '\tV8PLUSERR_%s,\n';
+
+var decl_epilogue =
+    '} v8plus_errno_t;\n';
+
+var guard_epilogue =
+    '#ifdef\t__cplusplus\n' +
+    '}\n' +
+    '#endif\t/* __cplusplus */\n\n' +
+    '#endif\t/* _V8PLUS_ERRNO_H */\n';
+
+var include =
+    '#include "v8plus_errno.h"\n\n';
+
+var func_prologue =
+    'const char *\n' +
+    'v8plus_%s(v8plus_errno_t e)\n' +
+    '{\n' +
+    '\tswitch (e) {\n';
+
+var generic_case =
+    '\tcase V8PLUSERR_%s:\n' +
+    '\t\treturn ("%s");\n';
+
+var errname_case = 
+    '\tcase V8PLUSERR_%s:\n' +
+    '\t\treturn ("V8PLUSERR_%s");\n';
+
+var func_epilogue =
+    '\tdefault:\n' +
+    '\t\treturn ("%s");\n' +
+    '\t}\n' +
+    '}\n';
+
+var BUILTIN_ERRORS = [
+	{
+		code: 'NOMEM',
+		msg: 'out of memory',
+		exception: 'Error'
+	},
+	{
+		code: 'YOUSUCK',
+		msg: 'programmer error',
+		exception: 'Error'
+	},
+	{
+		code: 'UNKNOWN',
+		msg: 'unknown error',
+		exception: 'Error'
+	},
+	{
+		code: 'MISSINGARG',
+		msg: 'missing argument is required',
+		exception: 'TypeError'
+	},
+	{
+		code: 'BADARG',
+		msg: 'argument is of incorrect type',
+		exception: 'TypeError'
+	},
+	{
+		code: 'EXTRAARG',
+		msg: 'superfluous argument(s) detected',
+		exception: 'TypeError'
+	},
+	{
+		code: 'BADF',
+		msg: 'bad file descriptor',
+		exception: 'Error'
+	}
+];
+
+function
+usage()
+{
+	console.log(process.argv[0] + ' ' + process.argv[1] +
+	    ' {-c|-h} [-o <output>] <input>\n');
+	process.exit(1);
+}
+
+function
+parse_arguments(argv)
+{
+	var opt_c = 0;
+	var opt_h = 0;
+	var option;
+	var obj = {};
+	var parser = new mod_getopt.BasicParser('cho:', argv);
+	var defs;
+
+	while ((option = parser.getopt()) !== undefined && !option.error) {
+		switch (option.option) {
+		case 'c':
+			opt_c++;
+			obj.action = 'c';
+			break;
+		case 'h':
+			opt_h++;
+			obj.action = 'h';
+			break;
+		case 'o':
+			obj.output = option.optarg;
+			break;
+		default:
+			usage();
+			break;
+		}
+	}
+
+	obj.input = argv[parser.optind()];
+
+	if (opt_c + opt_h != 1)
+		usage();
+
+	if (!obj.input)
+		usage();
+
+	defs = fs.readFileSync(obj.input);
+	obj.defs = JSON.parse(defs);
+
+	BUILTIN_ERRORS.forEach(function _prepend_err(e) {
+		obj.defs.errors.unshift(e);
+	});
+
+	return (obj);
+}
+
+function
+write(output, str)
+{
+	if (!output)
+		process.stdout.write(str);
+	else
+		fs.writeFileSync(output, str)
+}
+
+function
+write_c(defs, output)
+{
+	var out = '';
+
+	out += prologue;
+	out += include;
+
+	out += util.format(func_prologue, 'strerror');
+	defs.errors.forEach(function _append_str(e) {
+		out += util.format(generic_case, e.code, e.msg);
+	});
+	out += util.format(func_epilogue, 'unknown v8+ error code');
+	out += '\n';
+
+	out += util.format(func_prologue, 'errname');
+	defs.errors.forEach(function _append_name(e) {
+		out += util.format(errname_case, e.code, e.code);
+	});
+	out += util.format(func_epilogue, 'unknown v8+ error code');
+	out += '\n';
+
+	out += util.format(func_prologue, 'excptype');
+	defs.errors.forEach(function _append_excp(e) {
+		out += util.format(generic_case, e.code, e.exception);
+	});
+	out += util.format(func_epilogue, 'Error');
+
+	write(output, out);
+}
+
+function
+write_header(defs, output)
+{
+	var out = '';
+
+	out += prologue;
+	out += guard_prologue;
+	out += util.format(decl_prologue, defs.error_base, defs.errors[0].code);
+	defs.errors.forEach(function _spew_decl(e, i) {
+		if (i > 0)
+			out += util.format(decl_one, e.code);
+	});
+	out += decl_epilogue;
+	out += guard_epilogue;
+
+	write(output, out);
+}
+
+var action = parse_arguments(process.argv);
+
+switch (action.action) {
+case 'c':
+	write_c(action.defs, action.output);
+	break;
+case 'h':
+	write_header(action.defs, action.output);
+	break;
+default:
+	usage();
+	break;
+}
--- /dev/null	2013-10-21 19:08:26.000000000 +0000
+++ new/src/node-lockfd/node_modules/v8plus/node_modules/posix-getopt/LICENSE	2013-10-21 19:08:26.807879595 +0000
@@ -0,0 +1,19 @@
+Copyright 2011 David Pacheco. All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to
+deal in the Software without restriction, including without limitation the
+rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+IN THE SOFTWARE. 
--- /dev/null	2013-10-21 19:08:27.000000000 +0000
+++ new/src/node-lockfd/node_modules/v8plus/node_modules/posix-getopt/README.md	2013-10-21 19:08:26.958301958 +0000
@@ -0,0 +1,244 @@
+
+node-getopt
+==============
+
+Overview
+--------
+
+node-getopt is a Node.js module providing an interface to the POSIX-defined
+getopt() function, a general-purpose command line parser that follows the POSIX
+guidelines for command-line utilities.  Using these guidelines encourages
+common conventions among applications, including use of:
+
+    o short option names (e.g., "-r")
+    o options with arguments (e.g., "-f filename or -ffilename")
+    o chaining short option names when options have no arguments (e.g., "-ra")
+
+This implementation mirrors the Solaris getopt() implementation and supports
+long option names (e.g., "--recurse"), potentially with values specified using
+"=" (e.g., "--file=/path/to/file").
+
+Unlike other option parsers available for Node.js, the POSIX getopt() interface
+supports using the same option multiple times (e.g., "-vvv", commonly used to
+indicate level of verbosity).
+
+For further reference on the relevant POSIX standards, see the following:
+
+    http://pubs.opengroup.org/onlinepubs/009695399/functions/getopt.html
+    http://pubs.opengroup.org/onlinepubs/009695399/utilities/getopts.html
+
+The Utility Syntax Guidelines are described here:
+
+    http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap12.html
+
+
+Status
+------
+
+This module is considered complete except that
+
+    o test coverage is pretty minimal
+    o npm install has not been tested
+    o the source is not javascriptlint-clean
+
+There are no known bugs, but the module has not been extensively tested.
+
+
+Platforms
+---------
+
+This module should work on all platforms that support node.js.  The module is
+tested on MacOS X 10.6.5 and OpenSolaris based on build 111b and Illumos build
+147.
+
+
+Installation
+------------
+
+As an npm package, node-getopt is installed in the usual way:
+
+      % npm install posix-getopt
+
+
+API
+---
+
+### `new getopt.BasicParser(optstring, argv)`
+
+Instantiates a new object for parsing the specified arguments using the
+specified option string.  This interface is closest to the traditional getopt()
+C function.  Callers first instantiate a BasicParser and then invoke the
+getopt() method to iterate the options as they would in C.  (This interface
+allows the same option to be specified multiple times.)  The first two arguments
+in "argv" are ignored, since they generally denote the path to the node
+executable and the script being run, so options start with the third element.
+
+The option string consists of an optional leading ":" (see below) followed by a
+sequence of option-specifiers.  Each option-specifier consists of a single
+character denoting the short option name, optionally followed by a colon if the
+option takes an argument and/or a sequence of strings in parentheses
+representing long-option aliases for the option name.
+
+Example option strings:
+        ':r'            Command takes one option with no args: -r
+        ':ra'           Command takes two option with no args: -r and -a
+        ':raf:'         Command takes two option with no args: -r and -a
+                        and a single option that takes an arg: -f
+        ':f:(file)'     Command takes a single option with an argument: -f
+                        -f can also be specified as --file
+
+The presence of a leading colon in the option string determines the behavior
+when an argument is not specified for an option which takes an argument.  See
+getopt() below.  Additionally, if no colon is specified, then error messages are
+printed to stderr when invalid options, options with missing arguments, or
+options with unexpected arguments are encountered.
+
+
+### `parser.optind()`
+
+Returns the next argv-argument to be parsed.  When options are specified as
+separate "argv" arguments, this value is incremented with each option parsed.
+When multiple options are specified in the same argv-argument, the returned
+value is unspecified.  This matches the variable "OPTIND" from the POSIX
+standard, but is read-only.  (If you want to reset OPTIND, you must create a new
+BasicParser instance.)  This is most useful after parsing has finished to
+examine the non-option arguments.
+
+This value starts at "2" as described under "Departures from POSIX" below.
+
+
+### `parser.getopt()`
+
+Returns the next argument specified in "argv" (the object's constructor
+argument).  The returned value is either undefined or an object with at least
+the following members:
+
+	option		single-character option name
+
+The following members may also be present:
+
+	optarg		argument value, if any
+
+	optopt		option character that caused the error, if any
+
+	error		if true, this object represents an error
+
+This function scans "argv" starting at the current value of "optind" and returns
+an object describing the next argument based on the following cases:
+
+    o If the end of command line arguments is reached, an undefined value is
+      returned.  The end of arguments is signified by a single '-' argument, a
+      single '--' argument, an argument that's neither an option nor a previous
+      option's argument, the end of argv, or an error.
+
+    o If an unrecognized command line option is found (i.e. an option character
+      not defined in "optstring"), the returned object's "option" member
+      is just "?".  "optopt" is set to the unrecognized option letter.  "error"
+      is set to a true value.
+
+    o If a known command line option is found and the option takes no arguments
+      then the returned object's "option" member is the option's short name
+      (i.e.  the single character specifier in "optstring").
+      
+    o If a known command line option is found and that option takes an argument
+      and the argument is also found, then the returned object's "option"
+      member is the option's short name and the "optarg" member contains the
+      argument's value.
+
+    o If a known command line option is found and that option takes an argument
+      but the argument is not found, then the returned object's "option" member
+      is "?" unless the first character of "optstring" was a colon, in which
+      case the "option" member is set to ":".  Either way, the "optopt" member
+      is set to the option character that caused the error and "error" is set to
+      a true value.
+
+
+Departures from POSIX
+--------
+
+    o Global state in the C implementation (e.g., optind, optarg, and optopt) is
+      encapsulated in the BasicParser object.  optind is available as a method
+      call on the parser object.  optarg and optopt are returned directly by
+      getopt().
+
+    o Rather than returning an integer or character, getopt() returns an object
+      with the "option" field corresponding to the processed option character
+      and possibly the additional "optarg" and "optopt" fields.  If an error
+      occurs on a particular option, "error" is also set.  If an error occurs on
+      no particular option or if the end of input is encountered, undefined is
+      returned.
+
+    o Long option forms are supported as described above.  This introduces an
+      additional error case which is where an argument of the form
+      --option=value is encountered, where "option" does not take a value.
+
+    o POSIX starts "optind" at 1, since argv[0] is generally the name of the
+      command and options start at argv[1].  This implementation starts "optind"
+      at 2, since argv[0] is generally the path to the node binary and argv[1]
+      is the path to the script, so options start with argv[2].
+
+
+Examples
+--------
+
+### Example 1: simple short options
+
+	var mod_getopt = require('getopt')
+	var parser, option;
+	
+	parser = new mod_getopt.BasicParser('la',
+	    ['node', 'script', '-l', '-a', 'stuff']);
+	while ((option = parser.getopt()) !== undefined && !option.error)
+		console.error(option);
+
+### Example 2: invalid option specified
+
+	var mod_getopt = require('getopt')
+	var parser, option;
+	
+	parser = new mod_getopt.BasicParser('la',
+	    ['node', 'script', '-l', '-b', 'stuff']);
+	while ((option = parser.getopt()) !== undefined && !option.error)
+		console.error(option);
+	console.error(option);
+
+### Example 3: long options
+
+	var mod_getopt = require('getopt')
+	var parser, option;
+	
+	parser = new mod_getopt.BasicParser('lar(recurse)',
+	    ['node', 'script', '-l', '--recurse', 'stuff']);
+	while ((option = parser.getopt()) !== undefined && !option.error)
+		console.error(option);
+
+### Example 4: options with arguments
+
+	var mod_getopt = require('getopt')
+	var parser, option;
+	
+	parser = new mod_getopt.BasicParser('f:lad:',
+	    ['node', 'script', '-l', '-f', 'filename', '-dtype', 'stuff']);
+	while ((option = parser.getopt()) !== undefined && !option.error)
+		console.error(option);
+
+### Example 5: options with missing arguments
+
+	var mod_getopt = require('getopt')
+	var parser, option;
+	
+	parser = new mod_getopt.BasicParser('f:la',
+	    ['node', 'script', '-l', '-a', '-f']);
+	while ((option = parser.getopt()) !== undefined && !option.error)
+		console.error(option);
+	console.error(option);
+
+### Example 6: options specified multiple times
+
+	var mod_getopt = require('getopt')
+	var parser, option;
+	
+	parser = new mod_getopt.BasicParser('la',
+	    ['node', 'script', '-l', '-a', '-l']);
+	while ((option = parser.getopt()) !== undefined && !option.error)
+		console.error(option);
--- /dev/null	2013-10-21 19:08:27.000000000 +0000
+++ new/src/node-lockfd/node_modules/v8plus/node_modules/posix-getopt/examples/examples.js	2013-10-21 19:08:27.162300215 +0000
@@ -0,0 +1,40 @@
+var mod_getopt = require('getopt')
+var parser, option;
+
+console.error("Example 1: simple short options");
+parser = new mod_getopt.BasicParser('la',
+    ['node', 'script', '-l', '-a', 'stuff']);
+while ((option = parser.getopt()) !== undefined && !option.error)
+	console.error(option);
+
+console.error("Example 2: invalid option specified");
+parser = new mod_getopt.BasicParser('la',
+    ['node', 'script', '-l', '-b', 'stuff']);
+while ((option = parser.getopt()) !== undefined && !option.error)
+	console.error(option);
+console.error(option);
+
+console.error("Example 3: long options");
+parser = new mod_getopt.BasicParser('lar(recurse)',
+    ['node', 'script', '-l', '--recurse', 'stuff']);
+while ((option = parser.getopt()) !== undefined && !option.error)
+	console.error(option);
+
+console.error("Example 4: options with arguments");
+parser = new mod_getopt.BasicParser('f:lad:',
+    ['node', 'script', '-l', '-f', 'filename', '-dtype', 'stuff']);
+while ((option = parser.getopt()) !== undefined && !option.error)
+	console.error(option);
+
+console.error("Example 5: options with missing arguments");
+parser = new mod_getopt.BasicParser('f:la',
+    ['node', 'script', '-l', '-a', '-f']);
+while ((option = parser.getopt()) !== undefined && !option.error)
+	console.error(option);
+console.error(option);
+
+console.error("Example 6: options specified multiple times");
+parser = new mod_getopt.BasicParser('la',
+    ['node', 'script', '-l', '-a', '-l']);
+while ((option = parser.getopt()) !== undefined && !option.error)
+	console.error(option);
--- /dev/null	2013-10-21 19:08:27.000000000 +0000
+++ new/src/node-lockfd/node_modules/v8plus/node_modules/posix-getopt/lib/getopt.js	2013-10-21 19:08:27.319758278 +0000
@@ -0,0 +1,304 @@
+/*
+ * getopt.js: node.js implementation of POSIX getopt() (and then some)
+ *
+ * Copyright 2011 David Pacheco. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE. 
+ */
+
+var ASSERT = require('assert').ok;
+
+function goError(msg)
+{
+	return (new Error('getopt: ' + msg));
+};
+
+/*
+ * The BasicParser is our primary interface to the outside world.  The
+ * documentation for this object and its public methods is contained in
+ * the included README.md.
+ */
+function goBasicParser(optstring, argv)
+{
+	var ii;
+
+	ASSERT(optstring || optstring === '', "optstring is required");
+	ASSERT(optstring.constructor === String, "optstring must be a string");
+	ASSERT(argv, "argv is required");
+	ASSERT(argv.constructor === Array, "argv must be an array");
+
+	this.gop_argv = new Array(argv.length);
+	this.gop_options = {};
+	this.gop_aliases = {};
+	this.gop_optind = 2;
+	this.gop_subind = 0;
+
+	for (ii = 0; ii < argv.length; ii++) {
+		ASSERT(argv[ii].constructor === String,
+		    "argv must be string array");
+		this.gop_argv[ii] = argv[ii];
+	}
+
+	this.parseOptstr(optstring);
+}
+
+exports.BasicParser = goBasicParser;
+
+/*
+ * Parse the option string and update the following fields:
+ *
+ *	gop_silent	Whether to log errors to stderr.  Silent mode is
+ *			indicated by a leading ':' in the option string.
+ *
+ *	gop_options	Maps valid single-letter-options to booleans indicating
+ *			whether each option is required.
+ *
+ *	gop_aliases	Maps valid long options to the corresponding
+ *			single-letter short option.
+ */
+goBasicParser.prototype.parseOptstr = function (optstr)
+{
+	var chr, cp, alias, arg, ii;
+
+	ii = 0;
+	if (optstr.length > 0 && optstr[0] == ':') {
+		this.gop_silent = true;
+		ii++;
+	} else {
+		this.gop_silent = false;
+	}
+
+	while (ii < optstr.length) {
+		chr = optstr[ii];
+		arg = false;
+
+		if (!/^[\w\d]$/.test(chr))
+			throw (goError('invalid optstring: only alphanumeric ' +
+			    'characters may be used as options: ' + chr));
+
+		if (ii + 1 < optstr.length && optstr[ii + 1] == ':') {
+			arg = true;
+			ii++;
+		}
+
+		this.gop_options[chr] = arg;
+
+		while (ii + 1 < optstr.length && optstr[ii + 1] == '(') {
+			ii++;
+			cp = optstr.indexOf(')', ii + 1);
+			if (cp == -1)
+				throw (goError('invalid optstring: missing ' +
+				    '")" to match "(" at char ' + ii));
+
+			alias = optstr.substring(ii + 1, cp);
+			this.gop_aliases[alias] = chr;
+			ii = cp;
+		}
+
+		ii++;
+	}
+};
+
+goBasicParser.prototype.optind = function ()
+{
+	return (this.gop_optind);
+};
+
+/*
+ * For documentation on what getopt() does, see README.md.  The following
+ * implementation invariants are maintained by getopt() and its helper methods:
+ *
+ *	this.gop_optind		Refers to the element of gop_argv that contains
+ *				the next argument to be processed.  This may
+ *				exceed gop_argv, in which case the end of input
+ *				has been reached.
+ *
+ *	this.gop_subind		Refers to the character inside
+ *				this.gop_options[this.gop_optind] which begins
+ *				the next option to be processed.  This may never
+ *				exceed the length of gop_argv[gop_optind], so
+ *				when incrementing this value we must always
+ *				check if we should instead increment optind and
+ *				reset subind to 0.
+ *
+ * That is, when any of these functions is entered, the above indices' values
+ * are as described above.  getopt() itself and getoptArgument() may both be
+ * called at the end of the input, so they check whether optind exceeds
+ * argv.length.  getoptShort() and getoptLong() are called only when the indices
+ * already point to a valid short or long option, respectively.
+ *
+ * getopt() processes the next option as follows:
+ *
+ *	o If gop_optind > gop_argv.length, then we already parsed all arguments.
+ *
+ *	o If gop_subind == 0, then we're looking at the start of an argument:
+ *
+ *	    o Check for special cases like '-', '--', and non-option arguments.
+ *	      If present, update the indices and return the appropriate value.
+ *
+ *	    o Check for a long-form option (beginning with '--').  If present,
+ *	      delegate to getoptLong() and return the result.
+ *
+ *	    o Otherwise, advance subind past the argument's leading '-' and
+ *	      continue as though gop_subind != 0 (since that's now the case).
+ *
+ *	o Delegate to getoptShort() and return the result.
+ */
+goBasicParser.prototype.getopt = function ()
+{
+	if (this.gop_optind >= this.gop_argv.length)
+		/* end of input */
+		return (undefined);
+
+	arg = this.gop_argv[this.gop_optind];
+
+	if (this.gop_subind == 0) {
+		if (arg == '-' || arg === '' || arg[0] != '-')
+			return (undefined);
+	
+		if (arg == '--') {
+			this.gop_optind++;
+			this.gop_subind = 0;
+			return (undefined);
+		}
+
+		if (arg[1] == '-')
+			return (this.getoptLong());
+
+		this.gop_subind++;
+		ASSERT(this.gop_subind < arg.length);
+	}
+
+	return (this.getoptShort());
+};
+
+/*
+ * Implements getopt() for the case where optind/subind point to a short option.
+ */
+goBasicParser.prototype.getoptShort = function ()
+{
+	var arg, chr;
+
+	ASSERT(this.gop_optind < this.gop_argv.length);
+	arg = this.gop_argv[this.gop_optind];
+	ASSERT(this.gop_subind < arg.length);
+	chr = arg[this.gop_subind];
+
+	if (!(chr in this.gop_options))
+		return (this.errInvalidOption(chr));
+
+	if (++this.gop_subind >= arg.length) {
+		this.gop_optind++;
+		this.gop_subind = 0;
+	}
+
+	if (!this.gop_options[chr])
+		return ({ option: chr });
+
+	return (this.getoptArgument(chr));
+}
+
+/*
+ * Implements getopt() for the case where optind/subind point to a long option.
+ */
+goBasicParser.prototype.getoptLong = function ()
+{
+	var arg, alias, chr, eq;
+
+	ASSERT(this.gop_subind === 0);
+	ASSERT(this.gop_optind < this.gop_argv.length);
+	arg = this.gop_argv[this.gop_optind];
+	ASSERT(arg.length > 2 && arg[0] == '-' && arg[1] == '-');
+
+	eq = arg.indexOf('=');
+	alias = arg.substring(2, eq == -1 ? arg.length : eq);
+	if (!(alias in this.gop_aliases))
+		return (this.errInvalidOption(alias));
+
+	chr = this.gop_aliases[alias];
+	ASSERT(chr in this.gop_options);
+
+	if (!this.gop_options[chr]) {
+		if (eq != -1)
+			return (this.errExtraArg(alias));
+		
+		this.gop_optind++; /* eat this argument */
+		return ({ option: chr });
+	}
+
+	/*
+	 * Advance optind/subind for the argument value and retrieve it.
+	 */
+	if (eq == -1)
+		this.gop_optind++;
+	else
+		this.gop_subind = eq + 1;
+
+	return (this.getoptArgument(chr));
+};
+
+/*
+ * For the given option letter 'chr' that takes an argument, assumes that
+ * optind/subind point to the argument (or denote the end of input) and return
+ * the appropriate getopt() return value for this option and argument (or return
+ * the appropriate error).
+ */
+goBasicParser.prototype.getoptArgument = function (chr)
+{
+	var arg;
+
+	if (this.gop_optind >= this.gop_argv.length)
+		return (this.errMissingArg(chr));
+
+	arg = this.gop_argv[this.gop_optind].substring(this.gop_subind);
+	this.gop_optind++;
+	this.gop_subind = 0;
+	return ({ option: chr, optarg: arg });
+};
+
+goBasicParser.prototype.errMissingArg = function (chr)
+{
+	if (this.gop_silent)
+		return ({ option: '?', optopt: chr });
+
+	process.stderr.write('option requires an argument -- ' + chr + '\n');
+	return ({ option: ':', optopt: chr, error: true });
+};
+
+goBasicParser.prototype.errInvalidOption = function (chr)
+{
+	if (!this.gop_silent)
+		process.stderr.write('illegal option -- ' + chr + '\n');
+
+	return ({ option: '?', optopt: chr, error: true });
+};
+
+/*
+ * This error is not specified by POSIX, but neither is the notion of specifying
+ * long option arguments using "=" in the same argv-argument, but it's common
+ * practice and pretty convenient.
+ */
+goBasicParser.prototype.errExtraArg = function (chr)
+{
+	if (!this.gop_silent)
+		process.stderr.write('option expects no argument -- ' +
+		    chr + '\n');
+
+	return ({ option: '?', optopt: chr, error: true });
+};
--- /dev/null	2013-10-21 19:08:27.000000000 +0000
+++ new/src/node-lockfd/node_modules/v8plus/node_modules/posix-getopt/package.json	2013-10-21 19:08:27.452389907 +0000
@@ -0,0 +1,17 @@
+{
+  "name": "posix-getopt",
+  "version": "0.0.1",
+  "description": "POSIX-style getopt()",
+  "author": {
+    "name": "Dave Pacheco",
+    "url": "dap@cs.brown.edu"
+  },
+  "engines": {
+    "node": "*"
+  },
+  "main": "./lib/getopt",
+  "readme": "\nnode-getopt\n==============\n\nOverview\n--------\n\nnode-getopt is a Node.js module providing an interface to the POSIX-defined\ngetopt() function, a general-purpose command line parser that follows the POSIX\nguidelines for command-line utilities.  Using these guidelines encourages\ncommon conventions among applications, including use of:\n\n    o short option names (e.g., \"-r\")\n    o options with arguments (e.g., \"-f filename or -ffilename\")\n    o chaining short option names when options have no arguments (e.g., \"-ra\")\n\nThis implementation mirrors the Solaris getopt() implementation and supports\nlong option names (e.g., \"--recurse\"), potentially with values specified using\n\"=\" (e.g., \"--file=/path/to/file\").\n\nUnlike other option parsers available for Node.js, the POSIX getopt() interface\nsupports using the same option multiple times (e.g., \"-vvv\", commonly used to\nindicate level of verbosity).\n\nFor further reference on the relevant POSIX standards, see the following:\n\n    http://pubs.opengroup.org/onlinepubs/009695399/functions/getopt.html\n    http://pubs.opengroup.org/onlinepubs/009695399/utilities/getopts.html\n\nThe Utility Syntax Guidelines are described here:\n\n    http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap12.html\n\n\nStatus\n------\n\nThis module is considered complete except that\n\n    o test coverage is pretty minimal\n    o npm install has not been tested\n    o the source is not javascriptlint-clean\n\nThere are no known bugs, but the module has not been extensively tested.\n\n\nPlatforms\n---------\n\nThis module should work on all platforms that support node.js.  The module is\ntested on MacOS X 10.6.5 and OpenSolaris based on build 111b and Illumos build\n147.\n\n\nInstallation\n------------\n\nAs an npm package, node-getopt is installed in the usual way:\n\n      % npm install posix-getopt\n\n\nAPI\n---\n\n### `new getopt.BasicParser(optstring, argv)`\n\nInstantiates a new object for parsing the specified arguments using the\nspecified option string.  This interface is closest to the traditional getopt()\nC function.  Callers first instantiate a BasicParser and then invoke the\ngetopt() method to iterate the options as they would in C.  (This interface\nallows the same option to be specified multiple times.)  The first two arguments\nin \"argv\" are ignored, since they generally denote the path to the node\nexecutable and the script being run, so options start with the third element.\n\nThe option string consists of an optional leading \":\" (see below) followed by a\nsequence of option-specifiers.  Each option-specifier consists of a single\ncharacter denoting the short option name, optionally followed by a colon if the\noption takes an argument and/or a sequence of strings in parentheses\nrepresenting long-option aliases for the option name.\n\nExample option strings:\n        ':r'            Command takes one option with no args: -r\n        ':ra'           Command takes two option with no args: -r and -a\n        ':raf:'         Command takes two option with no args: -r and -a\n                        and a single option that takes an arg: -f\n        ':f:(file)'     Command takes a single option with an argument: -f\n                        -f can also be specified as --file\n\nThe presence of a leading colon in the option string determines the behavior\nwhen an argument is not specified for an option which takes an argument.  See\ngetopt() below.  Additionally, if no colon is specified, then error messages are\nprinted to stderr when invalid options, options with missing arguments, or\noptions with unexpected arguments are encountered.\n\n\n### `parser.optind()`\n\nReturns the next argv-argument to be parsed.  When options are specified as\nseparate \"argv\" arguments, this value is incremented with each option parsed.\nWhen multiple options are specified in the same argv-argument, the returned\nvalue is unspecified.  This matches the variable \"OPTIND\" from the POSIX\nstandard, but is read-only.  (If you want to reset OPTIND, you must create a new\nBasicParser instance.)  This is most useful after parsing has finished to\nexamine the non-option arguments.\n\nThis value starts at \"2\" as described under \"Departures from POSIX\" below.\n\n\n### `parser.getopt()`\n\nReturns the next argument specified in \"argv\" (the object's constructor\nargument).  The returned value is either undefined or an object with at least\nthe following members:\n\n\toption\t\tsingle-character option name\n\nThe following members may also be present:\n\n\toptarg\t\targument value, if any\n\n\toptopt\t\toption character that caused the error, if any\n\n\terror\t\tif true, this object represents an error\n\nThis function scans \"argv\" starting at the current value of \"optind\" and returns\nan object describing the next argument based on the following cases:\n\n    o If the end of command line arguments is reached, an undefined value is\n      returned.  The end of arguments is signified by a single '-' argument, a\n      single '--' argument, an argument that's neither an option nor a previous\n      option's argument, the end of argv, or an error.\n\n    o If an unrecognized command line option is found (i.e. an option character\n      not defined in \"optstring\"), the returned object's \"option\" member\n      is just \"?\".  \"optopt\" is set to the unrecognized option letter.  \"error\"\n      is set to a true value.\n\n    o If a known command line option is found and the option takes no arguments\n      then the returned object's \"option\" member is the option's short name\n      (i.e.  the single character specifier in \"optstring\").\n      \n    o If a known command line option is found and that option takes an argument\n      and the argument is also found, then the returned object's \"option\"\n      member is the option's short name and the \"optarg\" member contains the\n      argument's value.\n\n    o If a known command line option is found and that option takes an argument\n      but the argument is not found, then the returned object's \"option\" member\n      is \"?\" unless the first character of \"optstring\" was a colon, in which\n      case the \"option\" member is set to \":\".  Either way, the \"optopt\" member\n      is set to the option character that caused the error and \"error\" is set to\n      a true value.\n\n\nDepartures from POSIX\n--------\n\n    o Global state in the C implementation (e.g., optind, optarg, and optopt) is\n      encapsulated in the BasicParser object.  optind is available as a method\n      call on the parser object.  optarg and optopt are returned directly by\n      getopt().\n\n    o Rather than returning an integer or character, getopt() returns an object\n      with the \"option\" field corresponding to the processed option character\n      and possibly the additional \"optarg\" and \"optopt\" fields.  If an error\n      occurs on a particular option, \"error\" is also set.  If an error occurs on\n      no particular option or if the end of input is encountered, undefined is\n      returned.\n\n    o Long option forms are supported as described above.  This introduces an\n      additional error case which is where an argument of the form\n      --option=value is encountered, where \"option\" does not take a value.\n\n    o POSIX starts \"optind\" at 1, since argv[0] is generally the name of the\n      command and options start at argv[1].  This implementation starts \"optind\"\n      at 2, since argv[0] is generally the path to the node binary and argv[1]\n      is the path to the script, so options start with argv[2].\n\n\nExamples\n--------\n\n### Example 1: simple short options\n\n\tvar mod_getopt = require('getopt')\n\tvar parser, option;\n\t\n\tparser = new mod_getopt.BasicParser('la',\n\t    ['node', 'script', '-l', '-a', 'stuff']);\n\twhile ((option = parser.getopt()) !== undefined && !option.error)\n\t\tconsole.error(option);\n\n### Example 2: invalid option specified\n\n\tvar mod_getopt = require('getopt')\n\tvar parser, option;\n\t\n\tparser = new mod_getopt.BasicParser('la',\n\t    ['node', 'script', '-l', '-b', 'stuff']);\n\twhile ((option = parser.getopt()) !== undefined && !option.error)\n\t\tconsole.error(option);\n\tconsole.error(option);\n\n### Example 3: long options\n\n\tvar mod_getopt = require('getopt')\n\tvar parser, option;\n\t\n\tparser = new mod_getopt.BasicParser('lar(recurse)',\n\t    ['node', 'script', '-l', '--recurse', 'stuff']);\n\twhile ((option = parser.getopt()) !== undefined && !option.error)\n\t\tconsole.error(option);\n\n### Example 4: options with arguments\n\n\tvar mod_getopt = require('getopt')\n\tvar parser, option;\n\t\n\tparser = new mod_getopt.BasicParser('f:lad:',\n\t    ['node', 'script', '-l', '-f', 'filename', '-dtype', 'stuff']);\n\twhile ((option = parser.getopt()) !== undefined && !option.error)\n\t\tconsole.error(option);\n\n### Example 5: options with missing arguments\n\n\tvar mod_getopt = require('getopt')\n\tvar parser, option;\n\t\n\tparser = new mod_getopt.BasicParser('f:la',\n\t    ['node', 'script', '-l', '-a', '-f']);\n\twhile ((option = parser.getopt()) !== undefined && !option.error)\n\t\tconsole.error(option);\n\tconsole.error(option);\n\n### Example 6: options specified multiple times\n\n\tvar mod_getopt = require('getopt')\n\tvar parser, option;\n\t\n\tparser = new mod_getopt.BasicParser('la',\n\t    ['node', 'script', '-l', '-a', '-l']);\n\twhile ((option = parser.getopt()) !== undefined && !option.error)\n\t\tconsole.error(option);\n",
+  "readmeFilename": "README.md",
+  "_id": "posix-getopt@0.0.1",
+  "_from": "posix-getopt@~0.0.1"
+}
--- /dev/null	2013-10-21 19:08:27.000000000 +0000
+++ new/src/node-lockfd/node_modules/v8plus/node_modules/posix-getopt/tests/test-getopt.js	2013-10-21 19:08:27.582850058 +0000
@@ -0,0 +1,71 @@
+/*
+ * Tests getopt() itself.
+ */
+var mod_path = require('path');
+require.paths.unshift(mod_path.dirname(__dirname) + '/lib');
+
+var mod_sys = require('sys');
+var mod_getopt = require('getopt');
+var mod_assert = require('assert');
+
+var test_cases = [ {
+	optstr: '',
+	argv: [],
+	result: []
+}, {
+	optstr: ':',
+	argv: [],
+	result: []
+}, {
+	optstr: ':l',
+	argv: [],
+	result: []
+}, {
+	optstr: ':l:',
+	argv: [],
+	result: []
+}, {
+	optstr: ':las',
+	argv: [],
+	result: []
+}, {
+	optstr: ':l:a:s:',
+	argv: [],
+	result: []
+}, {
+	optstr: ':l(long)',
+	argv: [],
+	result: []
+}, {
+	optstr: ':l:(long)',
+	argv: ['cmd', 'script', '-l', 'arg1', '--long=q', 'b', '--long', 'foo'],
+	result: [
+	    { option: 'l', optarg: 'arg1' },
+	    { option: 'l', optarg: 'q' }
+	]
+}, {
+	optstr: 'l:(long)(longer)',
+	argv: [],
+	result: []
+}, {
+	optstr: ':la:r(recurse)(recur)f:(file)(filename)q',
+	argv: [],
+	result: []
+} ];
+
+var parser, ii, arg, result;
+for (ii = 0; ii < test_cases.length; ii++) {
+	console.log('test case %s: "%s" with argv = "%s"', ii + 1,
+	    test_cases[ii].optstr, test_cases[ii].argv);
+	parser = new mod_getopt.BasicParser(test_cases[ii].optstr,
+	    test_cases[ii].argv);
+	console.log(parser.gop_tokens);
+
+	result = [];
+	while ((arg = parser.getopt()) !== undefined)
+		result.push(arg);
+
+	mod_assert.deepEqual(test_cases[ii].result, result);
+}
+
+console.log('%s test cases passed', test_cases.length);
--- /dev/null	2013-10-21 19:08:27.000000000 +0000
+++ new/src/node-lockfd/node_modules/v8plus/node_modules/posix-getopt/tests/test-tokenize-optstr.js	2013-10-21 19:08:27.705548350 +0000
@@ -0,0 +1,74 @@
+/*
+ * Tests internal state of the parser.
+ */
+var mod_path = require('path');
+require.paths.unshift(mod_path.dirname(__dirname) + '/lib');
+
+var mod_sys = require('sys');
+var mod_getopt = require('getopt');
+var mod_assert = require('assert');
+
+var test_cases = [ {
+	optstr: '',
+	silent: false,
+	options: {},
+	aliases: {},
+}, {
+	optstr: ':',
+	silent: true,
+	options: {},
+	aliases: {},
+}, {
+	optstr: ':l',
+	silent: true,
+	options: { l: false },
+	aliases: {},
+}, {
+	optstr: ':l:',
+	silent: true,
+	options: { l: true },
+	aliases: {},
+}, {
+	optstr: ':las',
+	silent: true,
+	options: { l: false, a: false, s: false },
+	aliases: {},
+}, {
+	optstr: ':l:a:s:',
+	silent: true,
+	options: { l: true, a: true, s: true },
+	aliases: {},
+}, {
+	optstr: ':l(long)',
+	silent: true,
+	options: { l: false },
+	aliases: { long: 'l' },
+}, {
+	optstr: ':l:(long)',
+	silent: true,
+	options: { l: true },
+	aliases: { long: 'l' },
+}, {
+	optstr: 'l:(long)(longer)',
+	silent: false,
+	options: { l: true },
+	aliases: { long: 'l', longer: 'l' },
+}, {
+	optstr: ':la:r(recurse)(recur)f:(file)(filename)q',
+	silent: true,
+	options: { l: false, a: true, r: false, f: true, q: false },
+	aliases: { recurse: 'r', recur: 'r', file: 'f', filename: 'f' }
+} ];
+
+var parser, ii;
+for (ii = 0; ii < test_cases.length; ii++) {
+	console.log('test case %s: "%s"', ii + 1, test_cases[ii].optstr);
+	parser = new mod_getopt.BasicParser(test_cases[ii].optstr, []);
+	mod_assert.ok(test_cases[ii].silent === parser.gop_silent);
+	mod_assert.deepEqual(test_cases[ii].options,
+	    parser.gop_options);
+	mod_assert.deepEqual(test_cases[ii].aliases,
+	    parser.gop_aliases);
+}
+
+console.log('%s test cases passed', test_cases.length);
--- /dev/null	2013-10-21 19:08:27.000000000 +0000
+++ new/src/node-lockfd/node_modules/v8plus/origin.js	2013-10-21 19:08:27.835463378 +0000
@@ -0,0 +1,7 @@
+/*
+ * This is not a real module.  All it does when require()'d is spew the
+ * location of v8+'s base directory.  This is used by the makefiles so
+ * that consumers don't have to set $(V8PLUS) manually, and allows npm to
+ * install v8plus anywhere in node_modules.
+ */
+console.log(__dirname);
--- /dev/null	2013-10-21 19:08:28.000000000 +0000
+++ new/src/node-lockfd/node_modules/v8plus/package.json	2013-10-21 19:08:27.988731852 +0000
@@ -0,0 +1,30 @@
+{
+  "author": {
+    "name": "Keith M Wesolowski",
+    "email": "keith.wesolowski@joyent.com"
+  },
+  "name": "v8plus",
+  "description": "utility environment for writing addons in C",
+  "version": "0.1.0",
+  "contributors": [
+    {
+      "name": "Joshua M. Clulow",
+      "email": "jmc@joyent.com"
+    }
+  ],
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/joyent/v8plus.git"
+  },
+  "bugs": {
+    "url": "http://github.com/joyent/v8plus/issues"
+  },
+  "dependencies": {
+    "posix-getopt": "~0.0.1"
+  },
+  "main": "origin.js",
+  "readme": "# v8+: Node.js addon C++ to C boundary layer\n\nThis layer offers a way to write at least simple Node.js addons in C without\nall the horrible C++ goop you'd otherwise be expected to use.  That goop\nstill exists, but you don't have to write it.  More importantly, you can\nwrite your module in a sane programming environment, avoiding the confusing\nand error-prone C++ semantics.\n\n## Usage\n\nUnlike most Node.js modules, v8+ does nothing by itself.  It is intended to\nbe used as a build-time dependency of your native addon, providing you with\nan alternate programming environment.\n\nFor full docs, read the source code.\n\n## Node.js Support\n\nv8+ works with, and has been tested to some extent with, Node.js 0.6.18 and\n0.8.1.  It most likely works with other micro versions in the 0.6 and 0.8\nseries as well.  Note that this does not mean you can necessarily expect an\naddon built against a particular minor release of Node.js to work with any\nother minor release of Node.js.\n\n## Building and Installing\n\nThe v8+ source code is compiled into your module directly along with your\ncode.  There is no separate v8+ library or node module, so the v8+ source,\ntools, and makefiles are required to be present at the time your module is\nbuilt.  They are not required at runtime.\n\nNormally, your addon module will depend on the v8plus package and install it\nusing npm.  The v8+ makefiles are set up to accommodate the installation of\nv8+ anywhere `node(1)` would be able to find it using `require()` if it were\na normal JavaScript module, so simply including it as a dependency in your\n`package.json` will work correctly.  In addition, you will need to create a\n(normally trivial) makefile for your module that includes the makefiles\ndistributed as part of v8+.  Once you have done so, it is sufficient to run\n`gmake` to generate the native loadable module used by Node.js.\n\nThe overall outline for creating a v8+ module looks something like this:\n\n1. Write the C code that does whatever your module does.  Be sure to\n\\#include \"v8plus_glue.h\".  Do not include any other v8+ headers.\n\n2. Create an appropriate `package.json` file.  See below for details.\n\n3. Create a skeleton makefile.  See below for details.\n\n4. Create a JSON file defining the error codes your module will use.  See\nErrors below.\n\nYou should not (and need not) modify either of the delivered makefiles;\noverride the definitions in Makefile.v8plus.defs in your makefile as\nappropriate.\n\n### Packaging Considerations\n\nThere are two essential properties your `package.json` must contain in order\nto use v8+ with npm:\n\n1. A dependency on `v8plus`.\n\n2. An appropriate script entry for building your module.  It is strongly\n   recommended that you use something like the following:\n\n        \"postinstall\": \"gmake $(eval echo ${MAKE_OVERRIDES})\"\n\nThis will allow someone building your module to set make variables by adding\nthem to the `MAKE_OVERRIDES` environment variable; e.g.,\n\n        $ MAKE_OVERRIDES=\"CTFCONVERT=/bin/true CTFMERGE=/bin/true\" npm install\n\n### Tying into the Makefiles\n\nThe makefiles shipped with v8+ do the great majority of the heavy lifting\nfor you.  A minimally functional makefile for your addon must contain four\nthings:\n\n1. Variable definitions for `V8PLUS` and `PREFIX_NODE`.  Alternately, you\n   may choose to provide these on the command line or via the environment.\n   It is recommended that these assignments be made exactly as follows,\n   which will cause the addon to be built against the `node` that is found\n   first in your path:\n\n        PREFIX_NODE := $(shell dirname `bash -c 'hash node; hash -t node'`)/..\n        V8PLUS :=      $(shell $(PREFIX_NODE)/bin/node -e 'require(\"v8plus\");')\n\n   Note that the mechanism for finding `node` will not work correctly if\n   yours is a symlink.  This invocation of node(1) uses a v8+ mechanism to\n   locate v8+ sources anywhere that node(1) can find them and should not be\n   modified unless you want to test an alternate v8+.\n\n2. The exact line:\n\n        include $(V8PLUS)/Makefile.v8plus.defs\n\n3. Variable assignments specific to your module.  In particular, you must\n   define `SRCS`, `MODULE`, and `ERRNO_JSON`.  Additional customisation is\n   optional.\n\n4. The exact line:\n\n        include $(V8PLUS)/Makefile.v8plus.targ\n\nAdditional arbitrary customisation is possible using standard makefile\nsyntax; most things that are useful to change already have variables defined\nin `Makefile.v8plus.defs` whose values you may append to or override.  For\nexample, you may cause additional system libraries to be linked in by\nappending `-lname` to the `LIBS` variable.  By default, the makefiles assume\nthat your sources are located in the `src` subdirectory of your module, and\nthat you want the sole output of the build process to be called\n`$(MODULE).node` and located in the `lib` subdirectory.  This can be changed\nby overriding the `MODULE_DIR` variable.\n\nA simple example makefile may be found in the `examples/` subdirectory, and\nadditional examples may be found in existing consumers; see Consumers below.\nThe GNU people also provide a good manual for make if you get really stuck;\nsee <http://www.gnu.org/software/make/manual/make.html>.  In general,\nwriting the necessary makefile fragment is expected to be as easy as or\neasier than the equivalent task using `node-waf` or `node-gyp`, so if you're\nfinding it unexpectedly difficult or complicated there's probably an easier\nway.\n\nThe makefiles follow GNU make syntax; other makes may not work but patches\nthat correct this are generally welcome (in particular, Sun make and GNU\nmake have different and incompatible ways to set a variable from the output\nof a shell command, and there is no way I know to accommodate both).\n\n### Binary Interface\n\nBy default, the resulting object is linked with the `-zdefs` option, which\nwill cause the build to fail if any unresolved symbols remain.  In order to\naccommodate this, a mapfile specifying the available global symbols in your\n`node` binary is automatically generated as part of the build process.  This\nmakes it much easier to debug missing libraries; otherwise, a module with\nunresolved symbols will fail to load at runtime with no useful explanation.\nMapfile generation probably works only on illumos-derived systems.  Patches\nthat add support for other linkers are welcome.\n\nYour module will have all symbols (other than `init`, which is used directly\nby Node.js) reduced to local visibility, which is strongly recommended.  If\nfor some reason you want your module's symbols to be visible to Node.js or\nto other modules, you will have to modify the script that generates the\nmapfile.  See the `$(MAPFILE)` target in `Makefile.v8plus.targ`.\n\n## API\n\nYour module is an object factory that instantiates and returns native\nobjects, to which a fixed set of methods is attached as properties.  The\nconstructor, destructor, and methods all correspond 1-1 with C functions.\nIn addition, you may create additional class methods associated with the\nnative module itself, each of which will also have a 1-1 relationship to a\nset of C functions.\n\nThis functionality is generally sufficient to interface with the system in\nuseful ways, but it is by no means exhaustive.  Architectural limitations\nare noted throughout the documentation.\n\nSubsequent sections describe the API in greater detail, along with most of\nthe C functions that v8+ provides.  Some utility functions may not be listed\nhere; see `v8plus_glue.h` for additional commentary and functions that are\navailable to you.\n\n### Constructors, Methods, and Functions\n\nThe interface between your module and v8+ consists of a handful of objects\nwith fixed types and names.  These are:\n\n\tconst v8plus_c_ctor_f v8plus_ctor = my_ctor;\n\tconst v8plus_c_dtor_f v8plus_dtor = my_dtor;\n\tconst char *v8plus_js_factory_name = \"_new\";\n\tconst char *v8plus_js_class_name = \"MyObjectBinding\";\n\tconst v8plus_method_descr_t v8plus_methods[] = {\n\t        {\n\t                md_name: \"_my_method\",\n\t                md_c_func: my_method\n\t        },\n\t\t...\n\t};\n\tconst uint_t v8plus_method_count =\n\t    sizeof (v8plus_methods) / sizeof (v8plus_methods[0]);\n\n\tconst v8plus_static_descr_t v8plus_static_methods[] = {\n\t        {\n\t                sd_name: \"_my_function\",\n\t                sd_c_func: my_function\n\t        },\n\t\t...\n\t};\n\tconst uint_t v8plus_static_method_count =\n\t    sizeof (v8plus_static_methods) / sizeof (v8plus_static_methods[0]);\n\nAll of these must be present even if they have zero length or are NULL.  The\nprototypes and semantics of each function type are as follows:\n\n### nvlist_t *v8plus_c_ctor_f(const nvlist_t *ap, void **opp)\n\nThe constructor is responsible for creating the C object corresponding to\nthe native JavaScript object being created.  It is not a true constructor in\nthat you are actually an object factory; the C++ function associated with\nthe JavaScript constructor is called for you.  Your encoded arguments are in\n`ap`.  Allocate and populate a C object, stuff it into `*opp`, and return\n`v8plus_void()`.  If you need to throw an exception you can do so by\nreturning `v8plus_error()` or one of its wrappers, or by setting\n`_v8plus_errno` using one of those functions and then returning an nvlist\nwith an `err` member representing a decorated exception.\n\n### void v8plus_c_dtor_f(void *op)\n\nFree the C object `op` and anything else associated with it.  Your object is\ngoing away.  This function may be empty if the constructor did not allocate\nany memory (i.e., `op` is not a pointer to dynamically allocated memory).\n\n### nvlist_t *v8plus_c_method_f(void *op, const nvlist_t *ap)\n\nWhen the JavaScript method is called in the context of your object, the\ncorresponding C function is invoked.  `op` is the C object associated with\nthe JavaScript object, and `ap` is the encoded list of arguments to the\nfunction.  Return an encoded object with a `res` member, or use one of the\nerror/exception patterns.\n\n### nvlist_t *v8plus_c_static_method_f(const nvlist_t *ap)\n\nIn addition to methods on the native objects returned by your constructor,\nyou can also provide a set of functions on the native binding object itself.\nThis may be useful for providing bindings to libraries for which no object\nrepresentation makes sense, or that have functions that operate outside the\ncontext of any particular object.  Your arguments are once again encoded in\n`ap`, and your return values are an object containing `res` or an error.\n\n### Argument Handling\n\nWhen JavaScript objects cross the boundary from C++ to C, they are converted\nfrom v8 C++ objects into C nvlists.  This means that they are effectively\npassed by value, unlike in JavaScript or in native addons written in C++.\nThe arguments to the JavaScript function are treated as an array and\nmarshalled into a single nvlist whose properties are named \"0\", \"1\", and so\non.  Each such property is encoded as follows:\n\n- numbers and Number objects (regardless of size): double\n- strings and String objects: UTF-8 encoded C string\n- booleans and Boolean objects: boolean_value\n- undefined: boolean\n- null: byte, value 0\n- Objects, including Arrays: nvlist with own properties as members and the\nmember \".__v8plus_type\" set to the object's JavaScript type name.  Note\nthat the member name itself begins with a . to reduce the likelihood of a\ncollision with an actual JavaScript member name.\n- JavaScript Functions are passed in a format suitable for use with\n  `nvlist_lookup_jsfunc()` and `v8plus_args()` with the V8PLUS_TYPE_JSFUNC\n  token.  This type is restricted; see below.\n\nBecause JavaScript arrays may be sparse, we cannot use the libnvpair array\ntypes.  Consider them reserved for internal use.  JavaScript Arrays are\nrepresented as they really are in JavaScript: objects with properties whose\nnames happen to be integers.\n\nOther data types cannot be represented and will result in a TypeError\nbeing thrown.  If your object has methods that need other argument types,\nyou cannot use v8+.\n\nSide effects within the VM, including modification of the arguments, are\nnot supported.  If you need them, you cannot use v8+.\n\nWhile the standard libnvpair functions may be used to inspect the arguments\nto a method or function, v8+ also provides the `v8plus_args()` and\n`v8plus_typeof()` convenience functions, which simplify checking the types\nand obtaining the values of arguments.\n\n### int v8plus_args(const nvlist_t *lp, uint_t flags, v8plus_type_t t, ...)\n\nThis function checks `lp` for the exact sequence of arguments specified by\nthe list of types provided in the parameter list.  If `V8PLUS_ARG_F_NOEXTRA`\nis set in `flags`, the list of arguments must match exactly, with no\nadditional arguments.  The parameter list must be terminated by\n`V8PLUS_TYPE_NONE`.\n\nFollowing `flags` is a list of argument data types and, for most data types,\npointers to locations at which the native C value of that argument should be\nstored.  The following JavaScript argument data types are supported; for\neach, the parameter immediately following the data type parameter must be of\nthe indicated C type.  This parameter may be `NULL`, in which case the value\nwill not be stored anywhere.\n\n- V8PLUS_TYPE_NONE: used to terminate the parameter list only\n- V8PLUS_TYPE_STRING: char **\n- V8PLUS_TYPE_NUMBER: double *\n- V8PLUS_TYPE_BOOLEAN: boolean_t *\n- V8PLUS_TYPE_JSFUNC: v8plus_jsfunc_t *\n- V8PLUS_TYPE_OBJECT: nvlist_t **\n- V8PLUS_TYPE_NULL: no parameter\n- V8PLUS_TYPE_UNDEFINED: no parameter\n- V8PLUS_TYPE_INVALID: data_type_t (see below)\n- V8PLUS_TYPE_ANY: nvpair_t **\n- V8PLUS_TYPE_STRNUMBER64: uint64_t *\n- V8PLUS_TYPE_INL_OBJECT: illegal\n\nIn most cases, the behaviour is straightforward: the value pointer parameter\nprovides a location into which the C value of the specified argument should\nbe stored.  If the entire argument list matches the template, each\nargument's C value is stored in its respective location.  If not, no values\nare stored, in the return value locations, `_v8plus_errno` is set\nappropriately, and -1 is returned.\n\nThree data types warrant further explanation: an argument of type\n`V8PLUS_TYPE_INVALID` is any argument that may or may not match one of the\nacceptable types.  Its nvpair data type tag is stored and the argument\ntreated as matching.  The value is ignored.  `V8PLUS_TYPE_STRNUMBER64` is\nused with strings that should be interpreted as 64-bit unsigned integers.\nIf the argument is not a string, or is not parseable as a 64-bit unsigned\ninteger, the argument will be treated as a mismatch.  Finally,\n`V8PLUS_TYPE_INL_OBJECT` is not supported with `v8plus_args()`; JavaScript\nobjects in the argument list must be individually inspected as nvlists.\n\nA simple example:\n\n\tdouble_t d;\n\tboolean_t b;\n\tchar *s;\n\tv8plus_jsfunc_t f;\n\n\t/*\n\t * This function requires exactly four arguments: a number, a\n\t * boolean, a string, and a callback function.  It is not acceptable\n\t * to pass superfluous arguments to it.\n\t */\n\tif (v8plus_args(ap, V8PLUS_ARG_F_NOEXTRA,\n\t    V8PLUS_TYPE_NUMBER, &d,\n\t    V8PLUS_TYPE_BOOLEAN, &b,\n\t    V8PLUS_TYPE_STRING, &s,\n\t    V8PLUS_TYPE_JSFUNC, &f,\n\t    V8PLUS_TYPE_NONE) != 0)\n\t\treturn (NULL);\n\n### v8plus_type_t v8plus_typeof(const nvpair_t *pp)\n\nThis function simply returns the v8+ data type corresponding to the\nname/value pair `pp`.  If the value's type does not match the v8+ encoding\nrules, `V8PLUS_TYPE_INVALID` is returned.  This function cannot fail and\ndoes not modify `_v8plus_errno`.\n\n### Returning Values\n\nSimilarly, when returning data across the boundary from C to C++, a\npointer to an nvlist must be returned.  This object will be decoded in\nthe same manner as described above and returned to the JavaScript caller\nof your method.  Note that booleans, strings, and numbers will be encoded\nas their primitive types, not objects.  If you need to return something\ncontaining these object types, you cannot use v8+.  Other data types\ncannot be represented.  If you need to return them, you cannot use v8+.\n\nThe nvlist being returned must have one of two members: \"res\", an nvpair\ncontaining the result of the call to be returned, or \"err\", an nvlist\ncontaining members to be added to an exception.  You may return a value of\nany decodable type, and likewise may decorate an exception with properties\nof any decodable type.\n\nFor convenience, you may return v8plus_void() instead of an nvlist,\nwhich indicates successful execution of a function that returns nothing.\n\nIn addition, the `v8plus_obj()` routine is available for instantiating\nJavaScript objects to return.\n\n### nvlist_t *v8plus_void(void)\n\nThis function clears `_v8plus_errno` and returns NULL.  This is used to\nindicate to internal v8+ code that the method or function should not return\na value.\n\n### nvlist_t *v8plus_obj(v8plus_type_t t, ...)\n\nThis function creates and populates an nvlist conforming to the encoding\nrules of v8+ for returning a value or creating an exception.  It can be used\nto create anything from a single encoded value to arbitrarily nested\nobjects.  It is essentially the inverse of `v8plus_args()` above, with a few\ndifferences:\n\n- It cannot be used to encode invalid or illegal data types.\n- It accepts native C values, not pointers to them.\n- Each value must be named.\n- It can be used to encode nested objects inline using\n  `V8PLUS_TYPE_INL_OBJECT`, followed by type, name, value triples,\n  terminated with `V8PLUS_TYPE_NONE`.\n\nThis function can fail due to out-of-memory conditions, invalid or\nunsupported data types, or, most commonly, programmer error in casting the\narguments to the correct type.  *It is extremely important that data values,\nparticularly integers, be cast to the appropriate type (double) when passed\ninto this function!*\n\nFollowing is a list of types and the C data types corresponding to their\nvalues:\n\n- V8PLUS_TYPE_NONE: used to terminate the parameter list only\n- V8PLUS_TYPE_STRING: char *\n- V8PLUS_TYPE_NUMBER: double\n- V8PLUS_TYPE_BOOLEAN: boolean_t\n- V8PLUS_TYPE_JSFUNC: v8plus_jsfunc_t\n- V8PLUS_TYPE_OBJECT: nvlist_t *\n- V8PLUS_TYPE_NULL: no parameter\n- V8PLUS_TYPE_UNDEFINED: no parameter\n- V8PLUS_TYPE_ANY: nvpair_t *\n- V8PLUS_TYPE_STRNUMBER64: uint64_t\n- V8PLUS_TYPE_INL_OBJECT: NONE-terminated type/value list\n\nA simple example, in which we return a JavaScript object with two members,\none number and one embedded object with a 64-bit integer property.  Note\nthat if this function fails, we will return `NULL` with `_v8plus_errno` set\nappropriately, so v8+ will generate and throw an appropriate exception.\n\n\tint x;\n\tconst char *s;\n\n\t...\n\treturn (v8plus_obj(\n\t    V8PLUS_TYPE_INL_OBJECT, \"res\",\n\t\tV8PLUS_TYPE_NUMBER, \"value\", (double)x,\n\t\tV8PLUS_TYPE_INL_OBJECT, \"detail\",\n\t\t    V8PLUS_TYPE_STRNUMBER64, \"value64\", s,\n\t\t    V8PLUS_TYPE_NONE,\n\t\tV8PLUS_TYPE_NONE,\n\t    V8PLUS_TYPE_NONE));\n\nThe JSON representation of this object would be:\n\n\t{\n\t\t\"res\": {\n\t\t\t\"value\": <x>,\n\t\t\t\"detail\": {\n\t\t\t\t\"value64\": \"<s>\"\n\t\t\t}\n\t\t}\n\t}\n\n### v8plus_obj_setprops(nvlist_t *lp, v8plus_type_t t, ...)\n\nYou can also add or replace the values of properties in an existing nvlist,\nwhether created using `nvlist_alloc()` directly or via `v8plus_obj()`.  The\neffect is very similar to `nvlist_merge()`, where the second list is created\non the fly from your argument list.  The interpretation of the argument list\nis the same as for `v8plus_obj()`, and the two functions are implemented\nusing the same logic.\n\n### Exceptions\n\nIf you are unable to create an nvlist to hold exception data, or you want a\ngeneric exception to be thrown, return the value returned by v8plus_error().\nIn this case, the error code will be translated to an exception type and the\nmessage string will be used as the message member of the exception.  Other\nmembers will not be present in the exception unless you also return an\nnvlist containing an 'err' member (or, from a constructor, any nvlist) Only\nbasic v8-provided exception types can be thrown; if your addon needs to\nthrow some other kind of exception, you will need to either use v8 directly\nor catch and re-throw from a JavaScript wrapper.\n\n## Errors\n\nThe v8plus_errno_t enumerated type and a family of utility functions are\nautomatically generated by generrno.js from a simple JSON file.  The schema\nof this file is as follows:\n\n\t{\n\t\t\"error_base\": <string>,\n\t\t\"errors\": [\n\t\t{\n\t\t\t\"code\": <string>,\n\t\t\t\"msg\": <string>,\n\t\t\t\"exception\": <string>\n\t\t},\n\t\t...  ]\n\t}\n\nFor each entry in the errors array, an identifier V8PLUSERR_code will be\nadded to v8plus_errno_t.  By convention, code should be all upper case.  The\ndefault error message (present in JavaScript exceptions if a more specific\nerror message is not provided to v8plus_error()) is given by the msg\nproperty.  The exception property must be one of \"Error\", \"TypeError\",\n\"ReferenceError\", \"RangeError\", or \"SyntaxError\"; i.e., the standard\nexception types available in v8.  This is the type of exception that will be\ngenerated and thrown when a C function returns NULL with this error code\nset.  In addition, the built-in error codes V8PLUSERR_NOMEM,\nV8PLUSERR_YOUSUCK, and V8PLUSERR_UNKNOWN are available for your use,\nindicating an out of memory condition, programmer error (e.g., failure of\nsomething you would assert in JavaScript), and an error code that cannot be\ntranslated, respectively.\n\nSet the make variable ERRNO_JSON to the name of this file.\n\nTo set the value of `_v8plus_errno`, use one of the following functions.  It\nis a bug to manipulate this variable directly.\n\n### nvlist_t *v8plus_verror(v8plus_errno_t e, const char *fmt, va_list)\n\nThis is the varargs analogue to `v8plus_error()` and has identical\nsemantics.  Use this if you want to wrap manipulation of the v8+ error state\nwithin your own varargs functions.\n\n### nvlist_t *v8plus_error(v8plus_errno_t e, const char *fmt, ...)\n\nThis function sets the value of `_v8plus_errno` to `e` and sets the\nassociated error message string to the formatted string `fmt` using the\nargument list that follows.  The format string and arguments are interpreted\nas by `vsnprintf(3c)`.  NULL is returned, suitable for returning directly\nfrom a C function that provides a method if no exception decoration is\nrequired.\n\nIf `fmt` is NULL, a generic default message is used; for consumer-defined\nerror codes, that message is the one provided in `errno.json`.\n\n### nvlist_t *v8plus_nverr(int errno, const char *propname)\n\nThis function sets the value of `_v8plus_errno` to a value mapped from the\nsystem error code `errno` and sets the error message to a non-localised\nexplanation of the problem.  The string `propname`, if non-NULL, is\nindicated in the message as the name of the nvlist property being\nmanipulated when the error occurred.  NULL is returned.\n\n### nvlist_t *v8plus_syserr(int errno, const char *fmt, ...)\n\nAnalogous to `v8plus_error()`, this function instead sets the error code to\na mapped value derived from the system error code `errno`.  Not all error\ncodes can be mapped; those that are not known are mapped onto\n`V8PLUSERR_UNKNOWN`.  This function's semantics are otherwise identical to\nthose of `v8plus_error()`.\n\n### void v8plus_panic(const char *fmt, ...) __NORETURN\n\nThis function indicates a fatal runtime error.  The format string `fmt` and\nsubsequent arguments are interpreted as by `vsnprintf(3c)` and written to\nstandard error, which is then flushed.  `abort(3c)` or similar is then\ninvoked to terminate the Node.js process in which the addon is running.  Use\nof this function should be limited to those circumstances in which an\ninternal inconsistency has been detected that renders further progress\nhazardous to user data or impossible.\n\n### Asynchrony\n\nThere are two main types of asynchrony supported by v8+.  The first is the\ndeferred work model (using `uv_queue_work()` or the deprecated\n`eio_custom()` mechanisms) frequently written about and demonstrated by\nvarious practitioners around the world.  In this model, your method or\nfunction takes a callback argument and returns immediately after enqueuing a\ntask to run on one of the threads in the Node.js worker thread pool.  That\ntask consists of a C function to be run on the worker thread, which may not\nuse any V8 (or v8+) state, and a function to be run in the main event loop\nthread when that task has completed.  The latter function is normally\nexpected to invoke the caller's original callback.  In v8+, this takes the\nfollowing form:\n\n\tvoid *\n\tasync_worker(void *cop, void *ctxp)\n\t{\n\t\tmy_object_t *op = cop;\n\t\tmy_context_t *cp = ctxp;\n\t\tmy_result_t *rp = ...;\n\n\t\t/*\n\t\t * In thread pool context -- do not call any of the\n\t\t * following functions:\n\t\t * v8plus_obj_hold()\n\t\t * v8plus_obj_rele_direct()\n\t\t * v8plus_jsfunc_hold()\n\t\t * v8plus_jsfunc_rele_direct()\n\t\t * v8plus_call_direct()\n\t\t * v8plus_method_call_direct()\n\t\t * v8plus_defer()\n\t\t *\n\t\t * If you touch anything inside op, you may need locking to\n\t\t * protect against functions called in the main thread.\n\t\t */\n\t\t...\n\n\t\treturn (rp);\n\t}\n\n\tvoid\n\tasync_completion(void *cop, void *ctxp, void *resp)\n\t{\n\t\tmy_object_t *op = cop;\n\t\tmy_context_t *cp = ctxp;\n\t\tmy_result_t *rp = resp;\n\t\tnvlist_t *cbap;\n\t\tnvlist_t *cbrp;\n\n\t\t...\n\t\tcbap = v8plus_obj(\n\t\t    V8PLUS_TYPE_WHATEVER, \"0\", rp->mr_value,\n\t\t    V8PLUS_TYPE_NONE);\n\n\t\tif (cbap != NULL) {\n\t\t\tcbrp = v8plus_call(cp->mc_callback, cbap);\n\t\t\tnvlist_free(cbap);\n\t\t\tnvlist_free(cbrp);\n\t\t}\n\n\t\tv8plus_jsfunc_rele(cp->mc_callback);\n\t\tfree(cp);\n\t\tfree(rp);\n\t}\n\n\tnvlist_t *\n\tasync(void *cop, const nvlist_t *ap)\n\t{\n\t\tmy_object_t *op = cop;\n\t\tv8plus_jsfunc_t cb;\n\t\tmy_context_t *cp = malloc(sizeof (my_context_t));\n\t\t...\n\t\tif (v8plus_args(ap, 0, V8PLUS_TYPE_JSFUNC, &cb,\n\t\t    V8PLUS_TYPE_NONE) != 0) {\n\t\t\tfree(cp);\n\t\t\treturn (NULL);\n\t\t}\n\n\t\tv8plus_jsfunc_hold(cb);\n\t\tcp->mc_callback = cb;\n\t\tv8plus_defer(op, cp, async_worker, async_completion);\n\n\t\treturn (v8plus_void());\n\t}\n\nThis mechanism uses `uv_queue_work()` and as such will tie up one of the\nworker threads in the pool for as long as `async_worker` is running.\n\nThe other asynchronous mechanism is the Node.js `EventEmitter` model.  This\nmodel requires some assistance from JavaScript code, because v8+ native\nobjects do not inherit from `EventEmitter`.  To make this work, you will\nneed to create a JavaScript object (the object your consumers actually use)\nthat inherits from `EventEmitter`, hang your native object off this object,\nand populate the native object with an appropriate method that will cause\nthe JavaScript object to emit events when the native object invokes that\nmethod.  A simple example might look like this:\n\n\tvar util = require('util');\n\tvar binding = require('./native_binding');\n\tvar events = require('events');\n\n\tfunction\n\tMyObjectWrapper()\n\t{\n\t\tvar self = this;\n\n\t\tevents.EventEmitter.call(this);\n\t\tthis._native = binding._create.apply(this,\n\t\t    Array.prototype.slice.call(arguments));\n\t\tthis._native._emit = function () {\n\t\t\tvar args = Array.prototype.slice.call(arguments);\n\t\t\tself.emit.apply(self, args);\n\t\t};\n\t}\n\tutil.inherits(MyObjectWrapper, events.EventEmitter);\n\nThen, in C code, you must arrange for libuv to call a C function in the\ncontext of the main event loop.  The function `v8plus_method_call()` is safe\nto call from any thread: depending on the context in which it is invoked, it\nwill either make the call directly or queue the call in the main event loop\nand block on a reply.  Simply arrange to call back into your JavaScript\nobject when you wish to post an event:\n\n\tnvlist_t *eap;\n\tnvlist_t *erp;\n\tmy_object_t *op = ...;\n\t...\n\teap = v8plus_obj(\n\t    V8PLUS_TYPE_STRING, \"0\", \"my_event\",\n\t    ...,\n\t    V8PLUS_TYPE_NONE);\n\n\tif (eap != NULL) {\n\t\terp = v8plus_method_call(op, \"_emit\", eap);\n\t\tnvlist_free(eap);\n\t\tnvlist_free(erp);\n\t}\n\nThis example will generate an event named \"my_event\" and propagate it to\nlisteners registered with the `MyObjectWrapper` instance.  If additional\narguments are associated with the event, they may be added to `eap` and will\nalso be passed along to listeners as arguments to their callbacks.\n\n### void v8plus_obj_hold(const void *op)\n\nPlaces a hold on the V8 representation of the specified C object.  This is\nrarely necessary; `v8plus_defer()` performs this action for you, but other\nasynchronous mechanisms may require it.  If you are returning from a method\ncall but have stashed a reference to the object somewhere and are not\ncalling `v8plus_defer()`, you must call this first.  Holds and releases must\nbe balanced.  Use of the object within a thread after releasing is a bug.\n\n### void v8plus_obj_rele(const void *op)\n\nReleases a hold placed by `v8plus_obj_hold()`.  This function may be called\nsafely from any thread; releases from threads other than the main event loop\nare non-blocking and will occur some time in the future.\n\n### void v8plus_jsfunc_hold(v8plus_jsfunc_t f)\n\nPlaces a hold on the V8 representation of the specified JavaScript function.\nThis is required when returning from a C function that has stashed a\nreference to the function, typically to use it asynchronously as a callback.\nAll holds must be balanced with a release.  Because a single hold is placed\non such objects when passed to you in an argument list (and released for you\nwhen you return), it is legal to reference and even to invoke such a\nfunction without first placing an additional hold on it.\n\n### void v8plus_jsfunc_rele(v8plus_jsfunc_t f)\n\nReleases a hold placed by `v8plus_jsfunc_hold()`.  This function may be called\nsafely from any thread; releases from threads other than the main event loop\nthread are non-blocking and will occur some time in the future.\n\n### void v8plus_defer(void *op, void *ctx, worker, completion)\n\nEnqueues work to be performed in the Node.js shared thread pool.  The object\n`op` and context `ctx` are passed as arguments to `worker` executing in a\nthread from that pool.  The same two arguments, along with the worker's\nreturn value, are passed to `completion` executing in the main event loop\nthread.  See example above.\n\n### nvlist_t *v8plus_call(v8plus_jsfunc_t f, const nvlist_t *ap)\n\nCalls the JavaScript function referred to by `f` with encoded arguments\n`ap`.  The return value is the encoded return value of the function.  The\nargument and return value encoding match the encodings that are used by C\nfunctions that provide methods.\n\nAs JavaScript functions must be called from the event loop thread,\n`v8plus_call()` contains logic to determine whether we are in the\ncorrect context or not.  If we are running on some other thread we will\nqueue the request and sleep, waiting for the event loop thread to make the\ncall.  In the simple case, where we are already in the correct thread, we\nmake the call directly.\n\nNote that when passing JavaScript functions around as callbacks, you must use\nfirst use `v8plus_jsfunc_hold()` from within the main event loop thread.  Once\nfinished with the function, you may pass it to `v8plus_jsfunc_rele()` from any\nthread to clean up.\n\n### nvlist_t *v8plus_method_call(void *op, const char *name, const nvlist_t *ap)\n\nCalls the method named by `name` in the native object `op` with encoded\nargument list `ap`.  The method must exist and must be a JavaScript\nfunction.  Such functions may be attached by JavaScript code as in the event\nemitter example above.  The effects of using this function to call a native\nmethod are undefined.\n\nWhen called from threads other than the main event loop thread,\n`v8plus_method_call()` uses the same queue-and-block logic as described above\nin `v8plus_call()`.\n\n## FAQ\n\n- Why?\n\nBecause C++ is garbage.  Writing good software is challenging enough without\ntrying to understand a bunch of implicit side effects or typing templated\nidentifiers that can't fit in 80 columns without falling afoul of the\nlanguage's ambiguous grammar.  Don't get me started.\n\n- Why not use [FFI](https://github.com/rbranson/node-ffi)?\n\nFFI is really cool; it offers us the ability to use C libraries without\nwriting bindings at all.  However, it also exposes a lot of C nastiness to\nJavaScript code, essentially placing the interface boundary in consuming\ncode itself.  This pretty much breaks the JavaScript interface model --\nfor example, you can't really have a function that inspects the types of its\narguments -- and requires you to write an additional C library anyway if you\nwant or need to do something natively that's not quite what the C library\nalready does.  Of course, one could use it to write \"bindings\" in JavaScript\nthat actually look like a JavaScript interface, which may end up being the\nbest answer, especially if those are autogenerated from CTF!  In short, v8+\nand FFI are different approaches to the problem.  Use whichever fits your\nneed, and note that they're not mutually exclusive, either.\n\n- What systems can I use this on?\n\n[illumos](http://illumos.org) distributions, or possibly other platforms\nwith a working libnvpair.  I'm sorry if your system doesn't have it; it's\nopen source and pretty easy to port.\n\nThere is an OSX port; see [the ZFS port's\nimplementation](http://code.google.com/p/maczfs/source/browse/#git%2Fusr%2Fsrc%2Flib%2Flibnvpair).\nUnfortunately this port lacks the requisite support for floating-point data\n(DATA_TYPE_DOUBLE) but you could easily add that from the illumos sources.\n\n- What about node-waf and node-gyp?\n\nFuck python, fuck WAF, and fuck all the hipster douchebags for whom make is\ntoo hard, too old, or \"too Unixy\".  Make is simple, easy to use, and\nextremely reliable.  It was building big, important pieces of software when\nyour parents were young, and it Just Works.  If you don't like using make\nhere, you probably don't want to use v8+ either, so just go away.  Write\nyour CoffeeScript VM in something else, and gyp-scons-waf-rake your way to\nan Instagram retirement in Bali with all your hipster douchebag friends.\nJust don't bother me about it, because I don't care.\n\n- Why is Node failing in dlopen()?\n\nMost likely, your module has a typo or needs to be linked with a library.\nNormally, shared objects like Node addons should be linked with -zdefs so that\nthese problems are found at build time, but Node doesn't deliver a mapfile\nspecifying its API so you're left with a bunch of undefined symbols you just\nhave to hope are defined somewhere in your node process's address space.  If\nthey aren't, you're boned.  LD_DEBUG=all will help you find the missing\nsymbol(s).\n\nAs of 0.0.2, v8+ builds a mapfile for your node binary at the time you build\nyour addon.  It does not attempt to restrict the visibility of any symbols,\nso you will not be warned if your addon is using private or deprecated\nfunctionality in V8 or Node.js.  Your build will, however, fail if you've\nneglected to link in any required libraries, typo'd a symbol name, etc.\n\n- Why use the old init() instead of NODE_MODULE()?\n\nBecause NODE_MODULE() is a macro that can't be passed another macro as the\nname of your addon.  Using it would therefore require the source to v8+ to\nbe generated at build time to match your module's name, which is\ninconvenient.  There may be a way to work around this.\n\n- Why can't I see my exception's decorative properties in JavaScript?\n\nBe careful when decorating exceptions.  There are several built-in hidden\nproperties; if you decorate the exception with a property with the same\nname, you will change the hidden property's value but it will still be\nhidden.  This almost certainly is not what you want, so you should prefix\nthe decorative property names with something unique to your module to avoid\nstepping on V8's (or JavaScript's) property namespace.\n\n- What if the factory model doesn't work for me?\n\nSee \"License\" below.  Note also that one can export plain functions as well.\n\n- Why do I always die with \"invalid property type -3621\" (or other garbage)?\n\nYou are passing an object with the wrong C type to `v8plus_obj()`.  Like\nall varargs functions, it cannot tell the correct size or type of the\nobjects you have passed it; they must match the preceding type argument or\nit will not work correctly.  In this particular case, you've most likely\ndone something like:\n\n\tint foo = 0xdead;\n\n\tv8plus_obj(V8PLUS_TYPE_NUMBER, \"foo\", foo, V8PLUS_TYPE_NONE);\n\nAn 'int' is 4 bytes in size, and the compiler reserves 4 bytes on the stack\nand sticks the value of foo there.  When `v8plus_obj` goes to read it, it\nsees that the type is V8PLUS_TYPE_NUMBER, casts the address of the next\nargument slot to a `double *`, and dereferences it, then moves the argument\nlist pointer ahead by the size of a double.  Unfortunately, a double\nis usually 8 bytes long, meaning that (a) the value of the property is going\nto be comprised of the integer-encoded foo appended to the next data type,\nand (b) the next data type is going to be read from either undefined memory\nor from part of the address of the name of the next property.  To cure this,\nalways make sure that you cast your integral arguments properly when using\nV8PLUS_TYPE_NUMBER:\n\n\tv8plus_obj(V8PLUS_TYPE_NUMBER, \"foo\", (double)foo, V8PLUS_TYPE_NONE);\n\n## License\n\nMIT.\n\n## Bugs\n\nSee <https://github.com/joyent/v8plus/issues>.\n\n## Consumers\n\nThis is an incomplete list of native addons known to be using v8+.  If your\naddon uses v8+, please let me know and I will include it here.\n\n- <https://github.com/joyent/node-contract>\n",
+  "readmeFilename": "README.md",
+  "_id": "v8plus@0.1.0",
+  "_from": "v8plus@~0.1.0"
+}
--- /dev/null	2013-10-21 19:08:28.000000000 +0000
+++ new/src/node-lockfd/node_modules/v8plus/v8plus_csup.c	2013-10-21 19:08:28.153360390 +0000
@@ -0,0 +1,829 @@
+/*
+ * Copyright (c) 2012 Joyent, Inc.  All rights reserved.
+ */
+
+#include <sys/ccompile.h>
+#include <sys/debug.h>
+#include <sys/queue.h>
+#include <sys/types.h>
+#include <stdarg.h>
+#include <string.h>
+#include <strings.h>
+#include <errno.h>
+#include <uv.h>
+#include <pthread.h>
+#include "v8plus_glue.h"
+
+__thread v8plus_errno_t _v8plus_errno;
+__thread char _v8plus_errmsg[V8PLUS_ERRMSG_LEN];
+
+typedef struct v8plus_uv_ctx {
+	void *vuc_obj;
+	void *vuc_ctx;
+	void *vuc_result;
+	v8plus_worker_f vuc_worker;
+	v8plus_completion_f vuc_completion;
+} v8plus_uv_ctx_t;
+
+static STAILQ_HEAD(v8plus_callq_head, v8plus_async_call) _v8plus_callq =
+    STAILQ_HEAD_INITIALIZER(_v8plus_callq);
+static pthread_mutex_t _v8plus_callq_mtx;
+static pthread_t _v8plus_uv_event_thread;
+static uv_async_t _v8plus_uv_async;
+
+typedef enum v8plus_async_call_type {
+	ACT_OBJECT_CALL = 1,
+	ACT_OBJECT_RELEASE,
+	ACT_JSFUNC_CALL,
+	ACT_JSFUNC_RELEASE,
+} v8plus_async_call_type_t;
+
+typedef enum v8plus_async_call_flags {
+	ACF_COMPLETED	= 0x01,
+	ACF_NOREPLY	= 0x02
+} v8plus_async_call_flags_t;
+
+
+typedef struct v8plus_async_call {
+	v8plus_async_call_type_t vac_type;
+	v8plus_async_call_flags_t vac_flags;
+
+	/*
+	 * For ACT_OBJECT_{CALL,RELEASE}:
+	 */
+	void *vac_cop;
+	const char *vac_name;
+	/*
+	 * For ACT_JSFUNC_{CALL,RELEASE}:
+	 */
+	v8plus_jsfunc_t vac_func;
+
+	/*
+	 * Common call arguments:
+	 */
+	const nvlist_t *vac_lp;
+	nvlist_t *vac_return;
+
+	pthread_cond_t vac_cv;
+	pthread_mutex_t vac_mtx;
+
+	STAILQ_ENTRY(v8plus_async_call) vac_callq_entry;
+} v8plus_async_call_t;
+
+boolean_t
+v8plus_in_event_thread(void)
+{
+	return (_v8plus_uv_event_thread == pthread_self() ? B_TRUE : B_FALSE);
+}
+
+static void
+v8plus_async_callback(uv_async_t *async __UNUSED, int status __UNUSED)
+{
+	if (v8plus_in_event_thread() != B_TRUE)
+		v8plus_panic("async callback called outside of event loop");
+
+	for (;;) {
+		v8plus_async_call_t *vac = NULL;
+
+		/*
+		 * Fetch the next queued method:
+		 */
+		if (pthread_mutex_lock(&_v8plus_callq_mtx) != 0)
+			v8plus_panic("could not lock async queue mutex");
+		if (!STAILQ_EMPTY(&_v8plus_callq)) {
+			vac = STAILQ_FIRST(&_v8plus_callq);
+			STAILQ_REMOVE_HEAD(&_v8plus_callq, vac_callq_entry);
+		}
+		if (pthread_mutex_unlock(&_v8plus_callq_mtx) != 0)
+			v8plus_panic("could not unlock async queue mutex");
+
+		if (vac == NULL)
+			break;
+
+		/*
+		 * Run the queued method:
+		 */
+		if (vac->vac_flags & ACF_COMPLETED)
+			v8plus_panic("async call already run");
+
+		switch (vac->vac_type) {
+		case ACT_OBJECT_CALL:
+			vac->vac_return = v8plus_method_call_direct(
+			    vac->vac_cop, vac->vac_name, vac->vac_lp);
+			break;
+		case ACT_OBJECT_RELEASE:
+			v8plus_obj_rele_direct(vac->vac_cop);
+			break;
+		case ACT_JSFUNC_CALL:
+			vac->vac_return = v8plus_call_direct(
+			    vac->vac_func, vac->vac_lp);
+			break;
+		case ACT_JSFUNC_RELEASE:
+			v8plus_jsfunc_rele_direct(vac->vac_func);
+			break;
+		}
+
+		if (vac->vac_flags & ACF_NOREPLY) {
+			/*
+			 * The caller posted this event and is not sleeping
+			 * on a reply.  Just free the call structure and move
+			 * on.
+			 */
+			free(vac);
+			if (vac->vac_lp != NULL)
+				nvlist_free((nvlist_t *)vac->vac_lp);
+			continue;
+		}
+
+		if (pthread_mutex_lock(&vac->vac_mtx) != 0)
+			v8plus_panic("could not lock async call mutex");
+		vac->vac_flags |= ACF_COMPLETED;
+		if (pthread_cond_broadcast(&vac->vac_cv) != 0)
+			v8plus_panic("could not signal async call condvar");
+		if (pthread_mutex_unlock(&vac->vac_mtx) != 0)
+			v8plus_panic("could not unlock async call mutex");
+	}
+}
+
+/*
+ * As we cannot manipulate v8plus/V8/Node structures directly from outside the
+ * event loop thread, we push the call arguments onto a queue and post to the
+ * event loop thread.  We then sleep on our condition variable until the event
+ * loop thread makes the call for us and wakes us up.
+ *
+ * This routine implements the parts of this interaction common to all
+ * variants.
+ */
+static nvlist_t *
+v8plus_cross_thread_call(v8plus_async_call_t *vac)
+{
+	/*
+	 * Common call structure initialisation:
+	 */
+	if (pthread_mutex_init(&vac->vac_mtx, NULL) != 0)
+		v8plus_panic("could not init async call mutex");
+	if (pthread_cond_init(&vac->vac_cv, NULL) != 0)
+		v8plus_panic("could not init async call condvar");
+	vac->vac_flags &= ~(ACF_COMPLETED);
+
+	/*
+	 * Post request to queue:
+	 */
+	if (pthread_mutex_lock(&_v8plus_callq_mtx) != 0)
+		v8plus_panic("could not lock async queue mutex");
+	STAILQ_INSERT_TAIL(&_v8plus_callq, vac, vac_callq_entry);
+	if (pthread_mutex_unlock(&_v8plus_callq_mtx) != 0)
+		v8plus_panic("could not unlock async queue mutex");
+	uv_async_send(&_v8plus_uv_async);
+
+	if (vac->vac_flags & ACF_NOREPLY) {
+		/*
+		 * The caller does not care about the reply, and has allocated
+		 * the v8plus_async_call_t structure from the heap.  The
+		 * async callback will free the storage when it completes.
+		 */
+		return (NULL);
+	}
+
+	/*
+	 * Wait for our request to be serviced on the event loop thread:
+	 */
+	if (pthread_mutex_lock(&vac->vac_mtx) != 0)
+		v8plus_panic("could not lock async call mutex");
+	while (!(vac->vac_flags & ACF_COMPLETED)) {
+		if (pthread_cond_wait(&vac->vac_cv, &vac->vac_mtx) != 0)
+			v8plus_panic("could not wait on async call condvar");
+	}
+	if (pthread_mutex_unlock(&vac->vac_mtx) != 0)
+		v8plus_panic("could not unlock async call mutex");
+
+	if (pthread_cond_destroy(&vac->vac_cv) != 0)
+		v8plus_panic("could not destroy async call condvar");
+	if (pthread_mutex_destroy(&vac->vac_mtx) != 0)
+		v8plus_panic("could not destroy async call mutex");
+
+	return (vac->vac_return);
+}
+
+nvlist_t *
+v8plus_method_call(void *cop, const char *name, const nvlist_t *lp)
+{
+	v8plus_async_call_t vac;
+
+	if (v8plus_in_event_thread() == B_TRUE) {
+		/*
+		 * We're running in the event loop thread, so we can make the
+		 * call directly.
+		 */
+		return (v8plus_method_call_direct(cop, name, lp));
+	}
+
+	bzero(&vac, sizeof (vac));
+	vac.vac_type = ACT_OBJECT_CALL;
+	vac.vac_cop = cop;
+	vac.vac_name = name;
+	vac.vac_lp = lp;
+
+	return (v8plus_cross_thread_call(&vac));
+}
+
+nvlist_t *
+v8plus_call(v8plus_jsfunc_t func, const nvlist_t *lp)
+{
+	v8plus_async_call_t vac;
+
+	if (v8plus_in_event_thread() == B_TRUE) {
+		/*
+		 * We're running in the event loop thread, so we can make the
+		 * call directly.
+		 */
+		return (v8plus_call_direct(func, lp));
+	}
+
+	bzero(&vac, sizeof (vac));
+	vac.vac_type = ACT_JSFUNC_CALL;
+	vac.vac_func = func;
+	vac.vac_lp = lp;
+
+	return (v8plus_cross_thread_call(&vac));
+}
+
+void
+v8plus_obj_rele(const void *cop)
+{
+	v8plus_async_call_t *vac;
+
+	if (v8plus_in_event_thread() == B_TRUE) {
+		return (v8plus_obj_rele_direct(cop));
+	}
+
+	vac = calloc(1, sizeof (*vac));
+	if (vac == NULL)
+		v8plus_panic("could not allocate async call structure");
+
+	vac->vac_type = ACT_OBJECT_RELEASE;
+	vac->vac_flags = ACF_NOREPLY;
+	vac->vac_cop = (void *)cop;
+
+	(void) v8plus_cross_thread_call(vac);
+}
+
+void
+v8plus_jsfunc_rele(v8plus_jsfunc_t f)
+{
+	v8plus_async_call_t *vac;
+
+	if (v8plus_in_event_thread() == B_TRUE) {
+		return (v8plus_jsfunc_rele_direct(f));
+	}
+
+	vac = calloc(1, sizeof (*vac));
+	if (vac == NULL)
+		v8plus_panic("could not allocate async call structure");
+
+	vac->vac_type = ACT_JSFUNC_RELEASE;
+	vac->vac_flags = ACF_NOREPLY;
+	vac->vac_func = f;
+
+	(void) v8plus_cross_thread_call(vac);
+}
+
+/*
+ * Initialise structures for off-event-loop method calls.
+ *
+ * Note that uv_async_init() must be called inside the libuv event loop, so we
+ * do it here.  We also want to record the thread ID of the Event Loop thread
+ * so as to determine what kind of method calls to make later.
+ */
+void
+v8plus_crossthread_init(void)
+{
+	_v8plus_uv_event_thread = pthread_self();
+	if (uv_async_init(uv_default_loop(), &_v8plus_uv_async,
+	    v8plus_async_callback) != 0)
+		v8plus_panic("unable to initialise uv_async_t");
+	if (pthread_mutex_init(&_v8plus_callq_mtx, NULL) != 0)
+		v8plus_panic("unable to initialise mutex");
+}
+
+nvlist_t *
+v8plus_verror(v8plus_errno_t e, const char *fmt, va_list ap)
+{
+	if (fmt == NULL) {
+		if (e == V8PLUSERR_NOERROR) {
+			*_v8plus_errmsg = '\0';
+		} else {
+			(void) snprintf(_v8plus_errmsg, V8PLUS_ERRMSG_LEN,
+			    "%s", v8plus_strerror(e));
+		}
+	} else {
+		(void) vsnprintf(_v8plus_errmsg, V8PLUS_ERRMSG_LEN, fmt, ap);
+	}
+	_v8plus_errno = e;
+
+	return (NULL);
+}
+
+nvlist_t *
+v8plus_error(v8plus_errno_t e, const char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	(void) v8plus_verror(e, fmt, ap);
+	va_end(ap);
+
+	return (NULL);
+}
+
+static void __NORETURN
+v8plus_vpanic(const char *fmt, va_list ap)
+{
+	(void) vfprintf(stderr, fmt, ap);
+	(void) fflush(stderr);
+	abort();
+}
+
+void
+v8plus_panic(const char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	v8plus_vpanic(fmt, ap);
+	va_end(ap);
+}
+
+nvlist_t *
+v8plus_nverr(int nverr, const char *member)
+{
+	(void) snprintf(_v8plus_errmsg, V8PLUS_ERRMSG_LEN,
+	    "nvlist manipulation error on member %s: %s",
+	    member == NULL ? "<none>" : member, strerror(nverr));
+
+	switch (nverr) {
+	case ENOMEM:
+		_v8plus_errno = V8PLUSERR_NOMEM;
+		break;
+	case EINVAL:
+		_v8plus_errno = V8PLUSERR_YOUSUCK;
+		break;
+	default:
+		_v8plus_errno = V8PLUSERR_UNKNOWN;
+		break;
+	}
+
+	return (NULL);
+}
+
+nvlist_t *
+v8plus_syserr(int syserr, const char *fmt, ...)
+{
+	v8plus_errno_t e;
+	va_list ap;
+
+	switch (syserr) {
+	case ENOMEM:
+		e = V8PLUSERR_NOMEM;
+		break;
+	case EBADF:
+		e = V8PLUSERR_BADF;
+		break;
+	default:
+		e = V8PLUSERR_UNKNOWN;
+		break;
+	}
+
+	va_start(ap, fmt);
+	(void) v8plus_verror(e, fmt, ap);
+	va_end(ap);
+
+	return (NULL);
+}
+
+/*
+ * The NULL nvlist with V8PLUSERR_NOERROR means we are returning void.
+ */
+nvlist_t *
+v8plus_void(void)
+{
+	return (v8plus_error(V8PLUSERR_NOERROR, NULL));
+}
+
+v8plus_type_t
+v8plus_typeof(const nvpair_t *pp)
+{
+	data_type_t t = nvpair_type((nvpair_t *)pp);
+
+	switch (t) {
+	case DATA_TYPE_DOUBLE:
+		return (V8PLUS_TYPE_NUMBER);
+	case DATA_TYPE_STRING:
+		return (V8PLUS_TYPE_STRING);
+	case DATA_TYPE_NVLIST:
+		return (V8PLUS_TYPE_OBJECT);
+	case DATA_TYPE_BOOLEAN_VALUE:
+		return (V8PLUS_TYPE_BOOLEAN);
+	case DATA_TYPE_BOOLEAN:
+		return (V8PLUS_TYPE_UNDEFINED);
+	case DATA_TYPE_BYTE:
+	{
+		uchar_t v;
+		if (nvpair_value_byte((nvpair_t *)pp, &v) != 0 || v != 0)
+			return (V8PLUS_TYPE_INVALID);
+		return (V8PLUS_TYPE_NULL);
+	}
+	case DATA_TYPE_UINT64_ARRAY:
+	{
+		uint64_t *vp;
+		uint_t nv;
+		if (nvpair_value_uint64_array((nvpair_t *)pp, &vp, &nv) != 0 ||
+		    nv != 1) {
+			return (V8PLUS_TYPE_INVALID);
+		}
+		return (V8PLUS_TYPE_JSFUNC);
+	}
+	default:
+		return (V8PLUS_TYPE_INVALID);
+	}
+}
+
+static int
+v8plus_arg_value(v8plus_type_t t, const nvpair_t *pp, void *vp)
+{
+	data_type_t dt = nvpair_type((nvpair_t *)pp);
+
+	switch (t) {
+	case V8PLUS_TYPE_NONE:
+		return (-1);
+	case V8PLUS_TYPE_STRING:
+		if (dt == DATA_TYPE_STRING) {
+			if (vp != NULL) {
+				(void) nvpair_value_string((nvpair_t *)pp,
+				    (char **)vp);
+			}
+			return (0);
+		}
+		return (-1);
+	case V8PLUS_TYPE_NUMBER:
+		if (dt == DATA_TYPE_DOUBLE) {
+			if (vp != NULL) {
+				(void) nvpair_value_double((nvpair_t *)pp,
+				    (double *)vp);
+			}
+			return (0);
+		}
+		return (-1);
+	case V8PLUS_TYPE_BOOLEAN:
+		if (dt == DATA_TYPE_BOOLEAN_VALUE) {
+			if (vp != NULL) {
+				(void) nvpair_value_boolean_value(
+				    (nvpair_t *)pp, (boolean_t *)vp);
+			}
+			return (0);
+		}
+		return (-1);
+	case V8PLUS_TYPE_JSFUNC:
+		if (dt == DATA_TYPE_UINT64_ARRAY) {
+			uint_t nv;
+			uint64_t *vpp;
+
+			if (nvpair_value_uint64_array((nvpair_t *)pp,
+			    &vpp, &nv) == 0 && nv == 1) {
+				if (vp != NULL)
+					*(v8plus_jsfunc_t *)vp = vpp[0];
+				return (0);
+			}
+		}
+		return (-1);
+	case V8PLUS_TYPE_OBJECT:
+		if (dt == DATA_TYPE_NVLIST) {
+			if (vp != NULL) {
+				(void) nvpair_value_nvlist((nvpair_t *)pp,
+				    (nvlist_t **)vp);
+			}
+			return (0);
+		}
+		return (-1);
+	case V8PLUS_TYPE_NULL:
+		if (dt == DATA_TYPE_BYTE) {
+			uchar_t v;
+
+			if (nvpair_value_byte((nvpair_t *)pp, &v) == 0 &&
+			    v == 0)
+				return (0);
+		}
+		return (-1);
+	case V8PLUS_TYPE_UNDEFINED:
+		return (dt == DATA_TYPE_BOOLEAN ? 0 : -1);
+	case V8PLUS_TYPE_ANY:
+		if (vp != NULL)
+			*(const nvpair_t **)vp = pp;
+		return (0);
+	case V8PLUS_TYPE_INVALID:
+		if (vp != NULL)
+			*(data_type_t *)vp = dt;
+		return (0);
+	case V8PLUS_TYPE_STRNUMBER64:
+		if (dt == DATA_TYPE_STRING) {
+			char *s;
+			uint64_t v;
+
+			(void) nvpair_value_string((nvpair_t *)pp, &s);
+			errno = 0;
+			v = (uint64_t)strtoull(s, NULL, 0);
+			if (errno != 0)
+				return (-1);
+			if (vp != NULL)
+				*(uint64_t *)vp = v;
+			return (0);
+		}
+		return (-1);
+	default:
+		return (-1);
+	}
+}
+
+int
+v8plus_args(const nvlist_t *lp, uint_t flags, v8plus_type_t t, ...)
+{
+	v8plus_type_t nt;
+	nvpair_t *pp;
+	void *vp;
+	va_list ap;
+	uint_t i;
+	char buf[32];
+
+	va_start(ap, t);
+
+	for (i = 0, nt = t; nt != V8PLUS_TYPE_NONE; i++) {
+		switch (nt) {
+		case V8PLUS_TYPE_UNDEFINED:
+		case V8PLUS_TYPE_NULL:
+			break;
+		default:
+			(void) va_arg(ap, void *);
+		}
+
+		(void) snprintf(buf, sizeof (buf), "%u", i);
+		if (nvlist_lookup_nvpair((nvlist_t *)lp, buf, &pp) != 0) {
+			(void) v8plus_error(V8PLUSERR_MISSINGARG,
+			    "argument %u is required", i);
+			return (-1);
+		}
+
+		if (v8plus_arg_value(nt, pp, NULL) != 0) {
+			(void) v8plus_error(V8PLUSERR_BADARG,
+			    "argument %u is of incorrect type", i);
+			return (-1);
+		}
+
+		nt = va_arg(ap, data_type_t);
+	}
+
+	va_end(ap);
+
+	if (flags & V8PLUS_ARG_F_NOEXTRA) {
+		(void) snprintf(buf, sizeof (buf), "%u", i);
+		if (nvlist_lookup_nvpair((nvlist_t *)lp, buf, &pp) == 0) {
+			(void) v8plus_error(V8PLUSERR_EXTRAARG,
+			    "superfluous extra argument(s) detected");
+			return (-1);
+		}
+	}
+
+	va_start(ap, t);
+
+	for (i = 0, nt = t; nt != V8PLUS_TYPE_NONE; i++) {
+		switch (nt) {
+		case V8PLUS_TYPE_UNDEFINED:
+		case V8PLUS_TYPE_NULL:
+			vp = NULL;
+			break;
+		default:
+			vp = va_arg(ap, void *);
+		}
+
+		(void) snprintf(buf, sizeof (buf), "%u", i);
+		VERIFY(nvlist_lookup_nvpair((nvlist_t *)lp, buf, &pp) == 0);
+		VERIFY(v8plus_arg_value(nt, pp, vp) == 0);
+
+		nt = va_arg(ap, data_type_t);
+	}
+
+	va_end(ap);
+
+	return (0);
+}
+
+static int
+v8plus_obj_vsetprops(nvlist_t *lp, v8plus_type_t t, va_list *ap)
+{
+	v8plus_type_t nt = t;
+	char *name;
+	int err;
+
+	/*
+	 * Do not call va_start() or va_end() in this function!  We are limited
+	 * to a single traversal of the arguments so that we can recurse to
+	 * handle embedded object definitions.
+	 */
+
+	while (nt != V8PLUS_TYPE_NONE) {
+		name = va_arg(*ap, char *);
+
+		switch (nt) {
+		case V8PLUS_TYPE_STRING:
+		{
+			char *s = va_arg(*ap, char *);
+			if ((err = nvlist_add_string(lp, name, s)) != 0) {
+				(void) v8plus_nverr(err, name);
+				return (-1);
+			}
+			break;
+		}
+		case V8PLUS_TYPE_NUMBER:
+		{
+			double d = va_arg(*ap, double);
+			if ((err = nvlist_add_double(lp, name, d)) != 0) {
+				(void) v8plus_nverr(err, name);
+				return (-1);
+			}
+			break;
+		}
+		case V8PLUS_TYPE_BOOLEAN:
+		{
+			boolean_t b = va_arg(*ap, boolean_t);
+			if ((err = nvlist_add_boolean_value(lp,
+			    name, b)) != 0) {
+				(void) v8plus_nverr(err, name);
+				return (-1);
+			}
+			break;
+		}
+		case V8PLUS_TYPE_JSFUNC:
+		{
+			v8plus_jsfunc_t j = va_arg(*ap, v8plus_jsfunc_t);
+			if ((err = nvlist_add_uint64_array(lp,
+			    name, &j, 1)) != 0) {
+				(void) v8plus_nverr(err, name);
+				return (-1);
+			}
+			if ((err = nvlist_add_string_array(lp,
+			    V8PLUS_JSF_COOKIE, NULL, 0)) != 0) {
+				(void) v8plus_nverr(err, V8PLUS_JSF_COOKIE);
+				return (-1);
+			}
+			v8plus_jsfunc_hold(j);
+			break;
+		}
+		case V8PLUS_TYPE_OBJECT:
+		{
+			const nvlist_t *op = va_arg(*ap, const nvlist_t *);
+			if ((err = nvlist_add_nvlist(lp, name,
+			    (nvlist_t *)op)) != 0) {
+				(void) v8plus_nverr(err, name);
+				return (-1);
+			}
+			break;
+		}
+		case V8PLUS_TYPE_NULL:
+			if ((err = nvlist_add_byte(lp, name, 0)) != 0) {
+				(void) v8plus_nverr(err, name);
+				return (-1);
+			}
+			break;
+		case V8PLUS_TYPE_UNDEFINED:
+			if ((err = nvlist_add_boolean(lp, name)) != 0) {
+				(void) v8plus_nverr(err, name);
+				return (-1);
+			}
+			break;
+		case V8PLUS_TYPE_ANY:
+		{
+			nvpair_t *pp = va_arg(*ap, nvpair_t *);
+			if ((err = nvlist_add_nvpair(lp, pp)) != 0) {
+				(void) v8plus_nverr(err, name);
+				return (-1);
+			}
+			break;
+		}
+		case V8PLUS_TYPE_STRNUMBER64:
+		{
+			uint64_t v = va_arg(*ap, uint64_t);
+			char s[32];
+			(void) snprintf(s, sizeof (s), "%" PRIu64, v);
+			if ((err = nvlist_add_string(lp, name, s)) != 0) {
+				(void) v8plus_nverr(err, name);
+				return (-1);
+			}
+			break;
+		}
+		case V8PLUS_TYPE_INL_OBJECT:
+		{
+			nvlist_t *slp;
+
+			nt = va_arg(*ap, v8plus_type_t);
+			err = nvlist_alloc(&slp, NV_UNIQUE_NAME, 0);
+			if (err != 0) {
+				(void) v8plus_nverr(err, name);
+				return (-1);
+			}
+			if (v8plus_obj_vsetprops(slp, nt, ap) != 0)
+				return (-1);
+
+			err = nvlist_add_nvlist(lp, name, slp);
+			nvlist_free(slp);
+			if (err != 0) {
+				(void) v8plus_nverr(err, name);
+				return (-1);
+			}
+			break;
+		}
+		case V8PLUS_TYPE_INVALID:
+		default:
+			(void) v8plus_error(V8PLUSERR_YOUSUCK,
+			    "invalid property type %d", nt);
+			return (-1);
+		}
+
+		nt = va_arg(*ap, v8plus_type_t);
+	}
+
+	return (0);
+}
+
+nvlist_t *
+v8plus_obj(v8plus_type_t t, ...)
+{
+	nvlist_t *rp;
+	va_list ap;
+	int err;
+
+	if ((err = nvlist_alloc(&rp, NV_UNIQUE_NAME, 0)) != 0)
+		return (v8plus_nverr(err, NULL));
+
+	va_start(ap, t);
+	err = v8plus_obj_vsetprops(rp, t, &ap);
+	va_end(ap);
+
+	if (err != 0) {
+		nvlist_free(rp);
+		rp = NULL;
+	}
+
+	return (rp);
+}
+
+int
+v8plus_obj_setprops(nvlist_t *lp, v8plus_type_t t, ...)
+{
+	va_list ap;
+	int err;
+
+	va_start(ap, t);
+	err = v8plus_obj_vsetprops(lp, t, &ap);
+	va_end(ap);
+
+	return (err);
+}
+
+static void
+v8plus_uv_worker(uv_work_t *wp)
+{
+	v8plus_uv_ctx_t *cp = wp->data;
+
+	cp->vuc_result = cp->vuc_worker(cp->vuc_obj, cp->vuc_ctx);
+}
+
+static void
+v8plus_uv_completion(uv_work_t *wp)
+{
+	v8plus_uv_ctx_t *cp = wp->data;
+
+	cp->vuc_completion(cp->vuc_obj, cp->vuc_ctx, cp->vuc_result);
+	v8plus_obj_rele(cp->vuc_obj);
+	free(cp);
+	free(wp);
+}
+
+void
+v8plus_defer(void *cop, void *ctxp, v8plus_worker_f worker,
+    v8plus_completion_f completion)
+{
+	uv_work_t *wp = malloc(sizeof (uv_work_t));
+	v8plus_uv_ctx_t *cp = malloc(sizeof (v8plus_uv_ctx_t));
+
+	bzero(wp, sizeof (uv_work_t));
+	bzero(cp, sizeof (v8plus_uv_ctx_t));
+
+	v8plus_obj_hold(cop);
+	cp->vuc_obj = cop;
+	cp->vuc_ctx = ctxp;
+	cp->vuc_worker = worker;
+	cp->vuc_completion = completion;
+	wp->data = cp;
+
+	uv_queue_work(uv_default_loop(), wp, v8plus_uv_worker,
+	    v8plus_uv_completion);
+}
--- /dev/null	2013-10-21 19:08:28.000000000 +0000
+++ new/src/node-lockfd/node_modules/v8plus/v8plus_glue.h	2013-10-21 19:08:28.314644787 +0000
@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 2012 Joyent, Inc.  All rights reserved.
+ */
+
+#ifndef	_V8PLUS_GLUE_H
+#define	_V8PLUS_GLUE_H
+
+#include <stdarg.h>
+#include <libnvpair.h>
+#include "v8plus_errno.h"
+
+#ifdef	__cplusplus
+extern "C" {
+#endif	/* __cplusplus */
+
+#define	__UNUSED	__attribute__((__unused__))
+
+#define	V8PLUS_ARG_F_NOEXTRA	0x01
+
+#define	V8PLUS_ERRMSG_LEN	512
+#define	V8PLUS_JSF_COOKIE	".__v8plus_jsfunc_cookie"
+
+typedef enum v8plus_type {
+	V8PLUS_TYPE_NONE = 0,		/* N/A */
+	V8PLUS_TYPE_STRING,		/* char * */
+	V8PLUS_TYPE_NUMBER,		/* double */
+	V8PLUS_TYPE_BOOLEAN,		/* boolean_t */
+	V8PLUS_TYPE_JSFUNC,		/* v8plus_jsfunc_t */
+	V8PLUS_TYPE_OBJECT,		/* nvlist_t * */
+	V8PLUS_TYPE_NULL,		/* -- */
+	V8PLUS_TYPE_UNDEFINED,		/* -- */
+	V8PLUS_TYPE_INVALID,		/* data_type_t */
+	V8PLUS_TYPE_ANY,		/* nvpair_t * */
+	V8PLUS_TYPE_STRNUMBER64,	/* uint64_t */
+	V8PLUS_TYPE_INL_OBJECT		/* ... */
+} v8plus_type_t;
+
+typedef uint64_t v8plus_jsfunc_t;
+
+/*
+ * C constructor, destructor, and method prototypes.  See README.md.
+ */
+typedef nvlist_t *(*v8plus_c_ctor_f)(const nvlist_t *, void **);
+typedef nvlist_t *(*v8plus_c_static_f)(const nvlist_t *);
+typedef nvlist_t *(*v8plus_c_method_f)(void *, const nvlist_t *);
+typedef void (*v8plus_c_dtor_f)(void *);
+
+typedef struct v8plus_method_descr {
+	const char *md_name;
+	v8plus_c_method_f md_c_func;
+} v8plus_method_descr_t;
+
+typedef struct v8plus_static_descr {
+	const char *sd_name;
+	v8plus_c_static_f sd_c_func;
+} v8plus_static_descr_t;
+
+extern __thread v8plus_errno_t _v8plus_errno;
+extern __thread char _v8plus_errmsg[V8PLUS_ERRMSG_LEN];
+
+/*
+ * Set the errno and message, indicating an error.  The code and
+ * printf-formatted message, if one is given, will be used in constructing
+ * an exception to be thrown in JavaScript if your method later returns NULL
+ * or an nvlist with an "err" member.
+ */
+extern nvlist_t *v8plus_verror(v8plus_errno_t, const char *, va_list);
+extern nvlist_t *v8plus_error(v8plus_errno_t, const char *, ...);
+
+/*
+ * Suicide.  It's always an option.  Try to avoid using this as it's not
+ * very nice to kill the entire node process; if at all possible we need
+ * to throw a JavaScript exception instead.
+ */
+extern void v8plus_panic(const char *, ...) __PRINTFLIKE(1) __NORETURN;
+
+/*
+ * As above, this convenience function sets the error code and message based
+ * on the nvlist-generated error code in its first argument.  The second
+ * argument, which may be NULL, should contain the name of the member on
+ * which the error occurred.
+ */
+extern nvlist_t *v8plus_nverr(int, const char *);
+
+/*
+ * Similarly, for system errors.  Not all possible errno values are handled.
+ */
+extern nvlist_t *v8plus_syserr(int, const char *, ...);
+
+/*
+ * Clear the errno and message.  This is needed only when one wishes to return
+ * NULL from a C method whose return type is effectively void.  The idiom is
+ *
+ * return (v8plus_void());
+ */
+extern nvlist_t *v8plus_void(void);
+
+/*
+ * Find the named V8 function in the nvlist.  Analogous to other lookup
+ * routines; see libnvpair(3lib), with an important exception: the
+ * nvlist_lookup_v8plus_jsfunc() and nvpair_value_v8plus_jsfunc() functions
+ * place a hold on the underlying function object, which must be released by C
+ * code when it is no longer needed.  See the documentation to understand how
+ * this works.  The add routine is of very limited utility because there is no
+ * mechanism for creating a JS function from C.  It can however be used to
+ * return a function (or object containing one, etc.) from a deferred
+ * completion routine in which a JS function has been invoked that returned
+ * such a thing to us.
+ */
+extern int nvlist_lookup_v8plus_jsfunc(const nvlist_t *, const char *,
+    v8plus_jsfunc_t *);
+extern int nvpair_value_v8plus_jsfunc(const nvpair_t *, v8plus_jsfunc_t *);
+extern void v8plus_jsfunc_hold(v8plus_jsfunc_t);
+extern void v8plus_jsfunc_rele(v8plus_jsfunc_t);
+extern void v8plus_jsfunc_rele_direct(v8plus_jsfunc_t);
+
+/*
+ * Place or release a hold on the V8 representation of the specified C object.
+ * This is rarely necessary; v8plus_defer() performs this action for you, but
+ * other asynchronous mechanisms may require it.  If you are returning from
+ * a method call but have stashed a reference to the object somewhere and are
+ * not calling v8plus_defer(), you must call this first.  Holds and releases
+ * must be balanced.  Use of the object within a thread after releasing is a
+ * bug.
+ */
+extern void v8plus_obj_hold(const void *);
+extern void v8plus_obj_rele(const void *);
+extern void v8plus_obj_rele_direct(const void *);
+
+/*
+ * Convenience functions for dealing with JS arguments.
+ */
+extern v8plus_type_t v8plus_typeof(const nvpair_t *);
+extern int v8plus_args(const nvlist_t *, uint_t, v8plus_type_t t, ...);
+extern nvlist_t *v8plus_obj(v8plus_type_t, ...);
+extern int v8plus_obj_setprops(nvlist_t *, v8plus_type_t, ...);
+
+/*
+ * Perform a background, possibly blocking and/or expensive, task.  First,
+ * the worker function will be enqueued for execution on another thread; its
+ * first argument is a pointer to the C object on which to operate, and the
+ * second is arbitrary per-call context, arguments, etc. defined by the caller.
+ * When that worker function has completed execution, the completion function
+ * will be invoked in the main thread.  Its arguments are the C object, the
+ * original context pointer, and the return value from the worker function.
+ * See the documentation for a typical use case.
+ */
+typedef void *(*v8plus_worker_f)(void *, void *);
+typedef void (*v8plus_completion_f)(void *, void *, void *);
+
+extern void v8plus_defer(void *, void *, v8plus_worker_f, v8plus_completion_f);
+
+/*
+ * Call an opaque JavaScript function from C.  The caller is responsible for
+ * freeing the returned list.  The first argument is not const because it is
+ * possible for the JS code to modify the function represented by the cookie.
+ */
+extern nvlist_t *v8plus_call(v8plus_jsfunc_t, const nvlist_t *);
+extern nvlist_t *v8plus_call_direct(v8plus_jsfunc_t, const nvlist_t *);
+
+/*
+ * Call the named JavaScript function in the context of the JS object
+ * represented by the native object.  Calling and return conventions are the
+ * same as for the C interfaces; i.e., the nvlist will be converted into JS
+ * objects and the return value or exception will be in the "res" or "err"
+ * members of the nvlist that is returned, respectively.  If an internal
+ * error occurs, NULL is returned and _v8plus_errno set accordingly.  The
+ * results of calling a method implemented in C via this interface are
+ * undefined.
+ *
+ * These methods can be used in concert with JS code to emit events
+ * asynchronously; see the documentation.
+ *
+ * Note: As JavaScript functions must be called from the event loop thread,
+ * v8plus_method_call() contains logic to determine whether we are in the
+ * correct context or not.  If we are running on some other thread we will
+ * queue the request and sleep, waiting for the event loop thread to make the
+ * call.  In the simple case, where we are already in the correct thread,
+ * we make the call directly.  v8plus_method_call_direct() assumes we are
+ * on the correct thread and always makes the call directly.
+ */
+extern nvlist_t *v8plus_method_call(void *, const char *, const nvlist_t *);
+extern nvlist_t *v8plus_method_call_direct(void *, const char *,
+    const nvlist_t *);
+
+/*
+ * These methods are analogous to strerror(3c) and similar functions; they
+ * translate among error names, codes, and default messages.  There is
+ * normally little need for these functions in C methods, as everything
+ * necessary to construct a JavaScript exception is done by v8+, but these
+ * may be useful in the construction of supplementary exception decorations
+ * for debugging purposes.
+ */
+extern const char *v8plus_strerror(v8plus_errno_t);
+extern const char *v8plus_errname(v8plus_errno_t);
+extern const char *v8plus_excptype(v8plus_errno_t);
+
+/*
+ * Provided by C code.  See README.md.
+ */
+extern const v8plus_c_ctor_f v8plus_ctor;
+extern const v8plus_c_dtor_f v8plus_dtor;
+extern const char *v8plus_js_factory_name;
+extern const char *v8plus_js_class_name;
+extern const v8plus_method_descr_t v8plus_methods[];
+extern const uint_t v8plus_method_count;
+extern const v8plus_static_descr_t v8plus_static_methods[];
+extern const uint_t v8plus_static_method_count;
+
+/*
+ * Private methods.
+ */
+extern boolean_t v8plus_in_event_thread(void);
+extern void v8plus_crossthread_init(void);
+
+#ifdef	__cplusplus
+}
+#endif	/* __cplusplus */
+
+#endif	/* _V8PLUS_GLUE_H */
--- /dev/null	2013-10-21 19:08:28.000000000 +0000
+++ new/src/node-lockfd/node_modules/v8plus/v8plus_impl.h	2013-10-21 19:08:28.475196679 +0000
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2012 Joyent, Inc.  All rights reserved.
+ */
+
+#ifndef	_V8PLUS_IMPL_H
+#define	_V8PLUS_IMPL_H
+
+#include <sys/ccompile.h>
+#include <stdarg.h>
+#include <libnvpair.h>
+#include <v8.h>
+#include <unordered_map>
+#include "v8plus_glue.h"
+
+/*
+ * STOP!
+ *
+ * Do not #include this header in code that consumes v8+.  This is a private
+ * implementation header for use by v8+ internal C++ code.  It cannot be
+ * included from C code and contains nothing usable by consumers.
+ */
+
+#define	V8PLUS_THROW(_t, _e, _f, _args...) \
+    v8::ThrowException(v8plus::exception((_t), (_e), (_f), ## _args))
+#define	V8PLUS_THROW_DEFAULT()		V8PLUS_THROW(NULL, NULL, NULL)
+#define	V8PLUS_THROW_DECORATED(_e)	V8PLUS_THROW(NULL, (_e), NULL)
+
+#if NODE_MINOR_VERSION > 7 || NODE_MAJOR_VERSION > 0
+#define	NODE_MAKECALLBACK_RETURN
+#endif
+
+namespace v8plus {
+
+class ObjectWrap;
+
+class ObjectWrap : public node::ObjectWrap {
+public:
+	static void init(v8::Handle<v8::Object>);
+	static v8::Handle<v8::Value> cons(const v8::Arguments &);
+	static ObjectWrap *objlookup(const void *);
+	v8::Handle<v8::Value> call(const char *, int, v8::Handle<v8::Value>[]);
+	void public_Ref(void);
+	void public_Unref(void);
+
+private:
+	static v8::Persistent<v8::Function> _constructor;
+	static v8plus_method_descr_t *_mtbl;
+	static v8plus_static_descr_t *_stbl;
+	static std::unordered_map<void *, ObjectWrap *> _objhash;
+	void *_c_impl;
+
+	ObjectWrap() : _c_impl(NULL) {};
+	~ObjectWrap();
+
+	static v8::Handle<v8::Value> _new(const v8::Arguments &);
+	static v8::Handle<v8::Value> _entry(const v8::Arguments &);
+	static v8::Handle<v8::Value> _static_entry(const v8::Arguments &);
+};
+
+extern nvlist_t *v8_Arguments_to_nvlist(const v8::Arguments &);
+extern v8::Handle<v8::Value> nvpair_to_v8_Value(const nvpair_t *);
+extern v8::Local<v8::Value> exception(const char *, const nvlist_t *,
+    const char *, ...) __PRINTFLIKE(3);
+
+}; /* namespace v8plus */
+
+#endif	/* _V8PLUS_IMPL_H */
--- /dev/null	2013-10-21 19:08:28.000000000 +0000
+++ new/src/node-lockfd/node_modules/v8plus/v8plus_objectwrap.cc	2013-10-21 19:08:28.643664804 +0000
@@ -0,0 +1,321 @@
+/*
+ * Copyright (c) 2012 Joyent, Inc.  All rights reserved.
+ */
+
+#include <sys/types.h>
+#include <string.h>
+#include <new>
+#include <unordered_map>
+#include <stdlib.h>
+#include <node.h>
+#include "v8plus_impl.h"
+#include "v8plus_glue.h"
+
+#define	METHOD_NAME_FMT	"__v8plus_%s_%s"
+
+v8::Persistent<v8::Function> v8plus::ObjectWrap::_constructor;
+v8plus_method_descr_t *v8plus::ObjectWrap::_mtbl;
+v8plus_static_descr_t *v8plus::ObjectWrap::_stbl;
+std::unordered_map<void *, v8plus::ObjectWrap *> v8plus::ObjectWrap::_objhash;
+
+static char *
+function_name(const char *lambda)
+{
+	char *fn;
+	size_t len;
+
+	len = snprintf(NULL, 0, METHOD_NAME_FMT,
+	    v8plus_js_class_name, lambda);
+	if ((fn = (char *)malloc(len + 1)) == NULL)
+		v8plus_panic("out of memory for function name for %s", lambda);
+
+	(void) snprintf(fn, len + 1, METHOD_NAME_FMT,
+		    v8plus_js_class_name, lambda);
+
+	return (fn);
+}
+
+void
+v8plus::ObjectWrap::init(v8::Handle<v8::Object> target)
+{
+	uint_t i;
+
+	if (v8plus_static_method_count > 0) {
+		const v8plus_static_descr_t *sdp;
+
+		_stbl = new (std::nothrow)
+		    v8plus_static_descr_t[v8plus_static_method_count];
+		if (_stbl == NULL)
+			v8plus_panic("out of memory for static method table");
+
+		for (i = 0; i < v8plus_static_method_count; i++) {
+			v8::Local<v8::FunctionTemplate> fth =
+			    v8::FunctionTemplate::New(_static_entry);
+			v8::Local<v8::Function> fh = fth->GetFunction();
+			sdp = &v8plus_static_methods[i];
+
+			_stbl[i].sd_name = function_name(sdp->sd_name);
+			_stbl[i].sd_c_func = sdp->sd_c_func;
+
+			fh->SetName(v8::String::New(_stbl[i].sd_name));
+
+			target->Set(v8::String::NewSymbol(sdp->sd_name), fh);
+		}
+	}
+
+
+	if (v8plus_method_count > 0) {
+		v8::Local<v8::FunctionTemplate> tpl =
+		    v8::FunctionTemplate::New(_new);
+		const v8plus_method_descr_t *mdp;
+
+		_mtbl = new (std::nothrow)
+		    v8plus_method_descr_t[v8plus_method_count];
+		if (_mtbl == NULL)
+			v8plus_panic("out of memory for method table");
+
+		tpl->SetClassName(v8::String::NewSymbol(v8plus_js_class_name));
+		tpl->InstanceTemplate()->SetInternalFieldCount(
+		    v8plus_method_count);
+
+		for (i = 0; i < v8plus_method_count; i++) {
+			v8::Local<v8::FunctionTemplate> fth =
+			    v8::FunctionTemplate::New(_entry);
+			v8::Local<v8::Function> fh = fth->GetFunction();
+			mdp = &v8plus_methods[i];
+
+			_mtbl[i].md_name = function_name(mdp->md_name);
+			_mtbl[i].md_c_func = mdp->md_c_func;
+
+			fh->SetName(v8::String::New(_mtbl[i].md_name));
+
+			tpl->PrototypeTemplate()->Set(
+			    v8::String::NewSymbol(mdp->md_name), fh);
+		}
+
+		_constructor =
+		    v8::Persistent<v8::Function>::New(tpl->GetFunction());
+
+		target->Set(v8::String::NewSymbol(v8plus_js_factory_name),
+		    v8::FunctionTemplate::New(
+		    v8plus::ObjectWrap::cons)->GetFunction());
+	}
+
+	v8plus_crossthread_init();
+}
+
+v8::Handle<v8::Value>
+v8plus::ObjectWrap::_new(const v8::Arguments &args)
+{
+	v8::HandleScope scope;
+	v8plus::ObjectWrap *op = new v8plus::ObjectWrap();
+	nvlist_t *c_excp;
+	nvlist_t *c_args;
+
+	if ((c_args = v8plus::v8_Arguments_to_nvlist(args)) == NULL)
+		return (V8PLUS_THROW_DEFAULT());
+
+	c_excp = v8plus_ctor(c_args, &op->_c_impl);
+	nvlist_free(c_args);
+	if (op->_c_impl == NULL) {
+		if (c_excp == NULL) {
+			return (V8PLUS_THROW_DEFAULT());
+		} else {
+			return (V8PLUS_THROW_DECORATED(c_excp));
+		}
+	}
+
+	_objhash.insert(std::make_pair(op->_c_impl, op));
+	op->Wrap(args.This());
+
+	return (args.This());
+}
+
+v8plus::ObjectWrap::~ObjectWrap()
+{
+	v8plus_dtor(_c_impl);
+	(void) _objhash.erase(_c_impl);
+}
+
+v8::Handle<v8::Value>
+v8plus::ObjectWrap::cons(const v8::Arguments &args)
+{
+	v8::HandleScope scope;
+	const unsigned argc = 1;
+	v8::Handle<v8::Value> argv[argc] = { args[0] };
+	v8::Local<v8::Object> instance = _constructor->NewInstance(argc, argv);
+
+	return (scope.Close(instance));
+}
+
+v8plus::ObjectWrap *
+v8plus::ObjectWrap::objlookup(const void *cop)
+{
+	std::unordered_map<void *, v8plus::ObjectWrap *>::iterator it;
+
+	if ((it = _objhash.find(const_cast<void *>(cop))) == _objhash.end())
+		v8plus_panic("unable to find C++ wrapper for %p\n", cop);
+
+	return (it->second);
+}
+
+/*
+ * This is the entry point for all methods.  We will start by demultiplexing
+ * out the C method from the function name by which we were called.  There is
+ * probably some mechanism by which overly clever JavaScript code could make
+ * this not match the actual name; this will kill your Node process, so don't
+ * get cute.
+ */
+v8::Handle<v8::Value>
+v8plus::ObjectWrap::_entry(const v8::Arguments &args)
+{
+	v8::HandleScope scope;
+	v8plus::ObjectWrap *op =
+	    node::ObjectWrap::Unwrap<v8plus::ObjectWrap>(args.This());
+	nvlist_t *c_args;
+	nvlist_t *c_out;
+	nvlist_t *excp;
+	nvpair_t *rpp;
+	v8::Local<v8::String> self = args.Callee()->GetName()->ToString();
+	v8::String::Utf8Value selfsv(self);
+	const char *fn = *selfsv;
+	const v8plus_method_descr_t *mdp;
+	v8plus_c_method_f c_method = NULL;
+	uint_t i;
+
+	for (i = 0; i < v8plus_method_count; i++) {
+		mdp = &_mtbl[i];
+		if (strcmp(mdp->md_name, fn) == 0) {
+			c_method = mdp->md_c_func;
+			break;
+		}
+	}
+
+	if (c_method == NULL)
+		v8plus_panic("impossible method name %s\n", fn);
+
+	if ((c_args = v8plus::v8_Arguments_to_nvlist(args)) == NULL)
+		return (V8PLUS_THROW_DEFAULT());
+
+	c_out = c_method(op->_c_impl, c_args);
+	nvlist_free(c_args);
+
+	if (c_out == NULL) {
+		if (_v8plus_errno == V8PLUSERR_NOERROR)
+			return (scope.Close(v8::Undefined()));
+		else
+			return (V8PLUS_THROW_DEFAULT());
+	} else {
+		if (nvlist_lookup_nvlist(c_out, "err", &excp) == 0) {
+			v8::Handle<v8::Value> x = V8PLUS_THROW_DECORATED(excp);
+			nvlist_free(c_out);
+			return (x);
+		} else if (nvlist_lookup_nvpair(c_out, "res", &rpp) == 0) {
+			v8::Handle<v8::Value> r =
+			    v8plus::nvpair_to_v8_Value(rpp);
+			nvlist_free(c_out);
+			return (scope.Close(r));
+		} else {
+			v8plus_panic("bad encoded object in return");
+		}
+	}
+
+	/*NOTREACHED*/
+	return (v8::Undefined());
+}
+
+v8::Handle<v8::Value>
+v8plus::ObjectWrap::_static_entry(const v8::Arguments &args)
+{
+	v8::HandleScope scope;
+	nvlist_t *c_args;
+	nvlist_t *c_out;
+	nvlist_t *excp;
+	nvpair_t *rpp;
+	v8::Local<v8::String> self = args.Callee()->GetName()->ToString();
+	v8::String::Utf8Value selfsv(self);
+	const char *fn = *selfsv;
+	const v8plus_static_descr_t *sdp;
+	v8plus_c_static_f c_static = NULL;
+	uint_t i;
+
+	for (i = 0; i < v8plus_static_method_count; i++) {
+		sdp = &_stbl[i];
+		if (strcmp(sdp->sd_name, fn) == 0) {
+			c_static = sdp->sd_c_func;
+			break;
+		}
+	}
+
+	if (c_static == NULL)
+		v8plus_panic("impossible static method name %s\n", fn);
+
+	if ((c_args = v8plus::v8_Arguments_to_nvlist(args)) == NULL)
+		return (V8PLUS_THROW_DEFAULT());
+
+	c_out = c_static(c_args);
+	nvlist_free(c_args);
+
+	if (c_out == NULL) {
+		if (_v8plus_errno == V8PLUSERR_NOERROR)
+			return (scope.Close(v8::Undefined()));
+		else
+			return (V8PLUS_THROW_DEFAULT());
+	} else {
+		if (nvlist_lookup_nvlist(c_out, "err", &excp) == 0) {
+			v8::Handle<v8::Value> x = V8PLUS_THROW_DECORATED(excp);
+			nvlist_free(c_out);
+			return (x);
+		} else if (nvlist_lookup_nvpair(c_out, "res", &rpp) == 0) {
+			v8::Handle<v8::Value> r =
+			    v8plus::nvpair_to_v8_Value(rpp);
+			nvlist_free(c_out);
+			return (scope.Close(r));
+		} else {
+			v8plus_panic("bad encoded object in return");
+		}
+	}
+
+	/*NOTREACHED*/
+	return (v8::Undefined());
+}
+
+v8::Handle<v8::Value>
+v8plus::ObjectWrap::call(const char *name,
+    int argc, v8::Handle<v8::Value> argv[])
+{
+	v8::Handle<v8::Value> v = v8::Undefined();
+	v8::Local<v8::Value> f = handle_->Get(v8::String::NewSymbol(name));
+
+	/*
+ 	 * XXX - we'd like to throw here, but for some reason our TryCatch
+ 	 * block doesn't seem to handle the exception.
+ 	 */
+	if (!f->IsFunction())
+		return (v8::Undefined());
+
+#ifdef NODE_MAKECALLBACK_RETURN
+	v =
+#endif
+	node::MakeCallback(handle_, name, argc, argv);
+
+	return (v);
+}
+
+void
+v8plus::ObjectWrap::public_Ref(void)
+{
+	this->Ref();
+}
+
+void
+v8plus::ObjectWrap::public_Unref(void)
+{
+	this->Unref();
+}
+
+extern "C" void
+init(v8::Handle<v8::Object> target)
+{
+	v8plus::ObjectWrap::init(target);
+}
--- /dev/null	2013-10-21 19:08:28.000000000 +0000
+++ new/src/node-lockfd/node_modules/v8plus/v8plus_subr.cc	2013-10-21 19:08:28.806292142 +0000
@@ -0,0 +1,647 @@
+/*
+ * Copyright (c) 2012 Joyent, Inc.  All rights reserved.
+ */
+
+#include <sys/types.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <alloca.h>
+#include <dlfcn.h>
+#include <libnvpair.h>
+#include <node.h>
+#include <v8.h>
+#include <unordered_map>
+#include <string>
+#include "v8plus_impl.h"
+
+#define	V8PLUS_OBJ_TYPE_MEMBER	".__v8plus_type"
+#define	V8_EXCEPTION_CTOR_FMT \
+	"_ZN2v89Exception%u%sENS_6HandleINS_6StringEEE"
+
+typedef struct cb_hdl {
+	v8::Handle<v8::Function> ch_hdl;
+	uint_t ch_refs;
+	boolean_t ch_persist;
+} cb_hdl_t;
+
+static std::unordered_map<uint64_t, cb_hdl_t> cbhash;
+static uint64_t cbnext;
+static void (*__real_nvlist_free)(nvlist_t *);
+
+static const char *
+cstr(const v8::String::Utf8Value &v)
+{
+	return (*v);
+}
+
+/*
+ * Convenience macros for adding stuff to an nvlist and returning on failure.
+ */
+#define	LA_U(_l, _n, _e) \
+	if (((_e) = nvlist_add_boolean((_l), (_n))) != 0) \
+		return (_e)
+
+#define	LA_N(_l, _n, _e) \
+	if (((_e) = nvlist_add_byte((_l), (_n), 0)) != 0) \
+		return (_e)
+
+#define	LA_V(_l, _t, _n, _v, _e) \
+	if (((_e) = nvlist_add_##_t((_l), (_n), (_v))) != 0) \
+		return (_e)
+
+#define	LA_VA(_l, _t, _n, _v, _c, _e) \
+	if (((_e) = nvlist_add_##_t##_array((_l), (_n), (_v), (_c))) != 0) \
+		return (_e)
+
+/*
+ * Add an element named <name> to list <lp> with a transcoded value
+ * corresponding to <vh> if possible.  Only primitive types, objects that are
+ * thin wrappers for primitive types, and objects containing members whose
+ * types are all any of the above can be transcoded.
+ *
+ * Booleans and their Object type are encoded as boolean_value.
+ * Numbers and their Object type are encoded as double.
+ * Strings and their Object type are encoded as C strings (and assumed UTF-8).
+ * Any Object (including an Array) is encoded as an nvlist whose elements
+ * are the Object's own properties.
+ * Null is encoded as a byte with value 0.
+ * Undefined is encoded as the valueless boolean.
+ *
+ * Returns EINVAL if any argument fails these tests, or any other error code
+ * that may be returned by nvlist_add_XXX(3nvpair).
+ */
+static int
+nvlist_add_v8_Value(nvlist_t *lp, const char *name,
+    const v8::Handle<v8::Value> &vh)
+{
+	int err = 0;
+
+	if (vh->IsBoolean()) {
+		boolean_t vv = vh->BooleanValue() ? _B_TRUE : _B_FALSE;
+		LA_V(lp, boolean_value, name, vv, err);
+	} else if (vh->IsNumber()) {
+		double vv = vh->NumberValue();
+		LA_V(lp, double, name, vv, err);
+	} else if (vh->IsString()) {
+		v8::String::Utf8Value s(vh);
+		const char *vv = cstr(s);
+		LA_V(lp, string, name, vv, err);
+	} else if (vh->IsUndefined()) {
+		LA_U(lp, name, err);
+	} else if (vh->IsNull()) {
+		LA_N(lp, name, err);
+	} else if (vh->IsNumberObject()) {
+		double vv = vh->NumberValue();
+		LA_V(lp, double, name, vv, err);
+	} else if (vh->IsStringObject()) {
+		v8::String::Utf8Value s(vh);
+		const char *vv = cstr(s);
+		LA_V(lp, string, name, vv, err);
+	} else if (vh->IsBooleanObject()) {
+		boolean_t vv = vh->BooleanValue() ? _B_TRUE : _B_FALSE;
+		LA_V(lp, boolean_value, name, vv, err);
+	} else if (vh->IsFunction()) {
+		cb_hdl_t ch;
+
+		ch.ch_hdl = v8::Handle<v8::Function>::Cast(vh);
+		ch.ch_refs = 1;
+		ch.ch_persist = _B_FALSE;
+
+		while (cbhash.find(cbnext) != cbhash.end())
+			++cbnext;
+		cbhash.insert(std::make_pair(cbnext, ch));
+
+		LA_VA(lp, string, V8PLUS_JSF_COOKIE, NULL, 0, err);
+		LA_VA(lp, uint64, name, &cbnext, 1, err);
+	} else if (vh->IsObject()) {
+		v8::Local<v8::Object> oh = vh->ToObject();
+		v8::Local<v8::Array> keys = oh->GetOwnPropertyNames();
+		v8::Local<v8::String> th = oh->GetConstructorName();
+		v8::String::Utf8Value tv(th);
+		const char *type = cstr(tv);
+		nvlist_t *vlp;
+		uint_t i;
+
+		if ((err = nvlist_alloc(&vlp, NV_UNIQUE_NAME, 0)) != 0)
+			return (err);
+
+		/* XXX this is vile; can we handle this generally? */
+		if (strcmp(type, "Object") != 0) {
+			if (strcmp(type, "Array") == 0) {
+				if ((err = nvlist_add_string(vlp,
+				    V8PLUS_OBJ_TYPE_MEMBER, type)) != 0) {
+					nvlist_free(vlp);
+					return (err);
+				}
+			} else {
+				/*
+				 * XXX This is (C) programmer error.  Should
+				 * we plumb up a way to throw here?
+				 */
+				(void) v8plus_panic("can't handle %s", type);
+			}
+		}
+
+		for (i = 0; i < keys->Length(); i++) {
+			char knname[16];
+			v8::Local<v8::Value> mk;
+			v8::Local<v8::Value> mv;
+			const char *k;
+
+			(void) snprintf(knname, sizeof (knname), "%u", i);
+			mk = keys->Get(v8::String::New(knname));
+			mv = oh->Get(mk);
+			v8::String::Utf8Value mks(mk);
+			k = cstr(mks);
+
+			if ((err = nvlist_add_v8_Value(vlp, k, mv)) != 0) {
+				nvlist_free(vlp);
+				return (err);
+			}
+		}
+
+		LA_V(lp, nvlist, name, vlp, err);
+	} else {
+		return (EINVAL);
+	}
+
+	return (0);
+}
+
+#undef	LA_U
+#undef	LA_N
+#undef	LA_V
+
+nvlist_t *
+v8plus::v8_Arguments_to_nvlist(const v8::Arguments &args)
+{
+	char name[16];
+	nvlist_t *lp;
+	int err;
+	uint_t i;
+
+	if ((err = nvlist_alloc(&lp, NV_UNIQUE_NAME, 0)) != 0)
+		return (v8plus_nverr(err, NULL));
+
+	for (i = 0; i < (uint_t)args.Length(); i++) {
+		(void) snprintf(name, sizeof (name), "%u", i);
+		if ((err = nvlist_add_v8_Value(lp, name, args[i])) != 0) {
+			nvlist_free(lp);
+			return (v8plus_nverr(err, name));
+		}
+	}
+
+	return (lp);
+}
+
+static void
+decorate_object(v8::Local<v8::Object> &oh, const nvlist_t *lp)
+{
+	nvpair_t *pp = NULL;
+
+	while ((pp =
+	    nvlist_next_nvpair(const_cast<nvlist_t *>(lp), pp)) != NULL) {
+		oh->Set(v8::String::New(nvpair_name(pp)),
+		    v8plus::nvpair_to_v8_Value(pp));
+	}
+}
+
+#define	RETURN_JS(_p, _jt, _ct, _xt, _pt) \
+	do { \
+		_ct _v; \
+		(void) nvpair_value_##_pt(const_cast<nvpair_t *>(_p), &_v); \
+		return (v8::_jt::New((_xt)_v)); \
+	} while (0)
+
+v8::Handle<v8::Value>
+v8plus::nvpair_to_v8_Value(const nvpair_t *pp)
+{
+	const char *type;
+
+	switch (nvpair_type(const_cast<nvpair_t *>(pp))) {
+	case DATA_TYPE_BOOLEAN:
+		return (v8::Undefined());
+	case DATA_TYPE_BOOLEAN_VALUE:
+		RETURN_JS(pp, Boolean, boolean_t, bool, boolean_value);
+	case DATA_TYPE_BYTE:
+	{
+		uint8_t _v = (uint8_t)-1;
+
+		if (nvpair_value_byte(const_cast<nvpair_t *>(pp), &_v) != 0 ||
+		    _v != 0) {
+			v8plus_panic("bad byte value %02x\n", _v);
+		}
+
+		return (v8::Null());
+	}
+	case DATA_TYPE_INT8:
+		RETURN_JS(pp, Number, int8_t, double, int8);
+	case DATA_TYPE_UINT8:
+		RETURN_JS(pp, Number, uint8_t, double, uint8);
+	case DATA_TYPE_INT16:
+		RETURN_JS(pp, Number, int16_t, double, int16);
+	case DATA_TYPE_UINT16:
+		RETURN_JS(pp, Number, uint16_t, double, uint16);
+	case DATA_TYPE_INT32:
+		RETURN_JS(pp, Number, int32_t, double, int32);
+	case DATA_TYPE_UINT32:
+		RETURN_JS(pp, Number, uint32_t, double, uint32);
+	case DATA_TYPE_INT64:
+		RETURN_JS(pp, Number, int64_t, double, int64);
+	case DATA_TYPE_UINT64:
+		RETURN_JS(pp, Number, uint64_t, double, uint64);
+	case DATA_TYPE_DOUBLE:
+		RETURN_JS(pp, Number, double, double, double);
+	case DATA_TYPE_STRING:
+		RETURN_JS(pp, String, char *, const char *, string);
+	case DATA_TYPE_UINT64_ARRAY:
+	{
+		std::unordered_map<uint64_t, cb_hdl_t>::iterator it;
+		uint64_t *vp;
+		uint_t nv;
+		int err;
+
+		if ((err = nvpair_value_uint64_array(const_cast<nvpair_t *>(pp),
+		    &vp, &nv)) != 0)
+			v8plus_panic("bad JSFUNC pair: %s", strerror(err));
+		if (nv != 1)
+			v8plus_panic("bad uint64 array length %u", nv);
+		if ((it = cbhash.find(*vp)) == cbhash.end())
+			v8plus_panic("callback hash tag %llu not found", *vp);
+
+		return (it->second.ch_hdl);
+	}
+	case DATA_TYPE_NVLIST:
+	{
+		nvlist_t *lp;
+		v8::Local<v8::Object> oh;
+
+		(void) nvpair_value_nvlist(const_cast<nvpair_t *>(pp), &lp);
+
+		if (nvlist_lookup_string(const_cast<nvlist_t *>(lp),
+		    V8PLUS_OBJ_TYPE_MEMBER, const_cast<char **>(&type)) != 0)
+			type = "Object";
+
+		if (strcmp(type, "Array") == 0)
+			oh = v8::Array::New()->ToObject();
+		else if (strcmp(type, "Object") != 0)
+			v8plus_panic("bad object type %s\n", type);
+		else
+			oh = v8::Object::New();
+
+		decorate_object(oh, lp);
+		return (oh);
+	}
+	default:
+		v8plus_panic("bad data type %d\n",
+		    nvpair_type(const_cast<nvpair_t *>(pp)));
+	}
+
+	/*NOTREACHED*/
+	return (v8::Undefined());
+}
+
+#undef	RETURN_JS
+
+static uint_t
+nvlist_length(const nvlist_t *lp)
+{
+	uint_t l = 0;
+	nvpair_t *pp = NULL;
+
+	while ((pp =
+	    nvlist_next_nvpair(const_cast<nvlist_t *>(lp), pp)) != NULL)
+		++l;
+
+	return (l);
+}
+
+static void
+nvlist_to_v8_argv(const nvlist_t *lp, int *argcp, v8::Handle<v8::Value> *argv)
+{
+	nvpair_t *pp;
+	char name[16];
+	int i;
+
+	for (i = 0; i < *argcp; i++) {
+		(void) snprintf(name, sizeof (name), "%u", i);
+		if (nvlist_lookup_nvpair(const_cast<nvlist_t *>(lp),
+		    name, &pp) != 0)
+			break;
+		argv[i] = v8plus::nvpair_to_v8_Value(pp);
+	}
+
+	*argcp = i;
+}
+
+static v8::Local<v8::Value>
+sexception(const char *type, const nvlist_t *lp, const char *msg)
+{
+	char *ctor_name;
+	v8::Local<v8::Value> (*excp_ctor)(v8::Handle<v8::String>);
+	void *obj_hdl;
+	size_t len;
+	v8::Local<v8::Value> excp;
+	v8::Local<v8::Object> obj;
+	v8::Local<v8::String> jsmsg = v8::String::New(msg);
+
+	if (type == NULL) {
+		type = v8plus_excptype(_v8plus_errno);
+		if (type == NULL)
+			type = "Error";
+	}
+
+	len = snprintf(NULL, 0, V8_EXCEPTION_CTOR_FMT,
+	    (uint_t)strlen(type), type);
+	ctor_name = reinterpret_cast<char *>(alloca(len + 1));
+	(void) snprintf(ctor_name, len + 1, V8_EXCEPTION_CTOR_FMT,
+	    (uint_t)strlen(type), type);
+
+	obj_hdl = dlopen(NULL, RTLD_NOLOAD);
+	if (obj_hdl == NULL)
+		v8plus_panic("%s\n", dlerror());
+
+	excp_ctor = (v8::Local<v8::Value>(*)(v8::Handle<v8::String>))(
+	    dlsym(obj_hdl, ctor_name));
+
+	if (excp_ctor == NULL) {
+		(void) dlclose(obj_hdl);
+		if (strcmp(type, "Error") == 0) {
+			v8plus_panic("Unable to find %s, aborting\n",
+			    ctor_name);
+		} else {
+			excp = v8::Exception::Error(v8::String::New(
+			    "Nested exception: illegal exception type"));
+			return (excp);
+		}
+	}
+
+	excp = excp_ctor(jsmsg);
+	(void) dlclose(obj_hdl);
+
+	if (lp == NULL)
+		return (excp);
+
+	obj = excp->ToObject();
+	decorate_object(obj, lp);
+
+	return (excp);
+}
+
+v8::Local<v8::Value>
+v8plus::exception(const char *type, const nvlist_t *lp, const char *fmt, ...)
+{
+	v8::Local<v8::Value> exception;
+	char *msg;
+	size_t len;
+	va_list ap;
+
+	if (fmt != NULL) {
+		va_start(ap, fmt);
+		len = vsnprintf(NULL, 0, fmt, ap);
+		va_end(ap);
+		msg = reinterpret_cast<char *>(alloca(len + 1));
+
+		va_start(ap, fmt);
+		(void) vsnprintf(msg, len + 1, fmt, ap);
+		va_end(ap);
+	} else {
+		msg = _v8plus_errmsg;
+	}
+
+	exception = sexception(type, lp, msg);
+
+	return (exception);
+}
+
+extern "C" nvlist_t *
+v8plus_call_direct(v8plus_jsfunc_t f, const nvlist_t *lp)
+{
+	std::unordered_map<uint64_t, cb_hdl_t>::iterator it;
+	const int max_argc = nvlist_length(lp);
+	int argc, err;
+	v8::Handle<v8::Value> argv[max_argc];
+	v8::Handle<v8::Value> res;
+	nvlist_t *rp;
+
+	if ((it = cbhash.find(f)) == cbhash.end())
+		v8plus_panic("callback hash tag %llu not found", f);
+
+	argc = max_argc;
+	nvlist_to_v8_argv(lp, &argc, argv);
+
+	if ((err = nvlist_alloc(&rp, NV_UNIQUE_NAME, 0)) != 0)
+		return (v8plus_nverr(err, NULL));
+
+	v8::TryCatch tc;
+	res = it->second.ch_hdl->Call(v8::Context::GetCurrent()->Global(),
+	    argc, argv);
+	if (tc.HasCaught()) {
+		err = nvlist_add_v8_Value(rp, "err", tc.Exception());
+		tc.Reset();
+		if (err != 0) {
+			nvlist_free(rp);
+			return (v8plus_nverr(err, "err"));
+		}
+	} else if ((err = nvlist_add_v8_Value(rp, "res", res)) != 0) {
+		nvlist_free(rp);
+		return (v8plus_nverr(err, "res"));
+	}
+
+	return (rp);
+}
+
+extern "C" nvlist_t *
+v8plus_method_call_direct(void *cop, const char *name, const nvlist_t *lp)
+{
+	v8plus::ObjectWrap *op = v8plus::ObjectWrap::objlookup(cop);
+	const int max_argc = nvlist_length(lp);
+	int argc, err;
+	v8::Handle<v8::Value> argv[max_argc];
+	v8::Handle<v8::Value> res;
+	nvlist_t *rp;
+
+	if (v8plus_in_event_thread() != _B_TRUE)
+		v8plus_panic("direct method call outside of event loop");
+
+	argc = max_argc;
+	nvlist_to_v8_argv(lp, &argc, argv);
+
+	if ((err = nvlist_alloc(&rp, NV_UNIQUE_NAME, 0)) != 0)
+		return (v8plus_nverr(err, NULL));
+
+	v8::TryCatch tc;
+	res = op->call(name, argc, argv);
+	if (tc.HasCaught()) {
+		err = nvlist_add_v8_Value(rp, "err", tc.Exception());
+		tc.Reset();
+		if (err != 0) {
+			nvlist_free(rp);
+			return (v8plus_nverr(err, "err"));
+		}
+	} else if ((err = nvlist_add_v8_Value(rp, "res", res)) != 0) {
+		nvlist_free(rp);
+		return (v8plus_nverr(err, "res"));
+	}
+
+	return (rp);
+}
+
+extern "C" int
+nvlist_lookup_v8plus_jsfunc(const nvlist_t *lp, const char *name,
+    v8plus_jsfunc_t *vp)
+{
+	uint64_t *lvp;
+	uint_t nv;
+	int err;
+
+	err = nvlist_lookup_uint64_array(const_cast<nvlist_t *>(lp),
+	    name, &lvp, &nv);
+	if (err != 0)
+		return (err);
+
+	if (nv != 1)
+		v8plus_panic("bad array size %u for callback hash tag", nv);
+
+	*vp = *lvp;
+	return (0);
+}
+
+extern "C" void
+v8plus_jsfunc_hold(v8plus_jsfunc_t f)
+{
+	v8::Persistent<v8::Function> pfh;
+	std::unordered_map<uint64_t, cb_hdl_t>::iterator it;
+
+	if ((it = cbhash.find(f)) == cbhash.end())
+		v8plus_panic("callback hash tag %llu not found", f);
+
+	if (!it->second.ch_persist) {
+		pfh = v8::Persistent<v8::Function>::New(it->second.ch_hdl);
+		it->second.ch_hdl = pfh;
+		it->second.ch_persist = _B_TRUE;
+	}
+	++it->second.ch_refs;
+}
+
+extern "C" void
+v8plus_jsfunc_rele_direct(v8plus_jsfunc_t f)
+{
+	v8::Local<v8::Function> lfh;
+	std::unordered_map<uint64_t, cb_hdl_t>::iterator it;
+
+	if ((it = cbhash.find(f)) == cbhash.end())
+		v8plus_panic("callback hash tag %llu not found", f);
+
+	if (it->second.ch_refs == 0)
+		v8plus_panic("releasing unheld callback hash tag %llu", f);
+
+	if (--it->second.ch_refs == 0) {
+		if (it->second.ch_persist) {
+			v8::Persistent<v8::Function> pfh(it->second.ch_hdl);
+			pfh.Dispose();
+		}
+		cbhash.erase(it);
+	}
+}
+
+static size_t
+library_name(const char *base, const char *version, char *buf, size_t len)
+{
+#ifdef __MACH__
+	return (snprintf(buf, len, "lib%s.%s%sdylib", base,
+	    version ? version : "", version ? "." : ""));
+#else
+	return (snprintf(buf, len, "lib%s.so%s%s", base,
+	    version ? "." : "", version ? version : ""));
+#endif
+}
+
+/*
+ * This is really gross: we need to free up JS function slots when then list
+ * is freed, but there's no way for us to know that's happening.  So we
+ * interpose on nvlist_free() here, checking for function slots to free iff
+ * this is a list that has a V8 JS function handle in it.  Lists created by
+ * someone else, even if they have uint64 arrays in them, are passed through.
+ * This whole thing makes me want to cry.  Why can't we just have a decent
+ * JS VM?!
+ */
+extern "C" void
+nvlist_free(nvlist_t *lp)
+{
+	uint64_t *vp;
+	uint_t nv;
+	nvpair_t *pp = NULL;
+
+	if (lp == NULL)
+		return;
+
+	if (__real_nvlist_free == NULL) {
+		char *libname;
+		size_t len;
+		void *dlhdl;
+
+		len = library_name("nvpair", "1", NULL, 0) + 1;
+		libname = reinterpret_cast<char *>(alloca(len));
+		(void) library_name("nvpair", "1", libname, len);
+
+		dlhdl = dlopen(libname, RTLD_LAZY | RTLD_LOCAL);
+		if (dlhdl == NULL) {
+			v8plus_panic("unable to dlopen libnvpair: %s",
+			    dlerror());
+		}
+		__real_nvlist_free = (void (*)(nvlist_t *))
+		    dlsym(dlhdl, "nvlist_free");
+		if (__real_nvlist_free == NULL)
+			v8plus_panic("unable to find nvlist_free");
+	}
+
+	if (nvlist_exists(lp, V8PLUS_JSF_COOKIE)) {
+		while ((pp = nvlist_next_nvpair(lp, pp)) != NULL) {
+			if (nvpair_type(pp) != DATA_TYPE_UINT64_ARRAY)
+				continue;
+			if (nvpair_value_uint64_array(pp, &vp, &nv) != 0) {
+				v8plus_panic(
+				    "unable to obtain callbach hash tag");
+			}
+			if (nv != 1) {
+				v8plus_panic(
+				    "bad array size %u for callback hash tag",
+				    nv);
+			}
+			v8plus_jsfunc_rele(*vp);
+		}
+	}
+
+	__real_nvlist_free(lp);
+}
+
+extern "C" int
+nvpair_value_v8plus_jsfunc(const nvpair_t *pp, v8plus_jsfunc_t *vp)
+{
+	uint64_t *lvp;
+	uint_t nv;
+	int err;
+
+	if ((err = nvpair_value_uint64_array((nvpair_t *)pp, &lvp, &nv)) != 0)
+		return (err);
+
+	*vp = *lvp;
+
+	return (0);
+}
+
+extern "C" void
+v8plus_obj_hold(const void *cop)
+{
+	v8plus::ObjectWrap *op = v8plus::ObjectWrap::objlookup(cop);
+	op->public_Ref();
+}
+
+extern "C" void
+v8plus_obj_rele_direct(const void *cop)
+{
+	v8plus::ObjectWrap *op = v8plus::ObjectWrap::objlookup(cop);
+	op->public_Unref();
+}
--- /dev/null	2013-10-21 19:08:29.000000000 +0000
+++ new/src/node-lockfd/package.json	2013-10-21 19:08:28.970481595 +0000
@@ -0,0 +1,14 @@
+{
+  "name": "lockfd",
+  "description": "thin wrapper around fcntl(F_SETLK)",
+  "version": "0.0.2",
+  "author": "Joshua M. Clulow <jmc@joyent.com>",
+  "repository": "git://github.com/joyent/node-lockfd.git",
+  "dependencies": {
+    "v8plus": "~0.1.0"
+  },
+  "scripts": {
+    "postinstall": "cd src && gmake $(eval echo ${MAKE_OVERRIDES})"
+  },
+  "license": "MIT"
+}
--- /dev/null	2013-10-21 19:08:29.000000000 +0000
+++ new/src/node-lockfd/src/Makefile	2013-10-21 19:08:29.150842746 +0000
@@ -0,0 +1,25 @@
+#
+# Copyright (c) 2013 Joyent, Inc.  All rights reserved.
+#
+
+PREFIX_NODE :=	$(shell dirname $$(bash -c 'hash node; hash -t node'))/..
+V8PLUS :=       $(shell $(PREFIX_NODE)/bin/node -e 'require("v8plus");')
+
+include $(V8PLUS)/Makefile.v8plus.defs
+
+MODULE =	lockfd_binding
+
+SRCS =	\
+		lockfd.c
+
+ERRNO_JSON =	errno.json
+
+CC =		/opt/local/bin/gcc
+CXX =		/opt/local/bin/g++
+
+#WARN_FLAGS +=	-Wno-error=unused-parameter
+
+#LDFLAGS +=	-L/usr/lib/fm -R/usr/lib/fm
+LIBS +=		-lumem
+
+include $(V8PLUS)/Makefile.v8plus.targ
--- /dev/null	2013-10-21 19:08:29.000000000 +0000
+++ new/src/node-lockfd/src/errno.json	2013-10-21 19:08:29.322790762 +0000
@@ -0,0 +1,5 @@
+{
+  "error_base": "0x8a6d71",
+  "errors": [
+  ]
+}
--- /dev/null	2013-10-21 19:08:29.000000000 +0000
+++ new/src/node-lockfd/src/lockfd.c	2013-10-21 19:08:29.463862908 +0000
@@ -0,0 +1,143 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <pthread.h>
+
+#include <libnvpair.h>
+
+#include "v8plus_glue.h"
+
+typedef struct lockfd_args {
+	v8plus_jsfunc_t lfa_cb;
+	int lfa_fd;
+	struct flock lfa_flock;
+	boolean_t lfa_run_sync;
+} lockfd_args_t;
+
+/*
+ * Worker thread for blocking fcntl() calls:
+ */
+static void *
+lockfd_thread(void *arg)
+{
+	lockfd_args_t *lfa = arg;
+	nvlist_t *ap;
+	int ret, en = 0;
+	char *errmsg = "";
+
+	errno = 0;
+	if ((ret = fcntl(lfa->lfa_fd, F_SETLKW, &lfa->lfa_flock)) == -1) {
+		errmsg = strerror(en);
+	}
+
+	/*
+	 * Call back into JS:
+	 */
+	ap = v8plus_obj(
+	    V8PLUS_TYPE_NUMBER, "0", (double) ret,
+	    V8PLUS_TYPE_NUMBER, "1", (double) en,
+	    V8PLUS_TYPE_STRING, "2", errmsg,
+	    V8PLUS_TYPE_NONE);
+	(void) v8plus_call(lfa->lfa_cb, ap);
+	nvlist_free(ap);
+
+	if (!lfa->lfa_run_sync) {
+		/*
+		 * Release our callback, held from the ititial call:
+		 */
+		v8plus_jsfunc_rele(lfa->lfa_cb);
+	}
+
+	free(lfa);
+
+	return (NULL);
+}
+
+/*
+ * Primary entrypoint from Javascript:
+ */
+static nvlist_t *
+lockfd_lockfd(const nvlist_t *ap)
+{
+	lockfd_args_t *lfa = calloc(1, sizeof (*lfa));
+	pthread_t newthr;
+	double double_fd;
+	char *type;
+
+	if (v8plus_args(ap, V8PLUS_ARG_F_NOEXTRA,
+	    V8PLUS_TYPE_NUMBER, &double_fd,
+	    V8PLUS_TYPE_STRING, &type,
+	    V8PLUS_TYPE_BOOLEAN, &lfa->lfa_run_sync,
+	    V8PLUS_TYPE_JSFUNC, &lfa->lfa_cb,
+	    V8PLUS_TYPE_NONE) != 0) {
+		free(lfa);
+		return (v8plus_error(V8PLUSERR_BADARG, "bad args"));
+	}
+	lfa->lfa_fd = double_fd;
+
+	/*
+	 * Configure the flock struct for locking:
+	 */
+	if (strcmp(type, "read") == 0) {
+		lfa->lfa_flock.l_type = F_RDLCK;
+	} else if (strcmp(type, "write") == 0) {
+		lfa->lfa_flock.l_type = F_WRLCK;
+	} else if (strcmp(type, "unlock") == 0) {
+		lfa->lfa_flock.l_type = F_UNLCK;
+	} else {
+		free(lfa);
+		return (v8plus_error(V8PLUSERR_BADARG, "bad args: type"));
+	}
+	lfa->lfa_flock.l_whence = SEEK_SET;
+	lfa->lfa_flock.l_start = 0;
+	lfa->lfa_flock.l_len = 0;
+
+
+	if (lfa->lfa_run_sync) {
+		/*
+		 * Run the blocking fcntl() call in the current thread:
+		 */
+		lockfd_thread(lfa);
+	} else {
+		/*
+		 * Hold this function so that we can call it later from
+		 * the other thread:
+		 */
+		v8plus_jsfunc_hold(lfa->lfa_cb);
+
+		/*
+		 * Create a thread for the blocking fcntl(F_SETLKW) call:
+		 */
+		if (pthread_create(&newthr, NULL, lockfd_thread, lfa) != 0) {
+			return (v8plus_error(V8PLUSERR_UNKNOWN,
+			    "could not create thread"));
+		}
+	}
+
+	return (v8plus_void());
+}
+
+/*
+ * v8plus Boilerplate
+ */
+const v8plus_c_ctor_f v8plus_ctor = NULL;
+const v8plus_c_dtor_f v8plus_dtor = NULL;
+const char *v8plus_js_factory_name = NULL;
+const char *v8plus_js_class_name = NULL;
+
+const v8plus_method_descr_t v8plus_methods[] = {};
+const uint_t v8plus_method_count =
+    sizeof (v8plus_methods) / sizeof (v8plus_methods[0]);
+
+const v8plus_static_descr_t v8plus_static_methods[] = {
+	{
+		sd_name: "lock_fd",
+		sd_c_func: lockfd_lockfd
+	}
+};
+const uint_t v8plus_static_method_count =
+    sizeof (v8plus_static_methods) / sizeof (v8plus_static_methods[0]);
