By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
432,569 Members | 1,386 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 432,569 IT Pros & Developers. It's quick & easy.

Exception when calling a DOM method using a reference to it

P: n/a
In an attempt to answer another question in this group, I've had to resort
to calling the DOM method, Node.removeChild(), using a reference to it
(long story...). That is, passing Node.removeChild.

In Opera (7.23/Win), the call appears to do nothing - the node remains -
but no errors are shown. In Netscape (7.0/Win), an exception results[1].
On IE (6.0/Win), the node is removed.

Strangly, if I pass another function reference, say window.alert or a
user-defined function, there is no problem.

This illustrates the problem:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta http-equiv="Content-Script-Type" content="text/javascript">

<title>Function reference test</title>

<script type="text/javascript">
function executeRef( func, arg ) {
func( arg );
}

function performRefTest() {
var elem = document.getElementById('testDiv');
executeRef( elem.parentNode.removeChild, elem );
}
</script>
</head>

<body onload="performRefTest()">
<div id="testDiv">
Page content
</div>
<div>
This should be the only text remaining.
</div>
</body>
</html>

Any suggestions?

Mike
[1] The message:

Error: uncaught exception: [Exception... "Illegal operation on
WrappedNative prototype object" nsresult: "0x8057000c
(NS_ERROR_XPC_BAD_OP_ON_WN_PROTO)" location: "JS frame ::
file:///F:/Web/Blockquote/cite.js :: timerInstance_fire :: line 103"
data: no]

--
Michael Winter
M.******@blueyonder.co.invalid (replace ".invalid" with ".uk" to reply)
Jul 20 '05 #1
Share this Question
Share on Google+
14 Replies


P: n/a
On Sat, 14 Feb 2004 20:18:07 GMT, Michael Winter
<M.******@blueyonder.co.invalid> wrote:

[snip]
In Netscape (7.0/Win), an exception results[1].
[snip]
[1] The message:

Error: uncaught exception: [Exception... "Illegal operation on
WrappedNative prototype object" nsresult: "0x8057000c
(NS_ERROR_XPC_BAD_OP_ON_WN_PROTO)" location: "JS frame ::
file:///F:/Web/Blockquote/cite.js :: timerInstance_fire :: line 103"
data: no]


That's actually the wrong message, not that it makes any difference.
However, for correctness:

