The technical plans described below are long-term goals for SpiderMonkey. We aren't necessarily actively working toward completion of any of them. We do try to fix bugs in the short term, in ways that will make these plans easier, or will not get in their way.
If you're interested in any sort of architectural bug-fixing, feel free to work on any of these projects. Some are easier, some are harder and further-reaching, some would have been done already but for their requiring wider-spread changes, without immediate gain. For more details on any of these plans, ask questions in #jsapi.
- 1 Object representation
- 2 VM
- 3 JIT
- 4 JSAPI improvements
Proxies right now are highly entangled with the engine. Working with them often requires diving into friend APIs. As we make no promises about friend APIs remaining anything close to stable, this makes it tricky to use them. We want to gradually change the JSAPI so that if you want an object with any sort of "special" behavior, you implement it as a proxy.
As part of this plan,
JSClass will gradually die. The idea of classes is in the middle of deprecation in ECMAScript, so this is a natural step to make. We will still support objects with customized property-lookup, property-getting, property-setting, etc. behavior. These will simply be hooks defined as part of the proxy definition interface, not tied to something named
Replace the property lookup mechanism with
ECMAScript speaks in terms of properties existing as descriptors, that exist/are owned by a single object. This is similar to, but not quite the same, as the current
lookupProperty mechanism. We have a bit of work to do to change things so that when someone requests a property, instead of an opaque pointer, they receive (or have filled in) a property descriptor structure.
Split property/element storage
- bug 586842 - Store properties named by uint32_t separately from properties named otherwise
JSContext as a concept
JSContext included state necessary to run JS code. These days, most such state is instead stored in
JSRuntime, and some state is stored per-compartment or per-global object or per-zone. If we can move all such information out of
JSContext, we should be able to get rid of it entirely.
JSRuntime or global/compartment-centric methods would expose all the same information.
- bug 650361 - rm JSContext
Add a warning mechanism distinct from the error-reporting mechanism
Reporting a warning right now requires creating an error type, an error message reporter, and other inanities. Warnings should be reporting in a distinct manner from exceptions and shouldn't use the same overloaded mechanism.
Remove error reporting, replace it with exception-catching mechanisms
We currently have both error-reporting, and exception-throwing, error mechanisms. Two is too many. We need to come up with a coherent story for how to deal with all of this, that plays naturally to JS semantics. That probably means that errors should be dealt with only in terms of exception objects. And as far as extracting the information currently in a
JSErrorReport goes, that should probably be exposed through a method that takes in a value/object and returns the right data if a usable Error object was passed, or some sort of plausible, partial substitute if not.
Having multiple kinds of accessor properties -- the ECMAScript form, and ones with these C++ function-pointer types -- is all sorts of complicated. We should get rid of these types and have all properties be completely understood by, and mappable into, the ECMAScript system. If a property type that's a native C++ function pointer is desired, it should be
JSNative -- whose semantics map straightforwardly onto those defined by ECMAScript.
We've largely gotten rid of property op uses in Gecko, but there's still a bit more work to do before we could make this step and remove the idea completely. Particularly, there are a few internal uses of property ops in SpiderMonkey that will require careful work to address, before we can remove property ops completely.
- bug 570568? - Calling JSPropertyOps against objects not of the corresponding class has bad human factors
CodeGenerator to clearly separate architecture-agnostic/specific methods
CodeGenerator methods are implemented in all the separate backends, now (or sometimes in x86-shared backends). These methods are freely intermixed with methods defined only for a single architecture. If we threw some templates, protected inheritance, etc. at this, it should be possible to separate cross-architecture (but possibly defined in architecture-specific files) methods from architecture-specific methods. It's unclear how this could be done. Maybe private inheritance, plus
using statements in the architecture-specific
CodeGenerator base classes? This problem (of writing a patch, only to find on submission to try that an arch-specific method was mistakenly used) crops up pretty often for new-ish JIT hackers, so it'd be nice to fix it.
Create a clean, fully-C++ API
Most of the JSAPI is old, C-style
JS_* functions. These functions' APIs often aren't particularly simple, clean ways to implement those behaviors. A pleasant C++ API that reads more simply, and doesn't necessarily expose operations through hundreds of freestanding methods, would be nice. We've incrementally introduced such APIs at lower levels -- see for example
JS::Value -- but we haven't done anything yet at higher levels. Mostly this is a matter of inertia, and of API design being a bunch of hard work that's off the critical path for Firefox. We'd probably welcome help from embedders and the like with special interest and expertise in designing nice, clean C++ APIs for this stuff. (Do note, however, that we still require an exception-safe API -- true/false return values to indicate success will still probably be necessary.)
Recent changes mean that SpiderMonkey's historical
jschar type is identical to
char16_t (an emulated
typedef in older compilers). We should cut out the middle man and just use
char16_t directly. This is mostly a large search-and-replace operation on Gecko and JSAPI headers.
- Fixed by bug 1063962
const char* with
C string APIs were historically pretty convenient. These days, though, with the recent addition of
MOZ_UTF16, it's easy to write UTF-16 strings in source code. APIs that take C strings now, should be converted to take 16-bit-wide strings and lengths. This potentially eliminates an inflate operation and reduces the number of different string types to think about. It also makes non-ASCII strings be handled by the default case, which is good for correctness.
Remove shortids and tinyids (FIXED)
In ECMAScript, properties are referred to by strings, full stop. ES6 and our implementation add some flourishes to this (symbols/property keys, access by
uint32_t), but it remains the case that properties have only one name, and that name corresponds to the concept defined by ECMAScript, or a pure transformation of it.
Allowing properties to exist using a different name than the canonical ECMAScript name introduces a fair bit of complexity into SpiderMonkey. (And if there's a part of SpiderMonkey that absolutely can't afford extra complexity, it's our property representation/lookup code paths.) Doing so doesn't appear to have a memory cost, because the extra name fits into what would otherwise be padding. But it's extra work to keep track of it, extra work to preserve it, extra work to distinguish properties that differ only in their shortid -- and all this only for the benefit of users of
JSStrictPropertyOp, which as previously noted we want to remove.
- bug 797126 - Remove tinyid/shortid
Removal of the (FIXED)
jsval typedef in favor of
jsvaltypedef in favor of
JS::Value are identical. As part of moving more fully to cleaner C++, we should get rid of
jsval. Doing so requires cleaning all use of
jsval from Gecko -- not hard, but again, just not on anyone's critical path. (Embedders can easily adapt to this by adding
typedef JS::Value jsval; to their code as a temporary fix, if needed.)
bug 842186- Replace all use of jsval with JS::Value
JSNative's signature will be changed to accept
The current arguments to
JSNative are pretty error-prone. Passing a single class-based argument, that asserts correctness of use, would be preferable -- for correctness checking for sure, and possibly for greater performance (passing one argument being faster than passing two, potentially). We've introduced a helper structure,
JS::CallArgs, for this purpose, that can be created from the arguments passed to a
JSNative. It's trivial to create such a structure inside every method, then only interact with the arguments through that. New code should use
Once all of Gecko has switched to
JS::CallArgs, we can consider switching
JSNative to use it as a parameter -- probably
const CallArgs& -- with a minimum of effort. (Unfortunately this effort will involve touching every function implementing the
JSNative signature. At least with every function already working in terms of
JS::CallArgs, such a patch won't need to touch function logic when it does so.) This is a prerequisite to any such experimentation, or changes to