Brendan Eich brendan at mozilla.org
Mon Nov 12 12:39:28 PST 2007

On Nov 12, 2007, at 9:40 AM, Mark Miller wrote:

> On Nov 12, 2007 9:05 AM, Brendan Eich <brendan at mozilla.org> wrote:
>> [..], but the idea would
>> be to enable throwing of a ReadOnlyError on assignment to a ReadOnly
>
> Hi Brendan,
>
> I'm glad to hear that this possibility is in scope.

Me too -- this was one of the biggest botches during standardization
of ES1, and it should have been revisited when exception handling was

> In the Caja spec, we write:
>
>   \item[Silent errors.] In JavaScript, various operations, such as
> setting a
>   ReadOnly property, fail silently rather than throwing an error.
> Program
>   logic then proceeds along normal control flow paths premised on the
>   assumption that these operations succeeded, leading to
> inconsistency. To
>   program defensively in the face of this hazard, every assignment
> would be
>   followed by a \emph{did it really happen?}'' test. This would
> render
>   programs unreadable and unmaintainable. Where practical, Caja
> deviates from
>   standard JavaScript by throwing an exception rather than failing
> silently.
>
> For defensive consistency (as defined in my thesis) to be practical, I
> believe this change is necessary. I also believe that defensive
> consistency (or some close relative) is necessary for secure
> programming. Caja goes to a lot of trouble to achieve this while
> running on an ES3 platform. If ES4 made this change, it might make
> Caja's future life easier.

This may have been what I was thinking of when I wrote "incompatible
subset" the other week, now that you mention it. Syntactically Caja
is a subset of ES3, but the runtime semantics not only add
capabilities, they make even programs that are running in a single
trust label world, and that blithely continue past an attempt to set
a ReadOnly property in ES3, stop cold instead. As any sane runtime
semantics should!

We could just "make this change" if ES4 is selected. But ES4 already
makes Object, Array, etc. ReadOnly|DontDelete bindings in the global
object, necessary for sound typing, JSON defense in depth, etc. We
reckoned any AOP on these constructor functions was rare compared to
AOP on prototype methods (a spider of the web confirmed this; only an
old MSN .js file hacked Error for some reason). And it's not as if
ES1-3 provide for consistent AOP on the global constructor functions
anway:

http://wiki.ecmascript.org/doku.php?id=clarification:which_prototype

Therefore ES4 making the standard constructors bound by immutable
global properties is one of the two true incompatibilities mentioned in

http://www.ecmascript.org/es4/spec/incompatibilities.pdf

and we think it won't break the web, since the situation in real
browsers is inconsistent, not only per ES3's wild inconsistencies,
but because some browsers more than others avoid reflecting on
current values of the mutable bindings in spite of ES3 specifying

If some script somewhere does set Error = MyError, though, the
silence-is-golden behavior will let that pass without exception in
today's implementations. So changing ES4 to throw ReadOnlyError will
"break" what might have been benignly broken already. Not sure this
is going to cause hardship, or that it should *not* cause hardship.
You could argue that it's better to find out sooner than later. But
the costs may be born by browser users, not web developers, since the
content was written in 2002, the team that wrote it is long gone, and