Error: uncaught exception: [Exception... "Illegal operation on
WrappedNative prototype object" nsresult: "0x8057000c
(NS_ERROR_XPC_BAD_OP_ON_WN_PROTO)" location: "JS frame ::
file:///F:/Web/test.html :: executeRef :: line 13" data: no]

The previous message was from the actual script I was working on, whereas
the one above is from the sample I posted.

Mike

--
Michael Winter
M.******@blueyonder.co.invalid (replace ".invalid" with ".uk" to reply)
Jul 20 '05 #2

P: n/a
"Michael Winter" <M.******@blueyonder.co.invalid> wrote in message
news:op**************@news-text.blueyonder.co.uk...
<snip>
<script type="text/javascript">
function executeRef( func, arg ) {
func( arg );
}

function performRefTest() {
var elem = document.getElementById('testDiv');
executeRef( elem.parentNode.removeChild, elem );
}
</script>
</head>

<snip>

You are passing a reference to the method of a node to the - executeRef -
function. Once that function receives the reference it is just a reference
to a function object and not a method of an object. The association with -
elm.parentNode - is gone.

It would not necessarily work exactly the same for native code functions
(hence it working with IE) but calling - func(arg); - for a javascript
method would execute it in the global scope and result in the - this -
keyword referring to the window object instead of - elm.parentNode - .
And - arg - is not a child of the global object so that node could not be
removed, assuming the function would operate in that context at all without
erroring (as it does on Mozilla)

Richard.
Jul 20 '05 #3

P: n/a
On Sat, 14 Feb 2004 20:18:07 GMT, Michael Winter wrote:
In Opera (7.23/Win), the call appears to do nothing - the node remains -
but no errors are shown. In Netscape (7.0/Win), an exception results[1].
On IE (6.0/Win), the node is removed.


Probably 'cause you referer only the prototype function.

I mean:

<script type="text/javascript">
myobject={
message:"default",
me:function(){
alert(this.message);
}
}

myobject.me();

var x=myobject.me;
x();
</script>

How you can see, the x variable "point" to function, not the entire object.

If the function make a call to object, you get an exception, in native
code.

A possible workaround could be:

function executeRef(func, arg, obj) {
obj=obj||window;
obj[func](arg);
}
function performRefTest() {

executeRef ("alert","this is an argument");
var elem = document.getElementById('testDiv');
executeRef ("removeChild",elem, elem.parentNode);
}

But maybe this is not a solution for you.

--
C'ya,
ZER0 :: coder.gfxer.webDesigner();

"When you have eliminated the impossible, whatever remains,
however improbable, must be the truth." (S.H.)
Jul 20 '05 #4

P: n/a
Michael Winter wrote:
In an attempt to answer another question in this group, I've had to
resort to calling the DOM method, Node.removeChild(), using a reference
to it (long story...). That is, passing Node.removeChild. In Opera (7.23/Win), the call appears to do nothing - the node remains -
but no errors are shown. In Netscape (7.0/Win), an exception results[1].
On IE (6.0/Win), the node is removed. Error: uncaught exception: [Exception... "Illegal operation on
WrappedNative prototype object" nsresult: "0x8057000c
(NS_ERROR_XPC_BAD_OP_ON_WN_PROTO)"

The first time I've met this error was when testing
var gebi=document.all||document.getElementById;
which would work fine in IE but not in Mozilla.

Apparently, Mozilla's DOM methods need a context to execute correctly,
that is, you cannot pass the function without the appropriate "this"
value being set (this makes sense, since DOM object tend to be
prototyped in Mozilla, but not in IE, which therefore probably starts
from internal hash to resolve the property and re-set the "this" value).

function executeRef( func, arg ) {
func.call(arg.parentNode, arg);
// func( arg );
}

would demonstrate the point in your example, but brings no value; in the
end your conception should work with wrapper functions, like

function removeChild(parent, child) {
//maybe test for parent existence, removeChild support
// and that child belongs to parent
parent.removeChild(child);
}
HTH
Yep.
Jul 20 '05 #5

P: n/a
On Sat, 14 Feb 2004 21:55:48 +0000 (UTC), Richard Cornford
<Ri*****@litotes.demon.co.uk> wrote:

[snip]
You are passing a reference to the method of a node to the - executeRef -
function. Once that function receives the reference it is just a
reference to a function object and not a method of an object. The
association with - elm.parentNode - is gone.


[snip]

Ah, I see. I wasn't anticipating that at all. Until I tested the approach
in Netscape (where the exception occurred), I was going out of my mind as
all of the parameters were being passed correctly, but nothing was
happening. I realised that I could pass the object and then call the
method, but that didn't fit well with what I was trying to do. As it
happens, someone's already answered the problem that I was trying to
solve, so I can drop the whole thing now, anyway. It was a good coding
exercise though (apart from the headache).

Thank you.

Mike

--
Michael Winter
M.******@blueyonder.co.invalid (replace ".invalid" with ".uk" to reply)
Jul 20 '05 #6

P: n/a
Michael Winter <M.******@blueyonder.co.invalid> writes:
In an attempt to answer another question in this group, I've had to
resort to calling the DOM method, Node.removeChild(), using a
reference to it (long story...). That is, passing Node.removeChild.
Try this example:

var x = "Gotcha";
var obj = {x:42,foo:function(){alert(this.x);}};
obj.foo(); // alerts 42

Then try passing the foo method somewhere else, like
executeRed(obj.foo,null);
Unsurpricingly, it doesn't alert 42 any more. It is not called as a
method of the object named obj, so the "this" keyword doesn't refer
to it any more. Instead, since the function is called with no object,
this refers to the global object, and it alerts "Gotcha".
In Opera (7.23/Win), the call appears to do nothing - the node remains
Unsurpricing. That was what I would have expected, although I would have
expected an error message too.
-
but no errors are shown. In Netscape (7.0/Win), an exception
results[1].
Another valid result.
On IE (6.0/Win), the node is removed.
I would call that surpricing. Ofcourse, it is quite possible to remove
a node without knowing its parent, because the node has a reference to
it, so removeChild could be written without using the "this" reference.
Strangly, if I pass another function reference, say window.alert or a
user-defined function, there is no problem.
That is because the function doesn't use the object it is on. The
foo function above fails.
Don't pass a plain function. Pass the object and the name of the function,
and let the calling point make the connection:
---
<script type="text/javascript">
function executeRef( obj,func, arg ) {
obj[func]( arg );
}

function performRefTest() {
var elem = document.getElementById('testDiv');
executeRef( elem.parentNode,"removeChild", elem );
}
</script>
---

Or, pass the function as a function (not a string) together with the
object:
---
<script type="text/javascript">
function executeRef( obj,func, arg ) {
func.call(obj,arg);
}

function performRefTest() {
var elem = document.getElementById('testDiv');
executeRef( elem.parentNode,elem.parentNode.removeChild, elem );
}
</script>
---
For host objects like DOM nodes, I would not use the latter method,
because I am not sure it would work correctly. It might, but with host
objects, all bets are off.

[1] The message:

Error: uncaught exception: [Exception... "Illegal operation on
WrappedNative prototype object" nsresult: "0x8057000c
(NS_ERROR_XPC_BAD_OP_ON_WN_PROTO)" location: "JS frame ::
file:///F:/Web/Blockquote/cite.js :: timerInstance_fire :: line 103"
data: no]


Hardly informative, admittedly :)

/L
--
Lasse Reichstein Nielsen - lr*@hotpop.com
DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleDOM.html>
'Faith without judgement merely degrades the spirit divine.'
Jul 20 '05 #7

P: n/a
On Sat, 14 Feb 2004 22:02:39 GMT, ZER0 <ze********@libero.it> wrote:

[snip]
A possible workaround could be:

function executeRef(func, arg, obj) {
obj=obj||window;
obj[func](arg);
}
function performRefTest() {

executeRef ("alert","this is an argument");
var elem = document.getElementById('testDiv');
executeRef ("removeChild",elem, elem.parentNode);
}
As it happens, I tried exactly that (in the full, not test, script) whilst
trying to investigate what was happening.
But maybe this is not a solution for you.


Unfortunately, it was not. If I still had a desire to finish the script, I
would probably take this approach. Luckly, Yep posted a solution, so I
don't have to, and I get to avoid numerous IE workarounds (curse
Microsoft). :)

