Re: typeof document.all

On Oct 12, 2009, at 4:46 PM, Maciej Stachowiak wrote:

> I have mixed feelings about these particular details being specified  
> in Web IDL. Just stating facts in this case.

Me too (on the mixed feelings; will try to state facts as well ;-).


> One relevant question is: will future programs care about the  
> results of operations such as hasOwnProperty() or  
> getOwnPropertyDescriptor()? Will it make things harder for them if  
> the results are not consistent cross-browser?

If they are messing with document.all in ES5 code I wish them harm  
(true fact! :-|).

Seriously, while there might be property-name-generic programming  
going on, any new code touching document.all is in trouble already.


> It does seem that current code does not depend significantly on what  
> is an own property and what is a prototype property (possibly a  
> getter). But it seems to me that code wishing to extensively  
> prototype-hack the DOM, or build a facade on top of the DOM, could  
> benefit from these details being consistent.

For document.all, which is also falsy (not just in  
ToBoolean(document.all) -> false as I thought, but also in being ==  
null and == undefined as you wrote -- and === as well I presume),  
special care will be needed. You can't treat this property's value  
like any saner object, even if you can assume it is "own" in document  
or HTMLDocument.prototype. Is its property-home really that important  
in light of its unusual value-semantics?


> In the past, we have learned that it's required to have global  
> properties of the Window object with names like "HTMLInputElement"  
> and properties named "prototype" which hold the prototype to be used  
> for HTML input element instances, even though this was not spelled  
> out by former specs.

Isn't HTMLInputElement a replaceable property of the window object?


> This leads me to assume by default that any browser differences on  
> this are likely to create problems at some point (and in particular,  
> as the bigger differences are smoothed out, smaller differences may  
> start to matter more).

This argument applies to every DOM difference, and since bug for bug  
compatibility is impossible its absurd reduction is a single source  
base for all browsers. But since that's not going to happen, we have  
to draw lines well short of that mark.


> On the other hand, there are many potential performance tradeoffs to  
> how exactly DOM attributes get implemented. This concern would be  
> lessened if we could show that it's possible to use a variety of  
> implementation strategies while getting consistent output from  
> hasOwnProperty() and getOwnPropertyDescriptor().

We can and do use prototype properties with special attribute  
combinations that make them appear per-instance. This is good for  
shared non-configurable native-code-implemented getters bound in  
prototypes, where the referenced property seems to be "own" when  
tested on an object delegating to that prototype for the getter's id.

ES5 discussion of Object.getPrototypeOf led us to conclude that host  
objects can hide prototypes if they wish to, so long as they follow  
certain rules in ES5 Chapter 9.

So it seems to me we could more easily agree on hasOwnProperty and  
getOwnPropertyDescriptor than revise our document.all emulation, and  
allay some of your concern about metaprogramming the DOM breaking on  
divergent browser undetected document.all emulations.

But the long, almost Germanic string of nouns and adjectives in that  
last sentence makes me want to repeat that metaprogramming and  
document.all do not mix. Indeed if document.all is emulated in HTML5  
only in quirks mode, I doubt that this hypothetical problem is one we  
should spend any more time on.


>> I realize I'm asking about leaving things unspecified. But the  
>> plain fact is browsers don't agree today, so this can be  
>> considered. Lots of specs (especially programming languages not  
>> interoperating across the web, e.g. C and Scheme) are under- 
>> specified intentionally to allow for diverse implementations and  
>> optimizations.
>>
>> I didn't want to assume that document.all had to be fully  
>> specified, or to assume that, just because WebIDL does specify  
>> prototypes and "own" status, that it is not forcing over- 
>> specification in this case.
>
> Well, there's the general question of whether Web IDL should specify  
> things to this level of detail for normal properties (which is a Web  
> IDL question), and then if it does, the question of wether HTML5  
> should be more loose for document.all specifically (perhaps by  
> defining it completely outside IDL). I don't think document.all has  
> a special need to be more loosely specified in this regard than  
> other DOM attributes.

I do, if it is enough for real-world interop and we can fry bigger  
fishes.


>>>> 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.
>>
>> Ok, but doing what you ask here doesn't address my point 1.
>
> Maybe I misunderstood, but it sounded like your point 1 was really  
> about implementation mechanics, not just a purity issue. I think I  
> said above that the implementation mechanics were not that hard, and  
> in text you snipped, I gave some of the details of our  
> implementation. I don't really think either approach has full ES  
> spec purity. Implementation difficulty is a more significant concern.

Agreed, but we'll have to deal with TC39 too. I'm sure it was "not  
that hard" to do what you did; that phrase goes for what we did in  
2004 with detecting vs. non-detecting bytecode contexts. We'd need to  
scope the work.

Separately, someone has to come up with a proposal for ES-Harmony if  
we want standards conformance.


>> We classify bytecode combinations implementing if, ?:, switch,  
>> {===,!==,==,!=} x {null,undefined} (null or undefined only on the  
>> right of the operator, !, typeof, ||, &&, assignment, and property  
>> initialization as "detecting" and suppress lazy creation of  
>> document.all.
>>
>> (Testing showed that assignment to variables and initialisers led  
>> to later detection, so we imputed detection to the = operator and  
>> the property initialiser in d = {all: document.all}.)
>>
>> All other bytecode combinations are non-detecting and force lazy  
>> creation of document.all.
>
> Does anything different happen for the "detecting" bytecodes after  
> lazy creation has occurred (didn't seem to in my testing)?

Lazy creation puts the property in the prototype chain, using a  
special object whose job is to hold the document.all collection and to  
continue hiding it if it is used again in a detecting fashion. Believe  
it or not, this was real-world test-driven development. I can dig up  
the CVS references to bugzilla bugs from 2004 when I have more time.


> Do all looping constructs use different bytecodes in all cases?

We don't generally treat loops as detecting, although this may be  
unintended due to bytecode selection changes since 2004. But again it  
has not generated bugzilla signal, and I've never seen a loop testing  
document.all (which would be silly, but that never stopped the Web).  
It has not been a problem.


> What about the comma operator? I noticed in testing that "detecting"  
> taint seems to propagate through comma.

Testcase? You may be seeing dead code elimination instead of what you  
think you see.


> Also through redundant grouping parentheses.

Parentheses around expressions are not part of the abstract syntax.


> (Also, null and undefined equality comparisons seem to be special in  
> either order, i.e. (null == document.all) is true, as is  
> (document.all == null).)

Right, I should have remembered -- that works simply by virtue of the  
opcode sequence that resolves document.all being followed directly by  
the branching opcode, which is classified as detecting.


> Does the comparison have to be to constant undefined or null? It  
> seems that comparing document.all for equality to "void 0" or an  
> undefined local variable gives false.

That's right, the comments in the code talk about this not being a  
problem in practice.

People who bother to detect document.all usually just test its  
falsiness. If they pedantically compare it to something, it's == null  
or undefined, or maybe === undefined (to pass JSLint). We never  
discovered pages needing more.


> What is it that makes (document.all == document.all) false? If I  
> cheat and store document.all twice using functions for indirection,  
> the stored values compare ==.

See above about "... and to continue hiding it ..." in conjunction  
with the later rule about "... being followed directly by the  
branching opcode ....."

This is not something I would standardize, as I wrote on public-script- 
coord, in fact it's an unintended consequence. But it has never caused  
reported trouble (we have good bug triage and site analysis via the  
Mozilla community, in order to generate a technology evangelism bug or  
a bug against Gecko or SpiderMonkey). We could fix it, for sure, and  
may, whether that means a falsy object or a spot-fix.

/be

Received on Tuesday, 13 October 2009 00:41:29 UTC