...

View Full Version : pointer to document methods throw exception in moz



subhailc
08-27-2006, 08:06 PM
in moz/nn, this errors
var el = document.getElementById;
why?

pointers to core classes and/or singletons seem fine; this works for example
var ord = String.fromCharCode;
alert(ord(100));

Kor
08-28-2006, 12:25 PM
Not enough code and rather confusing. Can you detail a little bit? What does not work and what error do you get?

subhailc
08-28-2006, 02:17 PM
when referencing method pointer in mozilla/nn, this error occurs:
Error: uncaught exception: [Exception... "Illegal operation on WrappedNative prototype object" nsresult: "0x8057000c (NS_ERROR_XPC_BAD_OP_ON_WN_PROTO)" location: "JS frame :: anonymous :: line 9" data: no]
this only happens when referencing document or window methods - e.g., the following fail:

var a = document.getElementById;
alert(a("bob").tagName);
var b = document.getElementsByTagName;
alert(b("p").length);

these work fine

var a = String.fromCharCode;
alert(a(100));
var b = Math.round;
alert(b(12.34234));
var c = Array.prototype.sort;
alert(c.call([1,"a","z","m",10]));
var d = {e:{f:{g:{h:{i:function(args){return args;}}}}}};
var j = d.e.f.h.i;
alert(j("..."));

i'm not looking for a solution - i'd like to know why, purely for edification.

tyia.

Kor
08-28-2006, 05:21 PM
var a = document.getElementById
and
var b = document.getElementsByTagName
can not be objects, as long as you have not gave them valid id's and names.

jkd
08-29-2006, 06:03 AM
My educated guess:

When you do var x = document.getElementById and then x("hello") you are executing the function x in the context of the window object instead of the document object. Gecko probably utilizes the scoping of the document object to access some internal methods to execute getElementById, which the window object doesn't have. If you must do shortcuts like that, do:


function x(id) {
return document.getElementById(id);
}

subhailc
08-29-2006, 06:03 AM
um... id's and names? i'm not trying to retrieve an element, i'm trying to aim a pointer at the methods.



var bob = new Object();
bob.somemethod = function(a,b,c){return a + b + c;};

var shortcut = bob.somemethod;

alert(shortcut(1,2,3)); // outputs 6

subhailc
08-29-2006, 06:11 AM
jkd - thanks for the response. that was my first guess too, but even explicitly referencing document and window, it fails - there's nothing in the error that pertains to anything but mozilla's engine.

i've looked into the error message a bit more since, and it seems that there's no reason for it not to work - from everything i've seen it's nothing more glamorous than either a) a mistake, or b) deliberate non-compliant behavior specific to gecko. the more i get to know the moz/nn set up, the less i like it.

jkd
08-29-2006, 04:06 PM
a) a mistake, or b) deliberate non-compliant behavior specific to gecko. the more i get to know the moz/nn set up, the less i like it.

There is nothing standardized about that sort of behavior.

You could always do:

var x = document.getElementById;
var myElement = x.call(document, "hello");

subhailc
08-30-2006, 01:31 PM
nothing standardized about pointers? not in the document / browser-centric oop model, but that's just a (limited) implementation of the language - and seems to be one that causes a great deal of aggravation to users, myself included. the object model provides no tangible advantage, and offers only alleged transparency and intuitivity in lieu of functionality - a uneven trade at best, certainly when it seems that the reality has fallen far short of the ambition.

a method is a property of an object. you can reference any property of any object with declaration and simple assignment. for moz to supercede that in regard to certain arbitrary conditions is non-standard behavior.

Kor
08-30-2006, 04:26 PM
nothing standardized about pointers? not in the document / browser-centric oop model, but that's just a (limited) implementation of the language - and seems to be one that causes a great deal of aggravation to users, myself included. the object model provides no tangible advantage, and offers only alleged transparency and intuitivity in lieu of functionality - a uneven trade at best, certainly when it seems that the reality has fallen far short of the ambition.

a method is a property of an object. you can reference any property of any object with declaration and simple assignment. for moz to supercede that in regard to certain arbitrary conditions is non-standard behavior.

Oh, but there is a good standard, JSON. Using JSON every method, variable, function, object is treated like an objects' property:


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Untitled Document</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta http-equiv="Content-Style-Type" content="text/css">
<meta http-equiv="Content-Script-Type" content="text/javascript">
<script type="text/javascript">
function showT(id){
var method='getElementById'
alert(document[method](id).innerHTML)
}
onload=function(){showT('mydiv')}
</script>
</head>
<body>
<div id="mydiv">text</div>
</body>
</html>

