Skip to main content

1.2. The ten days

Not required part of the course

The class asked how true the "JavaScript was written in ten days" story is. Here we provide a short overview and some context.

The claim is essentially true. It also explains almost nothing that it gets used to explain.

"Ten days" circulates as a boast among people who like JavaScript and as an indictment among people who don't, and both uses rest on the same assumption: that the language you write today is the output of those ten days. It mostly isn't. Nearly every feature cited as evidence — ==, Date, with, typeof null — has a documented arrival date. Most of them arrive later. Several arrive by explicit user request. One of them was removed by its author and put back by committee.

And the code written in those ten days was thrown away about fifteen months later.


Two facts before we start​

A prototype is not a release.

The ten days ended in a demo to a room of colleagues. The thing you could download was ten months behind it, and the first version anyone considered complete was sixteen months behind it.

WhenWhat
3 April 1995Brendan Eich joins Netscape — to "do Scheme in the browser"
~6–15 May 1995The ten days. A pre-alpha demo of a language code-named Mocha
August 1995Navigator 2.0 feature freeze — the language is triaged down to what works
September 1995First public exposure, in Navigator 2.0 beta, named LiveScript
4 December 1995Renamed JavaScript in a joint Netscape/Sun press release
March 1996Navigator 2.0 ships. JavaScript 1.0
August 1996Navigator 3.0 ships JavaScript 1.1 — the design is finally "done"
Autumn 1996Eich rewrites the engine from scratch in two weeks → SpiderMonkey
June 1997ECMAScript 1 approved

A language is not an implementation. These two drifted apart immediately. The language kept growing for a year after the sprint; the engine underneath it was replaced wholesale. When someone says "the ten-day language," it is worth asking which artifact they mean, because neither one survived in the form the story implies.


1. Who was hired, and to do what​

Eich joined Netscape on 3 April 1995, ten years out of a masters at Illinois. Those ten years were Unix kernel and networking work at Silicon Graphics, then MicroUnity, where he worked on GCC. At both companies he had built small special-purpose languages for kernel and networking tasks.

He was recruited with an explicit promise, which he has repeated for two decades:

As I've often said, and as others at Netscape can confirm, I was recruited to Netscape with the promise of "doing Scheme" in the browser. At least client engineering management including Tom Paquin, Michael Toy, and Rick Schell, along with some guy named Marc Andreessen, were convinced that Netscape should embed a programming language, in source form, in HTML. So it was hardly a case of me selling a "pointy-haired boss" — more the reverse.

— Brendan Eich, Popularity, 2008

Two things follow from this that the folklore usually drops. Embedding a scripting language in the browser was management's idea, not his — Andreessen and the client engineering leads wanted it before they had anyone to build it. And the person they got was a systems programmer with a decade of experience and a habit of writing small languages, not an intern who happened to be free that week.

The HOPL history puts that second point sharply, in its closing list of things that could have gone differently:

What if Eich had been a more experienced language designer or implementor, and concluded that the 10-day demo was an impossible task?

A more credentialed designer would very likely have refused the deadline, and the browser would have shipped something else. The inexperience was real, and it was load-bearing.


2. Why ten days​

Not because anyone thought ten days was enough. Because the ten days were an audition, not a schedule.

In early 1995 Sun was running a pre-release marketing campaign for Java, and Netscape was negotiating to put it in Navigator 2. On 23 May 1995, at Sun's public Java announcement, Netscape announced its intent to license it. Eich's rallying cry from Andreessen in that period: "Netscape plus Java kills Windows."

A second, simpler scripting language alongside Java was contested inside both companies. Three objections had to be cleared:

ObjectionAnswer
Isn't Java already suitable for scripting?Java in spring 1995 made you wrap main in a static method in a class in a package, and declare every type. Not for beginners.
Why would two languages be better than one?Microsoft already shipped this arrangement: Visual C++ for professionals, Visual Basic for everyone else.
Does Netscape even have the expertise to build one?Unanswerable in the abstract. Eich's assignment was to answer it by producing something.

