Code · js2-mode
js2-mode
A JavaScript editing mode for GNU Emacs, written in 2008 around a recursive-descent parser hand-ported from Mozilla Rhino. The Emacs maintainers passed it over for something smaller. It became the JavaScript mode everyone used anyway — and eighteen years later it's still maintained, with my name still on it.
What it was
I wrote js2-mode as one half of a larger plan: to make it possible to write Emacs extensions in JavaScript instead of Emacs-Lisp. js2-mode was the editor side; Ejacs, a full JavaScript interpreter in elisp, would land later the same year as the runtime. The grand plan never fully came together. The editor side outlived it by nearly two decades.
The thing that made js2-mode work — and the thing that made it roughly ten thousand lines of elisp — was the parser. Instead of the usual Emacs trick of colouring text with font-lock regexps and a bag of heuristics, I ported Mozilla Rhino's recursive-descent JavaScript parser straight to Emacs Lisp. The mode highlighted and navigated your code from a real parse tree. As I put it in the announcement: “It doesn't use heuristics or guesswork; it's exactly the same parser used by JavaScript engines.”
That bought something almost nobody else's editor had in 2008: on-the-fly syntax checking. js2-mode flagged your syntax errors, undeclared variables and missing semicolons live in the buffer as you typed, the way a compiler would. Most other editors waited for a save, or a separate lint pass, or never told you at all. The red squiggle under a typo that every developer now takes for granted in VS Code was, back then, genuinely novel. People called it revolutionary, and for a JavaScript editor at the time it more or less was.
running and the
unclosed paren flagged on the fly. Click to enlarge.
The JavaScript Mode War
I offered js2-mode to the Emacs developers and said I'd do whatever it
took to get it bundled into Emacs itself. What happened next happened
mostly without me, on the emacs-devel mailing list across
2008 and 2009, and it has since picked up a name among Emacs
old-timers: the JavaScript Mode War.
The objection was size. Ten thousand lines of elisp and a whole ported
parser struck some maintainers as too heavy a thing to carry in core.
A simpler, lighter JavaScript mode — originally Karl Landström's
espresso-mode, later taken over and maintained by Daniel
Colascione — was championed as the alternative. When the dust
settled, Emacs 23.2 (2010) shipped that simpler mode,
renamed js-mode, as the bundled default. js2-mode stayed
outside, an extra package you had to go and install.
On the merits of the committee's brief, that's defensible: core should be lean, and not everyone wants a parser in their editor. But it left the more capable mode on the outside — the recurring shape of how these things go.
It won anyway
Being passed over for core turned out not to matter. js2-mode is the mode Emacs users actually installed — for over a decade it was the answer to “how do I edit JavaScript in Emacs,” and it still is. The bundled mode handled the common case; js2-mode was the one you reached for when you wanted the editor to actually understand the language.
I stopped maintaining it long ago. The community didn't let it die. Development moved to mooz/js2-mode (Mihai Bazon, Dmitry Gutov and a long list of contributors), and a historical mirror of my original sits at johan/js2-mode-yegge. The mode eventually made it into the official GNU package archive after all: it's on GNU ELPA today, and the author line still reads Steve Yegge, mooz, Dmitry Gutov.
And it has kept up with the language the whole way. The maintained js2-mode tracks async/await and ES6 modules (2016), class fields, optional chaining (2020), top-level await and async generators (2023) — a steady eighteen-year line of updates on a parser I ported on my commute in 2008. Most of the code I've written has a shelf life. This one is still running.
Read on
The original 2008 announcement — half release-notes, half manifesto — is here in the archive (and on its catalog page). Its companion, the Ejacs JavaScript interpreter, was the other half of the plan. For the rest of the open-source work, see the Code page.