jkd
08-30-2006, 05:47 PM
a method is a property of an object. you can reference any property of any object with declaration and simple assignment. for moz to supercede that in regard to certain arbitrary conditions is non-standard behavior.

Yes, and as a property of an object, it is well-justified in requiring that it is executed in the context of its object's scope. There is no distinction between methods and functions in Javascript, so it needs the scope to know what to operate on. Mozilla isn't superceding anything, working as expected. There can be multiple document objects in a scripting environment, so one would expect there to be a dynamic reference to it at some point. Besides, I gave you code to get around this problem.

Alternatively:


(function(f) {
document.__defineGetter__("getElementById", function() {
return function(id) {
return f.call(document, id);
}
});
})(document.getElementById);


If you must have it your way, you can always create closures around the methods and overload the properties to return those instead of the default methods.

Kor
08-30-2006, 05:49 PM
JSON looks simplier then a closure...

jkd
08-30-2006, 07:47 PM
JSON looks simplier then a closure...

But it doesn't cache the lookup. Microsoft pushed out an article recently with some DOM-tips for IE, and it mainly had to do with caching DOM objects and methods, since the DOM is implemented in a very strange way in IE (methods aren't actually Functions, objects aren't actually Objects, etc). Using the array notation just looks up the method every time, whereas storing document.getElementById keeps it ready to use at any time.

subhailc
08-30-2006, 08:18 PM
Besides, I gave you code to get around this problem.

i'm not looking for a solution - i'd like to know why, purely for edification.

tyia.
the point isn't how to get around it - it's only a pointer - you get around it by writing it verbosely. don't get your panties in a bunch because i bring to light one of the (myriad) flaws in the board's pet browser.






Yes, and as a property of an object, it is well-justified in requiring that it is executed in the context of its object's scope.and how's that compromised by making it available to a pointer, like every/any other object?






There is no distinction between methods and functions in Javascriptobviously, and not at all relevant. note
var a = String.fromCharCode;
alert(a(100));
var b = Math.round;
alert(b(12.34234));
var c = Array.prototype.sort;
alert(c.call([1,"a","z","m",10]));
var d = {e:{f:{g:{h:{i:function(args){return args;}}}}}};
var j = d.e.f.h.i;
alert(j("..."));






so it needs the scope to know what to operate onlol






Mozilla isn't superceding anythingum... it's written it's interpereter to handle arbitrary conditions with arbitrary instructions. every other object instantiation obeys the rules; by allowing/forcing the document object to behave differently, you've created the problem mozilla-lemmings have accussed IE of for years (btw, IE behaves appropriately as regards this.)






working as expectednot expected by anyone who realizes js!=dom.






There can be multiple document objects in a scripting environment, so one would expect there to be a dynamic reference to it at some pointand there won't be multiples of any other kind of object?






If you must have it your waywhy are you being discourteous? did i hurt your feelings?





bottom line: it doesnt need to be treated differently (e.g., IE); doing so limits rather than enriches the scripting environment, and creates implementation-specific idiosyncracies that're supposed to be the antithesis of the whole standards 'movement'.

Kor
08-30-2006, 08:55 PM
But it doesn't cache the lookup. Microsoft pushed out an article recently with some DOM-tips for IE, and it mainly had to do with caching DOM objects and methods, since the DOM is implemented in a very strange way in IE (methods aren't actually Functions, objects aren't actually Objects, etc). Using the array notation just looks up the method every time, whereas storing document.getElementById keeps it ready to use at any time.

Yes and no. Caching methods/elements might lead to a lack of memory, and IE is wellknown for this habbit when using closures.

jkd
08-30-2006, 10:38 PM
Yes and no. Caching methods/elements might lead to a lack of memory, and IE is wellknown for this habbit when using closures.

http://blogs.msdn.com/ie/archive/2006/08/28/728654.aspx
I was only repeating what they recommended. :)


subhailc, calm down. My post was courteous, and Firefox is not this board's "pet browser". I've in fact been using Opera for quite some time, I'm simply trying to explain to you how Javascript works.

The only difference between:

doSomething()
and:

document.doSomething()
as far as Javascript execution is concerned is that the internal this argument is passed different values, the former getting the window object and the latter getting the document object.

If it helps, imagine every single function in the language accepting a hidden parameter, "this":


function helloWorld(str) {
alert(str);
}

Is silently rewritten to:


function helloWorld(this, str) {
alert(str);
}


(That is how Python does it with methods, except that the argument is called "self".) Now:

someObject.helloWorld("hi")
Silently rewrites to:

helloWorld(someObject, "hi")

To explicitly change what object is being passed as the this argument, Javascript provides you with call and apply methods to instances of the Function object.

With that said, document.getElementById is simply whatever is stored at Document.prototype.getElementById (because of the prototype chain lookup that defines Javascript's Object Oriented abilities). It's not tied in any special way to the actual instance variable document. Thus, when you store document.getElementById, you're just storing the reference to Document.prototype.getElementById (or perhaps there is a more localized copy for HTML documents in HTMLDocument.prototype), which is completely agnostic to which particular instance you are operating on, and therefore requires knowledge of what object to operate on. Safari and Opera also fail in exactly the same way Firefox does in this particular scenario.

Internet Explorer must do funky things with internally creating closures to maintain the document reference, but that probably has to do with the bizarro COM object implementation that it utilizes, which doesn't follow the same rules as any other Javascript object. (And this is not necessarily a criticism, just a statement of the differences.)

Thus, the correct way as far as Javascript is concerned of doing this is to store the function in a variable and utilize either its call or apply methods. That, or store the reference in some closure and do it that way. The code works in IE as it is due to its DOM objects not actually being Javascript objects.

As for your DOM!=JS, or course it doesn't. DOM is an API, Javascript a language. However, as a Javascript developer (or a developer for any language), anything that an API exposes is expected to follow the same rules as the language you are working in. So infact, IE's behavior is the surprising and unexpected one, not everybody elses behavior.

jkd
08-30-2006, 10:49 PM
Also, to demonstrate that Firefox/Opera/Safari's behavior is expected (if the scoping arguments weren't sufficient):



function Example(str) {
this.__internalString__ = str;
this.publicMethod = function() {
alert(this.__internalString__);
}
}

var obj = new Example("hello world");
var x = obj.publicMethod;
x();


That code fails to work, because publicMethod loses the object context when it is stored into the variable x, so it cannot find __internalString__ anymore.

Kor
08-30-2006, 10:59 PM
eeer ... and JSON does not store functions in a variable (in fact is rather an object's property)?


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Untitled Document</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta http-equiv="Content-Style-Type" content="text/css">
<meta http-equiv="Content-Script-Type" content="text/javascript">
<script type="text/javascript">
var func='blah';
function blah(){
alert('here I am')
}
</script>
</head>
<body>
<span onclick="window[func]()">click</span>
</body>
</html>

... or I lost the main ideea of the thread, did I?

liorean
08-30-2006, 11:33 PM
subhailc: Something you have to realise when it comes to this is that there are two aspects at work here:

Why ECMAScript natives work like they do: ECMAScript built-in object members have defined algorithms that won't change when this doen't reference the original object any longer.
ECMAScript built-in object prototype members are generally made to be generic. Thus, you can apply most of the methods of built-in objects with this referencing pretty much any object that is sufficiently similar as to make no difference to the defined algorithm.
ECMAScript built-in object members, as differentiated from built-in object prototype members, are each made to perform a specific task that doesn't have to take this into consideration since they always do the same thing regardless.

Why DOM host object members work like they do: DOM host object prototype members are not generally made to be generic - they are simply located on the appropriate interface.
In the browser, you are always operating on an instance of a DOM interface, one of many possible such objects in the same scripting context. Thus, you don't use the Document object, you use the document object which is only one of many possible instances of the Document object.
That means all DOM methods you're using in the browser are DOM host object prototype members, not DOM host object members. They are all inherited, and thus they rely on this to reference the object on which they are to operate.
Which means that if you reference just the method, without an appropriate this reference, the browser will try to use the global object as the this object, which doesn't make any sense for most DOM methods.




Still, there's something you should report in bugzilla here if it's not already in there:

Error: uncaught exception: [Exception... "Illegal operation on WrappedNative prototype object" nsresult: "0x8057000c (NS_ERROR_XPC_BAD_OP_ON_WN_PROTO)" location: "JS frame :: anonymous :: line 9" data: no]
This is an uncaught internal exception - which means some internal function isn't doing it's exception handling right. The correct behaviour would probably be to throw some kind of DOMException, maybe an INVALID_ACCESS_ERR, a NOT_SUPPORTED_ERR or a TYPE_MISMATCH_ERR. I'm not really sure. The DOM error handling doesn't (from my glance reading of the [DOM3Core] (http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/) spec anyway) at all take into account the possibility of trying to use a member of an interface on an object that is not an instance of that interface.



EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum