Subj : Re: Equivalent of JS_InitClass for global object? To : "John J. Lee" From : Brendan Eich Date : Fri Aug 22 2003 05:24 pm John J. Lee wrote: >From the point of view of the JS interpreter, my "usual machinery" >does this: > >1. malloc a JSClass for the proxy. > Are you doing this for each and every proxy? I hope not. Why can't you use a static JSClass shared among all proxies, or at most one JSClass for each set of proxies of the same Python class? >2. Initialise the JSClass struct with stub methods, except for > get/setProperty (which delegate to the Python interpreter). >3. JS_InitClass( > cx, global_object, NULL, jsclass, constructor_stub, 0, > NULL, NULL, NULL, NULL); > Do you need step 3? What does constructor_stub do? >4. JS_DefineObject(cx, global_object, name, jsclass, NULL, > JSPROP_READONLY); > Do all proxies have unique names in the global object? >Obviously, 3 doesn't carry over to the case where the Python object >I'm trying to bind to JS is the JS global object itself. > Neither would 4. >So, what should I do instead? I tried the following in place of 3 and >4 above: > >3b. global_object = JS_NewObject(cx, jsclass, NULL, NULL); > This will work -- you need not call JS_InitClass to use a JSClass struct. You need to call JS_InitClass only if you have a class constructor, and want it to be named by the class name, and to have a class prototype; or, if you pass null for the constructor, to have the class name denote the class prototype object (e.g., Math). >4b. JS_DefineProperty(cx, global_object, name, > OBJECT_TO_JSVAL(global_object), NULL, NULL, 0); > Why would you make a synonym in the global referring to itself? You would if you want DOM level 0 properties such as "window" and "self" to work (and "top" in the topmost window in a frameset/frame hierarchy). So that must be what's going on here, but it seems like a different case from the original step 4. >So, to summarise, instead of: > >global_object = make_global_object(cx); >JS_InitStandardClasses(cx, global_object); > > >I've now got steps 1, 2, 3b, 4b, followed by JS_InitStandardClasses, >as usual. > Do you check the return value of JS_InitStandardClasses? Is it perhaps failing? >When I do that, though, binding another Python class (steps 1 to 3 >above) stops working -- eg. if I bind a Python class named "foo" and >then evaluate this: > >var f = new foo(); > > >spidermonkey complains: > >TypeError: foo is not a constructor > What is foo? Print or otherwise dump typeof foo, uneval(foo), etc. to get an idea. >It seems my JS_InitClass on foo doesn't work when the global object is >created with NewObject. > No, that's not the problem. The problem may lie in your proxy class's getProperty and setProperty hooks, especially in setProperty. What do those look like? > Another symptom is that, though the global >object has a "window" property, it doesn't delegate to Python -- >rather, I get: > >TypeError: window has no properties > For what expression do you get that error? You must be dereferencing window.foo or some such, and window's value is undefined or null. Again, I need to see what the proxy class's getProperty and setProperty hooks look like. >I don't understand that, because window was JS_DefineProperty'd to the >global object, whose class has get/setProperty functions that call >back to Python. > That's ok, but if your getProperty hook clobbers *vp with JSVAL_VOID, you would get the above outcome. >What am I doing wrong? > > Insufficient data, as the computers on old sci-fi movies would say; I need to see the relevant code to say more. /be .