spidermonkey_vm *sm_initialize(long thread_stack, long heap_size) { spidermonkey_vm *vm = ejs_alloc(sizeof(spidermonkey_vm)); spidermonkey_state *state = ejs_alloc(sizeof(spidermonkey_state)); state->branch_count = 0; state->error = NULL; state->terminate = 0; int gc_size = (int) heap_size * 0.25; vm->runtime = JS_NewRuntime(MAX_GC_SIZE); JS_SetGCParameter(vm->runtime, JSGC_MAX_BYTES, heap_size); JS_SetGCParameter(vm->runtime, JSGC_MAX_MALLOC_BYTES, gc_size); vm->context = JS_NewContext(vm->runtime, 8192); JS_SetScriptStackQuota(vm->context, thread_stack); begin_request(vm); JS_SetOptions(vm->context, JSOPTION_VAROBJFIX); JS_SetOptions(vm->context, JSOPTION_STRICT); JS_SetOptions(vm->context, JSOPTION_COMPILE_N_GO); JS_SetOptions(vm->context, JSVERSION_LATEST); vm->global = JS_NewCompartmentAndGlobalObject(vm->context, &global_class, NULL); JS_InitStandardClasses(vm->context, vm->global); JS_SetErrorReporter(vm->context, on_error); JS_SetOperationCallback(vm->context, on_branch); JS_SetContextPrivate(vm->context, state); JSNative funptr = (JSNative) &js_log; JS_DefineFunction(vm->context, JS_GetGlobalObject(vm->context), "ejsLog", funptr, 0, 0); end_request(vm); return vm; }
char *copy_string(const char *source) { size_t size = strlen(source); char *retval = ejs_alloc(size + 1); strncpy(retval, source, size); retval[size] = '\0'; return retval; }
static void process(ErlDrvData handle, ErlIOVec *ev) { spidermonkey_drv_t *dd = (spidermonkey_drv_t *) handle; char *data = ev->binv[1]->orig_bytes; char *command = read_command(&data); if (strncmp(command, "ij", 2) == 0) { char *call_id = read_string(&data); int thread_stack = read_int32(&data); if (thread_stack < 8) { thread_stack = 8; } thread_stack = thread_stack * (1024 * 1024); int heap_size = read_int32(&data) * (1024 * 1024); dd->vm = sm_initialize(thread_stack, heap_size); send_immediate_ok_response(dd, call_id); driver_free(call_id); } else { js_call *call_data = ejs_alloc(sizeof(js_call)); call_data->driver_data = dd; call_data->args = ev->binv[1]; call_data->return_terms[0] = 0; call_data->return_term_count = 0; call_data->return_string = NULL; driver_binary_inc_refc(call_data->args); ErlDrvPort port = dd->port; intptr_t port_ptr = (intptr_t) port; unsigned int thread_key = port_ptr; driver_async(dd->port, &thread_key, (asyncfun) run_js, (void *) call_data, NULL); } driver_free(command); }
static ErlDrvData start(ErlDrvPort port, char *cmd) { spidermonkey_drv_t *retval = ejs_alloc(sizeof(spidermonkey_drv_t)); retval->port = port; retval->shutdown = 0; retval->atom_ok = driver_mk_atom((char *) "ok"); retval->atom_error = driver_mk_atom((char *) "error"); retval->atom_unknown_cmd = driver_mk_atom((char *) "unknown_command"); return (ErlDrvData) retval; }
char *error_to_json(const spidermonkey_error *error) { char *escaped_source = escape_quotes(error->offending_source); /* size = length(escaped source) + length(error msg) + JSON formatting */ size_t size = strlen(escaped_source) + strlen(error->msg) + 80; char *retval = ejs_alloc(size); snprintf(retval, size, "{\"error\": {\"lineno\": %d, \"message\": \"%s\", \"source\": \"%s\"}}", error->lineno, error->msg, escaped_source); driver_free(escaped_source); return retval; }
char *escape_quotes(char *text) { size_t bufsize = strlen(text) * 2; char *buf = ejs_alloc(bufsize); memset(buf, 0, bufsize); int i = 0; int x = 0; int escaped = 0; for (i = 0; i < strlen(text); i++) { if (text[i] == '"') { if(!escaped) { memcpy(&buf[x], (char *) "\\\"", 2); x += 2; } else { memcpy(&buf[x], &text[i], 1); x++; } } else { if(text[i] =='\\') { escaped = 1; } else { escaped = 0; } memcpy(&buf[x], &text[i], 1); x++; } } size_t buf_size = strlen(buf); char *retval = ejs_alloc(buf_size + 1); strncpy(retval, buf, buf_size); retval[buf_size] = '\0'; driver_free(buf); return retval; }
void on_error(JSContext *context, const char *message, JSErrorReport *report) { if (report->flags & JSREPORT_EXCEPTION) { spidermonkey_error *sm_error = ejs_alloc(sizeof(spidermonkey_error)); if (message != NULL) { sm_error->msg = copy_string(message); } else { sm_error->msg = copy_string("undefined error"); } sm_error->lineno = report->lineno; if (report->linebuf != NULL) { sm_error->offending_source = copy_string(report->linebuf); } else { sm_error->offending_source = copy_string("unknown"); } spidermonkey_state *state = (spidermonkey_state *) JS_GetContextPrivate(context); state->error = sm_error; JS_SetContextPrivate(context, state); } }