Thanks,
Mike

--
Michael Winter
M.******@blueyonder.co.invalid (replace ".invalid" with ".uk" to reply)
Jul 20 '05 #8

P: n/a
On Sat, 14 Feb 2004 23:28:48 +0100, Lasse Reichstein Nielsen
<lr*@hotpop.com> wrote:

[snip]
On IE (6.0/Win), the node is removed.
I would call that surpricing. [...]


That did throw me somewhat. However, due to the fact that Opera and
Netscape were both having trouble, I quickly ruled it out as an IE oddity.

[snip]
Or, pass the function as a function (not a string) together with the
object:
---
<script type="text/javascript">
function executeRef( obj,func, arg ) {
func.call(obj,arg);
}

function performRefTest() {
var elem = document.getElementById('testDiv');
executeRef( elem.parentNode,elem.parentNode.removeChild, elem );
}
</script>
---
For host objects like DOM nodes, I would not use the latter method,
because I am not sure it would work correctly. It might, but with host
objects, all bets are off.


So *that's* how you use Function.call(). I only had Netscape's 1.3 spec to
hand and it explains it very poorly. The later versions are much improved.
[1] The message:

Error: uncaught exception: [Exception... "Illegal operation on
WrappedNative prototype object" nsresult: "0x8057000c
(NS_ERROR_XPC_BAD_OP_ON_WN_PROTO)" location: "JS frame ::
file:///F:/Web/Blockquote/cite.js :: timerInstance_fire :: line 103"
data: no]


