Notes
Outline
Embedding the JavaScript in C (SpiderMonkey) Engine
Viswanath Ramachandran
Netscape (iPlanet Web Server group)
Introduction
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
Agenda
JSAPI and JSVM
XDR to freeze and thaw scripts
LiveConnect 3
Checkout and build
References
Data Structures
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);
Objects
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)
Properties
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
Functions
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
Scripts
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
Other data structures
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
The Global Object
JS_SetGlobalObject(cx, obj);
JS_InitStandardClasses(cx,obj);
Garbage Collector Interaction
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)
Thread Safe Embedding
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);
Cleanup  and Shutdown
JS_DestroyContext(cx);
Does an implicit JS_EndRequest(cx)
JS_DestroyContextNoGC(cx)
JS_DestroyContextMaybeGC(cx)
JS_DestroyRuntime(rt);
Compiled Applications
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
Precompiling Scripts to XDR
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);
Loading XDR’ed Scripts
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 Support
LiveConnect 3
Callbacks
No JVM/JRE dependency - not statically linked
LiveConnect Callbacks
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}
LiveConnect Initialization
JSJ_Init(&callbacks);
//obtained from JNI
JavaVM* jvm;
JSJavaVM* jsjvm =  JSJ_ConnectToJavaVM(jvm, 0);
// Per global object not JSContext
JSJ_InitJSContext(cx, global, 0);
Attach Thread/Context to LC
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;
}
Detach Thread/Context from LC
Before destroying the context
JSJavaThreadState *jsj_env;
if ((jsj_env = (JSJavaThreadState *)JS_GetContextPrivate(cx)) != NULL)
 {
     JSJ_DetachCurrentThreadFromJava(jsj_env);
     JS_SetContextPrivate(cx, NULL);
 }
Checkout and Build
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)
Summary
JSAPI and JSVM
Key data structures and APIs
Compilation possible - SSJS
LiveConnect
Embed in multithreaded, scalable products
References
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