That third row is the whole reason for the number ten. The deadline wasn't a ship date; it was "before the Java deal is public and the question is settled without us." Andreessen supplied the code name — Mocha — in the hope it would be renamed JavaScript in due course, which tells you exactly how much of this was a naming exercise from the start.

And the design space was closed before Eich touched it:

The diktat from upper engineering management was that the language must "look like Java". That ruled out Perl, Python, and Tcl, along with Scheme. Later, in 1996, John Ousterhout came by to pitch Tk and lament the missed opportunity for Tcl. I'm not proud, but I'm happy that I chose Scheme-ish first-class functions and Self-ish (albeit singular) prototypes as the main ingredients. The Java influences, especially y2k Date bugs but also the primitive vs. object distinction (e.g., string vs. String), were unfortunate.

— Eich, Popularity

Read that again with the dates in mind. The parts he defends are the parts he chose in the sprint. The parts he calls unfortunate are the parts the "look like Java" order imposed. The constraint that shaped JavaScript most was a marketing decision, not a time constraint — and it would have applied just as hard with a year to work in.


3. What ten days actually bought​

Concretely, on a Silicon Graphics Indy workstation:

  • a hand-written lexer and a recursive-descent parser;
  • a bytecode emitter rather than a parse tree — because Netscape's LiveWire server team, ex-Borland and already planning to embed the language before it existed, wanted bytecode for fast server-side loading;
  • a bytecode interpreter, described by its author as simple and slow;
  • values as one large discriminated union, with reference counting for memory;
  • objects with properties, a new operator, constructor functions, a built-in Object;
  • first-class functions, and this borrowed from Java to unify methods and event handlers;
  • eval;
  • and a bytecode decompiler.

That last one deserves a moment, because it is the single most telling item on the list. Supporting eval created pressure for a Java-style toString on functions, which means a function has to be able to reproduce its own source. Keeping the source text around was unaffordable on Windows 3.1, with its 16-bit segmented memory model and manual overlays. So rather than store the source, Eich wrote a decompiler that reconstructs source from bytecode — inside the ten days. That is not the choice of someone flailing. It is a targeted engineering decision about 1995 memory budgets.

What the ten days did not buy is more instructive. Eich picked a Self-inspired prototype-delegation object model with a single prototype link partly to save implementation time, and then ran out of time to expose it. Prototype-based inheritance — the thing the language is now known for — was not reachable from user code until JavaScript 1.1, sixteen months later. Function expressions were deferred too, though reserved in the grammar.

Here is JavaScript 1.0, the version that actually shipped to the public, characterised by what it refuses:

// Every line below fails in JavaScript 1.0 (March 1996).
var a = [1, 2, 3]; // no array literals; no distinct Array type at all
var o = { x: 1 }; // no object literals
if (a === b) {
} // no === operator
switch (x) {
} // no switch
do {} while (x); // no do-while
try {
} catch (e) {} // no exceptions, anywhere
var f = function () {}; // no function expressions
function outer() {
function inner() {}
} // no nested functions
/ab+c/.test(s); // no regular expressions
typeof x; // no typeof operator
x instanceof Y; // no instanceof
Child.prototype = new Parent(); // no .prototype on functions
f.call(obj); // no call/apply
The shape of the thing that was demoed

The demo at the end of the ten days was a Mocha Console, opened by typing mocha: into the browser's address bar, which split the page into two frames and evaluated typed expressions against the top one. It shipped in production Netscape 2 essentially unchanged, as javascript: — with mocha: still working.

Every javascript: URL you have ever seen in a bookmarklet is a survivor of that ten-day demo harness.

A language with no arrays, no object literals, no exceptions, no regexes, no typeof and no visible prototypes is not the language anyone is complaining about. Object and array literals — half of JSON's syntax — arrive in JavaScript 1.2, in 1997.


4. The audit​