Hardly informative, admittedly :)


Yes, I know :) I included it only on the basis that someone might
recognise it as it was the only error message out of three browsers that I
could muster. As it happens, Yep did appear to recognise it.

Mike

--
Michael Winter
M.******@blueyonder.co.invalid (replace ".invalid" with ".uk" to reply)
Jul 20 '05 #9

P: n/a
On Sat, 14 Feb 2004 23:05:52 +0100, Yann-Erwan Perio
<y-*******@em-lyon.com> wrote:
[...] in the end your conception should work with wrapper
functions, like

function removeChild(parent, child) {
//maybe test for parent existence, removeChild support
// and that child belongs to parent
parent.removeChild(child);
}


I was considering that approach, but as you've already answered the
question I was responding to ("Putting functionality back into <blockquote
/>"), there isn't much point (especially as I've barely started the IE
workarounds[1]).

The point of this was that Opera immediately removed the node when passing
the cursor between the quote and the link (I didn't test your solution -
do you have this problem?). As a workaround, I set about placing the
removal on a short timer. The problem with this is that references passed
to setTimeout are out of scope by the time the timer expires. This lead to
a rather elaborate object pair that would store the references until the
timer expires allowing the methods to operate correctly, then cleaning up
afterwards. It was going so well, then this context business happened.

Oh well. I still learnt a lot from the exercise.

Thank you,
Mike

[1] IE might have been a lost cause though, due to its erroneous rendering
of the CSS rules which makes the link virtually unusable.

--
Michael Winter
M.******@blueyonder.co.invalid (replace ".invalid" with ".uk" to reply)
Jul 20 '05 #10

P: n/a
Michael Winter wrote:
The point of this was that Opera immediately removed the node when
passing the cursor between the quote and the link (I didn't test your
solution - do you have this problem?
Hm no, since the span is contained within the blockquote, the mouseout
handler is stopped in time (thanks to the event management system). I
have found that a good test to validate the strategy was to include an
inner blockquote in the outer blockquote; this showed most of the issues
which were to be addressed.
As a workaround, I set about
placing the removal on a short timer.
Actually I've considered using a timer, along with positioning
functions, but in order to improve the display only (I left it aside in
the end, since that would have made the script inappropriate to
demonstrate what I wanted to expose to the OP - way too complicated:-)).

Web browsers are event-driven environments, so it's better to use events
(it's not impossible to obtain satisfying solutions with timers, but
they're generally not as reliable, and certainly more difficult to set up).
The problem with this is that
references passed to setTimeout are out of scope by the time the timer
expires.
Then, if you're not already familiar with them, it's maybe time for you
to get into closures:-)
[1] IE might have been a lost cause though, due to its erroneous
rendering of the CSS rules which makes the link virtually unusable.


Yes that's indeed an annoying problem, however the OP seemed to really
have an idea about how the script could be written, so I've kept his
conception, I suppose that he'll be playing with padding/margin in order
to find some decent solution.
Cheers,
Yep.
Jul 20 '05 #11

P: n/a
On Sun, 15 Feb 2004 00:45:47 +0100, Yann-Erwan Perio
<y-*******@em-lyon.com> wrote:
Hm no, since the span is contained within the blockquote, the
mouseout handler is stopped in time (thanks to the event management
system). [...]
In my attempt, that wasn't the issue: I have the same structural layout as
the OP and you. The only major difference is that I used DOM Event methods
when available, and on<event> properties when not. When the former is in
use, passing the cursor between the quote and the link moves it into a
no-man's-land, firing the mouseout event and deleting the node.
Web browsers are event-driven environments, so it's better to use events
(it's not impossible to obtain satisfying solutions with timers, but
they're generally not as reliable, and certainly more difficult to set
up).


