Should isHostMethod be added to the FAQ?

T

Thomas 'PointedEars' Lahn

David said:
Thomas said:
David said:
Thomas 'PointedEars' Lahn wrote:
David Mark wrote:
kangax wrote:
Thomas 'PointedEars' Lahn wrote:
kangax wrote:
[...]
Host objects should not be passed to "isArray" functions of any
flavor. Most designs should not need a such a function anyway.
From what I remember (per Richard's observations), it was
*cross-window issue*, not cross-frame one.
But I thought the problem were different global objects, each with its own
Array property.
Yes, but AUIU only Array objects created in child windows have "Object"
[[Class]] values (rather than "Array" ones). This is what "confuses"
Miller device.
I thought it was frames as well. Regardless, as it is not 100%, you
must fall back to "duck typing" for "Object" classes. This is why
such functions should be designed out of the system.
How do you propose to do that here? It needs to be tested whether the
argument is an Array object reference or not.
Chuck the whole thing and redo anything that initially indicated a
need for it.
Now that's a pretty useless reply. You owe me at least 15 seconds of my time.

Look again. It's the only practical answer to your question.

It isn't even remotely practical! One needs to differentiate between
testing foo.bar.baz, or foo.bar and foo.baz etc. without much fuss about
objects and properties on call. AFAICS only Arrays can provide that in
these languages.


PointedEars
 
D

David Mark

David said:
Thomas said:
David Mark wrote:
Thomas 'PointedEars' Lahn wrote:
David Mark wrote:
Thomas 'PointedEars' Lahn wrote:
RobG wrote:
<FAQENTRY>
There has been frequent mention of the legendary "isHostMethod"
function in this group over the last 18 months or so in conjunction
with statements that "boolean type conversion is out" for testinghost
method availability.  While that may be so, trying to find the elusive
method in all the noise is pretty difficult.
I discovered this version posted by Thomas in February 2008[1]:
My JSdoc™ says:
 * @author
 *   (C) 2003-2009  Thomas Lahn &lt;[email protected]&gt;
Oh mercy.  You wrote that comment.
Because it's true.
Sort of.
I won't debate that the version of 2003/2004 is less evolved than whatI
have now (that would be pretty bad performance); but please, credit where
credit is due:
<http://bytes.com/groups/javascript/151754-when-window-location-url-ex....>
(Google doesn't seem to have it anymore, or the search function is borken..)
If you mean isMethodType, then yes.

You really can search for "function isMethod" there if you want.  Trustme.

I believe you, but if it accepts references to host objects for the
first argument, I'm confused by your prior position on isHostMethod.
You fought tooth and nail when I proposed isHostMethod, which is just a
slight improvement.

Come on!  I debated whether it would be useful in general to have a method
that requires another test before it can be used.  And in part I still do,
hence my considering to allow identifier/member expression string evaluation
back (if via flag) after all.  (I have already allowed a single argument for
isMethod() so that e.g. arguments of other methods could be tested without
isMethodType() and the "unknown" expression [the base object of the
reference would be the context's Variable Object, which is unavailable per
reference except global].  Turned out that you can't pass "unknown"s anyway.)

You can't do much of anything with unknown types (except call some of
them.)
What are you talking about?  [snip irrelevance]

<news:[email protected]>

If that's from today, I read it (and explained its relative relevance
a minute ago.)
I don't follow.

You snipped too hastily apparently. You said something about not
knowing the difference between testing for "unknown" or not. Big
difference there (safe vs. explosive.)
It is going to be jsx.object.areMethods (and jsx.object.areHostMethods
should it prove to be needed), so there is only a remote possibility for
confusion.

Sounds good. My areHostMethods just allows for n string arguments
after the host object reference (e.g. gEBI, gEBTN, etc.) It's handy
when an app needs to check several methods of the same host object.
 
D

David Mark

David said:
Thomas said:
David Mark wrote:
Thomas 'PointedEars' Lahn wrote:
David Mark wrote:
kangax wrote:
Thomas 'PointedEars' Lahn wrote:
kangax wrote:
[...]
Host objects should not be passed to "isArray" functions of any
flavor.  Most designs should not need a such a function anyway.
From what I remember (per Richard's observations), it was
*cross-window issue*, not cross-frame one.
But I thought the problem were different global objects, each with its own
Array property.
Yes, but AUIU only Array objects created in child windows have "Object"
[[Class]] values (rather than "Array" ones). This is what "confuses"
Miller device.
I thought it was frames as well.  Regardless, as it is not 100%, you
must fall back to "duck typing" for "Object" classes.  This is why
such functions should be designed out of the system.
How do you propose to do that here?  It needs to be tested whetherthe
argument is an Array object reference or not.
Chuck the whole thing and redo anything that initially indicated a
need for it.
Now that's a pretty useless reply.  You owe me at least 15 seconds of my time.
Look again.  It's the only practical answer to your question.

It isn't even remotely practical!

Strange. I've never once needed an isArray method and I've written
damned near everything you can imagine for browsers.
One needs to differentiate between
testing foo.bar.baz, or foo.bar and foo.baz etc. without much fuss about
objects and properties on call.  AFAICS only Arrays can provide that in
these languages.

I didn't say there was anything wrong with arrays. Just design your
app so that you do not need to test for them explicitly. In other
words, if an "overloaded" function takes a string or an array
argument, test for the string (else assume an array.)
 
T

Thomas 'PointedEars' Lahn

David said:
Thomas said:
David said:
Thomas 'PointedEars' Lahn wrote:
David Mark wrote:
Thomas 'PointedEars' Lahn wrote:
David Mark wrote:
Thomas 'PointedEars' Lahn wrote:
RobG wrote:
<FAQENTRY>
There has been frequent mention of the legendary "isHostMethod"
function in this group over the last 18 months or so in conjunction
with statements that "boolean type conversion is out" for testing host
method availability. While that may be so, trying to find the elusive
method in all the noise is pretty difficult.
I discovered this version posted by Thomas in February 2008[1]:
My JSdocâ„¢ says:
* @author
* (C) 2003-2009 Thomas Lahn &lt;[email protected]&gt;
Oh mercy. You wrote that comment.
Because it's true.
Sort of.
I won't debate that the version of 2003/2004 is less evolved than what I
have now (that would be pretty bad performance); but please, credit where
credit is due:
<http://bytes.com/groups/javascript/151754-when-window-location-url-ex....>
(Google doesn't seem to have it anymore, or the search function is borken..)
If you mean isMethodType, then yes.
You really can search for "function isMethod" there if you want. Trust me.

I believe you, but if it accepts references to host objects for the
first argument, I'm confused by your prior position on isHostMethod.

4 years later in cljs ... and my code (style) had changed significantly;
much for the better, thanks to the discussions here.
I presume Google Groups still has the first version, either here or in
de.comp.lang.javascript.
Huh? The first version(s) were posted here during the CWR
discussions.
No, years before that. IIRC, even years before Peter and you found cljs (at
least before you were *posting* here).
That was certainly not isHostMethod as that is what I named my
function.
Yes, I have never seen the need to make a difference there and I still don't
see it. Apparently Peter started to doubt, too.
What are you talking about? [snip irrelevance]
<news:[email protected]>

If that's from today, I read it (and explained its relative relevance
a minute ago.)

That's just too cryptic for me to parse right now.
You snipped too hastily apparently. You said something about not
knowing the difference between testing for "unknown" or not.

No, I didn't.

BTW, I just noticed that I searched for "typeof unknown" and ended up
referring to the wrong posting. That which I referred to does not contain
"unknown" at all.

First mention of "unknown" as typeof result here by Thor Larholm in 2000:

<http://groups.google.com/group/comp.lang.javascript/msg/13c5162bcbac2434?hl=en&dmode=source>

First mention of "unknown" on host objects here by James D. Rofkar in 2001:

<http://groups.google.com/group/comp...8bd2abc186d1?hl=en&dmode=source&output=gplain>

First mention of "unknown" objects throwing an exception on property access
by John Irish in 2001:

<http://groups.google.com/group/comp...8f52773542bc?hl=en&dmode=source&output=gplain>

Incidentally, that research (keywords: typeof unknown
group:comp.lang.javascript) has showed up a number of interesting postings
in the past about "unknown" objects and their history in MSHTML.
Big difference there (safe vs. explosive.)

Of course.
Sounds good. My areHostMethods just allows for n string arguments
after the host object reference (e.g. gEBI, gEBTN, etc.) It's handy
when an app needs to check several methods of the same host object.

As discussed, that approach has the drawback that the method needs
to be called repeatedly if "properties of properties" need to be tested.


PointedEars
 
D

David Mark

On Jul 3, 12:26 am, Thomas 'PointedEars' Lahn <[email protected]>
wrote:

[smip]
First mention of "unknown" as typeof result here by Thor Larholm in 2000:

<http://groups.google.com/group/comp.lang.javascript/msg/13c5162bcbac2...>

First mention of "unknown" on host objects here by James D. Rofkar in 2001:

<http://groups.google.com/group/comp.lang.javascript/msg/5e638bd2abc18...>

First mention of "unknown" objects throwing an exception on property access
by John Irish in 2001:

<http://groups.google.com/group/comp.lang.javascript/msg/2de58f5277354...>

Perhaps I never brought up the pre-2000 Mac IE object that lead me to
use typeof for feature detection. I think the first time I discussed
it here was in response to a query about a window.external method and
that would have been in 2007. I came up with the isMethod
augmentation (isHostMethod) shortly thereafter. I'm pretty sure I was
the first to mention that ActiveX was the culprit and "unknown" likely
referred to the IUnknown interface.
Incidentally, that research (keywords: typeof unknown
group:comp.lang.javascript) has showed up a number of interesting postings
in the past about "unknown" objects and their history in MSHTML.

Probably wouldn't interest me at this point. :)
Of course.



As discussed, that approach has the drawback that the method needs
to be called repeatedly if "properties of properties" need to be tested.

That's another function (which I think you posted recently.)
 
W

wilq

In comp.lang.javascript message <[email protected]>, Thu,


An excellent demonstration of the relative powers of arguing and of
getting actual facts.

Time taken by D.getTime(), as percentage of time for +D, if I tested
correctly :

        IE 7            85
        FF 3.0.11       85
        Op 9.64         43
        Safari 4.0      65
        Chrome 2.0      29

Testing with new Date() gives rather irregular results, presumably
because of the many OS calls; but supports the conclusion.

Using getTime calls explicitly for use of that Method; using unary +
calls implicitly for the use of method valueOf, presumably the same
code, and also does the "return a Number" operation, apparently not
optimising it out.

But I suggest that testing is not needed to see that unary + is faster
to type and to read.

Did that speed difference not get mentioned here before, not so long
ago?

--
 (c) John Stockton, nr London, UK.    [email protected]     Turnpike v6.05.
 Web  <URL:http://www.merlyn.demon.co.uk/> - w. FAQish topics, links,acronyms
 PAS EXE etc : <URL:http://www.merlyn.demon.co.uk/programs/> - see 00index.htm
 Dates - miscdate.htm estrdate.htm js-dates.htm pas-time.htm critdate.htm etc.


Well basically as all of us knows (new Date()).getTime are not very
reliable on short timings. This is where iteration comes in. If the
time produced because of iteration will be really long (i.e. few
seconds), you will minimise all influence from (new Date()).getTime()
- that is an idea of doing any tests... So even moving to +(new Date)
will not change alot in tests right now... Please try...
 
W

wilq

The question raised by this is: Is it realistic for an app to perform that
many calls of isMethod() consecutively?  If not, the number is too high..
And as it is too high (IMHO), differences in runtime efficiency between
these approaches are in fact not as important as you present them to be.
And, as I said, efficiency is not everything.  To begin with, any approach
should balance efficiency against reliability.

For real working app ? Well probably you wont fire that function
500000 in real app, but results I get that it can be even to 3 times
slower is just something that might be important for me if I planning
to create wig app that uses alot of javascript code that I want to
make it runing as fast as possible. This reminds me a case when
someone want to follow standard in className for DOM elements, where
it says that you can use whitespaces to separate classes. This means
that you could put tab or enter there. Thats great but to put that
idea inside function instead of splitting className over space, you
need to split that using regexp. This function was fired many times in
project and removing regexp just makes it working alot faster. Those
small diffrences of performance DO matters if its beeing called many
times in project. 1ms or 3ms is no diffrence, count that * 1000, and
you have 1s vs 3s. 1000 of calling this method in really big app is -
you think - much or not ?
No, you don't.


Hardly.  Fair would be

  someTemp = regExp.test(a) || regExp.test(b);

Think, in every iteration I doing two tests. Like you would fire
function twice.
someTemp = regExp.test(a);
someTemp = regExp.test(b);

First part of this is best case, second is worst case (for string
comparsion). This cases almost does not matter for regexp, but this is
still behaves as a twice execution of the function that I profiling.

This concept:

someTemp = regExp.test(a) || regExp.test(b);

is wrong because it works more like a one iteration... first part
before || will always return true because I assume 'a' to be string
containing "function" or "object" (I remove stage of type conversion
assuming that I have a string in return). Second part will never be
fired in that circumstances..... Dont you see that ?
The problem is that you are picking the cases that are in your favor,
IOW you *are* cheating here.

I pick two cases - "function" and "object" what is wrong with those
cases ? Please propose then cases that will make your statements true.
But dont try to cheat like with this "someTemp = regexp || regexp"
This test is biased(, then).

I think that you dont get whole idea..
*Maybe* so, on *your* computer, *without RegExp optimization*.  But it is
on *all* computers (running non-obsolete implementations) *less reliable*..

So on other computers with regexp optimalization it will be __faster__
that simple string comparsion?


I have posted and pointed to the current (abridged) isMethod()
implementation already; now you only need to notice that.

Maybe I did not notice your test case and profiling testing.. Please
be so kind and point me directly where exacly are this test/profiling
function.
 
D

Dr J R Stockton

In comp.lang.javascript message <b683c06c-1221-42c6-b91f-d40e09e23b1d@y9
g2000yqg.googlegroups.com>, Fri, 3 Jul 2009 01:24:13, wilq
Well basically as all of us knows (new Date()).getTime are not very
reliable on short timings. This is where iteration comes in. If the
time produced because of iteration will be really long (i.e. few
seconds), you will minimise all influence from (new Date()).getTime()
- that is an idea of doing any tests... So even moving to +(new Date)
will not change alot in tests right now... Please try...


A well-written newsreader should have trimmed that sig from the quote;
but not using one is not adequate justification for leaving it in.

Firstly, who said that (new Date()).getTime() was used *to perform the
timings*? After all, there is at least one other way of doing it,
without using values of new Date() at all.

Secondly, who said that the durations measured were short? Those are
percentages, and you have no way of telling the overall number of
seconds measured.

Evidently you are not a metrologist.

I often advise people to read messages carefully before posting
"answers"; in this case that hardly seems worth-while.

YGCIB.
 
J

Jorge

(...)
Firstly, who said that (new Date()).getTime() was used *to perform the
timings*?  After all, there is at least one other way of doing it,
without using values of new Date() at all.
(...)

How, please ?

TIA,
 
D

David Mark

[snip]
Just to make things clear, I am interested in your opinion about
boolean- type conversion of host objects (not methods). You mentioned
that it is safe to type convert `<nodeRef>.firstChild/lastChild`. Now
I'm trying to figure out whether it is safe to type-convert other host
objects, such as `document`;

e.g. - `if (<global object>.window.document) { ... }`.

[snip]

Depends. Consult isHostObjectProperty. The "unknown" properties
known *not* to be implemented as methods are unusable.

An example has been demonstrated in the past where an element orphaned
by an innerHTML assignment will have an "unknown" offsetParent
property. Hard to say why, but it is certainly a useless property at
that point (even an access throws an exception.)

That reminds me, always use typeof to test string properties as well
(isHostStringProperty?) In at least some builds of IE7, news link
(NNTP protocol) href properties (normally strings) are "unknown." Go
figure.

And then there are the truly unknown problems that nobody has
discovered (or invented) yet. There may be host objects out there
that have "poison" types or "don't tread on me" types. Such surprises
are best avoided as well (at least until they can be studied.) The
isHost* functions (or methods in most cases) are very simple, but
quite calculated in what they allow. An easy rule for choosing
between the main two is to use isHostMethod for anything you plan to
call. Use isHostObjectProperty for virtually everything else. I
can't even remember what the third one was (host collections?) I know
I never use it.
 
G

Garrett Smith

When does that happen?

All those extra function calls would slow the function down.
Yes, this "method" is usually faster if you don't care about "lost"
event listeners of original element.

That is true for all properties that don't reflect.
There are some problems with `cloneNode`, though. IIRC, cloning form
elements doesn't "copy" user-set values of containing input elements in
IE (not sure which versions, probably <=6).
Would be nice to have a DOM method for that and serialization.

e.g.
var formClone = form.cloneObject(); // Copy state.
var formHTML = form.toHTML(); // Serialize state.
I remember I first found this bug in Garrett's APE (should be fixed now).
It should, but I'm not sure if it actually is.

Garrett
 
P

Peter

kangax pisze:
Yes, this "method" is usually faster if you don't care about "lost"
event listeners of original element.

I found some information that "Only events added as attributes are
cloned. Not those added using AddEventListener."

http://tinyurl.com/m2tgyr

But I can't find some more information in Google. Maybe someone could
write something more about above sentence.
 
D

David Mark

David said:
Just to make things clear, I am interested in your opinion about
boolean- type conversion of host objects (not methods). You mentioned
that it is safe to type convert `<nodeRef>.firstChild/lastChild`. Now
I'm trying to figure out whether it is safe to type-convert other host
objects, such as `document`;
e.g. - `if (<global object>.window.document) { ... }`.

Depends.  Consult isHostObjectProperty.  The "unknown" properties
known *not* to be implemented as methods are unusable.
An example has been demonstrated in the past where an element orphaned
by an innerHTML assignment will have an "unknown" offsetParent
property.  Hard to say why, but it is certainly a useless property at
that point (even an access throws an exception.)

Doesn't have to be orphaned by an `innerHTML`, if I'm not mistaken. I
remember writing a feature test for this particular bug in Prototype:

<http://github.com/kangax/prototype/blob/a223833c8b49ae55f03b1e1a3a5b7...>

It crashed my browser again (preceded by a large black box on the
document and my CPU fans going through the roof.) No thanks.
(Don't mind all the mess around in that file.)

Never got to see it.
Also note that it is lack of "parentNode" that seems to be the root of
the issue, not the orphanness of an element per se.

I fail to see the difference (and can't pin down "orphanness" anyway.)
Well, IE can return "unknown" for `lastChild` as well, so element's
contents would need to be emptied as:

while (isHostObjectProperty(element, "lastChild")) {
   element.removeChild(element.lastChild);

}

Not really. Your app should never present such a possibility.
Trouble comes when you try to write a library for every occasion (e.g.
Prototype.)
Btw, looking at MyLib.js, I see that you do indeed use
`isHostObjectProperty` for testing `firstChild`, although it's being

In one-off feature detection I am sure.
used inconsistently and some of the checks seem to be missing (e.g.
`getElementText` has it, but `setElementText` doesn't).

I assume you mean used inconsistently in that some of the checks are
missing. No doubt about it. Was slapped together in about two months
and I lost interest soon afterward. Turned out to be the magic
formula! ;)
I also see that you never test `firstChild` with `isHostObjectProperty`
at runtime (I assume for perf. reasons?).

Should fail immediately. The calling app blew it at that point.
You test
`document.documentElement`'s `firstChild` upfront and assume that
`firstChild` of any other DOM element doesn't blow up. Is this really a
safe assumption to make?

That's not testing for the IE explosion issue (just that the property
exists.)
On a side note, it would be nice if we could automate testing of
`isHostMethod` coverage. Maybe create an artificial environment where
host objects properties would be defined via error-throwing setters.

Be my guest.
Then run test suite through all unit tests and ensure that nothing blows
up (i.e. that there's no plain host objects properties access, and that
everything is proxied through `isHostObjectProperty`)

Well, you don't normally need to be so thorough with the testing.
Often it is good to let things fail immediately. I laugh when I see
that "unspecified error" on a job site. The fix is never to add a
call to isHostObjectProperty (it's to fix whatever made the mistake of
passing an "orphaned" element.)
 
D

David Mark

When does that happen?

Again? IE can return "unknown" for any host object property at any
given time. It's particularly true of elements, as has been discussed
here many times. I told you the keywords to search last time you
asked (so search for your query.)

[snip]
 
R

Roger

David said:
David Mark wrote:
[snip]
Just to make things clear, I am interested in your opinion about
boolean- type conversion of host objects (not methods). You mentioned
that it is safe to type convert `<nodeRef>.firstChild/lastChild`. Now
I'm trying to figure out whether it is safe to type-convert other host
objects, such as `document`;
e.g. - `if (<global object>.window.document) { ... }`.
[snip]
Depends. Consult isHostObjectProperty. The "unknown" properties
known *not* to be implemented as methods are unusable.
An example has been demonstrated in the past where an element orphaned
by an innerHTML assignment will have an "unknown" offsetParent
property. Hard to say why, but it is certainly a useless property at
that point (even an access throws an exception.)
Doesn't have to be orphaned by an `innerHTML`, if I'm not mistaken. I
remember writing a feature test for this particular bug in Prototype:
<http://github.com/kangax/prototype/blob/a223833c8b49ae55f03b1e1a3a5b7...>
It crashed my browser again (preceded by a large black box on the
document and my CPU fans going through the roof.) No thanks.

Jeez. It never crashed on me. Which browser/OS are you using?

XP Pro with FF3.x. Last time it was just a black box at the bottom
(no crash.) IIRC, the site uses jQuery, so anything is possible.
Here's a plain "js" file. Search for "var
OFFSET_PARENT_THROWS_ON_ORPHANED_ELEMENT"

http://github.com/kangax/prototype/raw/a223833c8b49ae55f03b1e1a3a5b7e...

Not that there's something extraordinary there.

I'll take your word for it (and I think I've seen it.)
Orphaned element is the one that is not in a document at a given time.
In other words, you won't get to its `ownerDocument` by following its
`parentNode` chain.

var divEl = document.createElement('div');
var spanEl = document.createElement('span');
divEl.appendChild(spanEl);

At this point `divEl` has no `parentNode` and is orphaned from the
document. At the same time, `spanEl` *has `parentNode`* but is still
orphaned from the document.

If I'm correct, IE won't throw on `spanEl.offsetParent`, but will throw
on `divEl.offsetParent`, even though both elements are orphaned ones. I
assume this missing `parentNode` is what causes IE to throw (maybe
`offsetParent` tries to call one of its members internally or smth.)

Does this make things clearer?

Yes, but I think your recollections are off regarding IE, orphans and
the "unspecified error." I don't think a newly created element has an
"unknown" offsetParent property. I'm pretty sure I had to do
something odd to make that happen (e.g. user innerHTML.) Hard to say
though as IE varies according to Windows update. These rules have
been known to change overnight.
Not sure what you mean. How else will my helper clear element's
contents? You either use `isHostObjectProperty` at runtime when
accessing `firstChild`, or you use boolean type conversion and face a
chance of blow up.

(I really hate Google. The "posting limit" for my real account has
been exceeded.)

It won't blow up unless the caller did something it shouldn't have
(and in that case you want it to blow up.) These isHost* methods are
primarily for feature testing things once at the outset. For
instance, if you have an absolute position function (not recommended
of course), you will need to check offsetParent. You wouldn't want to
treat an "unknown" offsetParent like one that is missing. The former
clearly indicates a mistake by the caller, the latter does not. Best
to let obvious mistakes blow up (else they can sneak into production.)
That's what I meant.




That's what I thought. Why are you stuffing `firstChild` in a plain
type-conversion at run time then? What if `firstChild` references
"unknown" object/element at some point?

That would be a highly unexpected turn of events (unlike offsetParent
above.) You can't prevent every conceivable problem, else your code
would go on forever. In this case, I'd want to see it blow up so I
could investigate the cause.
I'll think about this whole idea and how to implement it better.
Perhaps, using Rhino with specifically crafted environment simulating
hostile, error-throwing DOM.

I don't know much about Rhino.
Of course. But if doesn't fail upfront, there's no guarantee it won't
fail at load time. Obviously, that's the main danger in that kind of
inference (object inference type II, is it?)

No. You are confusing feature detection with the perceived need to
defend against all cases of the "unspecified error" in IE. They are
somewhat related by the use of common methods, but not at all the same
thing.
 
D

David Mark

kangax pisze:





I found some information that "Only events added as attributes are
cloned. Not those added using AddEventListener."

http://tinyurl.com/m2tgyr

But I can't find some more information in Google. Maybe someone could
write something more about above sentence.

It's a clumsy way of saying that (in FF) intrinsic event handler
attributes are copied to the clone, but attached listeners are not
(which seems reasonable.) I wouldn't count on anything to do with
cloning (or importing) elements with intrinsic event handlers (or
inline styles) though. If you must do such things, you will have to
feature test each case.
 
R

RobG

kangax pisze:

It also goes belly-up in some earlier versions of Safar or Opera or
maybe both, I can't remember. The clone was created OK, but an error
was thrown during the replace. Anyone who cares about such ancient
artifacts should test thoroughly.

I found some information that "Only events added as attributes are
cloned. Not those added using AddEventListener."

http://tinyurl.com/m2tgyr

Per the DOM 2 Events spec for interface EventListener:

"When a Node is copied using the cloneNode method the
EventListeners attached to the source Node are not attached
to the copied Node. If the user wishes the same EventListeners
to be added to the newly created copy the user must add them
manually."

<URL: http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-EventListener
The story in IE, Fx and Safari at least is:

1. If added as attributes, they're clonded too

2. If added as properties, they're dropped

3. If added using addEventListener they're dropped (W3C compliant)

4. If added using attachEvent, they're cloned too (in IE at least).
 
G

Garrett Smith

kangax said:
When `lastChild` references an element/object with "unknown" typeof in
IE, I suppose.

The providing of such an example would be good, helpful, and informative.

That is true for all properties that don't reflect.

What do you mean by "properties that don't reflect"?

[...]

Using HTML 5 term to describe the phenomenon:
| Some DOM attributes are defined to reflect a particular content
| attribute. This means that on getting, the DOM attribute returns the
| current value of the content attribute, and on setting, the DOM
| attribute changes the value of the content attribute to the given
| value.

From:
http://www.whatwg.org/specs/web-apps/current-work/multipage/infrastructure.html#reflect

(I am using a term to describe a phenomenon. The HTML 5 draft, again, is
a draft, not a TR.)

Implementations vary a lot on actual behavior. To make IE's behavior
allowable, HTML 5 could create properties I mentioned earlier, and then
IE could implement those and recommend those. That makes it easier for
IE to change behavior of attributes and serialization (innerHTML) to
match the other browsers (which copied IE halfway) and allow developers
a way to still get the IE attributes/serialization behavior AND have it
work in more browsers (should they implement such strategies).

Garrett
 
D

David Mark

You know that if I had one, I would have already provided it :)

I'm speaking theoretically, of course; based on previous observations of
host objects. I personally have never seen `lastChild`/`firstChild`
reference `unknown`. Whether these properties should be tested for it is
a rather subjective topic.

One approach is to test every access of every host property via
relatively safe wrapper such as isHostMethod/isHostObjectProperty.

As mentioned, that is definitely the wrong approach. Those methods
are virtually always used for feature testing (and once per load.)

Instead of firstChild/lastChild (which can be "unknown" as I've seen
elements in the debugger with every property inaccessible and the
value as "[unknown]"), take offsetParent, which we all know can be
unknown (and the cause seems to be predictable.)

If you have a function to calculate position offsets, one of the first
few lines is likely to read:

if (el.offsetParent) { ... }

Likely the rest of the logic is contained in this branch, else you
would check the computed style (e.g. some browsers set offsetParent to
null for elements with fixed position.) Clearly this is an important
test and perhaps it looks like it would be dangerous and you might
jump to the conclusion that using this would be more safe:

if (isHostObjectProperty(el, 'offsetParent')) { ... }

As mentioned, this much slower and additional baggage for nothing (you
should have already tested the property is available on elements.)
But that's not the real issue. The logic is flat-out wrong. Look at
the two cases where this would fail:

1. Fixed position in some browsers
2. Orphaned element in IE (under some circumstances)

These are completely incompatible cases, each requiring its own logic.

The first one is something you need to check. The second should
*never* come up as the rest of your app should know better than to try
to compute offsets for orphaned elements. In this second case, you
want the exception to be thrown, then you can easily find the bug by
examining the call stack.

Obviously, this is the only correct solution:

if (el.offsetParent) { ... }

These patterns repeat themselves endlessly in DOM scripting. If you
find yourself hiding from "unknown" types after the gateway is cleared
(i.e. feature detection is complete), you are likely shielding
yourself from critical debugging information.

And think about what you would do if the second pattern failed.
Trying to get the computed style (actually cascaded in IE) will not
yield anything related to an offset for an orphaned element. It may
fail silently with an odd result (in which case, you've got a very
obscure bug to track down) or it may throw further exceptions.
Obviously, the last thing you would do is add more calls to isHost* to
prevent further exceptions.

Does that make it clear?
The
downside to this is performance hit. The benefit is protection against
any existent and future throwable properties.

Absolutely not. See above.
Another - perhaps more pragmatic - approach is to only use wrapper on
elements which are known (or likely) to blow up. Performance would be
higher then, but so would the chance of stumbling upon unknown/future
throwable property.

No. You use these isHost* functions during feature detection and for
every host method and property. You cannot pick and choose. You
virtually never use them afterward.
That is true for all properties that don't reflect.
What do you mean by "properties that don't reflect"?
[...]
Using HTML 5 term to describe the phenomenon:

WTF. Who is trying too hard to be clever? Don't use terms from that
draft here.

Especially not *that* one. Whoever came up with "DOM attributes" to
describe properties should be locked up (or at least barred from such
discussions.)

Same for "content attribute." Twits shouldn't be allowed to write
these documents. Nobody is going to understand them.

Just read it aloud and it becomes crystal clear.

Lets stop posting that link as well. From what I've heard, the score
is two crashed browsers plus one successful load that took six
minutes.
That makes sense. Thanks.

Doh!
 
R

RobG

RobG wrote:

[...]
Per the DOM 2 Events spec for interface EventListener:
  "When a Node is copied using the cloneNode method the
   EventListeners attached to the source Node are not attached
   to the copied Node. If the user wishes the same EventListeners
   to be added to the newly created copy the user must add them
   manually."

The story in IE, Fx and Safari at least is:
1. If added as attributes, they're clonded too
2. If added as properties, they're dropped

Note that properties (and so attributes) that don't correspond to any of
intrinsic event handler names are cloned too. (in IE)

And Firefox. To add to the mix, non-standard properties are clonded in
IE but not in Firefox, non-standard attributes are cloned in both. I
lost interest in documenting it in more detail after discovering how
random it is, so there are likely many more inconsistancies.
In other words,

.... it's a complete mess. :-(

cloneNode(false) can't be used as a general method to empty content,
though it is OK for specific cases where the pitfalls are avoided.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,093
Messages
2,570,607
Members
47,226
Latest member
uatas12

Latest Threads

Top