Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

JavaScript ajax library critique

11 views
Skip to first unread message

Mychal Hackman

unread,
Dec 22, 2009, 3:25:42 PM12/22/09
to
I am a new JavaScript programmer. In training I was introduced to
Prototype and in the first ~8 months of my job I heavily relied on it.
Over time I realized how ridiculous it was to include over 4000 lines
of code for event handling and XHR. (As well as I didn't think script
errors on every page seemed professional.)

I've started writing my own library, and I originally attempt to make
it appear similar to Prototype, in the hopes that I could easily get
the other developers off Prototype and eventually improve our site.

The following is the "Ajax" section of the code, and I would greatly
appreciate (and request) critiques of the code from the group.

Ajax = {
transport : (function(){
if(window.XMLHttpRequest){
return new XMLHttpRequest();
}else if(window.ActiveXObject){
return new ActiveXObject('Microsoft.XMLHTTP');
}else{
return false;
}
})(),

encodeURIParams : function(params){
var url='',
noCACHE = Math.random()*10e17,
key, i;

for(key in params){
if(params.hasOwnProperty(key) && key != 'noCACHE'){
//in the case of a select multiple
if(typeof params[key] == 'object' &&
params[key] instanceof Array){
for(i = params[key].length; i--;){
url += encodeURIComponent(key) + '=' +
encodeURIComponent(params[key][i])+'&';
}

}else{
url += encodeURIComponent(key) + '=' +
encodeURIComponent(params[key])+'&';
}
}
}

if(!params.hasOwnProperty('noCACHE')){
url += 'noCACHE='+noCACHE;
}else{
url = url.substring(0, url.length-1);
}

return url;
},

Request : function(url, params, onsuccess, method){
var xhr = Ajax.transport,
res = '',
post = null;

xhr.onreadystatechange = function(){
if(onsuccess && xhr.readyState==4){
res = xhr.responseText ||
xhr.responseJSON ||
xhr.responseXML;

onsuccess(res);
}
};

if(method && method.toUpperCase() == 'POST'){
params.noCACHE = false;
post = Ajax.encodeURIParams(params);
xhr.open(method, url, true);
xhr.setRequestHeader('Content-type', 'application/x-www-
form-urlencoded');
xhr.setRequestHeader('Content-length', post.length);
xhr.setRequestHeader('Connection', 'close');
}else{
method = 'GET';
xhr.open(method, url+'?'+Ajax.encodeURIParams(params),
true);
}
xhr.send(post);
}
}

David Mark

unread,
Dec 22, 2009, 4:20:04 PM12/22/09
to
On Dec 22, 3:25 pm, Mychal Hackman <mycha...@gmail.com> wrote:
> I am a new JavaScript programmer. In training I was introduced to
> Prototype and in the first ~8 months of my job I heavily relied on it.
> Over time I realized how ridiculous it was to include over 4000 lines
> of code for event handling and XHR. (As well as I didn't think script
> errors on every page seemed professional.)

No question. But these days it is typically jQuery fouling up behind
the scenes, not Prototype.

>
> I've started writing my own library, and I originally attempt to make
> it appear similar to Prototype, in the hopes that I could easily get
> the other developers off Prototype and eventually improve our site.

I sure wouldn't copy Prototype's much-maligned design.

>
> The following is the "Ajax" section of the code, and I would greatly
> appreciate (and request) critiques of the code from the group.
>
> Ajax = {
>     transport : (function(){
>         if(window.XMLHttpRequest){

Bad feature detection. Use typeof (or a wrapper like isHostMethod).

>             return new XMLHttpRequest();
>         }else if(window.ActiveXObject){
>             return new ActiveXObject('Microsoft.XMLHTTP');

You need a try-catch around this (ActiveX is easily disabled) and
there are more ID's to consider.

>         }else{
>             return false;
>         }
>     })(),
>
>     encodeURIParams : function(params){
>         var url='',
>             noCACHE = Math.random()*10e17,

Why? There are headers for this.

>             key, i;
>
>         for(key in params){
>             if(params.hasOwnProperty(key) && key != 'noCACHE'){

Don't use hasOwnProperty as it isn't supported by Safari 2 (for
example). Use a wrapper like isOwnProperty.


>                 //in the case of a select multiple
>                 if(typeof params[key] == 'object' &&
>                     params[key] instanceof Array){

Don't use instanceof for this (and don't design code that must
discriminate between Array objects and Object objects). What other
sort of object could this be anyway?


>                     for(i = params[key].length; i--;){
>                         url += encodeURIComponent(key) + '=' +
>                             encodeURIComponent(params[key][i])+'&';
>                     }
>
>                 }else{
>                     url += encodeURIComponent(key) + '=' +
>                         encodeURIComponent(params[key])+'&';
>                 }
>             }
>         }

Faster to push the names, values and separators to an array and then
join with "".

>
>         if(!params.hasOwnProperty('noCACHE')){

See above. And if it does _not_ have this property, wouldn't that
mean to cache? It's very confusing to have this magic parameter in
with the rest of the data. Also, the caching behavior for XHR GET's
varies cross-browser (IE doesn't bother to check freshness).

>             url += 'noCACHE='+noCACHE;

Never do this. Certainly not for data that will be POSTed.

>         }else{
>             url = url.substring(0, url.length-1);
>         }
>
>         return url;
>     },
>
>     Request : function(url, params, onsuccess, method){

This is not a constructor.

>         var xhr = Ajax.transport,

Do you really need a "namespace" for this?

>             res = '',
>             post = null;
>
>         xhr.onreadystatechange = function(){
>             if(onsuccess && xhr.readyState==4){
>                 res = xhr.responseText ||
>                       xhr.responseJSON ||
>                       xhr.responseXML;

This is bizarre.

>
>                 onsuccess(res);
>             }
>         };
>
>         if(method && method.toUpperCase() == 'POST'){
>             params.noCACHE = false;

What does this mean, caching is true for POST's? I doubt it. :)

>             post = Ajax.encodeURIParams(params);

But you put the cache-buster BS in there!

>             xhr.open(method, url, true);
>             xhr.setRequestHeader('Content-type', 'application/x-www-
> form-urlencoded');
>             xhr.setRequestHeader('Content-length', post.length);
>             xhr.setRequestHeader('Connection', 'close');

Why add these headers?

>         }else{
>             method = 'GET';
>             xhr.open(method, url+'?'+Ajax.encodeURIParams(params),
> true);

What if the URI already had a query part?

>         }
>         xhr.send(post);

Need a try-catch around that.

>     }
>
> }

Will leak memory in IE too. You need to set onreadystatechange to an
empty function when done.

The people you are trying to get off Prototype will complain that you
are "reinventing the wheel". For them there are only two choices: use
a ridiculously complex and ineffectual library or write _everything_
from scratch. You need to find some middle ground (e.g. download a
solid XHR wrapper to start with).

Garrett Smith

unread,
Dec 22, 2009, 7:45:40 PM12/22/09
to
Mychal Hackman wrote:
> I am a new JavaScript programmer. In training I was introduced to
> Prototype and in the first ~8 months of my job I heavily relied on it.
> Over time I realized how ridiculous it was to include over 4000 lines
> of code for event handling and XHR. (As well as I didn't think script
> errors on every page seemed professional.)
>
> I've started writing my own library, and I originally attempt to make
> it appear similar to Prototype, in the hopes that I could easily get
> the other developers off Prototype and eventually improve our site.
>
> The following is the "Ajax" section of the code, and I would greatly
> appreciate (and request) critiques of the code from the group.
>
> Ajax = {
> transport : (function(){
> if(window.XMLHttpRequest){
> return new XMLHttpRequest();
> }else if(window.ActiveXObject){
> return new ActiveXObject('Microsoft.XMLHTTP');
> }else{
> return false;
> }
> })(),
>

Be careful to avoid potential circular reference of Host object to
JScript object. You have Ajax.transport -> Host object...

> encodeURIParams : function(params){
> var url='',
> noCACHE = Math.random()*10e17,
> key, i;
>
> for(key in params){

What is - params - ? Is it a native ECMAScript object? If so, and if
you're not modifying object.prototype, you can ditch the call to
hasOwnProperty.


> if(params.hasOwnProperty(key) && key != 'noCACHE'){
> //in the case of a select multiple
> if(typeof params[key] == 'object' &&
> params[key] instanceof Array){
> for(i = params[key].length; i--;){

// Move the repeated encodeURIComponent(key) outside the loop and
// save the result in a variable (like encodedKey).

> url += encodeURIComponent(key) + '=' +
> encodeURIComponent(params[key][i])+'&';
> }
>
> }else{
> url += encodeURIComponent(key) + '=' +
> encodeURIComponent(params[key])+'&';
> }
> }
> }
>

Avoid the if else. Make

> if(!params.hasOwnProperty('noCACHE')){
> url += 'noCACHE='+noCACHE;
> }else{
> url = url.substring(0, url.length-1);
> }
>
> return url;
> },
>
> Request : function(url, params, onsuccess, method){
> var xhr = Ajax.transport,
> res = '',
> post = null;
>
> xhr.onreadystatechange = function(){

I believe you have created a circular reference here.

xhr has an onreadystatechange, which has xhr.

setting xhr = null will not solve the problem here. onreadystatechange
has Ajax.transport in scope chain.

Ajax.transport -> onreadystatechange -> [[Scope]] -> Ajax.transport.


> if(onsuccess && xhr.readyState==4){
> res = xhr.responseText ||
> xhr.responseJSON ||
> xhr.responseXML;
>
> onsuccess(res);
> }
> };

Why not just use responseText?

What if responseText is ""?

What is responseJSON?

> if(method && method.toUpperCase() == 'POST'){
> params.noCACHE = false;

Caching can be useful at times. Consider an application where the user
enters home zip, looks at result, then tries work zip code, looks at
result, then re-enters home zip. The home zip being cached would be useful.
--
Garrett
comp.lang.javascript FAQ: http://jibbering.com/faq/

Garrett Smith

unread,
Dec 22, 2009, 7:50:49 PM12/22/09
to
David Mark wrote:
> On Dec 22, 3:25 pm, Mychal Hackman <mycha...@gmail.com> wrote:

[...]

>
> Will leak memory in IE too. You need to set onreadystatechange to an
> empty function when done.
>

(Such as Function.prototype)

Thomas 'PointedEars' Lahn

unread,
Dec 22, 2009, 8:22:30 PM12/22/09
to
Garrett Smith wrote:

> Mychal Hackman wrote:
>> Ajax = {
>> transport : (function(){
>> if(window.XMLHttpRequest){
>> return new XMLHttpRequest();
>> }else if(window.ActiveXObject){
>> return new ActiveXObject('Microsoft.XMLHTTP');
>> }else{
>> return false;
>> }
>> })(),
>
> Be careful to avoid potential circular reference of Host object to
> JScript object. You have Ajax.transport -> Host object...

Where is the circular reference? And how would you avoid it, then?


PointedEars
--
var bugRiddenCrashPronePieceOfJunk = (
navigator.userAgent.indexOf('MSIE 5') != -1
&& navigator.userAgent.indexOf('Mac') != -1
) // Plone, register_function.js:16

David Mark

unread,
Dec 22, 2009, 8:53:22 PM12/22/09
to
On Dec 22, 7:45 pm, Garrett Smith <dhtmlkitc...@gmail.com> wrote:
> Mychal Hackman wrote:
> > I am a new JavaScript programmer. In training I was introduced to
> > Prototype and in the first ~8 months of my job I heavily relied on it.
> > Over time I realized how ridiculous it was to include over 4000 lines
> > of code for event handling and XHR. (As well as I didn't think script
> > errors on every page seemed professional.)
>
> > I've started writing my own library, and I originally attempt to make
> > it appear similar to Prototype, in the hopes that I could easily get
> > the other developers off Prototype and eventually improve our site.
>
> > The following is the "Ajax" section of the code, and I would greatly
> > appreciate (and request) critiques of the code from the group.
>
> > Ajax = {
> >     transport : (function(){
> >         if(window.XMLHttpRequest){
> >             return new XMLHttpRequest();
> >         }else if(window.ActiveXObject){
> >             return new ActiveXObject('Microsoft.XMLHTTP');
> >         }else{
> >             return false;
> >         }
> >     })(),
>
> Be careful to avoid potential circular reference of Host object to
> JScript object. You have Ajax.transport -> Host object...

It's the start of a chain.

Yes.

[xmlhttp]--readystatechange-->[anon function]-->[Activation Object]-->
[xmlhttp]

But this is unrelated to the previously mentioned (partial) chain.

>
> xhr has an onreadystatechange, which has xhr.
>
> setting xhr = null will not solve the problem here. onreadystatechange
> has Ajax.transport in scope chain.

That won't solve the problem because it will blow up in IE6. You have
to set it to a Function object (preferably an empty one).

>
> Ajax.transport -> onreadystatechange -> [[Scope]] -> Ajax.transport.

No. Ajax is global. It's not referenced by the local Activation
Object. If it were, virtually everything would leak (think about it).

>
> >             if(onsuccess && xhr.readyState==4){
> >                 res = xhr.responseText ||
> >                       xhr.responseJSON ||
> >                       xhr.responseXML;
>
> >                 onsuccess(res);
> >             }
> >         };
>
> Why not just use responseText?

You might want the XML.

onsuccess(xhr.resonseText, xhr.responseXML);

Or just:-

onsuccess(xhr);

>
> What if responseText is ""?

Nothing good. :)

>
> What is responseJSON?

Who knows? Something Prototype does?

>
> >         if(method && method.toUpperCase() == 'POST'){
> >             params.noCACHE = false;
>
> Caching can be useful at times. Consider an application where the user
> enters home zip, looks at result, then tries work zip code, looks at
> result, then re-enters home zip. The home zip being cached would be useful.

Caching POST's? I don't follow. And caching GET's is a major pain
because of IE's problems. So caching XHR is best avoided.

David Mark

unread,
Dec 22, 2009, 8:53:57 PM12/22/09
to
On Dec 22, 7:50 pm, Garrett Smith <dhtmlkitc...@gmail.com> wrote:
> David Mark wrote:
> > On Dec 22, 3:25 pm, Mychal Hackman <mycha...@gmail.com> wrote:
>
> [...]
>
>
>
> > Will leak memory in IE too.  You need to set onreadystatechange to an
> > empty function when done.
>
> (Such as Function.prototype)

That's an interesting idea. I've always used an empty function.

Mychal Hackman

unread,
Dec 22, 2009, 8:54:04 PM12/22/09
to
On Dec 22, 2:20 pm, David Mark <dmark.cins...@gmail.com> wrote:
> On Dec 22, 3:25 pm, Mychal Hackman <mycha...@gmail.com> wrote:
>
> > Over time I realized how ridiculous it was to include over 4000 lines
> > of code for event handling and XHR. (As well as I didn't think script
> > errors on every page seemed professional.)
>
> No question.  But these days it is typically jQuery fouling up behind
> the scenes, not Prototype.
>
Yeah, that has been recommended to me quite often lately.

>
>
> Bad feature detection.  Use typeof (or a wrapper like isHostMethod).
>
> >             return new XMLHttpRequest();
> >         }else if(window.ActiveXObject){
> >             return new ActiveXObject('Microsoft.XMLHTTP');
>
> You need a try-catch around this (ActiveX is easily disabled) and
> there are more ID's to consider.

I recall having trouble finding information about the ID's, and what
the differences were.


>
> >     encodeURIParams : function(params){
> >         var url='',
> >             noCACHE = Math.random()*10e17,
>
> Why?  There are headers for this.
>

I have removed the noCACHE parts, caching will be prevented if
necessary by setting the headers server-side.

>
> Don't use hasOwnProperty as it isn't supported by Safari 2 (for
> example).  Use a wrapper like isOwnProperty.

Thanks, I'll look into that.


>
> >                 //in the case of a select multiple
> >                 if(typeof params[key] == 'object' &&
> >                     params[key] instanceof Array){
>
> Don't use instanceof for this (and don't design code that must
> discriminate between Array objects and Object objects).  What other
> sort of object could this be anyway?
>

Good question...


>
> Faster to push the names, values and separators to an array and then
> join with "".

Makes sense.


>
> >     Request : function(url, params, onsuccess, method){
>
> This is not a constructor.

Sorry, I don't follow here. Can you elaborate please?

> >         xhr.onreadystatechange = function(){
> >             if(onsuccess && xhr.readyState==4){
> >                 res = xhr.responseText ||
> >                       xhr.responseJSON ||
> >                       xhr.responseXML;
>
> This is bizarre.

Agreed. Not sure where responseJSON even came from...


>
> >             xhr.open(method, url, true);
> >             xhr.setRequestHeader('Content-type', 'application/x-www-
> > form-urlencoded');
> >             xhr.setRequestHeader('Content-length', post.length);
> >             xhr.setRequestHeader('Connection', 'close');
>
> Why add these headers?

Removed last two. Obviously wasn't thinking (just following blindly).


>
>
> Will leak memory in IE too.  You need to set onreadystatechange to an
> empty function when done.

Thanks again. I will have to read about circular references in IE and
try to understand this more clearly.


>
> a ridiculously complex and ineffectual library or write _everything_
> from scratch.

Writing some of this will (hopefully) give me a better understanding
of the language and improve my skills as a programmer.

David Mark

unread,
Dec 22, 2009, 8:54:21 PM12/22/09
to
On Dec 22, 8:22 pm, Thomas 'PointedEars' Lahn <PointedE...@web.de>
wrote:

> Garrett Smith wrote:
> > Mychal Hackman wrote:
> >> Ajax = {
> >>     transport : (function(){
> >>         if(window.XMLHttpRequest){
> >>             return new XMLHttpRequest();
> >>         }else if(window.ActiveXObject){
> >>             return new ActiveXObject('Microsoft.XMLHTTP');
> >>         }else{
> >>             return false;
> >>         }
> >>     })(),
>
> > Be careful to avoid potential circular reference of Host object to
> > JScript object. You have Ajax.transport -> Host object...
>
> Where is the circular reference?  And how would you avoid it, then?
>

There is none and there would be no way to avoid it if there was.

Thomas 'PointedEars' Lahn

unread,
Dec 22, 2009, 9:20:30 PM12/22/09
to
David Mark wrote:

> Garrett Smith wrote:
>> David Mark wrote:


>> > Mychal Hackman wrote:
>> >> [...]
>> > Will leak memory in IE too. You need to set onreadystatechange to an
>> > empty function when done.
>>
>> (Such as Function.prototype)
>
> That's an interesting idea. I've always used an empty function.

There is also a subtle difference between ES3F and ES5 that challenges
whether using `Function.prototype' here is still a viable approach:

,-[ECMAScript Language Specification, Edition 3 Final]
|
| 15.3.4 Properties of the Function Prototype Object
|
| The Function prototype object is itself a Function object (its [[Class]]
| is "Function") that, when invoked, accepts any arguments and returns
| undefined.
|
| The value of the internal [[Prototype]] property of the Function prototype
| object is the Object prototype object (section 15.3.2.1).
|
| It is a function with an “empty body”; if it is invoked, it merely returns
| undefined.
|
| The Function prototype object does not have a valueOf property of its own;
| however, it inherits the valueOf property from the Object prototype
| Object.

,-[ECMAScript Language Specification, Edition 5
| ("Final final final final draft"¹)]
|
| 15.3.4 Properties of the Function Prototype Object
|
| The Function prototype object is itself a Function object (its [[Class]]
| is "Function") that, when invoked, accepts any arguments and returns
| undefined.
|
| The value of the [[Prototype]] internal property of the Function prototype
| object is the standard built-in Object prototype object (15.2.4). The
| initial value of the [[Extensible]] internal property of the Function
| prototype object is true.
|
| The Function prototype object does not have a valueOf property of its own;
| however, it inherits the valueOf property from the Object prototype
| Object.
|
| The length property of the Function prototype object is 0.

Note that the part about the empty body is gone from ES5 which means that a
ES5-conforming implementation could actually do something when this method
is called as long as it accepts any arguments and returns `undefined'.


PointedEars
___________
¹ in the title of the corresponding PDF document although not advertised as
such

Garrett Smith

unread,
Dec 23, 2009, 12:55:24 AM12/23/09
to
Mychal Hackman wrote:
> I am a new JavaScript programmer. In training I was introduced to

[...]

> The following is the "Ajax" section of the code, and I would greatly
> appreciate (and request) critiques of the code from the group.
>
> Ajax = {

Don't make assignments to undeclared identifiers (don't forget var).

Garrett Smith

unread,
Dec 23, 2009, 1:02:11 AM12/23/09
to
David Mark wrote:
> On Dec 22, 7:45 pm, Garrett Smith <dhtmlkitc...@gmail.com> wrote:
>> Mychal Hackman wrote:

[...]

>>> Request : function(url, params, onsuccess, method){
>>> var xhr = Ajax.transport,
>>> res = '',
>>> post = null;
>>> xhr.onreadystatechange = function(){
>> I believe you have created a circular reference here.
>
> Yes.
>
> [xmlhttp]--readystatechange-->[anon function]-->[Activation Object]-->
> [xmlhttp]
>
> But this is unrelated to the previously mentioned (partial) chain.
>

There are two references to the XMLHttpRequest object: xhr and
Ajax.transport. Both are in scope of the function that is assigned to
onreadystatechange.

>> xhr has an onreadystatechange, which has xhr.
>>
>> setting xhr = null will not solve the problem here. onreadystatechange
>> has Ajax.transport in scope chain.
>
> That won't solve the problem because it will blow up in IE6. You have
> to set it to a Function object (preferably an empty one).
>

Setting xhr = null won't blow up in IE. Setting xhr.onreadystatechange =
null will, but setting xhr = null won't.

Setting xhr won't break the circle, either. There is still
Ajax.transport in scope of the function assigned to xhr.onreadystatechange.

>> Ajax.transport -> onreadystatechange -> [[Scope]] -> Ajax.transport.
>
> No. Ajax is global. It's not referenced by the local Activation
> Object. If it were, virtually everything would leak (think about it).
>

Identifier Ajax does not need to be referenced by the local activation
object. It is in the scope chain.

For example, if the onreadystatechange has an eval:-

xhr.onreadystatechange = function(){
if(Math.random > .999) {
eval("alert(typeof Ajax.transport)");
}
}

- it would still have to look up the scope chain and find
Ajax.transport. It makes no difference if the Ajax object is global. The
Ajax identifier is in the scope chain of the function assigned to
onreadystatechange.

The onreadystatechange has Ajax.transport and Ajax.transport has
onreadystatechange.

>>> if(onsuccess && xhr.readyState==4){
>>> res = xhr.responseText ||
>>> xhr.responseJSON ||
>>> xhr.responseXML;
>>> onsuccess(res);
>>> }
>>> };
>> Why not just use responseText?
>
> You might want the XML.
>
> onsuccess(xhr.resonseText, xhr.responseXML);
>
> Or just:-
>
> onsuccess(xhr);
>

Passing responseXML when responseText is empty string would be an
unlikely problem case for the caller to handle. Best avoid that.

[...]

It is an odd design to have a globally accessible Ajax.transport object,
and then pass that very same object to onsuccess. I think the global
object should be gotten rid of.


IE6 (and 7?) throws errors when calling send on an XHR that has been
opened. TO reuse the object, it is necessary to fist call the xhr's
abort method.

>>> if(method && method.toUpperCase() == 'POST'){
>>> params.noCACHE = false;
>> Caching can be useful at times. Consider an application where the user
>> enters home zip, looks at result, then tries work zip code, looks at
>> result, then re-enters home zip. The home zip being cached would be useful.
>
> Caching POST's? I don't follow. And caching GET's is a major pain
> because of IE's problems. So caching XHR is best avoided.

I misread. Caching POST would be odd.

Garrett Smith

unread,
Dec 23, 2009, 1:05:46 AM12/23/09
to
Thomas 'PointedEars' Lahn wrote:
> Garrett Smith wrote:
>
>> Mychal Hackman wrote:
>>> Ajax = {
>>> transport : (function(){
>>> if(window.XMLHttpRequest){
>>> return new XMLHttpRequest();
>>> }else if(window.ActiveXObject){
>>> return new ActiveXObject('Microsoft.XMLHTTP');
>>> }else{
>>> return false;
>>> }
>>> })(),
>> Be careful to avoid potential circular reference of Host object to
>> JScript object. You have Ajax.transport -> Host object...
>
> Where is the circular reference? And how would you avoid it, then?
>
It occurs below, as I believed it would. I wrote "potential". I did not
write that the circle was already established.

I try to creating references from host object to jscript object, in
general.

To avoid a leak, either don't create one or break the chain between host
object to jscript object.

Garrett Smith

unread,
Dec 23, 2009, 1:07:15 AM12/23/09
to

No, actually a circular reference does exist below. One of the
identifiers in scope of that reference is Ajax.transport.

Gregor Kofler

unread,
Dec 23, 2009, 6:33:10 AM12/23/09
to
Mychal Hackman meinte:

> On Dec 22, 2:20 pm, David Mark <dmark.cins...@gmail.com> wrote:

>>> Request : function(url, params, onsuccess, method){
>> This is not a constructor.
>
> Sorry, I don't follow here. Can you elaborate please?

By convention, upper case function names are reserved for constructors.

Gregor


--
http://www.gregorkofler.com

David Mark

unread,
Dec 23, 2009, 10:56:12 AM12/23/09
to
On Dec 23, 1:02 am, Garrett Smith <dhtmlkitc...@gmail.com> wrote:
> David Mark wrote:
> > On Dec 22, 7:45 pm, Garrett Smith <dhtmlkitc...@gmail.com> wrote:
> >> Mychal Hackman wrote:
>
> [...]
>
> >>>     Request : function(url, params, onsuccess, method){
> >>>         var xhr = Ajax.transport,
> >>>             res = '',
> >>>             post = null;
> >>>         xhr.onreadystatechange = function(){
> >> I believe you have created a circular reference here.
>
> > Yes.
>
> > [xmlhttp]--readystatechange-->[anon function]-->[Activation Object]-->
> > [xmlhttp]
>
> > But this is unrelated to the previously mentioned (partial) chain.
>
> There are two references to the XMLHttpRequest object: xhr and
> Ajax.transport. Both are in scope of the function that is assigned to
> onreadystatechange.
>
> >> xhr has an onreadystatechange, which has xhr.
>
> >> setting xhr = null will not solve the problem here. onreadystatechange
> >> has Ajax.transport in scope chain.
>
> > That won't solve the problem because it will blow up in IE6.You have

> > to set it to a Function object (preferably an empty one).
>
> Setting xhr = null won't blow up in IE. Setting xhr.onreadystatechange =
> null will, but setting xhr = null won't.

That's correct. I misread.

>
> Setting xhr won't break the circle, either. There is still
> Ajax.transport in scope of the function assigned to xhr.onreadystatechange.

But setting onreadystatechange to an empty Function will. That's the
most important point.

>
> >> Ajax.transport -> onreadystatechange -> [[Scope]] -> Ajax.transport.
>
> > No.  Ajax is global.  It's not referenced by the local Activation
> > Object.  If it were, virtually everything would leak (think about it).
>
> Identifier Ajax does not need to be referenced by the local activation
> object. It is in the scope chain.

That's irrelevant. There's no circular reference in that case. ;)

>
> For example, if the onreadystatechange has an eval:-
>
> xhr.onreadystatechange = function(){
>    if(Math.random > .999) {
>      eval("alert(typeof Ajax.transport)");
>    }
>
> }
>
> - it would still have to look up the scope chain and find
> Ajax.transport. It makes no difference if the Ajax object is global.

Of course it does. Diagram it.

> The
> Ajax identifier is in the scope chain of the function assigned to
> onreadystatechange.

As mentioned, that is irrelevant to the memory leak consideration.

>
> The onreadystatechange has Ajax.transport and Ajax.transport has
> onreadystatechange.
>
>
>
>
>
> >>>             if(onsuccess && xhr.readyState==4){
> >>>                 res = xhr.responseText ||
> >>>                       xhr.responseJSON ||
> >>>                       xhr.responseXML;
> >>>                 onsuccess(res);
> >>>             }
> >>>         };
> >> Why not just use responseText?
>
> > You might want the XML.
>
> > onsuccess(xhr.resonseText, xhr.responseXML);
>
> > Or just:-
>
> > onsuccess(xhr);
>
> Passing responseXML when responseText is empty string would be an
> unlikely problem case for the caller to handle. Best avoid that.
>
> [...]
>
> It is an odd design to have a globally accessible Ajax.transport object,
> and then pass that very same object to onsuccess. I think the global
> object should be gotten rid of.

Certainly.

>
> IE6 (and 7?) throws errors when calling send on an XHR that has been
> opened. TO reuse the object, it is necessary to fist call the xhr's
> abort method.
>
> >>>         if(method && method.toUpperCase() == 'POST'){
> >>>             params.noCACHE = false;
> >> Caching can be useful at times. Consider an application where the user
> >> enters home zip, looks at result, then tries work zip code, looks at
> >> result, then re-enters home zip. The home zip being cached would be useful.
>
> > Caching POST's?  I don't follow.  And caching GET's is a major pain
> > because of IE's problems.  So caching XHR is best avoided.
>
> I misread. Caching POST would be odd.

Yes.

David Mark

unread,
Dec 23, 2009, 11:18:47 AM12/23/09
to
On Dec 23, 1:05 am, Garrett Smith <dhtmlkitc...@gmail.com> wrote:
> Thomas 'PointedEars' Lahn wrote:
> > Garrett Smith wrote:
>
> >> Mychal Hackman wrote:
> >>> Ajax = {
> >>>     transport : (function(){
> >>>         if(window.XMLHttpRequest){
> >>>             return new XMLHttpRequest();
> >>>         }else if(window.ActiveXObject){
> >>>             return new ActiveXObject('Microsoft.XMLHTTP');
> >>>         }else{
> >>>             return false;
> >>>         }
> >>>     })(),
> >> Be careful to avoid potential circular reference of Host object to
> >> JScript object. You have Ajax.transport -> Host object...
>
> > Where is the circular reference?  And how would you avoid it, then?
>
> It occurs below, as I believed it would. I wrote "potential". I did not
> write that the circle was already established.

But it does _not_ occur because of this potential (which is never
realized). That's a very important distinction.

>
> I try to creating references from host object to jscript object, in
> general.

To avoid? Yes, I do too. In light of IE's problems in this area,
it's the only sane approach. Just like you should avoid overloading
due to language constraints. Nevertheless, both of those bee-lines to
disaster are buzzing with activity (pick up any library or framework).

>
> To avoid a leak, either don't create one or break the chain between host
> object to jscript object.

Exactly.

David Mark

unread,
Dec 23, 2009, 11:19:42 AM12/23/09
to

As mentioned, that doesn't matter. Think about it (or draw a diagram
if in doubt).

Mychal Hackman

unread,
Dec 23, 2009, 12:59:16 PM12/23/09
to
I have modified the code using information presented in this
discussion:

var Ajax = (function(){

var getXhr = (function(){
if(typeof window.XMLHttpRequest != 'undefined'){
return new XMLHttpRequest();

//lookup other progIds
}else if(typeof window.ActiveXObject != 'undefined'){
try{


return new ActiveXObject('Microsoft.XMLHTTP');

}catch(e){ return false; }
}else{
return false;
}
})(),

encodeURIParams = function(params){
var url = [], key, i;

for(key in params){


//in the case of a select multiple

if(typeof params[key] == 'object'){


for(i = params[key].length; i--;){

url.push(encodeURIComponent(key), '=',
encodeURIComponent(params[key][i]), '&');
}

}else{
url.push(encodeURIComponent(key), '=',
encodeURIComponent(params[key]), '&');
}
}
return url.join('');
},

Request = function(url, params, onsuccess, method){
var xmlHttp = getXhr,
post = null;

xmlHttp.onreadystatechange = function(){
if(onsuccess && xmlHttp.readyState==4){
onsuccess(xmlHttp.responseText, xmlHttp.responseXML);

xmlHttp.onreadystatechange = function(){};
}
};

if(method && method.toUpperCase() == 'POST'){

post = encodeURIParams(params);
xmlHttp.open(method, url, true);
xmlHttp.setRequestHeader('Content-type', 'application/x-
www-form-urlencoded');
}else{
method = 'GET';
//need to deal with uris with existing query
xmlHttp.open(method, url+'?'+encodeURIParams(params),
true);
}

try{
xmlHttp.send(post);
}catch(e){}
};

return { Request : Request };
})();

Asen Bozhilov

unread,
Dec 23, 2009, 2:32:51 PM12/23/09
to
Mychal Hackman wrote:

>         xmlHttp.onreadystatechange = function(){
>                 xmlHttp.onreadystatechange = function(){};

That isn't break circular reference in the way you do it. You again
form closure and you produce long Scope Chain. That empty function
refer from [[scope]] property AO/VO associated with execution context
in wich you create.

AO/VO => Request EC
^
AO/VO => xmlHttp.onreadystatechange EC
^
[[scope]] of xmlHttp.onreadystatechange = function(){};

Read that article <URL: http://www.jibbering.com/faq/faq_notes/closures.html>

David Mark

unread,
Dec 23, 2009, 2:48:59 PM12/23/09
to
On Dec 23, 2:32 pm, Asen Bozhilov <asen.bozhi...@gmail.com> wrote:
> Mychal Hackman wrote:
> >         xmlHttp.onreadystatechange = function(){
> >                 xmlHttp.onreadystatechange = function(){};
>
> That isn't break circular reference in the way you do it. You again
> form closure and you produce long Scope Chain.

Correct.

var fn = function() {};

...

(function() {

...

xmlHttp.onreadystatechange = fn; // fn defined outside of closure

JR

unread,
Dec 23, 2009, 3:57:57 PM12/23/09
to
On Dec 23, 3:59 pm, Mychal Hackman <mycha...@gmail.com> wrote:
> I have modified the code using information presented in this
> discussion:
>
> var Ajax = (function(){
>
>     var getXhr = (function(){
>         if(typeof window.XMLHttpRequest != 'undefined'){
>             return new XMLHttpRequest();

As (window.someThing) can return an object, null or undefined (on the
browser-side), it's irrelevant to check for 'typeof window.someThing'.
So,

if (typeof window.XMLHttpRequest != 'undefined') {}

is equivalent to just

if (window.XMLHttpRequest) {} // null, undefined and '' evaluate to
false.


>         //lookup other progIds
>         }else if(typeof window.ActiveXObject != 'undefined'){
>             try{
>                 return new ActiveXObject('Microsoft.XMLHTTP');
>             }catch(e){ return false; }

Firstly, lose that "return false" in the catch(e) { } block. Secondly,
you've got to try "Msxml2.XMLHTTP" too, not just "Microsoft.XMLHTTP".
I suggest checking for that in the first place, because IE is *still*
the most used browser (I hat to admit that). For instance:

var getXhr = (function() {
var activeXmodes = ["Msxml2.XMLHTTP", "Microsoft.XMLHTTP"];
if (window.ActiveXObject) {
for (var i = 0; i < activeXmodes.length; i++) {
try { return new ActiveXObject(activeXmodes[i]); }
catch (e) { } // Ignores any error.
}
} else if (window.XMLHttpRequest) { // Firefox, Opera 8.0+, Safari.
return new XMLHttpRequest();
} else {
// this browser doesn't support AJAX.
return false;
}
})(),

--
JR

David Mark

unread,
Dec 23, 2009, 4:07:17 PM12/23/09
to
On Dec 23, 3:57 pm, JR <groups_j...@yahoo.com.br> wrote:
> On Dec 23, 3:59 pm, Mychal Hackman <mycha...@gmail.com> wrote:
>
> > I have modified the code using information presented in this
> > discussion:
>
> > var Ajax = (function(){
>
> >     var getXhr = (function(){
> >         if(typeof window.XMLHttpRequest != 'undefined'){
> >             return new XMLHttpRequest();
>
> As (window.someThing) can return an object, null or undefined (on the
> browser-side), it's irrelevant to check for 'typeof window.someThing'.
> So,
>
>   if (typeof window.XMLHttpRequest != 'undefined') {}
>
> is equivalent to just
>
>   if (window.XMLHttpRequest) {} // null, undefined and '' evaluate to
> false.

Never detect host objects by type conversion. Some of them blow
up. :)

>
> >         //lookup other progIds
> >         }else if(typeof window.ActiveXObject != 'undefined'){
> >             try{
> >                 return new ActiveXObject('Microsoft.XMLHTTP');
> >             }catch(e){ return false; }
>
> Firstly, lose that "return false" in the catch(e) { } block. Secondly,
> you've got to try "Msxml2.XMLHTTP" too, not just "Microsoft.XMLHTTP".

As noted.

> I suggest checking for that in the first place, because IE is *still*
> the most used browser (I hat to admit that). For instance:
>
> var getXhr = (function() {
>   var activeXmodes = ["Msxml2.XMLHTTP", "Microsoft.XMLHTTP"];
>   if (window.ActiveXObject) {

No. IE has supported XMLHttpRequest since version 7, some users have
ActiveX disabled for them and some agents have dummy global
ActiveXObject properties to prevent unnecessary exclusion by browser
sniffing scripts.

Asen Bozhilov

unread,
Dec 23, 2009, 4:14:46 PM12/23/09
to
David Mark wrote:
> var fn = function() {};
>
> ...
>
> (function() {
>
> ...
>
> xmlHttp.onreadystatechange = fn; // fn defined outside of closure

Excellent post. I hope OP understand your post. If you wrote:

(function(){
var fn = function() {};

Circular reference will be still there.

getXhr -> onreadystatechange -> fn -> AO -> getXhr

I have only one question. Why you suggest here to use function
expression and resolve `fn' identifier form Scope Chain instead of
`Function' constructor to create object with [[scope]] property which
refer Global Object? He can do it:

xmlHttp.onreadystatechange = Function();

Mychal Hackman

unread,
Dec 23, 2009, 4:33:29 PM12/23/09
to
On Dec 23, 2:14 pm, Asen Bozhilov <asen.bozhi...@gmail.com> wrote:
> David Mark wrote:
> > var fn = function() {};
>
> > ...
>
> > (function() {
>
> > ...
>
> > xmlHttp.onreadystatechange = fn; // fn defined outside of closure
>
> Excellent post. I hope OP understand your post. If you wrote:
Agreed.

> (function(){
>   var fn = function() {};
>
> Circular reference will be still there.

Yes because the function is created within the scope of
xmlHttp.onreadystatechange. If I understand correctly, the situation
would be exactly the same as before.

Asen Bozhilov

unread,
Dec 23, 2009, 4:36:56 PM12/23/09
to
Mychal Hackman wrote:

> if(typeof window.XMLHttpRequest != 'undefined'){
> return new XMLHttpRequest();

Why you mixin `11.2.1 Property Accessors` and `11.1.2 Identifier
Reference`? That can be very hard to debug. See below:

(function(){
var XMLHttpRequest;
if (window.XMLHttpRequest)
{
new XMLHttpRequest(); //TypeError for 11.2.2 point 3
}
}());

Should be:

new window.XMLHttpRequest();


> onsuccess(xmlHttp.responseText, xmlHttp.responseXML);

onsuccess should be test for internal [[Call]] before you called.

if (typeof onsuccess == 'function')
{
onsuccess();
}

David Mark

unread,
Dec 23, 2009, 4:47:45 PM12/23/09
to

Overkill. Documentation should specify the types of expected
arguments.

JR

unread,
Dec 23, 2009, 4:47:45 PM12/23/09
to
On Dec 23, 7:07 pm, David Mark <dmark.cins...@gmail.com> wrote:
> On Dec 23, 3:57 pm, JR <groups_j...@yahoo.com.br> wrote:
>
>
>
>
>
> > On Dec 23, 3:59 pm, Mychal Hackman <mycha...@gmail.com> wrote:
>
> > > I have modified the code using information presented in this
> > > discussion:
>
> > > var Ajax = (function(){
>
> > >     var getXhr = (function(){
> > >         if(typeof window.XMLHttpRequest != 'undefined'){
> > >             return new XMLHttpRequest();
>
> > As (window.someThing) can return an object, null or undefined (on the
> > browser-side), it's irrelevant to check for 'typeof window.someThing'.
> > So,
>
> >   if (typeof window.XMLHttpRequest != 'undefined') {}
>
> > is equivalent to just
>
> >   if (window.XMLHttpRequest) {} // null, undefined and '' evaluate to
> > false.
>
> Never detect host objects by type conversion.  Some of them blow
> up.  :)

I can't remember a single case in which window.XMLHttpRequest or
window.ActiveXObject should 'blow up'. I'm sitting on a bomb and
didn't know about that (just kidding).

> > >         //lookup other progIds
> > >         }else if(typeof window.ActiveXObject != 'undefined'){
> > >             try{
> > >                 return new ActiveXObject('Microsoft.XMLHTTP');
> > >             }catch(e){ return false; }
>
> > Firstly, lose that "return false" in the catch(e) { } block. Secondly,
> > you've got to try "Msxml2.XMLHTTP" too, not just "Microsoft.XMLHTTP".
>
> As noted.
>
> > I suggest checking for that in the first place, because IE is *still*
> > the most used browser (I hat to admit that). For instance:
>
> > var getXhr = (function() {
> >   var activeXmodes = ["Msxml2.XMLHTTP", "Microsoft.XMLHTTP"];
> >   if (window.ActiveXObject) {
>
> No.  IE has supported XMLHttpRequest since version 7

Ok, I forgot that IE's native XMLHTTP support is enabled by default.
But anyone can disable it, so... Anyway, if even MS checks for the
native object as a first step, I won't be the 'smart alec' here saying
the contrary:

http://msdn.microsoft.com/en-us/library/ms537505(VS.85).aspx


> [...] some users have


> ActiveX disabled for them and some agents have dummy global
> ActiveXObject properties to prevent unnecessary exclusion by browser
> sniffing scripts.

I didn't follow what's the problem?

--
JR

Garrett Smith

unread,
Dec 23, 2009, 4:48:45 PM12/23/09
to
Asen Bozhilov wrote:
> David Mark wrote:
>> var fn = function() {};
>>


[...]

> I have only one question. Why you suggest here to use function
> expression and resolve `fn' identifier form Scope Chain instead of
> `Function' constructor to create object with [[scope]] property which
> refer Global Object? He can do it:
>
> xmlHttp.onreadystatechange = Function();

The built-in Function constructor uses much less efficient algorithm for
building a function. A straight function expression is much simpler.

xmlHttp.onreadystatechange = noop;

If you get tired of defining a noop in all your modules, you want to
reuse a global function with global scope.

Function.prototype is a globally accessible function with global scope.
Function.prototype implements [[Call]] but not [[Construct]].

Asen Bozhilov

unread,
Dec 23, 2009, 4:48:50 PM12/23/09
to
David Mark wrote:

> Never detect host objects by type conversion.  Some of them blow
> up.  :)

Yes, i agree with you especially in ToPrimitive. But for ToBoolean are
have any example where ToBoolean can be harmful. I think ToBoolean and
ToObject, check the internal type of object.

ToBoolean:
if (Type(value) === Object)
{
return true;
}

ToObject:
if (Type(value) === Object)
{
return value;
}

David Mark

unread,
Dec 23, 2009, 4:50:15 PM12/23/09
to

The Function constructor is inherently evil (avoid whenever
possible). Calling it without the new Operator is bad form. Creating
a new function each time through is inefficient.

Asen Bozhilov

unread,
Dec 23, 2009, 4:52:20 PM12/23/09
to
David Mark wrote:

> Overkill.  Documentation should specify the types of expected
> arguments.

You are absolutely right. And you use absolutely right term. Thanks
for correction ;)

David Mark

unread,
Dec 23, 2009, 5:06:10 PM12/23/09
to
On Dec 23, 4:47 pm, JR <groups_j...@yahoo.com.br> wrote:
> On Dec 23, 7:07 pm, David Mark <dmark.cins...@gmail.com> wrote:
>
>
>
> > On Dec 23, 3:57 pm, JR <groups_j...@yahoo.com.br> wrote:
>
> > > On Dec 23, 3:59 pm, Mychal Hackman <mycha...@gmail.com> wrote:
>
> > > > I have modified the code using information presented in this
> > > > discussion:
>
> > > > var Ajax = (function(){
>
> > > >     var getXhr = (function(){
> > > >         if(typeof window.XMLHttpRequest != 'undefined'){
> > > >             return new XMLHttpRequest();
>
> > > As (window.someThing) can return an object, null or undefined (on the
> > > browser-side), it's irrelevant to check for 'typeof window.someThing'.
> > > So,
>
> > >   if (typeof window.XMLHttpRequest != 'undefined') {}
>
> > > is equivalent to just
>
> > >   if (window.XMLHttpRequest) {} // null, undefined and '' evaluate to
> > > false.
>
> > Never detect host objects by type conversion.  Some of them blow
> > up.  :)
>
> I can't remember a single case in which window.XMLHttpRequest or
> window.ActiveXObject should 'blow up'. I'm sitting on a bomb and
> didn't know about that (just kidding).

Do you keep a running list of host objects that do? It's best to
avoid the issue.

>
>
>
> > > >         //lookup other progIds
> > > >         }else if(typeof window.ActiveXObject != 'undefined'){
> > > >             try{
> > > >                 return new ActiveXObject('Microsoft.XMLHTTP');
> > > >             }catch(e){ return false; }
>
> > > Firstly, lose that "return false" in the catch(e) { } block. Secondly,
> > > you've got to try "Msxml2.XMLHTTP" too, not just "Microsoft.XMLHTTP".
>
> > As noted.
>
> > > I suggest checking for that in the first place, because IE is *still*
> > > the most used browser (I hat to admit that). For instance:
>
> > > var getXhr = (function() {
> > >   var activeXmodes = ["Msxml2.XMLHTTP", "Microsoft.XMLHTTP"];
> > >   if (window.ActiveXObject) {
>
> > No.  IE has supported XMLHttpRequest since version 7
>
> Ok, I forgot that IE's native XMLHTTP support is enabled by default.
> But anyone can disable it, so...

You need to use a try-catch with it as well.

> Anyway, if even MS checks for the
> native object as a first step, I won't be the 'smart alec' here saying
> the contrary:

Huh?

>
> http://msdn.microsoft.com/en-us/library/ms537505(VS.85).aspx

What is it you see there?

>
> > [...] some users have
> > ActiveX disabled for them and some agents have dummy global
> > ActiveXObject properties to prevent unnecessary exclusion by browser
> > sniffing scripts.
>
> I didn't follow what's the problem?
>

Some agents implement window.ActiveXObject, but it doesn't do anything.

Asen Bozhilov

unread,
Dec 23, 2009, 5:06:43 PM12/23/09
to
David Mark wrote:

> Overkill.  Documentation should specify the types of expected
> arguments.

Again here you are correct, but if it that argument is optional, i
think must be tested for [[Call]] before called. How you think about
that case and design with optiona* arguments?

David Mark

unread,
Dec 23, 2009, 5:12:51 PM12/23/09
to
On Dec 23, 4:48 pm, Asen Bozhilov <asen.bozhi...@gmail.com> wrote:
> David Mark wrote:
> > Never detect host objects by type conversion.  Some of them blow
> > up.  :)
>
> Yes, i agree with you especially in ToPrimitive. But for ToBoolean are
> have any example where ToBoolean can be harmful. I think ToBoolean and
> ToObject, check the internal type of object.

Yes. There are lots of examples (e.g. all ActiveX methods):-

if (window.external.addFavorite) {

...and properties under some circumstances:-

if (el.offsetParent) {

...will also blow up. The indicator is a typeof result of "unknown".

Asen Bozhilov

unread,
Dec 23, 2009, 5:26:22 PM12/23/09
to
David Mark wrote:

> Yes.  There are lots of examples (e.g. all ActiveX methods):-

No. From that i can see they have own implementation of internal
[[Get]] and [[Put]] methods.

var a = window.external.addFavorite;

No type conversion but error is still there. Interesting in that part
is typeof.

| 1. Evaluate UnaryExpression.
| [...]
| 4. Call GetValue(Result(1))

So here again we have implicit invocation of [[Get]] method of that
`object'. But i m not sure people of Microsoft implement in that way.
How you think about that?

David Mark

unread,
Dec 23, 2009, 5:41:22 PM12/23/09
to

I think they are nuts, but host objects can be implemented any way the
developers see fit.

I detect features with isHostMethod/isHostObjectProperty so I don't
have to keep track of their nonsense (and so I have a single line of
code to update in case they decide to change the rules after ten
years).

Garrett Smith

unread,
Dec 23, 2009, 6:20:29 PM12/23/09
to

You seem to have a misunderstanding of how scope chain and identifier
resolution works.

The next object in scope chain of the function assigned in
onreadystatechange is the function object assigned to Ajax.Request the
next object in the scope chain after that is the containing scope, which
contains the Ajax object itself.

onreadystatechange handler Scope --> Ajax.Request Scope --> containing
scope (global?)

In fact, Ajax object does not have to be global at all.

>
>> The
>> Ajax identifier is in the scope chain of the function assigned to
>> onreadystatechange.
>
> As mentioned, that is irrelevant to the memory leak consideration.
>

Ah, not that is you failing to see the relevance, not me writing
irrelevance.

The Ajax.transport is in scope of the function assigned. If, for
example, the anonymous function body set xhr = null, then there would be
still one remaining link to the XMLHttpRequest object. That reference is
Ajax.transport.
[Global Scope]
Variable: Ajax
|
|
[Ajax.Request Scope]
Variable: xhr, res, post, url, params, onsuccess, method
|
|
[onreadystatechange handler Scope]
Variable: {empty}

Start from the bottom of the diagram, in onreadystatechange handler
Scope. The scope chain includes Ajax.Request Scope, and then the scope
above that (global, apparently, but it doesn't really matter). The last
object on the scope chain has a reference to Ajax.transport.
Ajax.transport is in the scope chain of onreadystatechange.

>> The onreadystatechange has Ajax.transport and Ajax.transport has
>> onreadystatechange.
>>

David Mark

unread,
Dec 23, 2009, 6:48:41 PM12/23/09
to

No, you seem to be confused about how circular references are
created. ;)

[...]

>
> > As mentioned, that is irrelevant to the memory leak consideration.
>
> Ah, not that is you failing to see the relevance, not me writing
> irrelevance.

No, you are just confusing the uninitiated with your confusion.

>
> The Ajax.transport is in scope of the function assigned. If, for
> example, the anonymous function body set xhr = null, then there would be
> still one remaining link to the XMLHttpRequest object. That reference is
> Ajax.transport.
> [Global Scope]
> Variable: Ajax
>    |
>    |
> [Ajax.Request Scope]
>    Variable: xhr, res, post, url, params, onsuccess, method
>    |
>    |
> [onreadystatechange handler Scope]
>    Variable: {empty}
>
> Start from the bottom of the diagram, in onreadystatechange handler
> Scope. The scope chain includes Ajax.Request Scope, and then the scope
> above that (global, apparently, but it doesn't really matter). The last
> object on the scope chain has a reference to Ajax.transport.
> Ajax.transport is in the scope chain of onreadystatechange.
>

You are missing a link in the chain (Activation Object). Without it,
there's no linkage between the Function object and the globally
declared Ajax object.

Garrett Smith

unread,
Dec 23, 2009, 7:11:24 PM12/23/09
to
Thomas 'PointedEars' Lahn wrote:
> David Mark wrote:
>
>> Garrett Smith wrote:

>>> David Mark wrote:
>>>> Mychal Hackman wrote:
>>>>> [...]
>>>> Will leak memory in IE too. You need to set onreadystatechange to an
>>>> empty function when done.
>>> (Such as Function.prototype)
>> That's an interesting idea. I've always used an empty function.
>
> There is also a subtle difference between ES3F and ES5 that challenges
> whether using `Function.prototype' here is still a viable approach:
>

[...]

> Note that the part about the empty body is gone from ES5 which means that a
> ES5-conforming implementation could actually do something when this method
> is called as long as it accepts any arguments and returns `undefined'.

So what? They removed the obvious.

A legal implementation extension might be to add behavior to
Function.prototype that causes system side effects. The same is true for
any built-in function (parseInt, etc).

Garrett Smith

unread,
Dec 23, 2009, 7:17:40 PM12/23/09
to
David Mark wrote:
> On Dec 23, 6:20 pm, Garrett Smith <dhtmlkitc...@gmail.com> wrote:
>> David Mark wrote:
>>> On Dec 23, 1:02 am, Garrett Smith <dhtmlkitc...@gmail.com> wrote:
>>>> David Mark wrote:
>>>>> On Dec 22, 7:45 pm, Garrett Smith <dhtmlkitc...@gmail.com> wrote:
>>>>>> Mychal Hackman wrote:
>>>> [...]

[...]

>
> No, you are just confusing the uninitiated with your confusion.
>

You wrote:


| Ajax is global. It's not referenced by the local Activation
| Object. If it were, virtually everything would leak (think about it).

The Ajax object is not a member of the containing scope, but it is a
member of an object in the containing scope's containing scope.

So rather than xhr -> onreadystatechange function [[Scope]] -> function
[[Scope]] -> xhr, we have:

xhr -> onreadystatechange function [[Scope]] -> Ajax.Request function
[[Scope]] --> global [[Scope]].

>
> You are missing a link in the chain (Activation Object). Without it,
> there's no linkage between the Function object and the globally
> declared Ajax object.

The variable/activation object is written as "Variable:". In the
onreadystatechange handler, it is empty, written as "(empty)".

Thomas 'PointedEars' Lahn

unread,
Dec 23, 2009, 7:25:13 PM12/23/09
to
Garrett Smith wrote:

> Thomas 'PointedEars' Lahn wrote:
>> David Mark wrote:
>>> Garrett Smith wrote:
>>>> David Mark wrote:
>>>>> Mychal Hackman wrote:
>>>>>> [...]
>>>>> Will leak memory in IE too. You need to set onreadystatechange to an
>>>>> empty function when done.
>>>> (Such as Function.prototype)
>>> That's an interesting idea. I've always used an empty function.
>>
>> There is also a subtle difference between ES3F and ES5 that challenges
>> whether using `Function.prototype' here is still a viable approach:
>
> [...]
>
>> Note that the part about the empty body is gone from ES5 which means that
>> a ES5-conforming implementation could actually do something when this
>> method is called as long as it accepts any arguments and returns
>> `undefined'.
>
> So what? They removed the obvious.

Nonsense.

> A legal implementation extension might be to add behavior to
> Function.prototype that causes system side effects.

Which it why it should not be used anymore.

> The same is true for any built-in function (parseInt, etc).

You don't know what you are talking about.


PointedEars
--
Danny Goodman's books are out of date and teach practices that are
positively harmful for cross-browser scripting.
-- Richard Cornford, cljs, <cife6q$253$1$8300...@news.demon.co.uk> (2004)

David Mark

unread,
Dec 23, 2009, 7:53:27 PM12/23/09
to
On Dec 23, 7:17 pm, Garrett Smith <dhtmlkitc...@gmail.com> wrote:
> David Mark wrote:
> > On Dec 23, 6:20 pm, Garrett Smith <dhtmlkitc...@gmail.com> wrote:
> >> David Mark wrote:
> >>> On Dec 23, 1:02 am, Garrett Smith <dhtmlkitc...@gmail.com> wrote:
> >>>> David Mark wrote:
> >>>>> On Dec 22, 7:45 pm, Garrett Smith <dhtmlkitc...@gmail.com> wrote:
> >>>>>> Mychal Hackman wrote:
> >>>> [...]
>
> [...]
>
>
>
> > No, you are just confusing the uninitiated with your confusion.
>
> You wrote:
>
> | Ajax is global.  It's not referenced by the local Activation
> | Object.  If it were, virtually everything would leak (think about it).
>
> The Ajax object is not a member of the containing scope, but it is a
> member of an object in the containing scope's containing scope.

Which is irrelevant for our purposes. You are missing the obvious.

>
> So rather than xhr -> onreadystatechange function [[Scope]] -> function
> [[Scope]] -> xhr, we have:
>
> xhr -> onreadystatechange function [[Scope]] -> Ajax.Request function
> [[Scope]] --> global [[Scope]].

Nope. Not a circular reference.

Think about what you quoted above. _Everything_ would leak if
affected implementations were foolish enough to maintain links to the
Global Object for every object. They obviously have no need to do
that and they don't do it, so it doesn't matter.

http://www.jibbering.com/faq/faq_notes/closures.html#clMem

Garrett Smith

unread,
Dec 23, 2009, 8:15:27 PM12/23/09
to
Thomas 'PointedEars' Lahn wrote:
> Garrett Smith wrote:
>
>> Thomas 'PointedEars' Lahn wrote:
>>> David Mark wrote:
>>>> Garrett Smith wrote:
>>>>> David Mark wrote:
>>>>>> Mychal Hackman wrote:
>>>>>>> [...]
>>>>>> Will leak memory in IE too. You need to set onreadystatechange to an
>>>>>> empty function when done.
>>>>> (Such as Function.prototype)
>>>> That's an interesting idea. I've always used an empty function.
>>> There is also a subtle difference between ES3F and ES5 that challenges
>>> whether using `Function.prototype' here is still a viable approach:
>> [...]
>>
>>> Note that the part about the empty body is gone from ES5 which means that
>>> a ES5-conforming implementation could actually do something when this
>>> method is called as long as it accepts any arguments and returns
>>> `undefined'.
>> So what? They removed the obvious.
>
> Nonsense.
>

What is nonsense? And why?

>> A legal implementation extension might be to add behavior to
>> Function.prototype that causes system side effects.
>
> Which it why it should not be used anymore.
>
>> The same is true for any built-in function (parseInt, etc).
>
> You don't know what you are talking about.
>

Do you have a reason for believing that, or is it more hot air?

Garrett Smith

unread,
Dec 23, 2009, 8:33:51 PM12/23/09
to

The global scope object is on the scope chain.

Suppose the entire object were not global, but hidden.

(function(){

var Ajax = {
transport : function(){
if(window.XMLHttpRequest){
return new XMLHttpRequest();
}else if(window.ActiveXObject){


return new ActiveXObject('Microsoft.XMLHTTP');

}else{
return false;
}
})(),

Request : function(url, params, onsuccess, method){
var xhr = Ajax.transport,
res = '',
post = null;

xhr.onreadystatechange = function(){
if(onsuccess && xhr.readyState==4){
res = xhr.responseText ||
xhr.responseJSON ||
xhr.responseXML;

onsuccess(res);
}
};
//...
}
}

Now suppose for a second that a local identifer xhr had *not* been used,
but instead, that Ajax.transport had been used. Would there be a
circular reference?

Request : function(url, params, onsuccess, method){

var res = '',
post = null;

Ajax.transport.onreadystatechange = function(){
if(onsuccess && xhr.readyState==4){
res = xhr.responseText ||
xhr.responseJSON ||
xhr.responseXML;

onsuccess(res);
}
};
// ...

> http://www.jibbering.com/faq/faq_notes/closures.html#clMem

Good:
| A circular reference is when two or more objects refer to each other
| in a way that can be followed and lead back to the starting point.

Is there a circular reference in the above example?

Ajax.transport -> XHR_OBJECT -> onreadystatechange -> function[[Scope]]
- > function[[scope]] -> Ajax.transport.

As long as Ajax.transport exists on the scope chain, it can't be collected.

The Ajax object itself could be collected, so long as there were no
other references to it. The transport property would be collectible too,
but that has a reference and that reference is a Host object. Now that
host object has a property onreadystatechange, which points to a
function, and that function has a scope chain, that scope chain has, at
the end, a member object with the member Ajax.

David Mark

unread,
Dec 23, 2009, 8:42:01 PM12/23/09
to

That's obviously different. As with the viewport discussion (and
attributes before that) you've latched on to the wrong end of the
stick and are beating the thread to death with it. :(

Garrett Smith

unread,
Dec 23, 2009, 8:43:13 PM12/23/09
to
Asen Bozhilov wrote:
> David Mark wrote:
>
>> Yes. There are lots of examples (e.g. all ActiveX methods):-
>
> No. From that i can see they have own implementation of internal
> [[Get]] and [[Put]] methods.
>
> var a = window.external.addFavorite;
>
> No type conversion but error is still there. Interesting in that part
> is typeof.

[...]

The error is unrelated to type conversion. The typeof operator works on
reference and so it seems that typeof can't get a reference, then it
returns "unknown".

JR

unread,
Dec 23, 2009, 10:38:02 PM12/23/09
to

Wise advice. Thanks.


> > > > I suggest checking for that in the first place, because IE is *still*
> > > > the most used browser (I hat to admit that). For instance:
>
> > > > var getXhr = (function() {
> > > >   var activeXmodes = ["Msxml2.XMLHTTP", "Microsoft.XMLHTTP"];
> > > >   if (window.ActiveXObject) {
>
> > > No.  IE has supported XMLHttpRequest since version 7
>
> > Ok, I forgot that IE's native XMLHTTP support is enabled by default.
> > But anyone can disable it, so...
>
> You need to use a try-catch with it as well.
>
> > Anyway, if even MS checks for the
> > native object as a first step, I won't be the 'smart alec' here saying
> > the contrary:
>
> Huh?
>
>
>
> >http://msdn.microsoft.com/en-us/library/ms537505(VS.85).aspx
>
> What is it you see there?

I see the following text [excerpt]:

"XMLHTTP in IE7 vs. IE6
The native implementation of the XMLHTTP object is designed with cross-
browser compatibility in mind. With just a bit of script, it is easy
to build a function that works with either version of Internet
Explorer, or any browser that supports XMLHTTP. See XMLHttpRequest for
complete documentation and examples.

var xmlHttp = null;
if (window.XMLHttpRequest) {
// If IE7, Mozilla, Safari, and so on: Use native object.
xmlHttp = new XMLHttpRequest();
}
else
{
if (window.ActiveXObject) {
// ...otherwise, use the ActiveX control for IE5.x and IE6.
xmlHttp = new ActiveXObject('MSXML2.XMLHTTP.3.0');
}
}

Internet Explorer 7 supports the legacy implementation of XMLHTTP in
addition to the new native object, so pages currently using the
ActiveX control do not have to be rewritten. However, it is more
efficient to create a native scriptable object than to create an
ActiveX object. This is especially beneficial to those AJAX
applications that create a new XMLHTTP object for each request.

The native object also supports the use of expandos (custom
properties), and properly recognizes the 'this' notation of
Javascript.

ActiveX vs. XMLHTTP
Users and organizations that choose to disallow ActiveX controls can
still use XMLHTTP-based Web applications in Internet Explorer 7.
However, native XMLHTTP support can be disabled from the Advanced
settings tab of the Internet Options dialog box.

Internet Options Dialog
Clients can configure their own policy and simultaneously retain
functionality across key AJAX scenarios. By default, the native
implementation of XMLHTTP is enabled for all MSHTML hosts; however,
individual host applications can choose to disable XMLHTTP with the
FEATURE_XMLHTTP feature control key. An organization can use Group
Policy to disable XMLHTTP for all users of its network.

If native XMLHTTP has been disabled, developers can override the
XMLHttpRequest property of the window object with the MSXML-XMLHTTP
control, unless ActiveX has also been disabled, as in the following
example.

if (!window.XMLHttpRequest) {
window.XMLHttpRequest = function() {
try {
return new ActiveXObject('MSXML2.XMLHTTP.3.0');
}
catch (ex) {
return null;
}
}
}
"


> > > [...] some users have
> > > ActiveX disabled for them and some agents have dummy global
> > > ActiveXObject properties to prevent unnecessary exclusion by browser
> > > sniffing scripts.
>
> > I didn't follow what's the problem?
>
> Some agents implement window.ActiveXObject, but it doesn't do anything.

Thanks for that!

Cheers,
JR

David Mark

unread,
Dec 24, 2009, 12:02:45 AM12/24/09
to

So, they don't know how to detect their own hosts' features.

>   // If IE7, Mozilla, Safari, and so on: Use native object.
>   xmlHttp = new XMLHttpRequest();}
>
> else
> {
>   if (window.ActiveXObject) {

And so on.

>      // ...otherwise, use the ActiveX control for IE5.x and IE6.
>      xmlHttp = new ActiveXObject('MSXML2.XMLHTTP.3.0');

No try-catch either. :)

>   }
>
> }
>
> Internet Explorer 7 supports the legacy implementation of XMLHTTP in
> addition to the new native object, so pages currently using the
> ActiveX control do not have to be rewritten. However, it is more
> efficient to create a native scriptable object than to create an
> ActiveX object. This is especially beneficial to those AJAX
> applications that create a new XMLHTTP object for each request.

Yes. Lot of those. :(

>
> The native object also supports the use of expandos (custom
> properties), and properly recognizes the 'this' notation of
> Javascript.
>
> ActiveX vs. XMLHTTP
> Users and organizations that choose to disallow ActiveX controls can
> still use XMLHTTP-based Web applications in Internet Explorer 7.

Yes.

> However, native XMLHTTP support can be disabled from the Advanced
> settings tab of the Internet Options dialog box.

Yes.

>

[...]

>
> If native XMLHTTP has been disabled, developers can override the
> XMLHttpRequest property of the window object with the MSXML-XMLHTTP
> control, unless ActiveX has also been disabled, as in the following
> example.
>
> if (!window.XMLHttpRequest) {
>     window.XMLHttpRequest = function() {
>         try {
>             return new ActiveXObject('MSXML2.XMLHTTP.3.0');
>         }
>         catch (ex) {
>             return null;
>         }
>     }}

Awful.

Garrett Smith

unread,
Dec 24, 2009, 2:55:04 AM12/24/09
to

Is it a difference that would create a memory leak?

If so, can you explain how?

David Mark

unread,
Dec 24, 2009, 1:50:11 PM12/24/09
to

You are going around in circles. :)

http://www.jibbering.com/faq/faq_notes/closures.html#clMem

I already diagrammed the OP's case (as I've done for a thousand
similar cases in the last few years). It's the same diagram for your
latest example. Your previous example had no such (valid) diagram.

Asen Bozhilov

unread,
Dec 24, 2009, 2:50:13 PM12/24/09
to
Garrett Smith wrote:
> David Mark wrote:

> > No, you are just confusing the uninitiated with your confusion.
>
> You wrote:
>
> | Ajax is global.  It's not referenced by the local Activation
> | Object.  If it were, virtually everything would leak (think about it).
>
> The Ajax object is not a member of the containing scope, but it is a
> member of an object in the containing scope's containing scope.

If you are correct:

window.onload = function(){};

That will be produce circular reference. If `window' host object is
property of Global Object diagram is:

Global Object -> window -> onload -> AF[[scope]] -> Global Object


David Mark

unread,
Dec 24, 2009, 3:47:17 PM12/24/09
to

And that's just the tip of the (hypothetical) iceberg. Think about
what other host objects are in the Global scope.

So the hypothesis (which is not new) is obviously bunk.

Garrett Smith

unread,
Dec 24, 2009, 4:30:19 PM12/24/09
to
David Mark wrote:
> On Dec 24, 2:55 am, Garrett Smith <dhtmlkitc...@gmail.com> wrote:
>> David Mark wrote:
>>> On Dec 23, 8:33 pm, Garrett Smith <dhtmlkitc...@gmail.com> wrote:
>>>> David Mark wrote:
>>>>> On Dec 23, 7:17 pm, Garrett Smith <dhtmlkitc...@gmail.com> wrote:
>>>>>> David Mark wrote:
>>>>>>> On Dec 23, 6:20 pm, Garrett Smith <dhtmlkitc...@gmail.com> wrote:
>>>>>>>> David Mark wrote:
>>>>>>>>> On Dec 23, 1:02 am, Garrett Smith <dhtmlkitc...@gmail.com> wrote:
>>>>>>>>>> David Mark wrote:
>>>>>>>>>>> On Dec 22, 7:45 pm, Garrett Smith <dhtmlkitc...@gmail.com> wrote:
>>>>>>>>>>>> Mychal Hackman wrote:
>>>>>>>>>> [...]

[...]


>>> That's obviously different.
>> Is it a difference that would create a memory leak?
>>
>> If so, can you explain how?
>
> You are going around in circles. :)
>

Either you can explain the difference or you cannot. So far, you have
not been able to explain the difference.

> http://www.jibbering.com/faq/faq_notes/closures.html#clMem
>
> I already diagrammed the OP's case (as I've done for a thousand
> similar cases in the last few years). It's the same diagram for your
> latest example. Your previous example had no such (valid) diagram.

A diagram does not need use the same notation that you used to be valid
and it is indeed valid, just not apparently understandable by you.

David Mark

unread,
Dec 24, 2009, 5:04:39 PM12/24/09
to
On Dec 24, 4:30 pm, Garrett Smith <dhtmlkitc...@gmail.com> wrote:
> David Mark wrote:
> > On Dec 24, 2:55 am, Garrett Smith <dhtmlkitc...@gmail.com> wrote:
> >> David Mark wrote:
> >>> On Dec 23, 8:33 pm, Garrett Smith <dhtmlkitc...@gmail.com> wrote:
> >>>> David Mark wrote:
> >>>>> On Dec 23, 7:17 pm, Garrett Smith <dhtmlkitc...@gmail.com> wrote:
> >>>>>> David Mark wrote:
> >>>>>>> On Dec 23, 6:20 pm, Garrett Smith <dhtmlkitc...@gmail.com> wrote:
> >>>>>>>> David Mark wrote:
> >>>>>>>>> On Dec 23, 1:02 am, Garrett Smith <dhtmlkitc...@gmail.com> wrote:
> >>>>>>>>>> David Mark wrote:
> >>>>>>>>>>> On Dec 22, 7:45 pm, Garrett Smith <dhtmlkitc...@gmail.com> wrote:
> >>>>>>>>>>>> Mychal Hackman wrote:
> >>>>>>>>>> [...]
>
> [...]>>> That's obviously different.  
> >> Is it a difference that would create a memory leak?
>
> >> If so, can you explain how?
>
> > You are going around in circles.  :)
>
> Either you can explain the difference or you cannot. So far, you have
> not been able to explain the difference.

Either you didn't understand the explanation(s) or you are trying to
save face (and that ship has sailed). There is a third possibility
that you want me to spoon-feed it to you, but baiting won't make that
happen.

>
> >http://www.jibbering.com/faq/faq_notes/closures.html#clMem
>
> > I already diagrammed the OP's case (as I've done for a thousand
> > similar cases in the last few years).  It's the same diagram for your
> > latest example.  Your previous example had no such (valid) diagram.
>
> A diagram does not need use the same notation that you used to be valid
> and it is indeed valid, just not apparently understandable by you.

Who said anything about notation? Your diagram makes no sense in any
notation (that's the point).

Is anyone else here confused? We've been over these circular
reference patterns ad nauseam, but if this is not an isolated case of
confusion, I guess we can go over it again...

Thomas 'PointedEars' Lahn

unread,
Dec 24, 2009, 5:59:02 PM12/24/09
to
David Mark wrote:

> On Dec 23, 3:57 pm, JR <groups_j...@yahoo.com.br> wrote:
>> On Dec 23, 3:59 pm, Mychal Hackman <mycha...@gmail.com> wrote:

>> > //lookup other progIds
>> > }else if(typeof window.ActiveXObject != 'undefined'){
>> > try{

>> > return new ActiveXObject('Microsoft.XMLHTTP');

>> > }catch(e){ return false; }
>>
>> Firstly, lose that "return false" in the catch(e) { } block. Secondly,
>> you've got to try "Msxml2.XMLHTTP" too, not just "Microsoft.XMLHTTP".
>
> As noted.

What would one need "Msxml2.XMLHTTP" for?


PointedEars
--
var bugRiddenCrashPronePieceOfJunk = (
navigator.userAgent.indexOf('MSIE 5') != -1
&& navigator.userAgent.indexOf('Mac') != -1
) // Plone, register_function.js:16

Garrett Smith

unread,
Dec 24, 2009, 8:00:50 PM12/24/09
to

Right.

In IE, the global variable object is implemented as a JScript object,
and the global object is implemented by the host. That is a bug of IE,
explained in Eric Lippert's blog entry many years ago.

// IE global obj.
Ajax = { ... }

// Global variable obj.
var Ajax = { ... }

COM_OBJECT -> JSCRIPT_OBJ_CHAIN -> COM_OBJ

The global object has to have some sort of tear down to remove break the
chain, as above, so that afte page tear down, there would be:

GLOBAL_COM_OBJ -|| JSCRIPT_OBJ_CHAIN -> COM_OBJ -|| GLOBAL_COM_OBJ

"-||" means chain broken.

And the same for the global variable object:

GLOBAL_SCOPE_OBJECT -|| JSCRIPT_OBJ_CHAIN -> COM_OBJ ->
JSCRIPT_SCOPE_CHAIN -|| GLOBAL_SCOPE_OBJECT

A leak won't occur unless the chain is broken. If the chain is broken
automatically for global object and global variable object then that
leak won't occur.

Someone from Microsoft could probably explain how IE implements page
tear down.

[1]http://blogs.msdn.com/ericlippert/archive/2005/05/04/414684.aspx

David Mark

unread,
Dec 24, 2009, 8:10:07 PM12/24/09
to
On Dec 24, 8:00 pm, Garrett Smith <dhtmlkitc...@gmail.com> wrote:
> Asen Bozhilov wrote:
> > Garrett Smith wrote:
> >> David Mark wrote:
>
> >>> No, you are just confusing the uninitiated with your confusion.
> >> You wrote:
>
> >> | Ajax is global.  It's not referenced by the local Activation
> >> | Object.  If it were, virtually everything would leak (think about it).
>
> >> The Ajax object is not a member of the containing scope, but it is a
> >> member of an object in the containing scope's containing scope.
>
> > If you are correct:
>
> > window.onload = function(){};
>
> > That will be produce circular reference. If `window' host object is
> > property of Global Object diagram is:
>
> > Global Object -> window -> onload -> AF[[scope]] -> Global Object
>
> Right.

Wrong, no leak. Give it up.

Garrett Smith

unread,
Dec 24, 2009, 10:57:53 PM12/24/09
to

It must be frustrating not being able to explain things.

Thomas 'PointedEars' Lahn

unread,
Dec 25, 2009, 9:43:43 AM12/25/09
to
David Mark wrote:

> On Dec 23, 10:38 pm, JR <groups_j...@yahoo.com.br> wrote:
>> Internet Explorer 7 supports the legacy implementation of XMLHTTP in
>> addition to the new native object, so pages currently using the
>> ActiveX control do not have to be rewritten. However, it is more
>> efficient to create a native scriptable object than to create an
>> ActiveX object. This is especially beneficial to those AJAX
>> applications that create a new XMLHTTP object for each request.
>
> Yes. Lot of those. :(

While it might be more efficient to use the new "native object" (it isn't
one) over the ActiveX object, it is less helpful, and not suited for a
general-purpose XHR library: by contrast, it does not support `file://' URIs
and it is not backwards-compatible.


PointedEars
--
realism: HTML 4.01 Strict
evangelism: XHTML 1.0 Strict
madness: XHTML 1.1 as application/xhtml+xml
-- Bjoern Hoehrmann

JR

unread,
Dec 25, 2009, 11:11:37 AM12/25/09
to
On Dec 24, 8:59 pm, Thomas 'PointedEars' Lahn <PointedE...@web.de>
wrote:

> David Mark wrote:
> > On Dec 23, 3:57 pm, JR <groups_j...@yahoo.com.br> wrote:
> >> On Dec 23, 3:59 pm, Mychal Hackman <mycha...@gmail.com> wrote:
> >> > //lookup other progIds
> >> > }else if(typeof window.ActiveXObject != 'undefined'){
> >> > try{
> >> > return new ActiveXObject('Microsoft.XMLHTTP');
> >> > }catch(e){ return false; }
>
> >> Firstly, lose that "return false" in the catch(e) { } block. Secondly,
> >> you've got to try "Msxml2.XMLHTTP" too, not just "Microsoft.XMLHTTP".
>
> > As noted.
>
> What would one need "Msxml2.XMLHTTP" for?

According to Adam Wiener, Lead Program Manager for Data
Programmability/XML Technologies (Microsoft), the “Microsoft”
namespace is actually older and is only implemented in MSXML3 for
legacy support. So “msxml2” namespace should be used for
instantiating objects.

http://blogs.msdn.com/xmlteam/archive/2006/10/23/using-the-right-version-of-msxml-in-internet-explorer.aspx

--
JR

JR

unread,
Dec 25, 2009, 11:18:52 AM12/25/09
to
On Dec 25, 12:43 pm, Thomas 'PointedEars' Lahn <PointedE...@web.de>
wrote:

> David Mark wrote:
> > On Dec 23, 10:38 pm, JR <groups_j...@yahoo.com.br> wrote:
> >> Internet Explorer 7 supports the legacy implementation of XMLHTTP in
> >> addition to the new native object, so pages currently using the
> >> ActiveX control do not have to be rewritten. However, it is more
> >> efficient to create a native scriptable object than to create an
> >> ActiveX object. This is especially beneficial to those AJAX
> >> applications that create a new XMLHTTP object for each request.
>
> > Yes.  Lot of those.  :(
>
> While it might be more efficient to use the new "native object" (it isn't
> one) over the ActiveX object, it is less helpful, and not suited for a
> general-purpose XHR library: by contrast, it does not support `file://' URIs
> and it is not backwards-compatible.

`file://' URIs are blocked by default in FF 3 for instance
(about:config, security.fileuri.strict_origin_policy).

-- JR

Thomas 'PointedEars' Lahn

unread,
Dec 25, 2009, 12:41:02 PM12/25/09
to
Garrett Smith wrote:

> Asen Bozhilov wrote:
>> David Mark wrote:
>>> Yes. There are lots of examples (e.g. all ActiveX methods):-
>> No. From that i can see they have own implementation of internal
>> [[Get]] and [[Put]] methods.
>>
>> var a = window.external.addFavorite;
>>
>> No type conversion but error is still there. Interesting in that part
>> is typeof.
>
> [...]
>
> The error is unrelated to type conversion.

True. It is related to the implementation-dependent [[Get]] method of the
host object that `window.external' refers to, which is triggered by the
property accessor (ES3F/ES5, 11.2.1).

> The typeof operator works on reference and so it seems that typeof can't
> get a reference, then it returns "unknown".

"unknown" is one possible implementation-dependent value returned by the
algorithm for the `typeof' operator as triggered by its step 5 (ES3F,
11.4.3) or 3 (ES5, 11.4.3). It does not require the type of the operand to
be a non-Reference, and it is not likely for a property accessor to a
method to result in such a value.


PointedEars
--
Prototype.js was written by people who don't know javascript for people
who don't know javascript. People who don't know javascript are not
the best source of advice on designing systems that use javascript.
-- Richard Cornford, cljs, <f806at$ail$1$8300...@news.demon.co.uk>

David Mark

unread,
Dec 25, 2009, 1:43:16 PM12/25/09
to

Go back and read my posts to this thread. I explained your
misunderstanding at least twice. Baiting won't garner a third. ;)

Asen Bozhilov

unread,
Dec 25, 2009, 4:14:21 PM12/25/09
to
Thomas 'PointedEars' Lahn wrote:

> "unknown" is one possible implementation-dependent value returned by the
> algorithm for the `typeof' operator as triggered by its step 5 (ES3F,
> 11.4.3) or 3 (ES5, 11.4.3).  It does not require the type of the operand to
> be a non-Reference, and it is not likely for a property accessor to a
> method to result in such a value.

All right but step 4 in 11.4.3 ECMA3 explicit say:

| 4. Call GetValue(Result(1)).

So again we have implicit invocation of [[Get]]. They have error
handling in typeof implementation or treat that for special case in
theirs [[Get]] method. Can you give a clear explanation or better
supposition?

Merry Christmas.

Thomas 'PointedEars' Lahn

unread,
Dec 27, 2009, 8:25:12 PM12/27/09
to
JR wrote:

That does not answer my question, though.

And since "Microsoft.XMLHTTP" apparently means the same as
"MSXML2.XMLHTTP.2.0", what he suggested in 2006 did not make sense then and
is not making more sense now. Replacing the identifier with
"MSXML2.XMLHTTP.3.0" as he suggests would break compatibility. Adding the
identifier would decrease efficiency for older implementations at no
advantage. Surely you are not suggesting Microsoft would deliberately
break backwards-compatibility?

JR

unread,
Dec 28, 2009, 6:40:35 PM12/28/09
to
On Dec 27, 11:25 pm, Thomas 'PointedEars' Lahn <PointedE...@web.de>
wrote:

> JR wrote:
> > Thomas 'PointedEars' Lahn wrote:
> >> David Mark wrote:
> >> > On Dec 23, 3:57 pm, JR <groups_j...@yahoo.com.br> wrote:
> >> >> On Dec 23, 3:59 pm, Mychal Hackman <mycha...@gmail.com> wrote:
> >> >> Firstly, lose that "return false" in the catch(e) { } block.
> >> >> Secondly, you've got to try "Msxml2.XMLHTTP" too, not just
> >> >> "Microsoft.XMLHTTP".
>
> >> > As noted.
>
> >> What would one need "Msxml2.XMLHTTP" for?
>
> > According to Adam Wiener, Lead Program Manager for Data
> > Programmability/XML Technologies (Microsoft), the “Microsoft”
> > namespace is actually older and is only implemented in MSXML3 for
> > legacy support.  So “msxml2” namespace should be used for
> > instantiating objects.
>
> >http://blogs.msdn.com/xmlteam/archive/2006/10/23/using-the-right-vers...

>
> of-msxml-in-internet-explorer.aspx
>
> That does not answer my question, though.
>
> And since "Microsoft.XMLHTTP" apparently means the same as    
> "MSXML2.XMLHTTP.2.0", what he suggested in 2006 did not make sense then and
> is not making more sense now.  Replacing the identifier with
> "MSXML2.XMLHTTP.3.0" as he suggests would break compatibility.  Adding the
> identifier would decrease efficiency for older implementations at no
> advantage.  Surely you are not suggesting Microsoft would deliberately
> break backwards-compatibility?

According to MSDN (http://msdn.microsoft.com/en-us/library/
cc507441%28VS.85%29.aspx)
- "MSXML 3.0 and prior versions of MSXML are version independent.
MSXML 3.0 was the last version of MSXML to support version-independent
CLSIDs and ProgIDs."
- "MSXML 3.0 is supported in Windows Vista; Windows Server 2003;
Windows XP; Windows 2000; Windows 98; Windows Millenium Edition (ME)."

You seem to be mistaking MSXML versions with IE versions. You may look
for msxml3.dll (v. 3.0) in your Windows\System32 folder to verify the
above information.

Since the OP's original code 'try-catch' only version 2.0
(Microsoft.XMLHTTP), I think his code needs to test for version 3.0 as
well (MSXML2.XMLHTTP).

--
JR

JR

unread,
Dec 29, 2009, 7:31:12 AM12/29/09
to

Actually, you only need to use new ActiveXObject("Msxml2.XMLHTTP"). Do
not worry about the current MSXML version registered in the client's
computer.

--
JR

JR

unread,
Dec 29, 2009, 8:05:03 AM12/29/09
to

So, returning to the OP's original code, I'd suggest the following
snippet:

Ajax = {
transport : (function () {
var req = null;


if (typeof window.XMLHttpRequest != "undefined") {

// IE7+, FF, Opera 8.0+, Safari.
try { req = new XMLHttpRequest(); }
catch (e) { } // Ignores any exception.
} else if (typeof window.ActiveXObject != "undefined") {
//IE 5+, 6, or IE7/8 with native XMLHTTP support disabled.
try { req = new ActiveXObject("Msxml2.XMLHTTP"); }
catch (ex) {
try { req = new ActiveXObject("Microsoft.XMLHTTP"); }
catch (expt) { }
}
} else {
// alert("Your browser doesn't support AJAX. Sorry!");
}
return req;
})();

// other properties.
};

--
JR

Garrett Smith

unread,
Dec 29, 2009, 1:15:56 PM12/29/09
to
JR wrote:
> On Dec 29, 10:31 am, JR <groups_j...@yahoo.com.br> wrote:
>> On Dec 28, 9:40 pm, JR <groups_j...@yahoo.com.br> wrote:
>>
>>
>>
>>> On Dec 27, 11:25 pm, Thomas 'PointedEars' Lahn <PointedE...@web.de>
>>> wrote:
>>>> JR wrote:
>>>>> Thomas 'PointedEars' Lahn wrote:
>>>>>> David Mark wrote:
>>>>>>> On Dec 23, 3:57 pm, JR <groups_j...@yahoo.com.br> wrote:
>>>>>>>> On Dec 23, 3:59 pm, Mychal Hackman <mycha...@gmail.com> wrote:

[...]

> So, returning to the OP's original code, I'd suggest the following
> snippet:
>
> Ajax = {

Don't forget var.

JR

unread,
Dec 29, 2009, 4:10:59 PM12/29/09
to
On Dec 29, 4:15 pm, Garrett Smith <dhtmlkitc...@gmail.com> wrote:
> JR wrote:
> > On Dec 29, 10:31 am, JR <groups_j...@yahoo.com.br> wrote:
> >> On Dec 28, 9:40 pm, JR <groups_j...@yahoo.com.br> wrote:
>
> >>> On Dec 27, 11:25 pm, Thomas 'PointedEars' Lahn <PointedE...@web.de>
> >>> wrote:
> >>>> JR wrote:
> >>>>> Thomas 'PointedEars' Lahn wrote:
> >>>>>> David Mark wrote:
> >>>>>>> On Dec 23, 3:57 pm, JR <groups_j...@yahoo.com.br> wrote:
> >>>>>>>> On Dec 23, 3:59 pm, Mychal Hackman <mycha...@gmail.com> wrote:
>
> [...]
>
> > So, returning to the OP's original code, I'd suggest the following
> > snippet:
>
> > Ajax = {
>
> Don't forget var.

Oops! Thank you!

I'd also substitute:
- 'Ajax' for 'var ajax = {...}', because 'ajax' won't be used as a
constructor; and
- the semicolon (;) after the 'transport' method for just a comma (,)
because there are other properties coming after it.

Cheers,
JR

Hans-Georg Michna

unread,
Dec 31, 2009, 9:37:01 AM12/31/09
to
Had to look into this last night and will use something like
this, gleaned from Wikipedia:

if (typeof XMLHttpRequest == "undefined") {
XMLHttpRequest = function() {
try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); }
catch (ignore) {}
try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); }
catch (ignore) {}
throw new Error("This browser does not support
XMLHttpRequest.");
};
}

If you want to support browsers older than IE6, you may have to
add things like:

try { return new ActiveXObject("Msxml2.XMLHTTP"); }
catch (ignore) {}
try { return new ActiveXObject("Microsoft.XMLHTTP"); }
catch (ignore) {}

But are you sure your JavaScript will actually run perfectly in
Internet Explorer 5.x or other older browsers? Fortunately I
don't have to support those.

Hans-Georg

JR

unread,
Dec 31, 2009, 4:54:10 PM12/31/09
to
On 31 dez, 12:37, Hans-Georg Michna <hans-

georgNoEmailPle...@michna.com> wrote:
> Had to look into this last night and will use something like
> this, gleaned from Wikipedia:
>
> if (typeof XMLHttpRequest == "undefined") {
>   XMLHttpRequest = function() {
>     try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); }
>       catch (ignore) {}
>     try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); }
>       catch (ignore) {}
>     throw new Error("This browser does not support
> XMLHttpRequest.");
>   };
>
> }

Firstly, the code should try new XMLHttpRequest() before the
activeXObject, because it's supported in all of the new versions of
IE, FF, Safari, Opera, and Chrome, just to mention the 'majors'.

In addition, David Mark has made a negative comment on a similar code
that I've copied (and pasted here) from the MSDN site. I think he used
the term 'awful' to describe the attempt to override the
XMLHttpRequest object.


> If you want to support browsers older than IE6, you may have to
> add things like:
>
>     try { return new ActiveXObject("Msxml2.XMLHTTP"); }
>       catch (ignore) {}
>     try { return new ActiveXObject("Microsoft.XMLHTTP"); }
>       catch (ignore) {}
>
> But are you sure your JavaScript will actually run perfectly in
> Internet Explorer 5.x or other older browsers? Fortunately I
> don't have to support those.

According to my readings on the Microsoft website (MSDN mainly), it is
not really necessary to specify the version of the Msxml2.XMLHTTP
ActiveX object. When you write 'new ActiveXObject("Msxml2.XMLHTTP");',
the browser (IE) tries to instantiate the active version registered in
the computer's OS (Windows).

Cheers,
JR

Garrett Smith

unread,
Dec 31, 2009, 5:07:37 PM12/31/09
to
Hans-Georg Michna wrote:
> Had to look into this last night and will use something like
> this, gleaned from Wikipedia:
>
> if (typeof XMLHttpRequest == "undefined") {
> XMLHttpRequest = function() {

Why is it that this thread keeps missing var?

The problem with adding a user-defiend global XMLHttpRequest is that it
will trip up other code that makes the same check:-

if(typeof XMLHttpRequest == "undefined") {

Hans-Georg Michna

unread,
Dec 31, 2009, 5:59:23 PM12/31/09
to
On Thu, 31 Dec 2009 13:54:10 -0800 (PST), JR wrote:

>On 31 dez, 12:37, Hans-Georg Michna <hans-
>georgNoEmailPle...@michna.com> wrote:

>> Had to look into this last night and will use something like
>> this, gleaned from Wikipedia:
>>
>> if (typeof XMLHttpRequest == "undefined") {
>> � XMLHttpRequest = function() {
>> � � try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); }
>> � � � catch (ignore) {}
>> � � try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); }
>> � � � catch (ignore) {}
>> � � throw new Error("This browser does not support
>> XMLHttpRequest.");
>> � };
>>
>> }

>Firstly, the code should try new XMLHttpRequest() before the
>activeXObject, because it's supported in all of the new versions of
>IE, FF, Safari, Opera, and Chrome, just to mention the 'majors'.

I guess you didn't read it right. The code checks whether
XMLHttpRequest is undefined and, if so, defines it. Then you can
use XMLHttpRequest as if your browser were standards-conformant.

If the browser is standards-conformant, the code does nothing,
and you use the original XMLHttpRequest.

>According to my readings on the Microsoft website (MSDN mainly), it is
>not really necessary to specify the version of the Msxml2.XMLHTTP
>ActiveX object. When you write 'new ActiveXObject("Msxml2.XMLHTTP");',
>the browser (IE) tries to instantiate the active version registered in
>the computer's OS (Windows).

This doesn't agree with what I learned.

Hey, another year is coming! Have to go and have a drink.

All the best to all the JavaScript junkies for another year of
many sucesses!

Hans-Georg

Hans-Georg Michna

unread,
Dec 31, 2009, 6:05:39 PM12/31/09
to
On Thu, 31 Dec 2009 14:07:37 -0800, Garrett Smith wrote:

>Hans-Georg Michna wrote:

>> Had to look into this last night and will use something like
>> this, gleaned from Wikipedia:
>>
>> if (typeof XMLHttpRequest == "undefined") {
>> XMLHttpRequest = function() {

>Why is it that this thread keeps missing var?
>
>The problem with adding a user-defiend global XMLHttpRequest is that it
>will trip up other code that makes the same check:-
>
>if(typeof XMLHttpRequest == "undefined") {
>
>}

Can't see any problem with it. Another program would likely do
the very same thing. If it finds the global XMLHttpRequest
already, it has to do nothing and can happily use it.

Typing this after shooting fireworks in the air after 2010 just
began over here in Europe. (:-)

Hans-Georg

Thomas 'PointedEars' Lahn

unread,
Dec 31, 2009, 7:47:09 PM12/31/09
to
Garrett Smith wrote:

> Hans-Georg Michna wrote:
>> Had to look into this last night and will use something like
>> this, gleaned from Wikipedia:
>>
>> if (typeof XMLHttpRequest == "undefined") {
>> XMLHttpRequest = function() {
>
> Why is it that this thread keeps missing var?
>
> The problem with adding a user-defiend global XMLHttpRequest is that it
> will trip up other code that makes the same check:-
>
> if(typeof XMLHttpRequest == "undefined") {
>
> }

You are not making any sense.


PointedEars
--
Danny Goodman's books are out of date and teach practices that are
positively harmful for cross-browser scripting.
-- Richard Cornford, cljs, <cife6q$253$1$8300...@news.demon.co.uk> (2004)

Garrett Smith

unread,
Jan 1, 2010, 12:58:51 AM1/1/10
to
Hans-Georg Michna wrote:
> On Thu, 31 Dec 2009 14:07:37 -0800, Garrett Smith wrote:
>
>> Hans-Georg Michna wrote:
>
>>> Had to look into this last night and will use something like
>>> this, gleaned from Wikipedia:
>>>
>>> if (typeof XMLHttpRequest == "undefined") {
>>> XMLHttpRequest = function() {
>
>> Why is it that this thread keeps missing var?
>>
>> The problem with adding a user-defiend global XMLHttpRequest is that it
>> will trip up other code that makes the same check:-
>>
>> if(typeof XMLHttpRequest == "undefined") {
>>
>> }
It makes your user-defined function look like the real deal.

Thomas 'PointedEars' Lahn

unread,
Jan 1, 2010, 9:25:43 AM1/1/10
to
Garrett Smith wrote:

> Hans-Georg Michna wrote:
>> On Thu, 31 Dec 2009 14:07:37 -0800, Garrett Smith wrote:
>>> Hans-Georg Michna wrote:
>>>> Had to look into this last night and will use something like
>>>> this, gleaned from Wikipedia:
>>>>
>>>> if (typeof XMLHttpRequest == "undefined") {
>>>> XMLHttpRequest = function() {
>>>
>>> Why is it that this thread keeps missing var?
>>>
>>> The problem with adding a user-defiend global XMLHttpRequest is that it
>>> will trip up other code that makes the same check:-
>>>
>>> if(typeof XMLHttpRequest == "undefined") {
>>>
>>> }
>
> It makes your user-defined function look like the real deal.

And that is bad[tm], because ...?

David Mark

unread,
Jan 1, 2010, 8:30:50 PM1/1/10
to
On Jan 1, 9:25 am, Thomas 'PointedEars' Lahn <PointedE...@web.de>
wrote:

> Garrett Smith wrote:
> > Hans-Georg Michna wrote:
> >> On Thu, 31 Dec 2009 14:07:37 -0800, Garrett Smith wrote:
> >>> Hans-Georg Michna wrote:
> >>>> Had to look into this last night and will use something like
> >>>> this, gleaned from Wikipedia:
>
> >>>> if (typeof XMLHttpRequest == "undefined") {
> >>>>   XMLHttpRequest = function() {
>
> >>> Why is it that this thread keeps missing var?
>
> >>> The problem with adding a user-defiend global XMLHttpRequest is that it
> >>> will trip up other code that makes the same check:-
>
> >>> if(typeof XMLHttpRequest == "undefined") {
>
> >>> }
>
> > It makes your user-defined function look like the real deal.
>
> And that is bad[tm], because ...?
>

Because they are not exactly equivalent.

Garrett Smith

unread,
Jan 2, 2010, 1:06:25 AM1/2/10
to
Thomas 'PointedEars' Lahn wrote:
> Garrett Smith wrote:
>
>> Hans-Georg Michna wrote:
>>> On Thu, 31 Dec 2009 14:07:37 -0800, Garrett Smith wrote:
>>>> Hans-Georg Michna wrote:
>>>>> Had to look into this last night and will use something like
>>>>> this, gleaned from Wikipedia:
>>>>>
>>>>> if (typeof XMLHttpRequest == "undefined") {
>>>>> XMLHttpRequest = function() {
>>>> Why is it that this thread keeps missing var?
>>>>
>>>> The problem with adding a user-defiend global XMLHttpRequest is that it
>>>> will trip up other code that makes the same check:-
>>>>
>>>> if(typeof XMLHttpRequest == "undefined") {
>>>>
>>>> }
>> It makes your user-defined function look like the real deal.
>
> And that is bad[tm], because ...?

Making the user-defined function look like the real deal is bad because
it isn't. If a script makes a check:-

var IS_NATIVE_XHR = typeof XMLHttpRequest !== "undefined";

- the script is misled. It might seem safe, but it isn't; the
user-defined new XMLHttpRequest() can throw:-

"This browser does not support XMLHttpRequest."

JR

unread,
Jan 2, 2010, 7:48:18 AM1/2/10
to

Yeah, a bad example (Very bad indeed!!!) from Wikipedia:
http://en.wikipedia.org/wiki/XMLHttpRequest

It's not even necessary to check for "Msxml2.XMLHTTP.6.0",
"Msxml2.XMLHTTP.5.0", 4.0 or 3.0. Just try using "Msxml2.XMLHTTP", and
"Microsoft.XMLHTTP" as a last alternative. As I posted earlier, the
version of the MSXML Parser is dependent on the Windows version, not
on the IE version, according to the MSDN article that I cited (on that
post).

--
JR

JR

unread,
Jan 2, 2010, 11:35:27 AM1/2/10
to

I wrote this example to let someone know which XLMHTTP versions are
available on his/her computer:

<script type="text/javascript">
(function () {
var xmlVersions = [
'Microsoft.XMLHTTP',
'Msxml2.XMLHTTP.3.0',
'Msxml2.XMLHTTP.4.0',
'Msxml2.XMLHTTP.5.0',
'Msxml2.XMLHTTP.6.0'
], i, len, xhr, ret = "<p>";
for (i = 0, len = xmlVersions.length; i < len; i++) {
try {
xhr = new ActiveXObject(xmlVersions[i]);
if (xhr) { ret += xmlVersions[i] +"<br>"; }
} catch(ex) { }
}
document.write('MSXML versions available on this computer:<br>' +
ret + '</p>');
})();
</script>

--
JR

David Mark

unread,
Jan 2, 2010, 4:24:54 PM1/2/10
to

Yes, that seems reasonable. I don't recall ever having to deal with
the version numbers instantiating COM objects (for any component) in
desktop development (of course, it's been quite a long time). IIRC,
looking at how the entries are registered with the OS is
illuminating. So glad I never have to deal with such MS nonsense
again. :)

This is from the old CWR project (and ended up in My Library). It was
discussed (here) quite a bit back then. I don't remember the details,
but the rationale seemed reasonable to me at the time.

// for legacy eg. IE 5
function() {
return new global.ActiveXObject("Microsoft.XMLHTTP");
},
// for fully patched Win2k SP4 and up
function() {
return new global.ActiveXObject("Msxml2.XMLHTTP.3.0");
},
// IE 6 users that have updated their msxml dll files.
function() {
return new global.ActiveXObject("Msxml2.XMLHTTP.6.0");
},

Thomas 'PointedEars' Lahn

unread,
Jan 4, 2010, 5:10:10 AM1/4/10
to
Garrett Smith wrote:

> Thomas 'PointedEars' Lahn wrote:
>> Garrett Smith wrote:
>>> Hans-Georg Michna wrote:
>>>> On Thu, 31 Dec 2009 14:07:37 -0800, Garrett Smith wrote:
>>>>> The problem with adding a user-defiend global XMLHttpRequest is that
>>>>> it will trip up other code that makes the same check:-
>>>>>
>>>>> if(typeof XMLHttpRequest == "undefined") {
>>>>>
>>>>> }
>>> It makes your user-defined function look like the real deal.
>>
>> And that is bad[tm], because ...?
>
> Making the user-defined function look like the real deal is bad because
> it isn't.

Nonsense.

> If a script makes a check:-
>
> var IS_NATIVE_XHR = typeof XMLHttpRequest !== "undefined";
>
> - the script is misled. It might seem safe, but it isn't; the
> user-defined new XMLHttpRequest() can throw:-
>
> "This browser does not support XMLHttpRequest."

And that is bad[tm], because ...? If it CAN `throw' (there is no MUST),
scripts using it can (and should) `try'...`catch'.

Thomas 'PointedEars' Lahn

unread,
Jan 4, 2010, 5:42:55 AM1/4/10
to
JR wrote:

> Thomas 'PointedEars' Lahn wrote:
>> JR wrote:
>> > Thomas 'PointedEars' Lahn wrote:
>> >> David Mark wrote:
>> >> > On Dec 23, 3:57 pm, JR <groups_j...@yahoo.com.br> wrote:
>> >> >> On Dec 23, 3:59 pm, Mychal Hackman <mycha...@gmail.com> wrote:
>> >> >> Firstly, lose that "return false" in the catch(e) { } block.
>> >> >> Secondly, you've got to try "Msxml2.XMLHTTP" too, not just
>> >> >> "Microsoft.XMLHTTP".
>> >> > As noted.
>> >> What would one need "Msxml2.XMLHTTP" for?
>> >
>> > According to Adam Wiener, Lead Program Manager for Data
>> > Programmability/XML Technologies (Microsoft), the “Microsoft”
>> > namespace is actually older and is only implemented in MSXML3 for
>> > legacy support. So “msxml2” namespace should be used for
>> > instantiating objects.
>> >
>> > http://blogs.msdn.com/xmlteam/archive/2006/10/23/using-the-right

>> > version-of-msxml-in-internet-explorer.aspx


>>
>> That does not answer my question, though.
>>
>> And since "Microsoft.XMLHTTP" apparently means the same as
>> "MSXML2.XMLHTTP.2.0", what he suggested in 2006 did not make sense then
>> and is not making more sense now. Replacing the identifier with
>> "MSXML2.XMLHTTP.3.0" as he suggests would break compatibility. Adding
>> the identifier would decrease efficiency for older implementations at no
>> advantage. Surely you are not suggesting Microsoft would deliberately
>> break backwards-compatibility?
>
> According to MSDN (http://msdn.microsoft.com/en-us/library/
> cc507441%28VS.85%29.aspx)
> - "MSXML 3.0 and prior versions of MSXML are version independent.
> MSXML 3.0 was the last version of MSXML to support version-independent
> CLSIDs and ProgIDs."

So what?

> - "MSXML 3.0 is supported in Windows Vista; Windows Server 2003;
> Windows XP; Windows 2000; Windows 98; Windows Millenium Edition (ME)."

So what?



> You seem to be mistaking MSXML versions with IE versions.

No, I don't. Curious how you got that idea again.

> You may look
> for msxml3.dll (v. 3.0) in your Windows\System32 folder to verify the
> above information.

This information is irrelevant to the discussed problem.



> Since the OP's original code 'try-catch' only version 2.0
> (Microsoft.XMLHTTP), I think his code needs to test for version 3.0 as
> well (MSXML2.XMLHTTP).

What for, if "Microsoft.XMLHTTP" is apparently both upwards and downwards-
compatible (running on Vista with msxml3.dll to msxml6.dll, and Windows XP
with msxml3.dll only, but no msxml2.dll or msxml1.dll here)?

And suppose the advantage is bugfixes in the greater versions, why not
prefer all the greater versions to get the latest bugfixes?

Your argument can be turned up and down, it simply does not make any sense.

JR

unread,
Jan 4, 2010, 9:28:58 AM1/4/10
to

No, the argument is clear for those who pay minimum attention while
reading.

JR

Hans-Georg Michna

unread,
Jan 4, 2010, 10:22:31 AM1/4/10
to
On Mon, 04 Jan 2010 11:42:55 +0100, Thomas 'PointedEars' Lahn
wrote:

>And suppose the advantage is bugfixes in the greater versions, why not
>prefer all the greater versions to get the latest bugfixes?

Perhaps not all of them. Microsoft recommends not to use
versions 4 and 5. They say, check for 6.0. If that is not there,
use 3.0.

All earlier versions are for IE versions before 6.

Hans-Georg

Thomas 'PointedEars' Lahn

unread,
Jan 4, 2010, 10:37:40 AM1/4/10
to
JR wrote:

Is that so? Then, pray tell, what exactly is the advantage of
trying "Msxml2.XMLHTTP" before or instead of "Microsoft.XMLHTTP"?


PointedEars
--
Use any version of Microsoft Frontpage to create your site.
(This won't prevent people from viewing your source, but no one
will want to steal it.)
-- from <http://www.vortex-webdesign.com/help/hidesource.htm> (404-comp.)

JR

unread,
Jan 4, 2010, 2:33:28 PM1/4/10
to
On 4 jan, 13:22, Hans-Georg Michna <hans-

georgNoEmailPle...@michna.com> wrote:
> On Mon, 04 Jan 2010 11:42:55 +0100, Thomas 'PointedEars' Lahn
> wrote:
>
> >And suppose the advantage is bugfixes in the greater versions, why not
> >prefer all the greater versions to get the latest bugfixes?
>
> Perhaps not all of them. Microsoft recommends not to use
> versions 4 and 5. They say, check for 6.0. If that is not there,
> use 3.0.

I've found an article on MSDN stating exactly the same. Furthermore,
there's another article on MSDN that doesn't encourage using version
5, which is installed by Office 2003. Inspecting my computer which has
Office 2003, I've confirmed that msxml5.dll is located in:
"C:\Program files\Common files\Microsoft Shared\OFFICE11\MSXML5.DLL"

> All earlier versions are for IE versions before 6.

Nowadays, it might be odd to find IE 5 or 5.5 on an XP or Vista
installation. But, in that case, I suppose IE 5 could instantiate
versions 3 and 6, because both XP and Vista come with the mentioned
versions of MSXML. But I can't test this supposition.

After searching my Windows Vista registry for "Msxml2.XMLHTTP", I've
found out two CLSID keys: one related to the "msxml2.dll" (version 2.6
on my system) and the other related to the "msxml3.dll" (version 3.0).
This is consistent with the MSDN article "MSXML 3.0 GUIDs and
ProgIDs" (http://msdn.microsoft.com/en-us/library/ms766426%28VS.
85%29.aspx).

But searching further, I've noticed that both "Microsoft.XMLHTTP" and
"Microsoft.XMLHTTP.1.0" are related to the msxml3.dll too. What? Now
it's not consistent with the same article on MSDN.

I've used VBA to instantiating "Msxml2.XMLHTTP", but I couldn't find
any property informing the dll filename or XMLHTTP version. I think
I'd need some C++ code to inspect what is really going on...

In short, after studying this matter I think the best approach would
be (referring to the OP's example):

var ajax = {


transport : (function () {
var req = null;
if (typeof window.XMLHttpRequest != "undefined") {
// IE7+, FF, Opera 8.0+, Safari.
try { req = new XMLHttpRequest(); }

catch (ex1) { } // Ignores.


} else if (typeof window.ActiveXObject != "undefined") {
//IE 5+, 6, or IE7/8 with native XMLHTTP support disabled.

try { req = new ActiveXObject("Msxml2.XMLHTTP.6.0"); }
catch (ex2) {
try { req = new ActiveXObject("Msxml2.XMLHTTP.3.0"); }
catch (ex3) {
try { req = new ActiveXObject("Microsoft.XMLHTTP"); }
catch (ex4) { } // game over.


}
}
} else {
// alert("Your browser doesn't support AJAX. Sorry!");
}
return req;

})(),

0 new messages