Subj : Equivalent of JS_InitClass for global object? To : netscape.public.mozilla.jseng From : jjl@pobox.com (John J. Lee) Date : Fri Aug 22 2003 11:07 pm I've written a Javascript/Python bridge. I can implement Javascript objects in Python, except for one case: I can't implement the JS global object in Python (in particular, I want to implement the "window" object found in web browsers' object models). Before, I just had this: static JSClass global_class = { "MyClass", 0, JS_PropertyStub, // JSPropertyOp addProperty; JS_PropertyStub, // JSPropertyOp delProperty; JS_PropertyStub, // JSPropertyOp getProperty; JS_PropertyStub, // JSPropertyOp setProperty; JS_EnumerateStub, // JSEnumerateOp enumerate; JS_ResolveStub, // JSResolveOp resolve; JS_ConvertStub, // JSConvertOp convert; JS_FinalizeStub // JSFinalizeOp finalize; }; JSObject * make_global_object(JSContext *cx) { /* Statically initialize a class to make "one-off" objects. */ return JS_NewObject(cx, &global_class, 0, 0); } and in my context initialisation code: global_object = make_global_object(cx); JS_InitStandardClasses(cx, global_object); That was working fine, but as I say, I wanted to implement the methods and properties of my global object in Python. So, instead of a static JSClass, I arranged to use my usual machinery for binding a proxy JS object to Python, with a small variation. From the point of view of the JS interpreter, my "usual machinery" does this: 1. malloc a JSClass for the proxy. 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); 4. JS_DefineObject(cx, global_object, name, jsclass, NULL, JSPROP_READONLY); 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. 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); 4b. JS_DefineProperty(cx, global_object, name, OBJECT_TO_JSVAL(global_object), NULL, NULL, 0); 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. 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 It seems my JS_InitClass on foo doesn't work when the global object is created with NewObject. 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 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. What am I doing wrong? John .