25.01.12

SpiderMonkey no longer supports sharp variables

Tags: , , , , — Jeff @ 10:17

ECMAScript object literals

ECMAScript, the standard underlying the JavaScript language, can represent simple objects and arrays using literals.

var arr = [1, 2, 3];
var obj = { property: "ohai" };

But it can’t represent all objects and arrays.

Cyclic and non-tree objects

ECMAScript literals can’t represent circular objects and arrays which (perhaps at some nesting distance) have properties referring to themselves (in other words, the objects form cyclic graphs). Nor can they (faithfully) represent objects which contain some other object multiple times (in other words, the objects form a directed acyclic graph which is not also a tree).

var arr = [1, "overwritten", 3];
arr[1] = arr; // cyclic
var obj = { property: "ohai", nest: {} };
obj.nest.parent = obj; // cyclic
obj.secondCopy = obj.nest; // non-tree, obj.nest is repeated

Sharp variables

SpiderMonkey historically supported extension syntax to represent such graphs under the name sharp variables. Sharp variables were inspired by Common Lisp syntax, and they enabled naming an object or array literal before it had been fully evaluated (even, to a limited extent, interacting with it). Netscape proposed sharp variables for inclusion in ES3, but the proposal was rejected as being too domain-specific and being arguably ugly. Since then the extension has lingered in SpiderMonkey but has seen very little use.

// Identical semantics using sharp variables
var arr = #1=[1, #1#, 3]; // #n= names an object being created, #n# refers to it
var obj = #1={ property: "ohai", nest: #2={ parent: #1# }, secondCopy: #2# };

No other ECMAScript implementer has since shown interest in implementing sharp variables. And with renewed efforts to evolve ECMAScript syntax, special characters like # are increasingly precious. Thus we’ve decided it’s time to remove sharp variable support from SpiderMonkey.

One benefit to removing sharp variables is that we can remove a good chunk of rarely-used code (and attack surface: sharp variables have been a source of some number of likely vulnerabilities) from SpiderMonkey. A syntax-removal patch added 79 lines and removed 1112 lines, including tests; not including tests, it added 42 lines and removed 677 lines. A subsequent patch to remove generation of sharp variable syntax from object decompilation added 65 lines and removed 128 lines. Removing sharp variables will also permit some simplifications now that evaluating a literal can’t have side effects beyond those in any nested property initializers.

Alternatives to sharp variables

Sharp variables may have been sometimes convenient, but they were mere syntactic sugar. It should be simple to convert any use of sharp variables to an equivalent sequence of property additions. If you were sufficiently aware of sharp variables to use them to represent non-tree objects, I trust I don’t have to explain how to do this.

Somewhat more interesting are the cases where decompiling an object produced sharp variable syntax, as when decompiling a cyclic object during debugging. (It’s worth noting in passing that decompilation will not infinitely recur: instead, it’ll bottom out with an empty object or an omitted property.) Jason Orendorff has written a sharps mini-library implementing decompilation of cyclic and non-tree objects which may be useful for this task.

When to expect this change

The sharp variable documentation on MDN has long noted that sharp variables were deprecated and would likely to be removed; a few months ago that warning was upgraded to a firm statement that they would be removed. The sharp variable removal patch that landed yesterday completes the process. The removal will first appear in either today or tomorrow’s nightly; in a week’s time it’ll make its way into the aurora branch, then the beta branch, and finally into Firefox 12. Versions of Firefox prior to 12 will not be affected by this removal, including the extended-support release Firefox 10.

6 Comments »

  1. Yay!!!

    Comment by Robert O'Callahan — 25.01.12 @ 13:35

  2. Great. Now we just need to remove E4X support :)

    Comment by njn — 25.01.12 @ 18:30

  3. Good man

    Comment by Luke Wagner — 25.01.12 @ 22:10

  4. @njn Are there plans to remove E4X support in the future or was that just a joke?

    Comment by Mathias Bynens — 30.01.12 @ 06:45

  5. Mathias: several of SpiderMonkey hackers would dearly love to remove E4X support — it’s a lot of complexity for not much benefit. But there are some existing consumers of that support, including some add-ons, and so removing it is not without some pain and it has some supporters. It’s an issue that has been argued about many times :/

    Comment by njn — 30.01.12 @ 16:58

  6. We don’t have definite plans at present to remove E4X support. But…

    E4X as a language feature is dying and a dead end. The ECMAScript language committee forbids use of E4X syntax in "use strict" code, and future syntax additions will build upon strict mode. Therefore using using syntax introduced by ES6, say, will require not using E4X. The version of SpiderMonkey in Firefox (either now, or in a forthcoming release, most likely the one occurring tomorrow) prohibits E4X syntax in strict mode code, so something like "use strict"; var x = <foo/>; is (or will shortly be) a syntax error.

    As a technical matter, E4X is a poor specification riddled with bugs and under-thought-out ideas. Its algorithms weren’t written with an eye toward ensuring correctness, and even fundamental E4X internal algorithms have contained, and doubtless still contain, obvious bugs. It does not integrate well with current ECMAScript (for example, it uses ES3′s internal meta-object protocol, not ES5′s newer, cleaner, better meta-object protocol), and it will integrate even worse with future versions.

    As a practical matter, SpiderMonkey hackers are much more focused on other aspects of JavaScript than E4X. E4X bugs are nearly always a low priority to fix, and they will remain so because no one else implements it, and the competitive pressure right now is on browser-agnostic JavaScript performance. No other engine implements E4X, and if I discovered one were going to implement it, I would strongly discourage them from doing so, due to E4X’s technical flaws mentioned above.

    In general, I would strongly recommend against using E4X, and I would recommend migrating existing code away from using it. It was an experiment in language evolution which did not pan out.

    Comment by Jeff — 30.01.12 @ 17:00

RSS feed for comments on this post. TrackBack URI

Leave a comment

HTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>