Please note, this is a STATIC archive of website developer.mozilla.org from 03 Nov 2016, cach3.com does not collect or store any user information, there is no "phishing" involved.

Comment intégrer le moteur Javascript

Voir aussi le guide utilisateur JSAPI. Il possède de meilleurs et plus nombreux exemples de code!

Un Tutoriel Couvrant l'Essentiel

Exemple d'intégration dans une application

Le code suivant est une simple application montrant comment intégrer SpiderMonkey et exécuter un script Javascript simple. Voir les instructions concernant la compilation et l'exécution en dessous du code.

/*
 * Uniquement sur Windows, il s'agit d'un fix pour le bug 661663.
 */
#ifdef _MSC_VER
# define XP_WIN
#endif

/* Inclusion du header JSAPI afin d'accéder à SpiderMonkey. */
#include "jsapi.h"

/* La classe de l'objet global. */
static JSClass global_class = {
    "global", JSCLASS_GLOBAL_FLAGS,
    JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
    JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
    JSCLASS_NO_OPTIONAL_MEMBERS
};

/* Callback du rapporteur d'erreurs. */
void reportError(JSContext *cx, const char *message, JSErrorReport *report)
{
    fprintf(stderr, "%s:%u:%s\n",
            report->filename ? report->filename : "<no filename=\"filename\">",
            (unsigned int) report->lineno,
            message);
}

int main(int argc, const char *argv[])
{
    /* Variables JSAPI. */
    JSRuntime *rt;
    JSContext *cx;
    JSObject  *global;

    /* Créer un runtime JS. Il faut toujours un runtime par processus. */
    rt = JS_NewRuntime(8 * 1024 * 1024);
    if (rt == NULL)
        return 1;

    /* 
     * Créée un contexte. Il faut toujours un contexte par thread.
     * Notez que ce programme n'est pas multi-threadé.
     */
    cx = JS_NewContext(rt, 8192);
    if (cx == NULL)
        return 1;
    JS_SetOptions(cx, JSOPTION_VAROBJFIX | JSOPTION_JIT | JSOPTION_METHODJIT);
    JS_SetVersion(cx, JSVERSION_LATEST);
    JS_SetErrorReporter(cx, reportError);

    /*
     * Créée l'objet global dans un nouveau compartiment.
     * Il faut toujours un objet global par contexte.
     */
    global = JS_NewCompartmentAndGlobalObject(cx, &global_class, NULL);
    if (global == NULL)
        return 1;

    /*
     * On peuple l'objet global avec les fonctions et les objets
     * Javascript standard, tels que Object, Array ou Date.
     */
    if (!JS_InitStandardClasses(cx, global))
        return 1;

    /* Le code de votre application est ici. Ceci inclue la création de
     * vos propres objets Javascript ou l'exécution de scripts via JSAPI.
     *
     * L'exemple suivant créée un script Javascript littéral,
     * l'évalue, et affiche le résultat dans stdout.
     *
     * Par convention les erreurs sont stockées dans la variable JSBool ok.
     */
    const char *script = "'Hello ' + 'World!'";
    jsval rval;
    JSString *str;
    JSBool ok;
    const char *filename = "noname";
    uintN lineno = 0;

    ok = JS_EvaluateScript(cx, global, script, strlen(script),
                           filename, lineno, &rval);
    if (rval == JS_NULL | rval == JS_FALSE)
        return 1;

    str = JS_ValueToString(cx, rval);
    printf("%s\n", JS_EncodeString(cx, str));

    /* Fin de votre code d'application */

    /* Nettoyage et fermeture de SpiderMonkey. */
    JS_DestroyContext(cx);
    JS_DestroyRuntime(rt);
    JS_ShutDown();
    return 0;
}

L'exemple Hello World mis à jour pour SpiderMonkey24:

#include "jsapi.h"

/* Classe de l'objet global. */
static JSClass global_class = {
    "global", 
    JSCLASS_GLOBAL_FLAGS,
    JS_PropertyStub, 
    JS_DeletePropertyStub, 
    JS_PropertyStub, 
    JS_StrictPropertyStub,
    JS_EnumerateStub,  
    JS_ResolveStub, 
    JS_ConvertStub
};


int main(int argc, const char *argv[])
{
    JS_Init();

    JSRuntime *rt = JS_NewRuntime(8L * 1024 * 1024, JS_NO_HELPER_THREADS);
    if (!rt)
        return 1;

    JSContext *cx = JS_NewContext(rt, 8192);
    if (!cx)
        return 1;

    JS::RootedObject global(cx, JS_NewGlobalObject(cx, &global_class, nullptr, JS::DontFireOnNewGlobalHook));
    if (!global)
        return 1;

    JS::Value rval;
    bool ok;
    {
      JSAutoCompartment ac(cx, *global); 
      JS_InitStandardClasses(cx, *global);

      const char *script = "'hello'+'world, it is '+new Date()";
      const char *filename = "noname";
      int lineno = 0;
      ok = JS_EvaluateScript(cx, *global, script, strlen(script), filename, lineno, &rval);
      if (rval.isNull() | rval.isFalse() )
        return 1;
    }

    JSString *str = rval.toString();
    printf("%s\n", JS_EncodeString(cx, str));

    JS_DestroyContext(cx);
    JS_DestroyRuntime(rt);
    JS_ShutDown();
    return 0;
}
 

