Embedding the JavaScript in C (SpiderMonkey) Engine
Viswanath Ramachandran | |
Netscape (iPlanet Web Server group) |
iPlanet Web Server 4.0 embeds the SpiderMonkey (JS in C) engine from mozilla.org | |
Threadsafe, high performance usage | |
Base for enterprise-class services | |
You too can use SpiderMonkey in your products to provide JavaScript support. | |
Advanced Tutorial - need your help |
JSAPI and JSVM | |
XDR to freeze and thaw scripts | |
LiveConnect 3 | |
Checkout and build | |
References |
Primitive Values | |
jsval v; // data or pointer to heap | |
JSVAL_IS_NUMBER(v), JSVAL_TO_STRING(v), OBJECT_TO_JSVAL(obj), JSVAL_NULL, JSVAL_FALSE | |
JavaScript Runtime | |
JSRuntime *rt = JS_NewRuntime(maxbytes); | |
JavaScript Context | |
JSContext *cx = JS_NewContext(rt, stacksize); | |
JSObject obj; // a JavaScript object | |
Prototype | |
JS_GetPrototype(cx, obj), JS_SetPrototype(cx, obj, proto) | |
Parent | |
JS_GetParent(cx, obj), JS_SetParent(cx, obj, parent) | |
Create them | |
JS_NewObject(cx, clasp, proto, parent), | |
JS_DefineObject(cx, obj, name, clasp, proto, flags) | |
Object Private Data | |
JS_GetPrivate(cx, obj), JS_SetPrivate(cx, obj, data) | |
Fundamental notion in JavaScript | |
JSPropertySpec ps; // one or more properties of an obj | |
JS_DefineProperties(cx, obj, ps); | |
// single property | |
JSPropertyOp getter, setter; // getProperty and setProperty methods | |
JS_DefineProperty(cx, obj, name, v, getter, setter, flags); // has variations | |
JS_LookupProperty, JS_GetProperty, JS_SetPropert, JS_DeleteProperty |
JSFunctionSpec *fs;// one or more functions of an object | |
JS_DefineFunctions(cx, obj, fs); | |
//single function | |
JSFunction *fun = JS_DefineFunction(cx, obj, name, native, nargs, flags); | |
JSObject *fobj = JS_GetFunctionObject(fun); | |
// call the function | |
JS_CallFunction(cx, obj, fun, argc, argv, rval); | |
JS_CallFunctionName(cx, obj, name, argc, argv, rval); | |
JS_NewFunction, JS_CloneFunctionObject, JS_CompileFunction |
Encapsulates a compiled program | |
JSScript *script = JS_CompileFile(cx, obj, filename); | |
JSObject *obj = JS_NewScriptObject(cx, script); | |
JS_CompileScriptForPrincipals, JS_CompileUCScript, JS_CompileUCScriptForPrincipals, JS_CompileFile, JS_NewScriptObject, JS_DestroyScript |
JSString - JS_NewString, JS_GetStringChars | |
JSClass - JS_GetClass, JS_InstanceOf | |
JSPrincipals - JS_CompileUCScriptForPrincipals | |
Error Handling - JS_ReportError, JS_SetErrorReporter | |
Arrays - JS_NewArrayObject, JS_SetArrayLength | |
JSBool | |
JSType - JS_TypeOfValue, JS_GetTypeName |
JS_SetGlobalObject(cx, obj); | |
JS_InitStandardClasses(cx,obj); |
Root all objects | ||
JS_AddRoot(cx, &obj); // JSObject *obj | ||
JS_AddRoot(cx, &str); // JSString *str; | ||
Memory allocation | ||
JS_malloc(cx, bytes), JS_realloc(cx, p, bytes), JS_free(cx,p) | ||
GC is not asynchronous | ||
JS_GC(cx), JS_MaybeGC(cx) | ||
Branch Callbacks | ||
JS_SetBranchCallBack(cx, callback) |
Compile with -DJS_THREADSAFE | |
JSContext:Thread is a many:1 mapping | |
JS_SetContextThread(cx); | |
Before entering JS | |
JS_BeginRequest(cx); | |
When leaving JS | |
JS_EndRequest(cx); |
JS_DestroyContext(cx); | ||
Does an implicit JS_EndRequest(cx) | ||
JS_DestroyContextNoGC(cx) | ||
JS_DestroyContextMaybeGC(cx) | ||
JS_DestroyRuntime(rt); |
Server Side JavaScript (SSJS) | |
jsac -o myapp.web *.js *.html | |
Rough equivalent of a Java class is a JavaScript XDR | |
XDR a lower level abstraction than class |
JSScript* script = | |
JS_CompileScript(cx, global, script_chars, script_length, filename, 1); | |
JSObject *obj = JS_NewScriptObject(cx, script); | |
jsval rval; | |
JS_CallFunctionName(cx, obj, "freeze", 0, NULL, &rval); | |
JSString *str = JSVAL_TO_STRING(rval); | |
jschar* xdr = JS_GetStringChars(str); | |
size_t xdr_len = JS_GetStringLength(str); | |
jsval args[1]; | |
JSString *scriptStr = JS_NewUCStringCopyN(cx, xdr, xdr_len); | |
args[0] = STRING_TO_JSVAL(scriptStr); | |
JSObject* sobj = JS_NewScriptObject(cx, NULL); | |
JS_CallFunctionName(cx, sobj, "thaw", 1, args, &rval); | |
JSScript* dscript = (JSScript *) JS_GetPrivate(cx, sobj); | |
// Run it | |
JS_ExecuteScript(cx, obj, dscript, &rval); |
LiveConnect 3 | |
Callbacks | |
No JVM/JRE dependency - not statically linked |
JSJCallbacks callbacks = { | |
map_jsj_thread_to_js_context, | |
map_js_context_to_jsj_thread, | |
map_java_object_to_js_object, | |
get_JSPrincipals_from_java_caller, | |
enter_js_from_java, exit_js, | |
error_print, get_java_wrapper, | |
create_java_vm, | |
destroy_java_vm, | |
attach_current_thread, | |
detach_current_thread, | |
get_java_vm, | |
reserved10} | |
callbacks = { | |
0, | |
JSContext --> JSJavaThreadState, | |
0, | |
0, | |
0, 0, | |
const char* --> void, 0, | |
0, | |
0, | |
JavaVM* --> JNIEnv*, | |
JavaVM* x JNIenv* --> JSBool | |
JNIEnv* --> JavaVM*, | |
0} |
JSJ_Init(&callbacks); | |
//obtained from JNI | |
JavaVM* jvm; | |
JSJavaVM* jsjvm = JSJ_ConnectToJavaVM(jvm, 0); | |
// Per global object not JSContext | |
JSJ_InitJSContext(cx, global, 0); |
JSJavaThreadState * | |
map_js_context_to_jsj_thread(JSContext *cx, char **errp) | |
{ | |
JSJavaThreadState *jsj_env; | |
if ((jsj_env =JSJavaThreadState *)JS_GetContextPrivate(cx)) == NULL) | |
{ | |
jsj_env = JSJ_AttachCurrentThreadToJava(jsjvm, 0, 0); | |
JS_SetContextPrivate(cx, (void *) jsj_env); | |
} | |
return jsj_env; | |
} |
Before destroying the context | |
JSJavaThreadState *jsj_env; | |
if ((jsj_env = (JSJavaThreadState *)JS_GetContextPrivate(cx)) != NULL) | |
{ | |
JSJ_DetachCurrentThreadFromJava(jsj_env); | |
JS_SetContextPrivate(cx, NULL); | |
} |
cvs co -r SpiderMonkey140_NES40Rtm_Branch mozilla/js/src | |
get NSPR | |
cd mozilla/js/src | |
gmake -f Makefile.ref JS_THREADSAFE=1 JS_LIVECONNECT=1 NES40=1 (other flags also) | |
libjs.so libjsj.so (or js32.dll) |
JSAPI and JSVM | |
Key data structures and APIs | |
Compilation possible - SSJS | |
LiveConnect | |
Embed in multithreaded, scalable products |
www.mozilla.org/js | |
mozilla.org newsgroups for JS | |
mozilla.org JS people - Scott Furman, Roger Lawrence, Mike Shaver | |
developer.netscape.com/docs/manuals/javascriptapi/contents.htm | |
Source code - esp. jsapi.h and jsjava.h | |
ECMA standards documents |