I didn't want to use timers - I would have much prefered to depend upon
the event model. Unfortunately, circumstances prevented that.
The problem with this is that references passed to setTimeout are out
of scope by the time the timer expires.


Then, if you're not already familiar with them, it's maybe time for you
to get into closures:-)


I know of them, but they're rarely mentioned in an instructional context
(that is, no books or references). If you know of some good resources, I'd
be interested.

Mike

--
Michael Winter
M.******@blueyonder.co.invalid (replace ".invalid" with ".uk" to reply)
Jul 20 '05 #12

P: n/a
On Sun, 15 Feb 2004 17:43:38 +0100, Yann-Erwan Perio
<y-*******@em-lyon.com> wrote:
Michael Winter wrote:
The only major difference is that I used DOM Event methods when
available, and on<event> properties when not. When the former is in
use, passing the cursor between the quote and the link moves it into a
no-man's-land, firing the mouseout event and deleting the node.
To me, the way a handler is set shouldn't normally matter,


I wouldn't have thought so, either.
be it using "addEventListener" or on<event> (apart from the "this"
value not being set with "attachEvent"). The mouse(out|over) events are
normally fired in all cases, and the related target analysis occurs in
the event handler (depending on whether the event comes from or goes to
a contained element, the according code is executed).

I may be misunderstanding the problem though, so if you have a piece of
code demonstrating the issue I'd be happy to have a closer look (you may
have bumped into an Opera bug:-)).
Possibly. The offending code behaves "normally" in Mozilla and Netscape,
but not in Opera. Furthermore, I wrote a second example page which uses
intrinsic events (in HTML, not with properties) and works "normally" in
all three. I'd rather think that I did something odd, though; I'm not too
used to using DOM Events. By the way, "normally" would be a flickering,
but still visible, link.

I've uploaded the two examples and can be accessed with the addresses
below. Don't bother using IE or some other non-compliant browser: it will
error.

Using the DOM:

http://www.mlwinter.pwp.blueyonder.c...cite/cite.html

Using intrinsic events:

http://www.mlwinter.pwp.blueyonder.c...ite/cite2.html

[snip]
Unfortunately you're right, there aren't that many resources available
on the subject. It seems that most people using closures in javascript
have some kind of "functional programming" background, re-applying
effectively the associated patterns to javascript - but there are few
articles dealing specifically with closures in javascript!

Still, I'm aware of many must-read papers, by Richard Cornford and
Douglas Crockford:

<URL:http://www.litotes.demon.co.uk/js_info/private_static.html>
<URL:http://www.crockford.com/#javascript>
I've read some of what they have written in the past, but not regarding
closures. I'll take another look.
If you have some time, then I also suggest your investigating the
excellent TimedQue component by Richard:

<URL:http://groups.google.com/groups?selm=bphvt9%249je%241%248302bc10%40news.dem on.co.uk>


I shall give that a once over, too.

Thank you for your help, and Mr Cornford's and Mr Crockford's for their
publications.

Mike

--
Michael Winter
M.******@blueyonder.co.invalid (replace ".invalid" with ".uk" to reply)
Jul 20 '05 #13

P: n/a
Michael Winter wrote:
Possibly. The offending code behaves "normally" in Mozilla and Netscape,
but not in Opera.
That it behaves differently in Mozilla and Opera shows that one of them
is wrong, but in the case you've pointed out, I believe that Opera is
correct (and that Mozilla is NOT).
http://www.mlwinter.pwp.blueyonder.c...cite/cite.html


