Prev: FAQ Topic - How do I make a suggestion? (2010-01-17)
Next: Passing primitive variables by reference in JavaScript
From: Thomas 'PointedEars' Lahn on 17 Jan 2010 20:12 john wrote: > Garrett Smith wrote: >> john wrote: >>> given the following javascript: >>> >>> var hour = new Date().getHours().toString(); >>> document.body.className = '_' + hour; >>> >>> is it safe to assume that any browser supporting javascript will be >>> able to execute the code without error. in other words is it safe to >>> assume the features exist and implementations will work as expected? >> >> Nothing is guaranteed 100%. > > which seems like one of the more interesting parts of browser scripting. This phenomenon has nothing to do with "browser scripting". Instead, it has to do with a group of languages that require a runtime environment to be useful, that mostly serve as interfacing languages to control those environments, and where both the languages and the runtime environments have a rather long, vivid history, to say the least. Both client-side and server-side. >>> i have gathered a number of "ancient" browsers (MacIE 5.2.3, Opera >>> 7.54, Firefox 1.0.7 etc.) to test with but my question is more >>> concerned with finding a general principle for what and when to >>> feature test. >> That comes down to experience, unfortunately. > > fortunately this project is academic and for my own amusement so there > is plenty of time to gain the necessary experience (and thanks to Thomas > Lahn pointing out the evolt browser archive entirely possible). And thanks to the ECMAScript Support Matrix, I hope. For it is the ultimate target of that project to make such browser testing unnecessary, at least for older features. (Should you take the time to make tests, your support is appreciated.) >> Object.prototype.hasOwnProperty fails in older browsers, such as Mac IE. >> >> The greatest divergence will be found in browser object models. > > could you recommend a reference for the browser object model? As a result of the diversity of possible runtime environments, there is _not_ *the* browser model. > i searched with google but didn't find anything that looked > authoritative. i read the following pages from the search results: > > - <http://msdn.microsoft.com/en-us/library/ms952643.aspx> MSDN is a good starting point for learning about the object model of MSHTML-based user agents, and about the JScript language supported by MSHTML-based Web browsers (like Internet Explorer) and other Microsoftish runtime environments (like ASP [.NET] on IIS). > - > <http://javascript.about.com/od/browserobjectmodel/Browser_Object_Model.htm> Without looking at it, that is probably not a good starting point. > the MSDN article seems a bit sparse It is not just one article, is it? > and while thorough i'm not sure the accuracy of the about.com article. > are there others that would be worth reading? Yes. Read the FAQ. >> Use w3c standards features an approaches first and do not expect >> non-standard behavior from them. > > understood. It is *really* bad advice, though. Instead, expect rather insane DOM implementations: do not rely on any return value; especially, do not rely on implementation assertions provided by the API (like DOMImplementation::hasFeature()), and avoid the Element::*Attribute*() methods where short-hand attribute properties suffice (we have discussed this at length recently, I am surprised Garrett does not seem to remember.) PointedEars -- realism: HTML 4.01 Strict evangelism: XHTML 1.0 Strict madness: XHTML 1.1 as application/xhtml+xml -- Bjoern Hoehrmann
From: Thomas 'PointedEars' Lahn on 17 Jan 2010 22:04 john wrote: > Thomas 'PointedEars' Lahn wrote: >> Second, JavaScript is not the only ECMAScript implementation. > > as in the following? > > JavaScript, JScript and the implementations in Opera and WebKit (and > some browsers i've never heard of) are all unique; different versions of > an implementation may vary widely; and the implementations from various > vendors are bound to vary. additionally there are some implementations > that run completely outside of a web browser. Exactly; except that WebKit is not a browser (perhaps it is only poor wording there), but a KHTML fork that consists of WebCore, the Mac OS- influenced DOM implementation; JavaScriptCore (a KJS fork), the ECMAScript language implementation; and probably other features. You should quote properly, identifying all quotations as such (leading pipes are customary on Usenet for third-party quotations), and providing a citation, for example a Message-ID or the URI of a publicly accessible resource. (See also <http://en.wikipedia.org/wiki/Citation>.) >> What matters is that *some* of these features have been implemented >> since JavaScript 1.0 *and* specified since ECMAScript Edition 1. For >> historical reasons, it is therefore unlikely, though entirely possible, >> that an implementation still usable today would not provide *those* >> features or support them in that way. > > so what and when to test is a judgment call based on experience with > implementations (of the browsers you are interested in supporting) and > understanding of the relevant specifications? Exactly, but browsers (clients) are still only one part of the equation. > are there more criteria i'm missing? Some language features are known not to be available in older implementations that can still be considered to be in use. You can either avoid those language features (e.g., using hasOwnProperty() is avoided by using iterator prototype methods), apply emulations if necessary (e.g., define Array.prototype.map() if it is unavailable), use emulating wrappers instead (e.g., jsx.object._hasOwnProperty() to call Object.prototype.hasOwnProperty() if available, using alternatives otherwise), or use (eval-based) wrappers so that those language features are hidden from the compiler and do not trigger a syntax error (e.g, jsx.tryThis() to hide try-catch). In all of those cases it is only necessary to test the language feature once, if that. >>> while `className` and the `toString` method (on the Date object) were >>> implemented in JavaScript 1.1. >> >> You are mistaken. > > no doubt about that. i must not have been paying any attention when i > looked up the `className` property. where it's mentioned in the > JavaScript 1.3 reference it is clearly not what i was looking for. > > | className: The fully qualified name of a Java class in a package > | other than `netscape`, `java`, or `sun` that is available to > | JavaScript. Ahh, I did not know *that*. The Matrix has you! :) >>> are there reasons to feature test for `getHours`, `toString` and >> >> No. > > is that "No" because they are "old enough" features provided by the > ECMAScript language and you have witnessed them working as expected? > i.e. based on the relevant specifications and experience with > implementations. Yes. Date.prototype.getHours() is fully backwards-compatible, and I think we can safely consider Netscape 2.0 and other runtime environments that only support JavaScript 1.0 (which does not appear to implement Number.prototype.toString()) to be extinct by now. It is not very efficient (or not much fun, whatever term you prefer) to surf today's Web with them anyway; BTDT (clicked away 43 script error *windows* on that version's default homepage, redirected to <http://netscape.aol.com/>). The problem with this is that it is a often circulus virtuosus, pretty much a self-fulfilling prophecy: Incompetent people deprecate browsers because they cannot cope with deviations, often mistakenly think they are no longer in use, they use not backwards-compatible features and as a result users are forced to use newer browsers (or go to the more compatible competition) because the Web (site) had become unusable with what they were used to. >>> `className`? >> >> Yes. > > is that "Yes" because it is a feature of the host environment and host > environments should be assumed hostile? Not hostile; the languages would not be of much use without them. But they should be assumed to vary, and little if anything should be taken for granted. >>> if so would the following tests be adequate? >>> >>> if (Date.prototype.getHours&& Date.prototype.toString&& >>> typeof document.body.className !== 'undefined') { >>> // above code here >>> } >> >> No. You are testing the true-ness of the first two built-in properties, >> not their callability; if you think you need to test them, test whether >> `typeof' results in "function" instead. > > now that i've spent some more time reading and testing i can see that > those test are indeed inadequate. particularly if you don't want to > throw script errors in very old browsers; which i gather could be > considered unacceptable or unimportant under certain conditions. I do not think any of these tests would throw exceptions, though. Indeed, if you added the `typeof' test, the script would become incompatible to JavaScript 1.0 as that operator requires at least JavaScript 1.1. But as I said, that should no longer be a concern today. In fact, I think language features supported from JavaScript 1.3 (Netscape 4.06) on are safe to use without feature test by now (that is, provided it is specified or supported by known implementations; this assessment is likely to be subject to change as more implementations and versions are tested). The next release of the ECMAScript Support Matrix will reflect that, providing further hints as to what needs to be feature-tested according to (my) current level of knowledge. >> <http://PointedEars.de/es-matrix> > > bookmarked. :) >> Second you need to understand the difference between built-in objects >> like Date instances, and host objects (objects defined by the host >> environment) like HTMLBodyElement implementations. >> >> <http://ecmascript.org/> > > should i begin with the 5th edition keeping in mind that some of the new > language features will need feature testing or would it be better to > become familiar with the 3rd edition first? Yes. And you should use the Shift key of your keyboard where appropriate. > does it even matter? Edition 5 claims to specify behavior common to current implementations, so you should be aware of the changes from Edition 3 which is more widely implemented at this point. However, I must say that Edition 5 is even less readable for beginners than Edition 3 (OK, neither was ever meant to be, but there is nothing comparable): the abstraction level in the algorithms of the new Edition is quite extreme, to say the least¹; it is hard even for me (who claims to know Edition 3 and its implementations fairly well) to wrap my brain around it (if they even bothered to set some inline links ...) And I am not even mentioning the new Strict Mode deviations. PointedEars ___________ ¹ Example: Property read access (omitting the quotation prefixes here) The production MemberExpression : MemberExpression [ Expression ] is evaluated as follows: 1. Let baseReference be the result of evaluating MemberExpression. 2. Let baseValue be GetValue(baseReference). 3. Let propertyNameReference be the result of evaluating Expression. 4. Let propertyNameValue be GetValue(propertyNameReference). 5. Call CheckObjectCoercible(baseValue). 6. Let propertyNameString be ToString(propertyNameValue). 7. If the syntactic production that is being evaluated is contained in strict mode code, let strict be true, else let strict be false. 8. Return a value of type Reference whose base value is baseValue and whose referenced name is propertyNameString, and whose strict mode flag is strict. ~~~~~~~ 8.7.1 GetValue (V) 1. If Type(V) is not Reference, return V. 2. Let base be the result of calling GetBase(V). 3. If IsUnresolvableReference(V), throw a ReferenceError exception. 4. If IsPropertyReference(V), then a. If HasPrimitiveBase(V) is false, then let get be the [[Get]] internal method of base, otherwise let get be the special [[Get]] internal method defined below. b. Return the result of calling the get internal method using base as its this value, and passing GetReferencedName(V) for the argument. 5. Else, base must be an environment record. a. Return the result of calling the GetBindingValue (see 10.2.1) concrete method of base passing GetReferencedName(V) and IsStrictReference(V) as arguments. ~~~~~~~ 8 Types Within this specification, the notation “Type(x)” is used as shorthand for “the type of x” where “type” refers to the ECMAScript language and specification types defined in this clause. ~~~~~~~ 8.7 The Reference Specification Type [...] • GetBase(V). Returns the base value component of the reference V. [...] • HasPrimitiveBase(V). Returns true if the base value is a Boolean, String, or Number. • IsPropertyReference(V). Returns true if either the base value is an object or HasPrimitiveBase(V) is true; otherwise returns false. • IsUnresolvableReference(V). Returns true if the base value is undefined and false otherwise. (Still there? We're just taking off ;-)) ~~~~~~~ 8.12.2 [[GetProperty]] (P) When the [[GetProperty]] internal method of O is called with property name P, the following steps are taken: 1. Let prop be the result of calling the [[GetOwnProperty]] internal method of O with property name P. 2. If prop is not undefined, return prop. 3. Let proto be the value of the [[Prototype]] internal property of O. 4. If proto is null, return undefined. 5. Return the result of calling the [[GetProperty]] internal method of proto with argument P. 8.12.3 [[Get]] (P) When the [[Get]] internal method of O is called with property name P, the following steps are taken: 8. Let desc be the result of calling the [[GetProperty]] internal method of O with property name P. 9. If desc is undefined, return undefined. 10. If IsDataDescriptor(desc) is true, return desc.[[Value]]. 11. Otherwise, IsAccessorDescriptor(desc) must be true so, let getter be desc.[[Get]]. 12. If getter is undefined, return undefined. 13. Return the result calling the [[Call]] internal method of getter providing O as the this value and providing no arguments. ~~~~~~~ 8.10.2 IsDataDescriptor ( Desc ) When the abstract operation IsDataDescriptor is called with property descriptor Desc, the following steps are taken: 1. If Desc is undefined, then return false. 2. If both Desc.[[Value]] and Desc.[[Writable]] are absent, then return false. 3. Return true. ~~~~~~~ 8.6.1 Property Attributes Attribute Name | Value Domain | Description ---------------+----------------+------------------------------------------ [[Value]] | Any ECMAScript | The value retrieved by reading | language type | the property. ---------------+----------------+------------------------------------------ [[Writable]] | Boolean | If false, attempts by ECMAScript code | | to change the property's [[Value]] | | attribute using [[Put]] will not succeed. [...] ~~~~~~~ 8.10.1 IsAccessorDescriptor ( Desc ) When the abstract operation IsAccessorDescriptor is called with property descriptor Desc, the following steps are taken: 1. If Desc is undefined, then return false. 2. If both Desc.[[Get]] and Desc.[[Set]] are absent, then return false. 3. Return true. ~~~~~~~ 13.2.1 [[Call]] When the [[Call]] internal method for a Function object F is called with a this value and a list of arguments, the following steps are taken: 1. Let funcCtx be the result of establishing a new execution context for function code using the value of F's [[FormalParameters]] internal property, the passed arguments List args, and the this value as described in 10.4.3. 2. Let result be the result of evaluating the FunctionBody that is the value of F's [[Code]] internal property. If does not have a [[Code]] internal property or if its value is an empty FunctionBody, then result is (normal, undefined, empty). 3. Exit the execution context funcCtx, restoring the previous execution context. 4. If result.type is throw then throw result.value. 5. If result.type is return then return result.value. 6. Otherwise result.type must be normal. Return undefined. ~~~~~~~ 8.6.2 Object Internal Properties and Methods [...] Internal Property | Value Type | Description ---------------------+-----------------+----------------------------------- [...] [[FormalParameters]] | List of Strings | A possibly empty List containing | | the identifier Strings of a | | Function's FormalParameterList. | | Of the standard built-in | | ECMAScript objects, only | | Function objects implement | | [[FormalParameterList]]. ---------------------+-----------------+----------------------------------- [[Code]] | ECMAScript code | The ECMAScript code of a function. | | Of the standard built-in | | ECMAScript objects, only | | Function objects implement | | [[Code]]. [...] (etc. pp.) ~~~~~ (You did understand what was just said, didn't you? ;-)) -- 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$8300dec7(a)news.demon.co.uk>
From: Garrett Smith on 18 Jan 2010 01:26 Thomas 'PointedEars' Lahn wrote: > Garrett Smith wrote: > >> In your case, document.body might be undefined in an XHTML DOM. > > Where and under which circumstances? Are you considering that the W3C DOM > Level 2 HTML Specification applies to XHTML 1.0 as well? > It was an old "bug" of mozilla where document.body was undefined. That got fixed around 2003. > IMHO, it is rather unlikely that, since the same parser and layout engine > would be used as for XHTML 1.0 (when served declared as > application/xhtml+xml or another triggering media type), `document.body' > would not be available in XHTML (Basic) 1.1. Especially as XHTML (Basic) > 1.1 defined the `body' element in the required Structure Module that all > XHTML 1.1-compliant user agents MUST support. > There is "WICD Mobile 1.0" that suggests a subset of HTML DOM for mobile devices. That subset does not include a body property. Seems to have stopped at CR phase in 2007. http://www.w3.org/TR/WICDMobile/#dom http://www.w3.org/TR/WICDMobile/#dom-html-ref | interface HTMLDocument : Document { | NodeList getElementsByName(in DOMString elementName); | }; I don't know what the rationale is for omitting document.body, nor do I know which implementations actually do that. Anyone who is able to fix that, please do. -- Garrett comp.lang.javascript FAQ: http://jibbering.com/faq/
From: john on 18 Jan 2010 01:28 On 17 Jan 9:04 PM, Thomas 'PointedEars' Lahn wrote: > john wrote: > >> Thomas 'PointedEars' Lahn wrote: >>> Second, JavaScript is not the only ECMAScript implementation. >> >> as in the following? >> >> JavaScript, JScript and the implementations in Opera and WebKit (and >> some browsers i've never heard of) are all unique; different versions of >> an implementation may vary widely; and the implementations from various >> vendors are bound to vary. additionally there are some implementations >> that run completely outside of a web browser. > > Exactly; except that WebKit is not a browser (perhaps it is only poor > wording there), but a KHTML fork that consists of WebCore, the Mac OS- > influenced DOM implementation; JavaScriptCore (a KJS fork), the ECMAScript > language implementation; and probably other features. i didn't mean to imply that WebKit was a browser; merely that it contained a distinct implementation of the ECMAScript language. so yes it may have been a poor choice of words. > You should quote properly, identifying all quotations as such (leading > pipes are customary on Usenet for third-party quotations), and providing a > citation, for example a Message-ID or the URI of a publicly accessible > resource. (See also <http://en.wikipedia.org/wiki/Citation>.) i don't understand what you mean (although i'd like not to get sidetracked from the feature testing discussion which has been quite enlightening thus far). in Thunderbird i see your text as properly attributed to you and the rest attributed to me. i apologize if i've given the impression that some portion of that text was mis-attributed to you (or me) when that wasn't the case or if i'm misinterpreting your statement. (honestly my day to day communication via email [i know Usenet is not email but it seems the two are closely related; at least when you use Thunderbird for both] is generally top posted corporate correspondence so possibly i'm completely missing the point here). >> are there more criteria i'm missing? > > Some language features are known not to be available in older > implementations that can still be considered to be in use. You can either > avoid those language features (e.g., using hasOwnProperty() is avoided by > using iterator prototype methods), apply emulations if necessary (e.g., > define Array.prototype.map() if it is unavailable), use emulating wrappers > instead (e.g., jsx.object._hasOwnProperty() to call > Object.prototype.hasOwnProperty() if available, using alternatives > otherwise), or use (eval-based) wrappers so that those language features > are hidden from the compiler and do not trigger a syntax error (e.g, > jsx.tryThis() to hide try-catch). In all of those cases it is only > necessary to test the language feature once, if that. i found the jibbering.com article on feature testing very informative with regard to only testing a feature once as opposed to each time the feature is used. granted at this point my application of such information may be what an experienced developer would consider naive i'm certainly trying to come to terms with the principle. your scripts, David Mark's "My Library" and Garrett Smith's "APE JavaScript library" are certainly helping in getting a feel for how an experienced developer may apply those principles. so maybe my naive attempts will eventually reach maturity. from searching previous discussion on this list i think it's clear none of the "brand name" (e.g. Prototype, jQuery, Dojo etc.) scripts have much of anything to offer? are there any other scripts worth studying or are there things in the "brand name" scripts worth looking at? (by the way the JSDoc link in some of your scripts sends me to a 404 page; e.g. <http://pointedears.de/scripts/object.js>: "This document contains JavaScriptDoc. See <http://pointedears.de/scripts/JSdoc/> for details." the scripts are well documented inline so maybe whatever should be at the 404 link is not essential. just thought you might like to know.) >>>> while `className` and the `toString` method (on the Date object) were >>>> implemented in JavaScript 1.1. >>> >>> You are mistaken. >> >> no doubt about that. i must not have been paying any attention when i >> looked up the `className` property. where it's mentioned in the >> JavaScript 1.3 reference it is clearly not what i was looking for. >> >> | className: The fully qualified name of a Java class in a package >> | other than `netscape`, `java`, or `sun` that is available to >> | JavaScript. > > Ahh, I did not know *that*. The Matrix has you! :) i'm glad my temporary lack of attention turned into a happy accident instead of just me looking silly. >>>> are there reasons to feature test for `getHours`, `toString` and >>> >>> No. >> >> is that "No" because they are "old enough" features provided by the >> ECMAScript language and you have witnessed them working as expected? >> i.e. based on the relevant specifications and experience with >> implementations. > > Yes. Date.prototype.getHours() is fully backwards-compatible, and I think > we can safely consider Netscape 2.0 and other runtime environments that > only support JavaScript 1.0 (which does not appear to implement > Number.prototype.toString()) to be extinct by now. perhaps i'm particularly masochistic but regardless of extinction Netscape Navigator 2 (and other dinosaurs) is just the sort of environment i'm interested in. my interest is in determining if pages can be made that work (and take advantage of) modern ECMAScript implementations while not completely falling over (i.e. creating script error windows) in even the oldest dynamic browsers. (last year i undertook a similar "adventure" with the Ruby language and the various contemporary and ancient implementations; next year who knows maybe Lisp.) my tests with Netscape Navigator 2.0.2 seem to confirm your assertion regarding `Number.prototype.toString()`. > It is not very > efficient (or not much fun, whatever term you prefer) to surf today's Web > with them anyway; BTDT (clicked away 43 script error *windows* on that > version's default homepage, redirected to<http://netscape.aol.com/>). :) as soon as i got your message pointing to the evolt browser archive the next thing i did was download Netscape Navigator 2.0.2. except in my case (a Windows XP virtual machine in VMWare) the default homepage actually crashed the browser; it took a few tries to be fast enough to hit the stop button before the crash. now that i have a blank homepage it seems to be reliable enough for testing; although every single public web page i've pointed it at since threw multiple script errors or worse (e.g. <http://gmail.com/>). >> now that i've spent some more time reading and testing i can see that >> those test are indeed inadequate. particularly if you don't want to >> throw script errors in very old browsers; which i gather could be >> considered unacceptable or unimportant under certain conditions. > > I do not think any of these tests would throw exceptions, though. Indeed, > if you added the `typeof' test, the script would become incompatible to > JavaScript 1.0 as that operator requires at least JavaScript 1.1. But as I > said, that should no longer be a concern today. my interest is certainly less than practical and it was the `typeof` test that i was referring to about throwing errors ("typeof is not defined"). >> should i begin with the 5th edition keeping in mind that some of the new >> language features will need feature testing or would it be better to >> become familiar with the 3rd edition first? > > Yes. "Yes" it would be better to start with the 3rd edition or "Yes" i should begin with the 5th edition? > And you should use the Shift key of your keyboard where appropriate. sorry for the bad habit. perhaps we can just blame Herbert Bayer and/or e.e. cummings? ;) >> does it even matter? > > Edition 5 claims to specify behavior common to current implementations, so > you should be aware of the changes from Edition 3 which is more widely > implemented at this point. > > However, I must say that Edition 5 is even less readable for beginners than > Edition 3 (OK, neither was ever meant to be, but there is nothing > comparable): the abstraction level in the algorithms of the new Edition is > quite extreme, to say the least¹; it is hard even for me (who claims to > know Edition 3 and its implementations fairly well) to wrap my brain around > it (if they even bothered to set some inline links ...) And I am not even > mentioning the new Strict Mode deviations. i've certainly had a heck of time with it so far (compared to reading W3C specifications). which is probably why i've made more progress getting through the implementers documentation so far. > ¹ Example: Property read access (omitting the quotation prefixes here) > [example from ECMA-262 5th edition that are difficult for beginners] > > (You did understand what was just said, didn't you? ;-)) of course :) thanks for your thoughtful and informative replies.
From: john on 18 Jan 2010 01:49
On 17 Jan 7:12 PM, Thomas 'PointedEars' Lahn wrote: > john wrote: > >> Garrett Smith wrote: >>> Object.prototype.hasOwnProperty fails in older browsers, such as Mac IE. >>> >>> The greatest divergence will be found in browser object models. >> >> could you recommend a reference for the browser object model? > > As a result of the diversity of possible runtime environments, there is > _not_ *the* browser model. after my initial searching i thought that may be the case. >> i searched with google but didn't find anything that looked >> authoritative. i read the following pages from the search results: >> >> <http://javascript.about.com/od/browserobjectmodel/Browser_Object_Model.htm> > > Without looking at it, that is probably not a good starting point. after looking at it it certainly didn't feel authoritative. so i suspect your suspicions are correct. >> the MSDN article seems a bit sparse > > It is not just one article, is it? i can't say for sure. it was the only page from MSDN that showed up on the first page of google search results. perhaps tomorrow i'll have more time to explore that site and turn up meatier pages. >> and while thorough i'm not sure the accuracy of the about.com article. >> are there others that would be worth reading? > > Yes. Read the FAQ. i did search the FAQ and FAQ Notes but didn't see any mention of "browser object model" or "BOM". do you happen to know which section or page discusses this topic? >>> Use w3c standards features an approaches first and do not expect >>> non-standard behavior from them. >> >> understood. > > It is *really* bad advice, though. Instead, expect rather insane DOM > implementations: do not rely on any return value; especially, do not rely > on implementation assertions provided by the API (like > DOMImplementation::hasFeature()), and avoid the Element::*Attribute*() > methods where short-hand attribute properties suffice (we have discussed > this at length recently, I am surprised Garrett does not seem to remember.) i misread Garrett's response to say "do not expect _standard_ behavior from them". after even my basic testing i'm pretty much ready to expect non-standard behavior in even seemingly simple cases. |