Prev: A practical exercise: fighting maskons
Next: FAQ Topic - How do I get a jsp/php variable into client-side javascript? (2009-11-10)
From: Garrett Smith on 16 Nov 2009 03:34 Richard Cornford wrote: > kangax wrote: >> Richard Cornford wrote: >>> kangax wrote: >>>> Garrett Smith wrote: >>> <snip> [snip] >> I have always wondered why ECMA bindings don't define property >> attributes (such as those from 8.6.1 and 8.6.2). > > When a DOM property is stated as read-only (and that restriction is > implemented) then it is reasonable to assume that ECMAScript - > ReadOnly - attribute does apply. Other characteristics of such object's; > enumerability, general mutability, etc. are not really the > responsibility/concern of the W3C interfaces. > It is not always the case that a DOM readonly is implemented (in ECMAScript, in a browser) as ReadOnly. A DOM readonly attribute may be implemented with a getter but no setter. The result is not silent failure (as would be the case if it were implemented as ECMASCript {ReadOnly}, but an error, as seen in Firefox, where, for example, a MouseEvent has a readonly "clientX" property that is implemented as a getter (with no setter, resulting in error when attempting to set the property). Example: javascript: void(document.onclick=function c(e){alert(e.clientX=12);}); Result: Error: setting a property that has only a getter > But in any event, remember that the W3C does not employ people with a > good understanding of ECMAScript and/or browser scripting to work on > their APIs, so they are bound to always botch something. > Why do you think that is? -- Garrett comp.lang.javascript FAQ: http://jibbering.com/faq/
From: Richard Cornford on 16 Nov 2009 14:01 On Nov 16, 4:15 am, kangax wrote: > Richard Cornford wrote: >> kangax wrote: > [...] >>> Yes, one way or another Mozilla's implementation comes >>> out to be non-conforming. > >> Given that ECMAScript is allowed to have 'extensions', I have >> been wondering if what Mozilla is doing can be put across as >> an 'extension' of some sort. ... <snip> >>> if it doesn't function call rules are (as you have >>> explained). But that's the price of compatibility, and >>> there are other examples of spec violations like that >>> (`ToObject` not throwing Error in for-in, comes to mind :)) > >> That one is not a price of compatibility because for many >> years JavaScript(tm) regular expressions have been callable >> and have been reporting themselves as 'function' if tested >> with - typeof -. Any price this is extorting is the price >> of more or less ignorant web developers insisting that what >> they believe should be the case become the case, despite the >> consequences. > > I don't know the whole story there, but I was basing my > assumptions on Brendan's comments to this whole "situation". > To cite one > (https://bugs.webkit.org/show_bug.cgi?id=28117#c21) > > "[...] > We fixed the higher-numbered one first, making typeof /a/ == >"function". But then we retreated in 61911 due to complaints > and (I seem to recall; it's hard to find evidence at the moment) > real web compatibility problems. > > The complaints weren't all from spec-purists who did not like the > extension in SpiderMonkey that allows /a/(s) as shorthand for > /a/.exec(s). I remember more than a few places where real code was > flummoxed by typeof /a/ == "function". This confusing result broke > code, whether or not such code expected (this would have been > Mozilla-specific code, originally) to be able to call a regexp > as shorthand for exec'ing it. > > Anyway, we threw in the towel with the resolution of 61911. The > only further retreat for us is to remove callability, but that > may be hard. We may be stuck. We can't easily go back to typeof > /a/ == "function", in any event. > > /be" > > Is it only complains of incompetent web developers that triggered this > change? That does appear to be what he was saying. His "spec-purists" were (arguably) wrong, and a callable regular expression is an allowable language extension, so there complaints could be dismissed, but the authors of "real code [that] was flummoxed by typeof /a/ == "function"" seem to fall straight into my "ignorant web developers insisting that what they believe should be the case become the case, ... " as they have no grounds for expecting to be able to differentiate regular expressions from object with - typeof - 'function' (and testing in a range of browsers would have given them empirical evidence of not being able to do so in practice). > I don't know. It certainly looks like there could be more to it > (e.g. incompetent legacy scripts, which should still be > supported ;)) Where by "incompetent legacy scripts" you mean scripts that were authored without any testing on JavaScript(tm)? <snip> >>> And understanding of host objects and their unspecified nature >>> would completely avoid this problem. > >> But avoid the problem how? Presumably by triggering the realization >> that the general task of identifying some sort of 'type' by >> examining an arbitrary value is unsolvable, leading to the >> realization that code design should not then be predicated on >> the ability to derive types from arbitrary values. > > Understanding the nature of host objects would avoid never > ending patching of type-checking utility to account for cases > that can inherently take any form. So the code design is changed to avoid type-checking? <snip> >> <snip> >>> I understand that there are alternative ways to accomplish >>> this (such as introducing another method). > >> Where introducing another method is perfectly valid as with >> the 'overloading' you have it is necessary for the programmer >> to be aware of the types being passed as arguments at the point >> of calling the method, and so knowing the type could then know >> which method to use with that type. > > And I'm not sure which one makes for a more convenient/intuitive > API design. I am; it would be the multi-method approach. You don't end up with significantly more code, just more function objects (which get to execute quicker because they no longer need to examine the types of their arguments). > It seems that adding another method in situation like this could > actually result in a more understandable code; method name could > hint at method's semantics, whereas overloading could lead to > ambiguity. There are people who would put a 'does' in place of your 'could'. > [...] > >>> Oh wait, we also have [[Class]] == "Function" :) If object is >>> native and has [[Class]] == "Function", it's definitely >>> callable (as per 13.2); however, if it's native and its >>> [[Class]] is not "Function" it could be callable or it >>> could be not (as the regexp case shows, where implementation >>> gives [[Call]] to object with [[Class]] == "RegExp"). > >> Yes, and a definition of 'being a function' that says a >> 'function' is only any native function (all host objects/methods >> and unexpectedly callable objects are then not what we are >> calling a 'function') is at least a workable definition. > > Which is why testing object for [[Class]] == "Function" is a > more-or-less "viable" solution for isFunction utility, as long as > isFunction defines function to be a Function object. So long as - isFunction - defines host objects as being un-decidable cases that should never be presented as arguments. (So the person writing the code that calls - isFunction - is already expected to know enough about the object to be certain that it is not a host object.) > This is practically an alternative to instanceof check, but > the one that's cross-frame -safe. Instead of asserting that > something is a Function object by checking if > `Function.prototype` is in its prototype chain, we check if > its [[Class]] has a "Function" value. But in the event that you have a single page situation and know that you will not be creating/testing objects that are not callable but inherit from - Function.prototype - then each test is as good as the other. > There are, of course, other implications here that make this > "alternative" so much different that instanceof check possibility > of host objects implementing [[Class]] == "Function" Is there any reason a host object could not have - Function.prototype - on its prototype chain? I cannot see one, so these two tests are equivalent in their inability to predictably handle host objects. > (and so resulting in false positives) or IE's wrapping of > cross-window objects (and so giving false positives once again). I think the IE cross-windows stuff is more likely to result in a false negative (as it means that (at least some) native and built-in functions will report 'object' if tested with - typeof - by code in another window). > In any case, the more important question to ask here is what > exactly it is that needs to be done with an object which > requires to know whether it is a function. When this question > is asked, the solution usually becomes much more apparent and > viable. Knowing (being able to clearly state) the discrimination you need to make in context is the viable alternative to knowing what you mean by 'being a function'. There is nothing wrong with coming at the problem form the other direction, but the resulting test function certainly should not be called 'isFunction'. Richard.
From: Garrett Smith on 25 Nov 2009 15:29 kangax wrote: > Garrett Smith wrote: >> Richard Cornford wrote: >>> kangax wrote: >>>> Garrett Smith wrote: >>> <snip> >> [...] >> >>> A (one of the many) bugbears of - isFunction - Firefox's response to:- >>> >>> var x = document.createElement('OBJECT'); >>> >>> - which, when tested with - typeof - returns 'function'. This is seen >>> as incorrect, e.g.:- >>> >>> <URL: http://jsninja.com/Functions#Function_Type > >>> >> >> That code was reviewed here over a year ago and was changed in jQuery: >> >> | isFunction: function( obj ) { >> | return toString.call(obj) === "[object Function]"; >> | } >> >> What surprises me is that wiki document was modified very recently: > > Resig says that example now uses [[Class]] check. > Then he is mistaken. The site has the same code: http://jsninja.com/Functions#Function_Type // Do not use this function: | function isFunction( fn ) { | return !!fn && !fn.nodeName && fn.constructor != String && | fn.constructor != RegExp && fn.constructor != Array && | /function/i.test( fn + "" ); | } Nobody should be using that code at this time. That isFunction relies on function decompilation. It fails across frames. It provides wrong results for some cases, the most obvious being any object whose toString contains substring "function" (any case). var book = { title : "functional javascript", valueOf : function(){ return this.title; } }; That isFunction will result true. The justification for that function is based on the method overloading strategies used in the initial design of jQuery. We've been over and over this. I blogged about it with many examples, in 2007. That lousy function has gotten a lot of criticism. It seems hard to believe that Resig could be unaware of that criticism. So why is he writing about it advocating its use? Making a one-time mistake is understandable. Advocating the use a well-known mistake defies explanation. -- Garrett comp.lang.javascript FAQ: http://jibbering.com/faq/
From: Garrett Smith on 27 Nov 2009 14:05 Garrett Smith wrote: > kangax wrote: >> Richard Cornford wrote: >>> kangax wrote: > > > [...] > >>> >>> But in any event, remember that the W3C does not employ people with a >>> good understanding of ECMAScript and/or browser scripting to work on >>> their APIs, so they are bound to always botch something. >> >> Ok :) >> > > Couldn't be more true. The w3c employees have a strong aversion to > learning ECMAScript. [snip] The paying members to the w3c are not any better. Take Travis Leithead, Microsoft's Program Manager and Expert, trying to learn javascript from about.com while writing articles that show his misunderstanding of the language. http://www.w3.org/2009/09/23-webapps-minutes.html | TL: looking at a JS/unicode site. /u is supported natively in JS | | <Travis> http://javascript.about.com/library/blunicode.htm Travis tries to explain javascript inheritance, full of misiformation: http://msdn.microsoft.com/en-us/library/dd282900%28VS.85%29.aspx He (they) also proposed dropping currentStyle/runtimeStyle: http://www.pubbs.net/web/200909/112588/ Amazing. It's as if someone sat down and said, "Guys, how can we /really/ the web so that sites won't work in IE?". -- Garrett comp.lang.javascript FAQ: http://jibbering.com/faq/
From: Thomas 'PointedEars' Lahn on 28 Nov 2009 22:38
Richard Cornford wrote: > Given that ECMAScript is allowed to have 'extensions', I have been > wondering if what Mozilla is doing can be put across as an 'extension' > of some sort. Two parts of the (3rd Ed.) spec talk about 'extensions' > (what is, or is not, allowed); Section 16 (Errors) and Section 2 > (Conformance),. > > Section 2 states that; "A conforming implementation of ECMAScript is > permitted to support program and regular expression syntax not described > in this specification." So is allowing a regular expression to be called > even if it does not have a [[Call]] method a 'syntax extension'? I > don't see how it can be, as the syntax of a function call is unchanged > even when applied to regular expressions (in pure (non-extended) > ECMAScript calling a regular expression is not a syntax error, even if > it can be expected to result in a runtime error if executed). Or at > least, in this form:- > > var x = /a/g; > var y = x('a'); > > - there is no syntax error anD no deviation from the specified syntax. ACK. > However:- > > var y = /a/g('a'); > > - is a bit more problematic in ES3. We start at the syntax for Function > Call (11.2.3):- > > CallExpression : MemberExpression Arguments > > - and then have to examine MemberExpression (11.2)- > > MemberExpression : > PrimaryExpression > FunctionExpression > MemberExpression [ Expression ] > MemberExpression . Identifier > new MemberExpression Arguments > > - where we are expecting PrimaryExpression to be pertinent, so to > section 11.1:- > > PrimaryExpression : > this > Identifier > Literal > ArrayLiteral > ObjectLiteral > ( Expression ) > > In is the inclusion of Identifier in the PrimaryExpression list that > allows the first form of the syntax above, and guarantees that the > language's syntax cannot prevent a call to a regular expression. (at > least if you don't look too hard at the right hand side of the > assignment production and realise that ES3 makes no assertion about a > regular expression literal being an Expression of any sort). ISTM that, while trying to find an explanation for the observed behavior in the syntactical grammar, you are overlooking the constraints of the lexical grammar here (ES3F, 5.1.2). RegExp literals are produced by another goal symbol than other source code, /InputElementRegExp/. Therefore, in a strictly conforming implementation of ECMAScript Edition 3, var y = /a/g('a'); could not be produced by /VariableStatement/ because `/a/g' must be produced by /RegularExpressionLiteral/ which would leave only "('a')", a syntax error there, and the /Identifier/ production would not apply (/Expression/ would apply, but a /PrimaryExpression/ were not allowed in this context). > We might expect the RegularExpressionLiteral to be in the list for Literal > (section 7.8):- > > Literal :: > NullLiteral > BooleanLiteral > NumericLiteral > StringLiteral > > - but it is not. ES5 fixes this by adding RegularExpressionLiteral to > the end of the list for Literal. And, AISB, newer JavaScript versions appear to implement that. PointedEars -- Anyone who slaps a 'this page is best viewed with Browser X' label on a Web page appears to be yearning for the bad old days, before the Web, when you had very little chance of reading a document written on another computer, another word processor, or another network. -- Tim Berners-Lee |