W3C home > Mailing lists > Public > public-html@w3.org > October 2009

Re: typeof document.all

From: Maciej Stachowiak <mjs@apple.com>
Date: Mon, 12 Oct 2009 13:44:02 -0700
Cc: HTML WG <public-html@w3.org>
Message-id: <2EF99ADE-6598-428E-B309-4C49DAD7BE0E@apple.com>
To: Brendan Eich <brendan@mozilla.org>

On Oct 12, 2009, at 12:50 PM, Brendan Eich wrote:

> On Oct 12, 2009, at 12:22 PM, Maciej Stachowiak wrote:
>
>> On Oct 12, 2009, at 11:45 AM, Brendan Eich wrote:
>>
>>> On Tue, 14 Jul 2009 07:22:24 +0000 (UTC), Ian Hickson wrote:
>>> > On Mon, 13 Jul 2009, Boris Zbarsky wrote:
>>> > >
>>> > > In Gecko, document.all is in fact on the prototype of the  
>>> document.
>>> > > More precisely, trying to use document.all (as opposed to just  
>>> test for
>>> > > it) changes the prototype chain of the document such that its  
>>> prototype
>>> > > has the "all" property.  Try this in your favorite Gecko-based  
>>> browser:
>>> > >
>>> > > <script>
>>> > >   var oldProto = document.__proto__;
>>> > >   alert(oldProto.hasOwnProperty("all"));
>>> > >   document.all.length;
>>> > >   alert(oldProto.hasOwnProperty("all"));
>>> > >   alert(document.__proto__.hasOwnProperty("all"));
>>> > >   alert(document.__proto__ == oldProto);
>>> > >   alert(document.__proto__.__proto__ == oldProto);
>>> > > </script>
>>> > >
>>> > > You should be seeing alerts with the following values: false,  
>>> false,
>>> > > true, false, true
>>> >
>>> > The "adding 'all' after it's used" behaviour doesn't match other  
>>> browsers
>>> > as far as I can tell.
>>>
>>> The prototype chain is not directly observable according to the ES  
>>> specs, even
>>> with ES5's Object.getPrototypeOf (host objects can lie).
>>>
>>> Reifying a property on first use is a common technique, an  
>>> optimization (not
>>> observable, so conforming).
>>
>> In this case it's observable - the code cite above observes it. I'm  
>> not sure it matters in practice, but it is observable.
>
> No, I'm talking about lazy creation here. Not observable.
>
> What bz shows is using __proto__, of course he's observing stuff,  
> but that's not what I was talking about. Sorry if I got pedantic  
> there, I was trying to separate lazy creation from the non-existence  
> vs. exists-with-undefined-value issue.
>
>
>>> For document.all, the interoperation problem (if it
>>> is a problem) is that Mozilla reifies depending on context. WebKit  
>>> reifies
>>> (eagerly or lazily, doensn't matter) independent of context, and  
>>> with a falsy
>>> object value.
>>>
>>> Confusion arises because undefined is a falsy value, which  
>>> compares == itself
>>> and null as well as converts to false in boolean contexts. But a  
>>> property that
>>> has value undefined is observably different from no property, even  
>>> if one goes
>>> only by the ES specs.
>>
>> Specifically, the in operator and the hasOwnProperty() method will  
>> give different results.
>
> You must be talking about the other issue I failed to mention: where  
> on the prototype chain, if not directly on the referenced object,  
> the existent property (lazily created or not) lives.

No, I'm just explicitly stating the differences from a property that  
has value undefined from no property, which you mentioned.

>
> Good point, this is another potential interoperation issue, but only  
> if we care about prototype chain structure as reflected by __proto__  
> or ES5's Object.getPrototypeOf, and provided the host object  
> implementation doesn't lie to conceal intermediate hidden prototypes  
> and possibly thereby conform.
>
>
>> I think using the object in a with() statement will also give  
>> different results.
>
> There should be no 'with' connection. Do you have a testcase?

A property with value undefined will certainly cause different  
behavior when the object is used with 'with' than a missing property.  
I did not mean to imply this had any relation to document.all.

>
>
>>> If the prototype chain is not observable (by the book) why do the  
>>> IDL
>>> definitions matter?
>>
>> Web IDL defines which aspects of an IDL interface are prototype  
>> properties and which are own properties. The prototype chain is  
>> observable with nonstandard extensions, but also in part via  
>> prototype properties present on DOM (pseudo-)constructors.
>
> Right, of course -- but is 'all' supposed to be direct (or appear to  
> be that way), and not on any visible prototype? Or must it (by  
> hasOwnProperty) be a direct property of HTMLDocument.prototype?

According to Web IDL as currently written, I believe it should be an  
"own" property.

>
> This seems unimportant for interoperation based on what browsers  
> actually do so far. Must it be specified? If it must, what about  
> making it appear to be a direct ("own" in ES terms) property of  
> document? IIRC IE does that.

I think Web IDL makes all non-method properties be "own" properties  
currently, so I think that is what is specified.

>
>
>>> The issue is falsy object value. Must this be normative?
>>
>> Some way of making document.all undetectable should be normative.  
>> We can discuss the pros and cons of the Gecko and WebKit solutions  
>> to this. It might also be possible to specify things in a way that  
>> both the Gecko and WebKit behaviors end up conforming, for example  
>> by listing a series of if tests that must pass or fail, thus  
>> leaving some edge cases unspecified.
>
> I'm loath to volunteer Mozilla changing to match WebKit, unsinking  
> sunk costs and taking risks, but we might. Two issues stand in our  
> way:
>
> 1. The ES-purity point of ToBoolean(Object) -> true manded by all  
> ECMA-262 editions without host object exception, which is reflected  
> in our implementation, so it's not just a purity issue for us (even  
> if I'm not a purist about conformance).

We had to make some minor changes to our JavaScript implementation to  
support this. I think the changes to support the Mozilla behavior  
would be quite a bit more extensive. The code that implements property  
accesses on Document (or any host object property access) has no way  
of knowing if the value will be used in a boolean context, as the  
rvalue of an assignment, as part of an object initializer, or whatever  
other cases behave unusually in Gecko. I think we considered doing  
something Gecko-like back in the day and decided it was more  
complicated.

It would be useful if someone could explain the Gecko behavior in  
detail. I couldn't figure out exactly what it does either by testing  
or by reading the patch that implemented the behavior. Then we could  
consider technical pros and cons of both behaviors.

WebKit's behavior:
- ToBoolean conversions on the all collection object return false
- The all collection object compares equal to null (for purposes of  
==, !=).
- The all collection object compares equal to undefined (for purposes  
of ==, !=).
- typeof returns "undefined" for the all collection

I think this is equivalent to what HTML5 currently requires.

These behaviors are implemented by having a "masquerades as undefined"  
bit in the struct of JS type info for the HTMLAllCollection class, and  
checking it in the right places. The performance cost is negligible.

>
> 2. The quirks mode conditioning of our undetected document.all  
> emulation. We do not want document.all in standards mode. You agreed  
> in principle on public-script-coord recently. Who else needs to  
> agree for HTML5 to spec this as quirks-mode only (I may be showing  
> my ignorance by asking, if HTML5 has no quirks-mode at all)?

I think we could plausibly make it quirks-mode-only. I'd like to hear  
input from others. HTML5 most definitely has quirks mode and specifies  
what triggers quirks vs. standards as well as specifying some specific  
behavior differences.

Regards,
Maciej
Received on Monday, 12 October 2009 20:44:38 UTC

This archive was generated by hypermail 2.3.1 : Monday, 29 September 2014 09:39:09 UTC