Compiler et exécuter l'exemple Hello World

Voici un exemple en ligne de commande Linux (où <objdir> est le dossier dans lequel SpiderMonkey a été compilé):
    g++ -I<objdir>/dist/include -L<objdir>/dist/bin -lmozjs185  helloworld.cpp -O helloworld
   
Voici un exemple en ligne de commande Windows avec le shell MozillaBuildHere:
    cl helloworld.cpp -link dist/lib/mozjs185-1.0.lib
   
Ceci devrait afficher Hello World!
   
  1. Assurez-vous que l'ordinateur sur lequel vous effectuez la compilation remplit les prérequis pour compiler SpiderMonkey: Linux, Windows, Mac OS X, autres. Pour Windows, les étapes suivantes permettent de s'assurer que le package MozillaBuild est bien installé.
  2. Récupérez le code source de SpiderMonkey. Vous pouvez télécharger un archive contenant les sources ou utiliser Mercurial (hg) pour cloner le dépôt SpiderMonkey. Sur Windows, n'installez pas les sources de SpiderMonkey sous le dossier racine MSYS (qui est en général c:\mozilla-build\msys). Utilisez plutôt par exemple c:\js-1.8.5.
  3. Compilez SpiderMonkey en utilisant les instructions se trouvant dans Documentation de la compilation de SpiderMonkey. Par défaut une bibliothèque partagée de SpiderMonkey sera compilée que vous pourrez lier à votre application dans une prochaine étape.
  4. Copiez l'exemple de code plus haut dans un éditeur de texte et enregistrer le fichier en tant que helloworld.cpp dans le dossier de SpiderMonkey js\src. Pour copier le code sans les numéros de lignes, placez la souris au dessus de l'exemple près du haut et attendez l'apparition des boutons. Cliquez ensuite sur le bouton voir source, et copiez le code depuis la fenêtre qui apparaît.
  5. Compilez l'application HelloWorld and liez avec la bibliothèque SpiderMonkey.
  6. cl helloworld.cpp -link dist/lib/mozjs185-1.0.lib
  7. Exécutez le programme helloworld à l'aide de la ligne de commande:
        ./helloworld

Appeler des fonctions C depuis Javascript

Mettons que la fonction C est nommée doit et demande au moins deux paramètres lors de l'appel (si l'appelant en fournit moins, le moteur JS doit s'assurer que undefined est passé pour ceux manquants) :

#define DOIT_MINARGS 2

static JSBool
doit(JSContext *cx, unsigned argc, jsval *vp)
{
    jsval *argv = JS_ARGV(cx, vp);
    /*
     * Cherche dans argv les paramètres, et assigne *rval pour
     * retourner une valeur à l'appelant.
     */
    ...
}

Pour faire le lien avec JS, vous pouvez écrire :

ok = JS_DefineFunction(cx, global, "doit", doit, DOIT_MINARGS, 0);

Si vous avez plusieurs fonction natives à définir, vous pouvez les mettre dans un tableau :

static JSFunctionSpec my_functions[] = {
    {"doit", doit, DOIT_MINARGS, 0, 0},
    etc...
    {0,0,0,0,0},
};

(la spécification de fonction comportant uniquement des zéros délimite la fin du tableau) et effectuer :

ok = JS_DefineFunctions(cx, global, my_functions);

Appeler des fonctions Javascript depuis C

Considérons qu'un évènement de clic concerne l'élément d'interface utilisateur le plus à l'avant ou qui a le focus à une position donnée (x, y) :

JSObject *target, *event;
jsval argv[1], rval;

/*
 * On trouve la cible de l'évènement et créée un object d'évènement
 * représentant le clic.
 * On passe cx à NewEventObject pour que JS_NewObject puisse être appelé.
 */
target = FindEventTargetAt(cx, global, x, y);
event = NewEventObject(cx, "click", x, y);
argv[0] = OBJECT_TO_JSVAL(event);

/* Pour émuler le DOM, vous pouvez aussi essayer "onclick". */
ok = JS_CallFunctionName(cx, target, "onClick", 1, argv, &rval);

/* On teste rval pour voir si l'évènement doit être annulé. */
if (JSVAL_IS_BOOLEAN(rval) && !JSVAL_TO_BOOLEAN(rval))
    CancelEvent(event);

Une fois de plus, les tests d'erreurs ont été omis (tel que tester !ok après l'appel), et quelques comportements dans la gestion des évènements C pour annuler un évènement si le handler retourne false ont été simulés.

Informations sur le document original

  • Auteur : Brendan Eich
  • Dernière mise à jour : 21 Février 2000

 

Étiquettes et contributeurs liés au document

 Contributeurs à cette page : BubbleChien
 Dernière mise à jour par : BubbleChien,