dataset [[DefineProperty]] hook does not reject accessor properties
Reported by
bzbar...@mit.edu,
Sep 9 2016
|
|||||||||||||||
Issue description
UserAgent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:51.0) Gecko/20100101 Firefox/51.0
Example URL:
Steps to reproduce the problem:
1. Run this in the console:
var x = document.documentElement.dataset;
Object.defineProperty(x, "nosuchpropanywhere", {get: function() {} });
What is the expected behavior?
An exception is thrown.
What went wrong?
No exception.
Does it occur on multiple sites: Yes
Is it a problem with a plugin? No
Did this work before? N/A
Does this work in other browsers? No Firefox, current
Chrome version: 55.0.2853.0 (Official Build) dev (64-bit) Channel: n/a
OS Version: OS X 10.10
Flash Version: Shockwave Flash 22.0 r0
Relevant spec is https://tc39.github.io/ecma262/#sec-object.defineproperty which in step 4 calls https://tc39.github.io/ecma262/#sec-definepropertyorthrow which in step 3 calls O.[[DefineOwnProperty]].
That lands in <http://heycam.github.io/webidl/#defineownproperty>. This object does not support indexed properties, and this is not an array index property name anyway, so we go on to step 2. In step 2.1, this is not a supported property name, so we set creating to false. In step 2.2, the interface is in fact [OverrideBuiltins], so we go to step 2.2.1. The interface has a named property setter, so we go on to step 2.2.2. In step 2.2.2.1, IsDataDescriptor() is false, so we return false.
Now we unwind back to https://tc39.github.io/ecma262/#sec-definepropertyorthrow step 4, and since success is false, throw a TypeError exception.
This is the exception Chrome is not throwing.
⛆ |
|
|
,
Sep 9 2016
,
Sep 11 2016
,
Sep 12 2016
Franziska has been working on better-supporting Object.defineProperty when called on API objects.
,
Sep 13 2016
I'll have a look.
,
Sep 13 2016
We actually don't abort in 2.2.2.1 but define the property. I guess if we aborted, we might throw?
> Object.getOwnPropertyDescriptor(x, 'nosuchpropanywhere')
< Object {set: undefined, enumerable: false, configurable: false}
,
Sep 13 2016
,
Sep 13 2016
,
Sep 15 2016
bzbarsky, thanks for reporting this. The fix is easy (see https://codereview.chromium.org/2331223004), but it would break too many other things. Since Chrome, Safari, Edge, and Firefox all expose this behavior, I was hoping we could change the spec. Is a PR the right way to do this?
,
Sep 15 2016
What would it break? Changing the spec is doable, but the resulting behavior is completely broken (it just uses the "value" from a non-value descriptor and converts it to a string!), so I don't see how anyone could be depending on it right now...
,
Sep 16 2016
My fix would result in an exception in the Node.js interactive shell (REPL) every time defineProperty() with an accessor descriptor is called. Because REPL (or rather the vm module) defines NamedSetterCallbacks on the global object. Why do we not allow to set properties on platform objects to accessor descriptors? Is that an artifact from when defineProperty() wasn't around? (Sorry, I'm not very familiar with Web IDL spec).
,
Sep 16 2016
> My fix would result in an exception in the Node.js interactive shell That sounds like a Node-specific situation that shouldn't affect the behavior of Chrome. There's no a priori reason changing Chrome's behavior here should require changing Node.js. > defines NamedSetterCallbacks on the global object You don't have to apply this behavior to any objects that are not WebIDL objects with named setters, obviously. If you're applying it to other objects, that sounds like a problem with your fix... > Why do we not allow to set properties on platform objects to accessor descriptors? Because it's a nonsensical operation for an object with a named setter. The whole point of a named setter is that all property definition is diverted to the named setter. But it makes no sense to do that with a non-value descriptor. Note that this only affects objects with named setters, which in practice means just DOMStringMap. Now we could spec the "just use undefined" behavior, but I don't see how it would help authors any: instead of an exception that tells them their property did not get defined, they would just get silent failure to define it as they tried (and no functional getters or setters anyway, note!).
,
Jan 5 2017
I would really like to make progress on this, but don't want to make changes to Gecko that Chrome isn't going to follow. If you don't plan to implement the spec as written, have you raised a spec issue with your proposal for what the spec should say instead?
,
Jan 5 2017
+yukishiino@ as he's been helping a lot in making our bindings more compliant. I tend to agree with Boris that allowing this operation is nonsensical and that any Node.js-specific problems should be worked around, Node.js code isn't actually doing a defineProperty with an accessor descriptor on a DOM object, since there are no DOM objects in Node.js, so maybe we can fix e.g. by making it so the mechanism Node.js uses isn't conflated with the DOM (Web IDL) named setter mechanism.
,
Jan 10 2017
re #11: IIUC, the step 2.2.2.1 shouldn't be applied if the object is [Global] or [PrimaryGlobal]. "legacy platform object" is not [Global] nor [PrimaryGlobal] by definition at all, right? Then, your fix shouldn't be applied to the case of "REPL defines NamedSetterCallbacks on the global object." because it's the global object.
,
Nov 2 2017
Do we really want to fix this? We would have different behavior than Firefox.
,
Jun 14 2018
Firefox would like to change its behavior here, but not if we're the only ones doing it. So if you did make this change you would not end up with different behavior from Firefox.
,
Jun 15 2018
I should have taken much closer look one year ago. I now understand the issue and solution clearly. For indexed properties, Blink already implements "IsDataDescriptor(Desc) is false, then return false." https://cs.chromium.org/chromium/src/third_party/blink/renderer/bindings/templates/interface.cpp.tmpl?l=340&rcl=32efca451ff8fcdecb2733d873d24a977ddf2b28 For named properties, Blink should use v8::GenericNamedPropertyDefinerCallback where we can tell whether the property being defined is an accessor property or data property. Issue 764633 is related to use of "definer callback". Once we become to use "definer callback", then this issue will be fixed with a pretty straightforward way. I don't see difficulty on this issue. Of course, Blink-local change shouldn't affect Node.js. rakuco@, are you interested in this issue and/or Issue 764633 ? If you're busy with other projects, I will try to find time for this issue.
,
Jun 15 2018
I'd like to work on that one; I think the change is pretty straightforward, the problem is that we've been blocked on https://bugs.chromium.org/p/v8/issues/detail?id=7612 in V8 for a while now.
,
Jun 18 2018
,
Jun 18 2018
I see. Let's fix V8 first. Let me assign this issue to rakuco@ for the time being. |
||||||||||||
►
Sign in to add a comment |
|||||||||||||||
Comment 1 by bzbar...@mit.edu
, Sep 9 2016