So which notorious behaviours are genuinely the sprint's fault? Each of these has a paper trail.

BehaviourWhen it actually enteredVerdict
typeof null === "object"Value representation from the sprint; typeof itself only in JS 1.1Guilty, with an asterisk
== coercionsAdded after the sprint, on internal user requestNot guilty — see below
DateTransliterated from java.util.Date by a colleague, for Java interopNot guilty
withAdded after the sprint, at the LiveWire team's requestNot guilty
Implicit globals, function-scoped var, no block scopeIn the sprint, deliberately, for beginnersGuilty and intentional
Automatic semicolon insertionIn the sprint, deliberatelyGuilty and intentional
null vs undefinedIn the sprint, deliberately — null models Java's "no object" for interopGuilty and intentional
string vs String boxingConsequence of "look like Java"The diktat's fault
SlownessNot a goal in 1995; engines then stayed part-time-maintained interpreters for a decadeNot guilty
Reference counting (cycles leak)In the sprint, replaced in the 1996 rewriteGuilty, and the real cost

typeof null​

The famous one, and the fairest hit — but note what is actually being blamed.

Brendan Eich's recollection is that the value of typeof null was the result of a leaky abstraction in the original Mocha implementation. The runtime value of null was encoded with the same internal tag value used for object values and hence the implementation of the typeof operator returned "object" without needing any extra special-case logic.

The tagged-union representation is from the ten days. The operator that exposes it is from JavaScript 1.1, more than a year later, when there was time to special-case it and nobody did. This is the Error.isError pattern in embryo: an implementation detail becomes observable, and then observable becomes permanent. TC39 looked at fixing it for ES5 strict mode and concluded that changing typeof null "would not be subtractive" — i.e. it would break code rather than just forbid it — and left it alone.

==, in four acts​

This one is worth the space, because its history is the whole argument in miniature.

  1. In the ten days, == was strict. If the operands were of different primitive types, the answer was false.
  2. Over the summer of 1995, coercions were bolted on in response to internal Netscape alpha users. They wanted an HTTP status code arriving as the string "404" to compare equal to the number 404, and they wanted empty strings — unfilled HTML form fields — to act as 0 in numeric contexts. Both requests were granted.
  3. In JavaScript 1.2 (1997), Eich removed most of those coercions again. Users had found the behaviour confusing; so had he.
  4. In March 1997, at the third TC39 meeting, Microsoft's Shon Katzenberger argued successfully that it was too late: too many existing web pages would break. Eich reverted the change in JavaScript 1.3, and ES1 standardised the coercions. === was added alongside them as the escape hatch.

So the operator everyone points to as proof of the ten-day rush was strict when the ten days ended, was loosened by customer demand, was fixed by its author, and was un-fixed by committee on web-compatibility grounds — with the deciding argument coming from a competitor's implementer.

The result is the coercion table people screenshot:

1 == "1"; // true
1 == "1.0"; // true
"1" == "1.0"; // false ← so much for transitivity
"" == 0; // true ← someone's empty form field, 1995

Date​

Not Eich's code at all. JavaScript 1.0's Date was a direct transliteration — "bugs and all," in the history's words — of Java 1.0's java.util.Date, done by Ken Smith, an ex-Borland colleague. That is where the epoch, the 0-indexed months, and the Y2K ambiguities come from. It was deliberate, and the reason was Java interoperability.

new Date(2026, 8, 17); // September. Months are 0-indexed because java.util.Date was.

Only equals, before and after were left out of the port, because JavaScript's coercions let you use < and > on dates directly. Two warts holding each other up.

The one that actually cost something​

Reference counting. It was the cheap choice under deadline, it cannot collect cycles, and cycles are exactly what browser object graphs are full of. A proper mark/sweep collector didn't arrive until the 1996 rewrite, and the leak-and-then-use-after-free class of bug that followed from the original scheme is the one place where "we had ten days" produced lasting harm rather than a joke.


5. The rewrite nobody tells you about​

