Aller au contenu | Aller au menu | Aller à la recherche

Retourner un JSObject avec un XPCOM en C++

Je me suis lancé dans cette entreprise afin d'alléger l'utilisation de de XPConnect. L'objectif était de retourner un objet JavaScript au lieu d'un objet XPCOM. L'intérêt est de wrapper un objet C++ en JavaScript sans paser par de nombreux composants XPCOM. Le seul problème de cette technique est que l'on ne conserve pas de référence directe à l'Objet C++.

Récupérer le Context JavaScript

La première chose à faire est de récupérer le Context JavaScript, pour ce faire vous pouvez utiliser cette class créer par Paul :

class NativeJSContext {
  public:
    NativeJSContext() {
      if (!gXPConnect) {
        nsresult rv = CallGetService(nsIXPConnect::GetCID(), &gXPConnect);
        if (NS_FAILED(rv)) {
          NS_ERROR("Failed to get XPConnect!");
          return;
        }
      } else {
        NS_ADDREF(gXPConnect);
      }

      error = gXPConnect->GetCurrentNativeCallContext(&ncc);
      if (NS_FAILED(error))
        return;

      if (!ncc) {
        error = NS_ERROR_FAILURE;
        return;
      }

      ctx = nsnull;

      error = ncc->GetJSContext(&ctx);
      if (NS_FAILED(error))
        return;

      JS_BeginRequest(ctx);

      ncc->GetArgc(&argc);
      ncc->GetArgvPtr(&argv);
    }

    ~NativeJSContext() {
      JS_EndRequest(ctx);
    }

    nsAXPCNativeCallContext *ncc;
    nsresult error;
    JSContext *ctx;
    PRUint32 argc;
    jsval *argv;
};

Que vous exploiter ainsi :

 NativeJSContext js;
 if (NS_SUCCEEDED(js.error)) {
   /* Ici le code de création d'objet Javascript */
 }

Le Context JavaScript est nécessaire à la création de tout objet JavaScript et il est accessible ainsi :

 js.ctx /* tout simplement */

Créer un objet JavaScript

La première méthode consiste à créer un nouvel Objet JavaScript :

 JSObject *nJSObj = JS_NewObject(js.ctx, NULL, NULL, NULL);

Les méthode suivantes permettent de modifier l'objet en définissant ou ajoutant une propriété :

 jsval propval;
 JS_DefineProperty(js.ctx,nJSObj,"NewProp",propval,NULL,NULL,JSPROP_ENUMERATE);
 JS_SetProperty(js.ctx,nJSObj,"NewProp",&propval);

Créer un tableau JavaScript

La première méthode consiste à créer un nouveau tableau JavaScript :

 JSObject *nJSArray = JS_NewArrayObject(js.ctx, 0, NULL);

Les méthodes suivantes permettant d'ajouter un élément à notre tableau :

 jsuint len;
 JS_GetArrayLength(js.ctx, nJSArray, &len);
 jsval eleval;
 JS_SetElement(js.ctx,nJSArray,len,&eleval);

Créer des valeurs JavaScript

Comme vous avez pu le constater il faut créer des valeur JavaScript, jsval, pour pouvoir modifier vos objets JavaScript, objet et tableau.

La première méthode permet de transformer un objet ou un tableau en valeur JavaScript :

 jsval objval = OBJECT_TO_JSVAL(nJSObject);
 jsval arrayval = OBJECT_TO_JSVAL(nJSArray);

La seconde permet de transformer un entier en valeur JavaScript :

 jsval intval = INT_TO_JSVAL(100);

La troisième permet de transformer un nombre, double ou float, en valeur JavaScript :

 jsval numval;
 JS_NewNumberValue(js.ctx,10.50,&numval);

Enfin les méthodes suivantes permettent de transformer des chaines de caractères en valeur JavaScript :

 jsval strval;
 /* Pour un LITERAL ou une chaîne de caractères se finissant par null */
 strval = STRING_TO_JSVAL(JS_NewStringCopyZ(js.ctx,"une string"));
 /* Pour ne copier qu'un certains nombre de caractères */
 strval = STRING_TO_JSVAL(JS_NewStringCopyN(js.ctx,"une string",4));
 /* Pour créer une chaîne de caractères */
 strval = STRING_TO_JSVAL(JS_NewString(js.ctx,"une string",10));

Retourner l'Objet JavaScript créer

Voilà comment finir et faire en sorte que du côté JavaScript vous récupérier le réultat :

 jsval *retvalPtr = nsnull;
 js.ncc->GetRetValPtr(&retvalPtr);
 *retvalPtr = OBJECT_TO_JSVAL(featcol);
 js.ncc->SetReturnValueWasSet(PR_TRUE);

Conclusion

Maintenant vous avez tout ce qu'il faut pour créer vos premiers Objets JavaScript. Bien sûr Mozilla vous permet de faire plus comme créer des Class JavaScript ou des Fonctions JavaScript!

Voici le liste des références :