Assigning to ReadOnly properties

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
>> property. Comments?
>
> 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  
added in ES3.

> 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  
that sporadically.

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  
no one helpful is reading hostmaster at bigcompany.com.

If we instead add a pragma to enable ReadOnlyError, that would still  
help Caja at some point, right?

/be



More information about the Es4-discuss mailing list