SpiderMonkey's API has a lot of C-isms in it that will gradually disappear, moving forward, as we start using cleaner C++ idioms. This email announces a couple such changes, that embedders can begin reacting to now, in advance of SpiderMonkey 24 and future releases that make those changes.
The first change is the important one. The second change is less important, as the breaking change that motivates it is probably a ways off (and easily worked around when we do make it).
== Use JS::CallArgs and JS::CallArgsFromVp when writing JSNatives ==
The current JSNative signature in SpiderMonkey 17, and on trunk, is:
typedef JSBool (*JSNative)(JSContext *cx, unsigned argc, jsval *vp);
Every call to a JSNative has to push three (count 'em) arguments. Every argument push has a cost when JITting, or when calling from compiled code. It was far worse back in the JSNative+JSFastNative days, to be sure, when JSNative took five (?) arguments, but even three's still too many.
We'd like to cut JSNative down to one argument, but I doubt we'll get there by SpiderMonkey 24. There's a decent change we'll get it to two arguments, tho -- by combining argc/vp into one argument: a const JS::CallArgs&. This'll be a single pointer value (as a reference, for readability), taking us down to two arguments.
JS::CallArgs is a very minimal struct encapsulating argc/vp and providing access to the stuff in vp. It's basically a C++ version of the JS_THIS_VALUE, JS_THIS_OBJECT, JS_ARGV, JS_RVAL, JS_SET_RVAL, JS_CALLEE, etc. macros/inlines. One great part about it is that it asserts that you're using it correctly. The macros/inlines couldn't do this, because they didn't have all the info to do it.
We haven't changed JSNative, but we *have* made it possible in 17 to start using CallArgs even in JSNative as currently defined. Simply create a CallArgs from argc/vp at entry to your native, then use CallArgs for everything, and never use argc/vp. The JS::CallArgsFromVp(argc, vp) method will create a CallArgs for you to use. Here's a JSNative written the old way:
static JSBool
FunctionReturningArgcTimesArg0(JSContext *cx, unsigned argc, JS::Value *vp)
{
// Guard against no arguments or a non-numeric arg0.
if (argc == 0 || !JSVAL_IS_NUMBER(JS_ARGV(cx, vp)[0])) {
JS_SET_RVAL(cx, vp, JS::Int32Value(0));
return true;
}
JS_SET_RVAL(cx, vp, JS::NumberValue(args.length() * args[0].toNumber()));
return true;
}
And here's how you'd write it using CallArgs:
static JSBool
FunctionReturningArgcTimesArg0(JSContext *cx, unsigned argc, JS::Value *vp)
{
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
// Guard against no arguments or a non-numeric arg0.
if (args.length() == 0 || !args[0].isNumber()) {
args.rval().setInt32(0);
return true;
}
args.rval().set(JS::NumberValue(args.length() * args[0].toNumber()));
return true;
}
Pretty much everything you can do with the inlines/macros, you can do with methods on CallArgs. There is one exception: JS_THIS_OBJECT and JS_ComputeThis still require using |vp|. For these, we're probably going to have people handle the primitive-this-value cases manually. Strict mode functions can do it, so we think it's not generally a burden in most cases.
Where is CallArgs documented, you ask? We're documenting it in the header that defines it. (Given that headers are closer to code, we might follow this tack more in the future, but that's just a guess.) CallArgs is in jsapi.h in 17, mostly undocumented. But on trunk it's in its own js/CallArgs.h header, with copious documentation:
https://hg.mozilla.org/mozilla-central/file/4006800a51db/js/public/CallArgs.h
There are probably small parts of that that will change by the time 24 comes around, but what you see there should be pretty stable, and will correlate with what's in 17. It's worth reading or skimming the entire thing -- I basically relate the entire story of this email there, with a little more detail.
You don't *have* to use CallArgs now. But you probably should start using it now, gradually switching all uses of argc/vp over to it. Then, when JSNative changes, it's just a matter of changing each function's signature, and removing one line from each function, to be compatible with new SpiderMonkey.
== jsval is dead, long live JS::Value ==
In SpiderMonkey 17, jsval is still a C-compatible type, with JS::Value hidden behind C++ #ifdefs. On trunk, JS::Value and jsval are identical types -- with jsval as a typedef of JS::Value. It's likely that we'll eventually remove jsval and have only JS::Value, for simplicity. So you should gradually begin converting uses of the type "jsval" to instead use "JS::Value". Given its pervasive use everywhere, you might consider a |using JS::Value;| at the top of each file to avoid the JS:: prefix everywhere, but that's your own style issue to consider.
That said, the |typedef JS::Value jsval;| that exists now will probably stick around for awhile. There's no particular rush to remove jsval, so feel free to do s/jsval/JS::Value/ at your leisure. And whenever we do end up removing the typedef, you could easily add it to your own code if you preferred that name, to be sure.
Anyway, hope this helps embedders out. We don't have concrete plans for when we'll make the changes noted here, but given the fundamentality of the changes, you probably will want as much lead time as possible to react to them.
Jeff