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: Richard Cornford on 11 Nov 2009 14:32 Peter Michaux wrote: >On Nov 11, 11:40 am, Thomas 'PointedEars' Lahn wrote: >> Peter Michaux wrote: >>> Thomas 'PointedEars' Lahn wrote: <snip> >>>> Well, I for one do not want to see code like the following >>>> spreading around: <snip> >>>> Do you? >> >>> No. I think that I would not have allowed '$' to be part of >>> identifier in the first place. >> >> Then I do not understand your opinion above. A recommendation >> against, as it is in Edition 3, is a step in the right >> direction in that sense; a missing recommendation against, >> as it could be in Edition 5, is not. > > If '$' is allowed then just allow it without any qualification > or any advice about how it should be used unless such > qualification is enforced by the language. How do you proposes such a requirement be enforced? The javascript engine has no way of knowing how the source code it is presented with is generated, so know way of determining which, if any, of it has been machine generated. > Such wimpy advice as > given in ES3 will be and has been ignored as programmers If you want to call people who obviously didn't know any better "programmers". > will always do anything they can get away with doing. No they won't. there is a similar injunction (equally unenforceable) in Java, which I have never seen breached by a non-novice. It is possible for people to perceive reasons for not doing something despite there being nothing to stop them. >..so don't bother with the wimpy advice as part of the language > spec in the first place. Because in situations where javascript source code is partly or entirely machine generated being in a position to identify those parts of it that were machine generated aids debugging and maintenance. One of the issues you get with machine generated Identifiers is that it can be difficult to predict exactly which Identifiers will be generated, and so guaranteed that they will not collide with Identifiers already in use in the human generated code. One way of guaranteeing no collisions would be to provide each and every machine generated Identifier with a prefix that was never used in human generated code. The original ECMAScript spec made provision for that by allowing the $ symbol in identifiers, and stated that that was the reason the symbol had been allowed in Identifiers. It is a useful convention to follow, though may only appear to be useful to people who have experience of mixing machine generated javascript with human generated javascript (so likely not novices). > Imagine they had given indenting advice (e.g. four spaces, no > tabs). That would have been promptly ignored also if two > spaces and tabs were allowed. Now indenting requirements are something that could be enforced. Richard.
From: Garrett Smith on 11 Nov 2009 14:38 Thomas 'PointedEars' Lahn wrote: > kangax wrote: > >> Garrett Smith wrote: (the example I provided was snipped). >>> 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: | javascript: alert( Function.prototype.call.call(/a/, "a") ); | Webkit: | elerts "a" | | Tracemonkey: | TypeError: Function.prototype.call called on incompatible /a/ I'll explain why, but first Opera: elerts "null". That is odd, considering: javascript: alert( /a/("a")) Opera: elerts "a" The reason Function.prototype.call is used is that it requires the use of internal [[Call]] operator. Function.prototype.call: | 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. Read carefully this line: | If the object does not have a [[Call]] property, a TypeError exception | is thrown. Function.prototype.call throws a TypeError if the object does not have a [[Call]] property. That is exactly what happens in Tracemonkey. Function Calls also use the [[Call]] property of the object: | 11.2.3 Function Calls | | The production CallExpression : MemberExpression Arguments is | evaluated as follows: | | 1. Evaluate MemberExpression. | 2. Evaluate Arguments, producing an internal list of argument | values (see 11.2.4). | 3. Call GetValue(Result(1)). | 4. If Type(Result(3)) is not Object, throw a TypeError exception. | 5. If Result(3) does not implement the internal [[Call]] method, | throw a TypeError exception. | 6. [...] In Tracemonkey, /a/() does *not* throw a TypeError in step 5. I have no doubt that that is intentionally designed. Older versions of Firefox, typeof /a/ resulted "function" and RegExp had been a callable object in Firefox. The current implementation in Tracemonkey changes that. Probably to make different types of code work: 1) Code that typechecks methods such asl "isFunction" to return false when passed a RegExp 2) Existing code that performs a Function Call on RegExp. 3) Code that wants to typecheck to make sure a RegExp is an Object, possibly using a generic isObject function: // Do not use this function function isObject( thing ) { return typeof thing == "object" && thing !== null; } In case (3) example, the typeof check expecting "object" would fail to match a RegExp. The result of typeof /x/ in webkit and older Firefox is "function". The only sites that could be successfully relying on typeof /x/ == "object" would be IE-only sites. Public sites (that want to work in more than two browsers) could not work using such typechecks on RegExp. Callable RegExp in Tracemonkey and Opera is a mess. Code that doesn't hinge heavily on typechecking isFunction or isObject should not have to worry. > `/x/(s)' appears to return an Array of the matches of the Regular Expression > `/x/' in the string value `s' there, as if by the expression `/x/.exec(s)'. > > And no, that is _not_ "a clear violation" of ECMA-262 Ed. 3, but at least a > syntax extension supported the Specification itself. Indeed, I would like > to see it formally specified in Edition 5. > RegExp("a")("a") is a CallExpression, which is evaluated as described in "Function Calls" which requires a TypeError be thrown if the object does not implement [[Call]]. I can't explain what Tracemonkey and Opera do. And it doesn't matter when typechecking is avoided (and RegExp are not called). -- Garrett comp.lang.javascript FAQ: http://jibbering.com/faq/
From: Thomas 'PointedEars' Lahn on 11 Nov 2009 14:56 Garrett Smith wrote: > Thomas 'PointedEars' Lahn wrote: >> kangax wrote: >>> Garrett Smith wrote: > > (the example I provided was snipped). Because it was irrelevant. >>>> 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. > | 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. PointedEars -- realism: HTML 4.01 Strict evangelism: XHTML 1.0 Strict madness: XHTML 1.1 as application/xhtml+xml -- Bjoern Hoehrmann
From: Richard Cornford on 11 Nov 2009 14:59 Asen Bozhilov wrote: > Richard Cornford wrote: > >> 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. > > For my `function' is `object' who [[Prototype]] and Function.prototype > referred to same `object'. If i want to test someone `object' for > `isFunction' i ever used `instanceof'. > > if (f instanceof Function) > { > f.call; > f.apply; > f.dummyEnumPropertyInPrototypeChain; > } Which demonstrates that a clear statement about what 'being a function' means can quickly lead to a test that makes the required discrimination (- instanceof - test precisely that relationship). For a 'general purpose library' that definition of a function is next to useless because objects that cannot be called are allowed to have - Function.prototype - as their [[Prototype]] (or on their prototype chain), so the test is easily fooled. E.G.:- function F (){} F.prototype = Function.prototype; var f = new F(); alert(f instanceof Function); //alerts true, as it should On the other hand, it is an under-appreciated fact that no specific employment of javascript is truly 'general', so any specific test might answer the questions that need answering in the context of its use without needing to be generally effective. (that is, you don't write code to fool your own tests unless you mean/want to fool them). > Approach which compare internal [[Class]] property with string > literal '[object Function]'. I don't think proper name of that > approach is `isFunction' especially in browser environment, > where supports cross frame scripting. In ES3 terms that test has no technical basis. Host objects are allowed to have any value as their [[Class]] property, so no predictable relationship between the type of a host object and the outcome of applying - Object.prototype.toString - should be expected. And, of course, host object that are callable (so should be functions) have been observed that do not result in '[object Function]' when that method is applied to them (e.g. the - item - methods of collections in IE). > e.g. > > Function.prototype.bind = function(){}; > var f = window.frames[0].f; > if (Object.prototype.toString.call(f) == '[object Function]') //true > { > f.bind(); //throw f.bind is not a function > } Cross-frame/window always adds another dimension of complexity. Richard.
From: Peter Michaux on 11 Nov 2009 15:21
On Nov 11, 1:32 pm, "Richard Cornford" <Rich...(a)litotes.demon.co.uk> wrote: > Peter Michaux wrote: > >On Nov 11, 11:40 am, Thomas 'PointedEars' Lahn wrote: > >> Peter Michaux wrote: > >>> Thomas 'PointedEars' Lahn wrote: > <snip> > >>>> Well, I for one do not want to see code like the following > >>>> spreading around: > <snip> > >>>> Do you? > > >>> No. I think that I would not have allowed '$' to be part of > >>> identifier in the first place. > > >> Then I do not understand your opinion above. A recommendation > >> against, as it is in Edition 3, is a step in the right > >> direction in that sense; a missing recommendation against, > >> as it could be in Edition 5, is not. > > > If '$' is allowed then just allow it without any qualification > > or any advice about how it should be used unless such > > qualification is enforced by the language. > > How do you proposes such a requirement be enforced? The javascript > engine has no way of knowing how the source code it is presented with is > generated, so know way of determining which, if any, of it has been > machine generated. I don't propose such a requirement could be enforced. > > Such wimpy advice as > > given in ES3 will be and has been ignored as programmers > > If you want to call people who obviously didn't know any better > "programmers". If they are typing programs then I think they are programmers. > > will always do anything they can get away with doing. > > No they won't. there is a similar injunction (equally unenforceable) in > Java, which I have never seen breached by a non-novice. If you've seen it breached by a novice then you've seen it breached. That is all I meant. If something is allowed than someone will do it. I didn't mean everyone will do it. > It is possible > for people to perceive reasons for not doing something despite there > being nothing to stop them. > > >..so don't bother with the wimpy advice as part of the language > > spec in the first place. > > Because in situations where javascript source code is partly or entirely > machine generated being in a position to identify those parts of it that > were machine generated aids debugging and maintenance. It would be just as easy to have a convention where all identifiers that are machine generated start with the prefix "MACHINE_GENERATED_", for example. (Yes that example happens to be a long string.) > One of the issues you get with machine generated Identifiers is that it > can be difficult to predict exactly which Identifiers will be generated, > and so guaranteed that they will not collide with Identifiers already in > use in the human generated code. One way of guaranteeing no collisions > would be to provide each and every machine generated Identifier with a > prefix that was never used in human generated code. The original > ECMAScript spec made provision for that by allowing the $ symbol in > identifiers, and stated that that was the reason the symbol had been > allowed in Identifiers. It is a useful convention to follow, though may > only appear to be useful to people who have experience of mixing machine > generated javascript with human generated javascript (so likely not > novices). I agree the convention may be useful. I just don't think the convention belongs in the language specification...or if has to be in the language specification, there shouldn't be any bible thumpers running around telling people they are bad for doing something that is possible. I also don't know why there is a large worry that machine generated code would collide namespace with human generated code. Machines can generate and keep track of very weird identifiers no problem (e.g. "asdfrecwe" vs "asbfrecwe"). I think two pieces of human generated code written by different authors are far more likely to have a namespace collision. Why not have in the spec that all identifiers must start with your name? That is essentially the convention that has been used in Java. > > Imagine they had given indenting advice (e.g. four spaces, no > > tabs). That would have been promptly ignored also if two > > spaces and tabs were allowed. > > Now indenting requirements are something that could be enforced. Yes it could be enforced. I was suggesting you imagine they had given whitespace advice but not enforced it. Such advice would not have been followed just like the '$' advice was not followed. Peter |