On 05/25/2012 10:24 AM, Juan Conejero wrote:
> However, doesn't JS_ConstructObject() seem an easier and more convenient way (from the embedder's POV) to instantiate native classes?
It's more convenient because JS_InitClass returns the new prototype, and doesn't directly return the new constructor. I expect we'll make the constructor more prominent in the class API to address this at some point.
But JS_ConstructObject is also slower than JS_New because it recomputes the constructor function every time it's called. And it can't always compute it correctly. JS_ConstructObject(cx, clasp, parent) can throw or return a nonsensical value if anyone overwrites |global[clasp->name]|. This is an API design flaw that can't be worked around.
But if you wanted to keep using JS_ConstructObject warts and all, jorendorff suggests this (modulo any typos) would work:
JSObject *
JS_ConstructObjectWithArguments(JSContext *cx, JSClass *clasp,
JSObject *parent, unsigned argc, jsval *argv)
{
JSObject *global = JS_GetGlobalForScopeChain(cx);
jsval v;
if (!global || !JS_GetProperty(cx, global, clasp->name, &v))
return NULL;
if (JSVAL_IS_PRIMITIVE(v)) {
JS_ReportError(cx, "cannot construct object: constructor is gone");
return NULL;
}
return JS_New(cx, JSVAL_TO_OBJECT(v), argc, argv);
}
JSObject *
JS_ConstructObject(JSContext *cx, JSClass *clasp, JSObject *parent)
{
return JS_ConstructObjectWithArguments(cx, clasp, parent, 0, NULL);
}
> If there's no compelling reason to remove them, may I suggest that you preserve these API functions in future versions?
The API design flaw bit is the compelling reason not to preserve this. If we provide an API and simply hope people won't use it, we'll end up disappointed, even just because those people didn't know any better.
Jeff