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 11 Nov 2009 16:44 Thomas 'PointedEars' Lahn wrote: > Garrett Smith wrote: > >> Thomas 'PointedEars' Lahn wrote: >>> kangax wrote: >>>> Garrett Smith wrote: >> (the example I provided was snipped). > > Because it was irrelevant. > So you failed to understand the relevance? I'm not really sure what the problem is (It might be a reading and cognition problem on your part, though stubbornness is also a possibility. Let me try one more time. The point of trying Function.prototype.call on a regexp was to investigate what happens when an object is checked to see if it has an internal [[Call]] property. Places where a check to see if an object implements [[Call]]: * Function Calls * typeof operator * Function.prototype.call The thread alredy discussed Function Calls and typeof operator. I brought up Function.prototype.call. You then announced your inability to see the relevance while simultaneously blaming me for that. SO here I am explaining again (please do read before snipping). An object's [[Call]] property can be accessed using a CallExpression. An object's [[Call]] property can be indirectly accessed using Function.prototype.call. The example I provided uses the latter: Function.prototype.call.call(/a/, "a"); The result in Tracemonkey (in FF 3.5) is a TypeError: "TypeError: Function.prototype.call called on incompatible /a/" That shows that the object does not, in fact, implement [[Call]]. That behavior could be explained by what Juriy (kangax) posted: | Yes, from what I remember, Mozilla makes regex objects callable | without actually giving them [[Call]]. >>>>> That's odd. Seems in Tracemonkey, a RegExp is callable without >>>>> implementing [[Call]], or ? A bug in there syntax extension, due >>>>> to internal typechecking for RegExp, as: >>>>> typeof /a/ >>> The result of the `typeof' operation has no relevance to the >>> implementation of the [[Call]] property of its operand. >>> >>>> Yes, from what I remember, Mozilla makes regex objects callable without >>>> actually giving them [[Call]]. >>> How can you possibly tell? If it does not implement [[Call]] it must >>> throw a TypeError, but it does not do that in TraceMonkey 1.8.1 >>> (Iceweasel 3.5.4). So we have to assume it does implement [[Call]]. >> The example I provided: > > Does not prove anything, which is why it still is irrelevant and has thus > been snipped. > The example provides evidence for whether an object implement's [[Call]]. Please do read the specification for Function.prototype.call *carefully*. >> | javascript: alert( Function.prototype.call.call(/a/, "a") ); >> | Webkit: >> | elerts "a" >> | >> | Tracemonkey: >> | TypeError: Function.prototype.call called on incompatible /a/ >> >> I'll explain why, [...] > > No, thanks. You do not understand what a syntax extension is to begin with. > How convenient that you could snip what I wrote and summarily discard it as irrelevant, with no argument whatsoever, except for the hand-waving and condescending summation that "I don not understand what a syntax extension is to begin with." So lets cut the hand waving and see if there is any substance at all to what you're writing. Is this a syntax extension? Do you believe the () operator is overloaded for a new type of [[RegExpCall]]? It's possible, but not proven. I don't have much interest in proving that to be true or false. Really, I don't care. If you do, then please do, but don't expect me to take your word for it, just because (as you claim) I don't understand the concept of syntax extension. Searching bugzilla might lead to more clues. AISB, none of this matters when typechecking is avoided (and RegExp are not called). Since I avoid typechecking and don't call RegExp, I can move on to real problems. -- Garrett comp.lang.javascript FAQ: http://jibbering.com/faq/
From: Thomas 'PointedEars' Lahn on 11 Nov 2009 17:28 Garrett Smith wrote: > Thomas 'PointedEars' Lahn wrote: >> Garrett Smith wrote: >>> Thomas 'PointedEars' Lahn wrote: >>>> kangax wrote: >>>>> Garrett Smith wrote: >>> (the example I provided was snipped). >> >> Because it was irrelevant. > > So you failed to understand the relevance? So you failed to understand the lack of its relevance. > I'm not really sure what the problem is (It might be a reading and > cognition problem on your part, though stubbornness is also a > possibility. Or, by applying Occam's razor to the situation, you could be wrong. > Let me try one more time. Repeating the same nonsense over and over again does not make it more true. > The point of trying Function.prototype.call on a regexp was to > investigate what happens when an object is checked to see if it has an > internal [[Call]] property. But that is _not_ the correct way to test it as far too many variables are involved. Instead, the correct test is to call it in a /CallExpression/ with /Arguments/ and see if *that* throws a general TypeError; it does not, it returns a value (`null' or an object reference) instead, so by all accounts the object created by /x/ in /x/() must implement [[Call]]. That Function.prototype.call() throws a TypeError when passed a reference to a RegExp instance is nothing more than a peculiarity, maybe an oversight, that can be expected of an undocumented language feature like this. PointedEars -- realism: HTML 4.01 Strict evangelism: XHTML 1.0 Strict madness: XHTML 1.1 as application/xhtml+xml -- Bjoern Hoehrmann
From: Garrett Smith on 11 Nov 2009 18:10 Thomas 'PointedEars' Lahn wrote: > Garrett Smith wrote: > >> Thomas 'PointedEars' Lahn wrote: >>> Garrett Smith wrote: >>>> Thomas 'PointedEars' Lahn wrote: >>>>> kangax wrote: >>>>>> Garrett Smith wrote: >>>> (the example I provided was snipped). >>> Because it was irrelevant. >> So you failed to understand the relevance? > > So you failed to understand the lack of its relevance. > Ah, no, that would be you, and perpetually blamingme for your inability to see what is relevant and why. Explaining this to you starting to seem like a total waste of time. >> I'm not really sure what the problem is (It might be a reading and >> cognition problem on your part, though stubbornness is also a >> possibility. > > Or, by applying Occam's razor to the situation, you could be wrong. > >> Let me try one more time. > > Repeating the same nonsense over and over again does not make it more true. > >> The point of trying Function.prototype.call on a regexp was to >> investigate what happens when an object is checked to see if it has an >> internal [[Call]] property. > > But that is _not_ the correct way to test it as far too many variables are > involved. Instead, the correct test is to call it in a /CallExpression/ > with /Arguments/ and see if *that* throws a general TypeError; it does not, > it returns a value (`null' or an object reference) instead, so by all > accounts the object created by /x/ in /x/() must implement [[Call]]. That > Function.prototype.call() throws a TypeError when passed a reference to a > RegExp instance is nothing more than a peculiarity, maybe an oversight, that > can be expected of an undocumented language feature like this. > > You said that Function.prototype.call() throwing a TypeError when passed a reference to a RegExp instance is nothing more than a peculiarity That is not true. As I said, please do read the specification *carefully*. Again and again. One more time. | 15.3.4.4 Function.prototype.call(thisArg [ , arg1 [ , arg2, ... ] ] ) | | The call method takes one or more arguments, thisArg and | (optionally) arg1, arg2 etc, and performs a function call using the | [[Call]] property of the object. If the object does not have a | [[Call]] property, a TypeError exception is thrown. The called | function is passed arg1, arg2, etc. as the arguments. One more time: | If the object does not have a [[Call]] property, a TypeError exception | is thrown. Function.prototype.call.call(/a/, "a") throws in Tracemonkey. That behavior is relevant. Why? The result can be explained by /a/ not having a [[Call]] property. That is the point. Starting from "What is a function?" to "What can be called" to "does RegExp implement [[Call]]"? However: /a/("a") executes, and apparently the RegExp "/a/" appears t follow Function Call; indeed matching teh production for CallExpression: MemberExpression Arguments: /a/ - MemberExpression ("a") - Arguments So, if /a/("a") works, then why? does /a/ implement [[Call]]? We could look to typeof which we know lies. We could try Function.prototype.call. There really aren't any other means by which to access the internal [[Call]] property. -- Garrett comp.lang.javascript FAQ: http://jibbering.com/faq/
From: kangax on 12 Nov 2009 01:39 Richard Cornford wrote: > kangax wrote: >> Garrett Smith wrote: > <snip> >>> That's odd. Seems in Tracemonkey, a RegExp is callable without >>> implementing [[Call]], or ? A bug in there syntax extension, due >>> to internal typechecking for RegExp, as: >>> typeof /a/ >> >> Yes, from what I remember, Mozilla makes regex objects callable >> without actually giving them [[Call]]. > > That would be very clear violation of ECMA 262, 3rd Ed., where Section > 11.2.3 (Function Calls) features the words "If Result(3) does not > implement the internal [[Call]] method , throw a TypeError exception" as > step 5 in its algorithm. That is, in ES3 terms, if it does not have a > [[Call]] method it cannot be called, and so if it can be called it > _must_ have a [[Call]] method (or at least that is the required > behaviour, so the ability to call something has direct implications for > all other situations where the existence of a [[Call]] method is > relevant). The specifics have moved around in ES5, but the internal > IsCallable function still boils down to 'does the object have a [[Call]] > method', so nothing has really changed. Yes, one way or another Mozilla's implementation comes out to be non-conforming. If regex objects have [[Call]], then `typeof` rules are violated; 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 :)) There's an old-ish Mozilla issue https://bugzilla.mozilla.org/show_bug.cgi?id=61911 which, as I understand, is the one responsible for making typeof regex to be "object", not "function" as they had it before (e.g. in FF <= 2). Looking at their patch, I can't tell if [[Class]] was removed on regex objects or if they changed some internal `typeof` mapping (mapping of object types to return values of `typeof`). This whole issue was recently mentioned on es-discuss once again (https://mail.mozilla.org/pipermail/es-discuss/2009-August/009718.html), this time in context of `JSON.stringify`. Per specs, `JSON.stringify` should treat values that are callable (IsCallable returns true) as undefined. This is essentially why Function objects are ignored during serialization. The fun part is WebKit making regex objects callable. This makes `JSON.stringify(/x/)` return `undefined` in WebKit, but `{}` in Firefox, resulting in a nice cross-browser mess. Here's an involved discussion on this topic � https://bugs.webkit.org/show_bug.cgi?id=28117. We can blame specs and the way certain things are underspecified there. It's not very clear if RegExp objects can implement [[Call]] as part of allowed extension. > > On e of the main things that has dogged the - isFunction - question over > its very long history is that very few people have been willing to state > what 'being a function' represents. If you can give a clear definition > of what 'being a function' is then you are probably in a position to > either design and effective - isFunction - method, or to declare the > determination untestable and so give up the attempt. Instead we see lots > of example of - isFunction - method that do something, get criticised > for the inconsistencies in that something, and then get changed so they > do something else, with nobody ever stating what the definition of > 'Function' is that their - isFunction - is supposed to be testing. Right on point. This is why we should teach people internals (at least some) of the language. Understanding difference between native/host objects, and what [[Call]] is, would make things much easier for everyone. > > Personally, I like a definition of 'function' that goes; "if you can > call it then it is a function". It is a definition that rules out the > viability of an - isFunction - test function (you would have to call the > object to see if it is callable, and that might have side-effects), but > it is also a very simple/obvious definition that does not introduce > issues of itself. > > 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 > And understanding of host objects and their unspecified nature would completely avoid this problem. > > The idea being that - createElement - should return an object > implementing the Element (and by implication Node) interfaces from the > W3C DOM (which is true), and that those object should not be callable > (which is an assertion that has no technical basis[1]), and therefore > that the - typeof - operation applied to such an object should not > result in 'function'. > > [1] The W3C DOM is defined in terms of interfaces; sets of properties > and methods that object implementing those interfaces must possess (in > some practical sense). Neither ECMAScript, the W3C DOM specs nor the > ECMAScript bindings for the DOM interfaces place any restrictions on the > nature of the objects implementing an interface, and as ECMAScript > functions are objects there is absolutely no reason for any object > implementing a W3C DOM interface not to be an ECMAScript function. Thus > Element and Node interface implementing objects could be functions (as > could objects implementing HTMLCollection, NodeList or NamedNodeMap), > the decision is left up to the creators of the DOM providing host. I have always wondered why ECMA bindings don't define property attributes (such as those from 8.6.1 and 8.6.2). > > If you try to call the Firefox OBJECT element an exception is thrown, > but it is not the "x is not a function" exception that would be thrown > if the OBJECT element were not callable. The implication being that the > element is callable and the exception that is thrown is thrown within > the call. So, by a very reasonable definition of 'being a function' the > Firefox OBJECT element is a function (it can be called), and so its > resulting in 'function' when - typeof - is applied is actually a very > reasonable indicator of a truth about the nature of the object in question. Yes. > > The point being that there is no technical reason to expect to be able > to discriminate between objects implementing the Element interface (or > any other DOM specified interface) and an ECMAScript function. This > immediately brings into question the worth of having an - isFunction - > test function in the first place, especially in relation to its common > use in attempting to emulate 'method overloading' in ECMAScript. (In > fact, it brings into question the general viability of emulating 'method > overloading' in javascript, when you can only make superficial > discriminations between the types of values that are the arguments to a > function call). I find overloading to be useful when used sparingly. Consider an interface of 2d point implementation, where setting and retrieval of x/y properties is performed through corresponding methods. function Point(x,y){ this.x = x; this.y = y; } Point.prototype.getX = function(){ return this.x; }; Point.prototype.setX = function(value){ this.x = value; }; // similar getY, setY implementation var myPoint = new Point(10, 20); Now consider a case of "moving" a point by a certain value: myPoint.setX(myPoint.getX() + 10); This is perfectly fine, of course, but there's a possibility to implement something more elegant and cleaner: myPoint.setX(function(value){ return value + 10; }); Valid values of `x` can only be numeric ones, so it's safe to use overloading here: Point.prototype.setX = function(value){ if (typeof value == "number") { this.x = value; } else { this.x = value(this.x); } }; // or maybe even Point.prototype.setX = function(value){ if (typeof value == "number") { this.x = value; } else { // could recurse indefinitely if callback returns non-numeric value this.setX(value(this.getX())); } }; I understand that there are alternative ways to accomplish this (such as introducing another method). > > The relevance for a regular expression's having, or not having, a > [[Call] method? If you cannot expect to be able to discriminate a DOM > node from a function not finding it easy to discrimination a regular > expression from a function (using - typeof - (as the specific > discrimination by duck-typing the respective object's methods/properties > is viable)) is not making things any worse. isFunction can be specified to work reliably with native objects only, but regexp having [[Call]] would still hardly matter. It really makes sense to differentiate objects that are callable (i.e. native, implement [[Call]], and so should return "function" on typeof) and those that are instances of Function (have `Function.prototype` in their prototype chain, and so can be tested with `instanceof` or `constructor`). 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"). > >> In WebKit, on the other hand, regex do have [[Call]] and so typeof >> returns "function", as per specs (native object + has [[Call]] == >> "function"). > <snip> >>> Many won't read the documentation of others (including pertinent >>> specifications, as witnessed recently on this NG). Developers >>> often skip right to the "what does it do" (functions, examples, >>> or tests). > > I recall one of my colleagues being amused to find me reading the > SOAP/WSDL specifications prior to writing a SOAP client for our web > applications. I noticed that not many people are fond of reading specs. > >> It's no surprise that ES3 specs are hard to follow and full of >> ambiguities. A year ago, the only way I could understand certain >> things in specs is with the help of wonderful explanations by >> Cornford and Lasse in the archives (on related subjects). > > An interesting mix of formality and informality in your choice of > identifiers there. :) Sorry, I'll try to be consistent next time :) > >> Your last question on es-discuss proves how hard it could be to >> discern specs correctly. >> >> ES5, fortunately, takes care of some of these uncertainties. > <snip> > > The ES5 spec may remove some ambiguities, but it is not going to prove > any easier for newcomers to 'get into', at least in part becasue it > introduces many new internal objects/functions that will not ease the > need to continually be going back and forth cross-refencing things. Yes. Besides, ES5 is more or less a superset of ES3 (at least in a sense that there's now an extra layer of deeper object properties control, through property descriptors + array extras + JSON + strict mode). -- kangax
From: kangax on 12 Nov 2009 01:56
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. > > # (cur) (last) 22:22, 28 September 2009 Jsninja (Talk | contribs) m > (Protected "Functions" [edit=sysop:move=sysop]) (undo) > > The document also states: > > | var ninja = function myNinja(){ > | assert( ninja == myNinja, > | "This function is named two things - at once!" ); > | }; > | ninja(); > | assert( typeof myNinja == "undefined", > | "But myNinja isn't defined outside of the function." ); > | > | This brings up the most important point: Anonymous functions can be > | named but those names are only visible within the functions > | themselves. > > That statement is true in the spec, but not in reality, and if the > example had been run in IE, that would have been realized. That sentence � "This function is named two things - at once!" sounds a bit amateur. Function is always "named" once, if we consider name to be its Identifier (it's also what Mozilla stores in function objects' "name" property). What references function has little to do with its "name"; it could as well be hundreds of various identifiers in various execution contexts. I would also change "Anonymous functions can be named" (which sounds weird) to "Function _expressions_ can be named, i.e. they can have _optional identifier_". And, of course, a very important explanation of function expressions vs. function declarations seems to be missing there; nothing is being said about function statements, NFE bugs and other peculiarities. [...] -- kangax |