1 /*
   2  * Copyright (c) 2012 Joyent, Inc.  All rights reserved.
   3  */
   4 
   5 #ifndef _V8PLUS_GLUE_H
   6 #define _V8PLUS_GLUE_H
   7 
   8 #include <stdarg.h>
   9 #include <libnvpair.h>
  10 #include "v8plus_errno.h"
  11 
  12 #ifdef  __cplusplus
  13 extern "C" {
  14 #endif  /* __cplusplus */
  15 
  16 #define __UNUSED        __attribute__((__unused__))
  17 
  18 #define V8PLUS_ARG_F_NOEXTRA    0x01
  19 
  20 #define V8PLUS_ERRMSG_LEN       512
  21 #define V8PLUS_JSF_COOKIE       ".__v8plus_jsfunc_cookie"
  22 
  23 typedef enum v8plus_type {
  24         V8PLUS_TYPE_NONE = 0,           /* N/A */
  25         V8PLUS_TYPE_STRING,             /* char * */
  26         V8PLUS_TYPE_NUMBER,             /* double */
  27         V8PLUS_TYPE_BOOLEAN,            /* boolean_t */
  28         V8PLUS_TYPE_JSFUNC,             /* v8plus_jsfunc_t */
  29         V8PLUS_TYPE_OBJECT,             /* nvlist_t * */
  30         V8PLUS_TYPE_NULL,               /* -- */
  31         V8PLUS_TYPE_UNDEFINED,          /* -- */
  32         V8PLUS_TYPE_INVALID,            /* data_type_t */
  33         V8PLUS_TYPE_ANY,                /* nvpair_t * */
  34         V8PLUS_TYPE_STRNUMBER64,        /* uint64_t */
  35         V8PLUS_TYPE_INL_OBJECT          /* ... */
  36 } v8plus_type_t;
  37 
  38 typedef uint64_t v8plus_jsfunc_t;
  39 
  40 /*
  41  * C constructor, destructor, and method prototypes.  See README.md.
  42  */
  43 typedef nvlist_t *(*v8plus_c_ctor_f)(const nvlist_t *, void **);
  44 typedef nvlist_t *(*v8plus_c_static_f)(const nvlist_t *);
  45 typedef nvlist_t *(*v8plus_c_method_f)(void *, const nvlist_t *);
  46 typedef void (*v8plus_c_dtor_f)(void *);
  47 
  48 typedef struct v8plus_method_descr {
  49         const char *md_name;
  50         v8plus_c_method_f md_c_func;
  51 } v8plus_method_descr_t;
  52 
  53 typedef struct v8plus_static_descr {
  54         const char *sd_name;
  55         v8plus_c_static_f sd_c_func;
  56 } v8plus_static_descr_t;
  57 
  58 extern __thread v8plus_errno_t _v8plus_errno;
  59 extern __thread char _v8plus_errmsg[V8PLUS_ERRMSG_LEN];
  60 
  61 /*
  62  * Set the errno and message, indicating an error.  The code and
  63  * printf-formatted message, if one is given, will be used in constructing
  64  * an exception to be thrown in JavaScript if your method later returns NULL
  65  * or an nvlist with an "err" member.
  66  */
  67 extern nvlist_t *v8plus_verror(v8plus_errno_t, const char *, va_list);
  68 extern nvlist_t *v8plus_error(v8plus_errno_t, const char *, ...);
  69 
  70 /*
  71  * Suicide.  It's always an option.  Try to avoid using this as it's not
  72  * very nice to kill the entire node process; if at all possible we need
  73  * to throw a JavaScript exception instead.
  74  */
  75 extern void v8plus_panic(const char *, ...) __PRINTFLIKE(1) __NORETURN;
  76 
  77 /*
  78  * As above, this convenience function sets the error code and message based
  79  * on the nvlist-generated error code in its first argument.  The second
  80  * argument, which may be NULL, should contain the name of the member on
  81  * which the error occurred.
  82  */
  83 extern nvlist_t *v8plus_nverr(int, const char *);
  84 
  85 /*
  86  * Similarly, for system errors.  Not all possible errno values are handled.
  87  */
  88 extern nvlist_t *v8plus_syserr(int, const char *, ...);
  89 
  90 /*
  91  * Clear the errno and message.  This is needed only when one wishes to return
  92  * NULL from a C method whose return type is effectively void.  The idiom is
  93  *
  94  * return (v8plus_void());
  95  */
  96 extern nvlist_t *v8plus_void(void);
  97 
  98 /*
  99  * Find the named V8 function in the nvlist.  Analogous to other lookup
 100  * routines; see libnvpair(3lib), with an important exception: the
 101  * nvlist_lookup_v8plus_jsfunc() and nvpair_value_v8plus_jsfunc() functions
 102  * place a hold on the underlying function object, which must be released by C
 103  * code when it is no longer needed.  See the documentation to understand how
 104  * this works.  The add routine is of very limited utility because there is no
 105  * mechanism for creating a JS function from C.  It can however be used to
 106  * return a function (or object containing one, etc.) from a deferred
 107  * completion routine in which a JS function has been invoked that returned
 108  * such a thing to us.
 109  */
 110 extern int nvlist_lookup_v8plus_jsfunc(const nvlist_t *, const char *,
 111     v8plus_jsfunc_t *);
 112 extern int nvpair_value_v8plus_jsfunc(const nvpair_t *, v8plus_jsfunc_t *);
 113 extern void v8plus_jsfunc_hold(v8plus_jsfunc_t);
 114 extern void v8plus_jsfunc_rele(v8plus_jsfunc_t);
 115 extern void v8plus_jsfunc_rele_direct(v8plus_jsfunc_t);
 116 
 117 /*
 118  * Place or release a hold on the V8 representation of the specified C object.
 119  * This is rarely necessary; v8plus_defer() performs this action for you, but
 120  * other asynchronous mechanisms may require it.  If you are returning from
 121  * a method call but have stashed a reference to the object somewhere and are
 122  * not calling v8plus_defer(), you must call this first.  Holds and releases
 123  * must be balanced.  Use of the object within a thread after releasing is a
 124  * bug.
 125  */
 126 extern void v8plus_obj_hold(const void *);
 127 extern void v8plus_obj_rele(const void *);
 128 extern void v8plus_obj_rele_direct(const void *);
 129 
 130 /*
 131  * Convenience functions for dealing with JS arguments.
 132  */
 133 extern v8plus_type_t v8plus_typeof(const nvpair_t *);
 134 extern int v8plus_args(const nvlist_t *, uint_t, v8plus_type_t t, ...);
 135 extern nvlist_t *v8plus_obj(v8plus_type_t, ...);
 136 extern int v8plus_obj_setprops(nvlist_t *, v8plus_type_t, ...);
 137 
 138 /*
 139  * Perform a background, possibly blocking and/or expensive, task.  First,
 140  * the worker function will be enqueued for execution on another thread; its
 141  * first argument is a pointer to the C object on which to operate, and the
 142  * second is arbitrary per-call context, arguments, etc. defined by the caller.
 143  * When that worker function has completed execution, the completion function
 144  * will be invoked in the main thread.  Its arguments are the C object, the
 145  * original context pointer, and the return value from the worker function.
 146  * See the documentation for a typical use case.
 147  */
 148 typedef void *(*v8plus_worker_f)(void *, void *);
 149 typedef void (*v8plus_completion_f)(void *, void *, void *);
 150 
 151 extern void v8plus_defer(void *, void *, v8plus_worker_f, v8plus_completion_f);
 152 
 153 /*
 154  * Call an opaque JavaScript function from C.  The caller is responsible for
 155  * freeing the returned list.  The first argument is not const because it is
 156  * possible for the JS code to modify the function represented by the cookie.
 157  */
 158 extern nvlist_t *v8plus_call(v8plus_jsfunc_t, const nvlist_t *);
 159 extern nvlist_t *v8plus_call_direct(v8plus_jsfunc_t, const nvlist_t *);
 160 
 161 /*
 162  * Call the named JavaScript function in the context of the JS object
 163  * represented by the native object.  Calling and return conventions are the
 164  * same as for the C interfaces; i.e., the nvlist will be converted into JS
 165  * objects and the return value or exception will be in the "res" or "err"
 166  * members of the nvlist that is returned, respectively.  If an internal
 167  * error occurs, NULL is returned and _v8plus_errno set accordingly.  The
 168  * results of calling a method implemented in C via this interface are
 169  * undefined.
 170  *
 171  * These methods can be used in concert with JS code to emit events
 172  * asynchronously; see the documentation.
 173  *
 174  * Note: As JavaScript functions must be called from the event loop thread,
 175  * v8plus_method_call() contains logic to determine whether we are in the
 176  * correct context or not.  If we are running on some other thread we will
 177  * queue the request and sleep, waiting for the event loop thread to make the
 178  * call.  In the simple case, where we are already in the correct thread,
 179  * we make the call directly.  v8plus_method_call_direct() assumes we are
 180  * on the correct thread and always makes the call directly.
 181  */
 182 extern nvlist_t *v8plus_method_call(void *, const char *, const nvlist_t *);
 183 extern nvlist_t *v8plus_method_call_direct(void *, const char *,
 184     const nvlist_t *);
 185 
 186 /*
 187  * These functions allow the consumer to hold the V8 event loop open for
 188  * potential input from other threads.  If your process blocks in another
 189  * thread, e.g. an event subscription thread, you must signal to v8plus
 190  * that the event loop should remain active.  Calls to v8plus_eventloop_hold()
 191  * and v8plus_eventloop_rele() should be balanced.  It is safe to call
 192  * v8plus_eventloop_rele() from outside the event loop thread.
 193  *
 194  * Note: Holds obtained via v8plus_obj_hold() and v8plus_jsfunc_hold() will
 195  * also automatically hold the event loop, removing the need to use this
 196  * interface explicitly.
 197  */
 198 extern void v8plus_eventloop_hold(void);
 199 extern void v8plus_eventloop_rele(void);
 200 extern void v8plus_eventloop_rele_direct(void);
 201 
 202 /*
 203  * These methods are analogous to strerror(3c) and similar functions; they
 204  * translate among error names, codes, and default messages.  There is
 205  * normally little need for these functions in C methods, as everything
 206  * necessary to construct a JavaScript exception is done by v8+, but these
 207  * may be useful in the construction of supplementary exception decorations
 208  * for debugging purposes.
 209  */
 210 extern const char *v8plus_strerror(v8plus_errno_t);
 211 extern const char *v8plus_errname(v8plus_errno_t);
 212 extern const char *v8plus_excptype(v8plus_errno_t);
 213 
 214 /*
 215  * Provided by C code.  See README.md.
 216  */
 217 extern const v8plus_c_ctor_f v8plus_ctor;
 218 extern const v8plus_c_dtor_f v8plus_dtor;
 219 extern const char *v8plus_js_factory_name;
 220 extern const char *v8plus_js_class_name;
 221 extern const v8plus_method_descr_t v8plus_methods[];
 222 extern const uint_t v8plus_method_count;
 223 extern const v8plus_static_descr_t v8plus_static_methods[];
 224 extern const uint_t v8plus_static_method_count;
 225 
 226 /*
 227  * Private methods.
 228  */
 229 extern boolean_t v8plus_in_event_thread(void);
 230 extern void v8plus_crossthread_init(void);
 231 
 232 #ifdef  __cplusplus
 233 }
 234 #endif  /* __cplusplus */
 235 
 236 #endif  /* _V8PLUS_GLUE_H */