@@toStringTag spoofing for null and undefined

Brendan Eich brendan at mozilla.org
Tue Jan 20 20:30:19 PST 2015

Mark S. Miller wrote:
> On Tue, Jan 20, 2015 at 4:44 PM, David Ungar <ungar at mac.com 
> <mailto:ungar at mac.com>> wrote:
>     Oh, the troubles with email.
>     I’ll try again:
>     Self stratifies things into base- and meta- level. The idea is
>     that almost all code is better off sticking to base level because
>     that promotes encapsulation and reuse.
>     At base-level all you can do is throw messages at objects and then
>     throw more messages at whatever bounces off of what the first
>     messages return.
>     So you can always substitute an object with similar behavior for
>     another.
>     At meta-level, you can interrogate the object to look inside; what
>     slots it has, etc.
>     This design confers reusability, eases deployment, proxying, etc.
>     The paper Gilad and I wrote for OOPSLA 2004 (“Mirrors…”) explains
>     this well.
>     I gave a talk on this just last Fall at OOPSLA -- the paper
>      received an award. (Gilad was great at explaining the benefits of
>     mirrors.)
>     In keeping with this design, our (base-level) identity operator
>     was just another message.
> For a greenfield design, all this sounds reasonable. E had identity as 
> == at base level, but we had only debated the alternatives of have it 
> at all (E) vs not having it at all (Joule). The idea of having it, but 
> placing it in a more obscure part of the language surface didn't occur 
> to us.

JS has a sorry history here, details below, but we might evolve (with 
messy redundancy, as usual on the Web due to backward compatibility) 
toward something like Self's nice separation.

>     When I asked about why JS has ===, it was a completely serious
>     question, hope it didn’t sound facetious: When === was put into
>     JS, what was the motivation?
>     I really don’t know. I designed Self’s identity operator based on
>     my perception of why ST had (and misdefined, IMO) its identity
>     operator.
> I didn't take it as facetious, but I was worried it might distract 
> from the current debate about what to do now, given our history.
> Regarding the original motivation, Brendan?

As is well known, I hacked JS in 10 days. I had only == (and != of 
course), along with the other C operators plus >>> from Java.

At first I believe == was an equivalence relation ignoring NaN. But I 
had Perl 4 and Borland "Loose-C" (Lucy, get it) and other influences 
pressing on me, some from Netscape early adopters of "Mocha" (JS's first 
code name), who were creating very early HTML scripts to manipulate 
numeric form fields. These folks asked for implicit string to number and 
other conversions.

I was an idiot: I gave them what they wanted.

When the smoke cleared by late summer 1995 and the first Netscape 2 beta 
that shipped "LiveScript" (second code-name), we were left with == 
damaged by implicit conversions, much as in other mid-90s amateur-hour 
dynamic languages.

When Netscape took JS for standardization to Ecma in fall 1996, I 
hustled to re-implement (in SpiderMonkey, which still lives and now has 
JITs, generation GC, the works), and I made a hard compatibility break 
under opt-in versioning. If you wrote

<script language="JavaScript1.2">...</script>

then the code elided via ... would get an == that is identical to the 
=== we know today, the one codified in ECMA-262 Edition 1 (1997).

During ES1 standardization, I tried briefly to talk Shon Katzenberger of 
MS into making a clean break, a kind of "flag day": Netscape and MS IE 
would both change the meaning of == on a certain release date. This was 
not workable, of course: Prisoner's Dilemma browser market share game.

As a fallback, I tried (also briefly) to promote opt-in versioning, but 
it was a non-starter then, just as it remains now (1JS FTW!). Versioning 
is an anti-pattern on the Web.

Shon put us out of my misery by counter-proposing that we add === and 
!==, which he was spec'ing in draft ES1 and had (IIRC) prototyped. Sold! 
I try not to look back, I'm all "cringed out". (But == stinks still; can 
it be reformed? See below.)

>     I apologize for belaboring the obvious.
> No apology necessary!

Definitely not!

>     From your response, it sounds as if == is non-overidable today. Is
>     that right?
> Correct.

For value objects in ES7, I've proposed that many operators become 
base-level messages (dispatch details for dyadic operators not to be 
digressed upon here ;-), to use the nice language David used above. From 
slide 4 of http://www.slideshare.net/BrendanEich/value-objects2,

• | ^ &
• ==
• < <=
• << >> >>>
• + -
• * / %
• unary- unary+ boolean-test(!!) ~

The other operators save === and !== (which cannot be overridden) are 
derived algebraically to preserve important identities.

Some sketchy later slides in that deck try for opt-in reform of == to 
undo the implicit conversions that make it intransitive for numbers and 
strings; I was just sketching. Point here is that with enough work on 
operators and value objects, I bet we could recover a better ==. We'd 
still be stuck with === but at least === is reliable without patching.


More information about the es-discuss mailing list