The problem is related to the event phase; since you have flagged the
"useCapture" argument as true, the handler is attached for the capture
phase, not the bubble phase. It would make more sense to attach the
listener to the bubbling phase, so using "false" for the third argument
(that would be compliant with the on<event> listener which is by default
set for the bubbling phase, or IE's attachEvent, which is also for the
bubble phase by defaut - and this would happen to give the expected
results).
When you click on your element, an event is created, with the
appropriate properties from the Event interface (target, eventPhase,
stopPropagation...), the UIEvent interface, and the MouseEvent interface
(clientX, screenX...). After the event is created/inited, it has to be
dispatched - this is called the event flow.

The event flow has three phases:
[1] the capturing phase, in which the event originates from the root
element and goes to the target, visiting all intermediate nodes,
triggering all *capturing* event listeners defined on the current target
(the node being visited),
[2] the "at target" phase, where the event is on the target, triggering
all *non-capturing* event listeners defined on the current target (which
is the target here),
[3] the "bubbling phase", where the event comes back to the root
element, following the same path as in the capturing phase, but in
reverse order, triggering all *non-capturing* event listeners defined on
the current target.

In your script, if you first mouseover the *text* in your blockquote,
then the following things happen:
- a mousevent is created and dispatched from the root element,
- it enters the capturing phase and heads towards the text node,
- it reaches the blockquote, execute the event listener (since there is
a mouseover handler available), and goes on,
- it reaches the target (the text node), does nothing,
- it bubbles back to the root element (triggering nothing, your
mouseover handler is for the capturing phase, not the bubbling phase).

If we now mouse slowly towards the left span, we'll be eventually doing
the following:

[1] mouseout from the P element:
- the event is inited, goes down towards the P element,
- it triggers on the way the mouseout handler for the blockquote
(since there is a mouseover handler available), which results into the
span removal,
- it goes on to the P, does nothing,
- it bubbles back to the root element, also doing nothing (your
mouseout handler is for the capturing phase, not the bubbling phase).

[2] mouseover the *blockquote* element:
- a mousevent is created and dispatched from the root element,
- it enters the capturing phase and heads towards the blockquote,
- it reaches the blockquote (so we are at the "at target" phase), but
does *not* execute the mouseover handler, since, as per the specs, <q>a
capturing EventListener will not be triggered by events dispatched
directly to the EventTarget upon which it is registered.</q>,
- it bubbles back to the root element (triggering nothing).

As a consequence, the span isn't added back. Opera's behavior is
therefore compliant with the W3C specs, while Mozilla's one is not.
Interestingly, the eventPhase values are set incorrectly in Mozilla for
the capturing phase (indicating AT_TARGET while it should be CAPTURING).

As a conclusion, don't use the capturing phase here:-) (all the more IE
doesn't support it directly with attachEvent, though offering
proprietary methods IIRC).
Regards,
Yep.

---
Quotes are taken from:
<URL:http://www.w3.org/TR/2000/REC-DOM-Level-2-Events-20001113/events.html>
Jul 20 '05 #14

P: n/a
"Michael Winter" <M.******@blueyonder.co.invalid> wrote in message
news:op**************@news-text.blueyonder.co.uk...
<snip>
<URL:http://groups.google.com/groups?selm=
bphvt9%249je%241%248302bc10%40news.demon.co.uk>
I shall give that a once over, too.
While you are at it you might like to look at its origins, in
a thread with the subject "closures, what are they good for?":-

<URL: "http://groups.google.com/groups?threadm=
b8dshd%24d46%241%248302bc10%40news.demon.co.uk >

- as it also has other closure related material (though google
failed to pick up two of the posts to the thread).
Thank you for your help, and Mr Cornford's and Mr Crockford's
for their publications.


Speaking for myself, you are welcome (but I wish you wouldn't
be so formal with may name (at least when it wouldn't be ambiguous)).

Richard.
Jul 20 '05 #15

This discussion thread is closed

Replies have been disabled for this discussion.