You are currently viewing a snapshot of www.mozilla.org taken on April 21, 2008. Most of this content is highly out of date (some pages haven't been updated since the project began in 1998) and exists for historical purposes only. If there are any pages on this archive site that you think should be added back to www.mozilla.org, please file a bug.



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 2

    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.
         */
        ...
    }

Then to wire it up to JS, you could write:
    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[] = {
        {"doit", doit, DOIT_MINARGS, 0, 0},
        etc...
        {0,0,0,0,0},
    };
(the final, all-zeroes function specifier terminates the table) and say:
    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;
    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);

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.