This is an archived snapshot of W3C's public bugzilla bug tracker, decommissioned in April 2019. Please see the home page for more details.

Bug 22320 - Form's supported property names should perhaps not be enumerable
Summary: Form's supported property names should perhaps not be enumerable
Status: RESOLVED WORKSFORME
Alias: None
Product: WebAppsWG
Classification: Unclassified
Component: WebIDL (show other bugs)
Version: unspecified
Hardware: Other other
: P3 normal
Target Milestone: ---
Assignee: Cameron McCormack
QA Contact: public-webapps-bugzilla
URL: http://www.whatwg.org/specs/web-apps/...
Whiteboard: [v1]
Keywords:
Depends on: 22600
Blocks:
  Show dependency treegraph
 
Reported: 2013-06-10 19:22 UTC by contributor
Modified: 2016-08-30 20:27 UTC (History)
9 users (show)

See Also:


Attachments

Description contributor 2013-06-10 19:22:03 UTC
Specification: http://www.whatwg.org/specs/web-apps/current-work/multipage/forms.html
Multipage: http://www.whatwg.org/C#the-form-element
Complete: http://www.whatwg.org/c#the-form-element
Referrer: http://www.whatwg.org/specs/web-apps/current-work/multipage/

Comment:
Form's supported property names should perhaps not be enumerable

Posted from: 98.110.194.206 by bzbarsky@mit.edu
User agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:24.0) Gecko/20130606 Firefox/24.0
Comment 1 Boris Zbarsky 2013-06-10 19:51:50 UTC
At first glance, this testcase:

  <form id="f"><input id="i"></form>
  <pre><script>
    var f = document.getElementById("f");

    document.writeln("i" in f);
    document.writeln("i" in Object.getPrototypeOf(f));
    var names = Object.getOwnPropertyNames(f);
    document.writeln(names.indexOf("i"));
    var found = false;
    for (var x in f)
      if (x == "i") found = true;
    document.writeln(found);
  </script>

shows "true", "false", "-1", "false", in Gecko, Presto, and WebKit.

IE does something else, but it does not enumerate the 0 on the form....

Futhermore, this testcase:

  <form id="f"><input id="i"></form>
  <pre><script>
    var i = document.getElementById("i");
    var f = document.getElementById("f");

    f.i;
    i.id = "j";
    f.j;
    i.id = "i";
    f.i;
    var names = Object.getOwnPropertyNames(f);
    document.writeln(names);
  </script>

shows that the spec and IE disagree on whether "j" is visible (perhaps IE simply has no past names map?).

I believe the spec requires "j i" in that second testcase, which is.... quite annoying to implement.

I would like to propose that we simply not enumerate these named propertied on <form>.  We just need a way to say that; right now WebIDL doesn't allow us to.

For now, we'll be keeping our current behavior in Gecko.
Comment 2 Ian 'Hixie' Hickson 2013-06-10 22:44:51 UTC
Should I assign this to heycam, awaiting some WebIDL magic I can hook into?
Comment 3 Boris Zbarsky 2013-06-11 01:27:52 UTC
If we want to make this change, then yes.  You don't have a way to spec this right now....
Comment 4 Boris Zbarsky 2013-06-17 14:22:07 UTC
It might be good to add a warning in the spec for now so people don't waste time trying to implement this, though.
Comment 5 Ian 'Hixie' Hickson 2013-06-17 22:49:36 UTC
Not sure what warning I'd put where, exactly.

Reassigning to heycam for now.

heycam, please reassign back to me if I have things to change once this is done.

bz, please e-mail me directly if you would like a warning added to the spec beyond the current bug marking.
Comment 6 Boris Zbarsky 2013-06-18 02:11:10 UTC
> Not sure what warning I'd put where, exactly.

To the part about the set of supported names on form, about how the enumeration behavior this implies is not necessarily all that final...

Note that there is near-zero interop here right now: WebKit only enumerates indices, IE only enumerates names/ids, afaict, Gecko only enumerates names for things that have them, indices for the rest.  Until we switch to WebIDL for form, at which point we'll go with the WebKit behavior for now.
Comment 7 Boris Zbarsky 2013-07-09 03:36:54 UTC
One other note.  If you look carefully at the testcase and the results, Object.getOwnPropertyNames is _also_ not showing "i".  I propose to keep this behavior, insane as it is....  I have no idea how to spec it, though, in ES terms.
Comment 8 Mark S. Miller 2013-07-09 03:58:18 UTC
Having these properties not be enumerable, in the ES sense of "not enumerable", would be fine and probably expected. 