By late 1996 Eich was still the only full-time engineer on the engine, and Navigator 3.0's JavaScript 1.1 still ran mostly on the May 1995 code. Netscape management, stung by Microsoft's public needling about the absence of a specification — Thomas Reardon "took every opportunity he had to chide his counterparts at Netscape about the lack of a JavaScript language specification" — wanted him to go write one.

He refused, on the grounds that writing a spec meant reviewing the implementation line by line, and if he was going to read all of it he might as well rewrite it and fix the design mistakes before they got enshrined. The argument stalled, so he left the office, worked from home for two weeks, and replaced the core of the engine:

Ten-day MochaThe two-week rewrite
Values as discriminated unionsTagged pointers with immediate primitives
Reference countingMark/sweep garbage collection
No nested functionsNested functions
No function expressionsFunction expressions
No switchswitch

Chris Houck joined as the team's second engineer and named the new engine SpiderMonkey, after a line in Beavis and Butt-Head Do America. Mozilla still ships something under that name.

So: the ten-day codebase was in production from March 1996 to roughly the end of that year, and the language ES1 standardised in June 1997 was substantially the two-week rewrite. The most-repeated origin story in programming describes a codebase with a fifteen-month lifespan.


6. Where the warts actually came from​

In rough order of how much damage each did:

  1. "It must look like Java." A marketing constraint, not a schedule constraint. Source of the primitive/object split, null, the Date port, and the C-family syntax wrapped around a prototype language. Eich's own list of regrets is almost entirely this row.
  2. Alpha-user requests, summer 1995. =='s coercions and with both came in this way, from colleagues with a concrete problem and a deadline. Nobody was designing; everybody was unblocking.
  3. The August 1995 feature freeze. JavaScript 1.0's feature set was "essentially a triage of what was working or near working" that month. The shipped language is the intersection of a design and a calendar, and the calendar belonged to a browser release, not to a language.
  4. Two implementations and no specification. Microsoft shipped JScript in IE3 in August 1996, built by testing against thousands of live JavaScript pages and reverse-engineering every difference. Undocumented accidents became the compatibility contract before anyone wrote them down — which is precisely why Katzenberger could veto the == fix seven months later, and why he was right to.
  5. Standardisation, then stasis. ES1 froze the result in June 1997. ES3 in 1999, then nothing for a decade while ES4 was attempted and abandoned.

Step 4 is the mechanism that matters, and it is the same mechanism as in the Error.isError story a generation later. A decision costs nothing while one implementation has it and nobody has written it down. It becomes permanent the moment a second implementation copies the behaviour to stay compatible. Ten days determined what got into the first implementation; the next eighteen months determined what could never be taken out.


7. So how true is it?​

The claimVerdict
"Eich wrote the first JavaScript prototype in ten days"True. Around 6–15 May 1995 — by his own recollection; no record of the exact dates survives.
"JavaScript was designed in ten days"False. Design continued to JavaScript 1.1 in August 1996, and the core was reimplemented in between.
"JavaScript shipped in ten days"False. Public beta in four months, production release in ten.
"That's why the language is weird"Mostly false. "Look like Java," user requests, a feature freeze, and pre-specification compatibility did more damage.
"It was slapped together by someone out of their depth"False. Ten years of systems work, and a bytecode decompiler written inside the ten days.
"The ten-day code is still in there somewhere"False. Replaced in a two-week rewrite in late 1996.

The honest version is less quotable and more useful: ten days bought a demo good enough to win an internal argument, and winning that argument is what put a programming language in every browser. Everything people dislike about JavaScript was then decided at leisure — by a marketing diktat, by colleagues with tickets to close, by a browser's ship date, and finally by a competitor's compatibility testing.

If there is a lesson for the rest of this course, it is the one that Error.isError teaches from the other end. In JavaScript the cost of a decision has almost nothing to do with how long you spent making it, and almost everything to do with how many implementations copied it before anyone wrote it down.


Sources​