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; }
/* Execute a string in its own context (away from Synchronet objects) */ static JSBool js_eval(JSContext *parent_cx, uintN argc, jsval *arglist) { jsval *argv=JS_ARGV(parent_cx, arglist); char* buf; size_t buflen; JSString* str; JSObject* script; JSContext* cx; JSObject* obj; JSErrorReporter reporter; JS_SET_RVAL(cx, arglist, JSVAL_VOID); if(argc<1) return(JS_TRUE); if((str=JS_ValueToString(parent_cx, argv[0]))==NULL) return(JS_FALSE); JSSTRING_TO_MSTRING(parent_cx, str, buf, &buflen); HANDLE_PENDING(parent_cx); if(buf==NULL) return(JS_TRUE); if((cx=JS_NewContext(JS_GetRuntime(parent_cx),JAVASCRIPT_CONTEXT_STACK))==NULL) { free(buf); return(JS_FALSE); } /* Use the error reporter from the parent context */ reporter=JS_SetErrorReporter(parent_cx,NULL); JS_SetErrorReporter(parent_cx,reporter); JS_SetErrorReporter(cx,reporter); /* Use the operation callback from the parent context */ JS_SetContextPrivate(cx, JS_GetContextPrivate(parent_cx)); JS_SetOperationCallback(cx, JS_GetOperationCallback(parent_cx)); if((obj=JS_NewCompartmentAndGlobalObject(cx, &eval_class, NULL))==NULL || !JS_InitStandardClasses(cx,obj)) { JS_DestroyContext(cx); free(buf); return(JS_FALSE); } if((script=JS_CompileScript(cx, obj, buf, buflen, NULL, 0))!=NULL) { jsval rval; JS_ExecuteScript(cx, obj, script, &rval); JS_SET_RVAL(cx, arglist, rval); } free(buf); JS_DestroyContext(cx); return(JS_TRUE); }
/** Our "Operation Callback" multiplexes this Spidermonkey facility. It is called automatically by Spidermonkey, and is * triggered on a regular interval by gpsee_asyncCallbackTriggerThreadFunc() */ JSBool gpsee_operationCallback(JSContext *cx) { gpsee_runtime_t *grt = (gpsee_runtime_t *) JS_GetRuntimePrivate(JS_GetRuntime(cx)); GPSEEAsyncCallback *cb; /* The callbacks registered with GPSEE may want to invoke JSAPI functionality, which might toss us back out * to another invocation of gpsee_operationCallback(). The JSAPI docs for "operation callbacks" [1] suggest * removing the operation callback before calling JSAPI functionality from within an operation callback, * then resetting it when we're done making JSAPI calls. Since it's rather inexpensive, we'll just do it here * and then consumers of gpsee_addAsyncCallback() needn't worry about it (we don't want them touching that * callback slot anyway! * * [1] https://developer.mozilla.org/en/JS_SetOperationCallback * * Another side note: we do it before if(cb) because if gpsee_asyncCallbacks is empty, we want to uninstall our * operation callback altogether. */ JS_SetOperationCallback(cx, NULL); cb = grt->asyncCallbacks; if (cb) { GPSEEAsyncCallback *next; do { /* Save the 'next' link in case the callback deletes itself */ next = cb->next; /* Invoke callback */ if (!((*(cb->callback))(cb->cx, cb->userdata, cb))) /* Propagate exceptions */ return JS_FALSE; } while ((cb = next)); /* Reinstall our operation callback */ JS_SetOperationCallback(cx, gpsee_operationCallback); return JS_TRUE; } return JS_TRUE; }
static JSBool js_OperationCallback(JSContext *cx) { JSBool ret; sbbs_t* sbbs; JS_SetOperationCallback(cx, NULL); if((sbbs=(sbbs_t*)JS_GetContextPrivate(cx))==NULL) { JS_SetOperationCallback(cx, js_OperationCallback); return(JS_FALSE); } if(sbbs->js_callback.auto_terminate && !sbbs->online) { JS_ReportWarning(cx,"Disconnected"); sbbs->js_callback.counter=0; JS_SetOperationCallback(cx, js_OperationCallback); return(JS_FALSE); } ret=js_CommonOperationCallback(cx,&sbbs->js_callback); JS_SetOperationCallback(cx, js_OperationCallback); return ret; }
JsExecutionContext::JsExecutionContext(JsParser *jsParser) { parser = jsParser; /* Create a new runtime environment. */ rt = JS_NewRuntime(8L * 1024L * 1024L); if (!rt) { error("JsParser :: error creating runtime"); return; /* XXX should return int or ptr! */ } /* Create a new context. */ cx = JS_NewContext(rt, STACK_CHUNK_SIZE); /* if global_context does not have a value, end the program here */ if (cx == NULL) { error("JsParser :: error creating context"); return; } JS_BeginRequest(cx); // Store a reference to ourselves in the context ... JS_SetContextPrivate(cx, parser); /* Set a more strict error checking */ JS_SetOptions(cx, JSOPTION_VAROBJFIX); // | JSOPTION_STRICT); /* Set the branch callback */ #if defined JSOPTION_NATIVE_BRANCH_CALLBACK JS_SetBranchCallback(cx, js_static_branch_callback); #else JS_SetOperationCallback(cx, js_static_branch_callback); #endif /* Set the error reporter */ JS_SetErrorReporter(cx, js_error_reporter); /* Create the global object here */ // JS_SetGlobalObject(global_context, global_object); // this is done in init_class / JS_InitStandardClasses. obj = JS_NewObject(cx, &global_class, NULL, NULL); init_class(); JS_EndRequest(cx); // deassociate this context from the creating thread // so that it can be used in other threads // https://developer.mozilla.org/en/SpiderMonkey/JSAPI_Reference/JS_NewContext JS_ClearContextThread(cx); /** register SIGINT signal */ // signal(SIGINT, js_sigint_handler); }
long sbbs_t::js_execfile(const char *cmd, const char* startup_dir, JSObject* scope) { char* p; char* args=NULL; char* fname; int argc=0; char cmdline[MAX_PATH+1]; char path[MAX_PATH+1]; JSObject* js_scope=scope; JSObject* js_script=NULL; jsval rval; int32 result=0; if(js_cx==NULL) { errormsg(WHERE,ERR_CHK,"JavaScript support",0); errormsg(WHERE,ERR_EXEC,cmd,0); return -1; } SAFECOPY(cmdline,cmd); p=strchr(cmdline,' '); if(p!=NULL) { *p=0; args=p+1; } fname=cmdline; path[0]=0; if(strcspn(fname,"/\\")==strlen(fname)) { if(startup_dir!=NULL && *startup_dir) SAFEPRINTF3(path,"%s%s%s",startup_dir,fname,js_ext(fname)); if(path[0]==0 || !fexistcase(path)) { SAFEPRINTF3(path,"%s%s%s",cfg.mods_dir,fname,js_ext(fname)); if(cfg.mods_dir[0]==0 || !fexistcase(path)) SAFEPRINTF3(path,"%s%s%s",cfg.exec_dir,fname,js_ext(fname)); } } else SAFECOPY(path,fname); if(!fexistcase(path)) { errormsg(WHERE,ERR_OPEN,path,O_RDONLY); return -1; } JS_BEGINREQUEST(js_cx); if(js_scope==NULL) js_scope=JS_NewObject(js_cx, NULL, NULL, js_glob); if(js_scope!=NULL) { JSObject* argv=JS_NewArrayObject(js_cx, 0, NULL); JS_DefineProperty(js_cx, js_scope, "argv", OBJECT_TO_JSVAL(argv) ,NULL,NULL,JSPROP_READONLY|JSPROP_ENUMERATE); /* TODO: Handle quoted "one arg" syntax here? */ if(args!=NULL && argv!=NULL) { while(*args) { p=strchr(args,' '); if(p!=NULL) *p=0; while(*args && *args==' ') args++; /* Skip spaces */ JSString* arg = JS_NewStringCopyZ(js_cx, args); if(arg==NULL) break; jsval val=STRING_TO_JSVAL(arg); if(!JS_SetElement(js_cx, argv, argc, &val)) break; argc++; if(p==NULL) /* last arg */ break; args+=(strlen(args)+1); } } JS_DefineProperty(js_cx, js_scope, "argc", INT_TO_JSVAL(argc) ,NULL,NULL,JSPROP_READONLY|JSPROP_ENUMERATE); JS_ClearPendingException(js_cx); js_script=JS_CompileFile(js_cx, js_scope, path); } if(js_scope==NULL || js_script==NULL) { JS_ReportPendingException(js_cx); /* Added Feb-2-2006, rswindell */ JS_ENDREQUEST(js_cx); errormsg(WHERE,"compiling",path,0); return -1; } if(scope==NULL) { js_callback.counter=0; // Reset loop counter #if JS_VERSION>180 JS_SetOperationCallback(js_cx, js_OperationCallback); #else JS_SetBranchCallback(js_cx, js_BranchCallback); #endif js_PrepareToExecute(js_cx, js_glob, path, startup_dir); } JS_ExecuteScript(js_cx, js_scope, js_script, &rval); if(scope==NULL) { JS_GetProperty(js_cx, js_scope, "exit_code", &rval); if(rval!=JSVAL_VOID) JS_ValueToInt32(js_cx,rval,&result); js_EvalOnExit(js_cx, js_scope, &js_callback); } JS_ReportPendingException(js_cx); /* Added Dec-4-2005, rswindell */ JS_DestroyScript(js_cx, js_script); if(scope==NULL) JS_ClearScope(js_cx, js_scope); JS_GC(js_cx); JS_ENDREQUEST(js_cx); return(result); }
static PyObject *spindly_js(PyObject *self, PyObject *args) { JSRuntime *runtime; JSContext *context; JSObject *global; char *script; Py_ssize_t script_length; PyObject *params = NULL; int timeout = 10; jsval rvalue; int error = 0; struct watchdog *wd = NULL; if (!PyArg_ParseTuple(args, "s#|Oi:js", &script, &script_length, ¶ms, &timeout)) { return NULL; } if (params != NULL && !PyDict_Check(params)) { return PyErr_Format(PyExc_TypeError, "params must be a dict"); } runtime = JS_NewRuntime(1024L * 1024L); if (!runtime) { return PyErr_Format(PyExc_SystemError, "unable to initialize JS runtime\n"); } context = JS_NewContext(runtime, 8192); if (!context) { JS_DestroyRuntime(runtime); return PyErr_Format(PyExc_SystemError, "unable to initialize JS context\n"); } JS_SetContextPrivate(context, &error); JS_SetOptions(context, JSOPTION_VAROBJFIX); JS_SetVersion(context, JSVERSION_LATEST); JS_SetErrorReporter(context, raise_python_exception); JS_SetOperationCallback(context, js_destroy); global = JS_NewCompartmentAndGlobalObject(context, &global_class, NULL); JS_InitStandardClasses(context, global); if (params != NULL) { populate_javascript_object(context, global, params); } if (timeout > 0) { wd = run_watchdog(context, timeout); if (wd == NULL) { shutdown(runtime, context); return PyErr_Format(PyExc_SystemError, "unable to initialize JS watchdog\n"); } } JSBool retval = JS_EvaluateScript(context, global, script, script_length, "spindly", 1, &rvalue); if (wd) { shutdown_watchdog(wd); } if (retval == JS_FALSE || error == 1) { shutdown(runtime, context); return NULL; } PyObject *obj = to_python_object(context, rvalue); shutdown(runtime, context); return obj; }
void * spidermonkey_get_interpreter(struct ecmascript_interpreter *interpreter) { JSContext *ctx; JSObject *window_obj, *document_obj, *forms_obj, *history_obj, *location_obj, *statusbar_obj, *menubar_obj, *navigator_obj; assert(interpreter); if (!js_module_init_ok) return NULL; ctx = JS_NewContext(spidermonkey_runtime, 8192 /* Stack allocation chunk size */); if (!ctx) return NULL; interpreter->backend_data = ctx; JS_SetContextPrivate(ctx, interpreter); JS_SetOptions(ctx, JSOPTION_VAROBJFIX | JSOPTION_JIT | JSOPTION_METHODJIT); JS_SetVersion(ctx, JSVERSION_LATEST); JS_SetErrorReporter(ctx, error_reporter); #if defined(CONFIG_ECMASCRIPT_SMJS_HEARTBEAT) JS_SetOperationCallback(ctx, heartbeat_callback); #endif window_obj = JS_NewCompartmentAndGlobalObject(ctx, (JSClass *) &window_class, NULL); if (!window_obj) goto release_and_fail; if (!JS_InitStandardClasses(ctx, window_obj)) goto release_and_fail; if (!JS_DefineProperties(ctx, window_obj, (JSPropertySpec *) window_props)) goto release_and_fail; if (!spidermonkey_DefineFunctions(ctx, window_obj, window_funcs)) goto release_and_fail; if (!JS_SetPrivate(ctx, window_obj, interpreter->vs)) /* to @window_class */ goto release_and_fail; document_obj = spidermonkey_InitClass(ctx, window_obj, NULL, (JSClass *) &document_class, NULL, 0, (JSPropertySpec *) document_props, document_funcs, NULL, NULL); if (!document_obj) goto release_and_fail; forms_obj = spidermonkey_InitClass(ctx, document_obj, NULL, (JSClass *) &forms_class, NULL, 0, (JSPropertySpec *) forms_props, forms_funcs, NULL, NULL); if (!forms_obj) goto release_and_fail; history_obj = spidermonkey_InitClass(ctx, window_obj, NULL, (JSClass *) &history_class, NULL, 0, (JSPropertySpec *) NULL, history_funcs, NULL, NULL); if (!history_obj) goto release_and_fail; location_obj = spidermonkey_InitClass(ctx, window_obj, NULL, (JSClass *) &location_class, NULL, 0, (JSPropertySpec *) location_props, location_funcs, NULL, NULL); if (!location_obj) goto release_and_fail; menubar_obj = JS_InitClass(ctx, window_obj, NULL, (JSClass *) &menubar_class, NULL, 0, (JSPropertySpec *) unibar_props, NULL, NULL, NULL); if (!menubar_obj) goto release_and_fail; if (!JS_SetPrivate(ctx, menubar_obj, "t")) /* to @menubar_class */ goto release_and_fail; statusbar_obj = JS_InitClass(ctx, window_obj, NULL, (JSClass *) &statusbar_class, NULL, 0, (JSPropertySpec *) unibar_props, NULL, NULL, NULL); if (!statusbar_obj) goto release_and_fail; if (!JS_SetPrivate(ctx, statusbar_obj, "s")) /* to @statusbar_class */ goto release_and_fail; navigator_obj = JS_InitClass(ctx, window_obj, NULL, (JSClass *) &navigator_class, NULL, 0, (JSPropertySpec *) navigator_props, NULL, NULL, NULL); if (!navigator_obj) goto release_and_fail; return ctx; release_and_fail: spidermonkey_put_interpreter(interpreter); return NULL; }