But having them not be enumerated by getOwnPropertyNames is perverse, unexpected, hostile to the JavaScript programmer, likely in violation of the ES5 spec, and not possibly needed for compatibility with any pre-ES5 legacy, since getOwnPropertyNames started in ES5. 

getOwnPropertyNames must enumerate *all* own properties, whether enumerable or not.
Comment 9 Boris Zbarsky 2013-07-09 04:22:25 UTC
Mark, at the same time implementations already don't return them from getOwnPropertyNames.  Furthermore, defining getOwnPropertyNames to return them requires an ordering to be put on the property names, and the current ordering defined in the specification is ... somewhat insane to actually implement. 

Futhermore, last I checked it's not hard to create objects in ES6 that have that behavior for getOwnPropertyNames: just have a direct proxy return [] from the relevant trap.

I think we can all agree that objects like this one (with random named properties that come and go) are perverse, unexpected, hostile to the JavaScript programmer, and likely in violation of the ES5 spec.  The only reason they exist is backwards-compat, and I would argue that we should define them in the simplest possible way that's needed for said backwards compat and stop wasting time on them...
Comment 10 Mark S. Miller 2013-07-09 04:31:52 UTC
Backwards compat with what? getOwnPropertyNames didn't even exist prior to ES5. And your own analysis says that browsers differ on this odd case anyway. Just because some browsers shipped a bug, let's not immediately turn around and legislate that bug as a standard before the cement has dried, especially when this bug contradicts an existing standard.

Are the objects in question *necessarily* non-extensible? In other words, must they refuse Object.freeze, .seal, and .preventExtensions? After they are made non-extensible, if they claim (via getOwnPropertyNames) not to have an own property, they must not after (e.g., by getOwnPropertyDescriptor) claim to have that property, or they would violate the non-extensibility contract.
Comment 11 Boris Zbarsky 2013-07-09 07:36:17 UTC
> Backwards compat with what?

The main backwards compat requirement is that form.foo needs to return certain things for certain values of foo.

There is probably a less important requirement that the expression |"foo" in form| test true for certain values of "foo".

There is no backwards compat requirement on the behavior of getOwnPropertyNames, obviously, since nothing on the Web uses it, to a first approximation.

> Just because some browsers shipped a bug

More precisely, all those browsers implement these objects as something proxy-like and did the simplest possible implementation they could that satisfied the backwards compat requirements I outline above.  The simplest implementation is to return [] from getOwnPropertyNames (though in actuality it seems like they return [0, 1, 2, ...., length-1]).

> In other words, must they refuse Object.freeze, .seal, and .preventExtensions?

There is no explicit mention in the WebIDL spec of them behaving in interesting ways with those.  WebIDL just defines the behavior of [[GetOwnProperty]] and [[DefineOwnProperty]] on the objects and then things fall out from that (e.g. Object.freeze is described mostly in terms of those internal methods).

> After they are made non-extensible, if they claim (via getOwnPropertyNames)
> not to have an own property, they must not after (e.g., by
> getOwnPropertyDescriptor) claim to have
> that property, or they would violate the non-extensibility contract.

I strongly suspect that actual browser implementations do all sorts of weird stuff here.  And as far as I can tell, so can direct proxies...
Comment 12 Boris Zbarsky 2013-07-09 07:38:33 UTC
Oh, and my point is, it's not clear to me that doing anything other than the simplest possible implementation of these objects is worth the time, pain, effort, and performance impact it would seemingly entail...

