Embedding the JavaScript Engine
A Bare Bones Tutorial
Brendan Eich
21 February, 2000
How to start up the VM and Execute a Script
Without any error checking for:null returns from JS_ functions that return pointers
false returns from JS_ functions that return booleans
(errors are conventionally saved in a JSBool variable named ok).
JSRuntime *rt;
JSContext *cx;
JSObject *global;
JSClass global_class = {
"global",0,
JS_PropertyStub,JS_PropertyStub,JS_PropertyStub,JS_PropertyStub,
JS_EnumerateStub,JS_ResolveStub,JS_ConvertStub,JS_FinalizeStub
};/*
* You always need:
* a runtime per process,
* a context per thread,
* a global object per context,
* standard classes (e.g. Date).
*/
rt = JS_NewRuntime(0x100000);
cx = JS_NewContext(rt, 0x1000);
global = JS_NewObject(cx, &global_class, NULL, NULL);
JS_InitStandardClasses(cx, global);/*
* Now suppose script contains some JS to evaluate, say "22/7" as a
* bad approximation for Math.PI, or something longer, such as this:
* "(function fact(n){if (n <= 1) return 1; return n * fact(n-1)})(5)"
* to compute 5!
*/
char *script = "...";
jsval rval;
JSString *str;
JSBool ok;ok = JS_EvaluateScript(cx, global, script, strlen(script),
filename, lineno, &rval);
str = JS_ValueToString(cx, rval);
printf("script result: %s\n", JS_GetStringBytes(str));
How to call C functions from JavaScript
Say the C function is named doit and it would like at least two actual parameters when called (if the caller supplies fewer, the JS engine should ensure that undefined is passed for the missing ones):#define DOIT_MINARGS 2Then to wire it up to JS, you could write:static JSBool
doit(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
/*
* Look in argv for argc actual parameters, set *rval to return a
* value to the caller.
*/
...
}
ok = JS_DefineFunction(cx, global, "doit", doit, DOIT_MINARGS, 0);Or, if you had a bunch of native functions to define, you would probably put them in a table:
static JSFunctionSpec my_functions[] = {(the final, all-zeroes function specifier terminates the table) and say:
{"doit", doit, DOIT_MINARGS, 0, 0},
etc...
{0,0,0,0,0},
};
ok = JS_DefineFunctions(cx, global, my_functions);
How to call JavaScript functions from C (such as "onClick")
Say the click event is for the top-most or focused UI element at position (x, y):JSObject *target, *event;Again, I've elided error checking (such as testing for !ok after the call), and I've faked up some C event management routines that emulate the DOM's convention of canceling an event if its handler returns false.
jsval argv[1], rval;/*
* Find event target and make event object to represent this click.
* Pass cx to NewEventObject so JS_NewObject can be called.
*/
target = FindEventTargetAt(cx, global, x, y);
event = NewEventObject(cx, "click", x, y);
argv[0] = OBJECT_TO_JSVAL(event);/* To emulate the DOM, you might want to try "onclick" too. */
ok = JS_CallFunctionName(cx, target, "onClick", 1, argv, &rval);/* Now test rval to see whether we should cancel the event. */
if (JSVAL_IS_BOOLEAN(rval) && !JSVAL_TO_BOOLEAN(rval))
CancelEvent(event);