Figuring out the behavior of WindowProxy in the face of non-configurable properties

Mark S. Miller erights at
Tue Jan 27 13:44:32 PST 2015

Yehuda and I just talked about this code and realized that we can allow
this code to proceed on the success path without violating the invariants.
However, this analysis reveals that the intent stated in the comment is
unwarranted, but even that intent can be adequately honored in the scenario
of interest.

The reason why the intent is unwarranted is that the descriptor omits
"configurable:" rather than explicitly saying "configurable: true". If the
owner object already has a configurable own property of the same name, then
a defineProperty where the "configurable:" is omitted defines an own
property preserving the configurability of the original own property.

Even if owner could not have already had an own property of this name,
owner might be an ES6 proxy whose target is, say, an empty object. The
handler's defineProperty trap could still first define a configurable own
property of this name, and then proceed with the normal logic.

Since the WindowProxy is not a Proxy, or more relevantly, even if it were a
Proxy, the underlying Window is not its target, we can even do the

When the WindowProxy sees the defineProperty with the omitted
"configurable:" and determines that the underlying Window does not already
have this property. WindowProxy can even preserve the unwarranted intent
expressed in the comment by actually defining a *non-configurable* own
property on the Window itself. However, the behavior of the WindowProxy is
not observably different than our Proxy example: It acts as if it created a
configurable own property on the WindowProxy of this same name, and then
proceeds with the normal defineProperty behavior, which preserves that
alleged configurability.

On Tue, Jan 27, 2015 at 11:48 AM, Boris Zbarsky <bzbarsky at> wrote:

> On 12/4/14 11:49 AM, Mark S. Miller wrote:
>> On Thu, Dec 4, 2014 at 2:58 AM, Boris Zbarsky <bzbarsky at> wrote:
>>> OK.  What do we do if we discover that throwing from the defineProperty
>>> call
>>> with a non-configurable property descriptor is not web-compatible?
>> What we always do
> So just for the record, jQuery (at least all the 2.* versions I've looked
> at) contains that following bits:
>   Data.prototype = {
>         key: function( owner ) {
> ...
>                 var descriptor = {},
> ...
>                         // Secure it in a non-enumerable, non-writable
> property
>                         try {
>                                 descriptor[ this.expando ] = { value:
> unlock };
>                                 Object.defineProperties( owner, descriptor
> );
>                         // Support: Android < 4
>                         // Fallback to a less secure definition
>                         } catch ( e ) {
>                                 descriptor[ this.expando ] = unlock;
>                                 jQuery.extend( owner, descriptor );
>                         }
> This function is called from Data.prototype.get, which is called from
> jQuery.event.add.  So the upshot is that trying to add an event listener to
> the window via the jQuery API will hit this codepath.
> Now the good news is that the try/catch _is_ present there, so this
> doesn't immediately break sites.  But it's something to watch out for, and
> we _will_ be changing the behavior of jQuery here in a way that the jQuery
> developers clearly think is undesirable.
> -Boris

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <>

More information about the es-discuss mailing list