If people come up with a proposal that behaves sanely and does _not_ entail those problems, so much the better, of course.
Comment 13 Mark S. Miller 2013-07-09 14:02:09 UTC
(In reply to comment #12)
> Oh, and my point is, it's not clear to me that doing anything other than the
> simplest possible implementation of these objects is worth the time, pain,
> effort, and performance impact it would seemingly entail...
> 
> If people come up with a proposal that behaves sanely and does _not_ entail
> those problems, so much the better, of course.

Hi Boris, thanks, I understand better now. Given all this, the proposal would simply be to have getOwnPropertyNames return a list of all the own property names. After all, that is what it is for and what it means. The operation was not added on JavaScript on a whim, so it shouldn't be broken lightly. And you agree that this would not create any compat issues.

The notion of "simplest" should be judged regarding the overall system, not of the browser implementation taken by itself. Breaking expectations about fundamental operations forces expensive workarounds on our users. For example, https://bugzilla.mozilla.org/show_bug.cgi prevented SpiderMonkey from being considered SES-safe for a very long time. The workaround at https://code.google.com/p/google-caja/source/browse/trunk/src/com/google/caja/ses/repairES5.js#3127 was only possible once we knew the worst case list of possible missing properties. It doesn't sound like even this workaround would be possible in this case.

There are a lot more users than implementors, and the complexity of implementing getOwnProperties correctly is not unreasonable.
Comment 14 Mark S. Miller 2013-07-09 14:03:25 UTC
(In reply to comment #13)
> For
> example, https://bugzilla.mozilla.org/show_bug.cgi prevented SpiderMonkey

Should be https://bugzilla.mozilla.org/show_bug.cgi?id=724768


> from being considered SES-safe for a very long time. The workaround at
> https://code.google.com/p/google-caja/source/browse/trunk/src/com/google/
> caja/ses/repairES5.js#3127 was only possible once we knew the worst case
> list of possible missing properties. It doesn't sound like even this
> workaround would be possible in this case.
> 
> There are a lot more users than implementors, and the complexity of
> implementing getOwnProperties correctly is not unreasonable.
Comment 15 Boris Zbarsky 2013-07-09 15:01:58 UTC
> the proposal would simply be to have getOwnPropertyNames return a list of all
> the own property names.

That's not a problem.  The problem is the ordering.

> and the complexity of implementing getOwnProperties correctly is not
> unreasonable.

The complexity of implementing it for this object as currently defined in the spec is unreasonable.
Comment 16 Mark S. Miller 2013-07-09 15:21:44 UTC
(In reply to comment #15)
> > the proposal would simply be to have getOwnPropertyNames return a list of all
> > the own property names.
> 
> That's not a problem.  The problem is the ordering.

Could you please expand on this? IIRC, the ES specs do not specify any particular order for this.


> 
> > and the complexity of implementing getOwnProperties correctly is not
> > unreasonable.
> 
> The complexity of implementing it for this object as currently defined in
> the spec is unreasonable.

The key phrase here seems to be "as currently defined in the spec". Presumably the w3 spec? Perhaps the w3 spec should be changed to not deter conformance with the ES spec? Again, please expand.
Comment 17 Boris Zbarsky 2013-07-09 15:34:55 UTC
> the ES specs do not specify any particular order for this.

One of the goals of the current web specs is to not have undefined behavior.  That means they do in fact specify an order here.

Again, if the spec changes such that it's sane to implement, it'll perhaps get implemented (I obviously can't speak for WebKit or Blink, but we would implement in Gecko).  If it does not, it probably won't be (as now).
Comment 18 Mark S. Miller 2013-07-09 17:16:04 UTC
(In reply to comment #17)
> > the ES specs do not specify any particular order for this.
> 
> One of the goals of the current web specs is to not have undefined behavior.
> That means they do in fact specify an order here.

Other things being equal, removing undefined behavior from specs is a great thing. I've fought for this many times in tc39 as well. However, breaking a feature because
1) the feature itself could be provided cheaply, in a way that conforms to the es spec, at the price of non-deterministic order.
2) the defined order, which no one really cares about for this feature, would for some reason be expensive.

Btw, why would a deterministic order for this be expensive? I don't get it.


> Again, if the spec changes such that it's sane to implement, it'll perhaps
> get implemented (I obviously can't speak for WebKit or Blink, but we would
> implement in Gecko).  If it does not, it probably won't be (as now).

So how about we change the spec to "have getOwnPropertyNames return a list of the own property names"? What is the right forum to get this spec changed?
Comment 19 Boris Zbarsky 2013-07-09 17:19:27 UTC
> Btw, why would a deterministic order for this be expensive? I don't get it.

The particular order defined in the spec is expensive.  Please do read the spec; it's linked in comment 0.

> So how about we change the spec to "have getOwnPropertyNames return a list of
> the own property names"? What is the right forum to get this spec changed?

This needs changes to both WebIDL and HTML, as things stand.
Comment 20 Mark S. Miller 2013-07-09 18:40:07 UTC
(In reply to comment #19)
> > Btw, why would a deterministic order for this be expensive? I don't get it.
> 
> The particular order defined in the spec is expensive.  Please do read the
> spec; it's linked in comment 0.

Nowhere on any of the pages linked from comment 0 is "getOwnPropertyNames" mentioned. What is the relevant part of what spec?

> 
> > So how about we change the spec to "have getOwnPropertyNames return a list of
> > the own property names"? What is the right forum to get this spec changed?
> 
> This needs changes to both WebIDL and HTML, as things stand.

Let's do it.
Comment 21 Boris Zbarsky 2013-07-09 19:14:20 UTC
> What is the relevant part of what spec?

The part where it defines "supported property names".

That said, WebIDL doesn't actually define anything about how getOwnPropertyNames interacts with the supported property names.  It does define the interaction with enumeration at http://dev.w3.org/2006/webapi/WebIDL/#property-enumeration
Comment 22 Mark S. Miller 2013-07-09 19:56:50 UTC
(In reply to comment #21)
> > What is the relevant part of what spec?
> 
> The part where it defines "supported property names".
> 
> That said, WebIDL doesn't actually define anything about how
> getOwnPropertyNames interacts with the supported property names.  It does
> define the interaction with enumeration at
> http://dev.w3.org/2006/webapi/WebIDL/#property-enumeration

That says "[...] Finally, any enumerable own properties or properties from the object’s prototype chain are then enumerated, in no defined order."

So even if we did take this text as applying to getOwnPropertyNames, wouldn't this imply that we can have getOwnPropertyNames return the list of own properties in question "in no defined order"?

And even if it would not imply this, as you point out, it is not talking about getOwnPropertyNames anyway.
Comment 23 Boris Zbarsky 2013-07-09 20:02:56 UTC
In that case, nothing at all defines the behavior of getOwnPropertyNames on these objects right now.  Defining that would be good.  ;)
Comment 24 Ian 'Hixie' Hickson 2013-07-09 20:34:00 UTC
(In reply to comment #6)
> > Not sure what warning I'd put where, exactly.
> 
> To the part about the set of supported names on form, about how the
> enumeration behavior this implies is not necessarily all that final...

Sorry, I missed that, since the bug wasn't assigned to me.

I'll add something to the HTML spec saying that the names shouldn't be enumerable for now. When WebIDL gives me a more formal way to do this, I'll update this (and navigator.plugins, etc) to do it that way.

As far as the order goes, I don't mind what it is, if you want a different order just file a bug for it. As you say, we just need _an_ order.
Comment 25 Ian 'Hixie' Hickson 2013-07-09 20:40:22 UTC
Checked in as WHATWG revision r8041.
Check-in comment: Don't make form names enumerable.
http://html5.org/tools/web-apps-tracker?from=8040&to=8041
Comment 26 Mark S. Miller 2013-07-09 20:46:49 UTC
(In reply to comment #24)
> (In reply to comment #6)
> > > Not sure what warning I'd put where, exactly.
> > 
> > To the part about the set of supported names on form, about how the
> > enumeration behavior this implies is not necessarily all that final...
> 
> Sorry, I missed that, since the bug wasn't assigned to me.
> 
> I'll add something to the HTML spec saying that the names shouldn't be
> enumerable for now. When WebIDL gives me a more formal way to do this, I'll
> update this (and navigator.plugins, etc) to do it that way.
> 
> As far as the order goes, I don't mind what it is, if you want a different
> order just file a bug for it. As you say, we just need _an_ order.

Hi Ian, because in this thread we've discussed both whether certain own properties are "enumerable" in the ES sense (enumerated by for/in loops and Object.keys) and whether certain own properties are enumerated by getOwnProperties -- which should enumerate all own properties, whether enumerable or not. I just want to be sure what you're referring to.

There is no problem with these properties being non-enumerable. And I think Boris and I just established that there's neither a compat nor a spec conformance conflict with have all own properties be enumerated by getOwnPropertyNames. And there is an ES spec conformance issue with having these not be enumerated by getOwnPropertyNames.

As for whether we need "_an_ order", I would certainly prefer one and do not understand why this would be expensive. But the WebIDL spec doesn't seem to demand an order.
Comment 27 Boris Zbarsky 2013-07-09 20:51:52 UTC
> And there is an ES spec conformance issue with having these not be enumerated
> by getOwnPropertyNames.

That's actually not obvious to me, given the current state of ES specs and how WebIDL defines these properties...
Comment 28 Ian 'Hixie' Hickson 2013-07-09 20:52:27 UTC
Checked in as WHATWG revision r8041.
Check-in comment: Don't make form names enumerable.
http://html5.org/tools/web-apps-tracker?from=8040&to=8041
Comment 29 Boris Zbarsky 2013-07-09 20:53:48 UTC
And to be clear, I believe that's a bug in the ES+WebIDL combination, because I do think in an ideal world getOwnPropertyNames will return these properties.  There's just nothing in the specs as they are that requires it, which is bad.
Comment 30 Ian 'Hixie' Hickson 2013-07-09 20:55:32 UTC
(In reply to comment #26)
> 
> Hi Ian, because in this thread we've discussed both whether certain own
> properties are "enumerable" in the ES sense (enumerated by for/in loops and
> Object.keys) and whether certain own properties are enumerated by
> getOwnProperties -- which should enumerate all own properties, whether
> enumerable or not. I just want to be sure what you're referring to.

For HTML, I'm targeting WebIDL, not ES (JS). WebIDL then defines whatever this means for JS. The text I just added to HTML is essentially meaningless if you look too closely, but is supposed to be a stop-gap until heycam fixes this bug. As far as getOwnProperties and getOwnPropertyNames, if WebIDL doesn't define how those work for host objects, please file a separate bug.
Comment 31 Boris Zbarsky 2013-07-09 21:24:35 UTC
> There is no explicit mention in the WebIDL spec of them behaving in interesting > ways with those.

Just to be clear, this was wrong.  seal/freeze/preventExtensions throw on things with named or indexed props.
Comment 32 Mark S. Miller 2013-07-09 23:08:27 UTC
(In reply to comment #31)
> > There is no explicit mention in the WebIDL spec of them behaving in interesting > ways with those.
> 
> Just to be clear, this was wrong.  seal/freeze/preventExtensions throw on
> things with named or indexed props.

In that case, you are correct that ES allows the object to claim not to have own properties (e.g., via getOwnProperties returning an empty list) and then later claim to have properties (e.g., via getOwnPropertyDescriptor).

Nevertheless, we all seem to agree at this point that this behavior is programmer hostile and there's nothing that prevents us from fixing it. From Ian's comments, only WebIDL needs to be fixed -- the HTML spec is neutral on the matter.
Comment 33 Tom Van Cutsem 2013-07-10 20:05:53 UTC
Mark asked me to post the following, for the record, as evidence that the JS getOwnPropertyNames operation does come with a number of invariants defined in ES6:

Looking at JavaScript proxies, which are the tool one would use to self-host this in JavaScript, even a proxy cannot claim to be non-extensible and claim (via getOwnPropertyNames) to have no own properties, but later claim by other means (e.g. getOwnPropertyDescriptor) to have own properties.

In other words, the result returned by getOwnPropertyNames should be consistent with the result returned by e.g. getOwnPropertyDescriptor.

Test case:

var target = Object.preventExtensions({});
var proxy = new Proxy(target, {
 getOwnPropertyDescriptor: function(target, name) {
   if (name === 'foo') {
     return {value:42};
   }
 }
});

Object.isExtensible(proxy) // false
Object.getOwnPropertyNames(proxy) // []
Object.getOwnPropertyDescriptor(proxy,'foo') // TypeError: cannot report a new own property 'foo' on a non-extensible object

IOW, if getOwnPropertyNames returns the empty array (and the object in question is non-extensible), then that object should also not report the existence of own properties through other traps.
Comment 34 Ian 'Hixie' Hickson 2014-04-11 18:59:35 UTC
(I think this got fixed in bug 22600.)
Comment 35 Boris Zbarsky 2014-04-11 19:35:08 UTC
Yes, looks good.
Comment 36 Anne 2016-03-06 07:04:06 UTC
There is a way for this now and the HTML Standard uses it.
Comment 37 Boris Zbarsky 2016-08-30 20:27:12 UTC
I've spun off the "spec-defined ordering is slow" bit to https://github.com/whatwg/html/issues/1731