1 /* 2 * Copyright (c) 2012 Joyent, Inc. All rights reserved. 3 */ 4 5 #include <sys/ccompile.h> 6 #include <stdlib.h> 7 #include <float.h> 8 #include <errno.h> 9 #include <libnvpair.h> 10 #include "example.h" 11 12 static nvlist_t * 13 example_set_impl(example_t *ep, nvpair_t *pp) 14 { 15 double dv; 16 const char *sv; 17 const char *ev; 18 uint64_t v; 19 20 switch (v8plus_typeof(pp)) { 21 case V8PLUS_TYPE_NUMBER: 22 (void) nvpair_value_double(pp, &dv); 23 if (dv > (1ULL << DBL_MANT_DIG) - 1) { 24 return (v8plus_error(V8PLUSERR_IMPRECISE, 25 "large number lacks integer precision")); 26 } 27 ep->e_val = (uint64_t)dv; 28 break; 29 case V8PLUS_TYPE_STRING: 30 (void) nvpair_value_string(pp, (char **)&sv); 31 errno = 0; 32 v = (uint64_t)strtoull(sv, (char **)&ev, 0); 33 if (errno == ERANGE) { 34 return (v8plus_error(V8PLUSERR_RANGE, 35 "value '%s' is out of range", sv)); 36 } 37 if (ev != NULL && *ev != '\0') { 38 return (v8plus_error(V8PLUSERR_MALFORMED, 39 "value '%s' is malformed", sv)); 40 } 41 ep->e_val = v; 42 break; 43 case V8PLUS_TYPE_UNDEFINED: 44 ep->e_val = 0; 45 break; 46 default: 47 return (v8plus_error(V8PLUSERR_BADARG, 48 "argument 0 is of incorrect type %d", v8plus_typeof(pp))); 49 } 50 51 return (v8plus_void()); 52 } 53 54 static nvlist_t * 55 example_ctor(const nvlist_t *ap, void **epp) 56 { 57 nvpair_t *pp; 58 example_t *ep; 59 60 if (v8plus_args(ap, V8PLUS_ARG_F_NOEXTRA, V8PLUS_TYPE_NONE) != 0 && 61 v8plus_args(ap, V8PLUS_ARG_F_NOEXTRA, 62 V8PLUS_TYPE_ANY, &pp, V8PLUS_TYPE_NONE) != 0) 63 return (NULL); 64 65 if ((ep = malloc(sizeof (example_t))) == NULL) 66 return (v8plus_error(V8PLUSERR_NOMEM, NULL)); 67 68 (void) example_set_impl(ep, pp); 69 if (_v8plus_errno != V8PLUSERR_NOERROR) { 70 free(ep); 71 return (NULL); 72 } 73 74 *epp = ep; 75 76 return (v8plus_void()); 77 } 78 79 static void 80 example_dtor(void *op) 81 { 82 free(op); 83 } 84 85 static nvlist_t * 86 example_set(void *op, const nvlist_t *ap) 87 { 88 nvpair_t *pp; 89 example_t *ep = op; 90 91 if (v8plus_args(ap, V8PLUS_ARG_F_NOEXTRA, 92 V8PLUS_TYPE_ANY, &pp, 93 V8PLUS_TYPE_NONE) != 0) 94 return (NULL); 95 96 (void) example_set_impl(ep, pp); 97 if (_v8plus_errno != V8PLUSERR_NOERROR) 98 return (NULL); 99 100 return (v8plus_void()); 101 } 102 103 static nvlist_t * 104 example_add(void *op, const nvlist_t *ap) 105 { 106 example_t *ep = op; 107 example_t ae; 108 nvpair_t *pp; 109 nvlist_t *eap; 110 nvlist_t *erp; 111 112 if (v8plus_args(ap, V8PLUS_ARG_F_NOEXTRA, 113 V8PLUS_TYPE_ANY, &pp, V8PLUS_TYPE_NONE) != 0) 114 return (NULL); 115 116 (void) example_set_impl(&ae, pp); 117 if (_v8plus_errno != V8PLUSERR_NOERROR) 118 return (NULL); 119 120 ep->e_val += ae.e_val; 121 122 eap = v8plus_obj(V8PLUS_TYPE_STRING, "0", "add", V8PLUS_TYPE_NONE); 123 if (eap != NULL) { 124 erp = v8plus_method_call(op, "__emit", eap); 125 nvlist_free(eap); 126 nvlist_free(erp); 127 } 128 129 return (v8plus_void()); 130 } 131 132 static nvlist_t * 133 example_static_add(const nvlist_t *ap) 134 { 135 example_t ae0, ae1; 136 nvpair_t *pp0, *pp1; 137 uint64_t rv; 138 139 if (v8plus_args(ap, V8PLUS_ARG_F_NOEXTRA, 140 V8PLUS_TYPE_ANY, &pp0, 141 V8PLUS_TYPE_ANY, &pp1, 142 V8PLUS_TYPE_NONE) != 0) 143 return (NULL); 144 145 (void) example_set_impl(&ae0, pp0); 146 if (_v8plus_errno != V8PLUSERR_NOERROR) 147 return (NULL); 148 149 (void) example_set_impl(&ae1, pp1); 150 if (_v8plus_errno != V8PLUSERR_NOERROR) 151 return (NULL); 152 153 rv = ae0.e_val + ae1.e_val; 154 155 return (v8plus_obj( 156 V8PLUS_TYPE_STRNUMBER64, "res", rv, 157 V8PLUS_TYPE_NONE)); 158 } 159 160 static nvlist_t * 161 example_multiply(void *op, const nvlist_t *ap) 162 { 163 example_t *ep = op; 164 example_t ae; 165 nvpair_t *pp; 166 167 if (v8plus_args(ap, V8PLUS_ARG_F_NOEXTRA, 168 V8PLUS_TYPE_ANY, &pp, V8PLUS_TYPE_NONE) != 0) 169 return (NULL); 170 171 (void) example_set_impl(&ae, pp); 172 if (_v8plus_errno != V8PLUSERR_NOERROR) 173 return (NULL); 174 175 ep->e_val *= ae.e_val; 176 177 return (v8plus_void()); 178 } 179 180 typedef struct async_multiply_ctx { 181 example_t amc_operand; 182 uint64_t amc_result; 183 v8plus_jsfunc_t amc_cb; 184 } async_multiply_ctx_t; 185 186 static void * 187 async_multiply_worker(void *op, void *ctx) 188 { 189 example_t *ep = op; 190 async_multiply_ctx_t *cp = ctx; 191 example_t *ap = &cp->amc_operand; 192 193 cp->amc_result = ep->e_val * ap->e_val; 194 195 return (NULL); 196 } 197 198 static void 199 async_multiply_done(void *op, void *ctx, void *res __UNUSED) 200 { 201 async_multiply_ctx_t *cp = ctx; 202 example_t *ep = op; 203 nvlist_t *rp; 204 nvlist_t *ap; 205 206 ep->e_val = cp->amc_result; 207 ap = v8plus_obj(V8PLUS_TYPE_NONE); 208 if (ap != NULL) { 209 rp = v8plus_call(cp->amc_cb, ap); 210 nvlist_free(ap); 211 nvlist_free(rp); 212 } 213 214 v8plus_jsfunc_rele(cp->amc_cb); 215 free(cp); 216 } 217 218 static nvlist_t * 219 example_multiplyAsync(void *op, const nvlist_t *ap) 220 { 221 nvpair_t *pp; 222 v8plus_jsfunc_t cb; 223 async_multiply_ctx_t *cp; 224 225 if (v8plus_args(ap, V8PLUS_ARG_F_NOEXTRA, 226 V8PLUS_TYPE_ANY, &pp, 227 V8PLUS_TYPE_JSFUNC, &cb, 228 V8PLUS_TYPE_NONE) != 0) 229 return (NULL); 230 231 if ((cp = malloc(sizeof (async_multiply_ctx_t))) == NULL) 232 return (v8plus_error(V8PLUSERR_NOMEM, "no memory for context")); 233 234 (void) example_set_impl(&cp->amc_operand, pp); 235 if (_v8plus_errno != V8PLUSERR_NOERROR) { 236 free(cp); 237 return (NULL); 238 } 239 240 v8plus_jsfunc_hold(cb); 241 cp->amc_cb = cb; 242 243 v8plus_defer(op, cp, async_multiply_worker, async_multiply_done); 244 245 return (v8plus_void()); 246 } 247 248 static nvlist_t * 249 example_toString(void *op, const nvlist_t *ap) 250 { 251 example_t *ep = op; 252 nvpair_t *pp; 253 254 /* 255 * Example of decorated exceptions. Not strictly needed. 256 */ 257 if (v8plus_args(ap, 0, 258 V8PLUS_TYPE_ANY, &pp, V8PLUS_TYPE_NONE) == 0) { 259 (void) v8plus_error(V8PLUSERR_EXTRAARG, NULL); 260 return (v8plus_obj( 261 V8PLUS_TYPE_INL_OBJECT, "err", 262 V8PLUS_TYPE_NUMBER, "example_argument", (double)0, 263 V8PLUS_TYPE_NUMBER, "example_type", 264 (double)v8plus_typeof(pp), 265 V8PLUS_TYPE_NONE, 266 V8PLUS_TYPE_NONE)); 267 } 268 269 return (v8plus_obj( 270 V8PLUS_TYPE_STRNUMBER64, "res", (uint64_t)ep->e_val, 271 V8PLUS_TYPE_NONE)); 272 } 273 274 static nvlist_t * 275 example_static_object(const nvlist_t *ap __UNUSED) 276 { 277 return (v8plus_obj( 278 V8PLUS_TYPE_INL_OBJECT, "res", 279 V8PLUS_TYPE_NUMBER, "fred", (double)555.5, 280 V8PLUS_TYPE_STRING, "barney", "the sky is blue", 281 V8PLUS_TYPE_INL_OBJECT, "betty", 282 V8PLUS_TYPE_STRING, "bert", "ernie", 283 V8PLUS_TYPE_BOOLEAN, "coffeescript_is_a_joke", B_TRUE, 284 V8PLUS_TYPE_NONE, 285 V8PLUS_TYPE_NULL, "wilma", 286 V8PLUS_TYPE_UNDEFINED, "pebbles", 287 V8PLUS_TYPE_NUMBER, "bam-bam", (double)-32, 288 V8PLUS_TYPE_STRNUMBER64, "dino", 0x1234567812345678ULL, 289 V8PLUS_TYPE_NONE, 290 V8PLUS_TYPE_NONE)); 291 } 292 293 /* 294 * v8+ boilerplate 295 */ 296 const v8plus_c_ctor_f v8plus_ctor = example_ctor; 297 const v8plus_c_dtor_f v8plus_dtor = example_dtor; 298 const char *v8plus_js_factory_name = "create"; 299 const char *v8plus_js_class_name = "Example"; 300 const v8plus_method_descr_t v8plus_methods[] = { 301 { 302 md_name: "set", 303 md_c_func: example_set 304 }, 305 { 306 md_name: "add", 307 md_c_func: example_add 308 }, 309 { 310 md_name: "multiply", 311 md_c_func: example_multiply 312 }, 313 { 314 md_name: "toString", 315 md_c_func: example_toString 316 }, 317 { 318 md_name: "multiplyAsync", 319 md_c_func: example_multiplyAsync 320 } 321 }; 322 const uint_t v8plus_method_count = 323 sizeof (v8plus_methods) / sizeof (v8plus_methods[0]); 324 325 const v8plus_static_descr_t v8plus_static_methods[] = { 326 { 327 sd_name: "static_add", 328 sd_c_func: example_static_add 329 }, 330 { 331 sd_name: "static_object", 332 sd_c_func: example_static_object 333 } 334 }; 335 const uint_t v8plus_static_method_count = 336 sizeof (v8plus_static_methods) / sizeof (v8plus_static_methods[0]);