From: Richard Cornford on
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
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
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
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
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