Subj : Re: updated jsgen (maybe rc1?) - beta 7 To : netscape.public.mozilla.jseng From : Marcello Bastea-Forte Date : Sun Jan 04 2004 03:57 pm > Avoid mutable statics -- looks like you've done that (sorry I haven't > had time to read your source). No problem, if you get a chance I'd appreciate it, but I don't want you to feel obligated. :) > This is quite like what XBL does. How exactly do you mean? Does XBL generate JavaScript classes based on some xml? > One small improvement: use > JS_LookupProperty instead of JS_GetProperty if your global object > class's getter does any computation -- Lookup retrieves the slot-cached > value of the property without calling the getter. I just looked up the JS_LookupProperty function, and it needs (instead of const char *): index jsint Index number of the element to look up. Where would I get/make this value? > Another nit: use JSTest::_jsClass.name instead of repeating "JSTest". Ok, updated. > That's neither fish nor foul: better would be to avoid any dependence on > JS_GetGlobalObject, or use only it, and insist that there be a 1:1 > relationship between JSContext and global object. Mozilla's DOM does > the latter, but it is heavier-weight than the former. Would you recommend one method over the other? The only advantage I can see to allowing specific objects is for some kind of namespace functionality. For example, putting all the classes in a GUI JSObject*, and then doing something like var win = new GUI.Window(320,240). (You can do that in JS, right?) I would design without JS_GetGlobalObject, if I didn't run into the following problem: My generated getJSObject() function (all functions generated by jsgen are member functions of the individual class) is used to "convert" C++ objects to JSObject*, this is crucial for autoconversion of JS/C++ types. This function will either return the JSObject* created previously, or create a new one by calling JS_NewObject(). The problem arises when the class is a subclass, and needs to get the prototype for the parent class. It calls the parent class' JSInit function to get the prototype. That needs a JSContext* and a JSObject* so it can JS_InitClass when necessary. That JSObject* is the core of the problem. --------------------------------------------------------------- Here's an example of the generated code: _JSinternal.o = JS_NewObject(cx, &JSTestChild::_jsClass, JSTest::JSInit(cx,NULL), NULL); --------------------------------------------------------------- Currently it passes NULL for the JSObject*, (which currently defaults to JS_GetGlobalObject(cx)). To fix that, I could add a JSObject* parameter to the getJSObject() function, and pass that to JSInit. This means I need to update calls to getJSObject(). Unfortunately, in the generated JSGetProperty(...) function, I call getJSObject to convert a C++ object from the class to a JSObject*. Initially there will be no JSObject* in the C++ object to return, so it calls JS_NewObject() and needs to supply a JSObject* parameter to getJSObject(). But, I don't have as JSObject* to pass the JSInit function at this point! (The JSObject* passed to JSGetProperty is the JSObject* we're getting a property from.) The only solution I can think of is to somehow get the object where the class of the JSObject* is defined. That seems complicated and I'm not immediately sure how to do it. --------------------------------------------------------------- Besides the namespace thing, can you think of any reason to bother doing it any way other than by requiring the 1:1 global/context mapping? (Can multiple contexts share the same global object?) Similarly, do you see a way to do the namespace thing while using the JS_GetGlobalObject method? The issue only enters when using prototypes, so that could be one reason for allowing both ways. Thanks for the comments, Marcello .