![]() |
typeof for feature testing host methods
There have been many threads lately about testing for the existence of
host object methods. I have usually just feature tested the existence of host methods with the following if (document.getElementById) There is concern from several people in the group that this is insufficient for at least a couple reasons. One reason for concern is the above test does not determine if document.getElementById is callable. No one has reported a case where a browser that has document.getElementById will be non-callable. In some browsers it may be that some other JavaScript has assigned a non- callable value to the the document.getElementById property. In those browsers, it may also be true that someone has assigned a function to document.getElementById. If this has been done then none of the proposed tests would detect that the callable value is not the expected callable value. Thomas Lahn seems particularly concerned about these problems (and he is preparing to tell I am wrong or that I have missed the point.) Another reason for concern is that even though the host may provide a callable document.getElementById but that when writing just "if (document.getElementById)" it isn't the [[Call]] property the [[Get]] property that is used. David Mark seems to think this is a problem with some (all?) ActiveX objects. All host objects are required to implement [[Get]] so IE is not ECMAScript compliant if it does not. So when we are feature testing host objects we are worried about testing ECMAScript non-compliant browsers. Both Thomas' and David's feature testing uses typeof for testing host methods. Thomas tests the document.evaluate host method <URL: http://pointedears.de/scripts/types.js> function isMethodType(s) { return /\b(function|object)\b/i.test(s); } <URL: http://pointedears.de/scripts/dhtml.js> if (this.isMethodType(typeof document.evaluate) && document.evaluate) { // W3C DOM Level 3 XPath return function dhtml_getElemByTagName(s, i) { if (!s) { // --------------------- David tests for document.getElementById <URL: http://groups.google.com/group/comp.lang.javascript/msg/d8a9ec709205ae47> var reFeaturedMethod = new RegExp('^function|object$', 'i'); var isFeaturedMethod = function(o, m) { var t = typeof(o[m]); return !!((reFeaturedMethod.test(t) && o[m]) || t == 'unknown'); }; if (isFeaturedMethod(doc, 'getElementById')) { return function(id, docNode) { return idCheck((docNode || doc).getElementById(id), id); }; } // --------------------- The ECMA standard says that the value of a "typeof hostObject" expression can be any string. So both Thomas' and David's techniques could result in false negatives which would leave a browser unenabled. This is better than a false positive where a function is enabled in a browser but the function will not function. What I'm more concerned about is that typeof is being considered a solution for the unimplemented [[Get]] problem David wrote about. Both if (document.getElementById) and typeof document.getElementById are described as calling [[Get]] somewhere in their evaluation. If a browser really did not supply the [[Get]] property at all for an object then both likely throw an error and probably a TypeError. (More serious alternatives would be crashing the browser or computer and we can't protect against that.) The ECMAScript specification of typeof does not say it will catch that error. Using typeof isn't some sort of panacea for feature detecting a host method to avoid errors thrown in non-compliant browsers. It does seem that using the technique "typeof document.getElementById" works better in IE than "if (document.getElementById)" if document happened to be an ActiveX object. However, according to the ECMAScript standard, there is no reason one should be superior to the other. Some additional protection for non-compliant browsers could be gained by adjusting David's code, for example, by adding a try-catch. I've also changed it to check "unknown" objects for null. It seems to me an "unknown" object that is null would be somewhat useless. var reFeaturedMethod = new RegExp('^function|object|unknown$', 'i'); var isFeaturedMethod = function(o, m) { try { var t = typeof(o[m]); // throws error if o doesn't have [[Get]] return !!(reFeaturedMethod.test(t) && o[m]); } catch(e) { return false; } }; This is a general mess thanks to the possible behaviors of non- compliant browsers. It is somewhat clear that using typeof for testing a host object feature in a non-complaint browser is not guaranteed to work but does seem to work in the population of browsers today. It seems to be a practical solution or at least a better way to feature detect. It is not a theoretical solution since typeof doesn't catch errors. -- Peter Code Worth Recommending Project http://cljs.michaux.ca/ |
Re: typeof for feature testing host methods
On Dec 14, 9:04 pm, Peter Michaux <petermich...@gmail.com> wrote:
> I've > also changed it to check "unknown" objects for null. It seems to me an > "unknown" object that is null would be somewhat useless. > > var reFeaturedMethod = new RegExp('^function|object|unknown$', 'i'); > > var isFeaturedMethod = function(o, m) { > try { > var t = typeof(o[m]); // throws error if o doesn't have [[Get]] > return !!(reFeaturedMethod.test(t) && o[m]); > } > catch(e) { > return false; > } > > }; Laps in judgment above. Should be var reFeaturedMethod = new RegExp('^function|object$', 'i'); var isFeaturedMethod = function(o, m) { try { var t = typeof(o[m]); // throws error if o doesn't have [[Get]] return !!((reFeaturedMethod.test(t) && o[m]) || t == 'unknown'); } catch(e) { return false; } }; -- Peter Code Worth Recommending Project http://cljs.michaux.ca/ |
Re: typeof for feature testing host methods
On Dec 15, 10:04 am, Peter Michaux <petermich...@gmail.com> wrote:
> var isFeaturedMethod = function(o, m) { > try { > var t = typeof(o[m]); // throws error if o doesn't have [[Get]] ----------------------------- To avoid errors and try...catch: var t = typeof Object(o)[m]; |
Re: typeof for feature testing host methods
On Dec 14, 10:49 pm, AKS <aksus...@yandex.ru> wrote:
> On Dec 15, 10:04 am, Peter Michaux <petermich...@gmail.com> wrote: > > > var isFeaturedMethod = function(o, m) { > > try { > > var t = typeof(o[m]); // throws error if o doesn't have [[Get]] > > ----------------------------- > > To avoid errors and try...catch: > > var t = typeof Object(o)[m]; What will that do? Calling Object(o) as a function with an object for the argument will call ToObject(o) in section 9.9 in ECMAScript 3rd. When ToObject(o) is passed an object it just returns that object with no conversion. So "typeof Object(o)[m]" is the same as "typeof o[m]". -- Peter Code Worth Recommending Project http://cljs.michaux.ca/ |
Re: typeof for feature testing host methods
On Dec 15, 11:57 am, Peter Michaux <petermich...@gmail.com> wrote:
> So "typeof Object(o)[m]" is the same as "typeof o[m]". I was mistaken (have thought of null), excuse me. |
Re: typeof for feature testing host methods
On Dec 15, 8:04 am, Peter Michaux <petermich...@gmail.com> wrote:
> There have been many threads lately about testing for the existence of > host object methods. I have usually just feature tested the existence > of host methods with the following > > if (document.getElementById) > > There is concern from several people in the group that this is > insufficient for at least a couple reasons. > > One reason for concern is the above test does not determine if > document.getElementById is callable. No one has reported a case where > a browser that has document.getElementById will be non-callable. In > some browsers it may be that some other JavaScript has assigned a non- > callable value to the the document.getElementById property. A really good program/programmer must expose two main thinking features: modularity and synthesis. Modularity makes any task being a single indivisible unit where any further granularity is either impossible or pointless. Only _after_ that one can start with synthesis so to see what units are possible can be overlapped with the execution blocks. Modularity was always a weak point of some people in clj because of the tradition to simply bring all possible/near possible/nearly impossible failure possibility from all accross the Web and dumping them into the same subroutine. In the particular case you are asking about there are two completely different tasks to deal with: 1) a presence of a particular DOM method in the factory state of a particular UA. 2) a possibility of a particular DOM method being hidden behind a maskon at runtime. The first task for document.getElementById in the particular is not any more actual and it doesn't worth any programming efforts. The second task for document element methods fails under the category of a script developer actively trying to produce a non-working code. My position remains the same here: so let him. Still the maskon problem for windows host object methods is actual and important. You may find interesting to read my post about the maskon problem at http://groups.google.com/group/comp....a858c19f383df0 It is also useful to read the whole thread inspired my post about the 23rd Chaos Communication Congress in 2006 http://groups.google.com/group/comp....14bbdba707b891 |
Re: typeof for feature testing host methods
In the linked post of mine:
http://groups.google.com/group/comp....a858c19f383df0 I have explained why I would like do not express myself publicly on the maskon problem though anyone is welcome of course. Somehow you guys finally arrived to a serious programming task, moreover to the task where web-developers and browser-developers are being in a sharp stand: thus what is considered as a security measure by ones - it is considered as a security violation by other side - and vice versa. But once again it is not related with document.getElementById method for a common use library. For the original topic the answer is the same, a reliable universal wrapper is function $(id) { return document.getElementById(id); } and not a single char extra. Since the start of magicFunction/Greeasemonkey/Squid/and Co. deal I had to write a number of programs ensuring unaltered 3rd party content delivery to the end client or deny on service of no other way around. Just take a deep breath please: I never in my life participated in any illegal activity including virus and trojan destribution. Just in some businesses - it is not a general rule of the Web - one either takes what content provider requires or not being served at all. Like one may pick up only red flowers in the field but left all blue ones; at the same time one may not pull out bonus 6oz shampoo bottle from the bonus package and take only that one. Again: a particular situation may require a particular handling. Back to the subject: From the programmatical point of view IE is the most difficult to fight with maskons, Fx is more eazy on that because of its slavery ECMA standard emulation window === this === Global. But neither with IE nor with Fx I want to produce or accelerate the next "security improvement" by the producers so forced to fix the libraries once over again. As a compromise I can give you a stripped down version of one of my year 2006 testcases for IE6. It doesn't cure the problem, but it still tells you that you have a problem. One may as a mind exercise to find the alternative for Fx: if more hints are needed I may provide them. <html> <head> <title>Maskons : IE : ie/2006/023</title> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <script type="text/jscript"> function maskonize() { window.ActiveXObject = psiConstructor; var _expando = document.expando; document.expando = true; document.getElementById = psiCollector; document.expando = _expando; window.setTimeout('takeRedPill()', 10); } function takeRedPill() { if (typeof window.ActiveXObject. prototype != 'undefined') { /* Maskon instead of real ActiveXObject */ /* Maskon factory first found and destroyed */ // Code is not disclosed /* Real ActiveXObject is restored */ // Code is not disclosed window.alert('ActiveXObject: Matrix has you!'); } if (typeof document.getElementById. prototype != 'undefined') { /* Maskon instead of real getElementById */ /* Maskon factory first found and destroyed */ // Code is not disclosed /* Real getElementById is restored */ // Code is not disclosed window.alert('getElementById: Matrix has you!'); } } function psiConstructor() {} function psiCollector() {return new Array;} function psiObjector() {return new Object;} function psiRelaxer() {return true;} window.onload = maskonize; </script> </head> <body> </body> </html> |
Re: typeof for feature testing host methods
On Dec 15, 1:46 am, Peter Michaux <petermich...@gmail.com> wrote:
> On Dec 14, 9:04 pm, Peter Michaux <petermich...@gmail.com> wrote: > > > > > > > I've > > also changed it to check "unknown" objects for null. It seems to me an > > "unknown" object that is null would be somewhat useless. > > > var reFeaturedMethod = new RegExp('^function|object|unknown$', 'i'); > > > var isFeaturedMethod = function(o, m) { > > try { > > var t = typeof(o[m]); // throws error if o doesn't have [[Get]] > > return !!(reFeaturedMethod.test(t) && o[m]); > > } > > catch(e) { > > return false; > > } > > > }; > > Laps in judgment above. Should be > > var reFeaturedMethod = new RegExp('^function|object$', 'i'); > > var isFeaturedMethod = function(o, m) { > try { > var t = typeof(o[m]); // throws error if This does not throw an error. Example: (typeof window.external.addFavorite) Evaluates to "unknown" (window.external.addFavorite) Throws an error in IE. So I don't see what benefit the try clause adds. However, it does have the unwanted effect of short-circuiting feature testing in agents that cannot parse try clauses. |
Re: typeof for feature testing host methods
On Dec 15, 4:46 am, VK <schools_r...@yahoo.com> wrote:
> On Dec 15, 8:04 am, Peter Michaux <petermich...@gmail.com> wrote: > > > There have been many threads lately about testing for the existence of > > host object methods. I have usually just feature tested the existence > > of host methods with the following > > > if (document.getElementById) > > > There is concern from several people in the group that this is > > insufficient for at least a couple reasons. > > > One reason for concern is the above test does not determine if > > document.getElementById is callable. No one has reported a case where > > a browser that has document.getElementById will be non-callable. In > > some browsers it may be that some other JavaScript has assigned a non- > > callable value to the the document.getElementById property. > [snip] > In the particular case you are asking about there are two completely > different tasks to deal with: > > 1) a presence of a particular DOM method in the factory state of a > particular UA. Can you define "factory state?" > 2) a possibility of a particular DOM method being hidden behind a > maskon at runtime. Behind a what? > > The first task for document.getElementById in the particular is not > any more actual and it doesn't worth any programming efforts. It isn't clear what you think the first task is. > The second task for document element methods fails under the category > of a script developer actively trying to produce a non-working code. Whatever that means. > My position remains the same here: so let him. Still the maskon > problem for windows host object methods is actual and important. You It seems you don't understand the problem with "windows host object methods" at all. Microsoft implements some of them as ActiveX objects and the internal [[Get]] method of their methods throws an exception. The solution to this is trivial. > may find interesting to read my post about the maskon problem athttp://groups.google.com/group/comp.lang.javascript/msg/65a858c19f383df0 No thanks. > > It is also useful to read the whole thread inspired my post about the > 23rd Chaos Communication Congress in 2006http://groups.google.com/group/comp.lang.javascript/browse_frm/thread... I have little interest in the 23rd iteration of something I have never heard of. Certainly anything that you consider useful or inspirational is right out. |
Re: typeof for feature testing host methods
On Dec 15, 10:12 am, David Mark <dmark.cins...@gmail.com> wrote:
> On Dec 15, 1:46 am, Peter Michaux <petermich...@gmail.com> wrote: > > > > > On Dec 14, 9:04 pm, Peter Michaux <petermich...@gmail.com> wrote: > > > > I've > > > also changed it to check "unknown" objects for null. It seems to me an > > > "unknown" object that is null would be somewhat useless. > > > > var reFeaturedMethod = new RegExp('^function|object|unknown$', 'i'); > > > > var isFeaturedMethod = function(o, m) { > > > try { > > > var t = typeof(o[m]); // throws error if o doesn't have [[Get]] > > > return !!(reFeaturedMethod.test(t) && o[m]); > > > } > > > catch(e) { > > > return false; > > > } > > > > }; > > > Laps in judgment above. Should be > > > var reFeaturedMethod = new RegExp('^function|object$', 'i'); > > > var isFeaturedMethod = function(o, m) { > > try { > > var t = typeof(o[m]); // throws error if > > This does not throw an error. Example: > > (typeof window.external.addFavorite) In the ECMAScript standarad the above expression uses [[Get]]. > Evaluates to "unknown" > > (window.external.addFavorite) > > Throws an error in IE. In the ECMAScript standard the above expression uses [[Get]] just like the typeof expression above. It could be something more along the lines of the ToBoolean that is the problem here instead of a missing [[Get]]. [[Get]] and ToBoolean are only included in the standard as ways to explain the actual standard. > So I don't see what benefit the try clause adds. In a practical sense perhaps nothing. There is nothing in the standard that states typeof would catch an error thrown if [[Get]] is missing. > However, it does > have the unwanted effect of short-circuiting feature testing in agents > that cannot parse try clauses. True. The point I was investigating was is if typeof is implemented according to the standard, but other parts of the implementation are non-standard, does typeof guarantee errors will not be thrown? The answer seems to be no. In practice it seems to be working. If we are relying on typeof in this way I simply want it noted that there is no theoretical reason why it should work but that it seems to work. The additional try-catch would gaurantee that we have the behavior we are looking for of avoiding throwing errors and the reasoning for this would then be included in the standard. That is what try-catch is for. -- Peter Code Worth Recommending Project http://cljs.michaux.ca/ |
| All times are GMT. The time now is 07:55 AM. |
Powered by vBulletin®. Copyright ©2000 - 2013, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.