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

This seems overall sane to me. Pretty convoluted, but https://bugzilla.mozilla.org/show_bug.cgi?id=1043690 makes it clear there's web-compat constraints that will probably get in the way of anything simpler, and your test cases imply this gives a good compatibility cross-section.

I don't suppose there's a way to change the results for Three and Four that both gets at least two browsers and simplifies the proposal? That's the only way I see this being improved. I apologize for not having the fortitude to dive into the details and attempt to come up with such a modification myself.

-----Original Message-----
From: Boris Zbarsky [mailto:bzbarsky@mit.edu] 
Sent: Tuesday, February 10, 2015 14:02
To: public-script-coord@w3.org
Subject: 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 22:00:29 UTC