Defining a [[Set]] internal method for platform objects

I'm looking for some feedback, especially from folks familiar with the 
ES spec and other implementors, for some changes I'd like to propose to 
how platform objects with named properties work.  These changes are 
meant to address <https://www.w3.org/Bugs/Public/show_bug.cgi?id=26521> 
and <https://www.w3.org/Bugs/Public/show_bug.cgi?id=25025>.

The changes are as follows:

1)  Factor out the algorithm currently defined in 
http://heycam.github.io/webidl/#getownproperty into a 
PlatformObjectGetOwnProperty abstract operation that takes three 
arguments: an object O, a property name P and a boolean "ignore" value. 
  Remove the current step 1 of that algorithm, since the "ignore" value 
is now passed in.

2)  Change [[GetOwnProperty]] on platform objects to call 
PlatformObjectGetOwnProperty(O, P, false), thus preserving its current 
behavior.

3)  Define a [[Set]] on platform objects that does the following:

1.  If O == Receiver, then:
     a. If O supports indexed properties, P is an array index
        property name, and O implements an interface with an indexed
        property setter, then:
        i.  Invoke the indexed setter (this will actually be a few
            more steps).
        ii. Return true.
     b. If O supports named properties, P is not an array index
        property name, Type(P) is String, and O implements an interface
        with a named property setter, then:
        i.  Invoke the named setter (this will actually be a few
            more steps).
        ii. Return true.

2.  Let ownDesc be the result of calling
     PlatformObjectGetOwnProperty(O, P, O == Receiver)

3.  Perform steps 3-11 of 
http://people.mozilla.org/~jorendorff/es6-draft.html#sec-ordinary-object-internal-methods-and-internal-slots-set-p-v-receiver

The idea is to ensure that we call named setters, but only when O == 
Receiver (this fixes 
<https://www.w3.org/Bugs/Public/show_bug.cgi?id=25025>) and to ensure 
that we ignore named properties when looking for a setter for the 
property (this fixes 
<https://www.w3.org/Bugs/Public/show_bug.cgi?id=26521>).  Apart from 
that, we just do the default [[Set]] behavior.

Thoughts?

To make this more concrete, here is a testcase that tests some of these 
bits, for both overridebuiltins (the dataset) and non-overridebuiltins 
(Storage) objects:

<script>
   // named setter on proto chain, no overridebuiltins
   var foo = Object.create(sessionStorage);
   foo.x = "a";
   alert("One: " + foo.x);
   alert("Two: " + sessionStorage.x);

   // named setter on object, no overridebuiltins
   sessionStorage.getItem = "b";
   alert("Three: " + sessionStorage.getItem);
   alert("Four: " + Storage.prototype.getItem.call(sessionStorage, 
"getItem"));

   // named setter on proto chain, overidebuiltins
   var bar = Object.create(document.documentElement.dataset);
   bar.x = "c";
   alert("Five: " + bar.x);
   alert("Six: " + document.documentElement.dataset.x);

   // named setter on object, overridebuiltins
   Object.prototype.z = "d";
   document.documentElement.dataset.z = "e";
   alert("Seven: " + document.documentElement.dataset.z);
   alert("Eight: " + document.documentElement.getAttribute("data-z"));
</script>

You can try it yourself at <http://jsfiddle.net/p6obqavd/>.  The above 
proposal would produce the following alerts:

   One: "a" (matches, Firefox, Chrome, Safari, IE)
   Two: undefined ((matches, Firefox, Chrome, Safari, IE)
   Three: The getItem function (matches Firefox)
   Four: "b" (matches Firefox, IE)
   Five: "c" (matches Firefox, Chrome, Safari, IE)
   Six: undefined (matches Chrome, Safari, IE)
   Seven: "e" (matches Firefox, Chrome, Safari)
   Eight: "e" (matches Firefox, Chrome, Safari, IE)

Note that the cases in which the new proposal doesn't match IE (cases 
Seven and Three) seem to be due to it treating dataset as _not_ 
overridebuiltins while treating sessionStorage as overridebuiltins, 
unlike every other browser...  So modulo that, this proposal actually 
matches IE exactly.

-Boris

Received on Tuesday, 10 February 2015 19:02:12 UTC